org.adaic.arm_form/0000755000175200010010000000000012302607050013441 5ustar stepheNoneorg.adaic.arm_form/build/0000755000175200010010000000000012302611435014542 5ustar stepheNoneorg.adaic.arm_form/build/arm_info.gpr0000755000175200010010000000607512302224724017062 0ustar stepheNoneproject ARM_Info is for Source_Dirs use ("../progs"); for Main use ("arm_form.ada"); for Object_Dir use "objects"; for Exec_Dir use "."; package Naming is for Spec ("ARM_Contents") use "arm_cont.ads"; for Body ("ARM_Contents") use "arm_cont.adb"; for Spec ("ARM_Corr") use "arm_corr.ads"; for Body ("ARM_Corr") use "arm_corr.adb"; for Spec ("ARM_Database") use "arm_db.ads"; for Body ("ARM_Database") use "arm_db.adb"; for Spec ("ARM_File") use "arm_file.ads"; for Body ("ARM_File") use "arm_file.adb"; for Spec ("ARM_Format") use "arm_frm.ads"; for Body ("ARM_Format") use "arm_frm.adb"; for Spec ("ARM_Format.Data") use "arm_frmd.ads"; for Body ("ARM_Format.Data") use "arm_frmd.adb"; for Body ("ARM_Format.Scan") use "arm_frms.adb"; for body ("ARM_Formatter") use "arm_form.ada"; for spec ("ARM_HTML") use "arm_html.ads"; for Body ("ARM_HTML") use "arm_html.adb"; for Spec ("ARM_Index") use "arm_indx.ads"; for Body ("ARM_Index") use "arm_indx.adb"; for Spec ("ARM_Input") use "arm_inp.ads"; for Body ("ARM_Input") use "arm_inp.adb"; for Spec ("ARM_Master") use "arm_mast.ads"; for Body ("ARM_Master") use "arm_mast.adb"; for Spec ("ARM_Output") use "arm_out.ads"; for spec ("ARM_RTF") use "arm_rtf.ads"; for Body ("ARM_RTF") use "arm_rtf.adb"; for Spec ("ARM_String") use "arm_str.ads"; for Body ("ARM_String") use "arm_str.adb"; for Spec ("ARM_Subindex") use "arm_sub.ads"; for Body ("ARM_Subindex") use "arm_sub.adb"; for Spec ("ARM_Syntax") use "arm_syn.ads"; for Body ("ARM_Syntax") use "arm_syn.adb"; for Spec ("ARM_Text") use "arm_text.ads"; for Body ("ARM_Text") use "arm_text.adb"; for Spec ("ARM_Texinfo") use "arm_texi.ads"; for Body ("ARM_Texinfo") use "arm_texi.adb"; end Naming; package Compiler is -- upstream wants Ada 2005 syntax, no GNAT-specific pragmas. -- We disable some warnings to minimize source diff with upstream. -- We append ADAFLAGS so the Makefile can add or override options. Switches := ("-g", "-O0", "-gnat2005", "-gnatfoqQ", "-gnatVa", "-gnatwaCeFKLMP", "-fstack-check", "-gnatybefip") & External_As_List ("ADAFLAGS", " "); for Default_Switches ("Ada") use Switches; -- arm_frm has code that passes the same object via two 'in out' -- params; GNAT 4.8 warns about that, so we suppress the warning -- here. for Switches ("arm_frm.adb") use Switches & ("-gnatw.I"); end Compiler; package Binder is for Default_Switches ("Ada") use ("-E"); end Binder; package Builder is for Default_Switches ("Ada") use ("-C"); -- We use ".exe" extension even on non-Windows, to simplify the makefiles. for Executable_Suffix use ".exe"; for Switches ("ARM_FORM.ADA") use ("-o", "arm_form.exe"); end Builder; package Linker is for Default_Switches ("Ada") use External_As_List ("LDFLAGS", " "); end Linker; end ARM_Info; org.adaic.arm_form/build/arm_info.prj0000755000175200010010000000006412117600736017062 0ustar stepheNonegpr_file=arm_info.gpr casing=emacs_case_exceptions org.adaic.arm_form/build/download.py0000755000175200010010000001252512273462240016740 0ustar stepheNone#!/usr/bin/python3 # Script to download the Ada Reference Manual and its formatting tool. # Copyright (c) 2010, 2012 Stephen Leake # Copyright (c) 2013 Nicolas Boulenguez # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import os.path import re import urllib.request import sys USE_EXISTING_FILES = True ###################################################################### class CVSWeb (): def __init__ (self, hostname, top_directory): # Instantiation requires distant root. self._host = 'http://' + hostname self._cgi = '/cgi-bin/cvsweb.cgi/' + top_directory + '/' def files_in_directory (self, path): # List text files in the head revision of a directory. # I did not find a way to list a tagged revision, except a # direct tag list for each file. cgi = self._cgi + str.lower (path) + '/' with urllib.request.urlopen (self._host + cgi) as f: contents = f.read () # Refuse directory names (with a trailing slash). # Ignore case of the displayed file name. pattern = '(\\1)
' matches = re.finditer (str.encode (pattern), contents, re.IGNORECASE) return (bytes.decode (m.group (2)) for m in matches) def download_file (self, path, tag = None): # None means the head revision. # Return the contents of the tagged revision of path, as bytes. # If tag is provided, but no revision of this file carries it, # None is returned. cgi = self._cgi + str.lower (path) if tag != None: with urllib.request.urlopen (self._host + cgi) as f: contents = f.read () pattern = '\\1
\r\n' \ + 'Modified [^<]*\r\n' \ + 'by [^<]*( with line changes [^<]*)?
\r\n' \ + 'CVS Tags: [^<]*' + re.escape (tag) + '[^<]*
' match = re.search (str.encode (pattern), contents) if not match: return None cgi += '?rev=' + bytes.decode (match.group (1)) else: cgi += '?rev=HEAD' with urllib.request.urlopen (self._host + cgi) as f: contents = f.read () return contents ###################################################################### def download_subdir (cvsweb, subdir, tag = None, # None means the head revision. rename_lowercase = False, strip_carriage_returns = False): def fmt (a, b): print ('{:<30} : {}'.format (a, b)) fmt ('Subdirectory', subdir) if tag: fmt ('Revision', tag) else: fmt ('Revision', 'latest') fmt ('Renaming files to lowercase', rename_lowercase) fmt ('Stripping carriage returns', strip_carriage_returns) try: os.mkdir (subdir) # Fails if the directory exists. except FileExistsError: if not USE_EXISTING_FILES: raise for basename in cvsweb.files_in_directory (subdir): src = subdir + '/' + basename if rename_lowercase: basename = str.lower (basename) dst = os.path.join (subdir, basename) # Local path join. if USE_EXISTING_FILES and os.path.exists (dst): fmt (dst, 'using existing file') continue contents = cvsweb.download_file (src, tag) if not contents: fmt (dst, 'no such tag') continue if strip_carriage_returns: contents = re.sub (b'\r\n', b'\n', contents) with open (dst, 'bw') as o: o.write (contents) fmt (dst, 'downloaded') ###################################################################### cvsweb = CVSWeb (hostname = 'www.ada-auth.org', top_directory = 'arm') tags = { '1995':'Final_TC1', '2005':'Amend_Final', '2012':'Ada2012_Final' } if len (sys.argv) == 2 and sys.argv [1] == 'progs': download_subdir (cvsweb, 'progs', rename_lowercase = True) print (""" No certification or signature used for downloaded code sources. Hint: diff -rN --ignore-file-name-case --strip-trailing-cr old/ progs/ """) elif len (sys.argv) == 2 and sys.argv [1] in tags: download_subdir (cvsweb, 'source', tag = tags [sys.argv [1]], rename_lowercase = True, strip_carriage_returns = True) else: print ('Usage: {} [progs | {}]'.format ( sys.argv [0], str.join (' | ', sorted ([str (year) for year in tags.keys ()])))) org.adaic.arm_form/build/emacs_case_exceptions0000755000175200010010000000001411776511201021013 0ustar stepheNone*ARM *LaTeX org.adaic.arm_form/build/Makefile0000755000175200010010000001656412302611163016217 0ustar stepheNone# Compilation of the Scribe formatter written for the Ada Reference # Manual, translating .ms[ms] files into various formats. Also build # tar.gz for the web page. # Copyright (c) 2010, 2013 Stephen Leake # Copyright (c) 2013 Nicolas Boulenguez # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Specific targets generate every $document$year.$format combination. # Ex: make arm2012.pdf AVAILABLE_DOCUMENTS := aarm arm AVAILABLE_YEARS := 2005 2012 AVAILABLE_FORMATS := html info texinfo txt pdf # 'all' builds all versions except pdf; to build a subset, override these on the command line. DOCUMENTS := $(AVAILABLE_DOCUMENTS) YEARS := $(AVAILABLE_YEARS) FORMATS := $(filter-out pdf texinfo, $(AVAILABLE_FORMATS)) # Texinfo is an intermediate, and is built as necessary. # Pdf requires installation of many huge formatting tools; we assume they are not installed. # see ../README.txt for list of things to change when Scribe or Ada source changes. # # Cygwin texi2dvi (GNU Texinfo 4.13) 1.135 fails silently! # Debian standard build flags for Ada projects BUILDER_OPTIONS := -k ADAFLAGS := LDFLAGS := # arm_info.gpr sets its own flags, then appends these variables so # that they take precedence. The intent is that you may configure the # build with a simple variable override. .PHONY: all clean publish all: $(foreach d,$(DOCUMENTS),\ $(foreach y,$(YEARS),\ $(foreach f,$(FORMATS),\ $(d)$(y).$(f)))) # We have been unable to get rid of all the section ref violations, so we # specify --no-validate. Delete that to see the errors. TEXI_INFO_OPTS := --no-split --no-number-sections --no-validate TEXI_PDF_OPTS := --quiet SOURCE_DIR_2005 := ../source_2005 SOURCE_DIR_2012 := ../source_2012 # See progs/command.txt. CHANGES := New-Only # See inside SOURCE_DIR_YEAR/DOCUMENT.msm for possible values. VERSION_2005 := 2 VERSION_2012 := 3 # Mapping from document acronyms to Randy's file names MASTER_arm := rm.msm MASTER_aarm := aarm.msm # Rough dependency, but Scribe files should not change often. SOURCES_2005 := $(wildcard $(SOURCE_DIR_2005)/*.ms[ms]) SOURCES_2012 := $(wildcard $(SOURCE_DIR_2012)/*.ms[ms]) define doc_year_build $(d)$(y).texinfo: arm_form.exe $(SOURCES_$(y)) cd $(SOURCE_DIR_$(y)); \ $(CURDIR)/$$< $(MASTER_$(d)) info $(CHANGES) $(VERSION_$(y)) $(CURDIR)/ mv `sed -ne 's/^@FilePrefix{\(.*\)}/\L\1/p' $(SOURCE_DIR_$(y))/$(MASTER_$(d))`.texinfo $$@ clean:: rm -f $(d)$(y).texinfo $(d)$(y).html: arm_form.exe $(SOURCES_$(y)) rm -f -r $$@ mkdir --parents $$@ cd $(SOURCE_DIR_$(y)); \ $(CURDIR)/$$< $(MASTER_$(d)) HTML $(CHANGES) $(VERSION_$(y)) $(CURDIR)/$$@/ clean:: rm -f -r $(d)$(y).html $(d)$(y).txt: arm_form.exe $(SOURCES_$(y)) rm -f -r $$@ mkdir --parents $$@ cd $(SOURCE_DIR_$(y)); \ $(CURDIR)/$$< $(MASTER_$(d)) Text $(CHANGES) $(VERSION_$(y)) $(CURDIR)/$$@/ clean:: rm -f -r $(d)$(y).txt # texi2any is from texinfo 5 $(d)$(y).info: $(d)$(y).texinfo texi2any --info $(TEXI_INFO_OPTS) $$< -o $$@ clean:: rm -f $(d)$(y).info $(d)$(y).pdf: $(d)$(y).texinfo texi2any --pdf $(TEXI_PDF_OPTS) $$< -o $$@ clean:: rm -f $(d)$(y).log $(d)$(y).pdf $(d)$(y).toc endef $(foreach d,$(AVAILABLE_DOCUMENTS),\ $(foreach y,$(AVAILABLE_YEARS),\ $(eval $(doc_year_build)))) arm_form.exe : force gnatmake -p $(BUILDER_OPTIONS) -P arm_info.gpr $(foreach var,ADAFLAGS LDFLAGS,"-X$(var)=$($(var))") clean:: rm -f arm_form.exe rm -f -r objects trace : addr2line -e arm_form.exe 0x5c12e7 0x5c598e 0x43e05b 0x446c5b 0x448369 0x545205 0x4e9221 0x4e3b1a 0x5831a1 0x5ad295 0x5adee9 0x4cb3f5 0x401850 0x401235 0x401286 0x7c817075 # year is latest standard; bump trailing digit for any change. ZIP_VERSION := $(lastword $(AVAILABLE_YEARS)).2 INFO_ARCHIVE := arm_info-$(ZIP_VERSION).tar.gz SOURCE_ARCHIVE := arm_info-$(ZIP_VERSION)-src.tar.gz publish: $(INFO_ARCHIVE) $(SOURCE_ARCHIVE) # --no-name eliminates time stamps, which helps make the tarball reproducible # --best gives higher compression than the default; we can afford the time here. GZIP := --no-name --best $(INFO_ARCHIVE): $(foreach d,$(DOCUMENTS),\ $(foreach y,$(YEARS),\ $(d)$(y).info)) tar cf - $^ | gzip $(GZIP) -c > $@ clean:: rm -f $(INFO_ARCHIVE) ZIP_EXCLUDES := *~ *.dvi *.gz *.info *.log *.pdf *.ps *.texinfo *.toc \ *.stamp *.zip arm_form.exe _MTN .mtn-ignore .dvc-exclude aarm2005.html \ aarm2005.txt aarm2012.html aarm2012.txt arm2005.html arm2005.txt arm2012.html \ arm2012.txt objects $(SOURCE_ARCHIVE): tar cf - -C ../.. $(foreach e,$(ZIP_EXCLUDES),--exclude="$(e)") org.adaic.arm_form | gzip $(GZIP) -c > $@ clean:: rm -f $(SOURCE_ARCHIVE) update_upstream : source_ada.clean source_ada.stamp update_upstream : source_scribe_2005.clean source_scribe_2005.stamp update_upstream : source_scribe_2012.clean source_scribe_2012.stamp # download.py does not convert to unix line endings here to minimize # the diff with upstream; the Ada compiler can handle DOS line endings # on Unix. download.py does convert file names to lower case here, for # consistency. source_ada.stamp : rm -rf ../../org.adaic.arm_form.upstream/progs cd ../../org.adaic.arm_form.upstream; python3 ../org.adaic.arm_form/build/download.py progs touch source_ada.stamp source_ada.clean : rm -f source_ada.stamp # This retrieves the CVS tag for the year given on the command line # commit to mtn: (dvc-status "../../org.adaic.arm_form.upstream") # # download.py converts to unix line endings here, because the scribe # processor insists on uniform formatting; this works for both Windows # and Debian. download.py also converts all file names to lowercase, # and arm_form does as well; upstream only runs on Windows, which # ignores case in filenames, so the file names in the sources are not # consistently cased. source_scribe_%.stamp : rm -rf ../../org.adaic.arm_form.upstream/source_$* cd ../../org.adaic.arm_form.upstream; python3 ../org.adaic.arm_form/build/download.py $* mv ../../org.adaic.arm_form.upstream/source ../../org.adaic.arm_form.upstream/source_$* touch source_scribe_$*.stamp source_scribe_%.clean : rm -f source_scribe_$*.stamp # These sources do not match teh correpsonding CVS tag, although they are close. ARM_SRC.ZIP ARM_FORM.ZIP ARM_FSRC.ZIP 2005-SRC.zip 2012-SRC.zip : wget http://www.ada-auth.org/arm-files/$@ # delete everything back to mtn checkout # # Note that additional 'clean' targets are specified after every # target that builds something. clean :: rm -f *.stamp *.zip info-clean : rm -f *.info* .PHONY : force VPATH = ../source_2005 ../source_2012 ../progs #Local Variables: #eval: (delete '("\\.mss\\'" . scribe-mode) auto-mode-alist) #eval: (ada-parse-prj-file "arm_info.prj") #eval: (ada-select-prj-file "arm_info.prj") #End: # end of file org.adaic.arm_form/progs/0000755000175200010010000000000012273462240014602 5ustar stepheNoneorg.adaic.arm_form/progs/alkc.bat0000755000175200010010000000034712273462240016213 0ustar stepheNoneMove .\Object\%1.Obj . link -subsystem:console -entry:mainCRTStartup -out:%1.exe %1.obj libc.lib kernel32.lib -map:%1.map Del %1.Obj Rem Del %1.Map Copy %1.Exe \RRS\Docs Move %1.Exe ..\Source Move .\Object\%1.Dbg ..\Source org.adaic.arm_form/progs/arm_cont.adb0000755000175200010010000007220012273462240017060 0ustar stepheNonewith Ada.Characters.Handling; --with Ada.Text_IO; -- Debug. --with Ada.Exceptions; package body ARM_Contents is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to manage section/clause/subclause -- references. -- -- --------------------------------------- -- Copyright 2000, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/19/00 - RLB - Created base package. -- 4/26/00 - RLB - Added Previous_Clause and Next_Clause. -- 5/15/00 - RLB - Added rules about unnumbered sections. -- 5/22/00 - RLB - Added Unnumbered_Section level. -- 8/22/00 - RLB - Added Old_Title handling. -- 9/ 9/04 - RLB - Removed unused with. -- 2/ 2/05 - RLB - Allowed more old titles. -- 1/16/06 - RLB - Added debugging. -- 9/22/06 - RLB - Created type Clause_Number_Type and added SubSubClause. -- 10/12/07 - RLB - Extended the range of properly formatted clause numbers. -- 12/18/07 - RLB - Added Plain_Annex. -- 10/24/08 - RLB - More old titles. -- 5/07/09 - RLB - Added Dead_Clause. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added Parent_Clause from Stephen Leake's version. -- 10/25/11 - RLB - Added version to Old name strings. -- 8/30/12 - RLB - Added traps if we're reading Section = UNKNOWN. function "<" (Left, Right : Clause_Number_Type) return Boolean is -- True if Left comes before Right in the collating order. begin if Left.Section = UNKNOWN then raise Bad_Clause_Error with "Left has Unknown section"; elsif Right.Section = UNKNOWN then raise Bad_Clause_Error with "Right has Unknown section"; elsif Left.Section < Right.Section then return True; elsif Left.Section > Right.Section then return False; elsif Left.Clause < Right.Clause then return True; elsif Left.Clause > Right.Clause then return False; elsif Left.Subclause < Right.Subclause then return True; elsif Left.Subclause > Right.Subclause then return False; elsif Left.Subsubclause < Right.Subsubclause then return True; else return False; end if; end "<"; function ">" (Left, Right : Clause_Number_Type) return Boolean is -- True if Left comes after Right in the collating order. begin return Right < Left; end ">"; function "<=" (Left, Right : Clause_Number_Type) return Boolean is -- True if Left comes before or is the same as Right in the -- collating order. begin return not (Right < Left); end "<="; function ">=" (Left, Right : Clause_Number_Type) return Boolean is -- True if Left comes after or is the same as Right in the -- collating order. begin return not (Left < Right); end ">="; type Title_Record is record Title : Title_Type; -- Title in original format. Search_Title : Title_Type; -- Title in all lower case. Level : Level_Type; Clause_Number : Clause_Number_Type; Version : ARM_Contents.Change_Version_Type := '0'; end record; Title_List : array (1 .. 900) of Title_Record; Last_Title : Natural; Old_Title_List : array (1 .. 300) of Title_Record; Last_Old_Title : Natural; procedure Initialize is -- Initialize this package; make sure the contents are empty. begin Last_Title := 0; end Initialize; procedure Add (Title : in Title_Type; Level : in Level_Type; Clause_Number : in Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type := '0') is -- Add a section or clause to the contents. It has the specified -- characteristics. begin if Level /= Subsubclause and then Clause_Number.Subsubclause /= 0 then raise Bad_Clause_Error with "not a subsubclause but non-zero subsubclause number"; end if; if Level /= Subsubclause and then Level /= Subclause and then Clause_Number.Subclause /= 0 then raise Bad_Clause_Error with "not a subclause but non-zero subclause number"; end if; if (Level /= Subsubclause and then Level /= Subclause and then Level /= Clause and then Level /= Unnumbered_Section and then Level /= Dead_Clause) and then Clause_Number.Clause /= 0 then raise Bad_Clause_Error with "not a clause but non-zero clause number"; end if; Last_Title := Last_Title + 1; Title_List (Last_Title) := (Title => Title, Search_Title => Ada.Characters.Handling.To_Lower (Title), Level => Level, Clause_Number => Clause_Number, Version => Version); --Ada.Text_IO.Put_Line (" Add " & Title & -- " Index=" & Natural'Image(Last_Title) & " Level=" & Level_Type'Image(Level)); --Ada.Text_IO.Put_Line (" Section" & Section_Number_Type'Image(Clause_Number.Section) & -- " Clause" & Natural'Image(Clause_Number.Clause) & " Subclause" & Natural'Image(Clause_Number.Subclause) & -- " Subsubclause" & Natural'Image(Clause_Number.Subsubclause)); end Add; procedure Add_Old (Old_Title : in Title_Type; Level : in Level_Type; Clause_Number : in Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type := '0') is -- Add an old title for a section or clause to the contents. It has -- the specified characteristics; the version is the version for which -- it first was present in the document. begin if Level /= Subsubclause and then Clause_Number.Subsubclause /= 0 then raise Bad_Clause_Error with "not a subsubclause but non-zero subsubclause number"; end if; if Level /= Subsubclause and then Level /= Subclause and then Clause_Number.Subclause /= 0 then raise Bad_Clause_Error with "not a subclause but non-zero subclause number"; end if; if (Level /= Subsubclause and then Level /= Subclause and then Level /= Clause and then Level /= Unnumbered_Section and then Level /= Dead_Clause) and then Clause_Number.Clause /= 0 then raise Bad_Clause_Error with "not a clause but non-zero clause number"; end if; Last_Old_Title := Last_Old_Title + 1; Old_Title_List (Last_Old_Title) := (Title => Old_Title, Search_Title => Ada.Characters.Handling.To_Lower (Old_Title), Level => Level, Clause_Number => Clause_Number, Version => Version); --Ada.Text_IO.Put_Line (" Add_Old " & Old_Title & -- " Index=" & Natural'Image(Last_Old_Title) & " Level=" & Level_Type'Image(Level)); --Ada.Text_IO.Put_Line (" Section" & Section_Number_Type'Image(Section_Number) & -- " Clause" & Natural'Image(Clause_Number.Clause) & " Subclause" & Natural'Image(Clause_Number.Subclause) & -- " Subsubclause" & Natural'Image(Clause_Number.Subsubclause)); end Add_Old; function Make_Clause_Number (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return String is -- Returns a properly formatted Section or clause number reference. begin if Clause_Number.Section = UNKNOWN then raise Bad_Clause_Error with "unknown section number"; -- else not unknown end if; case Level is when Plain_Annex | Normative_Annex | Informative_Annex => if Clause_Number.Clause /= 0 or else Clause_Number.Subclause /= 0 or else Clause_Number.Subsubclause /= 0 or else Clause_Number.Section <= 30 then raise Bad_Clause_Error; -- Illegal numbers. end if; return "Annex " & Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)); when Section => if Clause_Number.Clause /= 0 or else Clause_Number.Subclause /= 0 or else Clause_Number.Section >= ANNEX_START then raise Bad_Clause_Error; -- Illegal numbers. end if; if Clause_Number.Section < 10 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ""; elsif Clause_Number.Section < 20 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10); elsif Clause_Number.Section < 30 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20); else return "3" & Character'Val (Character'Pos('0') + Clause_Number.Section - 30); end if; when Unnumbered_Section => if Clause_Number.Clause = 0 or else Clause_Number.Subclause /= 0 or else Clause_Number.Section /= 0 then raise Bad_Clause_Error; -- Illegal numbers. end if; if Clause_Number.Clause < 10 then return "0." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return "0.1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return "0.2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); else return "0.3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); end if; when Clause => if Clause_Number.Subclause /= 0 then raise Bad_Clause_Error; -- Illegal number. end if; if Clause_Number.Section < 10 then if Clause_Number.Clause < 10 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & "." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); elsif Clause_Number.Clause < 40 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); elsif Clause_Number.Clause < 50 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 40); elsif Clause_Number.Clause < 60 then return Character'Val (Character'Pos('0') + Clause_Number.Section) & ".5" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 50); else raise Bad_Clause_Error; -- Out of range. end if; elsif Clause_Number.Section < 20 then if Clause_Number.Clause < 10 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & "." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); elsif Clause_Number.Clause < 40 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); elsif Clause_Number.Clause < 50 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 40); elsif Clause_Number.Clause < 60 then return "1" & Character'Val (Character'Pos('0') + Clause_Number.Section - 10) & ".5" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 50); else raise Bad_Clause_Error; -- Out of range. end if; elsif Clause_Number.Section < 30 then if Clause_Number.Clause < 10 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & "." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); elsif Clause_Number.Clause < 40 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); elsif Clause_Number.Clause < 50 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 40); elsif Clause_Number.Clause < 60 then return "2" & Character'Val (Character'Pos('0') + Clause_Number.Section - 20) & ".5" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 50); else raise Bad_Clause_Error; -- Out of range. end if; elsif Clause_Number.Section = 30 then if Clause_Number.Clause < 10 then return "30." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return "30.1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return "30.2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); elsif Clause_Number.Clause < 40 then return "30.3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); elsif Clause_Number.Clause < 50 then return "30.4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 40); elsif Clause_Number.Clause < 60 then return "30.5" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 50); else raise Bad_Clause_Error; -- Out of range. end if; else if Clause_Number.Clause < 10 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & "." & Character'Val (Character'Pos('0') + Clause_Number.Clause); elsif Clause_Number.Clause < 20 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 10); elsif Clause_Number.Clause < 30 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 20); elsif Clause_Number.Clause < 40 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 30); elsif Clause_Number.Clause < 50 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 40); elsif Clause_Number.Clause < 60 then return Character'Val (Character'Pos('A') + (Clause_Number.Section - ANNEX_START)) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Clause - 50); else raise Bad_Clause_Error; -- Out of range. end if; end if; when Subclause => if Clause_Number.Section = UNKNOWN then raise Bad_Clause_Error with "unknown section number"; elsif Clause_Number.Subclause < 10 then return Make_Clause_Number (Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)) & "." & Character'Val (Character'Pos('0') + Clause_Number.Subclause); elsif Clause_Number.Subclause < 20 then return Make_Clause_Number (Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Subclause - 10); elsif Clause_Number.Subclause < 30 then return Make_Clause_Number (Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Subclause - 20); elsif Clause_Number.Subclause < 40 then return Make_Clause_Number (Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Subclause - 30); elsif Clause_Number.Subclause < 50 then return Make_Clause_Number (Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Subclause - 40); else raise Bad_Clause_Error; -- Out of range. end if; when Subsubclause => if Clause_Number.Subsubclause < 10 then return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)) & "." & Character'Val (Character'Pos('0') + Clause_Number.Subsubclause); elsif Clause_Number.Subclause < 20 then return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)) & ".1" & Character'Val (Character'Pos('0') + Clause_Number.Subsubclause - 10); elsif Clause_Number.Subclause < 30 then return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)) & ".2" & Character'Val (Character'Pos('0') + Clause_Number.Subsubclause - 20); elsif Clause_Number.Subclause < 40 then return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)) & ".3" & Character'Val (Character'Pos('0') + Clause_Number.Subsubclause - 30); elsif Clause_Number.Subclause < 50 then return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)) & ".4" & Character'Val (Character'Pos('0') + Clause_Number.Subsubclause - 40); else raise Bad_Clause_Error; -- Out of range. end if; when Dead_Clause => return "X.X"; end case; end Make_Clause_Number; procedure Make_Clause (Clause_String : in String; Clause_Number : out Clause_Number_Type) is -- Returns the clause number for a properly formatted Section or -- clause string. Next : Positive; function Get_Section_Number return Section_Number_Type is -- Extract the section number: begin if Clause_String'Length = 1 or else Clause_String(Clause_String'First + 1) = '.' then Next := Clause_String'First + 2; if Clause_String (Clause_String'First) in '0' .. '9' then return Character'Pos(Clause_String (Clause_String'First)) - Character'Pos('0'); else return Character'Pos(Clause_String (Clause_String'First)) - Character'Pos('A') + ANNEX_START; end if; else Next := Clause_String'First + 3; return (Character'Pos(Clause_String (Clause_String'First)) - Character'Pos('0')) * 10 + Character'Pos(Clause_String (Clause_String'First + 1)) - Character'Pos('0'); end if; end Get_Section_Number; function Get_Clause_Number return Natural is -- Extract the clause: begin if Clause_String'Last - Next + 1 = 1 or else Clause_String(Next + 1) = '.' then Next := Next + 2; return Character'Pos(Clause_String (Next - 2)) - Character'Pos('0'); else Next := Next + 3; return (Character'Pos(Clause_String (Next - 3)) - Character'Pos('0')) * 10 + Character'Pos(Clause_String (Next - 3 + 1)) - Character'Pos('0'); end if; end Get_Clause_Number; begin if Clause_String'Length = 7 and then Clause_String (Clause_String'First .. Clause_String'First + 5) = "Annex " then -- Annex clauses. Clause_Number := (Section => Character'Pos(Clause_String (Clause_String'First + 6)) - Character'Pos('A') + ANNEX_START, Clause | Subclause | Subsubclause => 0); elsif Clause_String'Length = 1 then Clause_Number := (Section => Get_Section_Number, Clause | Subclause | Subsubclause => 0); elsif Clause_String'Length = 2 then Clause_Number := (Section => Get_Section_Number, Clause | Subclause | Subsubclause => 0); else Clause_Number := (Section => Get_Section_Number, Clause | Subclause | Subsubclause => 0); -- Next is now the start of the Clause: if Clause_String'Last - Next + 1 = 1 then Clause_Number.Clause := Get_Clause_Number; elsif Clause_String'Last - Next + 1 = 2 then Clause_Number.Clause := Get_Clause_Number; else Clause_Number.Clause := Get_Clause_Number; -- Next is now the start of the Subclause: if Clause_String'Last - Next + 1 = 1 then Clause_Number.Subclause := Character'Pos(Clause_String (Next)) - Character'Pos('0'); elsif Clause_String'Last - Next + 1 = 2 then Clause_Number.Subclause := (Character'Pos(Clause_String (Next)) - Character'Pos('0')) * 10 + Character'Pos(Clause_String (Next + 1)) - Character'Pos('0'); else if Clause_String'Last - Next + 1 = 1 or else Clause_String(Next + 1) = '.' then Next := Next + 2; Clause_Number.Subclause := Character'Pos(Clause_String (Next - 2)) - Character'Pos('0'); else Next := Next + 3; Clause_Number.Subclause := (Character'Pos(Clause_String (Next - 3)) - Character'Pos('0')) * 10 + Character'Pos(Clause_String (Next - 3 + 1)) - Character'Pos('0'); end if; if Clause_String'Last - Next + 1 = 1 then Clause_Number.Subsubclause := Character'Pos(Clause_String (Next)) - Character'Pos('0'); else -- Two digit. Clause_Number.Subsubclause := (Character'Pos(Clause_String (Next)) - Character'Pos('0')) * 10 + Character'Pos(Clause_String (Next + 1)) - Character'Pos('0'); end if; end if; end if; end if; if Clause_Number.Section = UNKNOWN then raise Bad_Clause_Error with "unknown section number"; -- else not unknown end if; end Make_Clause; function Lookup_Clause_Number (Title : in Title_Type) return String is -- Given the title of a clause, returns the formatted Section or -- clause number reference for that title. The Title must match -- exactly, except for case. Raises Not_Found_Error if not found. Lower_Title : constant Title_Type := Ada.Characters.Handling.To_Lower (Title); begin for I in 1 .. Last_Title loop if Lower_Title = Title_List(I).Search_Title then return Make_Clause_Number (Title_List(I).Level, Title_List(I).Clause_Number); end if; end loop; raise Not_Found_Error; end Lookup_Clause_Number; function Lookup_Level (Title : in Title_Type) return Level_Type is -- Given the title of a clause, returns the level for that title. The Title must match -- exactly, except for case. Raises Not_Found_Error if not found. Lower_Title : constant Title_Type := Ada.Characters.Handling.To_Lower (Title); begin for I in 1 .. Last_Title loop if Lower_Title = Title_List(I).Search_Title then return Title_List(I).Level; end if; end loop; raise Not_Found_Error; end Lookup_Level; function Lookup_Title (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return Title_Type is -- Given the level and clause numbers, return the appropriate -- title. Raises Not_Found_Error if not found. begin if Clause_Number.Section = UNKNOWN then raise Bad_Clause_Error with "unknown section number"; -- else not unknown end if; for I in 1 .. Last_Title loop if Title_List(I).Level = Level and then Title_List(I).Clause_Number = Clause_Number then return Title_List(I).Title; end if; end loop; raise Not_Found_Error; end Lookup_Title; function Lookup_Old_Title (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return Title_Type is -- Given the level and clause numbers, return the appropriate -- old title. Calls Lookup_Title if not found (thus returning the -- regular (new) title. begin if Clause_Number.Section = UNKNOWN then raise Bad_Clause_Error with "unknown section number"; -- else not unknown end if; for I in 1 .. Last_Old_Title loop if Old_Title_List(I).Level = Level and then Old_Title_List(I).Clause_Number = Clause_Number then return Old_Title_List(I).Title; end if; end loop; return Lookup_Title (Level, Clause_Number); end Lookup_Old_Title; function Previous_Clause (Clause : in String) return String is -- Returns the string of the previous clause (in the table of contents) -- for the properly formatted clause string Clause. -- Raises Not_Found_Error if not found. Clause_Number : Clause_Number_Type; begin Make_Clause (Clause, Clause_Number); for I in 1 .. Last_Title loop if Title_List(I).Clause_Number = Clause_Number then for J in reverse 1 .. I - 1 loop if Title_List(J).Level /= Dead_Clause then return Make_Clause_Number (Title_List(J).Level, Title_List(J).Clause_Number); -- else skip it and continue. end if; end loop; -- If we get here, it was not found. raise Not_Found_Error; end if; end loop; raise Not_Found_Error; end Previous_Clause; function Next_Clause (Clause : in String) return String is -- Returns the string of the next clause (in the table of contents) -- for the properly formatted clause string Clause. -- Raises Not_Found_Error if not found. Clause_Number : Clause_Number_Type; begin Make_Clause (Clause, Clause_Number); for I in 1 .. Last_Title loop if Title_List(I).Clause_Number = Clause_Number then for J in I + 1 .. Last_Title loop if Title_List(J).Level /= Dead_Clause then return Make_Clause_Number (Title_List(J).Level, Title_List(J).Clause_Number); -- else skip it and continue. end if; end loop; -- If we get here, it was not found. raise Not_Found_Error; end if; end loop; raise Not_Found_Error; end Next_Clause; function Parent_Clause (Clause : in String) return String is -- Returns the string of the parent clause (in the table of contents) -- for the properly formatted clause string Clause. -- -- Result is a null string if Clause is a top level clause; -- Section, Unnumbered_Section, Normative_Annex, -- Informative_Annex, Plain_Annex. Clause_Number : Clause_Number_Type; begin Make_Clause (Clause, Clause_Number); if Clause_Number.Clause = 0 then -- Clause is a section; no parent return ""; elsif Clause_Number.Subclause = 0 then -- Clause is a clause; parent is Section or Annex if Clause_Number.Section >= ANNEX_START then return Make_Clause_Number (Normative_Annex, (Clause_Number.Section, 0, 0, 0)); else return Make_Clause_Number (Section, (Clause_Number.Section, 0, 0, 0)); end if; elsif Clause_Number.Subsubclause = 0 then -- Clause is a subclause; clause is parent return Make_Clause_Number (ARM_Contents.Clause, (Clause_Number.Section, Clause_Number.Clause, 0, 0)); else -- Clause is a subsubclause; subclause is parent return Make_Clause_Number (Subclause, (Clause_Number.Section, Clause_Number.Clause, Clause_Number.Subclause, 0)); end if; end Parent_Clause; procedure For_Each is -- Call Operate for each title in the contents, in the order that -- they were added to the contents (other than dead clauses). If the -- Quit parameter to Operate is True when Operate returns, the -- iteration is abandoned. Quit : Boolean := False; begin for I in 1 .. Last_Title loop if Title_List(I).Level /= Dead_Clause then Operate (Title_List(I).Title, Title_List(I).Level, Title_List(I).Clause_Number, Title_List(I).Version, Quit); -- else skip it. end if; if Quit then return; end if; end loop; end For_Each; end ARM_Contents; org.adaic.arm_form/progs/arm_cont.ads0000755000175200010010000002003112273462240017074 0ustar stepheNonewith Ada.Strings.Unbounded; package ARM_Contents is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to manage section/clause/subclause -- references. -- -- --------------------------------------- -- Copyright 2000, 2004, 2006, 2007, 2009, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/19/00 - RLB - Created base package. -- 4/26/00 - RLB - Added Previous_Clause and Next_Clause. -- 5/15/00 - RLB - Added rules about unnumbered sections. -- 5/22/00 - RLB - Added Unnumbered_Section level. -- 8/ 7/00 - RLB - Made Make_Clause visible. -- 8/22/00 - RLB - Added Old_Title handling. -- 9/14/04 - RLB - Moved Change_Version_Type here, to avoid mutual -- dependence. -- - RLB - Added version to changes. -- 9/22/06 - RLB - Created type Clause_Number_Type and added SubSubClause. -- 12/18/07 - RLB - Added Plain_Annex. -- 5/06/09 - RLB - Added Versioned_String. -- 5/07/09 - RLB - Added Dead_Clause. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added Parent_Clause from Stephen Leake's version. -- 10/25/11 - RLB - Added version to Old name strings. -- 8/30/12 - RLB - Added initialization of Section to UNKNOWN to -- detect bugs earlier. subtype Title_Type is String (1 .. 80); -- The type of a title. type Section_Number_Type is range 0 .. 58; -- Values > 30 represent annex letters (31 => A, 32 => B, etc.) -- Value = 0 represents the preface, introduction, etc. No -- number is generated if Section_Number = 0. ANNEX_START : constant := 31; -- First annex section number. UNKNOWN : constant Section_Number_Type := 58; -- Uninitialized sections get this. subtype Change_Version_Type is Character range '0' .. '9'; -- Defines the change version. Version 0 is the original text. type Versioned_String is array (ARM_Contents.Change_Version_Type) of Ada.Strings.Unbounded.Unbounded_String; type Clause_Number_Type is record Section : Section_Number_Type := UNKNOWN; Clause : Natural := 0; Subclause : Natural := 0; Subsubclause : Natural := 0; end record; Not_Found_Error : exception; Bad_Clause_Error : exception; -- Raised by any of the below if the Clause_Number is -- invalid (potentially depending on the other parameters, -- like the level). procedure Initialize; -- Initialize this package; make sure the contents are empty. type Level_Type is (Section, Unnumbered_Section, Plain_Annex, Normative_Annex, Informative_Annex, Clause, Subclause, Subsubclause, Dead_Clause); -- Defines the level of a clause header. -- Clause is "xx.nn"; Subclause is "xx.nn.nn"; Subsubclause is "xx.nn.nn.nn". function "<" (Left, Right : Clause_Number_Type) return Boolean; -- True if Left comes before Right in the collating order. function ">" (Left, Right : Clause_Number_Type) return Boolean; -- True if Left comes after Right in the collating order. function "<=" (Left, Right : Clause_Number_Type) return Boolean; -- True if Left comes before or is the same as Right in the -- collating order. function ">=" (Left, Right : Clause_Number_Type) return Boolean; -- True if Left comes after or is the same as Right in the -- collating order. procedure Add (Title : in Title_Type; Level : in Level_Type; Clause_Number : in Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type := '0'); -- Add a section or clause to the contents. It has the specified -- characteristics. procedure Add_Old (Old_Title : in Title_Type; Level : in Level_Type; Clause_Number : in Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type := '0'); -- Add an old title for a section or clause to the contents. It has -- the specified characteristics; the version is the version for which -- it first was present in the document. function Make_Clause_Number (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return String; -- Returns a properly formatted Section or clause number reference. -- Note that an unnumbered section returns a number with a -- Section_Number of zero (for sorting purposes). procedure Make_Clause (Clause_String : in String; Clause_Number : out Clause_Number_Type); -- Returns the clause number for a properly formatted Section or -- clause string. function Lookup_Clause_Number (Title : in Title_Type) return String; -- Given the title of a clause, returns the formatted Section or -- clause number reference for that title. The Title must match -- exactly, except for case. Raises Not_Found_Error if not found. function Lookup_Level (Title : in Title_Type) return Level_Type; -- Given the title of a clause, returns the level for that title. The Title must match -- exactly, except for case. Raises Not_Found_Error if not found. function Lookup_Title (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return Title_Type; -- Given the level and clause numbers, return the appropriate -- title. Raises Not_Found_Error if not found. function Lookup_Old_Title (Level : in Level_Type; Clause_Number : in Clause_Number_Type) return Title_Type; -- Given the level and clause numbers, return the appropriate -- old title. Calls Lookup_Title if not found (thus returning the -- regular (new) title. function Previous_Clause (Clause : in String) return String; -- Returns the string of the previous clause (in the table of contents) -- for the properly formatted clause string Clause. -- Raises Not_Found_Error if not found. function Next_Clause (Clause : in String) return String; -- Returns the string of the next clause (in the table of contents) -- for the properly formatted clause string Clause. -- Raises Not_Found_Error if not found. function Parent_Clause (Clause : in String) return String; -- Returns the string of the parent clause (in the table of contents) -- for the properly formatted clause string Clause. -- -- Result is a null string if Clause is a top level clause; -- Section, Unnumbered_Section, Normative_Annex, -- Informative_Annex, Plain_Annex. generic with procedure Operate (Title : in Title_Type; Level : in Level_Type; Clause_Number : in Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type; Quit : out Boolean) is <>; procedure For_Each; -- Call Operate for each title in the contents, in the order that -- they were added to the contents. If the Quit parameter to Operate -- is True when Operate returns, the iteration is abandoned. end ARM_Contents; org.adaic.arm_form/progs/arm_corr.adb0000755000175200010010000020417612273462240017073 0ustar stepheNonewith --ARM_Output, --ARM_Contents, --Ada.Text_IO, Ada.Exceptions, Ada.Strings.Fixed, Ada.Strings.Maps; package body ARM_Corr is -- -- Ada reference manual formatter (ARM_Form). -- -- This package defines the text output object. -- Output objects are responsible for implementing the details of -- a particular format. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2006, 2007, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 6/ 2/05 - RLB - Created package from text and HTML versions. -- 1/11/06 - RLB - Eliminated dispatching Create in favor of tailored -- versions. -- 1/18/06 - RLB - Added additional styles. -- 2/ 8/06 - RLB - Added additional parameters to the table command. -- 2/10/06 - RLB - Added even more additional parameters to the -- table command. -- - RLB - Added picture command. -- 9/22/06 - RLB - Added missing with. -- 9/25/06 - RLB - Handled optional renaming of TOC. -- - RLB - Added Last_Column_Width to Start_Table. -- 10/13/06 - RLB - Added Local_Link_Start and Local_Link_End to allow -- formatting in the linked text. -- 2/ 9/07 - RLB - Changed comments on AI_Reference. -- 2/13/07 - RLB - Revised to separate style and indent information -- for paragraphs. -- 12/18/07 - RLB - Added Plain_Annex. -- 12/19/07 - RLB - Added limited colors to Text_Format. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/25/11 - RLB - Added old insertion version to Revised_Clause_Header. -- 8/31/12 - RLB - Added Output_Path. -- 10/18/12 - RLB - Added additional hanging styles. -- 11/26/12 - RLB - Added subdivision names to Clause_Header and -- Revised_Clause_Header. LINE_LENGTH : constant := 78; -- Maximum intended line length. Special_Set : constant Ada.Strings.Maps.Character_Set := Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('>'), Ada.Strings.Maps.To_Set ('@')); procedure Create (Output_Object : in out Corr_Output_Type; File_Prefix : in String; Output_Path : in String; Title : in String := "") is -- Create an Output_Object for a document. -- The prefix of the output file names is File_Prefix - this -- should be no more then 5 characters allowed in file names. -- The result files will be written to Output_Path. -- The title of the document is Title. begin if Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already valid object"); end if; Output_Object.Is_Valid := True; Ada.Strings.Fixed.Move (Target => Output_Object.File_Prefix, Source => File_Prefix); Ada.Strings.Fixed.Move (Target => Output_Object.Output_Path, Source => Output_Path); Output_Object.Output_Path_Len := Output_Path'Length; -- We don't use the title. end Create; procedure Close (Output_Object : in out Corr_Output_Type) is -- Close an Output_Object. No further output to the object is -- allowed after this call. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Ada.Text_IO.Is_Open (Output_Object.Output_File) then Ada.Text_IO.Close (Output_Object.Output_File); end if; Output_Object.Is_Valid := False; end Close; procedure Section (Output_Object : in out Corr_Output_Type; Section_Title : in String; Section_Name : in String) is -- Start a new section. The title is Section_Title (this is -- intended for humans). The name is Section_Name (this is -- intended to be suitable to be a portion of a file name). begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Section in paragraph"); end if; if Ada.Text_IO.Is_Open (Output_Object.Output_File) then Ada.Text_IO.Close (Output_Object.Output_File); end if; -- Create a new file for this section: -- Unix directory separator for Windows and Debian Ada.Text_IO.Create (Output_Object.Output_File, Ada.Text_IO.Out_File, Output_Object.Output_Path(1..Output_Object.Output_Path_Len) & Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-Corr-" & Section_Name & ".TXT"); Ada.Text_IO.New_Line (Output_Object.Output_File); end Section; procedure Set_Columns (Output_Object : in out Corr_Output_Type; Number_of_Columns : in ARM_Output.Column_Count) is -- Set the number of columns. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; -- No columns in text format. end Set_Columns; procedure Make_Indent (Output_Object : in out Corr_Output_Type) is -- Internal: -- Output the appropriate indent after a New_Line or Put_Line. begin --Ada.Text_IO.Put_Line("Make_Indent: Amount=" & Natural'Image(Output_Object.Indent_Amount)); for I in 1 .. Output_Object.Indent_Amount loop Ada.Text_IO.Put (Output_Object.Output_File, ' '); end loop; Output_Object.Char_Count := Output_Object.Indent_Amount; Output_Object.Out_Char_Count := Output_Object.Indent_Amount; Output_Object.Output_Buffer_Space_Before := False; end Make_Indent; procedure Spill (Output_Object : in out Corr_Output_Type) is -- Internal: -- Empty the output buffer in preperation for a New_Line or Put_Line. begin if Output_Object.Output_Buffer_Space_Before then Ada.Text_IO.Put (Output_Object.Output_File, ' '); Output_Object.Char_Count := Output_Object.Char_Count + 1; -- Count the space. Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 1; -- Count the space. end if; if Output_Object.Output_Buffer_Len /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, Output_Object.Output_Buffer (1 .. Output_Object.Output_Buffer_Len)); --Ada.Text_IO.Put_Line("Spill: Len=" & Natural'Image(Output_Object.Output_Buffer_Len) & -- " Space added=" & Boolean'Image(Output_Object.Output_Buffer_Space_Before) & " Text=" & -- Output_Object.Output_Buffer (1 .. Output_Object.Output_Buffer_Len)); Output_Object.Output_Buffer_Len := 0; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + Output_Object.Output_Buffer_Len; end if; Output_Object.Output_Buffer_Space_Before := False; end Spill; procedure Buffer (Output_Object : in out Corr_Output_Type; Char : in Character) is -- Internal: -- Add Char to the output buffer. Char will *not* be a word break -- character. begin if Output_Object.Output_Buffer_Len = Output_Object.Output_Buffer'Last then -- Oops, buffer is full. Spill it, and this character. --Ada.Text_IO.Put_Line("** Buffer overflow!!"); Spill (Output_Object); Ada.Text_IO.Put (Output_Object.Output_File, Char); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 1; return; end if; Output_Object.Output_Buffer_Len := Output_Object.Output_Buffer_Len + 1; Output_Object.Output_Buffer(Output_Object.Output_Buffer_Len) := Char; Output_Object.Char_Count := Output_Object.Char_Count + 1; end Buffer; procedure Buffer (Output_Object : in out Corr_Output_Type; Str : in String) is -- Internal: -- Add Char to the output buffer. String will *not* include a word -- break character. begin if Output_Object.Output_Buffer_Len+Str'Length >= Output_Object.Output_Buffer'Last then -- Oops, buffer is full. Spill it. --Ada.Text_IO.Put_Line("** Buffer overflow!!"); Spill (Output_Object); end if; Output_Object.Output_Buffer(Output_Object.Output_Buffer_Len+1..Output_Object.Output_Buffer_Len+Str'Length) := Str; Output_Object.Output_Buffer_Len := Output_Object.Output_Buffer_Len + Str'Length; Output_Object.Char_Count := Output_Object.Char_Count + Str'Length; end Buffer; procedure Start_Paragraph (Output_Object : in out Corr_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Number : in String; No_Prefix : in Boolean := False; Tab_Stops : in ARM_Output.Tab_Info := ARM_Output.NO_TABS; No_Breaks : in Boolean := False; Keep_with_Next : in Boolean := False; Space_After : in ARM_Output.Space_After_Type := ARM_Output.Normal; Justification : in ARM_Output.Justification_Type := ARM_Output.Default) is -- Start a new paragraph. The style and indent of the paragraph is as -- specified. The (AA)RM paragraph number (which might include update -- and version numbers as well: [12.1/1]) is Number. If the format is -- a type with a prefix (bullets, hangining items), the prefix is -- omitted if No_Prefix is true. Tab_Stops defines the tab stops for -- the paragraph. If No_Breaks is True, we will try to avoid page breaks -- in the paragraph. If Keep_with_Next is true, we will try to avoid -- separating this paragraph and the next one. (These may have no -- effect in formats that don't have page breaks). Space_After -- specifies the amount of space following the paragraph. Justification -- specifies the text justification for the paragraph. Not_Valid_Error -- is raised if Tab_Stops /= NO_TABS for a hanging or bulleted format. use type ARM_Output.Paragraph_Indent_Type; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already in paragraph"); end if; Output_Object.Is_In_Paragraph := True; Output_Object.Is_Hanging := False; Output_Object.Saw_Hang_End := False; Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; Output_Object.Output_Buffer_Space_Before := False; -- Nothing in it or on the line. Output_Object.Output_Buffer_Len := 0; Output_Object.Font := ARM_Output.Default; Output_Object.Is_Bold := False; Output_Object.Is_Italic := False; Output_Object.Size := 0; Output_Object.Para_Style := Style; Output_Object.Para_Indent := Indent; Output_Object.Is_Fixed_Format := False; if Output_Object.Clause_Len /= 0 and then Number /= "" then Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put (Output_Object.Output_File, "!paragraph "); Ada.Text_IO.Put (Output_Object.Output_File, Output_Object.Clause_Num(1..Output_Object.Clause_Len)); Ada.Text_IO.Put (Output_Object.Output_File, '('); Ada.Text_IO.Put (Output_Object.Output_File, Number); Ada.Text_IO.Put (Output_Object.Output_File, ") ["); Ada.Text_IO.Put (Output_Object.Output_File, ARM_Output.Paragraph_Style_Type'Image(Style) & " :" & ARM_Output.Paragraph_Indent_Type'Image(Indent)); Ada.Text_IO.Put_Line (Output_Object.Output_File, "]"); Ada.Text_IO.New_Line (Output_Object.Output_File); else Ada.Text_IO.New_Line (Output_Object.Output_File); end if; Output_Object.Indent_Amount := Integer(Indent)*4 + 2; case Style is when ARM_Output.Normal => if Indent = 0 then null; -- %% Temp. Output_Object.Indent_Amount := 0; -- %% Temp. elsif Indent = 3 then Ada.Text_IO.Put (Output_Object.Output_File, "@xindent<"); Output_Object.Char_Count := 9; Output_Object.Indent_Amount := 0; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Wide_Above => null; if Indent = 0 then null; -- %% Temp. Output_Object.Indent_Amount := 0; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small => if Indent = 1 then -- Notes. Ada.Text_IO.Put (Output_Object.Output_File, "@xindent<@s9<"); Output_Object.Char_Count := 13; Output_Object.Indent_Amount := 0; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Wide_Above => null; -- ** TBD (Unknown cases). when ARM_Output.Header => null; -- ** TBD (Unknown cases). when ARM_Output.Small_Header => if Indent = 1 then -- Notes Header. null; --Output_Object.Indent_Amount := 6; --** TBD. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Index => null; --** TBD. when ARM_Output.Syntax_Summary => null; --** TBD. when ARM_Output.Title => null; -- ** TBD (Unknown cases). when ARM_Output.Examples => if Indent = 1 then Ada.Text_IO.Put (Output_Object.Output_File, "@xcode<"); Output_Object.Char_Count := 7; Output_Object.Is_Fixed_Format := True; Output_Object.Indent_Amount := 0; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Examples => null; --** TBD. when ARM_Output.Swiss_Examples => if Indent = 1 then Ada.Text_IO.Put (Output_Object.Output_File, "@xcode<"); Output_Object.Char_Count := 7; Output_Object.Is_Fixed_Format := True; Output_Object.Indent_Amount := 0; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Swiss_Examples => null; --** TBD. when ARM_Output.Bulleted => if Indent = 1 then Output_Object.Indent_Amount := 0; -- %% Temp. if No_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, "@xindent<"); Output_Object.Char_Count := 9; else Ada.Text_IO.Put (Output_Object.Output_File, "@xbullet<"); Output_Object.Char_Count := 9; end if; else -- Unknown/unimplemented case. null; -- ** Tbd. end if; when ARM_Output.Nested_Bulleted => null; --** TBD. when ARM_Output.Small_Bulleted => null; --** TBD. when ARM_Output.Small_Nested_Bulleted => null; --** TBD. when ARM_Output.Giant_Hanging => null; --** TBD. when ARM_Output.Wide_Hanging => if Indent = 3 then Output_Object.Indent_Amount := 0; -- %% Temp. Output_Object.Is_Hanging := True; if No_Prefix then Output_Object.Saw_Hang_End := True; Output_Object.Char_Count := 0; else -- Has prefix -- No units on first line. Output_Object.Saw_Hang_End := False; Ada.Text_IO.Put (Output_Object.Output_File, "@xhang<@xterm<"); Output_Object.Char_Count := 14; end if; else -- Unknown/unimplemented case. null; -- ** Tbd. end if; when ARM_Output.Medium_Hanging => null; --** TBD. when ARM_Output.Narrow_Hanging => null; --** TBD. when ARM_Output.Hanging_in_Bulleted => null; --** TBD. when ARM_Output.Small_Giant_Hanging => null; --** TBD. when ARM_Output.Small_Wide_Hanging => null; --** TBD. when ARM_Output.Small_Medium_Hanging => null; --** TBD. when ARM_Output.Small_Narrow_Hanging => null; --** TBD. when ARM_Output.Small_Hanging_in_Bulleted => null; --** TBD. when ARM_Output.Enumerated => null; --** TBD. when ARM_Output.Small_Enumerated => null; --** TBD. end case; if Output_Object.Indent_Amount > 6 then for I in 1 .. (Output_Object.Indent_Amount-6)/4 loop Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + 4; end loop; end if; case Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Header | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Small_Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Swiss_Examples => Output_Object.Tab_Stops := Tab_Stops; -- We'll expand proportional stops here (text characters -- are larger than the variable ones these are set up for). for I in 1 .. Tab_Stops.Number loop if ARM_Output."=" (Tab_Stops.Stops(I).Kind, ARM_Output.Left_Proportional) then Output_Object.Tab_Stops.Stops(I).Stop := (Tab_Stops.Stops(I).Stop * 5 / 4) + Output_Object.Indent_Amount; else Output_Object.Tab_Stops.Stops(I).Stop := Tab_Stops.Stops(I).Stop + Output_Object.Indent_Amount; end if; end loop; when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted | ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Enumerated => if Tab_Stops.Number /= 0 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tabs in hanging/bulleted paragraph"); end if; end case; Output_Object.Out_Char_Count := Output_Object.Char_Count; -- Note: No_Breaks, Keep_with_Next, and Justification have no effect -- here. --Ada.Text_IO.Put_Line ("Start_Paragraph - Indent=" & Natural'Image(Output_Object.Indent_Amount) & " Cnt=" & -- Natural'Image(Output_Object.Char_Count)); end Start_Paragraph; procedure End_Paragraph (Output_Object : in out Corr_Output_Type) is -- End a paragraph. use type ARM_Output.Paragraph_Indent_Type; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; case Output_Object.Para_Style is when ARM_Output.Normal => if Output_Object.Para_Indent = 0 then null; elsif Output_Object.Para_Indent = 3 then Buffer (Output_Object, '>'); else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Wide_Above => null; if Output_Object.Para_Indent = 0 then null; -- %% Temp. else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small => if Output_Object.Para_Indent = 1 then -- Notes. Buffer (Output_Object, ">>"); else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Wide_Above => null; -- ** TBD (Unknown cases). when ARM_Output.Header => null; -- ** TBD (Unknown cases). when ARM_Output.Small_Header => if Output_Object.Para_Indent = 1 then -- Notes Header. null; else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Index => null; --** TBD. when ARM_Output.Syntax_Summary => null; --** TBD. when ARM_Output.Title => null; --** TBD. when ARM_Output.Examples => if Output_Object.Para_Indent = 1 then Buffer (Output_Object, '>'); else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Examples => null; --** TBD. when ARM_Output.Swiss_Examples => if Output_Object.Para_Indent = 1 then Buffer (Output_Object, '>'); else -- Unknown case. null; -- ** Tbd. end if; when ARM_Output.Small_Swiss_Examples => null; --** TBD. when ARM_Output.Bulleted => if Output_Object.Para_Indent = 1 then Buffer (Output_Object, '>'); else -- Unknown/unimplemented case. null; -- ** Tbd. end if; when ARM_Output.Nested_Bulleted => null; --** TBD. when ARM_Output.Small_Bulleted => null; --** TBD. when ARM_Output.Small_Nested_Bulleted => null; --** TBD. when ARM_Output.Giant_Hanging => null; --** TBD. when ARM_Output.Wide_Hanging => if Output_Object.Para_Indent = 3 then Buffer (Output_Object, '>'); else -- Unknown/unimplemented case. null; -- ** Tbd. end if; when ARM_Output.Medium_Hanging => null; --** TBD. when ARM_Output.Narrow_Hanging => null; --** TBD. when ARM_Output.Hanging_in_Bulleted => null; --** TBD. when ARM_Output.Small_Giant_Hanging => null; --** TBD. when ARM_Output.Small_Wide_Hanging => null; --** TBD. when ARM_Output.Small_Medium_Hanging => null; --** TBD. when ARM_Output.Small_Narrow_Hanging => null; --** TBD. when ARM_Output.Small_Hanging_in_Bulleted => null; --** TBD. when ARM_Output.Enumerated => null; --** TBD. when ARM_Output.Small_Enumerated => null; --** TBD. end case; if Output_Object.Output_Buffer_Len /= 0 then Spill (Output_Object); end if; Output_Object.Is_In_Paragraph := False; Ada.Text_IO.New_Line (Output_Object.Output_File, 2); -- Double space paragraphs. end End_Paragraph; procedure Category_Header (Output_Object : in out Corr_Output_Type; Header_Text : String) is -- Output a Category header (that is, "Legality Rules", -- "Dynamic Semantics", etc.) -- (Note: We did not use a enumeration here to insure that these -- headers are spelled the same in all output versions). -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put_Line (Output_Object.Output_File, "!subheader"); Ada.Text_IO.Put (Output_Object.Output_File, "@i<@s8<"); if Ada.Strings.Fixed.Count (Header_Text, Special_Set) = 0 then Ada.Text_IO.Put (Output_Object.Output_File, Header_Text); else for I in Header_Text'Range loop if Header_Text(I) = '>' then Ada.Text_IO.Put (Output_Object.Output_File, "@>"); elsif Header_Text(I) = '@' then Ada.Text_IO.Put (Output_Object.Output_File, "@@"); else Ada.Text_IO.Put (Output_Object.Output_File, Header_Text(I)); end if; end loop; end if; Ada.Text_IO.Put (Output_Object.Output_File, ">>"); Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; end Category_Header; procedure Clause_Header (Output_Object : in out Corr_Output_Type; Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False) is -- Output a Clause header. The level of the header is specified -- in Level. The Clause Number is as specified; the top-level (and -- other) subdivision names are as specified. These should appear in -- the table of contents. -- For hyperlinked formats, this should generate a link target. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Clause_Len := Clause_Number'Length; Output_Object.Clause_Num(1..Output_Object.Clause_Len) := Clause_Number; -- Special for table of contents: if Clause_Number = "" and then (Header_Text = "Table of Contents" or else Header_Text = "Contents") then Ada.Text_IO.Put (Output_Object.Output_File, "!clause "); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; return; end if; Ada.Text_IO.Put (Output_Object.Output_File, "!clause "); case Level is when ARM_Contents.Plain_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Normative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "(normative)"); Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Informative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "(informative)"); Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Section => case Top_Level_Subdivision_Name is when ARM_Output.Chapter => Ada.Text_IO.Put_Line (Output_Object.Output_File, "Chapter " & Clause_Number & ": " & Header_Text); when ARM_Output.Section => Ada.Text_IO.Put_Line (Output_Object.Output_File, "Section " & Clause_Number & ": " & Header_Text); when ARM_Output.Clause => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number & " " & Header_Text); end case; when ARM_Contents.Unnumbered_Section => if Header_Text /= "" then Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); end if; when ARM_Contents.Clause | ARM_Contents.Subclause | ARM_Contents.Subsubclause => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number & ' ' & Header_Text); when ARM_Contents.Dead_Clause => raise Program_Error; -- No headers for dead clauses. end case; Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; -- We don't have any page breaks here to suppress. end Clause_Header; procedure Revised_Clause_Header (Output_Object : in out Corr_Output_Type; New_Header_Text : in String; Old_Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Version : in ARM_Contents.Change_Version_Type; Old_Version : in ARM_Contents.Change_Version_Type; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False) is -- Output a revised clause header. Both the original and new text will -- be output. The level of the header is specified in Level. The Clause -- Number is as specified; the top-level (and other) subdivision names -- are as specified. These should appear in the table of contents. -- For hyperlinked formats, this should generate a link target. -- Version is the insertion version of the new text; Old_Version is -- the insertion version of the old text. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. function Header_Text return String is -- Note: Version and Old_Version are not used. begin return '{' & New_Header_Text & "} [" & Old_Header_Text & ']'; end Header_Text; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Clause_Len := Clause_Number'Length; Output_Object.Clause_Num(1..Output_Object.Clause_Len) := Clause_Number; -- Special for table of contents: if Clause_Number = "" and then (Header_Text = "Table of Contents" or else -- Ada 95 format Header_Text = "Contents") then -- ISO 2004 format. Ada.Text_IO.Put (Output_Object.Output_File, "!clause "); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; return; end if; Ada.Text_IO.Put (Output_Object.Output_File, "!clause "); case Level is when ARM_Contents.Plain_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Normative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "(normative)"); Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Informative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "(informative)"); Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); when ARM_Contents.Section => case Top_Level_Subdivision_Name is when ARM_Output.Chapter => Ada.Text_IO.Put_Line (Output_Object.Output_File, "Chapter " & Clause_Number & ": " & Header_Text); when ARM_Output.Section => Ada.Text_IO.Put_Line (Output_Object.Output_File, "Section " & Clause_Number & ": " & Header_Text); when ARM_Output.Clause => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number & " " & Header_Text); end case; when ARM_Contents.Unnumbered_Section => if Header_Text /= "" then Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text); end if; when ARM_Contents.Clause | ARM_Contents.Subclause | ARM_Contents.Subsubclause => Ada.Text_IO.Put_Line (Output_Object.Output_File, Clause_Number & ' ' & Header_Text); when ARM_Contents.Dead_Clause => raise Program_Error; -- No headers for dead clauses. end case; Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Output_Object.Char_Count := 0; Output_Object.Out_Char_Count := 0; -- We don't have any page breaks here to suppress. end Revised_Clause_Header; procedure TOC_Marker (Output_Object : in out Corr_Output_Type; For_Start : in Boolean) is -- Mark the start (if For_Start is True) or end (if For_Start is -- False) of the table of contents data. Output objects that -- auto-generate the table of contents can use this to do needed -- actions. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; null; -- We don't care about this. end TOC_Marker; procedure New_Page (Output_Object : in out Corr_Output_Type; Kind : ARM_Output.Page_Kind_Type := ARM_Output.Any_Page) is -- Output a page break. -- Note that this has no effect on non-printing formats. -- Any_Page breaks to the top of the next page (whatever it is); -- Odd_Page_Only breaks to the top of the odd-numbered page; -- Soft_Page allows a page break but does not force one (use in -- "No_Breaks" paragraphs.) -- Raises Not_Valid_Error if in a paragraph if Kind = Any_Page or -- Odd_Page, and if not in a paragraph if Kind = Soft_Page. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; case Kind is when ARM_Output.Any_Page | ARM_Output.Odd_Page_Only => if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Page in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File, 2); when ARM_Output.Soft_Page => if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Soft page not in paragraph"); end if; null; -- No page breaks. Spill (Output_Object); end case; end New_Page; procedure New_Column (Output_Object : in out Corr_Output_Type) is -- Output a column break. -- Raises Not_Valid_Error if in a paragraph, or if the number of -- columns is 1. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "New column in paragraph"); end if; -- No columns in text format. Ada.Text_IO.New_Line (Output_Object.Output_File); end New_Column; procedure Start_Table (Output_Object : in out Corr_Output_Type; Columns : in ARM_Output.Column_Count; First_Column_Width : in ARM_Output.Column_Count; Last_Column_Width : in ARM_Output.Column_Count; Alignment : in ARM_Output.Column_Text_Alignment; No_Page_Break : in Boolean; Has_Border : in Boolean; Small_Text_Size : in Boolean; Header_Kind : in ARM_Output.Header_Kind_Type) is -- Starts a table. The number of columns is Columns; the first -- column has First_Column_Width times the normal column width, and -- the last column has Last_Column_Width times the normal column width. -- Alignment is the horizontal text alignment within the columns. -- No_Page_Break should be True to keep the table intact on a single -- page; False to allow it to be split across pages. -- Has_Border should be true if a border is desired, false otherwise. -- Small_Text_Size means that the contents will have the AARM size; -- otherwise it will have the normal size. -- Header_Kind determines whether the table has headers. -- This command starts a paragraph; the entire table is a single -- paragraph. Text will be considered part of the caption until the -- next table marker call. -- Raises Not_Valid_Error if in a paragraph. begin -- Alignment, No_Page_Break, Border, Small_Text_Size, and Header_Kind -- not used here. if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Table in paragraph"); end if; Output_Object.Tab_Stops.Number := Columns; declare Column_Units : constant ARM_Output.Column_Count := Columns+First_Column_Width+Last_Column_Width-2; Width : Natural := (72/(Column_Units)); begin if Column_Units <= 3 then -- Keep it from getting too wide. Width := 22; end if; for I in 1 .. Columns loop Output_Object.Tab_Stops.Stops(I) := (Kind => ARM_Output.Left_Fixed, Stop => Width*(I+First_Column_Width-1)+10); end loop; end; Output_Object.Indent_Amount := 10; Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := 10; Output_Object.Out_Char_Count := 10; Output_Object.Is_In_Paragraph := True; Output_Object.Is_In_Table := True; end Start_Table; procedure Table_Marker (Output_Object : in out Corr_Output_Type; Marker : in ARM_Output.Table_Marker_Type) is -- Marks the end of an entity in a table. -- If Marker is End_Caption, the table caption ends and the -- future text is part of the table header. -- If Marker is End_Header, the table header ends and the -- future text is part of the table body. -- If Marker is End_Row, a row in the table is completed, and another -- row started. -- If Marker is End_Row_Next_Is_Last, a row in the table is completed, -- and another row started. That row is the last row in the table. -- If Marker is End_Item, an item in the table header or body is ended, -- and another started. -- If Marker is End_Table, the entire table is finished. -- Raises Not_Valid_Error if not in a table. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if (not Output_Object.Is_In_Paragraph) or (not Output_Object.Is_In_Table) then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Table marker not in table"); end if; case Marker is when ARM_Output.End_Item => -- Just tab over one row: Spill (Output_Object); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 1; for I in 1 .. Output_Object.Tab_Stops.Number loop if Output_Object.Tab_Stops.Stops(I).Stop > Output_Object.Char_Count then for J in Output_Object.Char_Count+1 .. Output_Object.Tab_Stops.Stops(I).Stop-1 loop Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 1; end loop; end if; end loop; when ARM_Output.End_Caption => Spill (Output_Object); Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := 10; Output_Object.Out_Char_Count := 10; when ARM_Output.End_Header => Spill (Output_Object); Ada.Text_IO.New_Line (Output_Object.Output_File, 2); Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := 10; Output_Object.Out_Char_Count := 10; when ARM_Output.End_Row | ARM_Output.End_Row_Next_Is_Last => Spill (Output_Object); Ada.Text_IO.New_Line (Output_Object.Output_File, 1); Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := 10; Output_Object.Out_Char_Count := 10; when ARM_Output.End_Table => Spill (Output_Object); Output_Object.Is_In_Paragraph := False; Output_Object.Is_In_Table := False; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Tab_Stops := ARM_Output.NO_TABS; end case; end Table_Marker; procedure Separator_Line (Output_Object : in out Corr_Output_Type; Is_Thin : Boolean := True) is -- Output a separator line. It is thin if "Is_Thin" is true. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Separator in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); if Is_Thin then Ada.Text_IO.Put_Line (Output_Object.Output_File, "---------------------------------------------------------------------"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, "====================================================================="); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); end Separator_Line; -- Text output: These are only allowed after a Start_Paragraph and -- before any End_Paragraph. Raises Not_Valid_Error if not allowed. procedure Ordinary_Text (Output_Object : in out Corr_Output_Type; Text : in String) is -- Output ordinary text. -- The text must end at a word break, never in the middle of a word. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; --Ada.Text_IO.Put_Line ("Ordinary_Text: Cnt=" & Natural'Image(Output_Object.Char_Count) & --" Buffer=" & Natural'Image(Output_Object.Output_Buffer_Len)); if Output_Object.Char_Count + Text'Length >= LINE_LENGTH - 2 and then Output_Object.Out_Char_Count > Output_Object.Indent_Amount then -- We want a line break here if the line is too long and something was output: Ada.Text_IO.New_Line (Output_Object.Output_File); Make_Indent (Output_Object); --Output_Object.Output_Buffer_Space_Before := False; -- Start of line, this is done by Make_Indent. Spill (Output_Object); else Spill (Output_Object); end if; if Ada.Strings.Fixed.Count (Text, Special_Set) = 0 then Ada.Text_IO.Put (Output_Object.Output_File, Text); Output_Object.Char_Count := Output_Object.Char_Count + Text'Length; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + Text'Length; else for I in Text'Range loop if Text(I) = '>' then Ada.Text_IO.Put (Output_Object.Output_File, "@>"); Output_Object.Char_Count := Output_Object.Char_Count + 2; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 2; elsif Text(I) = '@' then Ada.Text_IO.Put (Output_Object.Output_File, "@@"); Output_Object.Char_Count := Output_Object.Char_Count + 2; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 2; else Ada.Text_IO.Put (Output_Object.Output_File, Text(I)); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Out_Char_Count := Output_Object.Out_Char_Count + 1; end if; end loop; end if; Output_Object.Output_Buffer_Space_Before := False; -- No space between -- this and any following text. end Ordinary_Text; procedure Ordinary_Character (Output_Object : in out Corr_Output_Type; Char : in Character) is -- Output an ordinary character. -- Spaces will be used to break lines as needed. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Char_Count >= LINE_LENGTH and then Output_Object.Out_Char_Count > Output_Object.Indent_Amount then -- Insert a break here if anything has been output (but don't -- Spill the buffer): --Ada.Text_IO.Put_Line ("Ordinary_Char [Break, no spill]: Cnt=" & Natural'Image(Output_Object.Char_Count)); Ada.Text_IO.New_Line (Output_Object.Output_File); Make_Indent (Output_Object); --Output_Object.Output_Buffer_Space_Before := False; -- Start of line, this is done by Make_Indent. -- Note that this may make the space disappear. -- Add the contents of the buffer to the character count for this line: Output_Object.Char_Count := Output_Object.Char_Count + Output_Object.Output_Buffer_Len; if Char = '>' then Buffer (Output_Object, "@>"); elsif Char = '@' then Buffer (Output_Object, "@@"); elsif Char /= ' ' then Buffer (Output_Object, Char); else -- Break character, spill on the new line: if Output_Object.Output_Buffer_Len /= 0 then Spill (Output_Object); -- Output the buffer up to the space. Output_Object.Output_Buffer_Space_Before := True; -- Mid-line now. -- else nothing in buffer, so nothing to output; just skip it. end if; end if; elsif Char = ' ' then -- Break character, and it fits on this line: if Output_Object.Output_Buffer_Len /= 0 then --Ada.Text_IO.Put_Line ("Ordinary_Char [Space spill]: Cnt=" & Natural'Image(Output_Object.Char_Count)); Spill (Output_Object); -- Output the buffer up to the space. Output_Object.Output_Buffer_Space_Before := True; -- Mid-line now. else -- nothing in buffer. -- nothing to output. But make sure we display a space before -- the next item. Output_Object.Output_Buffer_Space_Before := True; -- Mid-line now. end if; elsif Char = '>' then Buffer (Output_Object, "@>"); elsif Char = '@' then Buffer (Output_Object, "@@"); else Buffer (Output_Object, Char); end if; end Ordinary_Character; procedure Hard_Space (Output_Object : in out Corr_Output_Type) is -- Output a hard space. No line break should happen at a hard space. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Is_Fixed_Format then -- In this format, all spaces are hard spaces. Buffer (Output_Object, ' '); else -- A hard space command. Buffer (Output_Object, "@ "); end if; end Hard_Space; procedure Line_Break (Output_Object : in out Corr_Output_Type) is -- Output a line break. This does not start a new paragraph. -- This corresponds to a "
" in HTML. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; --Ada.Text_Io.Put_Line ("Line_Break"); if Output_Object.Is_Fixed_Format then -- In this format, all line breaks are significant. null; else -- A hard space command. Buffer (Output_Object, "@hr"); end if; if Output_Object.Output_Buffer_Len /= 0 then Spill (Output_Object); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Make_Indent (Output_Object); end Line_Break; procedure Index_Line_Break (Output_Object : in out Corr_Output_Type; Clear_Keep_with_Next : in Boolean) is -- Output a line break for the index. This does not start a new -- paragraph in terms of spacing. This corresponds to a "
" -- in HTML. If Clear_Keep_with_Next is true, insure that the next -- line does not require the following line to stay with it. -- Raises Not_Valid_Error if the paragraph is not in the index format. begin Line_Break (Output_Object); end Index_Line_Break; procedure Soft_Line_Break (Output_Object : in out Corr_Output_Type) is -- Output a soft line break. This is a place (in the middle of a -- "word") that we allow a line break. It is usually used after -- underscores in long non-terminals. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- if Output_Object.Char_Count >= LINE_LENGTH - 10 then -- if Output_Object.Output_Buffer_Len /= 0 then -- Spill (Output_Object); -- end if; -- Ada.Text_IO.New_Line (Output_Object.Output_File); -- Make_Indent (Output_Object); -- -- else we don't need a line break. -- end if; null; -- Ignore this, there is no counterpart in Corrigendum formatting. end Soft_Line_Break; procedure Soft_Hyphen_Break (Output_Object : in out Corr_Output_Type) is -- Output a soft line break, with a hyphen. This is a place (in the middle of -- a "word") that we allow a line break. If the line break is used, -- a hyphen will be added to the text. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- if Output_Object.Char_Count >= LINE_LENGTH - 8 then -- Spill (Output_Object); -- Ada.Text_IO.Put_Line (Output_Object.Output_File, "-"); -- Add the hyphen and break. -- Make_Indent (Output_Object); -- -- else we don't need a line break. -- end if; null; -- Ignore this, there is no counterpart in Corrigendum formatting. end Soft_Hyphen_Break; procedure Tab (Output_Object : in out Corr_Output_Type) is -- Output a tab, inserting space up to the next tab stop. -- Raises Not_Valid_Error if the paragraph was created with -- Tab_Stops = ARM_Output.NO_TABS. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if ARM_Output."="(Output_Object.Tab_Stops, ARM_Output.NO_TABS) then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tab, but none set"); end if; -- We use the tab stops as characters here, and fixed and proportional -- stops are treated identically. -- Find the first stop greater than the current character count. (After -- writing a space). --Ada.Text_IO.Put_Line ("Tab"); Buffer (Output_Object, "@tab"); Output_Object.Output_Buffer_Space_Before := False; -- Spaces needed were output. end Tab; procedure Special_Character (Output_Object : in out Corr_Output_Type; Char : in ARM_Output.Special_Character_Type) is -- Output an special character. begin --** Could use Latin1 and Unicode equivalents for most of these. case Char is when ARM_Output.EM_Dash => Buffer (Output_Object, "@emdash"); when ARM_Output.EN_Dash => Buffer (Output_Object, "@endash"); when ARM_Output.GEQ => Ordinary_Text (Output_Object, ">="); -- Not available in Corrigendum, use the Ada one. when ARM_Output.LEQ => Ordinary_Text (Output_Object, "<="); -- Not available in Corrigendum, use the Ada one. when ARM_Output.NEQ => Ordinary_Text (Output_Object, "/="); -- Not available in Corrigendum, use the Ada one. when ARM_Output.PI => Buffer (Output_Object, "@pi"); when ARM_Output.Left_Ceiling => Ordinary_Text (Output_Object, "Ceiling("); -- Not available in Corrigendum. when ARM_Output.Right_Ceiling => Ordinary_Text (Output_Object, ")"); -- Not available in Corrigendum. when ARM_Output.Left_Floor => Ordinary_Text (Output_Object, "Floor("); -- Not available in Corrigendum. when ARM_Output.Right_Floor => Ordinary_Text (Output_Object, ")"); -- Not available in Corrigendum. when ARM_Output.Thin_Space => Ordinary_Text (Output_Object, " "); -- Not available in Corrigendum. when ARM_Output.Left_Quote => Buffer (Output_Object, "@lquote"); when ARM_Output.Right_Quote => Buffer (Output_Object, "@rquote"); when ARM_Output.Left_Double_Quote => Ordinary_Text (Output_Object, """"); -- Not available in Corrigendum, use double quote. when ARM_Output.Right_Double_Quote => Ordinary_Text (Output_Object, """"); -- Not available in Corrigendum, use double quote. when ARM_Output.Small_Dotless_I => Ordinary_Text (Output_Object, "i"); -- Not available in Corrigendum, use the nearest text. when ARM_Output.Capital_Dotted_I => Ordinary_Text (Output_Object, "I"); -- Not available in Corrigendum, use the nearest text. end case; end Special_Character; procedure Unicode_Character (Output_Object : in out Corr_Output_Type; Char : in ARM_Output.Unicode_Type) is -- Output a Unicode character, with code position Char. Char_Code : constant String := ARM_Output.Unicode_Type'Image(Char); begin -- We don't check, but we assume this is not a normal character. Buffer (Output_Object, "@unicode<" & Char_Code(2..Char_Code'Last) & ">"); end Unicode_Character; procedure End_Hang_Item (Output_Object : in out Corr_Output_Type) is -- Marks the end of a hanging item. Call only once per paragraph. -- Raises Not_Valid_Error if the paragraph style is not in -- Text_Prefixed_Style_Subtype, or if this has already been -- called for the current paragraph, or if the paragraph was started -- with No_Prefix = True. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if not Output_Object.Is_Hanging then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not a hanging paragraph"); end if; if Output_Object.Saw_Hang_End then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already saw the end of the hanging part"); end if; Output_Object.Saw_Hang_End := True; Buffer (Output_Object, ">"); -- Close @Xterm< end End_Hang_Item; procedure Text_Format (Output_Object : in out Corr_Output_Type; Format : in ARM_Output.Format_Type) is -- Change the text format so that all of the properties are as specified. -- Note: Changes to these properties ought be stack-like; that is, -- Bold on, Italic on, Italic off, Bold off is OK; Bold on, Italic on, -- Bold off, Italic off should be avoided (as separate commands). use type ARM_Output.Change_Type; use type ARM_Output.Location_Type; use type ARM_Output.Size_Type; -- Note: We ignore colors here, no colors in !Corrigendum markup. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if not Format.Bold and Output_Object.Is_Bold then Buffer (Output_Object, '>'); Output_Object.Is_Bold := False; end if; if not Format.Italic and Output_Object.Is_Italic then Buffer (Output_Object, '>'); Output_Object.Is_Italic := False; end if; if Format.Size /= Output_Object.Size then if Output_Object.Size /= 0 then Buffer (Output_Object, '>'); end if; end if; if Format.Location /= Output_Object.Location then if Output_Object.Location /= ARM_Output.Normal then --Buffer (Output_Object, '>'); null; -- Corrigendum doesn't support this. end if; end if; if ARM_Output."/=" (Format.Font, Output_Object.Font) then case Output_Object.Font is when ARM_Output.Default => null; when ARM_Output.Fixed => Buffer (Output_Object, '>'); when ARM_Output.Roman => Buffer (Output_Object, '>'); when ARM_Output.Swiss => Buffer (Output_Object, '>'); end case; end if; -- For the intended purpose, there should be no Change commands. if Format.Change /= Output_Object.Change then if Format.Change = ARM_Output.Both then -- Open only the one(s) needed: case Output_Object.Change is -- Note: Version is not used. when ARM_Output.Insertion => -- Open the deletion: Buffer(Output_Object, '['); when ARM_Output.Deletion => -- Open the insertion: Buffer(Output_Object, '{'); when ARM_Output.None => Buffer(Output_Object, '{'); Buffer(Output_Object, '['); when ARM_Output.Both => null; end case; elsif Output_Object.Change = ARM_Output.Both then -- Close only the one(s) needed: case Format.Change is -- Note: Version is not used. when ARM_Output.Insertion => -- Close the deletion: Buffer(Output_Object, ']'); when ARM_Output.Deletion => -- Close the insertion: Buffer(Output_Object, '}'); when ARM_Output.None => Buffer(Output_Object, ']'); Buffer(Output_Object, '}'); when ARM_Output.Both => null; end case; else -- Both can't get here. case Output_Object.Change is when ARM_Output.Insertion => Buffer(Output_Object, '}'); when ARM_Output.Deletion => Buffer(Output_Object, ']'); when ARM_Output.None => null; when ARM_Output.Both => Buffer(Output_Object, ']'); Buffer(Output_Object, '}'); end case; case Format.Change is -- Note: Version is not used. when ARM_Output.Insertion => Buffer(Output_Object, '{'); when ARM_Output.Deletion => Buffer(Output_Object, '['); when ARM_Output.None => null; when ARM_Output.Both => Buffer(Output_Object, '{'); Buffer(Output_Object, '['); end case; end if; Output_Object.Change := Format.Change; end if; if ARM_Output."/=" (Format.Font, Output_Object.Font) then case Format.Font is when ARM_Output.Default => null; when ARM_Output.Fixed => Buffer (Output_Object, "@fc<"); when ARM_Output.Roman => Buffer (Output_Object, "@ft<"); when ARM_Output.Swiss => Buffer (Output_Object, "@fa<"); end case; Output_Object.Font := Format.Font; end if; if Format.Location /= Output_Object.Location then case Format.Location is when ARM_Output.Superscript => --Buffer (Output_Object, "@+<"); null; -- Corrigendum doesn't support this. when ARM_Output.Subscript => --Buffer (Output_Object, "@+<"); null; -- Corrigendum doesn't support this. when ARM_Output.Normal => null; end case; Output_Object.Location := Format.Location; end if; if Format.Size /= Output_Object.Size then if Format.Size < 0 then Buffer (Output_Object, "@s" & Character'Val(10+Format.Size+Character'Pos('0')) & '<'); else Buffer (Output_Object, "@s1" & Character'Val(Format.Size+Character'Pos('0')) & '<'); end if; Output_Object.Size := Format.Size; end if; if Format.Italic and (not Output_Object.Is_Italic) then Buffer (Output_Object, "@i<"); Output_Object.Is_Italic := True; end if; if Format.Bold and (not Output_Object.Is_Bold) then Buffer (Output_Object, "@b<"); Output_Object.Is_Bold := True; end if; end Text_Format; procedure Clause_Reference (Output_Object : in out Corr_Output_Type; Text : in String; Clause_Number : in String) is -- Generate a reference to a clause in the standard. The text of -- the reference is "Text", and the number of the clause is -- Clause_Number. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end Clause_Reference; procedure Index_Target (Output_Object : in out Corr_Output_Type; Index_Key : in Natural) is -- Generate a index target. This marks the location where an index -- reference occurs. Index_Key names the index item involved. -- For hyperlinked formats, this should generate a link target; -- for other formats, nothing is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; null; -- Nothing to do for plain text. end Index_Target; procedure Index_Reference (Output_Object : in out Corr_Output_Type; Text : in String; Index_Key : in Natural; Clause_Number : in String) is -- Generate a reference to an index target in the standard. The text -- of the reference is "Text", and Index_Key and Clause_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end Index_Reference; procedure DR_Reference (Output_Object : in out Corr_Output_Type; Text : in String; DR_Number : in String) is -- Generate a reference to an DR from the standard. The text -- of the reference is "Text", and DR_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end DR_Reference; procedure AI_Reference (Output_Object : in out Corr_Output_Type; Text : in String; AI_Number : in String) is -- Generate a reference to an AI from the standard. The text -- of the reference is "Text", and AI_Number denotes -- the target (in unfolded format). For hyperlinked formats, this -- should generate a link; for other formats, the text alone is -- generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end AI_Reference; procedure Local_Target (Output_Object : in out Corr_Output_Type; Text : in String; Target : in String) is -- Generate a local target. This marks the potential target of local -- links identified by "Target". Text is the text of the target. -- For hyperlinked formats, this should generate a link target; -- for other formats, only the text is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end Local_Target; procedure Local_Link (Output_Object : in out Corr_Output_Type; Text : in String; Target : in String; Clause_Number : in String) is -- Generate a local link to the target and clause given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end Local_Link; procedure Local_Link_Start (Output_Object : in out Corr_Output_Type; Target : in String; Clause_Number : in String) is -- Generate a local link to the target and clause given. -- The link will surround text until Local_Link_End is called. -- Local_Link_End must be called before this routine can be used again. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin null; -- No link, nothing to do. end Local_Link_Start; procedure Local_Link_End (Output_Object : in out Corr_Output_Type; Target : in String; Clause_Number : in String) is -- End a local link for the target and clause given. -- This must be in the same paragraph as the Local_Link_Start. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin null; -- No link, nothing to do. end Local_Link_End; procedure URL_Link (Output_Object : in out Corr_Output_Type; Text : in String; URL : in String) is -- Generate a link to the URL given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin Ordinary_Text (Output_Object, Text); -- Nothing special in this format. end URL_Link; procedure Picture (Output_Object : in out Corr_Output_Type; Name : in String; Descr : in String; Alignment : in ARM_Output.Picture_Alignment; Height, Width : in Natural; Border : in ARM_Output.Border_Kind) is -- Generate a picture. -- Name is the (simple) file name of the picture; Descr is a -- descriptive name for the picture (it will appear in some web -- browsers). -- We assume that it is a .GIF or .JPG and that it will be present -- in the same directory as the input files and the same directory as -- the .HTML output files. -- Alignment specifies the picture alignment. -- Height and Width specify the picture size in pixels. -- Border specifies the kind of border. begin Ordinary_Text (Output_Object, "[Picture: " & Name & " - " & Descr & "]"); end Picture; end ARM_Corr; org.adaic.arm_form/progs/arm_corr.ads0000755000175200010010000005052512066652506017117 0ustar stepheNonewith ARM_Output, ARM_Contents, Ada.Text_IO; package ARM_Corr is -- -- Ada reference manual formatter (ARM_Form). -- -- This package defines the text output object. -- Output objects are responsible for implementing the details of -- a particular format. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2006, 2007, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 6/ 2/05 - RLB - Created base package from text and HTML versions. -- 1/11/06 - RLB - Eliminated dispatching Create in favor of tailored -- versions. -- 1/13/06 - RLB - Added new Link operations. -- 2/ 8/06 - RLB - Added additional parameters to the table command. -- 2/10/06 - RLB - Added even more additional parameters to the -- table command. -- - RLB - Added picture command. -- 9/25/06 - RLB - Added Last_Column_Width to Start_Table. -- 10/13/06 - RLB - Added Local_Link_Start and Local_Link_End to allow -- formatting in the linked text. -- 2/ 9/07 - RLB - Changed comments on AI_Reference. -- 2/13/07 - RLB - Revised to separate style and indent information -- for paragraphs. -- 12/19/07 - RLB - Added limited colors to Text_Format. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/25/11 - RLB - Added old insertion version to Revised_Clause_Header. -- 8/31/12 - RLB - Added Output_Path. -- 11/26/12 - RLB - Added subdivision names to Clause_Header and -- Revised_Clause_Header. type Corr_Output_Type is new ARM_Output.Output_Type with private; procedure Create (Output_Object : in out Corr_Output_Type; File_Prefix : in String; Output_Path : in String; Title : in String := ""); -- Create an Output_Object for a document. -- The prefix of the output file names is File_Prefix - this -- should be no more then 5 characters allowed in file names. -- The result files will be written to Output_Path. -- The title of the document is Title. procedure Close (Output_Object : in out Corr_Output_Type); -- Close an Output_Object. No further output to the object is -- allowed after this call. procedure Section (Output_Object : in out Corr_Output_Type; Section_Title : in String; Section_Name : in String); -- Start a new section. The title is Section_Title (this is -- intended for humans). The name is Section_Name (this is -- intended to be suitable to be a portion of a file name). procedure Set_Columns (Output_Object : in out Corr_Output_Type; Number_of_Columns : in ARM_Output.Column_Count); -- Set the number of columns. -- Raises Not_Valid_Error if in a paragraph. procedure Start_Paragraph (Output_Object : in out Corr_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Number : in String; No_Prefix : in Boolean := False; Tab_Stops : in ARM_Output.Tab_Info := ARM_Output.NO_TABS; No_Breaks : in Boolean := False; Keep_with_Next : in Boolean := False; Space_After : in ARM_Output.Space_After_Type := ARM_Output.Normal; Justification : in ARM_Output.Justification_Type := ARM_Output.Default); -- Start a new paragraph. The style and indent of the paragraph is as -- specified. The (AA)RM paragraph number (which might include update -- and version numbers as well: [12.1/1]) is Number. If the format is -- a type with a prefix (bullets, hangining items), the prefix is -- omitted if No_Prefix is true. Tab_Stops defines the tab stops for -- the paragraph. If No_Breaks is True, we will try to avoid page breaks -- in the paragraph. If Keep_with_Next is true, we will try to avoid -- separating this paragraph and the next one. (These may have no -- effect in formats that don't have page breaks). Space_After -- specifies the amount of space following the paragraph. Justification -- specifies the text justification for the paragraph. Not_Valid_Error -- is raised if Tab_Stops /= NO_TABS for a hanging or bulleted format. procedure End_Paragraph (Output_Object : in out Corr_Output_Type); -- End a paragraph. procedure Category_Header (Output_Object : in out Corr_Output_Type; Header_Text : String); -- Output a Category header (that is, "Legality Rules", -- "Dynamic Semantics", etc.) -- (Note: We did not use a enumeration here to insure that these -- headers are spelled the same in all output versions). -- Raises Not_Valid_Error if in a paragraph. procedure Clause_Header (Output_Object : in out Corr_Output_Type; Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False); -- Output a Clause header. The level of the header is specified -- in Level. The Clause Number is as specified; the top-level (and -- other) subdivision names are as specified. These should appear in -- the table of contents. -- For hyperlinked formats, this should generate a link target. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. procedure Revised_Clause_Header (Output_Object : in out Corr_Output_Type; New_Header_Text : in String; Old_Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Version : in ARM_Contents.Change_Version_Type; Old_Version : in ARM_Contents.Change_Version_Type; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False); -- Output a revised clause header. Both the original and new text will -- be output. The level of the header is specified in Level. The Clause -- Number is as specified; the top-level (and other) subdivision names -- are as specified. These should appear in the table of contents. -- For hyperlinked formats, this should generate a link target. -- Version is the insertion version of the new text; Old_Version is -- the insertion version of the old text. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. procedure TOC_Marker (Output_Object : in out Corr_Output_Type; For_Start : in Boolean); -- Mark the start (if For_Start is True) or end (if For_Start is -- False) of the table of contents data. Output objects that -- auto-generate the table of contents can use this to do needed -- actions. procedure New_Page (Output_Object : in out Corr_Output_Type; Kind : ARM_Output.Page_Kind_Type := ARM_Output.Any_Page); -- Output a page break. -- Note that this has no effect on non-printing formats. -- Any_Page breaks to the top of the next page (whatever it is); -- Odd_Page_Only breaks to the top of the odd-numbered page; -- Soft_Page allows a page break but does not force one (use in -- "No_Breaks" paragraphs.) -- Raises Not_Valid_Error if in a paragraph if Kind = Any_Page or -- Odd_Page, and if not in a paragraph if Kind = Soft_Page. procedure New_Column (Output_Object : in out Corr_Output_Type); -- Output a column break. -- Raises Not_Valid_Error if in a paragraph, or if the number of -- columns is 1. procedure Separator_Line (Output_Object : in out Corr_Output_Type; Is_Thin : Boolean := True); -- Output a separator line. It is thin if "Is_Thin" is true. -- Raises Not_Valid_Error if in a paragraph. procedure Start_Table (Output_Object : in out Corr_Output_Type; Columns : in ARM_Output.Column_Count; First_Column_Width : in ARM_Output.Column_Count; Last_Column_Width : in ARM_Output.Column_Count; Alignment : in ARM_Output.Column_Text_Alignment; No_Page_Break : in Boolean; Has_Border : in Boolean; Small_Text_Size : in Boolean; Header_Kind : in ARM_Output.Header_Kind_Type); -- Starts a table. The number of columns is Columns; the first -- column has First_Column_Width times the normal column width, and -- the last column has Last_Column_Width times the normal column width. -- Alignment is the horizontal text alignment within the columns. -- No_Page_Break should be True to keep the table intact on a single -- page; False to allow it to be split across pages. -- Has_Border should be true if a border is desired, false otherwise. -- Small_Text_Size means that the contents will have the AARM size; -- otherwise it will have the normal size. -- Header_Kind determines whether the table has headers. -- This command starts a paragraph; the entire table is a single -- paragraph. Text will be considered part of the caption until the -- next table marker call. -- Raises Not_Valid_Error if in a paragraph. procedure Table_Marker (Output_Object : in out Corr_Output_Type; Marker : in ARM_Output.Table_Marker_Type); -- Marks the end of an entity in a table. -- If Marker is End_Caption, the table caption ends and the -- future text is part of the table header. -- If Marker is End_Header, the table header ends and the -- future text is part of the table body. -- If Marker is End_Row, a row in the table is completed, and another -- row started. -- If Marker is End_Item, an item in the table header or body is ended, -- and another started. -- If Marker is End_Table, the entire table is finished. -- Raises Not_Valid_Error if not in a table. -- Text output: These are only allowed after a Start_Paragraph and -- before any End_Paragraph. Raises Not_Valid_Error if not allowed. procedure Ordinary_Text (Output_Object : in out Corr_Output_Type; Text : in String); -- Output ordinary text. -- The text must end at a word break, never in the middle of a word. procedure Ordinary_Character (Output_Object : in out Corr_Output_Type; Char : in Character); -- Output an ordinary character. -- Spaces will be used to break lines as needed. procedure Hard_Space (Output_Object : in out Corr_Output_Type); -- Output a hard space. No line break should happen at a hard space. procedure Line_Break (Output_Object : in out Corr_Output_Type); -- Output a line break. This does not start a new paragraph. -- This corresponds to a "
" in HTML. procedure Index_Line_Break (Output_Object : in out Corr_Output_Type; Clear_Keep_with_Next : in Boolean); -- Output a line break for the index. This does not start a new -- paragraph in terms of spacing. This corresponds to a "
" -- in HTML. If Clear_Keep_with_Next is true, insure that the next -- line does not require the following line to stay with it. procedure Soft_Line_Break (Output_Object : in out Corr_Output_Type); -- Output a soft line break. This is a place (in the middle of a -- "word") that we allow a line break. It is usually used after -- underscores in long non-terminals. procedure Soft_Hyphen_Break (Output_Object : in out Corr_Output_Type); -- Output a soft line break, with a hyphen. This is a place (in the middle of -- a "word") that we allow a line break. If the line break is used, -- a hyphen will be added to the text. procedure Tab (Output_Object : in out Corr_Output_Type); -- Output a tab, inserting space up to the next tab stop. -- Raises Not_Valid_Error if the paragraph was created with -- Tab_Stops = ARM_Output.NO_TABS. procedure Special_Character (Output_Object : in out Corr_Output_Type; Char : in ARM_Output.Special_Character_Type); -- Output an special character. procedure Unicode_Character (Output_Object : in out Corr_Output_Type; Char : in ARM_Output.Unicode_Type); -- Output a Unicode character, with code position Char. procedure End_Hang_Item (Output_Object : in out Corr_Output_Type); -- Marks the end of a hanging item. Call only once per paragraph. -- Raises Not_Valid_Error if the paragraph style is not in -- Text_Prefixed_Style_Subtype, or if this has already been -- called for the current paragraph, or if the paragraph was started -- with No_Prefix = True. procedure Text_Format (Output_Object : in out Corr_Output_Type; Format : in ARM_Output.Format_Type); -- Change the text format so that all of the properties are as specified. -- Note: Changes to these properties ought be stack-like; that is, -- Bold on, Italic on, Italic off, Bold off is OK; Bold on, Italic on, -- Bold off, Italic off should be avoided (as separate commands). procedure Clause_Reference (Output_Object : in out Corr_Output_Type; Text : in String; Clause_Number : in String); -- Generate a reference to a clause in the standard. The text of -- the reference is "Text", and the number of the clause is -- Clause_Number. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure Index_Target (Output_Object : in out Corr_Output_Type; Index_Key : in Natural); -- Generate a index target. This marks the location where an index -- reference occurs. Index_Key names the index item involved. -- For hyperlinked formats, this should generate a link target; -- for other formats, nothing is generated. procedure Index_Reference (Output_Object : in out Corr_Output_Type; Text : in String; Index_Key : in Natural; Clause_Number : in String); -- Generate a reference to an index target in the standard. The text -- of the reference is "Text", and Index_Key and Clause_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure DR_Reference (Output_Object : in out Corr_Output_Type; Text : in String; DR_Number : in String); -- Generate a reference to an DR from the standard. The text -- of the reference is "Text", and DR_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure AI_Reference (Output_Object : in out Corr_Output_Type; Text : in String; AI_Number : in String); -- Generate a reference to an AI from the standard. The text -- of the reference is "Text", and AI_Number denotes -- the target (in unfolded format). For hyperlinked formats, this should -- generate a link; for other formats, the text alone is generated. procedure Local_Target (Output_Object : in out Corr_Output_Type; Text : in String; Target : in String); -- Generate a local target. This marks the potential target of local -- links identified by "Target". Text is the text of the target. -- For hyperlinked formats, this should generate a link target; -- for other formats, only the text is generated. procedure Local_Link (Output_Object : in out Corr_Output_Type; Text : in String; Target : in String; Clause_Number : in String); -- Generate a local link to the target and clause given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Local_Link_Start (Output_Object : in out Corr_Output_Type; Target : in String; Clause_Number : in String); -- Generate a local link to the target and clause given. -- The link will surround text until Local_Link_End is called. -- Local_Link_End must be called before this routine can be used again. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Local_Link_End (Output_Object : in out Corr_Output_Type; Target : in String; Clause_Number : in String); -- End a local link for the target and clause given. -- This must be in the same paragraph as the Local_Link_Start. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure URL_Link (Output_Object : in out Corr_Output_Type; Text : in String; URL : in String); -- Generate a link to the URL given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Picture (Output_Object : in out Corr_Output_Type; Name : in String; Descr : in String; Alignment : in ARM_Output.Picture_Alignment; Height, Width : in Natural; Border : in ARM_Output.Border_Kind); -- Generate a picture. -- Name is the (simple) file name of the picture; Descr is a -- descriptive name for the picture (it will appear in some web -- browsers). -- We assume that it is a .GIF or .JPG and that it will be present -- in the same directory as the output files. -- Alignment specifies the picture alignment. -- Height and Width specify the picture size in pixels. -- Border specifies the kind of border. private subtype Buffer_String is String (1 .. 120); subtype Prefix_String is String(1..5); subtype Clause_String is String(1..20); type Corr_Output_Type is new ARM_Output.Output_Type with record Is_Valid : Boolean := False; Is_In_Paragraph : Boolean := False; Is_In_Table : Boolean := False; -- Are we processing a table? Is_Hanging : Boolean := False; -- If we are in a paragraph, -- is it a hanging paragraph? Saw_Hang_End : Boolean := False; -- If we are in a hanging paragraph, -- have we seen the end of the hanging part yet? Output_Buffer : Buffer_String; -- Output buffer to make smarter breaks. Output_Buffer_Len : Natural := 0; -- This should be empty between paragraphs. -- The idea is that the buffer is always logically -- preceeded by a space. Thus it is always OK to -- move the text in the buffer to the next line. Output_Buffer_Space_Before : Boolean := False; -- Do we need to output a space before the buffer? Output_File : Ada.Text_IO.File_Type; Output_Path : Buffer_String; Output_Path_Len : Natural := 0; File_Prefix : Prefix_String; -- Blank padded. Char_Count : Natural := 0; -- Characters on current line. Out_Char_Count : Natural := 0; -- Characters output on current line. Indent_Amount : Natural := 0; -- Amount to indent paragraphs. Para_Style : ARM_Output.Paragraph_Style_Type := ARM_Output.Normal; Para_Indent : ARM_Output.Paragraph_Indent_Type := 0; -- Specified indent. Is_Fixed_Format : Boolean; -- Is the text currently in a fixed format? (@Xcode) Is_Bold : Boolean; -- Is the text currently bold? Is_Italic : Boolean; -- Is the text current italics? Font : ARM_Output.Font_Family_Type; -- What is the current font family? Size : ARM_Output.Size_Type; -- What is the current relative size? Change : ARM_Output.Change_Type := ARM_Output.None; Location : ARM_Output.Location_Type := ARM_Output.Normal; Tab_Stops : ARM_Output.Tab_Info := ARM_Output.NO_TABS; Clause_Num : Clause_String; -- The number of the current clause Clause_Len : Natural := 0; end record; end ARM_Corr; org.adaic.arm_form/progs/arm_db.adb0000755000175200010010000003003311776511201016477 0ustar stepheNone-- with Ada.Text_IO; -- Debug. with Ada.Unchecked_Deallocation, Ada.Strings.Fixed, Ada.Characters.Handling; package body ARM_Database is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the database to store items for non-normative -- appendixes. -- -- --------------------------------------- -- Copyright 2000, 2004, 2005, 2006, 2009, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/16/00 - RLB - Created package. -- 8/28/00 - RLB - Added revision info to database. -- 10/28/04 - RLB - Added Inserted_Normal_Number change kind. -- 11/02/04 - RLB - Added Deleted_Inserted_Number change kind. -- 12/06/04 - RLB - Added Revised_Inserted_Number change kind. -- 12/14/04 - RLB - Made the hang item bigger. -- 1/19/05 - RLB - Added Added_Version. -- 10/17/05 - RLB - Fixed indexing of the Glossary. -- 10/18/06 - RLB - Added No_Deleted_Paragraph_Messages to Report. -- 11/30/09 - RLB - Made the hang item bigger again (to make room to -- handle commands like @ChgAdded). -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/20/11 - RLB - Added Initial_Version parameter. -- 3/19/12 - RLB - Added code to suppress indexing of deleted glossary items. type String_Ptr is access String; type Item is record Next : Item_List; Sort_Key : String(1 .. 50); Hang : String(1 .. 75); Hang_Len : Natural; Text : String_Ptr; Change_Kind : Paragraph_Change_Kind_Type; Version : Character; Initial_Version : Character; end record; procedure Free is new Ada.Unchecked_Deallocation (Item, Item_List); procedure Free is new Ada.Unchecked_Deallocation (String, String_Ptr); procedure Create (Database_Object : in out Database_Type) is -- Initialize a database object. begin Database_Object.Is_Valid := True; Database_Object.List := null; Database_Object.Item_Count := 0; end Create; procedure Destroy (Database_Object : in out Database_Type) is -- Destroy a database object, freeing any resources used. Temp : Item_List; begin if not Database_Object.Is_Valid then raise Not_Valid_Error; end if; while Database_Object.List /= null loop Temp := Database_Object.List; Database_Object.List := Temp.Next; Free (Temp.Text); Free (Temp); end loop; Database_Object.Is_Valid := False; end Destroy; procedure Insert (Database_Object : in out Database_Type; Sort_Key : in String; Hang_Item : in String; Text : in String; Change_Kind : in Paragraph_Change_Kind_Type := ARM_Database.None; Version : in Character := '0'; Initial_Version : in Character := '0') is -- Insert an item into the database object. -- Sort_Key is the string on which this item will be sorted (if it -- is sorted). Hang_Item is the item which hangs out for the item -- in the report (if any). Text is the text for the item; the text -- may include formatting codes. Change_Kind and Version are the -- revision status for this item. Initial_Version is the version of -- the initial text for this item. Temp_Item : Item; begin if not Database_Object.Is_Valid then raise Not_Valid_Error; end if; Ada.Strings.Fixed.Move (Target => Temp_Item.Sort_Key, Source => Ada.Characters.Handling.To_Lower(Sort_Key), Drop => Ada.Strings.Right, Pad => ' '); Ada.Strings.Fixed.Move (Target => Temp_Item.Hang, Source => Hang_Item, Drop => Ada.Strings.Error, Pad => ' '); Temp_Item.Hang_Len := Hang_Item'Length; -- Note: If this second item doesn't fit, we error so we can make -- the size larger. Temp_Item.Text := new String'(Text); Temp_Item.Change_Kind := Change_Kind; Temp_Item.Version := Version; Temp_Item.Initial_Version := Initial_Version; Temp_Item.Next := Database_Object.List; Database_Object.List := new Item'(Temp_Item); Database_Object.Item_Count := Database_Object.Item_Count + 1; end Insert; --generic -- with procedure Format_Text (Text : in String; -- Text_Name : in String); procedure Report (Database_Object : in out Database_Type; In_Format : in Format_Type; Sorted : in Boolean; Added_Version : Character := '0'; No_Deleted_Paragraph_Messages : in Boolean := False) is -- Output the items with the appropriate format to the -- "Format_Text" routine. "Format_Text" allows all commands -- for the full formatter. (Text_Name is an identifying name -- for error messages). This is an added list for Added_Version -- ('0' meaning it is not added); in that case, use normal numbers -- for items with a version less than or equal to Added_Version. -- (This is intended to be used to output the items to -- appropriate Format and Output objects; but we can't do that -- directly because that would make this unit recursive with -- ARM_Format. -- No paragraphs will be have deleted paragraph messages if -- No_Deleted_Paragraph_Messages is True. Temp : Item_List; function Change_if_Needed (Item : in Item_List) return String is begin -- Note: In the report, we always decide inserted/not inserted -- as determined by the initial version number, and not the -- original class. case Item.Change_Kind is when None => return ""; when Inserted | Inserted_Normal_Number => if Item.Initial_Version <= Added_Version then return "@ChgRef{Version=[" & Item.Version & "],Kind=[AddedNormal]}"; else return "@ChgRef{Version=[" & Item.Version & "],Kind=[Added]}"; end if; when Revised | Revised_Inserted_Number => if Item.Initial_Version <= Added_Version then return "@ChgRef{Version=[" & Item.Version & "],Kind=[Revised]}"; else return "@ChgRef{Version=[" & Item.Version & "],Kind=[RevisedAdded]}"; end if; when Deleted | Deleted_Inserted_Number => if Item.Initial_Version <= Added_Version then if No_Deleted_Paragraph_Messages then return "@ChgRef{Version=[" & Item.Version & "],Kind=[DeletedNoDelMsg]}"; else return "@ChgRef{Version=[" & Item.Version & "],Kind=[Deleted]}"; end if; else if No_Deleted_Paragraph_Messages then return "@ChgRef{Version=[" & Item.Version & "],Kind=[DeletedAddedNoDelMsg]}"; else return "@ChgRef{Version=[" & Item.Version & "],Kind=[DeletedAdded]}"; end if; end if; when Deleted_No_Delete_Message | Deleted_Inserted_Number_No_Delete_Message => if Item.Initial_Version <= Added_Version then return "@ChgRef{Version=[" & Item.Version & "],Kind=[DeletedNoDelMsg]}"; else return "@ChgRef{Version=[" & Item.Version & "],Kind=[DeletedAddedNoDelMsg]}"; end if; end case; end Change_if_Needed; begin if not Database_Object.Is_Valid then raise Not_Valid_Error; end if; if Sorted then declare Items : array (1..Database_Object.Item_Count) of Item_List; begin -- Load the items: Temp := Database_Object.List; for I in Items'range loop Items(I) := Temp; Temp := Temp.Next; end loop; -- Sort the items array (use an insertion sort because it is -- stable): declare Left : Natural; -- Left sorting stop begin for Right In Items'First+1 .. Items'Last loop -- Right sorting stop Temp := Items(Right); Left := Right - 1; while Temp.Sort_Key <= Items(Left).Sort_Key loop -- Switch items Items(Left + 1) := Items(Left); Left := Left - 1; exit when Left = 0; end loop; Items(Left + 1) := Temp; end loop; end; -- Relink the items in the sorted order: for I in Items'First .. Items'Last - 1 loop Items(I).Next := Items(I+1); end loop; if Items'Length > 0 then Items(Items'Last).Next := null; Database_Object.List := Items(1); else Database_Object.List := null; end if; end; end if; case In_Format is when Hanging_List => Format_Text ("@begin(description)" & Ascii.LF, "Prefix"); Temp := Database_Object.List; while Temp /= null loop --Ada.Text_IO.Put_Line ("^^ " & Paragraph_Change_Kind_Type'Image(Temp.Change_Kind) & -- " for " & Temp.Hang(1..Temp.Hang_Len) & " ref=" & Change_if_Needed (Temp)); --Ada.Text_IO.Put_Line (" " & Change_if_Needed (Temp) & --Temp.Hang(1..Temp.Hang_Len) & "@\" & --Temp.Text.all & Ascii.LF & Ascii.LF); Format_Text (Change_if_Needed (Temp) & Temp.Hang(1..Temp.Hang_Len) & "@\" & Temp.Text.all & Ascii.LF & Ascii.LF, Temp.Sort_Key); Temp := Temp.Next; end loop; Format_Text ("@end(description)" & Ascii.LF, "Suffix"); when Bullet_List => Format_Text ("@begin(itemize)" & Ascii.LF, "Prefix"); Temp := Database_Object.List; while Temp /= null loop Format_Text (Change_if_Needed (Temp) & Temp.Text.all & Ascii.LF & Ascii.LF, Temp.Sort_Key); Temp := Temp.Next; end loop; Format_Text ("@end(itemize)" & Ascii.LF, "Suffix"); when Normal_List => Format_Text ("@begin(intro)" & Ascii.LF, "Prefix"); Temp := Database_Object.List; while Temp /= null loop Format_Text (Change_if_Needed (Temp) & Temp.Text.all & Ascii.LF & Ascii.LF, Temp.Sort_Key); Temp := Temp.Next; end loop; Format_Text ("@end(intro)" & Ascii.LF, "Suffix"); when Normal_Indexed_List => Format_Text ("@begin(intro)" & Ascii.LF, "Prefix"); Temp := Database_Object.List; while Temp /= null loop case Temp.Change_Kind is when None | Inserted | Inserted_Normal_Number | Revised | Revised_Inserted_Number => --** Debug: --Ada.Text_IO.Put_Line("Format " & Change_if_Needed (Temp) & -- "@defn{" & Ada.Strings.Fixed.Trim (Temp.Sort_Key, Ada.Strings.Right) & "}" & Ascii.LF & -- Temp.Text.all); -- Index this item. Format_Text (Change_if_Needed (Temp) & "@defn{" & Ada.Strings.Fixed.Trim (Temp.Sort_Key, Ada.Strings.Right) & "}" & Ascii.LF & Temp.Text.all & Ascii.LF & Ascii.LF, Temp.Sort_Key); when Deleted | Deleted_Inserted_Number | Deleted_No_Delete_Message | Deleted_Inserted_Number_No_Delete_Message => --** Debug: --Ada.Text_IO.Put_Line("Format " & Change_if_Needed (Temp) & Ascii.LF & -- Temp.Text.all); -- Don't index deleted items. Format_Text (Change_if_Needed (Temp) & Ascii.LF & Temp.Text.all & Ascii.LF & Ascii.LF, Temp.Sort_Key); end case; Temp := Temp.Next; end loop; Format_Text ("@end(intro)" & Ascii.LF, "Suffix"); end case; end Report; end ARM_Database; org.adaic.arm_form/progs/arm_db.ads0000755000175200010010000001156311776511201016527 0ustar stepheNonepackage ARM_Database is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the database to store items for non-normative -- appendixes. -- -- --------------------------------------- -- Copyright 2000, 2004, 2005, 2006, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/16/00 - RLB - Created package. -- 8/10/00 - RLB - Added Normal_Indexed_List to fix glossary problems. -- 8/28/00 - RLB - Added revision info to database. -- 10/28/04 - RLB - Added Inserted_Normal_Number change kind. -- 11/02/04 - RLB - Added Deleted_Inserted_Number change kind. -- 12/06/04 - RLB - Added Revised_Inserted_Number change kind. -- 1/19/05 - RLB - Added Added_Version. -- 2/15/06 - RLB - Added Deleted_No_Delete_Message and -- Deleted_Inserted_Number_No_Delete_Message change kinds. -- 10/18/06 - RLB - Added No_Deleted_Paragraph_Messages to Report. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/20/11 - RLB - Added Initial_Version parameter. type Database_Type is tagged limited private; type Paragraph_Change_Kind_Type is (None, Inserted, Inserted_Normal_Number, Deleted, Deleted_Inserted_Number, Deleted_No_Delete_Message, Deleted_Inserted_Number_No_Delete_Message, Revised, Revised_Inserted_Number); Not_Valid_Error : exception; procedure Create (Database_Object : in out Database_Type); -- Initialize a database object. procedure Destroy (Database_Object : in out Database_Type); -- Destroy a database object, freeing any resources used. procedure Insert (Database_Object : in out Database_Type; Sort_Key : in String; Hang_Item : in String; Text : in String; Change_Kind : in Paragraph_Change_Kind_Type := ARM_Database.None; Version : in Character := '0'; Initial_Version : in Character := '0'); -- Insert an item into the database object. -- Sort_Key is the string on which this item will be sorted (if it -- is sorted). Hang_Item is the item which hangs out for the item -- in the report (if any). Text is the text for the item; the text -- may include formatting codes. Change_Kind and Version are the -- revision status for this item. Initial_Version is the version of -- the initial text for this item. type Format_Type is (Normal_List, Normal_Indexed_List, Bullet_List, Hanging_List); generic with procedure Format_Text (Text : in String; Text_Name : in String); procedure Report (Database_Object : in out Database_Type; In_Format : in Format_Type; Sorted : in Boolean; Added_Version : Character := '0'; No_Deleted_Paragraph_Messages : in Boolean := False); -- Output the items with the appropriate format to the -- "Format_Text" routine. "Format_Text" allows all commands -- for the full formatter. (Text_Name is an identifying name -- for error messages). This is an added list for Added_Version -- ('0' meaning it is not added); in that case, use normal numbers -- for items with a version less than or equal to Added_Version. -- (This is intended to be used to output the items to -- appropriate Format and Output objects; but we can't do that -- directly because that would make this unit recursive with -- ARM_Format. -- No paragraphs will be have deleted paragraph messages if -- No_Deleted_Paragraph_Messages is True. private type Item; type Item_List is access all Item; type Database_Type is tagged limited record Is_Valid : Boolean := False; List : Item_List; Item_Count : Natural; end record; end ARM_Database; org.adaic.arm_form/progs/arm_file.adb0000755000175200010010000001642711776511201017044 0ustar stepheNone--with ARM_Input, -- Ada.Text_IO; package body ARM_File is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the definition of reading an input file. -- -- --------------------------------------- -- Copyright 2000, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53704 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/15/00 - RLB - Created package. -- 10/18/11 - RLB - Changed to GPLv3 license. procedure Open (Input_Object : in out File_Input_Type; File_Name : in String) is -- Open an input object for a file. -- This may propagate file exceptions. begin Ada.Text_IO.Open (Input_Object.Fyle, Ada.Text_IO.In_File, File_Name); Input_Object.Line_Counter := 0; Input_Object.Buffer_Last := 0; Input_Object.Buffer_Index := 0; Input_Object.Is_Valid := True; if File_Name'Length > Input_Object.Name'Length then Input_Object.Name := File_Name(File_Name'First .. File_Name'First + Input_Object.Name'Length - 1); Input_Object.Name_Len := Input_Object.Name'Length; else Input_Object.Name(1..File_Name'Length) := File_Name; Input_Object.Name_Len := File_Name'Length; end if; end Open; procedure Close (Input_Object : in out File_Input_Type) is -- Close the input object (entity). -- May propagate exceptions from the underlying implementation -- (that is, I/O exceptions). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; Input_Object.Is_Valid := False; Ada.Text_IO.Close (Input_Object.Fyle); end Close; procedure Get_Char (Input_Object : in out File_Input_Type; Char : out Character) is -- We represent end of line by Ascii.LF. -- Raises: End_Error when the end of file is reached. -- Not_Valid_Error if Input_Object is not valid (open). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; if Input_Object.Buffer_Index >= Input_Object.Buffer_Last then begin Ada.Text_IO.Get_Line (Input_Object.Fyle, Input_Object.Buffer, Input_Object.Buffer_Last); -- Raises End_Error when the end of the file is reached. exception when Ada.Text_IO.End_Error => -- Set so we can do a Replace_Char on this. Input_Object.Buffer_Index := 1; Input_Object.Buffer_Last := 1; Input_Object.Buffer(1) := Ascii.SUB; -- File end marker. Char := Ascii.SUB; return; end; if Input_Object.Buffer_Last < Input_Object.Buffer'Last then Input_Object.Buffer_Last := Input_Object.Buffer_Last + 1; Input_Object.Buffer(Input_Object.Buffer_Last) := Ascii.LF; -- Line end marker. -- else broken line, no end needed. end if; --Ada.Text_IO.Put(Natural'Image(Input_Object.Line_Counter) & ":"); --Ada.Text_IO.Put_Line ("&& " & Input_Object.Buffer(1..Input_Object.Buffer_Last)); Input_Object.Buffer_Index := 0; Input_Object.Line_Counter := Input_Object.Line_Counter + 1; end if; Input_Object.Buffer_Index := Input_Object.Buffer_Index + 1; if Input_Object.Recording then Input_Object.Recording_Len := Input_Object.Recording_Len + 1; Input_Object.Recording_Buffer(Input_Object.Recording_Len) := Input_Object.Buffer(Input_Object.Buffer_Index); end if; Char := Input_Object.Buffer(Input_Object.Buffer_Index); end Get_Char; procedure Replace_Char (Input_Object : in out File_Input_Type) is -- Replaces the last character read (with Get_Char); the next call -- to Get_Char will return it. -- Raises: Not_Valid_Error if Input_Object is not valid (open). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; if Input_Object.Buffer_Index = 0 then raise Program_Error; -- Called twice or before any calls to Get_Char. end if; Input_Object.Buffer_Index := Input_Object.Buffer_Index - 1; if Input_Object.Recording then Input_Object.Recording_Len := Input_Object.Recording_Len - 1; end if; end Replace_Char; function Line_String (Input_Object : in File_Input_Type) return String is -- Returns a string representing the line number and entity. -- Usually used in error messages. -- Raises: Not_Valid_Error if Input_Object is not valid (open). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; return Natural'Image(Input_Object.Line_Counter) & " - " & Input_Object.Name(1..Input_Object.Name_Len); end Line_String; procedure Start_Recording (Input_Object : in out File_Input_Type) is -- Start recording all characters read into a local buffer. -- Use this when text needs to be formatted into the output -- file *and* be saved for future use. -- Raises: Not_Valid_Error if Input_Object is not valid (open). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; Input_Object.Recording := True; Input_Object.Recording_Len := 0; end Start_Recording; procedure Stop_Recording_and_Read_Result (Input_Object : in out File_Input_Type; Result : out String; Len : out Natural) is -- Stop recording characters read. Put the result into Result, -- and the number of characters written into Len. -- Raises: Not_Valid_Error if Input_Object is not valid (open). begin if not Input_Object.Is_Valid then raise ARM_Input.Not_Valid_Error; end if; if Input_Object.Recording_Len > Result'Length then Ada.Text_IO.Put_Line (" ** Too many characters recorded on line " & Line_String (Input_Object)); Len := 0; else Result (Result'First .. Result'First + Input_Object.Recording_Len - 1) := Input_Object.Recording_Buffer (1 .. Input_Object.Recording_Len); Len := Input_Object.Recording_Len; end if; Input_Object.Recording := False; end Stop_Recording_and_Read_Result; end ARM_File; org.adaic.arm_form/progs/arm_file.ads0000755000175200010010000001001411776511201017047 0ustar stepheNonewith ARM_Input, Ada.Text_IO; package ARM_File is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the definition of reading an input file. -- -- --------------------------------------- -- Copyright 2000, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53704 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/15/00 - RLB - Created package. -- 10/18/11 - RLB - Changed to GPLv3 license. type File_Input_Type is new ARM_Input.Input_Type with private; procedure Open (Input_Object : in out File_Input_Type; File_Name : in String); -- Open an input object for a file. -- This may propagate file exceptions. procedure Close (Input_Object : in out File_Input_Type); -- Close the input object (entity). -- May propagate exceptions from the underlying implementation -- (that is, I/O exceptions). procedure Get_Char (Input_Object : in out File_Input_Type; Char : out Character); -- We represent end of line by Ascii.LF. -- Raises: End_Error when the end of file is reached. -- Not_Valid_Error if Input_Object is not valid (open). procedure Replace_Char (Input_Object : in out File_Input_Type); -- Replaces the last character read (with Get_Char); the next call -- to Get_Char will return it. -- Raises: Not_Valid_Error if Input_Object is not valid (open). function Line_String (Input_Object : in File_Input_Type) return String; -- Returns a string representing the line number and entity. -- Usually used in error messages. -- Raises: Not_Valid_Error if Input_Object is not valid (open). procedure Start_Recording (Input_Object : in out File_Input_Type); -- Start recording all characters read into a local buffer. -- Use this when text needs to be formatted into the output -- file *and* be saved for future use. -- Raises: Not_Valid_Error if Input_Object is not valid (open). procedure Stop_Recording_and_Read_Result (Input_Object : in out File_Input_Type; Result : out String; Len : out Natural); -- Stop recording characters read. Put the result into Result, -- and the number of characters written into Len. -- Raises: Not_Valid_Error if Input_Object is not valid (open). private type File_Input_Type is new ARM_Input.Input_Type with record Is_Valid : Boolean := False; Fyle : Ada.Text_IO.File_Type; Line_Counter : Natural := 0; Buffer : String(1..250); Buffer_Last : Natural := 0; Buffer_Index : Natural := 0; -- Last character read from buffer. -- For recording: Recording : Boolean := False; Recording_Buffer : String(1..ARM_Input.MAX_RECORDING_SIZE); Recording_Len : Natural := 0; -- Name: Name : String(1..120); Name_Len : Natural; end record; end ARM_File; org.adaic.arm_form/progs/arm_form.ada0000755000175200010010000003101712273462240017060 0ustar stepheNonewith Ada.Text_IO, Ada.Strings.Fixed, Ada.Strings.Unbounded, Ada.Characters.Handling, Ada.Command_Line; with ARM_Master, ARM_Contents, ARM_Format; procedure ARM_Formatter is -- -- Ada reference manual formatter (ARM_Form). -- -- This is the main subprogram: format the sources for the -- Ada reference manual and other documents -- (in a vaguely Scribe-like macro language) into the actual -- reference manual files (in various formats). -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2006, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 3/ 9/00 - RLB - Created base program. -- 4/14/00 - RLB - Created from analysis program. -- 4/18/00 - RLB - Added scanning pass. -- 4/19/00 - RLB - Split 03 into two files. Added HTML output object. -- 4/24/00 - RLB - Added Change_Kind and Display_Index_Entries. -- 5/15/00 - RLB - Split formatter from input. -- 5/16/00 - RLB - Added missing Destroy for formatting objects. -- 5/18/00 - RLB - Added RTF output object. -- 5/25/00 - RLB - Added the Big-Files option. Added the library separator. -- 5/28/00 - RLB - Added index. -- 8/31/00 - RLB - Added the New-Changes option. -- 7/18/02 - RLB - Changed copyright date. -- - RLB - Changed Creates to include title and header. -- - RLB - Added Version parameter to command line and formatting -- commands. -- 9/10/04 - RLB - Updated descriptions of standard commands. -- 9/14/04 - RLB - Moved version to ARM_Contents. -- 12/05/04 - RLB - Split/added various source files. -- 6/ 2/05 - RLB - Added Corrigendum output module for comparisons to -- Amendment document. -- 10/12/05 - RLB - Changed the title to reflect what we learned from ISO. -- 10/28/05 - RLB - Added Annex Q. -- 1/ 5/06 - RLB - Revised to use master files, rather than hard-coded -- properties. -- 1/12/06 - RLB - Removed Document completely. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Removed junk withs (now in master file handler). -- 4/ 3/12 - RLB - Removed dead variable. -- 8/31/12 - RLB - Added output path parameter. -- Standard commands for Ada standards: -- For Original (Ada 95) RM: -- Arm_Form RM No-Changes 0 -- For Original AARM: -- Arm_Form AARM No-Changes 0 -- For RM with Corr: -- [With change bars for Word 97/2000:] -- Arm_Form RM RTF New-Changes 1 -- [Final versions with no changes:] -- Arm_Form RM New-Only 1 -- For AARM with Corr: -- [HTML; RTF for display]: -- Arm_Form AARM Show-Changes 1 -- [TXT; RTF for printing]: -- Arm_Form AARM New-Only 1 -- For RM with Corr and Amd: -- [With change bars for Word 97/2000:] -- Arm_Form RM RTF New-Changes 2 -- [With change ballons for Word XP/2003:] -- Arm_Form RM RTF Show-Changes 2 -- [Final versions with no changes:] -- Arm_Form RM New-Only 2 -- For AARM with Corr and Amd: -- [HTML; RTF for display]: -- Arm_Form AARM Changes-Only 2 -- (for only Amd changes) or -- Arm_Form AARM Show-Changes 2 -- (for all changes) -- [TXT; RTF for printing]: -- Arm_Form AARM New-Only 2 -- For Ada 2012 RM: -- [With change ballons for Word XP/2003:] -- Arm_Form RM RTF Show-Changes 3 -- [For change bar version for Word 97/2000:] -- Arm_Form RM RTF Changes-Only 3 -- [Final versions with no changes:] -- Arm_Form RM New-Only 3 -- For AARM with Corr and Amd: -- [HTML; RTF for display]: -- Arm_Form AARM Changes-Only 3 -- (for only Amda 2012 changes) or -- Arm_Form AARM Show-Changes 3 -- (for all changes) -- [TXT; RTF for printing]: -- Arm_Form AARM New-Only 3 No_Command_Error : exception; Format : ARM_Master.Output_Format_Type; -- Format to generate. Master_File : Ada.Strings.Unbounded.Unbounded_String; -- Master file for document to generate. Change_Kind : ARM_Format.Change_Kind; -- Changes to generate. Change_Version : ARM_Contents.Change_Version_Type; -- Change version. Output_Path : Ada.Strings.Unbounded.Unbounded_String; -- Output path. procedure Get_Commands is -- Process the command line for this program. begin if Ada.Command_Line.Argument_Count not in 1 .. 5 then Ada.Text_IO.Put_Line ("** Wrong number of arguments"); raise No_Command_Error; end if; if Ada.Command_Line.Argument_Count >= 5 then Output_Path := Ada.Strings.Unbounded.To_Unbounded_String( Ada.Strings.Fixed.Trim (Ada.Command_Line.Argument(5), Ada.Strings.Right)); -- Check that the Output_Path ends with a path separator. -- Note: This is a simple Windows check; it doesn't check for and -- allow bare disk names. This check works on Linux but allows -- ending with '\' which does not work on Linux (that will be -- failed when the files are opened). declare Last : constant Character := Ada.Strings.Unbounded.Element (Ada.Strings.Unbounded.Tail (Output_Path, 1), 1); begin if Last = '/' or else Last = '\' then null; -- OK; this ends with a path separator. else Ada.Text_IO.Put_Line ("** Output path does not end with a path separator: " & Ada.Strings.Unbounded.To_String (Output_Path)); raise No_Command_Error; end if; end; else Output_Path := Ada.Strings.Unbounded.To_Unbounded_String ("./output/"); -- Use '/' so this works on Linux and Windows. end if; if Ada.Command_Line.Argument_Count >= 4 then declare Version_Arg : String := Ada.Characters.Handling.To_Lower ( Ada.Strings.Fixed.Trim (Ada.Command_Line.Argument(4), Ada.Strings.Right)); begin if Version_Arg'Length = 1 and then Version_Arg(Version_Arg'First) in ARM_Contents.Change_Version_Type then Change_Version := Version_Arg(Version_Arg'First); else Ada.Text_IO.Put_Line ("** Unrecognized change version: " & Version_Arg); raise No_Command_Error; end if; end; else Change_Version := '0'; end if; if Ada.Command_Line.Argument_Count >= 3 then declare Changes_Arg : String := Ada.Characters.Handling.To_Lower ( Ada.Strings.Fixed.Trim (Ada.Command_Line.Argument(3), Ada.Strings.Right)); begin if Changes_Arg = "no-changes" then Change_Kind := ARM_Format.Old_Only; elsif Changes_Arg = "new-only" then Change_Kind := ARM_Format.New_Only; elsif Changes_Arg = "changes-only" then Change_Kind := ARM_Format.Changes_Only; elsif Changes_Arg = "show-changes" then Change_Kind := ARM_Format.Show_Changes; elsif Changes_Arg = "new-changes" then Change_Kind := ARM_Format.New_Changes; else Ada.Text_IO.Put_Line ("** Unrecognized changes: " & Changes_Arg); raise No_Command_Error; end if; end; else Change_Kind := ARM_Format.New_Only; end if; if Ada.Command_Line.Argument_Count >= 2 then declare Format_Arg : String := Ada.Characters.Handling.To_Lower ( Ada.Strings.Fixed.Trim (Ada.Command_Line.Argument(2), Ada.Strings.Right)); begin if Format_Arg = "rtf" then Format := ARM_Master.RTF; elsif Format_Arg = "html" then Format := ARM_Master.HTML; elsif Format_Arg = "text" then Format := ARM_Master.Text; elsif Format_Arg = "corr" then Format := ARM_Master.Corr; elsif Format_Arg = "info" then Format := ARM_Master.Info; else Ada.Text_IO.Put_Line ("** Unrecognized format: " & Format_Arg); raise No_Command_Error; end if; end; else Format := ARM_Master.HTML; end if; declare use type Ada.Strings.Unbounded.Unbounded_String; begin Master_File := Ada.Strings.Unbounded.To_Unbounded_String (Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Ada.Command_Line.Argument(1), Ada.Strings.Right))); if Ada.Strings.Unbounded.Index (Master_File, ".") = 0 then -- Add extension if it is missing. Master_File := Master_File & ".msm"; end if; end; exception when No_Command_Error => Ada.Text_IO.Put_Line (" Usage: Arm_Form [[ [ [ ]]]]}"); Ada.Text_IO.Put_Line (" where: is the file name (and optional path) for the master file"); Ada.Text_IO.Put_Line (" for the document;"); Ada.Text_IO.Put_Line (" where: = 'Text' (text files),"); Ada.Text_IO.Put_Line (" 'HTML' (HTML files),"); Ada.Text_IO.Put_Line (" 'RTF' (RTF files for Word 97 or later),"); Ada.Text_IO.Put_Line (" 'Corr' (Corrigendum-style command files for comparisons);"); Ada.Text_IO.Put_Line (" where: = 'No-Changes' (RM text),"); Ada.Text_IO.Put_Line (" 'New-Only' (Revised RM text only for ),"); Ada.Text_IO.Put_Line (" 'Changes-Only' (Text with changes marked for only),"); Ada.Text_IO.Put_Line (" 'Show-Changes' (Text with changes marked for and earlier),"); Ada.Text_IO.Put_Line (" 'New-Changes' (Text with insertions marked for and earlier);"); Ada.Text_IO.Put_Line (" where: = a value in 0 .. 9 representing the change version"); Ada.Text_IO.Put_Line (" 0-Original Ada 95 (equivalent to No-Changes)"); Ada.Text_IO.Put_Line (" 1-Technical Corrigendum 1"); Ada.Text_IO.Put_Line (" 2-Amendment 1"); Ada.Text_IO.Put_Line (" where: = it the path where to write the result files. This must"); Ada.Text_IO.Put_Line (" end with a path separator. It defaults to ./output/"); raise No_Command_Error; end Get_Commands; begin Ada.Text_IO.Put_Line ("Ada Manual formatter"); Ada.Text_IO.Put_Line (" Copyright 2000, 2002, 2004, 2005, 2006, 2011, 2012 AXE Consultants"); Ada.Text_IO.Put_Line (" P.O. Box 1512, Madison WI 53701"); Get_Commands; Ada.Text_IO.Put_Line (" Master File = " & Ada.Strings.Unbounded.To_String(Master_File)); Ada.Text_IO.Put_Line (" Format = " & ARM_Master.Output_Format_Type'Image(Format)); Ada.Text_IO.Put_Line (" Changes = " & ARM_Format.Change_Kind'Image(Change_Kind)); Ada.Text_IO.Put_Line (" Version = " & Change_Version); ARM_Master.Read_and_Process_Master_File ( File_Name => Ada.Strings.Unbounded.To_String(Master_File), The_Change_Kind => Change_Kind, The_Change_Version => Change_Version, Output_Format => Format, Output_Path => Ada.Strings.Unbounded.To_String(Output_Path)); Ada.Text_IO.Put_Line ("Ada document created"); exception when No_Command_Error => null; -- Error message displayed by command line processor. end ARM_Formatter; org.adaic.arm_form/progs/arm_frm.adb0000755000175200010010000170173312273462240016714 0ustar stepheNonewith -- ARM_Output, -- redudant with spec -- ARM_Input, ARM_File, ARM_String, -- ARM_Contents, -- ARM_Database, ARM_Syntax, ARM_Index, -- ARM_Subindex, ARM_Format.Data, Ada.Text_IO, Ada.Characters.Handling, Ada.Strings.Fixed; package body ARM_Format is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to parse the input files, and -- determine what to output. -- -- --------------------------------------- -- Copyright 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, -- 2010, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/14/00 - RLB - Created base package. -- 4/17/00 - RLB - Starting implementation of commands. -- 4/19/00 - RLB - Implemented contents package and section references. -- 4/21/00 - RLB - Added hard_space and line_break output routines. -- 4/24/00 - RLB - Added Change_Kind and Display_Index_Entries. -- - RLB - Added Change and ChgRef. -- 4/26/00 - RLB - Added paragraph commands and formats. -- 4/29/00 - RLB - Loose ends: "Part", fixes for the example format, -- "DescribeCode" and "Itemize". -- 5/10/00 - RLB - Added missing "MetricsName" and "MetricsTitle". -- Added additional paragraph format kinds. -- 5/11/00 - RLB - Implemented numbers on enumerated paragraphs. -- 5/12/00 - RLB - Added NoPrefix. -- - RLB - Added attribute commands. -- 5/13/00 - RLB - Added various character macros. -- 5/15/00 - RLB - Split input from parsing/formatting. -- 5/16/00 - RLB - Added database objects and Destroy. -- - RLB - Implemented pragma commands. -- 5/17/00 - RLB - Implemented syntax commands. -- 5/19/00 - RLB - Added hinge analysis. -- 5/23/00 - RLB - Added column commands. -- - RLB - Added tab commands. -- 5/24/00 - RLB - Implemented subscript/superscript commands. -- 5/25/00 - RLB - Added more formatting commands and styles. -- 5/26/00 - RLB - Removed hinge analysis, other junk. -- 5/28/00 - RLB - Implemented index operations. -- 6/ 2/00 - RLB - Implemented @|. -- - RLB - Added AdaDefn and AdaSubDefn commands, and unit saving. -- 8/ 2/00 - RLB - Implemented @! (as @| doesn't work); implemented -- lquote, etc. -- 8/ 4/00 - RLB - Added additional styles. -- 8/ 8/00 - RLB - Added Attribute_Leading. -- 8/11/00 - RLB - Fixed glossary report. -- - RLB - Added Hanging_in_Bulleted low-level style. -- 8/15/00 - RLB - Replaced "LangDefType" with "AdaTypeDefn" (much smaller). -- 8/16/00 - RLB - Added double nesting support for InnerItemize. -- - RLB - Added "noparanum" command; removed no paranum formats. -- 8/17/00 - RLB - Changed Leading flag to Space_After, added Trailing command. -- - RLB - Added Nested_Enumerated styles. -- 8/18/00 - RLB - Fixed a variety of errors in the AARM paragraph numbering. -- - RLB - Fixed Display_Index_Entry so it would work right when -- given in an insertion or deletion. -- 8/21/00 - RLB - Fixed so send and later references in a ChgReg command -- don't accidentally include all preceding ones. -- 8/22/00 - RLB - Added Labeled_Revised_Clause and -- Labeled_Revised_Subclause commands. -- 8/23/00 - RLB - Fixed Syntax_Rules to allow @Chg commands in the -- LHS. -- - RLB - Fixed error in display of Defn2 index entries. -- 8/28/00 - RLB - Added implementation-defined changes command. -- 8/30/00 - RLB - Adjusted code in index entries to match old AARM. -- - RLB - Made the deleted paragraph text appear in all new -- versions. -- - RLB - Added AddedSubheading. -- 8/31/00 - RLB - Added the New_Changes change kind. -- - RLB - Added RM_New_Page command. -- 9/ 1/00 - RLB - Fixed bugs that prevented "deleted paragraph" messages -- from appearing and caused junk headers to appear for -- sections not appearing in the old document. -- 9/ 8/00 - RLB - Added information about the language-defined -- subprograms to the index introduction. -- 9/26/00 - RLB - Added Syntax_Display format. -- 9/28/00 - RLB - Added RefSecbyNum command. -- 10/30/00 - RLB - Added ISOOnly paragraph grouping. -- - RLB - Fixed inserted paragraph numbers to support more than 9. -- 6/17/02 - RLB - Added Ada95 changes sections. -- 7/18/02 - RLB - Moved document type here. -- - RLB - Added ARef= parameter to ChgRef. -- - RLB - Added Changes_Only and versioning for individual changes. -- 4/10/03 - RLB - Fixed Index_Pragma to include " pragma". -- 4/11/03 - RLB - Fixed order of removal for formatting for Heading and -- Subheading, so that the nesting is right (it needs to -- be exactly like the order of application). -- - RLB - Fixed code so that parameter version numbers aren't -- displayed higher than the item we're generating. -- - RLB - Fixed ChgRef and others not to generate anything if -- we're not generating the version that the reference is -- for. Similarly, avoid changing the paragraph kind if -- we're not going to use the changes. -- - RLB - Fixed font for changing non-terminals in @Syn. -- 9/09/04 - RLB - Removed unused junk noticed by Stephen Leake. -- 9/10/04 - RLB - Added Version to many Text_Format commands. -- - RLB - Fixed Get_NT to allow the Version parameter in @Chg. -- - RLB - Updated to allow @Chg nesting. -- 9/14/04 - RLB - Moved Change_Version_Type to ARM_Contents. -- - RLB - Added version number parameters to revised header -- commands; added additional header commands. -- - RLB - Added code so that section references in Annex L and M -- are links. -- 9/15/04 - RLB - Fixed incorrect name for LabeledAddedSubClause command. -- - RLB - Fixed to lift limit on number of inserted paragraphs. -- 10/28/04 - RLB - Replaced double single quotes with double quotes, -- as directed by the ARG. -- - RLB - Added "AddedNormal" ChgRef kind. -- 10/29/04 - RLB - Added code so that section references in Annex K are -- links. -- 11/02/04 - RLB - Added "DeletedAdded" ChgRef kind. -- 11/03/04 - RLB - Fixed @Chg nesting glitch. -- - RLB - Added InnerInnerItemize == Nested_X2_Bulleted. -- 11/04/04 - RLB - Fixed a problem that reset the insertion number for -- paragraphs have a normal AARM para. was encountered. -- 11/15/04 - RLB - Added Indented_Nested_Bulleted style. -- 12/06/04 - RLB - Added "RevisedAdded" ChgRef kind. -- - RLB - Delayed generation of references until the start of -- the paragraph. That avoids "pinning" problems, -- especially for multiple changes in a single paragraph. -- - RLB - Allow multiple Ref and ARef params in ChgAttribute. -- - RLB - Added ChgAdded and ChgDeleted for entire paragraph -- operations. -- 12/11/04 - RLB - Fixed brackets in Added_Pragma_Syntax to allow {} in -- text. -- - RLB - Implemented attribute adding in Change_Attribute. -- 12/13/04 - RLB - Fixed problems in the new change commands. -- 12/15/04 - RLB - Fixed so a change is not left open across -- an End_Hang_Item. -- - RLB - Fixed glitches with deleted paragraphs. -- 1/19/05 - RLB - Added LabeledRevisedInformativeAnnex. -- - RLB - Fixed AARM paragraph numbers to allow more than 52, -- and to put out an error message if we exceed the maximum. -- - RLB - Added ChgDocReq and ChgImplAdvice. -- - RLB - Added AddedDocReqList and AddedImplAdviceList. -- 1/20/05 - RLB - Added debugging for stack overflows. -- 1/24/05 - RLB - Added Inner_Indented. -- 1/25/05 - RLB - Added AddedSyn and DeleteSyn commands. -- 2/ 1/05 - RLB - Added Turkish Is. -- 2/ 2/05 - RLB - Corrected so normal AARM numbers don't reset the -- RM insertion number. -- 3/15/05 - RLB - Corrected spelling. -- 5/27/05 - RLB - Added @Unicode command for examples. -- 8/ 9/05 - RLB - Changed the capitalization of some AARM note headers. -- 10/17/05 - RLB - Added Glossary change commands. -- 10/28/05 - RLB - Made index changes for Ada 200Y. -- - RLB - Added added Annex headers. -- - RLB - Added Language-Defined Entity indexes. -- 10/31/05 - RLB - Fixed the "this paragraph was deleted" code to -- not change the version; it's not necessarily -- initialized, and the Kind isn't set anyway if the -- version is too new. -- 1/ 5/06 - RLB - Corrected a comment. -- 1/12/06 - RLB - Replaced "Document" with a number of new more general -- properties. -- 1/13/06 - RLB - Added various link commands. -- 1/16/06 - RLB - Added missing initializations. -- - RLB - Added IndexList command. -- - RLB - Added Unnumbered_Section counter to ensure that -- such sections are uniquely named. -- 1/18/06 - RLB - Added "Example_Font". -- - RLB - Redid formatting command nesting so that closing -- restores to the initial state for the command, not the -- default state. -- 1/20/06 - RLB - Added AILink command. -- 2/ 8/06 - RLB - Added command checking at the end of each table row. -- 2/ 9/06 - RLB - Implemented enhanced Table command. -- 2/10/06 - RLB - Split scanning phase into a separate file. -- - RLB - Added additional features to the Table command. -- - RLB - Added the picture command. -- 2/15/06 - RLB - Added code to prevent the generation of note numbers -- for deleted notes in final documents. -- 2/17/06 - RLB - Tracked down issues with @ChgImplDef. -- - RLB - Added code so that index entries don't display soft -- hyphens. -- - RLB - Fixed glossary entries to not display insertions if -- the mode would prevent that. -- 6/22/06 - RLB - Added non-terminal linking. -- 8/ 4/06 - RLB - Added checking for bad unit indexing. -- 9/22/06 - RLB - Added "Use_ISO_2004_Note_Format", and implemented that -- format. -- - RLB - Revised to use Clause_Number_Type, and to support -- Subsubclauses. -- 9/25/06 - RLB - Added "Use_ISO_2004_Contents_Format". -- - RLB - Added LastColWidth to @Table. -- - RLB - Fixed Enumerated in Notes styles. -- 9/29/06 - RLB - Added Element_Ref and Child_Ref for ASIS. -- 10/04/06 - RLB - Added and implemented "Use_ISO_2004_List_Format". -- - RLB - Added "InnerEnumerate" text block. -- 10/13/06 - RLB - Added the @ntf command to handle cases where the -- text needs to look like a non-terminal but it isn't -- a real non-terminal. -- - RLB - Added code to handle simple embedded commands in -- @nt{} to generate links. -- 10/16/06 - RLB - Added code to register deleted non-terminals (so -- that they can be linked). -- 10/18/06 - RLB - Fixed so that deleted glossary items still get -- deleted paragraph numbers. -- 2/ 5/07 - RLB - Added a paragraph kind, and changed ones that -- appear in ASIS. Also renamed "Wide" to "Wide_Above" -- so the purpose is more obvious. -- 2/ 9/07 - RLB - Moved AI interpretation and folding to the HTML -- driver, as constructing the link should be its -- responsibility. This also allows new kinds of AI here. -- 2/13/07 - RLB - Redid output formating to use an explict indent; -- added ChildExample. -- 2/16/07 - RLB - Added Indent format. -- 2/19/07 - RLB - Added Title format. -- 12/18/07 - RLB - Initialized Version in some cases. -- - RLB - Added check for open formatting commands -- in Check_End_Paragraph. -- - RLB - Added Plain_Annex and associated commands. -- 12/19/07 - RLB - Added color commands. -- 6/12/08 - RLB - Corrected handling of the ChgGlossary command. -- 3/ 4/09 - RLB - Added code to suppress bullets and the like when -- displaying a deleted paragraph in New-Only mode -- and no paragraph numbers are shown. -- 5/ 6/09 - RLB - Added Labeled_Deleted_xxx. -- 5/15/09 - RLB - Fixed missing code for note numbers in revised/added clauses. -- 4/23/10 - RLB - Added Ada 2005 clause headers for Ada 2012 edition. -- 8/ 8/11 - RLB - Split various data items to reduce the size of this -- package. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added AspectDefn command. -- 10/20/11 - RLB - Added optional initial version parameter to ChgImplDef -- and related commands. -- - RLB - Added DeletedPragmaSyn command. -- 10/25/11 - RLB - Added optional initial version parameter to -- LabeledRevisedSomething commands. -- 10/26/11 - RLB - Added versioned break commands. -- 3/19/12 - RLB - Fixed bug that occurred only when paragraph numbers -- are off (ISO versions). Fixed sort order of attributes. -- 3/27/12 - RLB - Added more versioned break commands. -- 4/ 3/12 - RLB - Removed dead variables. -- 8/31/12 - RLB - Put glossary components into a subrecord to prevent -- inappropriate usage. -- 10/18/12 - RLB - Put impdef components into a subrecord to prevent -- inappropriate usage. Fixed problem caused by putting -- newer items than the generated version into the DB. -- - RLB - Added four specific indent hanging formats and -- "small" format. -- 11/ 5/12 - RLB - Added stupidly missing compare for "small" format. -- 11/26/12 - RLB - Added subdivision names. -- 7/ 5/13 - RLB - Added a nasty hack so added aspect names are marked -- as such in Show_Changes versions. type Command_Kind_Type is (Normal, Begin_Word, Parameter); use ARM_Format.Data; -- use all type ARM_Format.Data.Command_Type; -- Make the enumeration literals visible. Free_References : Reference_Ptr := null; -- Unused reference objects. -- We don't expect there ever to be many of these, so we don't try -- to deallocate them. Allocated_Reference_Count : Natural := 0; function Allocate_Reference return Reference_Ptr is -- Allocate a reference object from either the free list, or allocate -- it. T : Reference_Ptr; begin if Free_References /= null then T := Free_References; Free_References := Free_References.Next; return T; else Allocated_Reference_Count := Allocated_Reference_Count + 1; if Allocated_Reference_Count > 20 then -- Never more than this on one paragraph. Ada.Text_IO.Put_Line (" ** Too many references allocated"); end if; return new Reference; end if; end Allocate_Reference; procedure Free_Reference (Reference : in out Reference_Ptr) is -- Put a reference object on the free list; setting Reference to null. begin Reference.Next := Free_References; Free_References := Reference; Reference.Ref_Len := 0; -- Clear length, so we don't reuse by accident. Reference := null; end Free_Reference; procedure Create (Format_Object : in out Format_Type; Changes : in ARM_Format.Change_Kind; Change_Version : in ARM_Contents.Change_Version_Type; Display_Index_Entries : in Boolean; Include_Annotations : in Boolean; Include_ISO : in Boolean; Link_Non_Terminals : in Boolean; Number_Paragraphs : in Boolean; Examples_Font : in ARM_Output.Font_Family_Type; Use_ISO_2004_Note_Format : in Boolean; Use_ISO_2004_Contents_Format : in Boolean; Use_ISO_2004_List_Format : in Boolean; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind) is -- Initialize an input object. Changes and Change_Version determine -- which changes should be displayed. If Display_Index_Entries is True, -- index entries will be printed in the document; otherwise, they -- will not generate any visible text (although they might generate -- a link anchor). If Include_Annotations is True, annotations (AARM -- text) will be included in the output; otherwise it will not be. -- If Include_ISO is True, ISOOnly text will be included in the output -- (and NotISO text will not); otherwise the reverse is true. -- If Link_Non_Terminals is True, links will be generated for -- each Non_Terminal, linking it to its definition. -- If Number_Paragraphs is true, paragraphs will be numbered (per -- subclause); otherwise they will not be. -- Example_Font specifies the font that examples will be set in. -- If Use_ISO_2004_Note_Format is true, that format will be used; -- else the Ada95 standard's format will be used for notes. -- If Use_ISO_2004_Contents_Format is true, that format will be used; -- else the Ada95 standard's format will be used for the table of contents. -- If Use_ISO_2004_List_Format is true, then lists will be lettered; -- else the Ada95 standard's numbering format will be used for -- enumerated lists. -- The top-level (and other) subdivision names are as specified -- in Top_Level_Subdivision_Name. begin Format_Object.Changes := Changes; Format_Object.Change_Version := Change_Version; Format_Object.Display_Index_Entries := Display_Index_Entries; Format_Object.Include_Annotations := Include_Annotations; Format_Object.Include_ISO := Include_ISO; Format_Object.Link_Non_Terminals := Link_Non_Terminals; Format_Object.Number_Paragraphs := Number_Paragraphs; Format_Object.Examples_Font := Examples_Font; Format_Object.Use_ISO_2004_Note_Format := Use_ISO_2004_Note_Format; Format_Object.Use_ISO_2004_Contents_Format := Use_ISO_2004_Contents_Format; Format_Object.Use_ISO_2004_List_Format := Use_ISO_2004_List_Format; Format_Object.Top_Level_Subdivision_Name := Top_Level_Subdivision_Name; Format_Object.Clause_Number := (Section => 0, Clause => 0, Subclause => 0, Subsubclause => 0); Format_Object.Unnumbered_Section := 0; Format_Object.Next_Note := 1; Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; Format_Object.Next_AARM_Insert_Para := 1; Format_Object.Next_Enumerated_Num := 1; Format_Object.Enumerated_Level := 0; Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; ARM_Database.Create (Format_Object.Aspect_DB); ARM_Database.Create (Format_Object.Attr_DB); ARM_Database.Create (Format_Object.Pragma_DB); ARM_Database.Create (Format_Object.Glossary_DB); ARM_Database.Create (Format_Object.Impdef_DB); ARM_Database.Create (Format_Object.Impladv_DB); ARM_Database.Create (Format_Object.Docreq_DB); ARM_Syntax.Create; ARM_Index.Create; ARM_Subindex.Create (Format_Object.Package_Index); ARM_Subindex.Create (Format_Object.Type_Index); ARM_Subindex.Create (Format_Object.Subprogram_Index); ARM_Subindex.Create (Format_Object.Exception_Index); ARM_Subindex.Create (Format_Object.Object_Index); end Create; procedure Destroy (Format_Object : in out Format_Type) is -- Destroy a format object, releasing any resources. begin ARM_Database.Destroy (Format_Object.Aspect_DB); ARM_Database.Destroy (Format_Object.Attr_DB); ARM_Database.Destroy (Format_Object.Pragma_DB); ARM_Database.Destroy (Format_Object.Glossary_DB); ARM_Database.Destroy (Format_Object.Impdef_DB); ARM_Database.Destroy (Format_Object.Impladv_DB); ARM_Database.Destroy (Format_Object.Docreq_DB); ARM_Syntax.Destroy; ARM_Index.Destroy; ARM_Subindex.Destroy (Format_Object.Package_Index); ARM_Subindex.Destroy (Format_Object.Type_Index); ARM_Subindex.Destroy (Format_Object.Subprogram_Index); ARM_Subindex.Destroy (Format_Object.Exception_Index); ARM_Subindex.Destroy (Format_Object.Object_Index); end Destroy; function Clause_String (Format_Object : in Format_Type) return String is -- Returns a string for a clause reference. use type ARM_Contents.Section_Number_Type; begin if Format_Object.Clause_Number.Subsubclause /= 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.SubSubClause, Format_Object.Clause_Number); elsif Format_Object.Clause_Number.Subclause /= 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.SubClause, Format_Object.Clause_Number); elsif Format_Object.Clause_Number.Clause /= 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.Clause, Format_Object.Clause_Number); else if Format_Object.Clause_Number.Section = 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.Unnumbered_Section, Format_Object.Clause_Number); elsif Format_Object.Clause_Number.Section < ARM_Contents.ANNEX_START then return ARM_Contents.Make_Clause_Number ( ARM_Contents.Section, Format_Object.Clause_Number); else return ARM_Contents.Make_Clause_Number ( ARM_Contents.Plain_Annex, -- Same for all kinds of annex. Format_Object.Clause_Number); end if; end if; end Clause_String; Do_Not_Display_Text : constant ARM_Output.Change_Type := ARM_Output.Both; -- Special meaning for Calc_Change_Disposition, below. procedure Calc_Change_Disposition (Format_Object : in Format_Type; Version : in ARM_Contents.Change_Version_Type; Operation : in ARM_Output.Change_Type; Text_Kind : out ARM_Output.Change_Type) is -- Determine the appropriate disposition for text. -- The text is to be inserted if Operation is Insertion; -- and deleted if Operation is Deletion. -- The appropriate Change_Type to use is returned in Text_Kind. -- If Text_Kind is None, the text should be displayed normally. -- If Text_Kind is Insertion, the text should be displayed as inserted. -- If Text_Kind is Deletion, the text should be displayed as deletion. -- If Text_Kind is Do_Not_Display_Text (same as Both), the -- text should not be shown at all. -- Program_Error is raised if Operation is None or Both. -- This routine assumes that we are not nested -- in some other change item. use type ARM_Output.Change_Type; begin if Operation = ARM_Output.None or else Operation = ARM_Output.Both then raise Program_Error; end if; -- We can't check for nesting, because in some cases it happens -- harmlessly (i.e. Added_Pragma_Syn). case Format_Object.Changes is when ARM_Format.Old_Only => -- Display only the original version ('0'). if Operation = ARM_Output.Insertion then if Version > '0' then Text_Kind := Do_Not_Display_Text; -- Newer than original. else Text_Kind := ARM_Output.None; -- Display normally. end if; else -- Deletion if Version > '0' then Text_Kind := ARM_Output.None; -- Display normally, not deleted in original code. else Text_Kind := Do_Not_Display_Text; -- Deleted in original. end if; end if; when ARM_Format.New_Only => -- Display only the version -- Format_Object.Change_Version, no insertions or deletions. if Operation = ARM_Output.Insertion then if Version > Format_Object.Change_Version then -- Change version newer than we're displaying; -- ignore the item. Text_Kind := Do_Not_Display_Text; else -- Display the change normally. Text_Kind := ARM_Output.None; end if; else -- Deletion if Version > Format_Object.Change_Version then -- Change version newer than we're displaying; -- leave the item in and display normally. Text_Kind := ARM_Output.None; else -- Delete the item. Text_Kind := Do_Not_Display_Text; end if; end if; when ARM_Format.Changes_Only => -- Display only the the changes for version -- Format_Object.Change_Version, older changes -- are applied and newer changes are ignored. if Operation = ARM_Output.Insertion then if Version > Format_Object.Change_Version then -- Change version is newer than we're displaying; -- ignore the item. Text_Kind := Do_Not_Display_Text; elsif Version < Format_Object.Change_Version then -- Change version is older than we're displaying; -- display the change normally. Text_Kind := ARM_Output.None; else -- The correct version, display the change -- as an insertion. Text_Kind := ARM_Output.Insertion; end if; else -- Deletion. if Version > Format_Object.Change_Version then -- Change version is newer than we're displaying; -- the item isn't deleted yet, display the change -- normally. Text_Kind := ARM_Output.None; elsif Version < Format_Object.Change_Version then -- Change version is older than we're displaying; -- the item is deleted, so ignore the item. Text_Kind := Do_Not_Display_Text; else -- The correct version, display the change -- as a deletion. Text_Kind := ARM_Output.Deletion; end if; end if; when ARM_Format.Show_Changes | ARM_Format.New_Changes => -- Display all of the changes up to version -- Format_Object.Change_Version, newer changes are -- ignored. (New_Changes shows deletions as a single -- character for older versions of Word, but otherwise -- is the same.) if Operation = ARM_Output.Insertion then if Version > Format_Object.Change_Version then -- Change version is newer than we're displaying; -- ignore the item. Text_Kind := Do_Not_Display_Text; else -- This version or older, display the change -- as an insertion. Text_Kind := ARM_Output.Insertion; end if; else -- Deletion. if Version > Format_Object.Change_Version then -- Change version is newer than we're displaying; -- the item isn't deleted yet, display the change -- normally. Text_Kind := ARM_Output.None; else -- The correct version, display the change -- as a deletion. Text_Kind := ARM_Output.Deletion; end if; end if; end case; end Calc_Change_Disposition; function Get_Current_Item (Format_Object : in Format_Type; Input_Object : in ARM_Input.Input_Type'Class; Item : in String) return String is -- Return the "current" item from Item. This is Item itself, -- unless Item includes an @Chg. New_Pos : Natural; Close_Ch : Character; Open_Cnt : Natural; My_Item : constant String (1 .. Item'Length) := Item; -- Just to slide the bounds. Version : ARM_Contents.Change_Version_Type := '0'; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin if My_Item'Length < 11 or else My_Item (1) /= '@' or else Ada.Characters.Handling.To_Lower (My_Item (2 .. 4)) /= "chg" then -- No @Chg command here. return My_Item; end if; if Ada.Characters.Handling.To_Lower (My_Item (6 .. 9)) = "new=" then -- No version parameter: New_Pos := 6; Version := '1'; elsif My_Item'Length > 22 and then Ada.Characters.Handling.To_Lower (My_Item (6 .. 14)) = "version=[" and then Ada.Characters.Handling.To_Lower (My_Item (16 .. 21)) = "],new=" then New_Pos := 18; Version := My_Item(15); else Ada.Text_IO.Put_Line ("%% Oops, can't find either Version or New in item chg command, line " & ARM_Input.Line_String (Input_Object)); return My_Item; end if; Calc_Change_Disposition (Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- Find the end of the "New" parameter, and return the "Old" -- parameter. Close_Ch := ARM_Input.Get_Close_Char ( My_Item(New_Pos+4)); Open_Cnt := 1; for I in New_Pos+5 .. My_Item'Last loop if My_Item(I) = My_Item(New_Pos+4) then Open_Cnt := Open_Cnt + 1; elsif My_Item(I) = Close_Ch then if Open_Cnt <= 1 then -- OK, the end of the "New" parameter is at 'I'. if My_Item'Last < I+7 or else My_Item (I+1) /= ',' or else Ada.Characters.Handling.To_Lower (My_Item (I+2 .. I+4)) /= "old" or else My_Item (I+5) /= '=' then exit; -- Heck if I know. end if; Close_Ch := ARM_Input.Get_Close_Char ( My_Item(I+6)); Open_Cnt := 1; for J in I+7 .. My_Item'Last loop if My_Item(J) = My_Item(I+6) then Open_Cnt := Open_Cnt + 1; elsif My_Item(J) = Close_Ch then if Open_Cnt <= 1 then return My_Item (I + 7 .. J - 1); else Open_Cnt := Open_Cnt - 1; end if; -- else continue looking. end if; end loop; Ada.Text_IO.Put_Line ("%% Oops, can't find end of item chg old command, line " & ARM_Input.Line_String (Input_Object)); return My_Item (I + 7 .. My_Item'Last); else Open_Cnt := Open_Cnt - 1; end if; -- else continue looking. end if; end loop; Ada.Text_IO.Put_Line ("%% Oops, can't find end of item chg new command, line " & ARM_Input.Line_String (Input_Object)); return My_Item (New_Pos+5 .. My_Item'Length); else -- Some new format, use the new name. -- Find the end of the "New" parameter, and -- return it. Close_Ch := ARM_Input.Get_Close_Char (My_Item(New_Pos+4)); Open_Cnt := 1; for I in New_Pos+5 .. My_Item'Last loop if My_Item(I) = My_Item(New_Pos+4) then Open_Cnt := Open_Cnt + 1; elsif My_Item(I) = Close_Ch then if Open_Cnt <= 1 then return My_Item (New_Pos+5 .. I - 1); else Open_Cnt := Open_Cnt - 1; end if; -- else continue looking. end if; end loop; -- Weird if we get here, can't find end of parameter. Ada.Text_IO.Put_Line ("%% Oops, can't find end of NT chg new command, line " & ARM_Input.Line_String (Input_Object)); return My_Item (New_Pos+5 .. My_Item'Last); end if; end Get_Current_Item; function Get_Old_Item (Format_Object : in Format_Type; Input_Object : in ARM_Input.Input_Type'Class; Item : in String) return String is -- Return the "old" item from Item, or nothing if there is no -- old item. This is nothing unless Item includes an @Chg, -- *and* the new item in the @Chg is displayed. New_Pos : Natural; Close_Ch : Character; Open_Cnt : Natural; My_Item : constant String (1 .. Item'Length) := Item; -- Just to slide the bounds. Version : ARM_Contents.Change_Version_Type := '0'; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin if My_Item'Length < 11 or else My_Item (1) /= '@' or else Ada.Characters.Handling.To_Lower (My_Item (2 .. 4)) /= "chg" then -- No @Chg command here. return ""; end if; if Ada.Characters.Handling.To_Lower (My_Item (6 .. 9)) = "new=" then -- No version parameter: New_Pos := 6; Version := '1'; elsif My_Item'Length > 22 and then Ada.Characters.Handling.To_Lower (My_Item (6 .. 14)) = "version=[" and then Ada.Characters.Handling.To_Lower (My_Item (16 .. 21)) = "],new=" then New_Pos := 18; Version := My_Item(15); else Ada.Text_IO.Put_Line ("%% Oops, can't find either Version or New in item chg command, line " & ARM_Input.Line_String (Input_Object)); return ""; end if; Calc_Change_Disposition (Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition /= Do_Not_Display_Text then -- Some new item was shown. -- Find the end of the "New" parameter, and return the "Old" -- parameter. Close_Ch := ARM_Input.Get_Close_Char ( My_Item(New_Pos+4)); Open_Cnt := 1; for I in New_Pos+5 .. My_Item'Last loop if My_Item(I) = My_Item(New_Pos+4) then Open_Cnt := Open_Cnt + 1; elsif My_Item(I) = Close_Ch then if Open_Cnt <= 1 then -- OK, the end of the "New" parameter is at 'I'. if My_Item'Last < I+7 or else My_Item (I+1) /= ',' or else Ada.Characters.Handling.To_Lower (My_Item (I+2 .. I+4)) /= "old" or else My_Item (I+5) /= '=' then exit; -- Heck if I know. end if; Close_Ch := ARM_Input.Get_Close_Char ( My_Item(I+6)); Open_Cnt := 1; for J in I+7 .. My_Item'Last loop if My_Item(J) = My_Item(I+6) then Open_Cnt := Open_Cnt + 1; elsif My_Item(J) = Close_Ch then if Open_Cnt <= 1 then return My_Item (I + 7 .. J - 1); else Open_Cnt := Open_Cnt - 1; end if; -- else continue looking. end if; end loop; Ada.Text_IO.Put_Line ("%% Oops, can't find end of item chg old command, line " & ARM_Input.Line_String (Input_Object)); return My_Item (I + 7 .. My_Item'Last); else Open_Cnt := Open_Cnt - 1; end if; -- else continue looking. end if; end loop; Ada.Text_IO.Put_Line ("%% Oops, can't find end of item chg new command, line " & ARM_Input.Line_String (Input_Object)); return ""; else -- The new item wasn't displayed, so we already have used the -- old item. return ""; end if; end Get_Old_Item; procedure Scan (Format_Object : in out Format_Type; File_Name : in String; Section_Number : in ARM_Contents.Section_Number_Type; Starts_New_Section : in Boolean) is separate; -- Scans the contents for File_Name, determining the table of contents -- for the section. The results are written to the contents package. -- Starts_New_Section is True if the file starts a new section. -- Section_Number is the number (or letter) of the section. -- See ARM_FRMS.ADB. procedure Write_Table_of_Contents ( Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class) is -- Writes the table of contents for the document. (It will have -- a section name of "TOC"). This should be done after all calls to -- Scan and before any calls to Process. In_Paragraph : Boolean := False; procedure Write_It (Title : in ARM_Contents.Title_Type; Level : in ARM_Contents.Level_Type; Clause_Number : in ARM_Contents.Clause_Number_Type; Version : in ARM_Contents.Change_Version_Type; Quit : out Boolean) is Clause_Text : constant String := ARM_Contents.Make_Clause_Number (Level, Clause_Number); Old_Title : ARM_Contents.Title_Type := ARM_Contents.Lookup_Old_Title ( Level, Clause_Number); begin Quit := False; if Old_Title = ARM_Contents.Title_Type'(others => ' ') and then (Format_Object.Change_Version < Version or else ARM_Format."=" (Format_Object.Changes, ARM_Format.Old_Only)) then -- This is an added item, and we're generating a version -- that does not include it. Skip it completely. return; end if; if ARM_Contents."=" (Level, ARM_Contents.Clause) then ARM_Output.Line_Break (Output_Object); ARM_Output.Ordinary_Text (Output_Object, " "); ARM_Output.Ordinary_Text (Output_Object, Clause_Text); ARM_Output.Hard_Space (Output_Object); elsif ARM_Contents."=" (Level, ARM_Contents.Subclause) then ARM_Output.Line_Break (Output_Object); ARM_Output.Ordinary_Text (Output_Object, " "); ARM_Output.Ordinary_Text (Output_Object, Clause_Text); ARM_Output.Hard_Space (Output_Object); elsif ARM_Contents."=" (Level, ARM_Contents.Subsubclause) then ARM_Output.Line_Break (Output_Object); ARM_Output.Ordinary_Text (Output_Object, " "); ARM_Output.Ordinary_Text (Output_Object, Clause_Text); ARM_Output.Hard_Space (Output_Object); elsif ARM_Contents."=" (Level, ARM_Contents.Unnumbered_Section) then if In_Paragraph then ARM_Output.End_Paragraph (Output_Object); end if; ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Normal, Indent => 0, Number => "", Justification => ARM_Output.Left); In_Paragraph := True; else if In_Paragraph then ARM_Output.End_Paragraph (Output_Object); end if; ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Normal, Indent => 0, Number => "", Justification => ARM_Output.Left); In_Paragraph := True; if ARM_Contents."=" (Level, ARM_Contents.Section) then ARM_Output.Ordinary_Text (Output_Object, Clause_Text); ARM_Output.Ordinary_Text (Output_Object, ". "); else -- Annexes. ARM_Output.Ordinary_Character (Output_Object, Clause_Text(Clause_Text'Last)); -- We don't want the "Annex" part. ARM_Output.Ordinary_Text (Output_Object, ". "); end if; end if; if Format_Object.Change_Version < Version then -- Ignore the change: ARM_Output.Clause_Reference (Output_Object, Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Old_Title ( Level, Clause_Number), Ada.Strings.Right), Clause_Text); else case Format_Object.Changes is when ARM_Format.Old_Only => ARM_Output.Clause_Reference (Output_Object, Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Old_Title ( Level, Clause_Number), Ada.Strings.Right), Clause_Text); when ARM_Format.New_Only | ARM_Format.Changes_Only | ARM_Format.Show_Changes | ARM_Format.New_Changes => ARM_Output.Clause_Reference (Output_Object, Ada.Strings.Fixed.Trim (Title, Ada.Strings.Right), Clause_Text); end case; end if; end Write_It; procedure Write_Contents is new ARM_Contents.For_Each (Write_It); begin -- Note: For .RTF version, the result of this call will not be used, -- preferring to let Word make the TOC (it can include page numbers). if Format_Object.Use_ISO_2004_Contents_Format then ARM_Output.Section (Output_Object, Section_Title => "Contents", Section_Name => "TOC"); ARM_Output.Clause_Header (Output_Object, Header_Text => "Contents", Level => ARM_Contents.Section, Clause_Number => "", Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); else ARM_Output.Section (Output_Object, Section_Title => "Table of Contents", Section_Name => "TOC"); ARM_Output.Clause_Header (Output_Object, Header_Text => "Table of Contents", Level => ARM_Contents.Section, Clause_Number => "", Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end if; ARM_Output.TOC_Marker (Output_Object, For_Start => True); Write_Contents; if In_Paragraph then ARM_Output.End_Paragraph (Output_Object); end if; ARM_Output.TOC_Marker (Output_Object, For_Start => False); end Write_Table_of_Contents; procedure Make_References (List : in out Reference_Ptr; Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class) is -- Write the references to the Output_Object, using the format -- of Format_Object. -- Deallocate the references on List; List will be null afterwards. Temp : Reference_Ptr; Our_Text_Format : ARM_Output.Format_Type; begin -- We assume these are only stored here if we want to see them -- on *this* paragraph. Thus, we just output them if they exist -- here. Our_Text_Format := Format_Object.Text_Format; Our_Text_Format.Change := ARM_Output.None; -- No changes should be reflected in references. while List /= null loop -- Output a reference. These are *never* marked as -- inserted or deleted, so set the style properly. ARM_Output.Text_Format (Output_Object, Format => Our_Text_Format); ARM_Output.Ordinary_Character (Output_Object, '{'); Our_Text_Format.Italic := True; ARM_Output.Text_Format (Output_Object, Format => Our_Text_Format); if List.Is_DR_Ref then -- Output a DR reference. ARM_Output.DR_Reference (Output_Object, Text => List.Ref_Name(1..List.Ref_Len), DR_Number => List.Ref_Name(1..List.Ref_Len)); else -- Output an AI reference. ARM_Output.AI_Reference (Output_Object, Text => List.Ref_Name(1..List.Ref_Len), AI_Number => List.Ref_Name(1..List.Ref_Len)); end if; Our_Text_Format.Italic := Format_Object.Text_Format.Italic; ARM_Output.Text_Format (Output_Object, Format => Our_Text_Format); ARM_Output.Ordinary_Character (Output_Object, '}'); ARM_Output.Ordinary_Character (Output_Object, ' '); -- Reset to the current format. ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); Format_Object.Last_Non_Space := False; Temp := List; List := List.Next; Free_Reference (Temp); end loop; end Make_References; procedure Dump_References (List : in out Reference_Ptr) is -- Destroy any references in List; List will be null afterwards. Temp : Reference_Ptr; begin while List /= null loop Temp := List; List := List.Next; Free_Reference (Temp); end loop; end Dump_References; type Items is record Kind : Command_Kind_Type; Name : ARM_Input.Command_Name_Type; Command : Data.Command_Type; Close_Char : Character; -- Ought to be }, ], >, or ). Text_Format : ARM_Output.Format_Type; -- Format at the start of the command. -- The next four are only used if Kind=Begin_Word, or for -- Command=Implementation_Defined, Glossary_Text_Param, or -- Syntax_Rule_RHS. Old_Last_Subhead_Paragraph : Paragraph_Type; Old_Next_Subhead_Paragraph : Paragraph_Type; Old_Next_Paragraph_Format : Paragraph_Type; Old_Tab_Stops : ARM_Output.Tab_Info; Old_Next_Enum_Num : Positive; Is_Formatting : Boolean; -- Only used if Kind=Begin_Word. -- The command changes the PARAGRAPH format. -- Otherwise, it should be ignored when -- when determining the format. -- The following is only used if Command = Change, Change_Added, -- Change_Deleted, Added_Subheading, -- Added_Pragma_Syntax, Deleted_Pragma_Syntax, -- Added_Syntax, Deleted_Syntax, -- New_Page_for_Version, New_Column_for_Version, -- RM_New_Page_for_Version, Not_ISO_RM_New_Page_for_Version, and -- ISO_Only_RM_New_Page_for_Version. Change_Version : ARM_Contents.Change_Version_Type; -- The following are only used if Command = Change, -- Added_Pragma_Syntax, and Deleted_Pragma_Syntax. Prev_Change_Version : ARM_Contents.Change_Version_Type; -- The following are only used if Command = Change. Was_Text : Boolean; -- Did the current subcommand have text? Prev_Change : ARM_Output.Change_Type; Prev_Added_Change_Version : ARM_Contents.Change_Version_Type; end record; type Nesting_Stack_Type is array (1 .. 40) of Items; type Format_State_Type is record Nesting_Stack : Nesting_Stack_Type; Nesting_Stack_Ptr : Natural := 0; end record; procedure Real_Process (Format_Object : in out Format_Type; Format_State : in out Format_State_Type; Input_Object : in out ARM_Input.Input_Type'Class; Output_Object : in out ARM_Output.Output_Type'Class) is -- Process the contents of Input_Object, writing the results to -- Output_Object. (Output_Object uses dispatching calls to provide -- the correct formatting). Format_Object holds information about -- the state of the formatting. procedure Set_Nesting_for_Command (Name : in ARM_Input.Command_Name_Type; Kind : in Command_Kind_Type; Param_Ch : in Character) is -- Push the command onto the nesting stack. begin Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr + 1; Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr) := (Name => Name, Kind => Kind, Command => Data.Command (Name), Close_Char => ' ', -- Set below. Text_Format => Format_Object.Text_Format, -- Save the current format. -- Other things next necessarily used: Old_Last_Subhead_Paragraph => Plain, -- Not used. Old_Next_Subhead_Paragraph => Plain, -- Not used. Old_Next_Paragraph_Format => Plain, -- Not used. Old_Tab_Stops => ARM_Output.NO_TABS, -- Not used. Old_Next_Enum_Num => 1, -- Not used. Is_Formatting => False, -- Not used. Change_Version => '0', -- Not used. Was_Text => False, -- Not used. Prev_Change => ARM_Output.None, -- Not used. Prev_Change_Version => '0', -- Not used. Prev_Added_Change_Version => '0'); -- Not used. Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char := ARM_Input.Get_Close_Char (Param_Ch); --Ada.Text_IO.Put_Line (" &Stack (" & Name & "); Close-Char=" & -- Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char); end Set_Nesting_for_Command; procedure Set_Nesting_for_Parameter (Command : in Data.Command_Type; Close_Ch : in Character) is -- Push the parameter onto the nesting stack. begin Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr + 1; Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr) := (Name => (others => ' '), Kind => Parameter, Command => Command, Close_Char => Close_Ch, Text_Format => Format_Object.Text_Format, -- Save the current -- format (not really used here). Old_Last_Subhead_Paragraph => Plain, -- Not used. Old_Next_Subhead_Paragraph => Plain, -- Not used. Old_Next_Paragraph_Format => Plain, -- Not used. Old_Tab_Stops => ARM_Output.NO_TABS, -- Not used. Old_Next_Enum_Num => 1, -- Not used. Is_Formatting => False, -- Not used. Change_Version => '0', -- Not used. Was_Text => False, -- Not used. Prev_Change => ARM_Output.None, -- Not used. Prev_Change_Version => '0', -- Not used. Prev_Added_Change_Version => '0'); -- Not used. --Ada.Text_IO.Put_Line (" &Stack (Parameter)"); end Set_Nesting_for_Parameter; function Is_AARM_Paragraph (Kind : in Paragraph_Type) return Boolean is begin case Kind is when Plain | Introduction | Syntax | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | Documentation | Metrics | Permissions | Advice | Notes | Single_Note | Examples => return False; when Language_Design | Ada83_Inconsistencies | Ada83_Incompatibilities | Ada83_Extensions | Ada83_Wording | Ada95_Inconsistencies | Ada95_Incompatibilities | Ada95_Extensions | Ada95_Wording | Ada2005_Inconsistencies | Ada2005_Incompatibilities | Ada2005_Extensions | Ada2005_Wording | Ada2012_Inconsistencies | Ada2012_Incompatibilities | Ada2012_Extensions | Ada2012_Wording | Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Bare_Annotation | Element_Ref | Child_Ref | Usage_Note => return True; when In_Table => return False; -- Tables are never considered part of the -- AARM for formatting purposes, even when they are. when Wide_Above | Example_Text | Indented_Example_Text | Child_Example_Text | Code_Indented | Indent | Bulleted | Nested_Bulleted | Nested_X2_Bulleted | Display | Syntax_Display | Syntax_Indented | Syntax_Production | Enumerated | Nested_Enumerated | Hanging_Indented_1 | Hanging_Indented_2 | Hanging_Indented_3 | Hanging_Indented_4 | Small | Title => -- This depends on the containing paragraph kind; -- Last_Paragraph_Subhead_Type should contain that. if Format_Object.Last_Paragraph_Subhead_Type = Wide_Above or else Format_Object.Last_Paragraph_Subhead_Type = Example_Text or else Format_Object.Last_Paragraph_Subhead_Type = Child_Example_Text or else Format_Object.Last_Paragraph_Subhead_Type = Indented_Example_Text or else Format_Object.Last_Paragraph_Subhead_Type = Bulleted or else Format_Object.Last_Paragraph_Subhead_Type = Code_Indented or else Format_Object.Last_Paragraph_Subhead_Type = Indent or else Format_Object.Last_Paragraph_Subhead_Type = Nested_Bulleted or else Format_Object.Last_Paragraph_Subhead_Type = Nested_X2_Bulleted or else Format_Object.Last_Paragraph_Subhead_Type = Display or else Format_Object.Last_Paragraph_Subhead_Type = Syntax_Display or else Format_Object.Last_Paragraph_Subhead_Type = Syntax_Indented or else Format_Object.Last_Paragraph_Subhead_Type = Syntax_Production or else Format_Object.Last_Paragraph_Subhead_Type = Enumerated or else Format_Object.Last_Paragraph_Subhead_Type = Nested_Enumerated or else Format_Object.Last_Paragraph_Subhead_Type = Hanging_Indented_1 or else Format_Object.Last_Paragraph_Subhead_Type = Hanging_Indented_2 or else Format_Object.Last_Paragraph_Subhead_Type = Hanging_Indented_3 or else Format_Object.Last_Paragraph_Subhead_Type = Hanging_Indented_4 or else Format_Object.Last_Paragraph_Subhead_Type = Title or else Format_Object.Last_Paragraph_Subhead_Type = In_Table then Ada.Text_IO.Put_Line ("%% Oops, can't find out if AARM paragraph, line " & ARM_Input.Line_String (Input_Object)); return False; -- Oops, can't tell (double nesting). -- We make this check to avoid infinite recursion. else return Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type); end if; end case; end Is_AARM_Paragraph; procedure Paragraph_Number_String (Update_Numbers : in Boolean) is -- Generate the current (next) paragraph number string into -- Format_Object.Current_Paragraph_String. Update the paragraph -- numbers if Update_Numbers is True. PNum : constant String := Integer'Image(Format_Object.Next_Paragraph); PNum_Pred : constant String := Integer'Image(Format_Object.Next_Paragraph-1); use type Arm_Database.Paragraph_Change_Kind_Type; procedure AARM_Sub_Num (Sub_Letter : in Character) is -- Adds a properly formatted AARM sub letter, with leading '.'. -- Sets the length appropriately. begin Format_Object.Current_Paragraph_String(PNum_Pred'Last) := '.'; if Sub_Letter <= 'z' then Format_Object.Current_Paragraph_String(PNum_Pred'Last+1) := Sub_Letter; Format_Object.Current_Paragraph_Len := PNum_Pred'Last + 1; elsif Character'Val(Character'Pos(Sub_Letter) - 26) <= 'z' then -- Double letter. Format_Object.Current_Paragraph_String(PNum_Pred'Last+1) := Character'Val(Character'Pos(Sub_Letter) - 26); Format_Object.Current_Paragraph_String(PNum_Pred'Last+2) := Character'Val(Character'Pos(Sub_Letter) - 26); Format_Object.Current_Paragraph_Len := PNum_Pred'Last + 2; elsif Character'Val(Character'Pos(Sub_Letter) - 52) <= 'z' then -- Triple letter. Format_Object.Current_Paragraph_String(PNum_Pred'Last+1) := Character'Val(Character'Pos(Sub_Letter) - 52); Format_Object.Current_Paragraph_String(PNum_Pred'Last+2) := Character'Val(Character'Pos(Sub_Letter) - 52); Format_Object.Current_Paragraph_String(PNum_Pred'Last+3) := Character'Val(Character'Pos(Sub_Letter) - 52); Format_Object.Current_Paragraph_Len := PNum_Pred'Last + 3; else -- Doesn't fit! Ada.Text_IO.Put_Line ("** AARM paragraph number out of range, line " & ARM_Input.Line_String (Input_Object)); Format_Object.Current_Paragraph_String(PNum_Pred'Last+1) := '$'; Format_Object.Current_Paragraph_String(PNum_Pred'Last+2) := '$'; Format_Object.Current_Paragraph_String(PNum_Pred'Last+3) := '$'; Format_Object.Current_Paragraph_Len := PNum_Pred'Last + 3; end if; end AARM_Sub_Num; begin -- The full paragraph number is: -- Num.AARM.Ins/Vers -- where Num is a paragraph number in the RM; AARM is the -- paragraph subletter for AARM text; Ins is the number of -- inserted paragraph; and Vers is the version number ('1' -- for Technical Corrigendum 1; '0' for original RM.; -- '2' for Amendment 1). Note that we don't include change -- versions greater than the one we're currently processing. -- Unused parts are omitted. -- %%%% Buglet: If a paragraph was changed by multiple versions, -- we only know the last one. So we guess. If there was a change -- visible here, there must be a revision number, so we use the -- one we're generating. That could be wrong if we have three -- or more versions. I hope we don't need to regenerate old -- versions that far back. if Format_Object.Next_Paragraph_Change_Kind = ARM_Database.None or else Format_Object.Changes = Old_Only then -- Either there is no change, or we are only producing -- the original document (which means we ignore all -- marked changes). if Is_AARM_Paragraph (Format_Object.Next_Paragraph_Subhead_Type) then Format_Object.Current_Paragraph_String(1 .. PNum_Pred'Last-1) := PNum_Pred(2..PNum_Pred'Last); AARM_Sub_Num (Format_Object.Next_AARM_Sub); if Update_Numbers then Format_Object.Next_AARM_Sub := Character'Succ(Format_Object.Next_AARM_Sub); Format_Object.Next_AARM_Insert_Para := 1; end if; else Format_Object.Current_Paragraph_String(1 .. PNum'Last-1) := PNum(2..PNum'Last); Format_Object.Current_Paragraph_Len := PNum'Last - 1; if Update_Numbers then Format_Object.Next_Paragraph := Format_Object.Next_Paragraph + 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; Format_Object.Next_AARM_Insert_Para := 1; end if; end if; elsif Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Inserted or else Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Revised_Inserted_Number or else Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Deleted_Inserted_Number or else Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Deleted_Inserted_Number_No_Delete_Message then -- We'll assume that there are no more than 99 inserted -- paragraphs in a row. Format_Object.Current_Paragraph_String(1 .. PNum_Pred'Last-1) := PNum_Pred(2..PNum_Pred'Last); if Is_AARM_Paragraph (Format_Object.Next_Paragraph_Subhead_Type) then if Format_Object.Next_AARM_Sub = 'a' then AARM_Sub_Num ('a'); -- No paras before the insertion. else AARM_Sub_Num (Character'Pred(Format_Object.Next_AARM_Sub)); -- Insertions use the preceeding paragraph letter. end if; Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 1) := '.'; if Format_Object.Next_AARM_Insert_Para >= 10 then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Character'Val((Format_Object.Next_AARM_Insert_Para/10) + Character'Pos('0')); Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 3) := Character'Val((Format_Object.Next_AARM_Insert_Para mod 10) + Character'Pos('0')); Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len + 1; -- Make this consistent with the other cases. else Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Character'Val(Format_Object.Next_AARM_Insert_Para + Character'Pos('0')); end if; if Update_Numbers then Format_Object.Next_AARM_Insert_Para := Format_Object.Next_AARM_Insert_Para + 1; end if; else -- None inserted paragraphs. Format_Object.Current_Paragraph_Len := PNum_Pred'Last - 1; Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 1) := '.'; if Format_Object.Next_Insert_Para >= 10 then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Character'Val((Format_Object.Next_Insert_Para/10) + Character'Pos('0')); Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 3) := Character'Val((Format_Object.Next_Insert_Para mod 10) + Character'Pos('0')); Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len + 1; -- Make this consistent with the other cases. else Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Character'Val(Format_Object.Next_Insert_Para + Character'Pos('0')); end if; if Update_Numbers then Format_Object.Next_Insert_Para := Format_Object.Next_Insert_Para + 1; -- Note: We don't update the AARM numbers for -- inserted paragraphs, as the insertion number is -- not included in them. end if; end if; if Format_Object.Next_Paragraph_Version /= '0' then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 3) := '/'; if Format_Object.Next_Paragraph_Version <= Format_Object.Change_Version then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 4) := Format_Object.Next_Paragraph_Version; else -- Use the number we're generating. Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 4) := Format_Object.Change_Version; end if; Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len + 4; else Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len + 2; end if; else --if Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Revised or else -- Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Deleted or else -- Format_Object.Next_Paragraph_Change_Kind = ARM_Database.Inserted_Normal_Number then if Is_AARM_Paragraph (Format_Object.Next_Paragraph_Subhead_Type) then Format_Object.Current_Paragraph_String(1 .. PNum_Pred'Last-1) := PNum_Pred(2..PNum_Pred'Last); AARM_Sub_Num (Format_Object.Next_AARM_Sub); -- Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len; -- useless assign if Update_Numbers then Format_Object.Next_AARM_Sub := Character'Succ(Format_Object.Next_AARM_Sub); Format_Object.Next_AARM_Insert_Para := 1; end if; else Format_Object.Current_Paragraph_String(1 .. PNum'Last-1) := PNum(2..PNum'Last); Format_Object.Current_Paragraph_Len := PNum'Last - 1; if Update_Numbers then Format_Object.Next_Paragraph := Format_Object.Next_Paragraph + 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; Format_Object.Next_AARM_Insert_Para := 1; end if; end if; if Format_Object.Next_Paragraph_Version /= '0' then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 1) := '/'; if Format_Object.Next_Paragraph_Version <= Format_Object.Change_Version then Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Format_Object.Next_Paragraph_Version; else -- Use the number we're generating. Format_Object.Current_Paragraph_String(Format_Object.Current_Paragraph_Len + 2) := Format_Object.Change_Version; end if; Format_Object.Current_Paragraph_Len := Format_Object.Current_Paragraph_Len + 2; -- else no version to display. end if; end if; end Paragraph_Number_String; function Paragraph_String return String is -- Returns a string for a paragraph reference, for use in an -- index entry. begin if Format_Object.In_Paragraph then null; -- It is already is stored. else -- Generate the next paragraph number. Paragraph_Number_String (Update_Numbers => False); end if; return Format_Object.Current_Paragraph_String ( 1 .. Format_Object.Current_Paragraph_Len); end Paragraph_String; procedure Check_Paragraph is -- Open a paragraph if needed before outputting any text that needs -- one. procedure Set_Format (For_Type : Paragraph_Type) is use type ARM_Output.Paragraph_Indent_Type; function Enclosing_Format return Paragraph_Type is begin for I in reverse 1 .. Format_State.Nesting_Stack_Ptr loop if Format_State.Nesting_Stack(I).Command = Text_Begin and then (Format_State.Nesting_Stack(I).Is_Formatting) then return Format_State.Nesting_Stack(I).Old_Next_Paragraph_Format; end if; end loop; return Plain; -- The default format. end Enclosing_Format; function Enclosing_Indent return ARM_Output.Paragraph_Indent_Type is function Nested_Indent (Start_Nesting : in Natural) return ARM_Output.Paragraph_Indent_Type is begin for I in reverse 1 .. Start_Nesting loop if Format_State.Nesting_Stack(I).Command = Text_Begin and then (Format_State.Nesting_Stack(I).Is_Formatting) then case Format_State.Nesting_Stack(I).Old_Next_Paragraph_Format is when Plain | Introduction | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | -- ImplReq Documentation | -- DocReq Metrics | Permissions | -- ImplPerm Advice | -- ImplAdvice Examples => return 0; -- No indent. when Wide_Above => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then return 2; -- Normal indent for annotations. else return 0; -- No indent. end if; when Syntax => return 1; -- One unit. when Notes | Single_Note => -- Notes (only the numbering varies) return 1; -- One unit. when Element_Ref | Child_Ref | Usage_Note => -- Similar to an AARM note. return 2; -- Normal indent for annotations. when Language_Design | -- "MetaRules" Ada83_Inconsistencies | -- Inconsistent83 Ada83_Incompatibilities | -- Incompatible83 Ada83_Extensions | -- Extend83 Ada83_Wording | -- DiffWord83 Ada95_Inconsistencies | -- Inconsistent95 Ada95_Incompatibilities | -- Incompatible95 Ada95_Extensions | -- Extend95 Ada95_Wording | -- DiffWord95 Ada2005_Inconsistencies | -- Inconsistent2005 Ada2005_Incompatibilities | -- Incompatible2005 Ada2005_Extensions | -- Extend2005 Ada2005_Wording | -- DiffWord2005 Ada2012_Inconsistencies | -- Inconsistent2012 Ada2012_Incompatibilities | -- Incompatible2012 Ada2012_Extensions | -- Extend2012 Ada2012_Wording => -- DiffWord2012 return 2; -- Normal indent for annotations. when Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Bare_Annotation => return 2; -- Normal indent for annotations. when Example_Text => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then return 3; -- Three units. else return 1; -- One unit. end if; when Child_Example_Text => return 1 + Nested_Indent(I-1); -- Depends on enclosing. when Indented_Example_Text => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then return 6; -- Six units. else return 4; -- Four units. end if; when Code_Indented => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then return 4; -- Four units. else return 2; -- Two units. end if; when Indent => return 1 + Nested_Indent(I-1); -- Depends on enclosing. when Bulleted | Nested_Bulleted | Nested_X2_Bulleted => return 1 + Nested_Indent(I-1); -- Depends on enclosing. when Display => return 1 + Nested_Indent(I-1); -- Depends on enclosing. when Syntax_Display => return 1; -- One unit. when Enumerated | Nested_Enumerated => return 1 + Nested_Indent(I-1); -- Depends on enclosing. when Syntax_Indented => return 1; -- One unit. when Syntax_Production => return Nested_Indent(I-1); -- Depends on enclosing. when Hanging_Indented_1 => return Nested_Indent(I-1) + 1; -- Depends on enclosing, at least 1. when Hanging_Indented_2 => return Nested_Indent(I-1) + 2; -- Depends on enclosing, at least 2. when Hanging_Indented_3 => return Nested_Indent(I-1) + 3; -- Depends on enclosing, at least 3. when Hanging_Indented_4 => return Nested_Indent(I-1) + 4; -- Depends on enclosing, at least 4. when Small => return Nested_Indent(I-1); -- Depends on enclosing, does not change. when Title => return 0; -- No indent. when In_Table => -- Shouldn't get here. return 0; -- No indent. end case; end if; end loop; return 0; -- No indent. end Nested_Indent; begin return Nested_Indent (Format_State.Nesting_Stack_Ptr); end Enclosing_Indent; function Is_Small_Format_Paragraph (Subhead_Kind : in Paragraph_Type) return Boolean is -- AARM annotations are in the small font, as are user notes. begin if Is_AARM_Paragraph (Subhead_Kind) then return True; -- AARM paragraphs are always small. else -- Check the enclosing formatting for "small" or -- other styles that imply that. for I in reverse 1 .. Format_State.Nesting_Stack_Ptr loop if Format_State.Nesting_Stack(I).Command = Text_Begin and then (Format_State.Nesting_Stack(I).Is_Formatting) then case Format_State.Nesting_Stack(I).Old_Next_Paragraph_Format is when Introduction | Syntax | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | Documentation | Metrics | Permissions | Advice | Examples => return False; when Language_Design | Ada83_Inconsistencies | Ada83_Incompatibilities | Ada83_Extensions | Ada83_Wording | Ada95_Inconsistencies | Ada95_Incompatibilities | Ada95_Extensions | Ada95_Wording | Ada2005_Inconsistencies | Ada2005_Incompatibilities | Ada2005_Extensions | Ada2005_Wording | Ada2012_Inconsistencies | Ada2012_Incompatibilities | Ada2012_Extensions | Ada2012_Wording | Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Bare_Annotation | Element_Ref | Child_Ref | Usage_Note | Notes | Single_Note | Small => return True; when Plain | Wide_Above | In_Table | Example_Text | Indented_Example_Text | Child_Example_Text | Code_Indented | Indent | Bulleted | Nested_Bulleted | Nested_X2_Bulleted | Display | Syntax_Display | Syntax_Indented | Syntax_Production | Enumerated | Nested_Enumerated | Hanging_Indented_1 | Hanging_Indented_2 | Hanging_Indented_3 | Hanging_Indented_4 | Title => -- This depends on the containing paragraph kind, -- keep looking. null; end case; end if; end loop; return False; -- Don't know. end if; end Is_Small_Format_Paragraph; begin case For_Type is when Plain | Introduction | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | -- ImplReq Documentation | -- DocReq Metrics | Permissions | -- ImplPerm Advice | -- ImplAdvice Examples => Format_Object.Style := ARM_Output.Normal; Format_Object.Indent := 0; -- No indent. Format_Object.No_Breaks := False; when Wide_Above => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Wide_Above; Format_Object.Indent := 2; -- Two units. elsif Format_Object.Last_Paragraph_Subhead_Type = Notes or else Format_Object.Last_Paragraph_Subhead_Type = Single_Note then Format_Object.Style := ARM_Output.Small_Wide_Above; Format_Object.Indent := 1; -- One unit. else Format_Object.Style := ARM_Output.Wide_Above; Format_Object.Indent := 0; -- No indent. end if; Format_Object.No_Breaks := False; when Syntax => Format_Object.Style := ARM_Output.Normal; Format_Object.Indent := 1; -- One unit. Format_Object.No_Breaks := True; when Notes | Single_Note | Small => -- Notes (only the numbering varies) Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 1; -- One unit. Format_Object.No_Breaks := False; when Element_Ref | Child_Ref | Usage_Note => -- Similar to an AARM note. Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 2; -- Two units. Format_Object.No_Breaks := False; when Language_Design | -- "MetaRules" Ada83_Inconsistencies | -- Inconsistent83 Ada83_Incompatibilities | -- Incompatible83 Ada83_Extensions | -- Extend83 Ada83_Wording | -- DiffWord83 Ada95_Inconsistencies | -- Inconsistent95 Ada95_Incompatibilities | -- Incompatible95 Ada95_Extensions | -- Extend95 Ada95_Wording | -- DiffWord95 Ada2005_Inconsistencies | -- Inconsistent2005 Ada2005_Incompatibilities | -- Incompatible2005 Ada2005_Extensions | -- Extend2005 Ada2005_Wording | -- DiffWord2005 Ada2012_Inconsistencies | -- Inconsistent2012 Ada2012_Incompatibilities | -- Incompatible2012 Ada2012_Extensions | -- Extend2012 Ada2012_Wording => -- DiffWord2012 Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 2; -- Two units. Format_Object.No_Breaks := False; when Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Bare_Annotation => Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 2; -- Two units. Format_Object.No_Breaks := False; when Example_Text | Child_Example_Text | Indented_Example_Text => case Format_Object.Examples_Font is when ARM_Output.Fixed | ARM_Output.Default => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then --if not Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) and then -- Format_Object.Last_Paragraph_Subhead_Type /= Small then -- Ada.Text_IO.Put_Line ("$$ Example in notes: size change, line " & ARM_Input.Line_String (Input_Object)); --end if; Format_Object.Style := ARM_Output.Small_Examples; else Format_Object.Style := ARM_Output.Examples; end if; when ARM_Output.Roman => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small; else Format_Object.Style := ARM_Output.Normal; end if; when ARM_Output.Swiss => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Swiss_Examples; else Format_Object.Style := ARM_Output.Swiss_Examples; end if; end case; Format_Object.No_Breaks := True; if For_Type = Child_Example_Text then Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Child example paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); elsif For_Type = Indented_Example_Text then if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Indent := 6; -- Fixed indent. elsif Format_Object.Last_Paragraph_Subhead_Type = Notes or else Format_Object.Last_Paragraph_Subhead_Type = Single_Note then Format_Object.Indent := 5; -- Fixed indent. else Format_Object.Indent := 4; -- Fixed indent. end if; else if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Indent := 3; -- Fixed indent. elsif Format_Object.Last_Paragraph_Subhead_Type = Notes or else Format_Object.Last_Paragraph_Subhead_Type = Single_Note then Format_Object.Indent := 2; -- Fixed indent. else Format_Object.Indent := 1; -- Fixed indent. end if; end if; when Code_Indented => if Is_AARM_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 4; -- Four units. elsif Format_Object.Last_Paragraph_Subhead_Type = Notes or else Format_Object.Last_Paragraph_Subhead_Type = Single_Note then Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 3; -- Three units. elsif Format_Object.Last_Paragraph_Subhead_Type = Small then Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 2; -- Two units. else Format_Object.Style := ARM_Output.Normal; Format_Object.Indent := 2; -- Two indent. end if; Format_Object.No_Breaks := False; when Indent => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small; else Format_Object.Style := ARM_Output.Normal; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Child Indented paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.No_Breaks := False; when Bulleted => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Bulleted; else Format_Object.Style := ARM_Output.Bulleted; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Regular bulleted paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Nested_Bulleted => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Nested_Bulleted; else Format_Object.Style := ARM_Output.Nested_Bulleted; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Nested bulleted paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Nested_X2_Bulleted => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Nested_Bulleted; else Format_Object.Style := ARM_Output.Nested_Bulleted; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Nested X2 bulleted paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Display => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small; else Format_Object.Style := ARM_Output.Normal; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Display paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.No_Breaks := True; when Syntax_Display => Format_Object.Style := ARM_Output.Small; Format_Object.Indent := 1; Format_Object.No_Breaks := True; when Enumerated => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Enumerated; else Format_Object.Style := ARM_Output.Enumerated; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Regular enumerated paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Nested_Enumerated => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Enumerated; else Format_Object.Style := ARM_Output.Enumerated; end if; Format_Object.Indent := 1 + Enclosing_Indent; --Ada.Text_IO.Put_Line ("&& Nested enumerated paragraph, line " & ARM_Input.Line_String (Input_Object) & " EF=" & Paragraph_Type'Image(Enclosing_Format) & " Indent=" & -- ARM_Output.Paragraph_Indent_Type'Image(Format_Object.Indent)); -- Note: The difference here is the numbering, not the -- layout. Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Syntax_Indented => Format_Object.Style := ARM_Output.Normal; Format_Object.Indent := 1; -- One unit. Format_Object.No_Breaks := False; when Syntax_Production => null; -- Leave format alone (but line-breaks are preserved). Format_Object.No_Breaks := True; when Hanging_Indented_1 => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Narrow_Hanging; else -- Normal: Format_Object.Style := ARM_Output.Narrow_Hanging; end if; Format_Object.Indent := 1 + Enclosing_Indent; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Hanging_Indented_2 => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then if Enclosing_Format = Bulleted or else Enclosing_Format = Enumerated then Format_Object.Style := ARM_Output.Small_Hanging_in_Bulleted; -- The right margin is also adjusted in this case. -- This is a weird special case, used only in -- RM 11.5. else Format_Object.Style := ARM_Output.Small_Medium_Hanging; end if; else -- Normal: if Enclosing_Format = Bulleted or else Enclosing_Format = Enumerated then Format_Object.Style := ARM_Output.Hanging_in_Bulleted; -- The right margin is also adjusted in this case. else Format_Object.Style := ARM_Output.Medium_Hanging; end if; end if; Format_Object.Indent := 2 + Enclosing_Indent; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Hanging_Indented_3 => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Wide_Hanging; else -- Normal: Format_Object.Style := ARM_Output.Wide_Hanging; end if; Format_Object.Indent := 3 + Enclosing_Indent; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Hanging_Indented_4 => if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small_Giant_Hanging; else -- Normal: Format_Object.Style := ARM_Output.Giant_Hanging; end if; Format_Object.Indent := 4 + Enclosing_Indent; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.No_Breaks := False; when Title => Format_Object.Style := ARM_Output.Title; Format_Object.Indent := 0; -- No indent. Format_Object.No_Breaks := False; when In_Table => -- Shouldn't get here. if Is_Small_Format_Paragraph (Format_Object.Last_Paragraph_Subhead_Type) then Format_Object.Style := ARM_Output.Small; else Format_Object.Style := ARM_Output.Normal; end if; Format_Object.Indent := 0; -- No indent. Format_Object.No_Breaks := False; end case; end Set_Format; procedure Make_Subhead (For_Type : Paragraph_Type) is begin case For_Type is when Syntax | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | -- ImplReq Documentation | -- DocReq Metrics | Permissions | -- ImplPerm Advice | -- ImplAdvice Examples => ARM_Output.Category_Header (Output_Object, Data.Paragraph_Kind_Title(For_Type).Str(1..Data.Paragraph_Kind_Title(For_Type).Length)); Format_Object.Last_Paragraph_Subhead_Type := For_Type; when Notes | Single_Note => -- Notes if not Format_Object.Use_ISO_2004_Note_Format then -- The Notes header looks different from the others. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Small_Header, Indent => 1, Number => "", No_Breaks => True, Keep_with_Next => True); ARM_Output.Ordinary_Text (Output_Object, Data.Paragraph_Kind_Title(For_Type).Str(1..Data.Paragraph_Kind_Title(For_Type).Length)); ARM_Output.End_Paragraph (Output_Object); Format_Object.Last_Paragraph_Subhead_Type := For_Type; --!!Debug: --Ada.Text_IO.Put_Line ("Write notes header"); else null; -- No subheader. We don't change the last -- subheader generated, either. end if; when Language_Design | -- "MetaRules" Ada83_Inconsistencies | -- Inconsistent83 Ada83_Incompatibilities | -- Incompatible83 Ada83_Extensions | -- Extend83 Ada83_Wording | -- DiffWord83 Ada95_Inconsistencies | -- Inconsistent95 Ada95_Incompatibilities | -- Incompatible95 Ada95_Extensions | -- Extend95 Ada95_Wording | -- DiffWord95 Ada2005_Inconsistencies | -- Inconsistent2005 Ada2005_Incompatibilities | -- Incompatible2005 Ada2005_Extensions | -- Extend2005 Ada2005_Wording | -- DiffWord2005 Ada2012_Inconsistencies | -- Inconsistent2012 Ada2012_Incompatibilities | -- Incompatible2012 Ada2012_Extensions | -- Extend2012 Ada2012_Wording => -- DiffWord2012 ARM_Output.Category_Header (Output_Object, Paragraph_Kind_Title(For_Type).Str(1..Paragraph_Kind_Title(For_Type).Length)); Format_Object.Last_Paragraph_Subhead_Type := For_Type; when Plain | Introduction | Element_Ref | Child_Ref | Usage_Note => null; -- No subheader. We don't change the last -- subheader generated, either. when Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Bare_Annotation | Wide_Above | Example_Text | Child_Example_Text | Indented_Example_Text | Code_Indented | Indent | Bulleted | Nested_Bulleted | Nested_X2_Bulleted | Display | Syntax_Display | Syntax_Indented | Syntax_Production | Hanging_Indented_1 | Hanging_Indented_2 | Hanging_Indented_3 | Hanging_Indented_4 | Title | Enumerated | Nested_Enumerated | Small | In_Table => null; -- No subheader. We don't change the last -- subheader generated, either. end case; end Make_Subhead; procedure Make_Annotation_Preface (For_Type : Paragraph_Type) is begin case For_Type is when Plain | Introduction | Syntax | Resolution | Legality | Static_Semantics | Link_Time | Run_Time | Bounded_Errors | Erroneous | Requirements | -- ImplReq Documentation | -- DocReq Metrics | Permissions | -- ImplPerm Advice | -- ImplAdvice Examples | Notes | Single_Note | Language_Design | -- "MetaRules" Ada83_Inconsistencies | -- Inconsistent83 Ada83_Incompatibilities | -- Incompatible83 Ada83_Extensions | -- Extend83 Ada83_Wording | -- DiffWord83 Ada95_Inconsistencies | -- Inconsistent95 Ada95_Incompatibilities | -- Incompatible95 Ada95_Extensions | -- Extend95 Ada95_Wording | -- DiffWord95 Ada2005_Inconsistencies | -- Inconsistent2005 Ada2005_Incompatibilities | -- Incompatible2005 Ada2005_Extensions | -- Extend2005 Ada2005_Wording | -- DiffWord2005 Ada2012_Inconsistencies | -- Inconsistent2012 Ada2012_Incompatibilities | -- Incompatible2012 Ada2012_Extensions | -- Extend2012 Ada2012_Wording => -- DiffWord2012 null; -- Not an annotation. when Reason | Ramification | Proof | Imp_Note | Corr_Change | Discussion | Honest | Glossary_Marker | Element_Ref | Child_Ref | Usage_Note => declare Format_Bold : ARM_Output.Format_Type := Format_Object.Text_Format; begin Format_Bold.Bold := True; ARM_Output.Text_Format (Output_Object, Format => Format_Bold); end; ARM_Output.Ordinary_Text (Output_Object, Text => Paragraph_Kind_Title(For_Type).Str( 1..Paragraph_Kind_Title(For_Type).Length)); ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); Format_Object.Last_Paragraph_Subhead_Type := For_Type; when Bare_Annotation => null; -- Header (if any) is generated elsewhere. when Wide_Above | Example_Text | Child_Example_Text | Indented_Example_Text | Code_Indented | Indent | Bulleted | Nested_Bulleted | Nested_X2_Bulleted | Display | Syntax_Display | Syntax_Indented | Syntax_Production | Hanging_Indented_1 | Hanging_Indented_2 | Hanging_Indented_3 | Hanging_Indented_4 | Title | Enumerated | Nested_Enumerated | Small | In_Table => null; -- Just a format. end case; end Make_Annotation_Preface; function Show_Leading_Text_for_Paragraph return Boolean is -- Returns True if the leading text (note number, -- annotation preface, etc.) should be shown for this paragraph. -- We assume that the current paragraph has a version less than -- or equal to the one that we're displaying. -- ** Note: This is not quite right. If this -- paragraph is deleted, but a following one needs the -- leading item, this will still lead the item out. -- We *do* have enough information for that, at least in the -- case of annotations: they can be marked as deleted, in -- which case we don't need them here. *But* that information -- doesn't get here in the case that we're not showing deletions. -- I can't think of a fix right now, and the note numbers need -- fixing ASAP. begin --Ada.Text_IO.Put_Line ("Show_Leading_Text, para kind: " & --ARM_Database.Paragraph_Change_Kind_Type'Image(Format_Object.Next_Paragraph_Change_Kind) & --"; version=" & Format_Object.Next_Paragraph_Version & "; on line " & Arm_Input.Line_String(Input_Object)); if (ARM_Database."/=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) and then ARM_Database."/=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) and then ARM_Database."/=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) and then ARM_Database."/=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message)) then -- Not a deleted paragraph. --Ada.Text_IO.Put_Line ("%% True - Not deleted"); return True; end if; case Format_Object.Changes is when ARM_Format.Old_Only => -- Display only the original version ('0'). if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) then --Ada.Text_IO.Put_Line ("%% True - Not original"); return False; -- Not in the original document. else --Ada.Text_IO.Put_Line ("%% True - Original"); return True; -- Probably in the original document. -- (If the paragraph numbers were "new" in a -- later version, we couldn't tell.) end if; when ARM_Format.New_Only => -- Display only the version -- Format_Object.Change_Version, no insertions or deletions. --Ada.Text_IO.Put_Line ("%% False - New only"); return False; -- This is always deleted. when ARM_Format.Changes_Only => -- Display only the the changes for version -- Format_Object.Change_Version, older changes -- are applied and newer changes are ignored. if Format_Object.Next_Paragraph_Version < Format_Object.Change_Version then -- Change version is older than we're displaying; -- no text will be shown. --Ada.Text_IO.Put_Line ("%% False - changes only, old version"); return False; -- This is always deleted. else -- The correct version. --Ada.Text_IO.Put_Line ("%% True - changes only, current version"); return True; -- Show the item, as the old text -- will be shown as deleted. end if; when ARM_Format.Show_Changes | ARM_Format.New_Changes => -- Display all of the changes up to version -- Format_Object.Change_Version, newer changes are -- ignored. (New_Changes shows deletions as a single -- character for older versions of Word, but otherwise -- is the same.) --Ada.Text_IO.Put_Line ("%% True - show changes"); return True; -- Show the item, as the old text -- will be shown as deleted. end case; end Show_Leading_Text_for_Paragraph; begin if not Format_Object.In_Paragraph then -- Output subheader, if needed. if Format_Object.Next_Paragraph_Subhead_Type /= Format_Object.Last_Paragraph_Subhead_Type then if (ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- Nothing at all should be showm. null; if Format_Object.Next_Paragraph_Subhead_Type /= Plain or else Format_Object.Next_Paragraph_Subhead_Type /= Introduction then Ada.Text_IO.Put_Line(" -- No subhead (DelNoMsg); on line " & Arm_Input.Line_String(Input_Object)); end if; elsif ((not Format_Object.Number_Paragraphs) or else Format_Object.No_Para_Num) and then (ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- Nothing at all should be showm. null; if Format_Object.Next_Paragraph_Subhead_Type /= Plain or else Format_Object.Next_Paragraph_Subhead_Type /= Introduction then Ada.Text_IO.Put_Line(" -- No subhead (Del-no paranum); on line " & Arm_Input.Line_String(Input_Object)); end if; else Make_Subhead (Format_Object.Next_Paragraph_Subhead_Type); end if; end if; -- Set the paragraph format: Set_Format (Format_Object.Next_Paragraph_Format_Type); if Format_Object.Number_Paragraphs and then not Format_Object.No_Para_Num then -- Format the paragraph number: Paragraph_Number_String (Update_Numbers => True); --Ada.Text_IO.Put_Line ("Check_Paragraph, make number " & --Format_Object.Current_Paragraph_String (1 .. Format_Object.Current_Paragraph_Len) & --": format= " & Paragraph_Type'Image(Format_Object.Next_Paragraph_Format_Type)); -- ...and start the paragraph: if (ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- Nothing at all should be showm. -- ** Warning ** If we lie here, the program will crash! Format_Object.No_Start_Paragraph := True; Ada.Text_IO.Put_Line(" -- No Start Paragraph (DelNoMsg)"); else ARM_Output.Start_Paragraph (Output_Object, Style => Format_Object.Style, Indent => Format_Object.Indent, Number => Format_Object.Current_Paragraph_String (1 .. Format_Object.Current_Paragraph_Len), No_Prefix => Format_Object.No_Prefix, Tab_Stops => Format_Object.Paragraph_Tab_Stops, No_Breaks => Format_Object.No_Breaks or Format_Object.In_Bundle, Keep_with_Next => Format_Object.Keep_with_Next or Format_Object.In_Bundle, Space_After => Format_Object.Space_After); Format_Object.No_Start_Paragraph := False; end if; if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) then -- If needed, make the "deleted text" message. -- We trust that Next_Paragraph_Change_Kind is not -- set to Deleted if the version number of the change -- is beyond the document generation version. -- (Note that Current_Change_Version may not be set, -- so it is not safe to test here.) case Format_Object.Changes is when ARM_Format.New_Only | ARM_Format.Changes_Only | ARM_Format.Show_Changes | ARM_Format.New_Changes => -- Note that we include this in the -- "Show_Changes" and "Changes_Only" versions, -- so that complete paragraph deletions are obvious, -- and also so that we can use revision bars rather than -- displaying the changes in the RM version. if ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) and then (Format_Object.Next_Paragraph_Format_Type = Enumerated or else Format_Object.Next_Paragraph_Format_Type = Nested_Enumerated or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_1 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_2 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_3 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_4) then -- We're in a hanging style, we need to end hanging first. -- Nothing else will be displayed; if we didn't end the hang this -- would end up on the same line as the next paragraph. -- It's possible that we could have a problem with -- hanging in one of the other cases if no text will be -- displayed, but there is no way to know that here. ARM_Output.End_Hang_Item (Output_Object); end if; ARM_Output.Text_Format (Output_Object, Format => (Bold => Format_Object.Text_Format.Bold, Italic => True, Font => Format_Object.Text_Format.Font, Color => Format_Object.Text_Format.Color, Change => ARM_Output.None, -- Never mark this as changed!! Version => '0', Added_Version => '0', -- Not used. Size => ARM_Output."-"(Format_Object.Text_Format.Size, 1), Location => Format_Object.Text_Format.Location)); ARM_Output.Ordinary_Text (Output_Object, Text => "This paragraph was deleted."); ARM_Output.Text_Format (Output_Object, -- Restore the format. Format => Format_Object.Text_Format); when ARM_Format.Old_Only => null; -- Not deleted. end case; end if; Format_Object.In_Paragraph := True; Format_Object.Last_Non_Space := False; else -- No paragraph numbers (or if the paragraph -- number has been suppressed with @NoParaNum): --Ada.Text_IO.Put_Line ("Check_Paragraph, no number: format= " & Paragraph_Type'Image(Format_Object.Next_Paragraph_Format_Type) & -- " output style= " & ARM_Output.Paragraph_Style_Type'Image(Format_Object.Style)); -- Start the paragraph: if (ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- Nothing at all should be showm. -- ** Warning ** If we lie here, the program will crash! Format_Object.No_Start_Paragraph := True; Ada.Text_IO.Put_Line(" -- No Start Paragraph (Del-NewOnly)"); else ARM_Output.Start_Paragraph (Output_Object, Style => Format_Object.Style, Indent => Format_Object.Indent, Number => "", No_Prefix => Format_Object.No_Prefix, Tab_Stops => Format_Object.Paragraph_Tab_Stops, No_Breaks => Format_Object.No_Breaks or Format_Object.In_Bundle, Keep_with_Next => Format_Object.Keep_with_Next or Format_Object.In_Bundle, Space_After => Format_Object.Space_After); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; Format_Object.Current_Paragraph_Len := 0; -- Empty paragraph number. Format_Object.No_Para_Num := False; end if; end if; if not Format_Object.No_Prefix then if Format_Object.Next_Paragraph_Format_Type = Notes and then Show_Leading_Text_for_Paragraph then if not Format_Object.Use_ISO_2004_Note_Format then -- Output the note number (Ada95 format). declare NNum : constant String := Integer'Image(Format_Object.Next_Note); begin ARM_Output.Ordinary_Text (Output_Object, NNum(2..NNum'Last)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Format_Object.Next_Note := Format_Object.Next_Note + 1; end; else -- Output the note header (ISO 2004 format). declare NNum : constant String := Integer'Image(Format_Object.Next_Note); begin ARM_Output.Ordinary_Text (Output_Object, "NOTE " & NNum(2..NNum'Last)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Format_Object.Next_Note := Format_Object.Next_Note + 1; end; end if; elsif Format_Object.Next_Paragraph_Format_Type = Single_Note and then Show_Leading_Text_for_Paragraph then if not Format_Object.Use_ISO_2004_Note_Format then -- No note number, and nothing else needed. null; else -- Output the note header (ISO 2004 format) -- without a number. ARM_Output.Ordinary_Text (Output_Object, "NOTE"); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); end if; elsif (Format_Object.Next_Paragraph_Format_Type = Enumerated or else Format_Object.Next_Paragraph_Format_Type = Nested_Enumerated) and then Show_Leading_Text_for_Paragraph then -- Output the item number. if Format_Object.Use_ISO_2004_Note_Format then if Format_Object.Enumerated_Level <= 1 then -- Outer list. -- Lower case letters for list: ARM_Output.Ordinary_Text (Output_Object, Character'Val ((Format_Object.Next_Enumerated_Num - 1) + Character'Pos ('a')) & ')'); ARM_Output.End_Hang_Item (Output_Object); Format_Object.Next_Enumerated_Num := Format_Object.Next_Enumerated_Num + 1; else -- numbered. declare NNum : constant String := Integer'Image(Format_Object.Next_Enumerated_Num); begin ARM_Output.Ordinary_Text (Output_Object, NNum(2..NNum'Last) & ')'); ARM_Output.End_Hang_Item (Output_Object); Format_Object.Next_Enumerated_Num := Format_Object.Next_Enumerated_Num + 1; end; end if; else -- Ada 95 lists. declare NNum : constant String := Integer'Image(Format_Object.Next_Enumerated_Num); begin ARM_Output.Ordinary_Text (Output_Object, NNum(2..NNum'Last) & '.'); ARM_Output.End_Hang_Item (Output_Object); Format_Object.Next_Enumerated_Num := Format_Object.Next_Enumerated_Num + 1; end; end if; end if; else -- No prefix marked, meaning no number. Format_Object.No_Prefix := False; -- Reset. end if; Format_Object.Last_Non_Space := False; Format_Object.Keep_with_Next := False; -- Reset for next paragraph. Format_Object.Space_After := ARM_Output.Normal; -- Reset for next paragraph. -- Output the annotation preface, if needed. if Format_Object.Next_Paragraph_Subhead_Type /= Format_Object.Last_Paragraph_Subhead_Type then if Show_Leading_Text_for_Paragraph then Make_Annotation_Preface (Format_Object.Next_Paragraph_Subhead_Type); end if; end if; if Format_Object.References /= null then -- We assume these are only stored here if we want to see -- them on *this* paragraph. Thus, we just output them if -- they exist here. Note: This deallocates the references -- after writing them. if Format_Object.No_Start_Paragraph then -- Oh-oh! Can't generate references; there aren't -- supposed to be any at this point. Ada.Text_IO.Put_Line ("** References generated for no display paragraph; line " & ARM_Input.Line_String (Input_Object)); else Make_References (Format_Object.References, Format_Object, Output_Object); end if; end if; -- Reset the "next" paragraph kind and version (we have to -- wait, so that we can use this to determine whether -- note numbers and things are output): Format_Object.Next_Paragraph_Change_Kind := ARM_Database.None; Format_Object.Next_Paragraph_Version := '0'; -- else already in a paragraph. end if; end Check_Paragraph; procedure Check_End_Paragraph is -- Check for the end of a paragraph; closing it if necessary. -- We will never be in a paragraph after this routine. begin if Format_Object.In_Paragraph then if not Format_Object.No_Start_Paragraph then ARM_Output.End_Paragraph (Output_Object); --else Ada.Text_IO.Put_Line("No Start Paragraph, so no End Paragraph"); end if; Format_Object.In_Paragraph := False; Format_Object.No_Start_Paragraph := False; Format_Object.No_Para_Num := False; -- Make sure any "leftover" -- NoParaNums are cleared; we don't want this lasting into -- the next paragraph. if Format_Object.In_Change then Ada.Text_IO.Put_Line ("** Paragraph end while in change; line " & ARM_Input.Line_String (Input_Object)); Format_Object.In_Change := False; end if; -- Check command stack for any open formatting commands, -- and complain (these won't be closed properly and chaos -- may result): for I in reverse 1 .. Format_State.Nesting_Stack_Ptr loop if Format_State.Nesting_Stack (I).Command in Bold .. Tab_Set then -- There is a formatting command active. -- (Note: not all of these can be on the stack.) Ada.Text_IO.Put_Line ("** Paragraph end while in formatting command " & Data.Command_Type'Image(Format_State.Nesting_Stack (I).Command) & "; line " & ARM_Input.Line_String (Input_Object)); exit; end if; end loop; end if; end Check_End_Paragraph; type DIE_Kind is (None, Is_Root, Is_Partial); procedure Display_Index_Entry (Term_Text : in String; Special : in DIE_Kind := None) is -- If necessary, display the index entry for Term_Text. Is_AARM : constant Boolean := Is_AARM_Paragraph (Format_Object.Next_Paragraph_Subhead_Type); use type ARM_Output.Size_Type; begin if Format_Object.Display_Index_Entries then Check_Paragraph; if not Is_AARM then ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => -1, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); end if; ARM_Output.Ordinary_Character (Output_Object, '{'); if not Is_AARM then ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => True, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => -1, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); else ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => True, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => 0, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); end if; ARM_Output.Ordinary_Text (Output_Object, ARM_Index.Clean(Term_Text, Remove_Soft_Hyphens => True)); if not Is_AARM then ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => -1, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); else ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => 0, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); end if; case Special is when None => null; when Is_Root => ARM_Output.Ordinary_Text (Output_Object, " [distributed]"); when Is_Partial => ARM_Output.Ordinary_Text (Output_Object, " [partial]"); end case; ARM_Output.Ordinary_Character (Output_Object, '}'); if not Is_AARM then ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Color => ARM_Output.Default, Size => 0, Change => Format_Object.Text_Format.Change, Version => Format_Object.Text_Format.Version, Added_Version => Format_Object.Text_Format.Added_Version, Location => ARM_Output.Normal)); end if; ARM_Output.Ordinary_Character (Output_Object, ' '); Format_Object.Last_Non_Space := False; -- else not displayed. end if; end Display_Index_Entry; procedure Parse_Tab_Stops (Stops : in String; Tabs : in out ARM_Output.Tab_Info) is -- Parse "Stops" as a tab string; store the result in Tabs. Loc : Natural := Stops'First; begin -- Parse tab stops: -- ::= -- ::= L | P -- ::= {, } while Loc <= Stops'Length loop Tabs.Number := Tabs.Number + 1; if Stops(Loc) = 'l' or Stops(Loc) = 'L' then Tabs.Stops(Tabs.Number).Kind := ARM_Output.Left_Fixed; Loc := Loc + 1; elsif Stops(Loc) = 'p' or Stops(Loc) = 'P' then Tabs.Stops(Tabs.Number).Kind := ARM_Output.Left_Proportional; Loc := Loc + 1; else -- Default: Tabs.Stops(Tabs.Number).Kind := ARM_Output.Left_Fixed; end if; while Loc <= Stops'Length loop if Stops(Loc) in '0' .. '9' then Tabs.Stops(Tabs.Number).Stop := Tabs.Stops(Tabs.Number).Stop * 10 + Character'Pos(Stops(Loc)) - Character'Pos('0'); Loc := Loc + 1; else exit; -- Number ended. end if; end loop; if Tabs.Stops(Tabs.Number).Stop = 0 then Tabs.Number := Tabs.Number - 1; Ada.Text_IO.Put_Line (" ** Bad tab stop format, position" & Natural'Image(Loc) & " in [" & Stops & "] from line " & ARM_Input.Line_String (Input_Object)); exit; -- Give up on this tabset. elsif Tabs.Number < 1 and then Tabs.Stops(Tabs.Number-1).Stop >= Tabs.Stops(Tabs.Number).Stop then Tabs.Number := Tabs.Number - 1; Ada.Text_IO.Put_Line (" ** Bad tab stop, less than previous, at position" & Natural'Image(Loc) & " in [" & Stops & "] from line " & ARM_Input.Line_String (Input_Object)); exit; -- Give up on this tabset. end if; if Loc > Stops'Length then exit; -- Finished. elsif Stops(Loc) = ',' then Loc := Loc + 1; if Loc > Stops'Length then Ada.Text_IO.Put_Line (" ** Bad tab stop set format, ends with comma in [" & Stops & "] from line " & ARM_Input.Line_String (Input_Object)); exit; -- Give up on this tabset. end if; end if; -- Skip any blanks in between. while Loc <= Stops'Length and then Stops(Loc) = ' ' loop Loc := Loc + 1; end loop; end loop; end Parse_Tab_Stops; procedure Write_Subindex ( Subindex_Object : in out ARM_Subindex.Subindex_Type; Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class; Minimize_Lines : in Boolean) is -- Writes a subindex for the document. begin Check_End_Paragraph; -- Insert a blank paragraph: ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Normal, Indent => 0, Number => ""); ARM_Output.Hard_Space (Output_Object); ARM_Output.End_Paragraph (Output_Object); ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 2); ARM_Subindex.Write_Subindex ( Subindex_Object, Output_Object, Use_Paragraphs => Format_Object.Number_Paragraphs, Minimize_Lines => Minimize_Lines); ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 1); -- Not in a paragraph here, either. end Write_Subindex; procedure Simple_Subindex_Item ( Subindex_Object : in out ARM_Subindex.Subindex_Type; Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class; Entity_Kind_Name : in String) is -- Create a simple subindex item; the command has a single -- parameter . -- Create an "In_Unit" entry for the item; -- Also create two regular index entries: -- One for with a secondary entry of "@i{in} " -- (where Unit is the unit saved by a previous RootLibUnit or -- ChildUnit.), -- and a Second (only for version < 2 and if the entity name is -- non-null) for -- "Language-Defined " with a -- secondary entry of " @i{in} ". -- Also outputs the parameter to the output file. Entity : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key := ARM_Index.Get_Key; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Entity, Len); -- Determine what to do with the "Language-Defined" entry: Calc_Change_Disposition ( Format_Object => Format_Object, Version => '2', Operation => ARM_Output.Deletion, Text_Kind => Disposition); if Entity_Kind_Name'Length = 0 or else Disposition = Do_Not_Display_Text then null; -- Ignore this. elsif Disposition = ARM_Output.None then -- Normal reference: ARM_Index.Add_Reusing_Key ( Term => "Language-Defined " & Entity_Kind_Name, Subterm => Entity(1..Len) & " in " & Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Index.SubDeclaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); -- Note that the Subdeclaration type changes the -- "in" into italics. elsif Disposition = ARM_Output.Deletion then null; -- Ignore this (no change info in the index). else -- Insertion. raise Program_Error; -- An insertion inside of a deletion command! end if; Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); if Format_Object.Unit_Len = 0 then Ada.Text_IO.Put_Line ("** No unit defined for index entry expecting one on line " & ARM_Input.Line_String (Input_Object)); ARM_Index.Add_Reusing_Key ( Term => Entity(1..Len), Subterm => "*unknown*", Kind => ARM_Index.Declaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Subindex_Object, Entity => Entity(1..Len), From_Unit => "*unknown*", Kind => ARM_Subindex.In_Unit, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); else ARM_Index.Add_Reusing_Key ( Term => Entity(1..Len), Subterm => Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Index.Declaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Subindex_Object, Entity => Entity(1..Len), From_Unit => Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Subindex.In_Unit, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); end if; ARM_Output.Ordinary_Text (Output_Object, Entity(1..Len)); Format_Object.Last_Non_Space := True; end Simple_Subindex_Item; procedure Child_Unit ( Subindex_Object : in out ARM_Subindex.Subindex_Type; Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class) is -- Generates three index entries: An index entry for , with -- a secondary of "@i{child of} ", an index entry for -- "Language-Defined Library Units" with a secondary entry of -- ., and an index entry for .. The -- Unit is set to .. (For version 2 or later, the -- Language-Defined entry is not generated.) The first entry is -- added to the subindex list as well. Close_Ch : Character; Parent, Child : String(1..80); PLen, CLen : Natural := 0; Key : ARM_Index.Index_Key := ARM_Index.Get_Key; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Parent" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Parent, PLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Child" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Child, CLen); -- else no parameter. Weird. end if; -- Set the current unit for future use: Format_Object.Unit_Len := PLen + CLen + 1; Format_Object.Unit (1..Format_Object.Unit_Len) := Parent(1..PLen) & '.' & Child(1..CLen); ARM_Index.Add_Reusing_Key ( Term => Child(1..CLen), Subterm => Parent(1..PLen), Kind => ARM_Index.Child_Unit_Parent, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); -- Determine what to do with the "Language-Defined" entry: Calc_Change_Disposition ( Format_Object => Format_Object, Version => '2', Operation => ARM_Output.Deletion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then null; -- Ignore this. elsif Disposition = ARM_Output.None then -- Make reference: ARM_Index.Add_Reusing_Key ( Term => "Language-Defined Library Units", Subterm => Parent(1..PLen) & '.' & Child(1..CLen), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); elsif Disposition = ARM_Output.Deletion then null; -- Ignore this (no change info in the index). else -- Insertion. raise Program_Error; -- An insertion inside of a deletion command! end if; ARM_Index.Add_Reusing_Key ( Term => Parent(1..PLen) & '.' & Child(1..CLen), Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Subindex_Object, Entity => Child(1..CLen), From_Unit => Parent(1..PLen), Kind => ARM_Subindex.Child_of_Parent, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); -- Leave the command end marker, let normal processing -- get rid of it. end Child_Unit; procedure Process_Begin is -- Process a "begin". The "begin" has been stacked. procedure Toss_for_RM (Paragraph_Kind_Name : in String) is -- Call this for AARM-only sections. -- It skips *everything* until the matching end. This includes -- index references, section references, and the like. Anything -- that ought to be in the RM should be moved outside of the -- AARM specific code. Thus, we can use a fairly simple text -- skip. Ch : Character; Close_Ch : Character; Command_Name : ARM_Input.Command_Name_Type; begin -- Skip everything up to the next @end{ True); -- Get the command name. if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Command_Name, Ada.Strings.Right)) /= "end" then -- Not an "end" command, keep going. null; else -- An End command, check if this is the one we want: ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Close_Ch := ARM_Input.Get_Close_Char (Ch); Arm_Input.Get_Name (Input_Object, Command_Name); -- Get the end "type". if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Command_Name, Ada.Strings.Right)) /= Paragraph_Kind_Name then null; -- Wrong end, keep going. else -- Right end! -- Skip to the close character: while Ch /= Close_Ch loop ARM_Input.Get_Char (Input_Object, Ch); end loop; -- Unstack the "begin". Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (End AARM-Only)"); -- And we're done with this "begin". return; end if; else -- No parameter, forget it. null; end if; end if; end loop; end Toss_for_RM; begin Check_End_Paragraph; -- End any paragraph that we're in. if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "comment" then Toss_for_RM ("comment"); -- Format only: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "wideabove" then Format_Object.Next_Paragraph_Format_Type := Wide_Above; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "example" then Format_Object.Next_Paragraph_Format_Type := Example_Text; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "childexample" then Format_Object.Next_Paragraph_Format_Type := Child_Example_Text; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "descexample" then Format_Object.Next_Paragraph_Format_Type := Indented_Example_Text; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "describecode" then Format_Object.Next_Paragraph_Format_Type := Code_Indented; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "indent" then Format_Object.Next_Paragraph_Format_Type := Indent; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "itemize" then Format_Object.Next_Paragraph_Format_Type := Bulleted; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "inneritemize" then Format_Object.Next_Paragraph_Format_Type := Nested_Bulleted; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "innerinneritemize" then Format_Object.Next_Paragraph_Format_Type := Nested_X2_Bulleted; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "display" then Format_Object.Next_Paragraph_Format_Type := Display; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "syntaxdisplay" then Format_Object.Next_Paragraph_Format_Type := Syntax_Display; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "syntaxtext" then Format_Object.Next_Paragraph_Format_Type := Syntax_Indented; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "description" then Format_Object.Next_Paragraph_Format_Type := Hanging_Indented_3; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "small" then Format_Object.Next_Paragraph_Format_Type := Small; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "enumerate" then Format_Object.Next_Paragraph_Format_Type := Enumerated; Format_Object.Next_Enumerated_Num := 1; Format_Object.Enumerated_Level := Format_Object.Enumerated_Level + 1; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "innerenumerate" then Format_Object.Next_Paragraph_Format_Type := Nested_Enumerated; Format_Object.Next_Enumerated_Num := 1; Format_Object.Enumerated_Level := Format_Object.Enumerated_Level + 1; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "hang1list" then Format_Object.Next_Paragraph_Format_Type := Hanging_Indented_1; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "hang2list" then Format_Object.Next_Paragraph_Format_Type := Hanging_Indented_2; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "hang3list" then Format_Object.Next_Paragraph_Format_Type := Hanging_Indented_3; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "hang4list" then Format_Object.Next_Paragraph_Format_Type := Hanging_Indented_4; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "title" then Format_Object.Next_Paragraph_Format_Type := Title; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "bundle" then -- Should prevent any page breaks until the "end". Not -- implemented currently. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; -- Leave the format alone. Format_Object.In_Bundle := True; -- We don't need to stack this, -- because once we're in it, we can't leave it until the @End. elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "twocol" then -- Two column; no affect on format. ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 2); Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "fourcol" then -- Four column; no affect on format. ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 4); Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; -- RM groupings: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "intro" then Format_Object.Next_Paragraph_Format_Type := Introduction; Format_Object.Next_Paragraph_Subhead_Type := Introduction; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "syntax" then Format_Object.Next_Paragraph_Format_Type := Syntax; Format_Object.Next_Paragraph_Subhead_Type := Syntax; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "resolution" then Format_Object.Next_Paragraph_Format_Type := Resolution; Format_Object.Next_Paragraph_Subhead_Type := Resolution; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "legality" then Format_Object.Next_Paragraph_Format_Type := Legality; Format_Object.Next_Paragraph_Subhead_Type := Legality; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "staticsem" then Format_Object.Next_Paragraph_Format_Type := Static_Semantics; Format_Object.Next_Paragraph_Subhead_Type := Static_Semantics; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "linktime" then Format_Object.Next_Paragraph_Format_Type := Link_Time; Format_Object.Next_Paragraph_Subhead_Type := Link_Time; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "runtime" then Format_Object.Next_Paragraph_Format_Type := Run_Time; Format_Object.Next_Paragraph_Subhead_Type := Run_Time; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "bounded" then Format_Object.Next_Paragraph_Format_Type := Bounded_Errors; Format_Object.Next_Paragraph_Subhead_Type := Bounded_Errors; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "erron" then Format_Object.Next_Paragraph_Format_Type := Erroneous; Format_Object.Next_Paragraph_Subhead_Type := Erroneous; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "implreq" then Format_Object.Next_Paragraph_Format_Type := Requirements; Format_Object.Next_Paragraph_Subhead_Type := Requirements; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "docreq" then Format_Object.Next_Paragraph_Format_Type := Documentation; Format_Object.Next_Paragraph_Subhead_Type := Documentation; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "metrics" then Format_Object.Next_Paragraph_Format_Type := Metrics; Format_Object.Next_Paragraph_Subhead_Type := Metrics; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "implperm" then Format_Object.Next_Paragraph_Format_Type := Permissions; Format_Object.Next_Paragraph_Subhead_Type := Permissions; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "impladvice" then Format_Object.Next_Paragraph_Format_Type := Advice; Format_Object.Next_Paragraph_Subhead_Type := Advice; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "examples" then Format_Object.Next_Paragraph_Format_Type := Examples; Format_Object.Next_Paragraph_Subhead_Type := Examples; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "notes" then Format_Object.Next_Paragraph_Format_Type := Notes; Format_Object.Next_Paragraph_Subhead_Type := Notes; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "singlenote" then Format_Object.Next_Paragraph_Format_Type := Single_Note; Format_Object.Next_Paragraph_Subhead_Type := Single_Note; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "rmonly" then if Format_Object.Include_Annotations then -- AARM, but this is RM-only. Toss_for_RM ("rmonly"); else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; -- Leave the format alone. end if; -- NotISO text: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "notiso" then if Format_Object.Include_ISO then Toss_for_RM ("notiso"); -- This text does not appear in ISO documents. else -- not ISO Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; -- Leave the format alone. end if; --!!Debug: ---Ada.Text_IO.Put_Line ("Next=" & Paragraph_Type'Image(Format_Object.Next_Paragraph_Subhead_Type)); -- ISOOnly text: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "isoonly" then if Format_Object.Include_ISO then Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Is_Formatting := False; -- Leave the format alone. else -- Not ISO Toss_for_RM ("isoonly"); -- This text does not appear in non-ISO documents. end if; -- AARM groupings: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "metarules" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Language_Design; Format_Object.Next_Paragraph_Subhead_Type := Language_Design; else -- Don't show annotations. Toss_for_RM ("metarules"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "inconsistent83" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada83_Inconsistencies; Format_Object.Next_Paragraph_Subhead_Type := Ada83_Inconsistencies; else -- Don't show annotations. Toss_for_RM ("inconsistent83"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "incompatible83" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada83_Incompatibilities; Format_Object.Next_Paragraph_Subhead_Type := Ada83_Incompatibilities; else -- Don't show annotations. Toss_for_RM ("incompatible83"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "extend83" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada83_Extensions; Format_Object.Next_Paragraph_Subhead_Type := Ada83_Extensions; else -- Don't show annotations. Toss_for_RM ("extend83"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "diffword83" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada83_Wording; Format_Object.Next_Paragraph_Subhead_Type := Ada83_Wording; else -- Don't show annotations. Toss_for_RM ("diffword83"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "inconsistent95" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada95_Inconsistencies; Format_Object.Next_Paragraph_Subhead_Type := Ada95_Inconsistencies; else -- Don't show annotations. Toss_for_RM ("inconsistent95"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "incompatible95" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada95_Incompatibilities; Format_Object.Next_Paragraph_Subhead_Type := Ada95_Incompatibilities; else -- Don't show annotations. Toss_for_RM ("incompatible95"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "extend95" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada95_Extensions; Format_Object.Next_Paragraph_Subhead_Type := Ada95_Extensions; else -- Don't show annotations. Toss_for_RM ("extend95"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "diffword95" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada95_Wording; Format_Object.Next_Paragraph_Subhead_Type := Ada95_Wording; else -- Don't show annotations. Toss_for_RM ("diffword95"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "inconsistent2005" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2005_Inconsistencies; Format_Object.Next_Paragraph_Subhead_Type := Ada2005_Inconsistencies; else -- Don't show annotations. Toss_for_RM ("inconsistent2005"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "incompatible2005" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2005_Incompatibilities; Format_Object.Next_Paragraph_Subhead_Type := Ada2005_Incompatibilities; else -- Don't show annotations. Toss_for_RM ("incompatible2005"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "extend2005" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2005_Extensions; Format_Object.Next_Paragraph_Subhead_Type := Ada2005_Extensions; else -- Don't show annotations. Toss_for_RM ("extend2005"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "diffword2005" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2005_Wording; Format_Object.Next_Paragraph_Subhead_Type := Ada2005_Wording; else -- Don't show annotations. Toss_for_RM ("diffword2005"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "inconsistent2012" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2012_Inconsistencies; Format_Object.Next_Paragraph_Subhead_Type := Ada2012_Inconsistencies; else -- Don't show annotations. Toss_for_RM ("inconsistent2012"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "incompatible2012" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2012_Incompatibilities; Format_Object.Next_Paragraph_Subhead_Type := Ada2012_Incompatibilities; else -- Don't show annotations. Toss_for_RM ("incompatible2012"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "extend2012" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2012_Extensions; Format_Object.Next_Paragraph_Subhead_Type := Ada2012_Extensions; else -- Don't show annotations. Toss_for_RM ("extend2012"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "diffword2012" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ada2012_Wording; Format_Object.Next_Paragraph_Subhead_Type := Ada2012_Wording; else -- Don't show annotations. Toss_for_RM ("diffword2012"); end if; -- ASIS groupings: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "elementref" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Element_Ref; Format_Object.Next_Paragraph_Subhead_Type := Element_Ref; else -- Don't show annotations. Toss_for_RM ("elementref"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "childref" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Child_Ref; Format_Object.Next_Paragraph_Subhead_Type := Child_Ref; else -- Don't show annotations. Toss_for_RM ("childref"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "usagenote" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Usage_Note; Format_Object.Next_Paragraph_Subhead_Type := Usage_Note; else -- Don't show annotations. Toss_for_RM ("usagenote"); end if; -- AARM annotations: elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "discussion" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Discussion; Format_Object.Next_Paragraph_Subhead_Type := Discussion; else -- Don't show annotations. Toss_for_RM ("discussion"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "reason" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Reason; Format_Object.Next_Paragraph_Subhead_Type := Reason; else -- Don't show annotations. Toss_for_RM ("reason"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "ramification" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Ramification; Format_Object.Next_Paragraph_Subhead_Type := Ramification; else -- Don't show annotations. Toss_for_RM ("ramification"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "theproof" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Proof; Format_Object.Next_Paragraph_Subhead_Type := Proof; else -- Don't show annotations. Toss_for_RM ("theproof"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "implnote" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Imp_Note; Format_Object.Next_Paragraph_Subhead_Type := Imp_Note; else -- Don't show annotations. Toss_for_RM ("implnote"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "honest" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Honest; Format_Object.Next_Paragraph_Subhead_Type := Honest; else -- Don't show annotations. Toss_for_RM ("honest"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "glossarymarker" then if Format_Object.Include_Annotations then Format_Object.Next_Paragraph_Format_Type := Glossary_Marker; Format_Object.Next_Paragraph_Subhead_Type := Glossary_Marker; else -- Don't show annotations. Toss_for_RM ("glossarymarker"); end if; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right)) = "aarmonly" then if Format_Object.Include_Annotations then null; -- Leave the format alone. else -- Don't show annotations. Toss_for_RM ("aarmonly"); end if; else Ada.Text_IO.Put_Line (" -- Unknown 'begin' type - " & Ada.Strings.Fixed.Trim (Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; end Process_Begin; procedure Process_Command_with_Parameter is -- Process the start of a command with a parameter. -- The parameter character has been processed, and -- a stack item pushed. function Get_NT return String is -- Local routine: -- Return the "current" non-terminal from -- the Syntax_NT string. Handles @Chg. begin return Get_Current_Item (Format_Object, Input_Object, Format_Object.Syntax_NT (1 .. Format_Object.Syntax_NT_Len)); end Get_NT; function Get_Old_NT return String is -- Local routine: -- Return the "current" non-terminal from -- the Syntax_NT string. Handles @Chg. begin return Get_Old_Item (Format_Object, Input_Object, Format_Object.Syntax_NT (1 .. Format_Object.Syntax_NT_Len)); end Get_Old_NT; procedure Get_Change_Version (Is_First : in Boolean; Version : out Character) is -- Get a parameter named "Version", -- containing a character representing the version number. Ch, Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Version" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => Is_First, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the version character: ARM_Input.Get_Char (Input_Object, Version); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for change version on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; end Get_Change_Version; procedure Get_Change_Kind (Kind : out ARM_Database.Paragraph_Change_Kind_Type) is -- Get a parameter named "Kind", containing a word representing -- a change kind. Kind_Name : ARM_Input.Command_Name_Type; Ch, Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Kind" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the kind word: Arm_Input.Get_Name (Input_Object, Kind_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for change kind on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "revised" then Kind := ARM_Database.Revised; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "revisedadded" then Kind := ARM_Database.Revised_Inserted_Number; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "added" then Kind := ARM_Database.Inserted; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "addednormal" then Kind := ARM_Database.Inserted_Normal_Number; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "deleted" then Kind := ARM_Database.Deleted; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "deletedadded" then Kind := ARM_Database.Deleted_Inserted_Number; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "deletednodelmsg" then Kind := ARM_Database.Deleted_No_Delete_Message; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right)) = "deletedaddednodelmsg" then Kind := ARM_Database.Deleted_Inserted_Number_No_Delete_Message; else Ada.Text_IO.Put_Line (" ** Bad kind for change kind: " & Ada.Strings.Fixed.Trim (Kind_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; -- else no parameter. Weird. end if; end Get_Change_Kind; procedure Get_Boolean (Param_Name : in ARM_Input.Command_Name_Type; Result : out Boolean) is -- Get a boolean value from a parameter named Param_Name. Ch, Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => Param_Name, Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the Boolean character: ARM_Input.Get_Char (Input_Object, Ch); case Ch is when 'F' | 'f' | 'N' | 'n' => Result := False; when 'T' | 't' | 'Y' | 'y' => Result := True; when others => Ada.Text_IO.Put_Line (" ** Bad value for boolean parameter " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end case; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for boolean parameter " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; end Get_Boolean; procedure Gen_Ref_or_ARef_Parameter (Display_It : Boolean) is -- Generate (and read) a "Ref" or "ARef" parameter, containing -- a DR or AI reference. Generate it into the document only -- if Display_It is True. Ch, Close_Ch : Character; Ref_Name : ARM_Input.Command_Name_Type; Len : Natural; Which_Param : ARM_Input.Param_Num; New_Ref, Cursor : Reference_Ptr; begin ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "Ref" & (4..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "ARef" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the reference: Len := 0; loop ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Len := Len + 1; if Len > Ref_Name'Last then Ada.Text_IO.Put_Line (" ** Reference too long on line " & ARM_Input.Line_String (Input_Object)); else Ref_Name(Len) := Ch; end if; else -- End of the reference. if Len = 0 then Ada.Text_IO.Put_Line (" ** Failed to find reference on line " & ARM_Input.Line_String (Input_Object)); end if; exit; end if; end loop; if Display_It then -- Save a reference for outputting on the next -- paragraph start. New_Ref := Allocate_Reference; New_Ref.all := (Ref_Name => Ref_Name, Ref_Len => Len, Is_DR_Ref => (Which_Param = 1), -- DR reference if Param = 1; -- AI reference otherwise. Next => null); -- Attach this to the *end* of the list. if Format_Object.References = null then Format_Object.References := New_Ref; else Cursor := Format_Object.References; while Cursor.Next /= null loop Cursor := Cursor.next; end loop; Cursor.Next := New_Ref; end if; -- else don't display it. end if; -- else no parameter. Weird. end if; end Gen_Ref_or_ARef_Parameter; procedure Gen_Chg_xxxx (Param_Cmd : in Data.Command_Type; AARM_Prefix : in String) is -- Implement chgimpdef, chgimpladv, chgdocreq, and -- chgaspectdesc commands. -- The AARM prefix (if needed) is AARM_Prefix, and -- the parameter command is Param_Cmd. -- This command is of the form: -- @chgxxxxx{Version=[], Kind=(), -- Text=()}} -- where is a single character, is one -- of Revised, Added, or Deleted, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. Close_Ch : Character; Kind : ARM_Database.Paragraph_Change_Kind_Type; Version : ARM_Contents.Change_Version_Type; Display_It : Boolean; use type ARM_Database.Paragraph_Change_Kind_Type; Local_Change : ARM_Output.Change_Type; Skip_Header : Boolean := False; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". Get_Change_Kind (Kind); -- Read a parameter named "Kind". if Format_Object.Impdef_Info.Command /= None then Ada.Text_IO.Put_Line (" ** Nested impdef entry on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; -- Setup impdef information for this command: case Param_Cmd is when Change_Impdef_Text_Param => Format_Object.Impdef_Info := (Command => Impdef, Change_Kind => <>, -- Set below. Version => <>, -- Set below. Initial_Version => Version, -- Until we decide differently. Add_to_DB => True, -- Until we decide differently. Paragraph_String => <>, -- Set below. Paragraph_Len => <>);-- Set below. when Change_Docreq_Text_Param => Format_Object.Impdef_Info := (Command => Docreq, Change_Kind => <>, -- Set below. Version => <>, -- Set below. Initial_Version => Version, -- Until we decide differently. Add_to_DB => True, -- Until we decide differently. Paragraph_String => <>, -- Set below. Paragraph_Len => <>);-- Set below. when Change_Impladv_Text_Param => Format_Object.Impdef_Info := (Command => Impladv, Change_Kind => <>, -- Set below. Version => <>, -- Set below. Initial_Version => Version, -- Until we decide differently. Add_to_DB => True, -- Until we decide differently. Paragraph_String => <>, -- Set below. Paragraph_Len => <>);-- Set below. when Change_AspectDesc_Text_Param => Format_Object.Impdef_Info := (Command => Aspect, Change_Kind => <>, -- Set below. Version => <>, -- Set below. Initial_Version => Version, -- Until we decide differently. Add_to_DB => True, -- Until we decide differently. Aspect_Name => <>, -- Set below. Aspect_Name_Len => <>, -- Set below. Paragraph_String => <>, -- Set below. Paragraph_Len => <>);-- Set below. when others => raise Program_Error; -- Wrong kind of command passed in. end case; -- Check for the optional "InitialVersion" parameter, -- and the not optional, but only used for some commands -- "Aspect" parameter, stopping when we reach Text: -- Note: If there is no InitialVersion command, use the same -- version of the rest of the command (which was set when the -- Info was created). declare Which_Param : ARM_Input.Param_Num; Ch : Character; Saw_Aspect : Boolean := False; begin loop ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "InitialVersion" & (15..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "Aspect" & (7..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_3 => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if Which_Param = 1 and then Close_Ch /= ' ' then -- Found InitialVersion ARM_Input.Get_Char (Input_Object, Ch); Format_Object.Impdef_Info.Initial_Version := Ch; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for InitialVersion parameter on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; elsif Which_Param = 2 and then Close_Ch /= ' ' then -- Found Aspect parameter. Saw_Aspect := True; -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Impdef_Info.Aspect_Name, Format_Object.Impdef_Info.Aspect_Name_Len); else -- We found "Text" (or an error) exit; -- Handling of Text is below. end if; end loop; if Format_Object.Impdef_Info.Command = Aspect then if not Saw_Aspect then Ada.Text_IO.Put_Line (" ** Missing Aspect parameter on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; else -- Not aspect. if Saw_Aspect then Ada.Text_IO.Put_Line (" ** Aspect parameter on non-aspect command on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; end if; end; --Ada.Text_IO.Put_Line ("Gen_Chg_xxxx, Kind=" & --ARM_Database.Paragraph_Change_Kind_Type'Image(Kind) & --"; version=" & Version & "; InitVer=" & Format_Object.Impdef_Initial_Version); if (Kind = ARM_Database.Inserted or else Kind = ARM_Database.Inserted_Normal_Number) then Calc_Change_Disposition (Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Local_Change); --Ada.Text_IO.Put_Line (" Insert, Local_Change=" & --ARM_Output.Change_Type'Image(Local_Change)); case Local_Change is when Do_Not_Display_Text => Display_It := False; Local_Change := ARM_Output.None; Format_Object.Impdef_Info.Add_to_DB := False; -- Do not add to the database, or display anything. when ARM_Output.None|ARM_Output.Insertion => Format_Object.Impdef_Info.Version := Version; Format_Object.Impdef_Info.Change_Kind := Kind; Display_It := Format_Object.Include_Annotations; -- Show impdef notes only if we're showing annotations. when ARM_Output.Deletion => raise Program_Error; end case; elsif Kind = ARM_Database.Deleted or else Kind = ARM_Database.Deleted_Inserted_Number or else Kind = ARM_Database.Deleted_No_Delete_Message or else Kind = ARM_Database.Deleted_Inserted_Number_No_Delete_Message then Calc_Change_Disposition (Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Deletion, Text_Kind => Local_Change); --Ada.Text_IO.Put_Line (" Delete, Local_Change=" & --ARM_Output.Change_Type'Image(Local_Change)); case Local_Change is when Do_Not_Display_Text => --Display_It := False; -- We need to show the paragraph, without its header, -- so that we get a proper "this paragraph is deleted" -- message (if one is needed). Nothing will actually -- be output in this case. Local_Change := ARM_Output.None; Skip_Header := True; Format_Object.Impdef_Info.Version := Version; Format_Object.Impdef_Info.Change_Kind := Kind; Display_It := Format_Object.Include_Annotations; -- Show impdef notes only if we're showing annotations. Format_Object.Impdef_Info.Add_to_DB := True; -- This will add deleted text to the database, -- but there isn't a sensible alternative option, -- as we need to have the deleted paragraph numbers. when ARM_Output.None | ARM_Output.Deletion => Format_Object.Impdef_Info.Version := Version; Format_Object.Impdef_Info.Change_Kind := Kind; Display_It := Format_Object.Include_Annotations; -- Show impdef notes only if we're showing annotations. Skip_Header := False; when ARM_Output.Insertion => raise Program_Error; end case; else -- we always display it. --Ada.Text_IO.Put_Line (" Other"); Format_Object.Impdef_Info.Version := Version; Format_Object.Impdef_Info.Change_Kind := Kind; Display_It := Format_Object.Include_Annotations; -- Show impdef notes only if we're showing annotations. Local_Change := ARM_Output.None; end if; --Ada.Text_IO.Put_Line (" Display_It=" & Boolean'Image(Display_It)); -- "Text" parameter name consumed above. if Close_Ch /= ' ' then -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Param_Cmd, Close_Ch => Close_Ch); ARM_Input.Start_Recording (Input_Object); if Format_Object.In_Paragraph then -- Do this to preserve any inserted paragraph info. Format_Object.Impdef_Info.Paragraph_String := Format_Object.Current_Paragraph_String; Format_Object.Impdef_Info.Paragraph_Len := Format_Object.Current_Paragraph_Len; else declare PNum : constant String := Positive'Image ( Format_Object.Next_Paragraph - 1); begin Format_Object.Impdef_Info.Paragraph_Len := PNum'Length - 1; Format_Object.Impdef_Info.Paragraph_String (1 .. PNum'Last-1) := PNum (2 .. PNum'Last); end; end if; if Display_It then Check_End_Paragraph; -- End any paragraph that we're in. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Format_Object.Paragraph_Tab_Stops; Format_Object.Next_Paragraph_Format_Type := Bare_Annotation; Format_Object.Next_Paragraph_Subhead_Type := Bare_Annotation; Format_Object.Next_Paragraph_Version := Format_Object.Impdef_Info.Version; Format_Object.Next_Paragraph_Change_Kind := Format_Object.Impdef_Info.Change_Kind; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Check_Paragraph; if not Skip_Header then declare Local_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin Local_Format.Bold := True; Local_Format.Version := Format_Object.Impdef_Info.Version; if ARM_Output."/=" (Local_Change, ARM_Output.None) then Local_Format.Change := Local_Change; ARM_Output.Text_Format (Output_Object, Local_Format); else -- No change from us: ARM_Output.Text_Format (Output_Object, Local_Format); end if; ARM_Output.Ordinary_Text (Output_Object, Text => AARM_Prefix); Local_Format.Bold := Format_Object.Text_Format.Bold; Local_Format.Change := Format_Object.Text_Format.Change; ARM_Output.Text_Format (Output_Object, Local_Format); end; -- else skip the header, do nothing. end if; Format_Object.Last_Paragraph_Subhead_Type := Bare_Annotation; Format_Object.Last_Non_Space := False; if Format_Object.Impdef_Info.Command = Aspect then -- Output the aspect name: declare Local_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin Local_Format.Bold := True; Local_Format.Version := Format_Object.Impdef_Info.Version; if ARM_Output."/=" (Local_Change, ARM_Output.None) then Local_Format.Change := Local_Change; ARM_Output.Text_Format (Output_Object, Local_Format); else -- No change from us: ARM_Output.Text_Format (Output_Object, Local_Format); end if; ARM_Output.Ordinary_Text (Output_Object, Text => Format_Object.Impdef_Info.Aspect_Name(1..Format_Object.Impdef_Info.Aspect_Name_Len)); ARM_Output.Ordinary_Text (Output_Object, Text => ": "); Local_Format.Bold := Format_Object.Text_Format.Bold; Local_Format.Change := Format_Object.Text_Format.Change; ARM_Output.Text_Format (Output_Object, Local_Format); end; -- else no additional text. end if; else -- Don't display, skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Close_Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. end if; -- else no parameter. Weird. end if; end Gen_Chg_xxxx; procedure Get_Syntax_Parameters (Has_Version : in Boolean; RHS_Close_Ch : out Character) is -- Get the parameters for a Syn, AddedSyn, or DeletedSyn -- command. The command has a version parameter (it's not @Syn) -- if Has_Version is True. The results are put into the usual -- places. The RHS parameter's name is evaluated, and its -- closing character is RHS_Close_Ch. -- @Syn{[Tabs=, ]LHS=, RHS=} -- @AddedSyn{Version=[Version],[Tabs=, ]LHS=, RHS=} -- @DeletedSyn{Version=[Version],[Tabs=, ]LHS=, RHS=} Close_Ch, Ch : Character; Was_Tabs : Boolean := False; begin if Has_Version then Get_Change_Version (Is_First => True, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version); end if; -- Peek to see if Tabs parmeter is present: ARM_Input.Get_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); if Ch = 'T' or else Ch = 't' then Was_Tabs := True; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Tabs" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => (not Has_Version), Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Grab the tab string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Syntax_Tab, Format_Object.Syntax_Tab_Len); -- else no parameter. Weird. end if; else Format_Object.Syntax_Tab_Len := 0; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "LHS" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => (not Was_Tabs) and (not Has_Version), Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the non-terminal: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Syntax_NT, Format_Object.Syntax_NT_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "RHS" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => RHS_Close_Ch); end Get_Syntax_Parameters; procedure Gen_Syntax_Rule (Disposition : in ARM_Output.Change_Type; RHS_Close_Ch : in Character) is -- Generate a syntax rule with the specified disposition -- for explicitly generated text. All of the parameters have been -- read in; the close character for the RHS parameter is -- RHS_Close_Ch. use type ARM_Output.Change_Type; Org_Tabs : ARM_Output.Tab_Info; Key : ARM_Index.Index_Key; begin if Disposition = Do_Not_Display_Text then if RHS_Close_Ch /= ' ' then -- Skip the RHS and put nothing in the DB. ARM_Input.Skip_until_Close_Char (Input_Object, RHS_Close_Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) then -- In a deleted paragraph, call Check_Paragraph -- to trigger the "deleted paragraph" message. -- (Otherwise, this may never happen.) Check_Paragraph; -- else null; -- Nothing special to do. end if; end if; -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Syntax_Rule_RHS, Close_Ch => RHS_Close_Ch); -- (We probably don't need to do the above, but consistency -- is preferred.) else -- Set up the tabs: Org_Tabs := Format_Object.Paragraph_Tab_Stops; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; if Format_Object.Syntax_Tab_Len /= 0 then Parse_Tab_Stops (Format_Object.Syntax_Tab(1..Format_Object.Syntax_Tab_Len), Format_Object.Paragraph_Tab_Stops); end if; Check_Paragraph; ARM_Format.Format (Format_Object, "@s{" & Format_Object.Syntax_NT(1..Format_Object.Syntax_NT_Len) & "}", Output_Object, Text_Name => "@Syn(LHS=", No_Annotations => False); -- We use Format here so we can support changes in -- the non-terminal. -- Index the non-terminal: ARM_Index.Add (Term => Get_NT, Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); -- Make an anchor for the non-terminal: if Format_Object.Link_Non_Terminals then declare Lower_NT : constant String := Ada.Characters.Handling.To_Lower (Get_NT); Link_Target : ARM_Syntax.Target_Type := ARM_Syntax.Non_Terminal_Link_Target (Lower_NT); Lower_Old_NT : constant String := Ada.Characters.Handling.To_Lower (Get_Old_NT); Old_Link_Target : ARM_Syntax.Target_Type := ARM_Syntax.Non_Terminal_Link_Target (Lower_Old_NT); begin if Lower_NT /= "" then if Clause_String (Format_Object) /= ARM_Syntax.Non_Terminal_Clause (Lower_NT) then Ada.Text_IO.Put_Line (" ** Clause mismatch for non-terminal: Is=" & Clause_String (Format_Object) & "; Was=" & ARM_Syntax.Non_Terminal_Clause (Lower_NT) & "; NT=" & Lower_NT & "; on line " & ARM_Input.Line_String (Input_Object)); end if; ARM_Output.Local_Target (Output_Object, Text => "", Target => Link_Target); -- else the Non-Terminal was deleted, no -- anchor is needed. end if; if Lower_Old_NT /= "" then if Clause_String (Format_Object) /= ARM_Syntax.Non_Terminal_Clause (Lower_Old_NT) then -- This can happen if an item is inserted -- on one place and deleted in another. -- We'll assume this isn't an error and just -- do nothing here. --Ada.Text_IO.Put_Line (" %% Clause mismatch for old non-terminal: Is=" & -- Clause_String (Format_Object) & "; Was=" & ARM_Syntax.Non_Terminal_Clause (Lower_Old_NT) & -- "; NT=" & Lower_Old_NT & "; on line " & ARM_Input.Line_String (Input_Object)); null; else ARM_Output.Local_Target (Output_Object, Text => "", Target => Old_Link_Target); end if; -- else there was no old Non-Terminal. end if; end; end if; -- Set the font for the "::=". Note that we use @s{} -- above, so that any font changes in the Non-Terminal -- (as in a @Chg command) are respected. -- This command includes any needed insertion or deletion. declare Swiss_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin Swiss_Format.Font := ARM_Output.Swiss; if Disposition = ARM_Output.None then null; else Swiss_Format.Change := Disposition; Swiss_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version; end if; ARM_Output.Text_Format (Output_Object, Swiss_Format); end; ARM_Output.Ordinary_Text (Output_Object, " ::= "); ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset format. Format_Object.Last_Non_Space := False; if RHS_Close_Ch /= ' ' then -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Syntax_Rule_RHS, Close_Ch => RHS_Close_Ch); ARM_Input.Start_Recording (Input_Object); -- Set the format to preserve line breaks. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Org_Tabs; Format_Object.Next_Paragraph_Format_Type := Syntax_Production; -- Tab stops are already set. -- else no parameter, weird. end if; end if; end Gen_Syntax_Rule; procedure Format_Text (Text : in String; Text_Name : in String) is -- Note: We use the state of the surrounding call. Input_Object : Arm_String.String_Input_Type; Real_Include_Annotations : Boolean := Format_Object.Include_Annotations; begin -- Don't show annotations here: Format_Object.Include_Annotations := False; Arm_String.Open (Input_Object, Text, Text_Name); -- Open the input object using a string for input. Real_Process (Format_Object, Format_State, Input_Object, Output_Object); Arm_String.Close (Input_Object); Format_Object.Include_Annotations := Real_Include_Annotations; end Format_Text; procedure DB_Report is new ARM_Database.Report (Format_Text); begin case Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command is -- Basic text commands: when Redundant => if Format_Object.Include_Annotations then Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '['); Format_Object.Last_Non_Space := True; -- else ignored. end if; when Comment | Part => -- Skip the contents of this command. -- For Part, we don't use the information contained, -- but it would help a human reader. ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "comment" or "part" record. when Bold => Check_Paragraph; Format_Object.Text_Format.Bold := True; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Italic => Check_Paragraph; Format_Object.Text_Format.Italic := True; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Roman => Check_Paragraph; Format_Object.Text_Format.Font := ARM_Output.Roman; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Swiss => Check_Paragraph; Format_Object.Text_Format.Font := ARM_Output.Swiss; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Fixed => Check_Paragraph; Format_Object.Text_Format.Font := ARM_Output.Fixed; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Roman_Italic => Check_Paragraph; Format_Object.Text_Format.Italic := True; Format_Object.Text_Format.Font := ARM_Output.Roman; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Shrink => declare use type ARM_Output.Size_Type; begin Check_Paragraph; Format_Object.Text_Format.Size := Format_Object.Text_Format.Size - 1; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); end; when Grow => declare use type ARM_Output.Size_Type; begin Check_Paragraph; Format_Object.Text_Format.Size := Format_Object.Text_Format.Size + 1; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); end; when Black => Check_Paragraph; Format_Object.Text_Format.Color := ARM_Output.Black; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Red => Check_Paragraph; Format_Object.Text_Format.Color := ARM_Output.Red; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Green => Check_Paragraph; Format_Object.Text_Format.Color := ARM_Output.Green; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Blue => Check_Paragraph; Format_Object.Text_Format.Color := ARM_Output.Blue; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Keyword => Check_Paragraph; Format_Object.Text_Format.Bold := True; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Non_Terminal_Format => -- No linking here. Check_Paragraph; Format_Object.Text_Format.Font := ARM_Output.Swiss; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Example_Text => Check_Paragraph; Format_Object.Text_Format.Font := Format_Object.Examples_Font; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Example_Comment => Check_Paragraph; Format_Object.Text_Format.Font := ARM_Output.Roman; Format_Object.Text_Format.Italic := True; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Tab_Clear => Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; when Tab_Set => if Format_Object.Next_Paragraph_Format_Type = Bulleted or else Format_Object.Next_Paragraph_Format_Type = Nested_Bulleted or else Format_Object.Next_Paragraph_Format_Type = Nested_X2_Bulleted or else Format_Object.Next_Paragraph_Format_Type = Enumerated or else Format_Object.Next_Paragraph_Format_Type = Nested_Enumerated or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_1 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_2 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_3 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_4 then Ada.Text_IO.Put_Line (" ** Tab set in hang or bulleted format: " & Paragraph_Type'Image(Format_Object.Next_Paragraph_Format_Type) & ", line " & ARM_Input.Line_String (Input_Object)); elsif ARM_Output."/=" (Format_Object.Paragraph_Tab_Stops, ARM_Output.NO_TABS) then Ada.Text_IO.Put_Line (" ** Setting tabs when they are not clear on line " & ARM_Input.Line_String (Input_Object)); else declare My_Tabs : ARM_Output.Tab_Info := ARM_Output.NO_TABS; Stops : String(1..80); Len : Natural; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Stops, Len); Parse_Tab_Stops (Stops(1..Len), My_Tabs); Format_Object.Paragraph_Tab_Stops := My_Tabs; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Tabstop)"); end; end if; when Non_Terminal => -- @nt{text} -- This *was* simple, until we added linking. declare Name : String(1..120); Len : Natural; Swiss_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Name, Len); -- Set the appropriate style: Check_Paragraph; Swiss_Format.Font := ARM_Output.Swiss; ARM_Output.Text_Format (Output_Object, Format => Swiss_Format); if Format_Object.Link_Non_Terminals then if Ada.Strings.Fixed.Index (Name(1..Len), "@") /= 0 then -- Embedded commands. We have to clean the -- string of the commands (if we can) before -- making a link. declare Lower_NT : String := Ada.Characters.Handling.To_Lower (Name(1..Len)); Lower_NT_Len : Natural := Lower_NT'Length; Loc : Natural := Lower_NT'First; begin while Loc <= Lower_NT_Len loop -- Check for simple commands and remove them: if Lower_NT(Loc) = '@' then -- Start of a command. if Loc < Lower_NT_Len and then (Lower_NT(Loc+1) = '!' or else Lower_NT(Loc+1) = ';') then -- Soft hyphen or no-op, remove. Lower_NT(Loc .. Lower_NT_Len-2) := Lower_NT(Loc+2 .. Lower_NT_Len); Lower_NT_Len := Lower_NT_Len - 2; else -- Unknown. exit; end if; else -- nothing to do, move to next character Loc := Loc + 1; end if; end loop; declare Clause : constant String := ARM_Syntax.Non_Terminal_Clause (Lower_NT(1..Lower_NT_Len)); Target : constant ARM_Syntax.Target_Type := ARM_Syntax.Non_Terminal_Link_Target (Lower_NT(1..Lower_NT_Len)); Org_Font : ARM_Output.Font_Family_Type := Format_Object.Text_Format.Font; begin Format_Object.Text_Format.Font := ARM_Output.Swiss; if Clause = "" then -- Not found. No link, but error message: if Ada.Strings.Fixed.Index (Lower_NT(1..Lower_NT_Len), "@") /= 0 then Ada.Text_IO.Put_Line (" %% Non-terminal with complex embedded commands " & Lower_NT(1..Lower_NT_Len) & " on line " & ARM_Input.Line_String (Input_Object)); else Ada.Text_IO.Put_Line (" ?? Unknown non-terminal " & Lower_NT(1..Lower_NT_Len) & " on line " & ARM_Input.Line_String (Input_Object)); end if; ARM_Format.Format (Format_Object, Name(1..Len), Output_Object, Text_Name => "@nt{}", No_Annotations => False); else ARM_Output.Local_Link_Start (Output_Object, Target => Target, Clause_Number => Clause); ARM_Format.Format (Format_Object, Name(1..Len), Output_Object, Text_Name => "@nt{}", No_Annotations => False); ARM_Output.Local_Link_End (Output_Object, Target => Target, Clause_Number => Clause); end if; Format_Object.Text_Format.Font := Org_Font; end; end; else -- Ordinary link. declare Lower_NT : constant String := Ada.Characters.Handling.To_Lower (Name(1..Len)); Clause : constant String := ARM_Syntax.Non_Terminal_Clause (Lower_NT); Target : constant ARM_Syntax.Target_Type := ARM_Syntax.Non_Terminal_Link_Target (Lower_NT); begin if Clause = "" then -- Not found. No link, but error message: Ada.Text_IO.Put_Line (" ?? Unknown non-terminal " & Name(1..Len) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Output.Ordinary_Text (Output_Object, Name(1..Len)); else ARM_Output.Local_Link (Output_Object, Text => Name(1..Len), Target => Target, Clause_Number => Clause); end if; end; end if; else if Ada.Strings.Fixed.Index (Name(1..Len), "@") /= 0 then -- Embedded commands, better execute them. declare Org_Font : ARM_Output.Font_Family_Type := Format_Object.Text_Format.Font; begin Format_Object.Text_Format.Font := ARM_Output.Swiss; ARM_Format.Format (Format_Object, Name(1..Len), Output_Object, Text_Name => "@nt{}", No_Annotations => False); Format_Object.Text_Format.Font := Org_Font; end; else ARM_Output.Ordinary_Text (Output_Object, Name(1..Len)); end if; end if; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); Format_Object.Last_Non_Space := True; end; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Nonterminal)"); -- Versioned breaking: when New_Page_for_Version | RM_New_Page_for_Version | New_Column_for_Version | Not_ISO_RM_New_Page_for_Version | ISO_Only_RM_New_Page_for_Version => declare Version : ARM_Contents.Change_Version_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version := Version; end; -- Tables: when Table => -- @table(Columns=, -- Alignment=, -- FirstColWidth=, -- LastColWidth=, -- NoBreak=, -- Border=, -- SmallSize=, -- Caption=, -- Headers=, -- Body=) -- Columns must be a single digit (2-9). -- Caption defines the table caption. -- Headers defines the table headers. -- Body defines the table body. Check_End_Paragraph; -- End any paragraph we're in. declare Close_Ch, Ch : Character; Align_Name : ARM_Input.Command_Name_Type; Cols, FirstWidth, LastWidth : Character; No_Page_Break : Boolean; Has_Border : Boolean; Small_Text : Boolean; Alignment : ARM_Output.Column_Text_Alignment; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Columns" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then ARM_Input.Get_Char (Input_Object, Cols); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Table Columns on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Cols not in '2'..'9' then Ada.Text_IO.Put_Line (" ** Bad table column count on line " & ARM_Input.Line_String (Input_Object)); end if; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Alignment" & (10..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the alignment word: Arm_Input.Get_Name (Input_Object, Align_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Table Alignment on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "allleft" then Alignment := ARM_Output.Left_All; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "allcenter" then Alignment := ARM_Output.Center_All; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "centerexceptfirst" then Alignment := ARM_Output.Center_Except_First; else Ada.Text_IO.Put_Line (" ** Bad column alignment: " & Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "FirstColWidth" & (14..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then ARM_Input.Get_Char (Input_Object, FirstWidth); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Table FirstColWidth on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if FirstWidth not in '1'..'9' then Ada.Text_IO.Put_Line (" ** Bad table 1st column width on line " & ARM_Input.Line_String (Input_Object)); end if; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "LastColWidth" & (13..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then ARM_Input.Get_Char (Input_Object, LastWidth); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Table FirstColWidth on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if FirstWidth not in '1'..'9' then Ada.Text_IO.Put_Line (" ** Bad table last column width on line " & ARM_Input.Line_String (Input_Object)); end if; end if; Get_Boolean ("NoBreak" & (8..ARM_Input.Command_Name_Type'Last => ' '), No_Page_Break); Get_Boolean ("Border" & (7..ARM_Input.Command_Name_Type'Last => ' '), Has_Border); Get_Boolean ("SmallSize" & (10..ARM_Input.Command_Name_Type'Last => ' '), Small_Text); -- Set to the table format: Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Format_Object.Paragraph_Tab_Stops; Format_Object.Next_Paragraph_Format_Type := In_Table; Format_Object.In_Paragraph := True; -- A fake, but we cannot have any format. Format_Object.No_Start_Paragraph := False; -- For most purposes, being in a table is like being in a paragraph. -- OK, we've started the table. Now, get the caption: ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Caption" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Check if the parameter is empty: ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then -- There is a caption: ARM_Input.Replace_Char (Input_Object); -- Create the table. Arm_Output.Start_Table ( Output_Object, Columns => Character'Pos(Cols) - Character'Pos('0'), First_Column_Width => Character'Pos(FirstWidth) - Character'Pos('0'), Last_Column_Width => Character'Pos(LastWidth) - Character'Pos('0'), Alignment => Alignment, No_Page_Break => No_Page_Break, Has_Border => Has_Border, Small_Text_Size => Small_Text, Header_Kind => ARM_Output.Both_Caption_and_Header); -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Table_Param_Caption, Close_Ch => Close_Ch); else -- Empty Caption. Move on to the Headers -- command. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Headers" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Check if the parameter is empty: ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then -- There is a header: ARM_Input.Replace_Char (Input_Object); -- Create the table. Arm_Output.Start_Table ( Output_Object, Columns => Character'Pos(Cols) - Character'Pos('0'), First_Column_Width => Character'Pos(FirstWidth) - Character'Pos('0'), Last_Column_Width => Character'Pos(LastWidth) - Character'Pos('0'), Alignment => Alignment, No_Page_Break => No_Page_Break, Has_Border => Has_Border, Small_Text_Size => Small_Text, Header_Kind => ARM_Output.Header_Only); -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Table_Param_Header, Close_Ch => Close_Ch); else -- Empty Headers, too. Move on to the -- Body command. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Body" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Create the table. Arm_Output.Start_Table ( Output_Object, Columns => Character'Pos(Cols) - Character'Pos('0'), First_Column_Width => Character'Pos(FirstWidth) - Character'Pos('0'), Last_Column_Width => Character'Pos(LastWidth) - Character'Pos('0'), Alignment => Alignment, No_Page_Break => No_Page_Break, Has_Border => Has_Border, Small_Text_Size => Small_Text, Header_Kind => ARM_Output.No_Headers); -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Table_Param_Body, Close_Ch => Close_Ch); -- else no parameter, weird. end if; end if; -- else no parameter, weird. end if; end if; -- else no parameter, weird. end if; end; -- Pictures: when Picture_Alone | Picture_Inline => -- @PictureInline(Alignment=, -- Border=, -- Height=, -- Width=, -- Name=, -- Descr=) -- @PictureAlone(Alignment=, -- Border=, -- Height=, -- Width=, -- Name=, -- Descr=) declare Close_Ch, Ch : Character; Align_Name : ARM_Input.Command_Name_Type; Alignment : ARM_Output.Picture_Alignment; Border : ARM_Output.Border_Kind; Height : Natural := 0; Width : Natural := 0; Name, Descr : String(1..120); NLen, DLen : Natural := 0; begin if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Picture_Alone then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Alignment" & (10..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the alignment word: Arm_Input.Get_Name (Input_Object, Align_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Picture Alignment on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "left" then Alignment := ARM_Output.Alone_Left; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "right" then Alignment := ARM_Output.Alone_Right; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "center" then Alignment := ARM_Output.Alone_Center; else Ada.Text_IO.Put_Line (" ** Bad stand-alone picture alignment: " & Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; -- else no parameter. Weird. end if; else -- Picture_Inline. Check_Paragraph; -- Make sure we're in a paragraph. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Alignment" & (10..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the alignment word: Arm_Input.Get_Name (Input_Object, Align_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Picture Alignment on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "inline" then Alignment := ARM_Output.Inline; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "floatleft" then Alignment := ARM_Output.Float_Left; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "floatright" then Alignment := ARM_Output.Float_Right; else Ada.Text_IO.Put_Line (" ** Bad inline picture alignment: " & Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; -- else no parameter. Weird. end if; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Border" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the alignment word: Arm_Input.Get_Name (Input_Object, Align_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Picture Border on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "none" then Border := ARM_Output.None; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "thin" then Border := ARM_Output.Thin; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right)) = "thick" then Border := ARM_Output.Thick; else Ada.Text_IO.Put_Line (" ** Bad picture border: " & Ada.Strings.Fixed.Trim (Align_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Height" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Name, NLen); begin Height := Natural'Value(Name(1..NLen)); exception when Constraint_Error => Ada.Text_IO.Put_Line (" ** Bad picture height: " & Name(1..NLen) & " on line " & ARM_Input.Line_String (Input_Object)); end; -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Width" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Name, NLen); begin Width := Natural'Value(Name(1..NLen)); exception when Constraint_Error => Ada.Text_IO.Put_Line (" ** Bad picture width: " & Name(1..NLen) & " on line " & ARM_Input.Line_String (Input_Object)); end; -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Name, NLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Descr" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Descr, DLen); -- else no parameter. Weird. end if; ARM_Output.Picture ( Output_Object, Alignment => Alignment, Border => Border, Height => Height, Width => Width, Name => Name(1..NLen), Descr => Descr(1..DLen)); end; -- Normal processing should remove the command end marker. -- Paragraph kind commands: when Text_Begin => declare Type_Name : ARM_Input.Command_Name_Type; Ch : Character; begin -- OK, now read the begin "type": Arm_Input.Get_Name (Input_Object, Type_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch = ',' then -- Multiple parameters. The remaining -- parameters appear to be format instructions, -- which we ought to replace or remove. Ada.Text_IO.Put_Line (" -- Multi-parameter begin, line " & ARM_Input.Line_String (Input_Object)); -- We ignore everything until the end of the -- parameter. while Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char loop -- Ignore everything until the end character -- turns up. ARM_Input.Get_Char (Input_Object, Ch); end loop; end if; if Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char = Ch then -- Found the end of the parameter. -- Replace the top of stack with the appropriate begin record: Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr) := (Name => Ada.Characters.Handling.To_Lower (Type_Name), Kind => Begin_Word, Command => Text_Begin, Close_Char => ' ',-- No close character. Text_Format => Format_Object.Text_Format, -- Save the current format. Old_Last_Subhead_Paragraph => Format_Object.Last_Paragraph_Subhead_Type, Old_Next_Subhead_Paragraph => Format_Object.Next_Paragraph_Subhead_Type, Old_Next_Paragraph_Format => Format_Object.Next_Paragraph_Format_Type, Old_Tab_Stops => Format_Object.Paragraph_Tab_Stops, Old_Next_Enum_Num => Format_Object.Next_Enumerated_Num, Is_Formatting => True, -- Reset if needed later. Change_Version => '0', -- Not used. Was_Text => False, -- Not used. Prev_Change => ARM_Output.None, -- Not used. Prev_Change_Version => '0', -- Not used. Prev_Added_Change_Version => '0'); -- Not used. Process_Begin; else ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find close for parameter to begin, line " & ARM_Input.Line_String (Input_Object)); --Bracket_Check := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Bracket_State; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Bad Begin)"); end if; end; when Text_End => declare Type_Name : ARM_Input.Command_Name_Type; Ch : Character; begin Arm_Input.Get_Name (Input_Object, Type_Name); -- Get the end "type". ARM_Input.Get_Char (Input_Object, Ch); if Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char = Ch then -- Found end of parameter: Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "End" record. -- Check for the matching begin, and remove it. if Format_State.Nesting_Stack_Ptr = 0 then Ada.Text_IO.Put_Line (" ** No begin for end, line " & ARM_Input.Line_String (Input_Object)); elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name /= Ada.Characters.Handling.To_Lower (Type_Name) then Ada.Text_IO.Put_Line (" ** Names of begin and end mismatch, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Begin name: " & Ada.Strings.Fixed.Trim(Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right) & " End name: " & Ada.Strings.Fixed.Trim(Type_Name, Ada.Strings.Right)); --Ada.Text_IO.Put_Line (" &Stack name is " & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name); else if Format_Object.Next_Paragraph_Subhead_Type /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph then Format_Object.Last_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph; -- else still in same subhead, leave alone. (If -- we didn't do this, we'd output the subhead -- multiple times). end if; Format_Object.Next_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph; Format_Object.Next_Paragraph_Format_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format; Format_Object.Paragraph_Tab_Stops := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops; Format_Object.Next_Enumerated_Num := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Enum_Num; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (End)"); --!!Debug: --Ada.Text_IO.Put_Line ("(End) Next=" & Paragraph_Type'Image(Format_Object.Next_Paragraph_Subhead_Type)); end if; Check_End_Paragraph; -- End any paragraph that we're in. declare Lower_Type_Name : constant String := Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim ( Type_Name, Ada.Strings.Right)); begin -- Check if number of columns is changing: if Lower_Type_Name = "twocol" then -- Leaving two column region, reset to one: ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 1); elsif Lower_Type_Name = "fourcol" then -- Leaving four column region, reset to one: ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 1); end if; -- Check if we're leaving a bundle: if Lower_Type_Name = "bundle" then Format_Object.In_Bundle := False; end if; -- Check if we're leaving an enumerated list: if Lower_Type_Name = "enumerate" or else Lower_Type_Name = "innerenumerate" then Format_Object.Enumerated_Level := Format_Object.Enumerated_Level - 1; end if; end; else ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find close for parameter to end, line " & ARM_Input.Line_String (Input_Object)); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Bad End)"); end if; end; -- Indexing commands: when Defn | RootDefn => -- @Defn{term} or @RootDefn{term}. Index the term. -- Note that there is no difference between these in terms -- of the index, so we do them together. declare Term : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Term, Len); ARM_Index.Add (Term => Term(1..Len), Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Defn then Display_Index_Entry (Term(1..Len)); else -- RootDefn Display_Index_Entry (Term(1..Len), Special => Is_Root); end if; end if; ARM_Output.Index_Target (Output_Object, Key); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "(Root)Defn" record. end; when PDefn => -- @PDefn{term} ot @RootDefn{term}. Index the term as a partial -- definition. declare Term : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Term, Len); ARM_Index.Add (Term => Term(1..Len), Kind => ARM_Index.Partial_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then Display_Index_Entry (Term(1..Len), Special => Is_Partial); end if; ARM_Output.Index_Target (Output_Object, Key); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "PDefn" record. end; when Defn2 | RootDefn2 => -- @Defn2[Term={term}, Sec={sec}] -- @RootDefn[Term={term}, Sec={sec}]. Index the term and subterm. -- Note that there is no difference between these in terms -- of the index, so we do them together. declare Close_Ch : Character; Term, Subterm : String(1..90); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Sec" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Subterm, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => Subterm(1..SLen), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Defn2 then Display_Index_Entry (Term(1..TLen) & " (" & Subterm(1..SLen) & ')'); else -- RootDefn Display_Index_Entry (Term(1..TLen) & " (" & Subterm(1..SLen) & ')', Special => Is_Root); end if; end if; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when PDefn2 => -- @PDefn2[Term={term}, Sec={sec}]. Index the term and subterm. -- Note that there is no difference between these in terms -- of the index, so we do them together. declare Close_Ch : Character; Term, Subterm : String(1..90); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Sec" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Subterm, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => Subterm(1..SLen), Kind => ARM_Index.Partial_Term_with_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then Display_Index_Entry (Term(1..TLen) & " (" & Subterm(1..SLen) & ')', Special => Is_Partial); end if; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when Index_See => -- @IndexSee[Term={term}, See={see}]. Index a See item. declare Close_Ch : Character; Term, See : String(1..80); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "See" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, See, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => See(1..SLen), Kind => ARM_Index.See_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then Display_Index_Entry (Term(1..TLen) & ": See " & See(1..SLen)); end if; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when Index_See_Also => -- @IndexSeeAlso[Term={term}, See={see}]. Index a See Also item. declare Close_Ch : Character; Term, See : String(1..80); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "See" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, See, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => See(1..SLen), Kind => ARM_Index.See_Also_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then Display_Index_Entry (Term(1..TLen) & ": See also " & See(1..SLen)); end if; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when See_Other => -- @SeeOther[Primary={term}, Other={see}]. Generate a -- See {see} in the index, but no reference. declare Close_Ch : Character; Term, See : String(1..80); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Primary" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Other" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, See, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => See(1..SLen), Kind => ARM_Index.See_Other_Term, Clause => "", Paragraph => "", Key => Key); Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when See_Also => -- @SeeAlso[Primary={term}, Other={see}]. Generate a -- See also {see} in the index, but no reference. declare Close_Ch : Character; Term, See : String(1..80); TLen, SLen : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Primary" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Term, TLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Other" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, See, SLen); -- else no parameter. Weird. end if; ARM_Index.Add (Term => Term(1..TLen), Subterm => See(1..SLen), Kind => ARM_Index.See_Also_Other_Term, Clause => "", Paragraph => "", Key => Key); Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); -- Leave the command end marker, let normal processing -- get rid of it. end; when Index_Root_Unit => -- @RootLibUnit{} -- Generates two index entries: An index entry for -- "Language-Defined Library Units" with a secondary -- entry of , and an index entry for . declare Term : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key := ARM_Index.Get_Key; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Term, Len); -- Set the current unit for future use: Format_Object.Unit (1..Len) := Term(1..Len); Format_Object.Unit_Len := Len; -- Determine what to do with the "Language-Defined" entry: Calc_Change_Disposition ( Format_Object => Format_Object, Version => '2', Operation => ARM_Output.Deletion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then null; -- Ignore this. elsif Disposition = ARM_Output.None then -- Make reference: ARM_Index.Add_Reusing_Key ( Term => "Language-Defined Library Units", Subterm => Term(1..Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); elsif Disposition = ARM_Output.Deletion then null; -- Ignore this (no change info in the index). else -- Insertion. raise Program_Error; -- An insertion inside of a deletion command! end if; Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add_Reusing_Key ( Term => Term(1..Len), Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Format_Object.Package_Index, Entity => Term(1..Len), Kind => ARM_Subindex.Top_Level, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "RootLibUnit" record. end; when Index_Child_Unit => -- @ChildUnit{Parent=[],Child=[]} -- Generates three index entries: An index entry for , with a secondary -- of "@i{child of} ", an index entry for "Language-Defined -- Library Units" with a secondary entry of ., -- and an index entry for .. Child_Unit (Format_Object.Package_Index, Format_Object, Output_Object); when Index_Subprogram_Child_Unit => -- @ChildUnit{Parent=[],Child=[]} -- Generates three index entries: An index entry for , with a secondary -- of "@i{child of} ", an index entry for "Language-Defined -- Library Units" with a secondary entry of ., -- and an index entry for .. Child_Unit (Format_Object.Subprogram_Index, Format_Object, Output_Object); when Index_Type => -- @AdaTypeDefn{} -- Generates two index entries: one for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.), -- adds a similar entry to the exception list, -- and second for "Language-Defined Type" with a -- secondary entry of " @i{in} ". -- Also outputs the to the output file. Simple_Subindex_Item ( Format_Object.Type_Index, Format_Object, Output_Object, Entity_Kind_Name => "Type"); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaTypeDefn" record. when Index_Subtype => -- @AdaSubTypeDefn{Name=,Of=} -- Generates an index entry of " @i{subtype of} -- " with a secondary entry of "@i{in} " (where -- Unit is the unit saved by a previous RootLibUnit or -- ChildUnit.) The entry is added to the type list as well. -- Also outputs the to the output file. declare Subtype_Name, Type_Name : String(1..80); SLen, TLen : Natural := 0; Key : ARM_Index.Index_Key := ARM_Index.Get_Key; Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Subtype_Name, SLen); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Of" & (3..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Type_Name, TLen); -- else no parameter. Weird. end if; Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); if Format_Object.Unit_Len = 0 then Ada.Text_IO.Put_Line ("** No unit defined for index entry expecting one on line " & ARM_Input.Line_String (Input_Object)); ARM_Index.Add_Reusing_Key ( Term => Subtype_Name(1..SLen) & " subtype of " & Type_Name(1..TLen), Subterm => "*unknown*", Kind => ARM_Index.Subtype_Declaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Format_Object.Type_Index, Entity => Subtype_Name(1..SLen) & " subtype of " & Type_Name(1..TLen), From_Unit => "*unknown*", Kind => ARM_Subindex.Subtype_In_Unit, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); else ARM_Index.Add_Reusing_Key ( Term => Subtype_Name(1..SLen) & " subtype of " & Type_Name(1..TLen), Subterm => Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Index.Subtype_Declaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Subindex.Insert ( Subindex_Object => Format_Object.Type_Index, Entity => Subtype_Name(1..SLen) & " subtype of " & Type_Name(1..TLen), From_Unit => Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Subindex.Subtype_In_Unit, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); end if; ARM_Output.Ordinary_Text (Output_Object, Subtype_Name(1..SLen)); Format_Object.Last_Non_Space := True; -- Leave the command end marker, let normal processing -- get rid of it. end; when Index_Subprogram => -- @AdaSubDefn{} -- Generates two index entries: one for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.), -- adds a similar entry to the exception list, -- and second for "Language-Defined Subprogram" with a -- secondary entry of " @i{in} ". -- Also outputs the to the output file. Simple_Subindex_Item ( Format_Object.Subprogram_Index, Format_Object, Output_Object, Entity_Kind_Name => "Subprogram"); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaSubDefn" record. when Index_Exception => -- @AdaExcDefn{} -- Generates and index entries for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.), -- and adds a similar entry to the exception list. -- Also outputs the to the output file. Simple_Subindex_Item ( Format_Object.Exception_Index, Format_Object, Output_Object, Entity_Kind_Name => ""); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaExcDefn" record. when Index_Object => -- @AdaObjDefn{} -- Generates and index entries for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.), -- and adds a similar entry to the exception list. -- Also outputs the to the output file. Simple_Subindex_Item ( Format_Object.Object_Index, Format_Object, Output_Object, Entity_Kind_Name => ""); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaObjDefn" record. when Index_Package => -- @AdaObjDefn{} -- Generates and index entries for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.), -- and adds a similar entry to the package list. -- Also outputs the to the output file. Simple_Subindex_Item ( Format_Object.Package_Index, Format_Object, Output_Object, Entity_Kind_Name => ""); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaPackDefn" record. when Index_Other => -- @AdaDefn{} -- Generate an index entries for with a -- secondary entry of "@i{in} " (where Unit is -- the unit saved by a previous RootLibUnit or ChildUnit.). -- Also outputs the to the output file. declare Item : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Item, Len); ARM_Index.Add (Term => Item(1..Len), Subterm => Format_Object.Unit(1..Format_Object.Unit_Len), Kind => ARM_Index.Declaration_in_Package, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; ARM_Output.Index_Target (Output_Object, Key); ARM_Output.Ordinary_Text (Output_Object, Item(1..Len)); Format_Object.Last_Non_Space := True; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "AdaDefn" record. end; when Index_Check => -- @Indexcheck{} -- Generates index items for -- "check, language-defined", , -- and [partial]. declare Term : String(1..80); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Term, Len); ARM_Index.Add (Term => Term(1..Len), Kind => ARM_Index.Partial_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); Check_Paragraph; if Format_Object.Display_Index_Entries then Display_Index_Entry (Term(1..Len), Special => Is_Partial); end if; ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => "check, language-defined", Subterm => Term(1..Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); if Format_Object.Display_Index_Entries then Display_Index_Entry ("check, language-defined (" & Term(1..Len) & ")"); end if; ARM_Output.Index_Target (Output_Object, Key); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Indexcheck" record. end; when Index_Attr => -- This command indexes an attribute name. -- This calls Defn2("attributes", ), and -- also writes to output. declare Param : String(1..20); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Param, Len); Check_Paragraph; ARM_Index.Add (Term => "attributes", Subterm => Param(1..Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => Param(1..Len) & " attribute", Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Output.Ordinary_Text (Output_Object, Param(1..Len)); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Index_Attr" record. end; when Index_Pragma => -- This command indexes a pragma name. -- This calls Defn2("pragmas", ), and -- also writes to output. declare Param : String(1..30); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Param, Len); Check_Paragraph; ARM_Index.Add (Term => "pragmas", Subterm => Param(1..Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => Param(1..Len) & " pragma", Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Output.Ordinary_Text (Output_Object, Param(1..Len)); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Index_Pragma" record. end; when Index_Aspect => -- This command indexes an aspect name. -- This calls Defn2("aspects", ), and -- Defn( "aspect") declare Param : String(1..30); Len : Natural := 0; Key : ARM_Index.Index_Key; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Param, Len); Check_Paragraph; ARM_Index.Add (Term => "aspects", Subterm => Param(1..Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => Param(1..Len) & " aspect", Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Index_Aspect" record. end; when Syntax_Rule => -- @syn{[Tabs=, ]LHS=, RHS=} -- Marks a syntax production of the form: -- @nt ::= -- defines any tabs needed by the syntax production. -- -- Also, the is indexed. The -- and (and the clause number) are sent to the -- syntax manager. Also, saves for any -- following Syntax_Term (@Syn2) to use. declare RHS_Close_Ch : Character; begin Get_Syntax_Parameters (Has_Version => False, RHS_Close_Ch => RHS_Close_Ch); Gen_Syntax_Rule (ARM_Output.None, RHS_Close_Ch); end; when Added_Syntax_Rule => -- @AddedSyn{Version=[Version],[Tabs=, ]LHS=, RHS=} -- Marks an added syntax production of the form: -- @nt ::= -- See Syntax_Rule for the details. declare RHS_Close_Ch : Character; Disposition : ARM_Output.Change_Type; begin Get_Syntax_Parameters (Has_Version => True, RHS_Close_Ch => RHS_Close_Ch); if Format_Object.In_Change then Ada.Text_IO.Put_Line (" ** In change for AddedSyn on line " & ARM_Input.Line_String (Input_Object)); raise Program_Error; end if; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); Gen_Syntax_Rule (Disposition, RHS_Close_Ch); end; when Deleted_Syntax_Rule => -- @DeletedSyn{Version=[Version],[Tabs=, ]LHS=, RHS=} -- Marks a deleted syntax production of the form: -- @nt ::= -- See Syntax_Rule for the details. declare RHS_Close_Ch : Character; Disposition : ARM_Output.Change_Type; begin Get_Syntax_Parameters (Has_Version => True, RHS_Close_Ch => RHS_Close_Ch); if Format_Object.In_Change then Ada.Text_IO.Put_Line (" ** In change for DeletedSyn on line " & ARM_Input.Line_String (Input_Object)); raise Program_Error; end if; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); Gen_Syntax_Rule (Disposition, RHS_Close_Ch); end; when Syntax_Term | Syntax_Term_Undefined => -- Marks a non-terminal name in the production of a syntax -- rule. Generates the term in the same style as -- @nt (Non_Terminal). "Undefined" means the term is -- not formally defined (like the character class names in -- the Ada standard). -- If the current LHS non-terminal is not null, generates -- a syntax cross reference entry: -- in at . Also, -- generate an index entry for the item: -- @Defn2(Term=,Sec=@i{used}. -- Note: We assume no internal formatting in . declare Name : String(1..40); Len : Natural; Key : ARM_Index.Index_Key; Defined : constant Boolean := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Syntax_Term; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Name, Len); if Format_Object.Syntax_NT_Len /= 0 then -- Generate a syntax cross-reference entry. declare NT : constant String := Get_NT; begin if NT /= "" then ARM_Syntax.Add_Xref ( Name => Name(1..Len), Used_In => Get_NT, Clause => Clause_String (Format_Object), Defined => Defined); -- else this is a deleted production that is -- still displayed; forget the XRef. end if; end; end if; -- Index the non-terminal: ARM_Index.Add (Term => Name(1..Len), Kind => ARM_Index.Syntax_NT_Used, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); -- Set the appropriate style: Check_Paragraph; declare Swiss_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin Swiss_Format.Font := ARM_Output.Swiss; ARM_Output.Text_Format (Output_Object, Swiss_Format); end; if not Defined then -- No linking to do. ARM_Output.Ordinary_Text (Output_Object, Name(1..Len)); elsif Format_Object.Link_Non_Terminals then declare Lower_NT : constant String := Ada.Characters.Handling.To_Lower (Name(1..Len)); Clause : constant String := ARM_Syntax.Non_Terminal_Clause (Lower_NT); Target : constant ARM_Syntax.Target_Type := ARM_Syntax.Non_Terminal_Link_Target (Lower_NT); begin if Clause = "" then -- Not found. No link, but error message: Ada.Text_IO.Put_Line (" ** Unknown non-terminal in syntax production " & Name(1..Len) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Output.Ordinary_Text (Output_Object, Name(1..Len)); else ARM_Output.Local_Link (Output_Object, Text => Name(1..Len), Target => Target, Clause_Number => Clause); end if; end; else ARM_Output.Ordinary_Text (Output_Object, Name(1..Len)); end if; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset the format. Format_Object.Last_Non_Space := True; end; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Syntax Term)"); when Syntax_Prefix => -- Marks the prefix of a non-terminal. Writes italized -- text in the current font. -- Set the appropriate style: Check_Paragraph; Format_Object.Text_Format.Italic := True; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); when To_Glossary | To_Glossary_Also => -- This is a glossary command. -- It is of the form @ToGlossary(Term=[], Text=[]) -- We will store the term and definition in the glossary -- database. We also have to pass through the Text -- parameter, either to the regular text (for -- ToGlossaryAlso) or the AARM (for ToGlossary). declare Close_Ch : Character; Key : ARM_Index.Index_Key; begin if Format_Object.Glossary_Info.Active then Ada.Text_IO.Put_Line (" ** Nested glossary entry on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; -- Setup glossary information for this command: Format_Object.Glossary_Info := (Active => True, Change_Kind => ARM_Database.None, -- No change for this command. Term => <>, -- Set below. Term_Len => <>, -- Set below. Add_to_Glossary => True, -- Always add it. Displayed => False); -- Until we decide differently. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Glossary_Info.Term, Format_Object.Glossary_Info.Term_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Glossary_Text_Param, Close_Ch => Close_Ch); ARM_Input.Start_Recording (Input_Object); if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = To_Glossary_Also then -- The text just goes straight to the file. if Format_Object.Display_Index_Entries then Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. ARM_Output.Ordinary_Text (Output_Object, "[Glossary Entry]"); Format_Object.Last_Non_Space := True; -- else no marker. end if; -- Index the term (because it does appear here): Check_Paragraph; -- We've got to be in a paragraph to write this. ARM_Index.Add (Term => Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len), Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); Format_Object.Glossary_Info.Displayed := True; elsif Format_Object.Include_Annotations then Check_End_Paragraph; -- End any paragraph that we're in. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Format_Object.Paragraph_Tab_Stops; Format_Object.Next_Paragraph_Format_Type := Glossary_Marker; Format_Object.Next_Paragraph_Subhead_Type := Glossary_Marker; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. Format_Object.Glossary_Info.Displayed := True; -- Note: The term is indexed in the glossary, -- but not here. else -- No annotations, "To_Glossary" if Format_Object.Display_Index_Entries then Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. ARM_Output.Ordinary_Text (Output_Object, "[Glossary Entry]"); Format_Object.Last_Non_Space := True; -- else no marker. end if; -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. Format_Object.Glossary_Info.Displayed := False; -- Note: The term is indexed in the glossary, -- but not here. end if; end if; end; when Change_To_Glossary | Change_To_Glossary_Also => -- This is a change glossary command. -- It is of the form -- @ChgToGlossary(Version=[],Kind=(),Term=[], Text=[]) -- We will store the term and definition in the glossary -- database. We also have to pass through the Text -- parameter, either to the regular text (for -- ChgToGlossaryAlso) or the AARM (for ChgToGlossary). declare Close_Ch : Character; Key : ARM_Index.Index_Key; Kind : ARM_Database.Paragraph_Change_Kind_Type; Our_Version : ARM_Contents.Change_Version_Type; use type ARM_Database.Paragraph_Change_Kind_Type; Local_Change : ARM_Output.Change_Type; begin if Format_Object.Glossary_Info.Active then Ada.Text_IO.Put_Line (" ** Nested glossary entry on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; Get_Change_Version (Is_First => True, Version => Our_Version); -- Read a parameter named "Version". Get_Change_Kind (Kind); -- Read a parameter named "Kind". -- Setup glossary information for this command (now -- that we know the above): -- Note: Discriminants need to be static, so we have -- to use the following brain-damaged initialization. -- At least this lets us strip the number and message -- information from Inserted and Deleted (which we -- would have to do anyway). case Kind is when ARM_Database.Inserted | ARM_Database.Inserted_Normal_Number => Format_Object.Glossary_Info := (Active => True, Change_Kind => ARM_Database.Inserted, Version => Our_Version, Term => <>, -- Set below. Term_Len => <>, -- Set below. Add_to_Glossary => <>, -- Set below. Displayed => <>); -- Set below. when ARM_Database.Deleted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_No_Delete_Message | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => Format_Object.Glossary_Info := (Active => True, Change_Kind => ARM_Database.Deleted, Version => Our_Version, Term => <>, -- Set below. Term_Len => <>, -- Set below. Add_to_Glossary => <>, -- Set below. Displayed => <>); -- Set below. when ARM_Database.Revised => Format_Object.Glossary_Info := (Active => True, Change_Kind => ARM_Database.Revised, Version => Our_Version, Term => <>, -- Set below. Term_Len => <>, -- Set below. Add_to_Glossary => <>, -- Set below. Displayed => <>); -- Set below. when ARM_Database.Revised_Inserted_Number => Format_Object.Glossary_Info := (Active => True, Change_Kind => ARM_Database.Revised_Inserted_Number, Version => Our_Version, Term => <>, -- Set below. Term_Len => <>, -- Set below. Add_to_Glossary => <>, -- Set below. Displayed => <>); -- Set below. when ARM_Database.None => raise Program_Error; -- Can't happen. end case; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Change_To_Glossary_Also then -- The text just goes straight to the file. It will -- get formatted appropriately. So we only need to -- figure out whether it will get indexed and displayed -- in the Glossary. Format_Object.Glossary_Info.Displayed := True; Local_Change := ARM_Output.None; if Format_Object.Changes = ARM_Format.Old_Only and then Format_Object.Glossary_Info.Version > '0' then -- Old only, don't display it (and it won't be -- inserted, either). Format_Object.Glossary_Info.Add_to_Glossary := False; elsif Format_Object.Glossary_Info.Change_Kind = ARM_Database.Inserted then if Format_Object.Glossary_Info.Version <= Format_Object.Change_Version then Format_Object.Glossary_Info.Add_to_Glossary := True; else --This reference is too new, ignore it. Format_Object.Glossary_Info.Displayed := False; Format_Object.Glossary_Info.Add_to_Glossary := False; end if; elsif Format_Object.Glossary_Info.Change_Kind = ARM_Database.Deleted then Format_Object.Glossary_Info.Add_to_Glossary := True; else -- we always display it. Format_Object.Glossary_Info.Add_to_Glossary := True; end if; else if Format_Object.Glossary_Info.Change_Kind = ARM_Database.Inserted then Calc_Change_Disposition (Format_Object => Format_Object, Version => Format_Object.Glossary_Info.Version, Operation => ARM_Output.Insertion, Text_Kind => Local_Change); case Local_Change is when Do_Not_Display_Text => Format_Object.Glossary_Info.Displayed := False; Format_Object.Glossary_Info.Add_to_Glossary := False; Local_Change := ARM_Output.None; when ARM_Output.None|ARM_Output.Insertion => Format_Object.Glossary_Info.Displayed := Format_Object.Include_Annotations; Format_Object.Glossary_Info.Add_to_Glossary := True; when ARM_Output.Deletion => raise Program_Error; end case; elsif Format_Object.Glossary_Info.Change_Kind = ARM_Database.Deleted then -- Note: other forms of delete removed previously. Calc_Change_Disposition (Format_Object => Format_Object, Version => Format_Object.Glossary_Info.Version, Operation => ARM_Output.Deletion, Text_Kind => Local_Change); case Local_Change is when Do_Not_Display_Text => Format_Object.Glossary_Info.Displayed := False; Format_Object.Glossary_Info.Add_to_Glossary := True; -- We still add this to the glossary so that -- the deleted paragraph message can be displayed for it. Local_Change := ARM_Output.None; when ARM_Output.None|ARM_Output.Deletion => Format_Object.Glossary_Info.Displayed := Format_Object.Include_Annotations; Format_Object.Glossary_Info.Add_to_Glossary := True; when ARM_Output.Insertion => raise Program_Error; end case; else -- we always display it. Format_Object.Glossary_Info.Displayed := Format_Object.Include_Annotations; Format_Object.Glossary_Info.Add_to_Glossary := True; Local_Change := ARM_Output.None; end if; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Term" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Glossary_Info.Term, Format_Object.Glossary_Info.Term_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Now, handle the parameter: -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Glossary_Text_Param, Close_Ch => Close_Ch); ARM_Input.Start_Recording (Input_Object); if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = Change_To_Glossary_Also then -- The text just goes straight to the file. if Format_Object.Glossary_Info.Add_to_Glossary then if Format_Object.Display_Index_Entries then Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. ARM_Output.Ordinary_Text (Output_Object, "[Glossary Entry]"); Format_Object.Last_Non_Space := True; -- else no marker. end if; -- Index the term (because it does appear here): Check_Paragraph; -- We've got to be in a paragraph to write this. ARM_Index.Add (Term => Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len), Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); -- else no indexing. end if; elsif Format_Object.Glossary_Info.Displayed then -- Change_To_Glossary -- Create the AARM annotation: Check_End_Paragraph; -- End any paragraph that we're in. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Format_Object.Paragraph_Tab_Stops; Format_Object.Next_Paragraph_Format_Type := Glossary_Marker; Format_Object.Next_Paragraph_Subhead_Type := Glossary_Marker; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Format_Object.Next_Paragraph_Version := Format_Object.Glossary_Info.Version; Format_Object.Next_Paragraph_Change_Kind := Kind; -- We assume no outer changes; -- set new change state: Format_Object.Text_Format.Change := Local_Change; Format_Object.Text_Format.Version := Format_Object.Glossary_Info.Version; Format_Object.Text_Format.Added_Version := '0'; -- Change the state *before* outputting the -- paragraph header, so the AARM prefix is included. Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. Format_Object.Text_Format.Change := ARM_Output.None; -- Undo (header) change. Format_Object.Text_Format.Version := '0'; elsif Format_Object.Glossary_Info.Add_to_Glossary then -- Change_To_Glossary -- No AARM annotation: if Format_Object.Display_Index_Entries then Display_Index_Entry (Format_Object.Glossary_Info.Term (1..Format_Object.Glossary_Info.Term_Len)); -- Includes Check_Paragraph. ARM_Output.Ordinary_Text (Output_Object, "[Glossary Entry]"); Format_Object.Last_Non_Space := True; -- else no marker. end if; -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. -- Note: The term is indexed in the glossary, -- but not here. else -- Skip the text (it won't be used at all): ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. end if; end if; end; when Implementation_Defined => -- Store an "implementation-defined" entry for the parameter; -- also save the clause and paragraph reference. ARM_Input.Start_Recording (Input_Object); if Format_Object.Impdef_Info.Command /= None then Ada.Text_IO.Put_Line (" ** Nested impdef entry on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; -- Setup impdef information for this command: Format_Object.Impdef_Info := (Command => Impdef, Change_Kind => ARM_Database.None, Version => '0', Initial_Version => '0', Add_to_DB => True, -- Until we decide differently. Paragraph_String => <>, -- Set below. Paragraph_Len => <>);-- Set below. if Format_Object.In_Paragraph then -- Do this to preserve any inserted paragraph info. Format_Object.Impdef_Info.Paragraph_String := Format_Object.Current_Paragraph_String; Format_Object.Impdef_Info.Paragraph_Len := Format_Object.Current_Paragraph_Len; else declare PNum : constant String := Positive'Image ( Format_Object.Next_Paragraph - 1); begin Format_Object.Impdef_Info.Paragraph_Len := PNum'Length - 1; Format_Object.Impdef_Info.Paragraph_String (1 .. PNum'Last-1) := PNum (2 .. PNum'Last); end; end if; if Format_Object.Include_Annotations then Check_End_Paragraph; -- End any paragraph that we're in. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph := Format_Object.Last_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph := Format_Object.Next_Paragraph_Subhead_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format := Format_Object.Next_Paragraph_Format_Type; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops := Format_Object.Paragraph_Tab_Stops; Format_Object.Next_Paragraph_Format_Type := Bare_Annotation; Format_Object.Next_Paragraph_Subhead_Type := Bare_Annotation; Format_Object.Paragraph_Tab_Stops := ARM_Output.NO_TABS; Check_Paragraph; declare Bold_Format : ARM_Output.Format_Type := Format_Object.Text_Format; begin Bold_Format.Bold := True; -- Change only the boldface. ARM_Output.Text_Format (Output_Object, Bold_Format); end; ARM_Output.Ordinary_Text (Output_Object, Text => "Implementation defined: "); ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset style. Format_Object.Last_Paragraph_Subhead_Type := Bare_Annotation; Format_Object.Last_Non_Space := False; else -- No annotations -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. end if; when Prefix_Type => -- Copy the text into the Format_Object.Prefix_Text string. Check_Paragraph; ARM_Input.Start_Recording (Input_Object); -- No changes in this version (use ChgAttribute if you need that). Format_Object.Attr_Prefix_Change_Kind := ARM_Database.None; Format_Object.Attr_Prefix_Version := '0'; when Reset_Prefix_Type => -- Set Format_Object.Prefix_Text string to the default. Format_Object.Prefix_Text := "@b{NONE!}" & (10..160 => ' '); Format_Object.Prefix_Text_Len := 9; when Attribute | Attribute_Leading => -- @Attribute{Prefix=,AttrName=,Text=} -- Defines an attribute. Creates a hanging text item ', -- with the specified text. The text can contain arbitrary commands; -- it will be run through the full evaluation code. -- The attribute and text is also sent to a database used to later create -- Annex K. (This uses the current value of PrefixType.) Finally, the -- attribute is indexed as by calling @Defn2{Term=[Attribute], -- Sec=}, and as by calling @Defn{ attribute}. declare Close_Ch : Character; Key : ARM_Index.Index_Key; begin Check_End_Paragraph; -- This is always a paragraph end. -- No changes in this version (use ChgAttribute if you need that). Format_Object.Attr_Change_Kind := ARM_Database.None; Format_Object.Attr_Version := '0'; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Prefix" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save prefix: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Attr_Prefix, Format_Object.Attr_Prefix_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "AttrName" & (9..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Attr_Name, Format_Object.Attr_Name_Len); -- else no parameter. Weird. end if; -- Output ' as the hanging text. if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Attribute_Leading then Format_Object.Space_After := ARM_Output.Narrow; Format_Object.Attr_Leading := True; else Format_Object.Space_After := ARM_Output.Normal; Format_Object.Attr_Leading := False; end if; Check_Paragraph; ARM_Output.Ordinary_Text (Output_Object, Format_Object.Attr_Prefix (1 .. Format_Object.Attr_Prefix_Len)); ARM_Output.Ordinary_Character (Output_Object, '''); ARM_Output.Ordinary_Text (Output_Object, Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len)); ARM_Output.End_Hang_Item (Output_Object); Format_Object.Last_Non_Space := False; -- Treat like start of a line. ARM_Index.Add (Term => "attributes", Subterm => Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len) & " attribute", Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Now, handle the parameter: -- The text goes to the file *and* is recorded. Arm_Input.Start_Recording (Input_Object); -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Attribute_Text_Param, Close_Ch => Close_Ch); end if; end; when Pragma_Syntax => -- @PragmaSyntax{} -- Defines a pragma. The text can contain arbitrary commands; -- it will be run through the full evaluation code. -- The text is also sent to a database used to later create -- Annex L. -- Note that these are indented slightly more than regular -- syntax text. We handle that by adding a couple of -- spaces before the text. --Ada.Text_IO.Put_Line ("%% Pragma - normal initialization."); -- All we have to do here is output a couple of -- hard spaces and then start recording. Check_Paragraph; ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Input.Start_Recording (Input_Object); -- Just handle the text normally. when Added_Pragma_Syntax => -- @AddedPragmaSyntax{Version=[],} -- Defines a pragma. The text can contain arbitrary commands; -- it will be run through the full evaluation code. -- The text is also sent to a database used to later create -- Annex L. -- Note that these are indented slightly more than regular -- syntax text. We handle that by adding a couple of -- spaces before the text. declare Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then Ada.Text_IO.Put_Line (" ** Missing comma for AddedPragmaSyn on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version := Version; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version := Version; -- Don't have or need an InitialVersion parameter. Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); -- All we have to do here is output a couple of -- hard spaces (if anything will be displayed) and then -- start recording. The inner @Chg will handle the -- formatting for this. --Ada.Text_IO.Put_Line ("%% Added pragma."); Check_Paragraph; if Disposition /= Do_Not_Display_Text then ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); -- else nothing to display. end if; ARM_Input.Start_Recording (Input_Object); -- Just handle the text normally. end; when Deleted_Pragma_Syntax => -- @DeletedPragmaSyntax{Version=[],InitialVersion=[],} -- Defines a pragma. The text can contain arbitrary commands; -- it will be run through the full evaluation code. -- The text is also sent to a database used to later create -- Annex L. -- Note that these are indented slightly more than regular -- syntax text. We handle that by adding a couple of -- spaces before the text. declare Close_Ch, Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Initial_Version : ARM_Contents.Change_Version_Type := '0'; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Now, get InitialVersion. ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "InitialVersion" & (15..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); ARM_Input.Get_Char (Input_Object, Initial_Version); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for InitialVersion parameter on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then Ada.Text_IO.Put_Line (" ** Missing comma for AddedPragmaSyn on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version := Version; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version := Initial_Version; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); --Ada.Text_IO.Put_Line ("%% Deleted pragma."); -- All we have to do here is output a couple of -- hard spaces (if anything will be displayed) and then -- start recording. The inner @Chg will handle the -- formatting for this. Check_Paragraph; if Disposition /= Do_Not_Display_Text then ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); -- else nothing to display. end if; ARM_Input.Start_Recording (Input_Object); -- Just handle the text normally. end; -- Clause title and reference commands: when Labeled_Section | Labeled_Section_No_Break | Labeled_Annex | Labeled_Informative_Annex | Labeled_Normative_Annex | Labeled_Clause | Labeled_Subclause | Labeled_Subsubclause | Unnumbered_Section => -- Load the title into the Title string: declare Title : ARM_Contents.Title_Type; Title_Length : Natural; Level : ARM_Contents.Level_Type; begin ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char, Title, Title_Length); if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); Level := ARM_Contents.Subclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; Level := ARM_Contents.Subsubclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Clause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Unnumbered_Section then Format_Object.Unnumbered_Section := Format_Object.Unnumbered_Section + 1; Format_Object.Clause_Number := (Section => 0, Clause => Format_Object.Unnumbered_Section, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Unnumbered_Section; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Section or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Section_No_Break then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Section; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Plain_Annex; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Normative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Normative_Annex; else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Informative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Informative_Annex; end if; Title(Title_Length+1 .. Title'Last) := (others => ' '); begin declare Clause_Number : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin Check_End_Paragraph; -- End any paragraph that we're in. if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Section_No_Break then ARM_Output.Clause_Header (Output_Object, Title(1..Title_Length), Level => ARM_Contents.Section, Clause_Number => Clause_Number, No_Page_Break => True, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); else -- Other cases: ARM_Output.Clause_Header (Output_Object, Title(1..Title_Length), Level => Level, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end if; -- Check that the section numbers match the title: if Ada.Characters.Handling.To_Lower (Title) /= Ada.Characters.Handling.To_Lower (ARM_Contents.Lookup_Title ( Level, Format_Object.Clause_Number)) then Ada.Text_IO.Put_Line ("** Unable to match title with section numbers, line " & ARM_Input.Line_String (Input_Object)); end if; --!!Debug: --Ada.Text_IO.Put_Line ("Start clause " & Clause_Number & " -- " & Title(1..Title_Length)); end; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find header reference, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & Title(1..Title_Length)); end; end; -- Reset the paragraph numbers: Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; if Format_Object.Use_ISO_2004_Note_Format then -- Reset the note number: Format_Object.Next_Note := 1; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Section or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Section_No_Break or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Informative_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Normative_Annex then -- Reset the note number, only for sections: Format_Object.Next_Note := 1; end if; -- Reset the subhead: Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); when Labeled_Revised_Annex | Labeled_Revised_Informative_Annex | Labeled_Revised_Normative_Annex | Labeled_Revised_Section | Labeled_Revised_Clause | Labeled_Revised_Subclause | Labeled_Revised_Subsubclause => -- Load the title into the Title string: declare New_Title : ARM_Contents.Title_Type; New_Title_Length : Natural; Old_Title : ARM_Contents.Title_Type; Old_Title_Length : Natural; Close_Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Initial_Version : ARM_Contents.Change_Version_Type := '0'; Level : ARM_Contents.Level_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Check for the optional "InitialVersion" parameter, -- stopping when we reach "New": declare Which_Param : ARM_Input.Param_Num; Ch : Character; begin -- If there is no InitialVersion command, use the same -- version of the rest of the command. loop ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "InitialVersion" & (15..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "New" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if Which_Param = 1 and then Close_Ch /= ' ' then -- Found InitialVersion ARM_Input.Get_Char (Input_Object, Ch); Initial_Version := Ch; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for InitialVersion parameter on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; else -- We found "New" (or an error) exit; -- Handling of New is below. end if; end loop; end; if Close_Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, New_Title, New_Title_Length); New_Title(New_Title_Length+1 .. New_Title'Last) := (others => ' '); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Old" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Old_Title, Old_Title_Length); Old_Title(Old_Title_Length+1 .. Old_Title'Last) := (others => ' '); end if; end if; ARM_Input.Get_Char (Input_Object, Close_Ch); if Close_Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Revised_(SubClause|Annex) on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); Level := ARM_Contents.Subclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; Level := ARM_Contents.Subsubclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Clause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Section then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Section; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Plain_Annex; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Normative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Normative_Annex; else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Informative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Informative_Annex; end if; begin declare Clause_Number : constant String := ARM_Contents.Lookup_Clause_Number (New_Title); New_Disposition : ARM_Output.Change_Type; Old_Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Check_End_Paragraph; -- End any paragraph that we're in. -- Check that the section numbers match the title: if Ada.Characters.Handling.To_Lower (New_Title) /= Ada.Characters.Handling.To_Lower (ARM_Contents.Lookup_Title ( Level, Format_Object.Clause_Number)) then Ada.Text_IO.Put_Line ("** Unable to match title with section numbers, line " & ARM_Input.Line_String (Input_Object)); end if; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => New_Disposition); -- Note: We use insertion here because -- we want to decide what to do with -- the New part. Calc_Change_Disposition ( Format_Object => Format_Object, Version => Initial_Version, Operation => ARM_Output.Insertion, Text_Kind => Old_Disposition); if New_Disposition = Do_Not_Display_Text then if Old_Disposition = Do_Not_Display_Text then null; -- Show nothing. elsif Old_Disposition = ARM_Output.None then -- Use the old only: ARM_Output.Clause_Header (Output_Object, Old_Title(1..Old_Title_Length), Level => Level, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); elsif Old_Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- an insertion of the Old. Show this like an added item: ARM_Output.Revised_Clause_Header (Output_Object, New_Header_Text => Old_Title(1..Old_Title_Length), Old_Header_Text => "", Level => Level, Version => Initial_Version, Old_Version => '0', Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end if; elsif New_Disposition = ARM_Output.None then -- Use the new only: ARM_Output.Clause_Header (Output_Object, New_Title(1..New_Title_Length), Level => Level, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); -- In this case, we have no sane -- way to show the old, so we hope that -- isn't expected. --!!Debug: --Ada.Text_IO.Put_Line ("Start clause " & Clause_Number & " -- " & New_Title(1..New_Title_Length)); elsif New_Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. if Format_Object.Changes = ARM_Format.New_Changes or else Old_Disposition = Do_Not_Display_Text then ARM_Output.Revised_Clause_Header (Output_Object, New_Header_Text => New_Title(1..New_Title_Length), Old_Header_Text => " ", Level => Level, Version => Version, Old_Version => '0', Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); elsif Old_Disposition = ARM_Output.None then -- Show old without any insertion marks: ARM_Output.Revised_Clause_Header (Output_Object, New_Header_Text => New_Title(1..New_Title_Length), Old_Header_Text => Old_Title(1..Old_Title_Length), Level => Level, Version => Version, Old_Version => '0', Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); elsif Old_Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- An insertion of the Old item: ARM_Output.Revised_Clause_Header (Output_Object, New_Header_Text => New_Title(1..New_Title_Length), Old_Header_Text => Old_Title(1..Old_Title_Length), Level => Level, Version => Version, Old_Version => Initial_Version, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end if; --!!Debug: --Ada.Text_IO.Put_Line ("Start clause " & Clause_Number & " -- " & New_Title(1..New_Title_Length)); end if; end; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find header reference, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & New_Title(1..New_Title_Length)); end; -- Reset the paragraph numbers: Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; if Format_Object.Use_ISO_2004_Note_Format then -- Reset the note number: Format_Object.Next_Note := 1; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Section or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Informative_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Revised_Normative_Annex then -- Reset the note number, only for sections: Format_Object.Next_Note := 1; end if; -- Reset the subhead: Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Labeled_Added_Annex | Labeled_Added_Informative_Annex | Labeled_Added_Normative_Annex | Labeled_Added_Section | Labeled_Added_Clause | Labeled_Added_Subclause | Labeled_Added_Subsubclause => -- Load the title into the Title string: declare New_Title : ARM_Contents.Title_Type; New_Title_Length : Natural; Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Level : ARM_Contents.Level_Type; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Ch, New_Title, New_Title_Length); New_Title(New_Title_Length+1 .. New_Title'Last) := (others => ' '); end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Added_(Sub)Clause on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then null; -- Ignore this; it isn't numbered or anything. elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); Level := ARM_Contents.Subclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; Level := ARM_Contents.Subsubclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Clause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Section then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Section; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Plain_Annex; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Normative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Normative_Annex; else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Informative_Annex then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Informative_Annex; end if; begin declare Clause_Number : constant String := ARM_Contents.Lookup_Clause_Number (New_Title); begin if Disposition = ARM_Output.None then -- Normal reference: Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Clause_Header (Output_Object, New_Title(1..New_Title_Length), Level => Level, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); else -- Insertion. Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Revised_Clause_Header (Output_Object, New_Header_Text => New_Title(1..New_Title_Length), Old_Header_Text => "", Level => Level, Version => Version, Old_Version => '0', Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end if; -- Check that the section numbers match the title: if Ada.Characters.Handling.To_Lower (New_Title) /= Ada.Characters.Handling.To_Lower (ARM_Contents.Lookup_Title ( Level, Format_Object.Clause_Number)) then Ada.Text_IO.Put_Line ("** Unable to match title with section numbers, line " & ARM_Input.Line_String (Input_Object)); end if; --!!Debug: --Ada.Text_IO.Put_Line ("Start clause " & Clause_Number & " -- " & New_Title(1..New_Title_Length)); end; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find header reference, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & New_Title(1..New_Title_Length)); end; -- Reset the paragraph numbers: Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; if Format_Object.Use_ISO_2004_Note_Format then -- Reset the note number: Format_Object.Next_Note := 1; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Section or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Informative_Annex or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Added_Normative_Annex then -- Reset the note number, only for sections: Format_Object.Next_Note := 1; end if; -- Reset the subhead: Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; end if; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Labeled_Deleted_Clause | Labeled_Deleted_Subclause | Labeled_Deleted_Subsubclause => -- Load the title into the Title string: declare Old_Title : ARM_Contents.Title_Type; Old_Title_Length : Natural; Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Level : ARM_Contents.Level_Type; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Ch, Old_Title, Old_Title_Length); Old_Title(Old_Title_Length+1 .. Old_Title'Last) := (others => ' '); end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Deleted_(Sub)Clause on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); --Ada.Text_IO.Put_Line ("Labeled_Deleted disp: " & ARM_Output.Change_Type'Image(Disposition)); --Ada.Text_IO.Put_Line (" Version:" & Version); if Disposition = Do_Not_Display_Text then null; -- Ignore this; it isn't numbered or anything. elsif Disposition = ARM_Output.Insertion then raise Program_Error; -- An insertion inside of a deletion command! elsif Disposition = ARM_Output.Deletion then -- Format the text as a deletion, but not as a header. Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Title, Indent => 0, Number => ""); ARM_Output.Text_Format (Output_Object, Format => (Bold => True, Italic => False, Font => ARM_Output.Default, Size => ARM_Output.Size_Type(-2), Color => ARM_Output.Default, Change => ARM_Output.Deletion, Version => Version, Added_Version => '0', Location => ARM_Output.Normal)); ARM_Output.Ordinary_Text (Output_Object, Old_Title(1..Old_Title_Length)); ARM_Output.Text_Format (Output_Object, ARM_Output.NORMAL_FORMAT); ARM_Output.End_Paragraph (Output_Object); -- Reset the paragraph numbers: (for the following deleted text, presumably also shown). Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; if Format_Object.Use_ISO_2004_Note_Format then -- Reset the note number: Format_Object.Next_Note := 1; --elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Section or else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Annex or else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Informative_Annex or else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Normative_Annex then -- -- Reset the note number, only for sections: (no sections yet) -- Format_Object.Next_Note := 1; end if; -- Reset the subhead: Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; else -- Disposition = ARM_Output.None then if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); Level := ARM_Contents.Subclause; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; Level := ARM_Contents.Subsubclause; else --Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Labeled_Deleted_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); Level := ARM_Contents.Clause; end if; begin declare Clause_Number : constant String := ARM_Contents.Lookup_Clause_Number (Old_Title); begin -- Normal reference: Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Clause_Header (Output_Object, Old_Title(1..Old_Title_Length), Level => Level, Clause_Number => Clause_Number, Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); end; -- Check that the section numbers match the title: if Ada.Characters.Handling.To_Lower (Old_Title) /= Ada.Characters.Handling.To_Lower (ARM_Contents.Lookup_Title ( Level, Format_Object.Clause_Number)) then Ada.Text_IO.Put_Line ("** Unable to match title with section numbers, line " & ARM_Input.Line_String (Input_Object)); end if; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find header reference, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & Old_Title(1..Old_Title_Length)); end; -- Reset the paragraph numbers: Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; -- Reset the subhead: Format_Object.Last_Paragraph_Subhead_Type := Plain; Format_Object.Next_Paragraph_Format_Type := Plain; end if; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Preface_Section => Check_End_Paragraph; -- End any paragraph that we're in. --ARM_Output.New_Page (Output_Object, ARM_Output.Odd_Page_Only); ARM_Output.Clause_Header (Output_Object, Header_Text => "", Level => ARM_Contents.Unnumbered_Section, Clause_Number => "0.99", Top_Level_Subdivision_Name => Format_Object.Top_Level_Subdivision_Name); when Subheading => -- This is used in preface sections where no numbers or -- contents are desired. Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Wide_Above, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => True); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Format_Object.Text_Format.Bold := True; Format_Object.Text_Format.Font := ARM_Output.Swiss; Format_Object.Text_Format.Size := 2; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); when Added_Subheading => -- This is used in preface sections where no numbers or -- contents are desired. declare Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then Ada.Text_IO.Put_Line (" ** Missing comma for AddedSubheading on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version := Version; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. elsif Disposition = ARM_Output.None then -- Normal text: ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Wide_Above, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => True); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Format_Object.Text_Format.Bold := True; Format_Object.Text_Format.Font := ARM_Output.Swiss; Format_Object.Text_Format.Size := 2; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Wide_Above, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => True); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Format_Object.Text_Format.Bold := True; Format_Object.Text_Format.Font := ARM_Output.Swiss; Format_Object.Text_Format.Size := 2; Format_Object.Text_Format.Change := ARM_Output.Insertion; Format_Object.Text_Format.Version := Version; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); end if; end; when Heading => -- This is used in preface sections where no numbers or -- contents are desired. Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Title, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => True, Justification => ARM_Output.Center); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Format_Object.Text_Format.Bold := True; Format_Object.Text_Format.Font := ARM_Output.Swiss; Format_Object.Text_Format.Size := 0; -- Note that the size is +3 from the Title format. ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); when Center => Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Normal, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => False, Justification => ARM_Output.Center); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; when Right => Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.Start_Paragraph (Output_Object, Style => ARM_Output.Normal, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => False, Justification => ARM_Output.Right); Format_Object.In_Paragraph := True; Format_Object.No_Start_Paragraph := False; when Ref_Section | Ref_Section_Number => -- Load the title into the Title string: declare Ch : Character; Title : ARM_Contents.Title_Type; Title_Length : Natural; begin ARM_Input.Get_Char (Input_Object, Ch); Title_Length := 0; while Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char loop Title_Length := Title_Length + 1; Title(Title_Length) := Ch; ARM_Input.Get_Char (Input_Object, Ch); end loop; Title(Title_Length+1 .. Title'Last) := (others => ' '); begin declare Clause_Number_Text : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Ref_Section then Check_Paragraph; ARM_Output.Clause_Reference (Output_Object, Text => Clause_Number_Text, Clause_Number => Clause_Number_Text); ARM_Output.Ordinary_Text (Output_Object, ", "); -- Was: (To match the Ada 95 Standard) --ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Quote); --ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Quote); ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Double_Quote); if Format_Object.Change_Version < '1' or else Format_Object.Changes = ARM_Format.Old_Only then -- Use original version: declare Clause_Number : ARM_Contents.Clause_Number_Type; begin ARM_Contents.Make_Clause (Clause_Number_Text, Clause_Number); ARM_Output.Clause_Reference (Output_Object, Text => Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Old_Title ( ARM_Contents.Lookup_Level (Title), Clause_Number), Ada.Strings.Right), Clause_Number => Clause_Number_Text); end; else -- Use new version. We don't have version numbers for these yet. ARM_Output.Clause_Reference (Output_Object, Text => Title(1..Title_Length), Clause_Number => Clause_Number_Text); end if; -- Was: (To match the Ada 95 Standard) --ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Quote); --ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Quote); ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Double_Quote); else -- Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Ref_Section_Number then Check_Paragraph; ARM_Output.Clause_Reference (Output_Object, Text => Clause_Number_Text, Clause_Number => Clause_Number_Text); end if; Format_Object.Last_Non_Space := True; end; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find section reference, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & Title(1..Title_Length)); end; end; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Section Reference)"); when Ref_Section_by_Number => -- Load the number into the Number string: declare Ch : Character; Number : String(1..20); Number_Length : Natural; begin ARM_Input.Get_Char (Input_Object, Ch); Number_Length := 0; while Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char loop Number_Length := Number_Length + 1; Number(Number_Length) := Ch; ARM_Input.Get_Char (Input_Object, Ch); end loop; Number(Number_Length+1 .. Number'Last) := (others => ' '); Check_Paragraph; ARM_Output.Clause_Reference (Output_Object, Text => Number(1..Number_Length), Clause_Number => Number(1..Number_Length)); Format_Object.Last_Non_Space := True; -- No checking here. end; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Section Num Reference)"); -- Link commands: when Local_Target => -- @LocalTarget{Target=[],Text=[]} declare Close_Ch : Character; Target : String(1..40); Target_Len : Natural; Text : String(1..100); Text_Len : Natural; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Target" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save URL: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Target, Target_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Text, Text_Len); -- else no parameter. Weird. end if; Check_Paragraph; ARM_Output.Local_Target (Output_Object, Text => Text(1..Text_Len), Target => Target(1..Target_Len)); if Text_Len /= 0 and then Text(Text_Len) /= ' ' then Format_Object.Last_Non_Space := True; end if; end; -- Leave the command end marker, let normal processing -- get rid of it. when Local_Link => -- @LocalLink{Target=[],Sec=[],Text=[<text>]} declare Close_Ch : Character; Target : String(1..40); Target_Len : Natural; Text : String(1..100); Text_Len : Natural; Title : ARM_Contents.Title_Type; Title_Length : Natural; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Target" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save URL: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Target, Target_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Sec" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save URL: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Text, Text_Len); -- else no parameter. Weird. end if; begin declare Clause_Number_Text : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin Check_Paragraph; ARM_Output.Local_Link (Output_Object, Text => Text(1..Text_Len), Target => Target(1..Target_Len), Clause_Number => Clause_Number_Text); if Text_Len /= 0 and then Text(Text_Len) /= ' ' then Format_Object.Last_Non_Space := True; end if; end; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find section in local link, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Looking for " & Title(1..Title_Length)); end; end; -- Leave the command end marker, let normal processing -- get rid of it. when URL_Link => -- @URLLink{URL=[<URL>],Text=[<text>]} declare Close_Ch : Character; URL : String(1..80); URL_Len : Natural; Text : String(1..100); Text_Len : Natural; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "URL" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save URL: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, URL, URL_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Text, Text_Len); -- else no parameter. Weird. end if; Check_Paragraph; ARM_Output.URL_Link (Output_Object, Text => Text(1..Text_Len), URL => URL(1..URL_Len)); if Text_Len /= 0 and then Text(Text_Len) /= ' ' then Format_Object.Last_Non_Space := True; end if; end; -- Leave the command end marker, let normal processing -- get rid of it. when AI_Link => -- @AILink{AI=[<AI>],Text=[<text>]} declare Close_Ch : Character; AI : String(1..30); AI_Len : Natural; Text : String(1..100); Text_Len : Natural; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "AI" & (3..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save AI: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, AI, AI_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Text, Text_Len); -- else no parameter. Weird. end if; Check_Paragraph; ARM_Output.AI_Reference (Output_Object, Text => Text(1..Text_Len), AI_Number => AI(1..AI_Len)); if Text_Len /= 0 and then Text(Text_Len) /= ' ' then Format_Object.Last_Non_Space := True; end if; end; -- Leave the command end marker, let normal processing -- get rid of it. -- Change commands: when Change => -- This command is of the form: -- @chg{[version=<Version>],new=[<new text>],old=[<old text>]}. -- where the parameter names (other than version) are -- optional (but highly recommended), and the curly and -- square brackets can be any of the allowed bracketing characters. -- We have to process this in parts, in order that the -- text can be handled normally. declare Ch : Character; Saw_Version : Boolean; begin -- Check for the optional "Version" parameter: ARM_Input.Get_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); if Ch = 'V' or else Ch = 'v' then -- There is a Version parameter, grab it. Get_Change_Version (Is_First => True, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version); -- Read a parameter named "Version". Saw_Version := True; else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version := '1'; Saw_Version := False; end if; -- Save the current state: Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change := Format_Object.Text_Format.Change; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version := Format_Object.Text_Format.Version; Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Added_Change_Version := Format_Object.Text_Format.Added_Version; -- Check and handle the "New" parameter: ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "New" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => not Saw_Version, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter: -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Change_Param_New, Close_Ch => Ch); Format_Object.In_Change := True; -- Note: We can't use Calc_Change_Disposition here, -- because it isn't intended to work on possibly -- nested calls like these. -- Now, handle the parameter: if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version > Format_Object.Change_Version then -- Ignore any changes with version numbers higher than -- the current maximum. -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. else case Format_Object.Changes is when ARM_Format.Old_Only => -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. when ARM_Format.New_Only => if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) then -- In a deleted paragraph, call Check_Paragraph -- to trigger the "deleted paragraph" message. -- (Otherwise, this never happens.) Check_Paragraph; -- else null; -- Nothing special to do. end if; when ARM_Format.Changes_Only | ARM_Format.Show_Changes | ARM_Format.New_Changes => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version < Format_Object.Change_Version and then Format_Object.Changes = ARM_Format.Changes_Only then -- Just normal output text. if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) then -- In a deleted paragraph, call Check_Paragraph -- to trigger the "deleted paragraph" message. -- (Otherwise, this never happens.) Check_Paragraph; -- else null; -- Nothing special to do. end if; else ARM_Input.Get_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text := Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text then -- Non-empty text; Calculate new change state (current is insertion): Check_Paragraph; -- Change the state *after* outputting the paragraph header. case Format_Object.Text_Format.Change is when ARM_Output.Insertion | ARM_Output.None => Format_Object.Text_Format.Change := ARM_Output.Insertion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; when ARM_Output.Deletion => Format_Object.Text_Format.Change := ARM_Output.Both; Format_Object.Text_Format.Added_Version := -- The insertion should be older. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; -- .Text_Format.Version is unchanged. when ARM_Output.Both => Format_Object.Text_Format.Change := ARM_Output.Both; Format_Object.Text_Format.Added_Version := -- The insertion should be older. Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; -- .Text_Format.Version is unchanged. end case; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Set style. -- else no text, so don't bother. end if; end if; end case; end if; -- else no parameter. Weird. end if; end; when Change_Param_Old | Change_Param_New => -- These can't get here; they represent the parameters of -- "Change" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Change parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Added | Change_Deleted => -- @ChgAdded{Version=[<Version>],[NoPrefix=[T|F],][NoParanum=[T|F],] -- [Type=[Leading|Trailing|Normal],][Keepnext=[T|F],]Text=[text]} -- @ChgDeleted{Version=[<Version>],[NoPrefix=[T|F],][NoParanum=[T|F],] -- [Type=[Leading|Trailing|Normal],][Keepnext=[T|F],]Text=[text]} -- Whole paragraph change. These let us modify the AARM prefix -- (like "Reason:" or "Discussion:", and also let us -- conditionally handle paragraph formatting (which -- otherwise would come too late). declare Which_Param : ARM_Input.Param_Num; Close_Ch : Character; NoPrefix, Noparanum, Keepnext : Boolean := False; Space_After : ARM_Output.Space_After_Type := ARM_Output.Normal; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; function Read_Boolean (Close_Ch : in Character; Name : in String) return Boolean is -- Read a Boolean parameter for a parameter already -- opened and ending with Close_Ch. -- Name is the name of the parameter; for error messages only. Ch : Character; Result : Boolean; begin ARM_Input.Get_Char (Input_Object, Ch); case Ch is when 'F' | 'f' | 'N' | 'n' => Result := False; when 'T' | 't' | 'Y' | 'y' => Result := True; when others => Ada.Text_IO.Put_Line (" ** Bad value for boolean parameter " & Name & " on line " & ARM_Input.Line_String (Input_Object)); end case; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for boolean parameter " & Name & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; return Result; end Read_Boolean; function Read_Type (Close_Ch : in Character) return ARM_Output.Space_After_Type is -- Read the Type parameter. Type_Name : ARM_Input.Command_Name_Type; Ch : Character; Result : ARM_Output.Space_After_Type := ARM_Output.Normal; begin -- Get the type word: Arm_Input.Get_Name (Input_Object, Type_Name); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for Type on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; if Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Type_Name, Ada.Strings.Right)) = "leading" then Result := ARM_Output.Narrow; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Type_Name, Ada.Strings.Right)) = "trailing" then Result := ARM_Output.Wide; elsif Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Type_Name, Ada.Strings.Right)) = "normal" then Result := ARM_Output.Normal; else Ada.Text_IO.Put_Line (" ** Bad type for paragraph type: " & Ada.Strings.Fixed.Trim (Type_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end if; return Result; end Read_Type; begin -- These are not allowed in other @Chg commands. if Format_Object.In_Change then Ada.Text_IO.Put_Line ("** ChgAdded/ChgDeleted nested in other Chg, line " & ARM_Input.Line_String (Input_Object)); end if; Get_Change_Version (Is_First => True, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version); -- Read a parameter named "Version". loop -- Handle the optional parameters; stop on Text. ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "NoPrefix" & (9..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "NoParanum" & (10..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_3 => "Type" & (5..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_4 => "Keepnext" & (9..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_5 => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if Which_Param = 1 and then Close_Ch /= ' ' then NoPrefix := Read_Boolean (Close_Ch, "NoPrefix"); elsif Which_Param = 2 and then Close_Ch /= ' ' then NoParanum := Read_Boolean (Close_Ch, "NoParanum"); elsif Which_Param = 3 and then Close_Ch /= ' ' then Space_After := Read_Type (Close_Ch); elsif Which_Param = 4 and then Close_Ch /= ' ' then Keepnext := Read_Boolean (Close_Ch, "KeepNext"); else exit; -- We found "Text" (or an error) end if; end loop; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Change_Added and then Close_Ch /= ' ' then -- Generate an insertion, there is a Text parameter. Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Change_Added_Param, Close_Ch => Close_Ch); Format_Object.In_Change := True; if Disposition = Do_Not_Display_Text then -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. elsif Disposition = ARM_Output.None then -- Display the text normally. Format_Object.No_Prefix := NoPrefix; Format_Object.No_Para_Num := NoParanum; Format_Object.Keep_with_Next := KeepNext; Format_Object.Space_After := Space_After; elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. Format_Object.No_Prefix := NoPrefix; Format_Object.No_Para_Num := NoParanum; Format_Object.Keep_with_Next := KeepNext; Format_Object.Space_After := Space_After; -- We assume non-empty text and no outer changes; -- set new change state: Format_Object.Text_Format.Change := ARM_Output.Insertion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- Change the state *before* outputting the -- paragraph header, so the AARM prefix is included. ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset style. end if; elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Change_Deleted and then Close_Ch /= ' ' then -- Generate a deletion. Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Change_Deleted_Param, Close_Ch => Close_Ch); Format_Object.In_Change := True; if Disposition = Do_Not_Display_Text then -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. if ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Format_Object.Next_Paragraph_Change_Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message) then -- In a deleted paragraph, call Check_Paragraph -- to trigger the "deleted paragraph" message and -- increment the paragraph number. -- (Otherwise, this may never happen.) Format_Object.No_Para_Num := NoParanum; Check_Paragraph; -- else null; -- Nothing special to do. end if; elsif Disposition = ARM_Output.None then -- Display the text normally. Format_Object.No_Prefix := NoPrefix; Format_Object.No_Para_Num := NoParanum; Format_Object.Keep_with_Next := KeepNext; Format_Object.Space_After := Space_After; elsif Disposition = ARM_Output.Insertion then raise Program_Error; -- An insertion inside of a deletion command! else -- Deletion. if Format_Object.Changes = ARM_Format.New_Changes then -- Special case: we ignore the deleted text, but mark its presence. -- We assume that the text is non-empty; -- set the new change state. -- Note: We ignore the formatting here! Format_Object.No_Prefix := True; Format_Object.No_Para_Num := NoParanum; Format_Object.Text_Format.Change := ARM_Output.Deletion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- Output the paragraph headers *after* changing the state, -- so that AARM headers are marked. ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset style. ARM_Output.Ordinary_Character (Output_Object, ' '); -- Skip the text (we're not going to output it): ARM_Input.Skip_until_Close_Char (Input_Object, Close_Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. else -- Normal. -- We assume that the text is non-empty; -- set the new change state and formatting. Format_Object.No_Prefix := NoPrefix; Format_Object.No_Para_Num := NoParanum; Format_Object.Keep_with_Next := KeepNext; Format_Object.Space_After := Space_After; Format_Object.Text_Format.Change := ARM_Output.Deletion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- Output the paragraph headers *after* changing the state, -- so that AARM headers are marked. ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- Reset style. end if; end if; -- else no parameter; previous error. end if; end; when Change_Added_Param | Change_Deleted_Param => -- These can't get here; they represent the parameter of -- "Change_Added" and "Change_Deleted" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Change_xxx parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Table_Param_Caption | Table_Param_Header | Table_Param_Body => -- These can't get here; they represent the parameters of -- "Table" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Table parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Syntax_Rule_RHS => -- This can't get here; it represents the second parameter of -- "Syn" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Syntax parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Glossary_Text_Param => -- This can't get here; it represents the second parameter of -- "ToGlossary" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Glossary parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Attribute_Text_Param => -- This can't get here; it represents the third parameter of -- "Attribute" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Attribute parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Impdef_Text_Param => -- This can't get here; it represents the third parameter of -- "ChgImpldef" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Impdef parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Impladv_Text_Param => -- This can't get here; it represents the third parameter of -- "ChgImpladvice" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Impladv parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Docreq_Text_Param => -- This can't get here; it represents the third parameter of -- "ChgDocReq" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Docreq parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_AspectDesc_Text_Param => -- This can't get here; it represents the fourth parameter of -- "ChgAspectDesc" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** AspectDesc parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Prefix_Text_Param => -- This can't get here; it represents the second parameter of -- "ChgPrefixType" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** ChgPrefix parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Reference => -- This command is of the form: -- @chgref{Version=[<version>], Kind=(<kind>) -- {,Ref=(<DR_Number>)}{,ARef=(<AI_Number>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, followed by zero or more -- DR references, and finally zero or more AI references. -- As usual, any of the allowed bracketing characters can -- be used. declare Ch : Character; Kind : ARM_Database.Paragraph_Change_Kind_Type; Version : ARM_Contents.Change_Version_Type; Display_It : Boolean; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". Get_Change_Kind (Kind); -- Read a parameter named "Kind". if Version <= Format_Object.Change_Version then Format_Object.Next_Paragraph_Version := Version; Format_Object.Next_Paragraph_Change_Kind := Kind; if (ARM_Database."=" (Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- In this case, display nothing, period. Display_It := False; -- Check if any Ref's already exist; remove them -- if they do. %% Ugly: This is needed if -- a paragraph is first revised, then deleted, -- as in 4.6. There ought to be a better way -- of handling this, not sure what it is. Dump_References (Format_Object.References); elsif (ARM_Database."=" (Kind, ARM_Database.Deleted) or else ARM_Database."=" (Kind, ARM_Database.Deleted_Inserted_Number)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) and then (not Format_Object.Number_Paragraphs) then -- No delete messages ever in this case, so -- display nothing, period. Display_It := False; -- Check if any Ref's already exist; see above. Dump_References (Format_Object.References); else Display_It := Format_Object.Include_Annotations; end if; else --This reference is too new, ignore it. Display_It := False; end if; -- Handle zero or more "Ref" parameters. loop ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then exit; -- No more commands. else ARM_Input.Replace_Char (Input_Object); end if; Gen_Ref_or_ARef_Parameter (Display_It); -- Read (and possibly generate) a "Ref" or "ARef" parameter. end loop; -- Now, close the command. -- Ch was read when checking for commas, above. if Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Chgref on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Change_Reference" record. end; when Change_Note => -- Skip the contents of this command. ARM_Input.Skip_until_Close_Char (Input_Object, Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Change_Note" record. when Change_Implementation_Defined => -- This command is of the form: -- @chgimpldef{Version=[<version>], Kind=(<kind>), -- Text=(<text>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. Gen_Chg_xxxx (Param_Cmd => Change_Impdef_Text_Param, AARM_Prefix => "Implementation defined: "); when Change_Implementation_Advice => -- This command is of the form: -- @chgimpladvice{Version=[<version>], Kind=(<kind>), -- Text=(<text>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. Gen_Chg_xxxx (Param_Cmd => Change_Impladv_Text_Param, AARM_Prefix => "Implementation Advice: "); when Change_Documentation_Requirement => -- This command is of the form: -- @chgdocreq{Version=[<version>], Kind=(<kind>), -- Text=(<text>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. Gen_Chg_xxxx (Param_Cmd => Change_Docreq_Text_Param, AARM_Prefix => "Documentation Requirement: "); when Change_Aspect_Description => -- This command is of the form: -- @chgaspectdesc{Version=[<version>], Kind=(<kind>), -- Aspect=[<name>],Text=(<text>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, <Name> is the aspect -- name, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. Gen_Chg_xxxx (Param_Cmd => Change_AspectDesc_Text_Param, AARM_Prefix => "Aspect Description for "); when Change_Attribute => -- @ChgAttribute{Version=[<version>], Kind=(<kind>), -- Chginannex=[T|F],Leading=[T|F], -- Prefix=<Prefix>,AttrName=<Name>, -- {[A]Ref=[<DR_Number>]},Text=<Text>} -- Defines a changed attribute. declare Close_Ch : Character; Key : ARM_Index.Index_Key; Chg_in_Annex : Boolean; Is_Leading : Boolean; Kind : ARM_Database.Paragraph_Change_Kind_Type; Version : ARM_Contents.Change_Version_Type; Display_Ref : Boolean; Which_Param : ARM_Input.Param_Num; References : Reference_Ptr := null; procedure Make_Attribute_Text is -- Generate the attribute text. -- Output <Prefix>'<Name> as the hanging text. -- Generate the needed index entries. begin Check_Paragraph; ARM_Output.Ordinary_Text (Output_Object, Format_Object.Attr_Prefix (1 .. Format_Object.Attr_Prefix_Len)); ARM_Output.Ordinary_Character (Output_Object, '''); ARM_Output.Ordinary_Text (Output_Object, Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len)); ARM_Output.End_Hang_Item (Output_Object); Format_Object.Last_Non_Space := False; -- Treat like start of a line. ARM_Index.Add (Term => "attributes", Subterm => Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len), Kind => ARM_Index.Primary_Term_and_Subterm, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); ARM_Index.Add (Term => Format_Object.Attr_Name (1 .. Format_Object.Attr_Name_Len) & " attribute", Kind => ARM_Index.Primary_Term, Clause => Clause_String (Format_Object), Paragraph => Paragraph_String, Key => Key); ARM_Output.Index_Target (Output_Object, Key); Make_References (References, Format_Object, Output_Object); end Make_Attribute_Text; begin Check_End_Paragraph; -- This is always a paragraph end. Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". Get_Change_Kind (Kind); -- Read a parameter named "Kind". if Version <= Format_Object.Change_Version then Format_Object.Next_Paragraph_Version := Version; Format_Object.Next_Paragraph_Change_Kind := Kind; if (ARM_Database."=" (Kind, ARM_Database.Deleted_No_Delete_Message) or else ARM_Database."=" (Kind, ARM_Database.Deleted_Inserted_Number_No_Delete_Message)) and then ARM_Format."=" (Format_Object.Changes, ARM_Format.New_Only) then -- In this case, display nothing, period. Display_Ref := False; else Display_Ref := Format_Object.Include_Annotations; end if; else --This reference is too new, ignore it. Display_Ref := False; end if; Get_Boolean ("ChginAnnex" & (11..ARM_Input.Command_Name_Type'Last => ' '), Chg_in_Annex); -- Read a boolean parameter. if Chg_in_Annex then Format_Object.Attr_Change_Kind := Kind; Format_Object.Attr_Version := Version; else -- don't save the change info.; it only applies here. Format_Object.Attr_Change_Kind := ARM_Database.None; Format_Object.Attr_Version := '0'; end if; Get_Boolean ("Leading" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_Leading); -- Read a boolean parameter. if Is_Leading then Format_Object.Space_After := ARM_Output.Narrow; Format_Object.Attr_Leading := True; else Format_Object.Space_After := ARM_Output.Normal; Format_Object.Attr_Leading := False; end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Prefix" & (7..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save prefix: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Attr_Prefix, Format_Object.Attr_Prefix_Len); -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "AttrName" & (9..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Save name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Format_Object.Attr_Name, Format_Object.Attr_Name_Len); -- else no parameter. Weird. end if; -- Handle the Ref and ARef parameters, until -- the Text parameter shows up. loop ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "Ref" & (4..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "ARef" & (5..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_3 => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if (Which_Param = 1 or else Which_Param = 2) and then Close_Ch /= ' ' then declare Ref_Name : ARM_Input.Command_Name_Type; Len : Natural := 0; New_Ref, Cursor : Reference_Ptr; Ch : Character; begin -- Get the reference: loop ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Len := Len + 1; if Len > Ref_Name'Last then Ada.Text_IO.Put_Line (" ** Reference too long on line " & ARM_Input.Line_String (Input_Object)); else Ref_Name(Len) := Ch; end if; else -- End of the reference. if Len = 0 then Ada.Text_IO.Put_Line (" ** Failed to find reference on line " & ARM_Input.Line_String (Input_Object)); end if; exit; end if; end loop; if Display_Ref then -- Save a reference for outputting -- later. New_Ref := Allocate_Reference; New_Ref.all := (Ref_Name => Ref_Name, Ref_Len => Len, Is_DR_Ref => (Which_Param = 1), -- DR reference if Param = 1; -- AI reference otherwise. Next => null); -- Attach this to the *end* of the list. if References = null then References := New_Ref; else Cursor := References; while Cursor.Next /= null loop Cursor := Cursor.next; end loop; Cursor.Next := New_Ref; end if; -- else don't display it. end if; end; else exit; -- We found "Text" (or an error) end if; end loop; case Format_Object.Attr_Change_Kind is when ARM_Database.None | ARM_Database.Revised | ARM_Database.Revised_Inserted_Number => -- The prefix is unchanged. Make_Attribute_Text; if Close_Ch /= ' ' then -- Now, handle the parameter: -- The text goes to the file *and* is recorded. Arm_Input.Start_Recording (Input_Object); -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Attribute_Text_Param, Close_Ch => Close_Ch); end if; when ARM_Database.Inserted | ARM_Database.Inserted_Normal_Number => -- The insertion has to be both here and in the -- Annex. if not Chg_in_Annex then Ada.Text_IO.Put_Line (" ** Attribute adding in text, but not in Annex??? on line " & ARM_Input.Line_String (Input_Object)); end if; if Close_Ch /= ' ' then -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Attribute_Text_Param, Close_Ch => Close_Ch); declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Close_Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. elsif Disposition = ARM_Output.None then -- Display the text normally. Make_Attribute_Text; -- Nothing special to do (normal text). elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. -- We assume non-empty text and no outer changes; -- set new change state: Format_Object.Text_Format.Change := ARM_Output.Insertion; Format_Object.Text_Format.Version := Version; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- Change the state *before* outputting the -- paragraph header, so the AARM prefix is included. ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); Make_Attribute_Text; -- Reset the state to normal: Format_Object.Text_Format.Change := ARM_Output.None; Format_Object.Text_Format.Version := '0'; Format_Object.Text_Format.Added_Version := '0'; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); end if; end; -- The text goes to the file *and* is recorded. Arm_Input.Start_Recording (Input_Object); -- else no parameter. Do nothing. end if; when ARM_Database.Deleted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_No_Delete_Message | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => Ada.Text_IO.Put_Line (" ** Attribute deleting not implemented on line " & ARM_Input.Line_String (Input_Object)); -- This should work very similarly to the above. -- If disposition is do not display text, -- do not generate or store attribute in DB. -- That would require changes to Attribute_Text_Param. Make_Attribute_Text; if Close_Ch /= ' ' then -- Now, handle the parameter: -- The text goes to the file *and* is recorded. Arm_Input.Start_Recording (Input_Object); -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Attribute_Text_Param, Close_Ch => Close_Ch); end if; end case; end; when Change_Prefix_Type => -- This command is of the form: -- @chgprefixtype{Version=[<version>], Kind=(<kind>), -- Text=(<text>)}} -- where <version> is a single character, <Kind> is one -- of Revised, Added, or Deleted, and this is followed -- by the text. As usual, any of the -- allowed bracketing characters can be used. declare Close_Ch : Character; begin Get_Change_Version (Is_First => True, Version => Format_Object.Attr_Prefix_Version); -- Read a parameter named "Version". Get_Change_Kind (Format_Object.Attr_Prefix_Change_Kind); -- Read a parameter named "Kind". ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Stack it so we can process the end: Set_Nesting_for_Parameter (Command => Change_Prefix_Text_Param, Close_Ch => Close_Ch); ARM_Input.Start_Recording (Input_Object); -- else no parameter. Weird. end if; end; when Added_Implementation_Advice_List => -- This command is of the form: -- @AddedImplAdvice{Version=[v]} declare Version : ARM_Contents.Change_Version_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". DB_Report (Format_Object.ImplAdv_DB, ARM_Database.Bullet_List, Sorted => True, Added_Version => Version); end; when Added_Documentation_Requirements_List => -- This command is of the form: -- @AddedDocReq{Version=[v]} declare Version : ARM_Contents.Change_Version_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". DB_Report (Format_Object.Docreq_DB, ARM_Database.Bullet_List, Sorted => True, Added_Version => Version); end; when Added_Aspect_Description_List => -- This command is of the form: -- @AddedAspectList{Version=[v]} declare Version : ARM_Contents.Change_Version_Type; begin Get_Change_Version (Is_First => True, Version => Version); -- Read a parameter named "Version". DB_Report (Format_Object.Aspect_DB, ARM_Database.Hanging_List, Sorted => True, Added_Version => Version); end; when Latin_1 => -- The parameter is the decimal code for the Latin-1 -- character to generate. declare Value : String (1..5); Len : Natural := 0; Ch : Character; begin ARM_Input.Get_Char (Input_Object, Ch); while Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char loop Len := Len + 1; if Len > Value'Last then Ada.Text_IO.Put_Line (" ** Latin-1 value too long on line " & ARM_Input.Line_String (Input_Object)); exit; end if; Value(Len) := Ch; ARM_Input.Get_Char (Input_Object, Ch); end loop; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Latin-1" record. Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, Character'Val(Natural'Value(Value(1..Len)))); Format_Object.Last_Non_Space := True; exception when Constraint_Error => Ada.Text_IO.Put_Line (" ** Bad Latin-1 value [" & Value(1..Len) & "] on line " & ARM_Input.Line_String (Input_Object)); end; when Unicode => -- The parameter is the decimal code for the Uncode -- character to generate. declare Value : String (1..11); Len : Natural := 0; Ch : Character; begin ARM_Input.Get_Char (Input_Object, Ch); while Ch /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Close_Char loop Len := Len + 1; if Len > Value'Last then Ada.Text_IO.Put_Line (" ** Unicode value too long on line " & ARM_Input.Line_String (Input_Object)); exit; end if; Value(Len) := Ch; ARM_Input.Get_Char (Input_Object, Ch); end loop; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Remove the "Unicode" record. Check_Paragraph; ARM_Output.Unicode_Character (Output_Object, ARM_Output.Unicode_Type'Value(Value(1..Len))); Format_Object.Last_Non_Space := True; exception when Constraint_Error => Ada.Text_IO.Put_Line (" ** Bad Unicode value [" & Value(1..Len) & "] on line " & ARM_Input.Line_String (Input_Object)); end; when Ceiling => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Ceiling); Format_Object.Last_Non_Space := True; when Floor => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Floor); Format_Object.Last_Non_Space := True; when Absolute => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '|'); Format_Object.Last_Non_Space := True; when Log => Check_Paragraph; ARM_Output.Ordinary_Text (Output_Object, "log("); Format_Object.Last_Non_Space := True; when Down | Up => Ada.Text_IO.Put_Line (" ** Su(b|per)script can't occur directly, line " & ARM_Input.Line_String (Input_Object)); when New_Column | New_Page | RM_New_Page | Soft_Page | No_Prefix | No_Para_Num | Keep_with_Next | Leading | Trailing | Thin_Line | Thick_Line | Table_Last | Index_List | Syntax_Summary | Syntax_XRef | Glossary_List | Attribute_List | Pragma_List | Implementation_Defined_List | Package_List | Type_List | Subprogram_List | Exception_List | Object_List | Intro_Name | Syntax_Name | Resolution_Name | Legality_Name | Static_Name | Link_Name | Run_Name | Bounded_Name | Erroneous_Name | Req_Name | Doc_Name | Metrics_Name | Permission_Name | Advice_Name | Notes_Name | Single_Note_Name | Examples_Name | Meta_Name | Inconsistent83_Name | Incompatible83_Name | Extend83_Name | Wording83_Name | Inconsistent95_Name | Incompatible95_Name | Extend95_Name | Wording95_Name | Inconsistent2005_Name | Incompatible2005_Name | Extend2005_Name | Wording2005_Name | Inconsistent2012_Name | Incompatible2012_Name | Extend2012_Name | Wording2012_Name | Syntax_Title | Resolution_Title | Legality_Title | Static_Title | Link_Title | Run_Title | Bounded_Title | Erroneous_Title | Req_Title | Doc_Title | Metrics_Title | Permission_Title | Advice_Title | Notes_Title | Single_Note_Title | Examples_Title | Meta_Title | Inconsistent83_Title | Incompatible83_Title | Extend83_Title | Wording83_Title | Inconsistent95_Title | Incompatible95_Title | Extend95_Title | Wording95_Title | Inconsistent2005_Title | Incompatible2005_Title | Extend2005_Title | Wording2005_Title | Inconsistent2012_Title | Incompatible2012_Title | Extend2012_Title | Wording2012_Title | EM_Dash | EN_Dash | LT | LE | GT | GE | NE | PI | Times | PorM | Single_Quote | Thin_Space | Left_Quote | Right_Quote | Left_Double_Quote | Right_Double_Quote | Left_Quote_Pair | Right_Quote_Pair | Small_Dotless_I | Capital_Dotted_I => -- These commands must not have a parameter. Ada.Text_IO.Put_Line (" ** Parameter for " & Ada.Strings.Fixed.Trim (Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right) & ", line " & ARM_Input.Line_String (Input_Object)); when Unknown => Ada.Text_IO.Put_Line (" -- Unknown command (skipped) - " & Ada.Strings.Fixed.Trim (Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end case; end Process_Command_with_Parameter; procedure Process_Command_without_Parameter (Name : in ARM_Input.Command_Name_Type) is -- Process the start of a command without a parameter. The name -- of the command is Name. procedure Put_Name (Kind : Paragraph_Type) is begin Check_Paragraph; ARM_Output.Ordinary_Text (Output_Object, Data.Paragraph_Kind_Name(Kind).Str(1..Data.Paragraph_Kind_Name(Kind).Length)); Format_Object.Last_Non_Space := True; end Put_Name; procedure Put_Title (Kind : Paragraph_Type) is begin Check_Paragraph; ARM_Output.Ordinary_Text (Output_Object, Paragraph_Kind_Title(Kind).Str(1..Paragraph_Kind_Title(Kind).Length)); Format_Object.Last_Non_Space := True; end Put_Title; procedure Format_Text (Text : in String; Text_Name : in String) is -- Note: We use the state of the surrounding call. Input_Object : Arm_String.String_Input_Type; Real_Include_Annotations : Boolean := Format_Object.Include_Annotations; begin -- Don't show annotations here: Format_Object.Include_Annotations := False; Arm_String.Open (Input_Object, Text, Text_Name); -- Open the input object using a string for input. Real_Process (Format_Object, Format_State, Input_Object, Output_Object); Arm_String.Close (Input_Object); Format_Object.Include_Annotations := Real_Include_Annotations; end Format_Text; procedure DB_Report is new ARM_Database.Report (Format_Text); procedure Syn_Report is new ARM_Syntax.Report (Format_Text); procedure Syn_XRef is new ARM_Syntax.XRef (Format_Text); begin case Command (Name) is when Comment => null; -- Harmless, but still junk. when No_Prefix => Format_Object.No_Prefix := True; when No_Para_Num => Format_Object.No_Para_Num := True; when Keep_with_Next => Format_Object.Keep_with_Next := True; when Leading => Format_Object.Space_After := ARM_Output.Narrow; when Trailing => Format_Object.Space_After := ARM_Output.Wide; when New_Page => Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); when RM_New_Page => if not Format_Object.Include_Annotations then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); -- else do nothing. end if; when Soft_Page => Check_Paragraph; ARM_Output.New_Page (Output_Object, ARM_Output.Soft_Page); when New_Column => Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Column (Output_Object); when Thin_Line => Check_End_Paragraph; ARM_Output.Separator_Line (Output_Object, Is_Thin => True); when Thick_Line => Check_End_Paragraph; ARM_Output.Separator_Line (Output_Object, Is_Thin => False); when Table_Last => if Format_Object.Next_Paragraph_Format_Type = In_Table then -- If in a table, ends the second last row. ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Row_Next_is_Last); -- Eat the following LF, if any, to avoid confusing -- row ends: declare Ch : Character; begin ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Ascii.LF then ARM_Input.Replace_Char (Input_Object); end if; end; else Ada.Text_IO.Put_Line (" ** @Last command not in table, line " & ARM_Input.Line_String (Input_Object)); end if; when Index_List => -- Generate the index body. Check_End_Paragraph; ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 3); ARM_Index.Generate_Index_Body (Output_Object, Use_Paragraphs => Format_Object.Number_Paragraphs); ARM_Output.Set_Columns (Output_Object, Number_of_Columns => 1); when Syntax_Summary => --Ada.Text_IO.Put_Line ("%% Generate Syntax summary"); Syn_Report; when Syntax_XRef => --Ada.Text_IO.Put_Line ("%% Generate Syntax xref"); Syn_XRef; when Glossary_List => DB_Report (Format_Object.Glossary_DB, ARM_Database.Normal_Indexed_List, Sorted => True); when Attribute_List => DB_Report (Format_Object.Attr_DB, ARM_Database.Hanging_List, Sorted => True, No_Deleted_Paragraph_Messages => True); when Pragma_List => DB_Report (Format_Object.Pragma_DB, ARM_Database.Normal_List, Sorted => True); when Implementation_Defined_List => DB_Report (Format_Object.Impdef_DB, ARM_Database.Bullet_List, Sorted => True); when Package_List => Write_Subindex (Format_Object.Package_Index, Format_Object, Output_Object, Minimize_Lines => False); when Type_List => Write_Subindex (Format_Object.Type_Index, Format_Object, Output_Object, Minimize_Lines => False); when Subprogram_List => Write_Subindex (Format_Object.Subprogram_Index, Format_Object, Output_Object, Minimize_Lines => True); when Exception_List => Write_Subindex (Format_Object.Exception_Index, Format_Object, Output_Object, Minimize_Lines => False); when Object_List => Write_Subindex (Format_Object.Object_Index, Format_Object, Output_Object, Minimize_Lines => True); when Text_Begin | Text_End | Redundant | Part | Bold | Italic | Roman | Swiss | Fixed | Roman_Italic | Shrink | Grow | Black | Red | Green | Blue | Keyword | Non_Terminal | Non_Terminal_Format | Example_Text | Example_Comment | Up | Down | Tab_Clear | Tab_Set | New_Page_for_Version | RM_New_Page_for_Version | Not_ISO_RM_New_Page_for_Version | ISO_Only_RM_New_Page_for_Version | New_Column_for_Version | Table | Picture_Alone | Picture_Inline | Defn | RootDefn | PDefn | Defn2 | RootDefn2 | PDefn2 | Index_See | Index_See_Also | See_Other | See_Also | Index_Root_Unit | Index_Child_Unit | Index_Subprogram_Child_Unit | Index_Type | Index_Subtype | Index_Subprogram | Index_Exception | Index_Object | Index_Package | Index_Other | Index_Check | Index_Attr | Index_Pragma | Index_Aspect | Syntax_Rule | Syntax_Term | Syntax_Term_Undefined | Syntax_Prefix | Added_Syntax_Rule | Deleted_Syntax_Rule | To_Glossary | To_Glossary_Also | Change_To_Glossary | Change_To_Glossary_Also | Implementation_Defined | Prefix_Type | Reset_Prefix_Type | Attribute | Attribute_Leading | Pragma_Syntax | Added_Pragma_Syntax | Deleted_Pragma_Syntax | Labeled_Section | Labeled_Section_No_Break | Labeled_Clause | Labeled_Subclause | Labeled_Subsubclause | Labeled_Revised_Section | Labeled_Revised_Clause | Labeled_Revised_Subclause | Labeled_Revised_Subsubclause | Labeled_Added_Section | Labeled_Added_Clause | Labeled_Added_Subclause | Labeled_Added_Subsubclause | Labeled_Deleted_Clause | Labeled_Deleted_Subclause | Labeled_Deleted_Subsubclause | Labeled_Annex | Labeled_Revised_Annex | Labeled_Added_Annex | Labeled_Informative_Annex | Labeled_Revised_Informative_Annex | Labeled_Added_Informative_Annex | Labeled_Normative_Annex | Labeled_Revised_Normative_Annex | Labeled_Added_Normative_Annex | Unnumbered_Section | Subheading | Added_Subheading | Heading | Center | Right | Preface_Section | Ref_Section | Ref_Section_Number | Ref_Section_by_Number | Local_Target | Local_Link | URL_Link | AI_Link | Change | Change_Reference | Change_Note | Change_Added | Change_Deleted | Change_Implementation_Defined | Change_Implementation_Advice | Change_Documentation_Requirement | Change_Aspect_Description | Added_Implementation_Advice_List | Added_Documentation_Requirements_List | Added_Aspect_Description_List | Change_Attribute | Change_Prefix_Type | Latin_1 | Unicode | Ceiling | Floor | Absolute | Log => -- These commands must have a parameter. Ada.Text_IO.Put_Line (" ** Failed to find parameter for " & Ada.Strings.Fixed.Trim (Name, Ada.Strings.Right) & ", line " & ARM_Input.Line_String (Input_Object)); when Change_Param_Old | Change_Param_New | Change_Added_Param | Change_Deleted_Param => -- These can't get here; they represent the parameters of -- "Change" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Change parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Table_Param_Caption | Table_Param_Header | Table_Param_Body => -- These can't get here; they represent the parameters of -- "Table" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Table parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Syntax_Rule_RHS => -- This can't get here; it represents the second parameter of -- "Syn" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Syntax parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Glossary_Text_Param => -- This can't get here; it represents a parameter of -- "ToGlossary" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Glossary parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Attribute_Text_Param => -- This can't get here; it represents a parameter of -- "Attribute" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Attribute parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Impdef_Text_Param => -- This can't get here; it represents a parameter of -- "ChgImpldef" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Impdef parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Impladv_Text_Param => -- This can't get here; it represents a parameter of -- "ChgImpladv" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** Impladv parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Docreq_Text_Param => -- This can't get here; it represents a parameter of -- "ChgDocreq" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** DocReq parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_AspectDesc_Text_Param => -- This can't get here; it represents a parameter of -- "ChgAspectDesc" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** AspectDesc parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Change_Prefix_Text_Param => -- This can't get here; it represents a parameter of -- "ChgPrefixType" and can't be generated explicitly. Ada.Text_IO.Put_Line (" ** ChgPrefix parameter command?? on line " & ARM_Input.Line_String (Input_Object)); when Intro_Name => Put_Name(Introduction); when Syntax_Name => Put_Name(Syntax); when Resolution_Name => Put_Name(Resolution); when Legality_Name => Put_Name(Legality); when Static_Name => Put_Name(Static_Semantics); when Link_Name => Put_Name(Link_Time); when Run_Name => Put_Name(Run_Time); when Bounded_Name => Put_Name(Bounded_Errors); when Erroneous_Name => Put_Name(Erroneous); when Req_Name => Put_Name(Requirements); when Doc_Name => Put_Name(Documentation); when Metrics_Name => Put_Name(Metrics); when Permission_Name => Put_Name(Permissions); when Advice_Name => Put_Name(Advice); when Notes_Name => Put_Name(Notes); when Single_Note_Name => Put_Name(Single_Note); when Examples_Name => Put_Name(Examples); when Meta_Name => Put_Name(Language_Design); when Inconsistent83_Name => Put_Name(Ada83_Inconsistencies); when Incompatible83_Name => Put_Name(Ada83_Incompatibilities); when Extend83_Name => Put_Name(Ada83_Extensions); when Wording83_Name => Put_Name(Ada83_Wording); when Inconsistent95_Name => Put_Name(Ada95_Inconsistencies); when Incompatible95_Name => Put_Name(Ada95_Incompatibilities); when Extend95_Name => Put_Name(Ada95_Extensions); when Wording95_Name => Put_Name(Ada95_Wording); when Inconsistent2005_Name => Put_Name(Ada2005_Inconsistencies); when Incompatible2005_Name => Put_Name(Ada2005_Incompatibilities); when Extend2005_Name => Put_Name(Ada2005_Extensions); when Wording2005_Name => Put_Name(Ada2005_Wording); when Inconsistent2012_Name => Put_Name(Ada2012_Inconsistencies); when Incompatible2012_Name => Put_Name(Ada2012_Incompatibilities); when Extend2012_Name => Put_Name(Ada2012_Extensions); when Wording2012_Name => Put_Name(Ada2012_Wording); when Syntax_Title => Put_Title(Syntax); when Resolution_Title => Put_Title(Resolution); when Legality_Title => Put_Title(Legality); when Static_Title => Put_Title(Static_Semantics); when Link_Title => Put_Title(Link_Time); when Run_Title => Put_Title(Run_Time); when Bounded_Title => Put_Title(Bounded_Errors); when Erroneous_Title => Put_Title(Erroneous); when Req_Title => Put_Title(Requirements); when Doc_Title => Put_Title(Documentation); when Metrics_Title => Put_Title(Metrics); when Permission_Title => Put_Title(Permissions); when Advice_Title => Put_Title(Advice); when Notes_Title => Put_Title(Notes); when Single_Note_Title => Put_Title(Single_Note); when Examples_Title => Put_Title(Examples); when Meta_Title => Put_Title(Language_Design); when Inconsistent83_Title => Put_Title(Ada83_Inconsistencies); when Incompatible83_Title => Put_Title(Ada83_Incompatibilities); when Extend83_Title => Put_Title(Ada83_Extensions); when Wording83_Title => Put_Title(Ada83_Wording); when Inconsistent95_Title => Put_Title(Ada95_Inconsistencies); when Incompatible95_Title => Put_Title(Ada95_Incompatibilities); when Extend95_Title => Put_Title(Ada95_Extensions); when Wording95_Title => Put_Title(Ada95_Wording); when Inconsistent2005_Title => Put_Title(Ada2005_Inconsistencies); when Incompatible2005_Title => Put_Title(Ada2005_Incompatibilities); when Extend2005_Title => Put_Title(Ada2005_Extensions); when Wording2005_Title => Put_Title(Ada2005_Wording); when Inconsistent2012_Title => Put_Title(Ada2012_Inconsistencies); when Incompatible2012_Title => Put_Title(Ada2012_Incompatibilities); when Extend2012_Title => Put_Title(Ada2012_Extensions); when Wording2012_Title => Put_Title(Ada2012_Wording); when EM_Dash => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.EM_Dash); Format_Object.Last_Non_Space := True; when EN_Dash => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.EN_Dash); Format_Object.Last_Non_Space := True; when LE => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.LEQ); Format_Object.Last_Non_Space := True; when LT => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '<'); Format_Object.Last_Non_Space := True; when GE => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.GEQ); Format_Object.Last_Non_Space := True; when GT => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '>'); Format_Object.Last_Non_Space := True; when NE => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.NEQ); Format_Object.Last_Non_Space := True; when PI => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.PI); Format_Object.Last_Non_Space := True; when Times => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, Character'Val(183)); -- Middle Dot. Format_Object.Last_Non_Space := True; when PorM => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, Character'Val(177)); -- Plus or Minus character. Format_Object.Last_Non_Space := True; when Single_Quote => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '''); -- Single quote. Format_Object.Last_Non_Space := True; when Thin_Space => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Thin_Space); Format_Object.Last_Non_Space := True; when Small_Dotless_I => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Small_Dotless_I); Format_Object.Last_Non_Space := True; when Capital_Dotted_I => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Capital_Dotted_I); Format_Object.Last_Non_Space := True; when Left_Quote => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Quote); Format_Object.Last_Non_Space := True; when Right_Quote => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Quote); Format_Object.Last_Non_Space := True; when Left_Double_Quote => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Double_Quote); Format_Object.Last_Non_Space := True; when Right_Double_Quote => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Double_Quote); Format_Object.Last_Non_Space := True; when Left_Quote_Pair => Check_Paragraph; -- Was: To match the Ada 95 standard: --ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Quote); --ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Quote); ARM_Output.Special_Character (Output_Object, ARM_Output.Left_Double_Quote); Format_Object.Last_Non_Space := True; when Right_Quote_Pair => Check_Paragraph; -- Was: To match the Ada 95 standard: --ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Quote); --ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Quote); ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Double_Quote); Format_Object.Last_Non_Space := True; when Unknown => Ada.Text_IO.Put_Line (" -- Unknown command (skipped) - " & Ada.Strings.Fixed.Trim (Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end case; end Process_Command_without_Parameter; procedure Handle_End_of_Command is -- Unstack and handle the end of Commands. procedure Finish_and_DB_Entry (DB : in out ARM_Database.Database_Type) is -- Close the text parameter for a number of commands -- (impdef, chgimpdef, chgimpladv, chgdocreg) -- and insert the resulting string into the appropriate DB. Text_Buffer : String (1..ARM_Input.MAX_RECORDING_SIZE); Text_Buffer_Len : Natural; function DB_Clause_String return String is use type ARM_Contents.Section_Number_Type; begin if Format_Object.Clause_Number.Clause = 0 then if Format_Object.Clause_Number.Section in 0 .. 9 then return Character'Val(Character'Pos('0') + Format_Object.Clause_Number.Section) & ""; elsif Format_Object.Clause_Number.Section in 10 .. 19 then return "1" & Character'Val(Character'Pos('0') + Format_Object.Clause_Number.Section - 10); elsif Format_Object.Clause_Number.Section in 20 .. 29 then return "2" & Character'Val(Character'Pos('0') + Format_Object.Clause_Number.Section - 20); elsif Format_Object.Clause_Number.Section = 30 then return "30"; else --if Format_Object.Clause_Number.Section >= ARM_Contents.ANNEX_START then return Character'Val (Character'Pos('A') + (Format_Object.Clause_Number.Section - ARM_Contents.ANNEX_START)) & ""; end if; elsif Format_Object.Clause_Number.Subclause = 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.Clause, Format_Object.Clause_Number); elsif Format_Object.Clause_Number.Subsubclause = 0 then return ARM_Contents.Make_Clause_Number ( ARM_Contents.SubClause, Format_Object.Clause_Number); else return ARM_Contents.Make_Clause_Number ( ARM_Contents.SubsubClause, Format_Object.Clause_Number); end if; end DB_Clause_String; function Sort_Clause_String return String is Res : String(1..13); -- Always use the paragraph for sorting: begin -- The funny encoding to insure proper sorting. -- (Otherwise "10" sorts before "2". Res(1) := Character'Val (Natural(Format_Object.Clause_Number.Section) + 16#30#); Res(2) := '.'; Res(3) := Character'Val (Format_Object.Clause_Number.Clause + 16#30#); Res(4) := '.'; Res(5) := Character'Val (Format_Object.Clause_Number.Subclause + 16#30#); Res(6) := '.'; Res(7) := Character'Val (Format_Object.Clause_Number.Subsubclause + 16#30#); Res(8) := '('; Res(9) := Character'Val ((Format_Object.Next_Paragraph / 10) + 16#30#); Res(10) := Character'Val ((Format_Object.Next_Paragraph mod 10) + 16#30#); Res(11) := '.'; Res(12) := Character'Val ((Format_Object.Next_Insert_Para mod 10) + 16#30#); Res(13) := ')'; return Res; end Sort_Clause_String; function See_String return String is begin case Format_Object.Impdef_Info.Change_Kind is when ARM_Database.None | ARM_Database.Revised | ARM_Database.Revised_Inserted_Number => if Format_Object.Number_Paragraphs and then Format_Object.Impdef_Info.Command /= Aspect then return " See @RefSecbyNum{" & DB_Clause_String & "}(" & Format_Object.Impdef_Info.Paragraph_String (1..Format_Object.Impdef_Info.Paragraph_Len) & ")."; else -- No paragraph numbers. return " See @RefSecbyNum{" & DB_Clause_String & "}."; end if; when ARM_Database.Inserted | ARM_Database.Inserted_Normal_Number => if Format_Object.Number_Paragraphs and then Format_Object.Impdef_Info.Command /= Aspect then return "@Chg{Version=[" & Format_Object.Impdef_Info.Version & "], New=[ See @RefSecbyNum{" & DB_Clause_String & "}(" & Format_Object.Impdef_Info.Paragraph_String (1..Format_Object.Impdef_Info.Paragraph_Len) & ").],Old=[]}"; else -- No paragraph numbers. return "@Chg{Version=[" & Format_Object.Impdef_Info.Version & "], New=[ See @RefSecbyNum{" & DB_Clause_String & "}.],Old=[]}"; end if; when ARM_Database.Deleted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_No_Delete_Message | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => if Format_Object.Number_Paragraphs and then Format_Object.Impdef_Info.Command /= Aspect then return "@Chg{Version=[" & Format_Object.Impdef_Info.Version & "], New=[],Old=[ See @RefSecbyNum{" & DB_Clause_String & "}(" & Format_Object.Impdef_Info.Paragraph_String (1..Format_Object.Impdef_Info.Paragraph_Len) & ").]}"; else -- No paragraph numbers. return "@Chg{Version=[" & Format_Object.Impdef_Info.Version & "], New=[],Old=[ See @RefSecbyNum{" & DB_Clause_String & "}.]}"; end if; end case; end See_String; begin Arm_Input.Stop_Recording_and_Read_Result (Input_Object, Text_Buffer, Text_Buffer_Len); Text_Buffer_Len := Text_Buffer_Len - 1; -- Remove command close character. if not Format_Object.Impdef_Info.Add_to_DB then null; -- Don't add to the DB elsif Format_Object.Impdef_Info.Command = Aspect then if Format_Object.Impdef_Info.Initial_Version >= '4' then -- ** Horrible hack: We treat the aspect as inserted -- if the initial version is greater than 4 (this is -- what we need in the RM and AARM). This -- should depend on other parameters, and ideally -- be determined inside of the DB_Report code. ARM_Database.Insert (DB, Sort_Key => Format_Object.Impdef_Info.Aspect_Name(1..Format_Object.Impdef_Info.Aspect_Name_Len), Hang_Item => "@Chg{Version=[" & Format_Object.Impdef_Info.Initial_Version & "],New=[" & Format_Object.Impdef_Info.Aspect_Name(1..Format_Object.Impdef_Info.Aspect_Name_Len) & "],Old=[]}", Text => Text_Buffer(1..Text_Buffer_Len) & See_String, Change_Kind => Format_Object.Impdef_Info.Change_Kind, Version => Format_Object.Impdef_Info.Version, Initial_Version => Format_Object.Impdef_Info.Initial_Version); else -- Normal ARM_Database.Insert (DB, Sort_Key => Format_Object.Impdef_Info.Aspect_Name(1..Format_Object.Impdef_Info.Aspect_Name_Len), Hang_Item => Format_Object.Impdef_Info.Aspect_Name(1..Format_Object.Impdef_Info.Aspect_Name_Len), Text => Text_Buffer(1..Text_Buffer_Len) & See_String, Change_Kind => Format_Object.Impdef_Info.Change_Kind, Version => Format_Object.Impdef_Info.Version, Initial_Version => Format_Object.Impdef_Info.Initial_Version); end if; else ARM_Database.Insert (DB, Sort_Key => Sort_Clause_String, Hang_Item => "", Text => Text_Buffer(1..Text_Buffer_Len) & See_String, Change_Kind => Format_Object.Impdef_Info.Change_Kind, Version => Format_Object.Impdef_Info.Version, Initial_Version => Format_Object.Impdef_Info.Initial_Version); end if; -- Finish the text processing: if Format_Object.Impdef_Info.Add_to_DB and Format_Object.Include_Annotations then -- End the annotation: Check_End_Paragraph; if Format_Object.Next_Paragraph_Subhead_Type /= Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph then Format_Object.Last_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph; -- else still in same subhead, leave alone. (If -- we didn't do this, we'd output the subhead -- multiple times). end if; Format_Object.Next_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph; Format_Object.Next_Paragraph_Format_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format; Format_Object.Paragraph_Tab_Stops := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops; -- else nothing started, nothing to finish. end if; -- Clear the Impdef information: Format_Object.Impdef_Info := (Command => None); end Finish_and_DB_Entry; begin case Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command is when Redundant => if Format_Object.Include_Annotations then Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, ']'); -- else ignored. end if; when Bold | Italic | Roman | Swiss | Fixed | Roman_Italic | Shrink | Grow | Up | Down | Black | Red | Green | Blue | Keyword | Non_Terminal | Non_Terminal_Format | Example_Text | Example_Comment => -- Formatting commands; revert to the previous (saved) -- version: Check_Paragraph; Format_Object.Text_Format := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Text_Format; ARM_Output.Text_Format (Output_Object, Format => Format_Object.Text_Format); when Subheading | Heading => -- Restore the format. Check_Paragraph; ARM_Output.Text_Format (Output_Object, Format => ARM_Output.NORMAL_FORMAT); Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Check_End_Paragraph; when Added_Subheading => -- Restore the format. declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- The new text was ignored. null; -- Nothing to do (we nulled out the text before we got here). elsif Disposition = ARM_Output.None then -- Display the text normally. Check_Paragraph; ARM_Output.Text_Format (Output_Object, Format => ARM_Output.NORMAL_FORMAT); Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Check_End_Paragraph; elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. Check_Paragraph; ARM_Output.Text_Format (Output_Object, Format => ARM_Output.NORMAL_FORMAT); Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Check_End_Paragraph; end if; end; when Center | Right => -- Close the paragraph. Check_End_Paragraph; when New_Page_for_Version => -- The version parameter is stored in Change_Version on -- the stack. if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version = Format_Object.Change_Version then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); -- else do nothing. end if; when RM_New_Page_for_Version => -- The version parameter is stored in Change_Version on -- the stack. if not Format_Object.Include_Annotations and then Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version = Format_Object.Change_Version then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); -- else do nothing. end if; when Not_ISO_RM_New_Page_for_Version => -- The version parameter is stored in Change_Version on -- the stack. if not Format_Object.Include_Annotations and then not Format_Object.Include_ISO and then Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version = Format_Object.Change_Version then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); -- else do nothing. end if; when ISO_Only_RM_New_Page_for_Version => -- The version parameter is stored in Change_Version on -- the stack. if not Format_Object.Include_Annotations and then Format_Object.Include_ISO and then Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version = Format_Object.Change_Version then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Page (Output_Object, ARM_Output.Any_Page); -- else do nothing. end if; when New_Column_for_Version => -- The version parameter is stored in Change_Version on -- the stack. if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version = Format_Object.Change_Version then Check_End_Paragraph; -- End any paragraph that we're in. ARM_Output.New_Column (Output_Object); -- else do nothing. end if; when Table_Param_Caption => ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Caption); Format_Object.Last_Non_Space := False; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Unstack the "Caption" parameter. --Ada.Text_IO.Put_Line (" &Unstack (Tab Cap)"); -- Check and handle the following "Headers" parameter: declare Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Headers" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter. -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Table_Param_Header, Close_Ch => Ch); -- No processing needed here. -- else no parameter. Weird. end if; return; -- We've already done the unstacking. end; when Table_Param_Header => ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Header); Format_Object.Last_Non_Space := False; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Unstack the "Header" parameter. --Ada.Text_IO.Put_Line (" &Unstack (Tab Head)"); -- Check and handle the following "Body" parameter: declare Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Body" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter. -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Table_Param_Body, Close_Ch => Ch); -- No processing needed here. -- else no parameter. Weird. end if; return; -- We've already done the unstacking. end; when Table_Param_Body => -- Close the table: ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Table); Format_Object.Last_Non_Space := False; -- Reset the paragraph format (and skip over the parameter records): Format_Object.Last_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Old_Last_Subhead_Paragraph; Format_Object.Next_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Old_Next_Subhead_Paragraph; Format_Object.Next_Paragraph_Format_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Old_Next_Paragraph_Format; Format_Object.Paragraph_Tab_Stops := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Old_Tab_Stops; Format_Object.In_Paragraph := False; -- End fake paragraph. Format_Object.No_Start_Paragraph := False; when Syntax_Rule_RHS => -- Send the production to the syntax manager. -- Other processing has already been handled. declare Text_Buffer : String (1..ARM_Input.MAX_RECORDING_SIZE); Text_Buffer_Len : Natural; Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin -- Calculate Disposition: if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = Syntax_Rule then Disposition := ARM_Output.None; -- Normal text. elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = Added_Syntax_Rule then Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); else -- Deleted_Syntax_Rule Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); end if; if Disposition = Do_Not_Display_Text then -- The text was ignored and skipped. -- Set the Non-terminal to empty: Format_Object.Syntax_NT_Len := 0; Format_Object.Syntax_Tab_Len := 0; else Arm_Input.Stop_Recording_and_Read_Result (Input_Object, Text_Buffer, Text_Buffer_Len); Text_Buffer_Len := Text_Buffer_Len - 1; -- Remove command close character. if Disposition = ARM_Output.None then -- Display the text normally. ARM_Syntax.Insert_Rule (For_Clause => Clause_String (Format_Object), Rule => "@ntf{" & Format_Object.Syntax_NT(1..Format_Object.Syntax_NT_Len) & " ::=} " & Text_Buffer(1..Text_Buffer_Len), Tabset => Format_Object.Syntax_Tab(1..Format_Object.Syntax_Tab_Len)); elsif Disposition = ARM_Output.Deletion then ARM_Syntax.Insert_Rule (For_Clause => Clause_String (Format_Object), Rule => "@ntf{" & Format_Object.Syntax_NT(1..Format_Object.Syntax_NT_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version & "],New=[],Old=[ ::=]}} " & Text_Buffer(1..Text_Buffer_Len), Tabset => Format_Object.Syntax_Tab(1..Format_Object.Syntax_Tab_Len)); else -- Insertion. ARM_Syntax.Insert_Rule (For_Clause => Clause_String (Format_Object), Rule => "@ntf{" & Format_Object.Syntax_NT(1..Format_Object.Syntax_NT_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version & "],New=[ ::=],Old=[]}} " & Text_Buffer(1..Text_Buffer_Len), Tabset => Format_Object.Syntax_Tab(1..Format_Object.Syntax_Tab_Len)); end if; -- Note: The LHS non-terminals aren't linked as usual. Check_End_Paragraph; -- End the paragraph, so the -- next rule gets its own. -- Reset the paragraph format: Format_Object.Last_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph; Format_Object.Next_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph; Format_Object.Next_Paragraph_Format_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format; Format_Object.Paragraph_Tab_Stops := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops; -- Set the Non-terminal to empty: Format_Object.Syntax_NT_Len := 0; Format_Object.Syntax_Tab_Len := 0; end if; end; when Syntax_Prefix => -- Reset the style: Check_Paragraph; Format_Object.Text_Format.Italic := False; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); when Glossary_Text_Param => -- Save the glossary entry in the Glossary database. if not Format_Object.Glossary_Info.Active then Ada.Text_IO.Put_Line (" ** Not in glossary command at end of glossary command!? on line " & ARM_Input.Line_String (Input_Object)); -- else OK. end if; declare use type ARM_Database.Paragraph_Change_Kind_Type; Text_Buffer : String (1..ARM_Input.MAX_RECORDING_SIZE); Text_Buffer_Len : Natural; begin Arm_Input.Stop_Recording_and_Read_Result (Input_Object, Text_Buffer, Text_Buffer_Len); Text_Buffer_Len := Text_Buffer_Len - 1; -- Remove command close character. if Format_Object.Glossary_Info.Add_to_Glossary then if Format_Object.Glossary_Info.Change_Kind = ARM_Database.Inserted then ARM_Database.Insert (Format_Object.Glossary_DB, Sort_Key => Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len), Hang_Item => "", Text => "@chg{Version=[" & Format_Object.Glossary_Info.Version & "],New=[@b{" & Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len) & ".}],Old=[]} " & Text_Buffer(1..Text_Buffer_Len), Change_Kind => Format_Object.Glossary_Info.Change_Kind, Version => Format_Object.Glossary_Info.Version, Initial_Version => Format_Object.Glossary_Info.Version); elsif Format_Object.Glossary_Info.Change_Kind = ARM_Database.Deleted then ARM_Database.Insert (Format_Object.Glossary_DB, Sort_Key => Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len), Hang_Item => "", Text => "@chg{Version=[" & Format_Object.Glossary_Info.Version & "],New=[],Old=[@b{" & Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len) & ".}]} " & Text_Buffer(1..Text_Buffer_Len), Change_Kind => Format_Object.Glossary_Info.Change_Kind, Version => Format_Object.Glossary_Info.Version); elsif Format_Object.Glossary_Info.Change_Kind = ARM_Database.None then ARM_Database.Insert (Format_Object.Glossary_DB, Sort_Key => Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len), Hang_Item => "", Text => "@b{" & Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len) & ".} " & Text_Buffer(1..Text_Buffer_Len), Change_Kind => ARM_Database.None); else ARM_Database.Insert (Format_Object.Glossary_DB, Sort_Key => Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len), Hang_Item => "", Text => "@b{" & Format_Object.Glossary_Info.Term(1..Format_Object.Glossary_Info.Term_Len) & ".} " & Text_Buffer(1..Text_Buffer_Len), Change_Kind => Format_Object.Glossary_Info.Change_Kind, Version => Format_Object.Glossary_Info.Version); end if; end if; end; -- Finish the text processing: if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = To_Glossary_Also or else Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Command = Change_To_Glossary_Also then null; -- Normal text, no special handling needed. else if Format_Object.Glossary_Info.Displayed then -- End the annotation. Check_End_Paragraph; Format_Object.Last_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Last_Subhead_Paragraph; Format_Object.Next_Paragraph_Subhead_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Subhead_Paragraph; Format_Object.Next_Paragraph_Format_Type := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Next_Paragraph_Format; Format_Object.Paragraph_Tab_Stops := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Old_Tab_Stops; else null; -- No text, no special handling needed. end if; end if; -- Remove glossary information as the command is finished: Format_Object.Glossary_Info := (Active => False, Change_Kind => ARM_Database.None); when Attribute_Text_Param => declare Text_Buffer : String (1..ARM_Input.MAX_RECORDING_SIZE); Text_Buffer_Len : Natural; function Chg_Command (Kind : in ARM_Database.Paragraph_Change_Kind_Type; Version : in Character) return String is begin case Kind is when ARM_Database.None => return ""; when ARM_Database.Inserted | ARM_Database.Inserted_Normal_Number => return "@Chgref{Version=[" & Version & "],Kind=[Added]}"; when ARM_Database.Deleted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_No_Delete_Message | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => return "@Chgref{Version=[" & Version & "],Kind=[Deleted]}"; when ARM_Database.Revised | ARM_Database.Revised_Inserted_Number => return "@Chgref{Version=[" & Version & "],Kind=[Revised]}"; end case; end Chg_Command; procedure Write_to_DB (Prefix_Kind, Text_Kind : in ARM_Database.Paragraph_Change_Kind_Type; Prefix_Version, Text_Version : in Character) is -- Write the item to the DB; use Prefix_Kind and -- Text_Kind for the change kind. Init_Version : Character; function Sort_Key return String is -- Generate a Sort Key so that these sort -- as they did in Ada 95. begin if Format_Object.Attr_Prefix_Len > 2 and then Format_Object.Attr_Prefix(2) = ''' then -- Class-wide prefix. For some reason, this -- sorts before the main item in the Ada 95 RM. -- (And this continues in later RMs.) return Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len) & ''' & Character'Pred(Format_Object.Attr_Prefix(1)) & "'Class"; -- Sort by name, then by prefix. else return Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len) & ''' & Format_Object.Attr_Prefix(1..Format_Object.Attr_Prefix_Len); -- Sort by name, then by prefix. end if; -- Note: Ada 2005 sorted E'Identity and T'Identity -- backwards from Ada 95. This will fix that. end Sort_Key; begin -- Guess the Initial_Version (eventually, we'll -- add this as an optional parameter): case Prefix_Kind is when ARM_Database.Revised_Inserted_Number | ARM_Database.Inserted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => Init_Version := Prefix_Version; --Ada.Text_IO.Put_Line ("-- Inserted."); when ARM_Database.None | ARM_Database.Revised | ARM_Database.Inserted_Normal_Number | ARM_Database.Deleted | ARM_Database.Deleted_No_Delete_Message => --Ada.Text_IO.Put_Line ("-- Normal."); Init_Version := '0'; end case; if Format_Object.Attr_Leading then ARM_Database.Insert (Format_Object.Attr_DB, Sort_Key => Sort_Key, Hang_Item => Format_Object.Attr_Prefix(1..Format_Object.Attr_Prefix_Len) & ''' & Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len), Text => "For " & Format_Object.Prefix_Text(1..Format_Object.Prefix_Text_Len) & ":" & Ascii.LF & Ascii.LF & Chg_Command (Text_Kind, Text_Version) & "@leading@noprefix@;" & Text_Buffer(1..Text_Buffer_Len) & " See @RefSecbyNum{" & Clause_String(Format_Object) & "}.", Change_Kind => Prefix_Kind, Version => Prefix_Version, Initial_Version => Init_Version); else -- not leading: ARM_Database.Insert (Format_Object.Attr_DB, Sort_Key => Sort_Key, Hang_Item => Format_Object.Attr_Prefix(1..Format_Object.Attr_Prefix_Len) & ''' & Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len), Text => "For " & Format_Object.Prefix_Text(1..Format_Object.Prefix_Text_Len) & ":" & Ascii.LF & Ascii.LF & Chg_Command (Text_Kind, Text_Version) & "@noprefix@;" & Text_Buffer(1..Text_Buffer_Len) & " See @RefSecbyNum{" & Clause_String(Format_Object) & "}.", Change_Kind => Prefix_Kind, Version => Prefix_Version, Initial_Version => Init_Version); end if; end Write_to_DB; use type ARM_Database.Paragraph_Change_Kind_Type; begin Arm_Input.Stop_Recording_and_Read_Result (Input_Object, Text_Buffer, Text_Buffer_Len); Text_Buffer_Len := Text_Buffer_Len - 1; -- Remove command close character. --Ada.Text_IO.Put_Line ("&& Attr: " & Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len) & -- " Prefix kind=" & ARM_Database.Paragraph_Change_Kind_Type'Image(Format_Object.Attr_Prefix_Change_Kind) & -- " Attr chg kind=" & ARM_Database.Paragraph_Change_Kind_Type'Image(Format_Object.Attr_Change_Kind)); case Format_Object.Attr_Change_Kind is when ARM_Database.None | ARM_Database.Revised | ARM_Database.Revised_Inserted_Number => -- Ordinary text processing is fine for the local text. Write_to_DB (Prefix_Kind => Format_Object.Attr_Prefix_Change_Kind, Text_Kind => Format_Object.Attr_Change_Kind, Prefix_Version => Format_Object.Attr_Prefix_Version, Text_Version => Format_Object.Attr_Version); when ARM_Database.Inserted | ARM_Database.Inserted_Normal_Number => declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_Object.Attr_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then null; -- Do *not* put this into the DB. --Ada.Text_IO.Put_Line (" Inserted: Ignore"); elsif Disposition = ARM_Output.None then --Ada.Text_IO.Put_Line (" Inserted: Normal"); -- Normal reference: Write_to_DB (Prefix_Kind => ARM_Database.Inserted, Text_Kind => ARM_Database.Inserted, Prefix_Version => Format_Object.Attr_Version, Text_Version => Format_Object.Attr_Version); -- We could get away without any -- insert, except that then the paragraph -- numbers would be wrong. Note (as below), -- the whole thing is an insertion, so -- we ignore the prefix kind and version and force this -- to have an inserted kind. elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. -- Write inserted text: -- We need to mark everything with -- the kind and version of the *entire* insertion, -- because the entire thing is an -- insertion. (So we ignore the prefix kind and version). --Ada.Text_IO.Put_Line (" Inserted: Inserted version:" & Format_Object.Attr_Version); if Format_Object.Attr_Leading then ARM_Database.Insert (Format_Object.Attr_DB, Sort_Key => Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len), Hang_Item => "@ChgAdded{Version=[" & Format_Object.Attr_Version & "],Text=[" & Format_Object.Attr_Prefix(1..Format_Object.Attr_Prefix_Len) & ''' & Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len) & "]}", Text => "@ChgAdded{Version=[" & Format_Object.Attr_Version & "],Text=[" & "For " & Format_Object.Prefix_Text(1..Format_Object.Prefix_Text_Len) & ":]}" & Ascii.LF & Ascii.LF & Chg_Command (Format_Object.Attr_Change_Kind, Format_Object.Attr_Version) & "@leading@noprefix@;" & Text_Buffer(1..Text_Buffer_Len) & " See @RefSecbyNum{" & Clause_String(Format_Object) & "}.", Change_Kind => Format_Object.Attr_Change_Kind, Version => Format_Object.Attr_Version, Initial_Version => Format_Object.Attr_Version); else -- not leading: ARM_Database.Insert (Format_Object.Attr_DB, Sort_Key => Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len), Hang_Item => "@ChgAdded{Version=[" & Format_Object.Attr_Version & "],Text=[" & Format_Object.Attr_Prefix(1..Format_Object.Attr_Prefix_Len) & ''' & Format_Object.Attr_Name(1..Format_Object.Attr_Name_Len) & "]}", Text => "@ChgAdded{Version=[" & Format_Object.Attr_Version & "],Text=[" & "For " & Format_Object.Prefix_Text(1..Format_Object.Prefix_Text_Len) & ":]}" & Ascii.LF & Ascii.LF & Chg_Command (Format_Object.Attr_Change_Kind, Format_Object.Attr_Version) & "@noprefix@;" & Text_Buffer(1..Text_Buffer_Len) & " See @RefSecbyNum{" & Clause_String(Format_Object) & "}.", Change_Kind => Format_Object.Attr_Change_Kind, Version => Format_Object.Attr_Version, Initial_Version => Format_Object.Attr_Version); end if; end if; end; when ARM_Database.Deleted | ARM_Database.Deleted_Inserted_Number | ARM_Database.Deleted_No_Delete_Message | ARM_Database.Deleted_Inserted_Number_No_Delete_Message => -- *** We don't support this yet. (It doesn't make much sense; -- *** it would be unlikely that we'd stop defining -- *** an attribute). Write_to_DB (Prefix_Kind => Format_Object.Attr_Prefix_Change_Kind, Text_Kind => Format_Object.Attr_Change_Kind, Prefix_Version => Format_Object.Attr_Prefix_Version, Text_Version => Format_Object.Attr_Version); end case; end; when Pragma_Syntax | Added_Pragma_Syntax | Deleted_Pragma_Syntax => -- Note: Pragma_Syntax is not recorded in the syntax summary. declare Text_Buffer : String (1..ARM_Input.MAX_RECORDING_SIZE); Text_Buffer_Len : Natural; function My_Sort return String is -- Find and return the @prag argument. begin for I in 1 .. Text_Buffer_Len - 7 loop if Text_Buffer(I) = '@' and then (Text_Buffer(I+1) = 'p' or else Text_Buffer(I+1) = 'P') and then (Text_Buffer(I+2) = 'r' or else Text_Buffer(I+2) = 'R') and then (Text_Buffer(I+3) = 'a' or else Text_Buffer(I+3) = 'A') and then (Text_Buffer(I+4) = 'g' or else Text_Buffer(I+4) = 'G') and then ARM_Input.Is_Open_Char (Text_Buffer(I+5)) then -- Found @prag. for J in I+6 .. Text_Buffer_Len loop if Text_Buffer(J) = ARM_Input.Get_Close_Char (Text_Buffer(I+5)) then return Text_Buffer(I+6 .. J-1); end if; end loop; Ada.Text_IO.Put_Line ("** Can't find argument for @prag: " & Text_Buffer(1..Text_Buffer_Len) & " on line " & ARM_Input.Line_String (Input_Object)); return ""; -- Never found the end of the argument. -- else not @prag, keep looking. end if; end loop; -- If we get here, we never found "@prag" Ada.Text_IO.Put_Line ("** Funny pragma format: " & Text_Buffer(1..Text_Buffer_Len) & " on line " & ARM_Input.Line_String (Input_Object)); return ""; -- Gotta return something. end My_Sort; begin Arm_Input.Stop_Recording_and_Read_Result (Input_Object, Text_Buffer, Text_Buffer_Len); Text_Buffer_Len := Text_Buffer_Len - 1; -- Remove command close character. -- Ordinary text processing is fine for the local text. if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Pragma_Syntax then ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => Text_Buffer(1..Text_Buffer_Len) & " @em See @RefSecbyNum{" & Clause_String(Format_Object) & "}."); elsif Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Added_Pragma_Syntax then declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then null; -- Not in old versions, omit from Annex. elsif Disposition = ARM_Output.None then -- Normal reference: ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],Kind=[Added]}" & Text_Buffer(1..Text_Buffer_Len) & " @em See @RefSecbyNum{" & Clause_String(Format_Object) & "}."); -- Note: We still need the @ChgRef in order -- to get the paragraph numbers right. elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],Kind=[Added]}" & Text_Buffer(1..Text_Buffer_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],New=[" & " @em See @RefSecbyNum<" & Clause_String(Format_Object) & ">.],Old=[]}"); -- Note: Text includes any needed @Chg commands. end if; end; else --if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Command = Deleted_Pragma_Syntax then declare Add_Disposition : ARM_Output.Change_Type; Del_Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; function Para_Kind return String is begin if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version = '0' and then Add_Disposition /= ARM_Output.Insertion then return "Deleted"; else return "DeletedAdded"; end if; end Para_Kind; begin Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version, Operation => ARM_Output.Deletion, Text_Kind => Del_Disposition); if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version = '0' then Add_Disposition := ARM_Output.None; else Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Add_Disposition); end if; if Del_Disposition = Do_Not_Display_Text then --Ada.Text_IO.Put_Line ("%% Deleted pragma completely omitted"); if Add_Disposition /= Do_Not_Display_Text and then Format_Object.Number_Paragraphs then -- If this was in older editions, then -- we need a deletion message (and also -- to get the paragraph numbers right). -- But don't need this if there are no -- paragraph numbers (then there is no -- deleted message). --Ada.Text_IO.Put_Line (" ... but need a deletion message"); ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],Kind=[" & Para_Kind & "]}@ "); else null; -- Not at all in this version, omit from Annex. end if; elsif Del_Disposition = ARM_Output.None then --Ada.Text_IO.Put_Line ("%% Deleted pragma normal format"); -- Is the initial item inserted or normal? if Add_Disposition = ARM_Output.Insertion then --Ada.Text_IO.Put_Line ("... but inserted"); -- Inserted reference: ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version & "],Kind=[Added]}" & Text_Buffer(1..Text_Buffer_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version & "],New=[" & " @em See @RefSecbyNum<" & Clause_String(Format_Object) & ">.],Old=[]}"); else -- Anything else. -- Normal reference: if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version = '0' then ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => Text_Buffer(1..Text_Buffer_Len) & " @em See @RefSecbyNum{" & Clause_String(Format_Object) & "}."); else ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version & "],Kind=[Added]}" & Text_Buffer(1..Text_Buffer_Len) & " @em See @RefSecbyNum{" & Clause_String(Format_Object) & "}."); -- Note: We still need the @ChgRef in order -- to get the paragraph numbers right. end if; end if; elsif Del_Disposition = ARM_Output.Insertion then raise Program_Error; -- An insertion inside of a deletion command! else -- Deletion. --Ada.Text_IO.Put_Line ("%% Deleted pragma deleted text"); -- Is the initial item inserted or normal? if Add_Disposition = ARM_Output.Insertion then ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],Kind=[DeletedAdded]}" & Text_Buffer(1..Text_Buffer_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Prev_Change_Version & "],New=[" & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],New=[],Old=[" & " @em See @RefSecbyNum<" & Clause_String(Format_Object) & ">.]}],Old=[]}"); else -- Anything else. -- Just a deleted reference: ARM_Database.Insert (Format_Object.Pragma_DB, Sort_Key => My_Sort, Hang_Item => "", Text => "@ChgRef{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],Kind=[" & Para_Kind & "]}" & Text_Buffer(1..Text_Buffer_Len) & "@Chg{Version=[" & Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr).Change_Version & "],New=[],Old=[" & " @em See @RefSecbyNum<" & Clause_String(Format_Object) & ">.]}"); -- Note: We still need the @ChgRef in order -- to get the paragraph numbers right and for the deleted paragraph message. end if; end if; end; end if; end; when Implementation_Defined | Change_Impdef_Text_Param => -- Save the implementation-defined entry in the database. Finish_and_DB_Entry (Format_Object.Impdef_DB); when Change_Impladv_Text_Param => -- Save the implementation advice entry in the database. Finish_and_DB_Entry (Format_Object.Impladv_DB); when Change_Docreq_Text_Param => -- Save the documentation requirement entry in the database. Finish_and_DB_Entry (Format_Object.Docreq_DB); when Change_AspectDesc_Text_Param => -- Save the documentation requirement entry in the database. Finish_and_DB_Entry (Format_Object.Aspect_DB); when Prefix_Type | Change_Prefix_Text_Param => -- Copy the text into the Format_Object.Prefix_Text string. ARM_Input.Stop_Recording_and_Read_Result ( Input_Object, Format_Object.Prefix_Text, Format_Object.Prefix_Text_Len); Format_Object.Prefix_Text_Len := Format_Object.Prefix_Text_Len - 1; -- Remove command close character. when Change_Param_Old => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version > Format_Object.Change_Version then -- The new text was ignored, use the old only. null; -- Nothing special to do. else case Format_Object.Changes is when ARM_Format.Old_Only => null; -- Nothing special to do. when ARM_Format.New_Only => null; -- Nothing to do (we nulled out the text before we got here). when ARM_Format.Changes_Only | ARM_Format.Show_Changes | ARM_Format.New_Changes => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version < Format_Object.Change_Version and then Format_Object.Changes = ARM_Format.Changes_Only then -- Old enough that only the new text is shown. null; -- Nothing to do (we nulled out the text before we got here). else if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text then -- Non-empty text. Restore the previous -- insertion state. Format_Object.Text_Format.Change := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Change; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Change_Version; Format_Object.Text_Format.Added_Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Added_Change_Version; Check_Paragraph; -- We have to be in a paragraph -- in correct code, but this could happen -- if the user ended the paragraph by mistake -- (we've already generated an error in that case). ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- else no text. end if; end if; end case; end if; Format_Object.In_Change := Arm_Output."/=" (Format_Object.Text_Format.Change, ARM_Output.None); when Change_Param_New => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version > Format_Object.Change_Version then -- The new text was ignored. null; -- Nothing to do (we nulled out the text before we got here). else case Format_Object.Changes is when ARM_Format.Old_Only => null; -- Nothing to do (we nulled out the text before we got here). when ARM_Format.New_Only => null; -- Nothing special to do. when ARM_Format.Changes_Only | ARM_Format.Show_Changes | ARM_Format.New_Changes => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version < Format_Object.Change_Version and then Format_Object.Changes = ARM_Format.Changes_Only then -- Old enough that only the new text is shown. null; -- Nothing special to do. else if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text then -- Non-empty text. Restore the previous -- insertion state. Format_Object.Text_Format.Change := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Change; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Change_Version; Format_Object.Text_Format.Added_Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Prev_Added_Change_Version; Check_Paragraph; -- We have to be in a paragraph -- in correct code, but this could happen -- if the user ended the paragraph by mistake -- (we've already generated an error in that case). ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- else no text. end if; end if; end case; end if; Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; -- Unstack the "New" parameter. --Ada.Text_IO.Put_Line (" &Unstack (Chg New)"); -- Check and handle the following "Old" parameter: declare Ch, Ch2 : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Old" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter. -- Stack the parameter so we can process the end: Set_Nesting_for_Parameter (Command => Change_Param_Old, Close_Ch => Ch); -- Now, handle the parameter: if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version > Format_Object.Change_Version then -- The new text was ignored, show the old only. null; -- Nothing special to do. else case Format_Object.Changes is when ARM_Format.Old_Only => null; -- Nothing special to do. when ARM_Format.New_Only => -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. when ARM_Format.Changes_Only | ARM_Format.Show_Changes => if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version < Format_Object.Change_Version and then Format_Object.Changes = ARM_Format.Changes_Only then -- Old enough that only the new text is shown. -- Skip the text: ARM_Input.Skip_until_Close_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. else ARM_Input.Get_Char (Input_Object, Ch2); ARM_Input.Replace_Char (Input_Object); Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text := Ch /= Ch2; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text then -- Non-empty text; calculate new change state: (current is deletion) Check_Paragraph; -- Output the paragraph headers before changing the state. -- This can only matter for a deletion without -- an insertion; otherwise, we're already in a paragraph. case Format_Object.Text_Format.Change is when ARM_Output.Deletion | ARM_Output.None => Format_Object.Text_Format.Change := ARM_Output.Deletion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; when ARM_Output.Insertion => Format_Object.Text_Format.Change := ARM_Output.Both; Format_Object.Text_Format.Added_Version := Format_Object.Text_Format.Version; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; when ARM_Output.Both => Format_Object.Text_Format.Change := ARM_Output.Both; -- Added_Version is unchanged. Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; end case; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); -- else no text, so don't emit a change area. end if; end if; when ARM_Format.New_Changes => ARM_Input.Get_Char (Input_Object, Ch2); ARM_Input.Replace_Char (Input_Object); Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text := Ch /= Ch2; if Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Was_Text then -- Non-empty text; calculate new change state: (current is deletion) Check_Paragraph; case Format_Object.Text_Format.Change is when ARM_Output.Deletion | ARM_Output.None => Format_Object.Text_Format.Change := ARM_Output.Deletion; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; Format_Object.Text_Format.Added_Version := '0'; when ARM_Output.Insertion => Format_Object.Text_Format.Change := ARM_Output.Both; Format_Object.Text_Format.Added_Version := Format_Object.Text_Format.Version; Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; when ARM_Output.Both => Format_Object.Text_Format.Change := ARM_Output.Both; -- Added_Version is unchanged. Format_Object.Text_Format.Version := Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version; end case; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); ARM_Output.Ordinary_Character (Output_Object, ' '); -- Skip the text (we're not going to output it): ARM_Input.Skip_until_Close_Char (Input_Object, Ch); ARM_Input.Replace_Char (Input_Object); -- Let the normal termination clean this up. -- else no text, so don't emit a change area. end if; end case; end if; Format_Object.In_Change := True; -- else no parameter. Weird. end if; return; -- We've already done the unstacking. end; when Change_Added_Param => declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Format_Object.In_Change := False; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version, Operation => ARM_Output.Insertion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- The new text was ignored. null; -- Nothing to do (we nulled out the text before we got here). elsif Disposition = ARM_Output.None then -- Display the text normally. null; -- Nothing special to do. elsif Disposition = ARM_Output.Deletion then raise Program_Error; -- A deletion inside of an insertion command! else -- Insertion. -- Reset the state to normal: Format_Object.Text_Format.Change := ARM_Output.None; Format_Object.Text_Format.Version := '0'; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- We have to be in a paragraph -- in correct code, but this could happen -- if the user ended the paragraph by mistake -- (we've already generated an error in that case). ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); end if; end; when Change_Deleted_Param => declare Disposition : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Format_Object.In_Change := False; Calc_Change_Disposition ( Format_Object => Format_Object, Version => Format_State.Nesting_Stack(Format_State.Nesting_Stack_Ptr-1).Change_Version, Operation => ARM_Output.Deletion, Text_Kind => Disposition); if Disposition = Do_Not_Display_Text then -- The old text was ignored. null; -- Nothing to do (we nulled out the text before we got here). elsif Disposition = ARM_Output.None then -- Display the text normally. null; -- Nothing special to do. elsif Disposition = ARM_Output.Insertion then raise Program_Error; -- An insertion inside of a deletion command! else -- Insertion. -- Reset the state to normal: Format_Object.Text_Format.Change := ARM_Output.None; Format_Object.Text_Format.Version := '0'; Format_Object.Text_Format.Added_Version := '0'; Check_Paragraph; -- We have to be in a paragraph -- in correct code, but this could happen -- if the user ended the paragraph by mistake -- (we've already generated an error in that case). ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); end if; end; when Ceiling => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Ceiling); Format_Object.Last_Non_Space := True; when Floor => Check_Paragraph; ARM_Output.Special_Character (Output_Object, ARM_Output.Right_Floor); Format_Object.Last_Non_Space := True; when Absolute => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '|'); Format_Object.Last_Non_Space := True; when Log => Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, ')'); Format_Object.Last_Non_Space := True; when others => -- No special handling needed. null; end case; --Ada.Text_IO.Put_Line (" &Unstack (Normal)"); Format_State.Nesting_Stack_Ptr := Format_State.Nesting_Stack_Ptr - 1; end Handle_End_of_Command; procedure Process_Special is -- Process a special command/macro/tab. -- These all start with '@'. -- @xxxx is a command. It may have parameters delimited by -- (), {}, [], or <>. There does not appear to be an escape, so -- we don't have to worry about '}' being used in {} brackets, -- for example. (Must be a pain to write, though.) Command_Name : ARM_Input.Command_Name_Type; Ch : Character; use type ARM_Output.Size_Type; begin ARM_Input.Get_Char (Input_Object, Ch); if Ch = '\' then -- This represents a tab, or the end of centered text. -- (According to Bob Duff, from the Scribe manual). if Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_1 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_2 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_3 or else Format_Object.Next_Paragraph_Format_Type = Hanging_Indented_4 then -- Instead of a tab, just use this to mark the end -- of the hanging portion: Check_Paragraph; if Format_Object.In_Change then -- Close all formatting: declare Closed_Formatting : ARM_Output.Format_Type := ARM_Output.NORMAL_FORMAT; begin Closed_Formatting.Font := Format_Object.Text_Format.Font; -- No clear default for these. Closed_Formatting.Size := Format_Object.Text_Format.Size; ARM_Output.Text_Format (Output_Object, Closed_Formatting); end; end if; ARM_Output.End_Hang_Item (Output_Object); if Format_Object.In_Change then -- Reset to the normal case: ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); end if; elsif Format_Object.Next_Paragraph_Format_Type = In_Table then -- If in a table, ends a item. ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Item); -- elsif centered text: TBD. elsif ARM_Output."="(Format_Object.Paragraph_Tab_Stops, ARM_Output.NO_TABS) then Ada.Text_IO.Put_Line (" ** Tab, but no tab stops set on line " & ARM_Input.Line_String (Input_Object)); else Check_Paragraph; ARM_Output.Tab (Output_Object); end if; return; -- We're done here. elsif Ch = '=' then -- This marks the start of centered text. -- (According to Bob Duff, from the Scribe manual). -- We're not implementing this; we're just going to replace -- the handful of uses. -- We're done here. Ada.Text_IO.Put_Line (" ** Centered text unimplemented (skipped) on line " & ARM_Input.Line_String (Input_Object)); return; elsif Ch = '^' then -- This represents setting at tab stop at the current location. -- Neither HTML nor RTF supports such a thing, so these should -- all have been replaced by conventional tab stops. Ada.Text_IO.Put_Line (" && Cursor tab stop unimplemented (skipped) on line " & ARM_Input.Line_String (Input_Object)); return; elsif Ch = '@' then -- This represents @ in the text. We're done here. Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, '@'); return; elsif Ch = ' ' then -- This represents a hard space in the text. We're done here. Check_Paragraph; ARM_Output.Hard_Space (Output_Object); return; elsif Ch = ';' then -- This seems to be an end of command (or substitution) marker. -- For instance, it is used in Section 1: -- .. the distinction between @ResolutionName@;s and ... -- This converts to: -- .. the distinction between Name Resolution Rules and ... -- Without it, the 's' would append to the command name, and -- we would get the wrong command. Thus, it itself does nothing -- at all, so we're done here. return; elsif Ch = '-' then -- This represents a subscript. It has an argument. ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Name => '-' & (2..ARM_Input.Command_Name_Type'Last => ' '), Kind => Normal, Param_Ch => Ch); Check_Paragraph; Format_Object.Text_Format.Size := Format_Object.Text_Format.Size - 2; Format_Object.Text_Format.Location := ARM_Output.Subscript; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); else -- No parameter. Weird. ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find parameter for subscript, line " & ARM_Input.Line_String (Input_Object)); end if; return; elsif Ch = '+' then -- This represents a superscript. It has an argument. ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Name => '+' & (2..ARM_Input.Command_Name_Type'Last => ' '), Kind => Normal, Param_Ch => Ch); Check_Paragraph; Format_Object.Text_Format.Size := Format_Object.Text_Format.Size - 2; Format_Object.Text_Format.Location := ARM_Output.Superscript; ARM_Output.Text_Format (Output_Object, Format_Object.Text_Format); else -- No parameter. Weird. ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find parameter for superscript, line " & ARM_Input.Line_String (Input_Object)); end if; return; elsif Ch = ':' then -- According to Tucker, the Scribe manual says: -- @: After a ".", it forces the "." to be interpreted as a -- sentence-ending period rather than as an initial-ending -- period. E.g.: You are better than I.@: F. Stone is -- even better. Without the @:, the period after "I" -- would be interpreted as the period signifying an -- initial. -- -- Besides not making much sense, this certainly does nothing -- for us. return; elsif Ch = '*' then -- According to Tucker, the Scribe manual says: -- @* This forces a line break, without starting a new -- paragraph. -- Tucker thinks this is "<BR>" in HTML. if Format_Object.In_Paragraph then ARM_Output.Line_Break (Output_Object); Format_Object.Last_Non_Space := False; -- else why start a paragraph with a line break?? end if; return; elsif Ch = '|' then -- According to Tucker, the Scribe manual says: -- @| This marks a place within a word where a line break -- may be inserted, *without* inserting a hyphen. It is -- effectively a zero-length "word". You can use it to add -- spaces between words that disappear if the line gets -- broken there. For example: -- This is @| a sentence with two spaces between "is" and "a". -- The extra space will disappear if the line is broken -- between "is" and "a". -- -- However, this appears to be used mainly to insert potential -- line breaks into large words, and we use and implement it -- that way. if Format_Object.In_Paragraph then ARM_Output.Soft_Line_Break (Output_Object); Format_Object.Last_Non_Space := False; -- else don't care about non-required breaks between paragraphs. end if; return; elsif Ch = '!' then -- This marks a place within a word where a line break -- may be inserted, inserting a hyphen. if Format_Object.In_Paragraph then ARM_Output.Soft_Hyphen_Break (Output_Object); Format_Object.Last_Non_Space := False; -- else don't care about non-required breaks between paragraphs. end if; return; elsif Ch = Ascii.LF then -- Stand alone '@'. -- I now believe this is an error, perhaps a hard space where -- the trailing blank was dropped. It originally appeared in -- Infosys.MSS. Ada.Text_IO.Put_Line("** Stand-alone '@' on line " & ARM_Input.Line_String (Input_Object)); return; end if; ARM_Input.Replace_Char (Input_Object); ARM_Input.Get_Name (Input_Object, Command_Name); --Ada.Text_IO.Put_Line("!!Command=" & Ada.Strings.Fixed.Trim(Command_Name, Ada.Strings.Both)); ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Name => Ada.Characters.Handling.To_Lower (Command_Name), Kind => Normal, Param_Ch => Ch); Process_Command_with_Parameter; else ARM_Input.Replace_Char (Input_Object); Process_Command_without_Parameter (Command_Name); end if; end Process_Special; procedure Lookahead_for_End_of_Paragraph is -- Look at the command following to see if it would -- end the paragraph. If not, generate a Line_Break. -- In any case, process the command (we don't allow more than -- one call to Replace_Char). -- We can assume that we are in a paragraph. Command_Name : ARM_Input.Command_Name_Type; Ch : Character; begin ARM_Input.Get_Char (Input_Object, Ch); if Ch not in 'A' .. 'Z' and then Ch not in 'a' .. 'z' then -- Not a named command, these never end a paragraph: ARM_Input.Replace_Char (Input_Object); ARM_Output.Line_Break (Output_Object); Format_Object.Last_Non_Space := False; Process_Special; else -- Named command. ARM_Input.Replace_Char (Input_Object); ARM_Input.Get_Name (Input_Object, Command_Name); case Command (Command_Name) is when Text_Begin | Text_End | New_Page | New_Column | RM_New_Page | Thin_Line | Thick_Line | Table | Picture_Alone | To_Glossary | Change_To_Glossary | Implementation_Defined | Change_Implementation_Defined | Change_Implementation_Advice | Change_Documentation_Requirement | Labeled_Section | Labeled_Section_No_Break | Labeled_Clause | Labeled_Subclause | Labeled_Subsubclause | Labeled_Revised_Section | Labeled_Revised_Clause | Labeled_Revised_Subclause | Labeled_Revised_Subsubclause | Labeled_Added_Section | Labeled_Added_Clause | Labeled_Added_Subclause | Labeled_Added_Subsubclause | Labeled_Deleted_Clause | Labeled_Deleted_Subclause | Labeled_Deleted_Subsubclause | Preface_Section | Labeled_Annex | Labeled_Revised_Annex | Labeled_Added_Annex | Labeled_Informative_Annex | Labeled_Revised_Informative_Annex | Labeled_Added_Informative_Annex | Labeled_Normative_Annex | Labeled_Revised_Normative_Annex | Labeled_Added_Normative_Annex | Unnumbered_Section | Subheading | Heading | Center | Right => -- Ends a paragraph. No line break needed here (or -- we'd end up with two). null; when others => -- Does not end a paragraph. Put in the soft break. ARM_Output.Line_Break (Output_Object); Format_Object.Last_Non_Space := False; end case; -- Now, process the command: ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Name => Ada.Characters.Handling.To_Lower (Command_Name), Kind => Normal, Param_Ch => Ch); Process_Command_with_Parameter; else ARM_Input.Replace_Char (Input_Object); Process_Command_without_Parameter (Command_Name); end if; end if; end Lookahead_for_End_of_Paragraph; begin Reading_Loop: loop declare Char : Character; begin ARM_Input.Get_Char (Input_Object, Char); --Ada.Text_IO.Put_Line("!!Char=" & Char & " Nesting=" & Natural'Image(Format_State.Nesting_Stack_Ptr)); case Char is when '@' => Process_Special; when Ascii.LF => ARM_Input.Get_Char (Input_Object, Char); if Char /= Ascii.LF then -- Soft line break. if Format_Object.Next_Paragraph_Format_Type = Example_Text or else Format_Object.Next_Paragraph_Format_Type = Child_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Indented_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Production then -- These formats preserves all line breaks, but a -- "soft" break does not end a paragraph. if Char /= '@' or else (not Format_Object.In_Paragraph) then -- Not a paragraph end coming up: if Format_Object.In_Paragraph then ARM_Output.Line_Break (Output_Object); Format_Object.Last_Non_Space := False; -- else not in paragraph, we don't need to preserve -- the break. end if; ARM_Input.Replace_Char (Input_Object); else -- A command following, and we're in a paragraph. -- If that command ends the paragraph, then -- we don't want a soft break here (else we'd -- end up with an extra blank line at the end). -- Otherwise, we do. Lookahead_for_End_of_Paragraph; end if; elsif Format_Object.Next_Paragraph_Format_Type = In_Table then -- If in a table, ends a row. ARM_Output.Table_Marker (Output_Object, ARM_Output.End_Row); ARM_Input.Replace_Char (Input_Object); Format_Object.Last_Non_Space := False; -- There should be nothing above the table at -- this point. Complain about other commands -- (this is a signficant aid to building tables): declare Start_Depth : Natural := 1; begin --Find the table: for I in reverse 1 .. Format_State.Nesting_Stack_Ptr loop if Format_State.Nesting_Stack(I).Command = Table then Start_Depth := I; exit; end if; end loop; if Format_State.Nesting_Stack(Start_Depth+1).Command /= Table_Param_Body then Ada.Text_IO.Put_Line (" ** Wrong command on top of table, line " & ARM_Input.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Command=" & Format_State.Nesting_Stack(Start_Depth+1).Name & " Class=" & Data.Command_Type'Image(Format_State.Nesting_Stack(Start_Depth+1).Command)); elsif Format_State.Nesting_Stack_Ptr /= Start_Depth+1 then Ada.Text_IO.Put_Line (" ** Unfinished commands detected at end of row, line " & ARM_Input.Line_String (Input_Object)); end if; for I in reverse Start_Depth+2 .. Format_State.Nesting_Stack_Ptr loop Ada.Text_IO.Put_Line (" Open command=" & Format_State.Nesting_Stack(I).Name & " Class=" & Data.Command_Type'Image(Format_State.Nesting_Stack(I).Command)); end loop; end; else -- Normal paragraph: -- Output a space if the last character was -- not a space and the next character is -- not a space. Eliminate any leading blanks -- added for formatting: if Format_Object.In_Paragraph and then Format_Object.Last_Non_Space then ARM_Output.Ordinary_Character (Output_Object, ' '); Format_Object.Last_Non_Space := False; end if; -- Skip any leading spaces for the next paragraph: while Char = ' ' loop ARM_Input.Get_Char (Input_Object, Char); end loop; ARM_Input.Replace_Char (Input_Object); end if; else -- Hard paragraph break. Only one, no matter -- how many blank lines there are: while Char = Ascii.LF loop ARM_Input.Get_Char (Input_Object, Char); end loop; if Format_Object.Next_Paragraph_Format_Type = Example_Text or else Format_Object.Next_Paragraph_Format_Type = Child_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Indented_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Production then null; -- In these formats, blanks remain. else -- Also remove any leading blanks from the next -- paragraph: while Char = ' ' loop ARM_Input.Get_Char (Input_Object, Char); end loop; end if; ARM_Input.Replace_Char (Input_Object); Check_End_Paragraph; -- End the paragraph. end if; when ' ' => if Format_Object.Next_Paragraph_Format_Type = Example_Text or else Format_Object.Next_Paragraph_Format_Type = Child_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Indented_Example_Text or else Format_Object.Next_Paragraph_Format_Type = Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Display or else Format_Object.Next_Paragraph_Format_Type = Syntax_Production then -- Spaces are significant these formats. Check_Paragraph; ARM_Output.Hard_Space (Output_Object); else if Format_Object.In_Paragraph then if Format_Object.No_Start_Paragraph then -- Not really in a paragraph. Ada.Text_IO.Put_Line ("Attempt to write into a deleted paragraph, on line " & ARM_Input.Line_String (Input_Object)); -- We'll probably crash soon. null; else ARM_Output.Ordinary_Character (Output_Object, ' '); end if; -- else we never want to start a paragraph with a space. end if; end if; Format_Object.Last_Non_Space := False; when Ascii.SUB => -- End of file. exit Reading_Loop; when others => if Format_State.Nesting_Stack_Ptr /= 0 and then Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char /= ' ' and then Format_State.Nesting_Stack (Format_State.Nesting_Stack_Ptr).Close_Char = Char then -- Closing a command, remove it from the stack. Handle_End_of_Command; else Check_Paragraph; ARM_Output.Ordinary_Character (Output_Object, Char); null; -- Ordinary characters, output them. Format_Object.Last_Non_Space := True; end if; end case; end; end loop Reading_Loop; exception when ARM_Output.Not_Valid_Error => Ada.Text_IO.Put_Line ("** Output validity error processing line " & ARM_Input.Line_String (Input_Object)); raise; end Real_Process; procedure Process (Format_Object : in out Format_Type; File_Name : in String; Output_Object : in out ARM_Output.Output_Type'Class; Section_Name : in String; Section_Number : in ARM_Contents.Section_Number_Type; Starts_New_Section : in Boolean) is -- Process the contents for File_Name, writing the results to -- Output_Object. (Output_Object uses dispatching calls to provide -- the correct formatting). Section_Name is the name of the section -- for this file. Starts_New_Section is True if the file starts -- a new section. Section_Number is the number (or letter) of the -- section. Values > 20 represent annex letters (21 => A, 22 => B, etc.) Input_Object : Arm_File.File_Input_Type; Format_State : Format_State_Type; begin Ada.Text_IO.Put_Line ("-- Processing " & File_Name); begin Arm_File.Open (Input_Object, File_Name); exception when others => Ada.Text_IO.Put_Line ("** Unable to open file " & File_Name); raise; end; if Starts_New_Section then Format_Object.Clause_Number := (Section => Section_Number, Clause => 0, Subclause => 0, Subsubclause => 0); declare use type ARM_Contents.Section_Number_Type; begin if Section_Number = 0 then -- No title at all. ARM_Output.Section (Output_Object, Section_Title => "", Section_Name => Section_Name); elsif Section_Number < ARM_Contents.ANNEX_START then ARM_Output.Section (Output_Object, Section_Title => Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Title (ARM_Contents.Section, (Section => Section_Number, others => 0)), Ada.Strings.Right), Section_Name => Section_Name); else -- We don't have a way to tell between the three kinds of annexes, so we try them all: begin ARM_Output.Section (Output_Object, Section_Title => Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Title (ARM_Contents.Normative_Annex, (Section => Section_Number, others => 0)), Ada.Strings.Right), Section_Name => Section_Name); exception when ARM_Contents.Not_Found_Error => begin ARM_Output.Section (Output_Object, Section_Title => Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Title (ARM_Contents.Informative_Annex, (Section => Section_Number, others => 0)), Ada.Strings.Right), Section_Name => Section_Name); exception when ARM_Contents.Not_Found_Error => ARM_Output.Section (Output_Object, Section_Title => Ada.Strings.Fixed.Trim ( ARM_Contents.Lookup_Title (ARM_Contents.Plain_Annex, (Section => Section_Number, others => 0)), Ada.Strings.Right), Section_Name => Section_Name); -- If this fails, too, we just propagate to the outer handler. end; end; end if; exception when ARM_Contents.Not_Found_Error => Ada.Text_IO.Put_Line ("** Unable to find section title, line " & ARM_File.Line_String (Input_Object)); end; Format_Object.Next_Note := 1; Format_Object.Next_Paragraph := 1; Format_Object.Next_Insert_Para := 1; Format_Object.Next_AARM_Sub := 'a'; Format_Object.Next_Enumerated_Num := 1; Format_Object.Enumerated_Level := 0; Format_Object.Text_Format := ARM_Output.NORMAL_FORMAT; Format_Object.No_Prefix := False; Format_Object.No_Para_Num := False; Format_Object.Keep_with_Next := False; Format_Object.Space_After := ARM_Output.Normal; Format_Object.No_Breaks := False; Format_Object.In_Change := False; Format_Object.Last_Non_Space := False; Format_Object.Next_Paragraph_Change_Kind := ARM_Database.None; Format_Object.Style := ARM_Output.Normal; -- The default. Format_Object.Indent := 0; -- No indent to start. Format_Object.In_Paragraph := False; Format_Object.No_Start_Paragraph := False; end if; Real_Process (Format_Object, Format_State, Input_Object, Output_Object); -- Reached end of the file/input object. -- Kill any open paragraph: if Format_Object.In_Paragraph and then (not Format_Object.No_Start_Paragraph) then ARM_Output.End_Paragraph (Output_Object); Format_Object.In_Paragraph := False; Format_Object.No_Start_Paragraph := False; end if; Ada.Text_IO.Put_Line (" Lines processed: " & ARM_File.Line_String (Input_Object)); Arm_File.Close (Input_Object); if Format_State.Nesting_Stack_Ptr /= 0 then Ada.Text_IO.Put_Line (" ** Unfinished commands detected."); for I in reverse 1 .. Format_State.Nesting_Stack_Ptr loop Ada.Text_IO.Put_Line (" Open command=" & Format_State.Nesting_Stack(I).Name); end loop; end if; end Process; procedure Format (Format_Object : in out Format_Type; Text : in String; Output_Object : in out ARM_Output.Output_Type'Class; Text_Name : in String; No_Annotations : in Boolean) is -- Format the contents of Text, writing the results to -- Output_Object. (Output_Object uses dispatching calls to provide -- the correct formatting). Text is assumed to be a component of -- a larger section. Text_Name is an identifying name for error messages. -- If No_Annotations is true, we don't want any annotations even if we -- are generating a document with annotations. Input_Object : Arm_String.String_Input_Type; Format_State : Format_State_Type; Real_Include_Annotations : Boolean := Format_Object.Include_Annotations; begin if No_Annotations then Format_Object.Include_Annotations := False; end if; Arm_String.Open (Input_Object, Text, Text_Name); -- Open the input object using a string for input. Real_Process (Format_Object, Format_State, Input_Object, Output_Object); Arm_String.Close (Input_Object); Format_Object.Include_Annotations := Real_Include_Annotations; if Format_State.Nesting_Stack_Ptr /= 0 then Ada.Text_IO.Put_Line (" ** Unfinished commands detected."); end if; end Format; end ARM_Format; �������������������������������������org.adaic.arm_form/progs/arm_frm.ads����������������������������������������������������������������0000755�0001752�0001001�00000052051�12273462240�016724� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������with ARM_Output, ARM_Contents; --private -- Ada 2005 with ARM_Input, ARM_Database, ARM_Subindex; package ARM_Format is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to parse the input files, and -- determine what to output. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2006, 2007, 2010, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/14/00 - RLB - Created base package. -- 4/18/00 - RLB - Added additional information to Object; -- added Scan. -- 4/24/00 - RLB - Added Change_Kind and Display_Index_Entries. -- - RLB - Added Change format. -- 4/25/00 - RLB - Added Size. -- 4/26/00 - RLB - Added paragraph formats. -- 5/10/00 - RLB - Added additional paragraph kinds. -- 5/11/00 - RLB - Added numbers for enumerated paragraphs. -- 5/12/00 - RLB - Added attribute prefix text. -- 5/15/00 - RLB - Split input from parsing/formatting. -- 5/16/00 - RLB - Added database objects and Destroy. -- 5/23/00 - RLB - Added tab stops. -- 5/24/00 - RLB - Implemented subscript/superscript commands. -- 5/28/00 - RLB - Implemented index operations. -- 6/ 2/00 - RLB - Added Unit. -- 8/ 2/00 - RLB - Added Leading and Syntax_Leading styles. -- 8/ 4/00 - RLB - Added more new styles. -- 8/ 7/00 - RLB - Added Leading flag, removed Leading styles. -- 8/ 8/00 - RLB - Added Attr_Leading flag. -- 8/16/00 - RLB - Added No_Para_Num flag, removed No_Pnum formats. -- 8/17/00 - RLB - Changed Leading flag to Space_After. -- 8/28/00 - RLB - Added flags for ChgAttribute and ChgImpldef commands. -- 8/31/00 - RLB - Added the New_Changes change kind. -- 9/26/00 - RLB - Added Syntax_Display format. -- 6/17/02 - RLB - Added Ada95 changes sections. -- 7/18/02 - RLB - Moved document type here. -- - RLB - Added Changes_Only and versioning for individual changes. -- 9/10/04 - RLB - Added support for nested changes. -- 9/14/04 - RLB - Moved Change_Version_Type to ARM_Contents. -- 11/03/04 - RLB - Added Nested_X2_Bulleted. -- 11/16/04 - RLB - Added Attr_Prefix_Text_Change_Kind. -- 12/06/04 - RLB - Added reference chain for Format_Type. -- 12/11/04 - RLB - Increased Syntax_NT length. -- 10/17/05 - RLB - Added Glossary change items. -- 10/28/05 - RLB - Added Language-Define subindexes. -- 1/12/06 - RLB - Replaced "Document" with a number of new more general -- properties. -- 1/16/06 - RLB - Added "Unnumbered_Section" counter, so we can assign -- names without special cases. -- 1/18/06 - RLB - Added "Example_Font". -- 9/22/06 - RLB - Added "Use_ISO_2004_Note_Format". -- - RLB - Revised to use Clause_Number_Type. -- 9/25/06 - RLB - Added "Use_ISO_2004_Contents_Format". -- 10/04/06 - RLB - Added "Use_ISO_2004_List_Format". -- 2/ 5/07 - RLB - Added Usage_Note for ASIS, and renamed Wide paragraph -- kinds. -- 2/13/07 - RLB - Redid output formating to use an explict indent; -- added ChildExample. -- 2/16/07 - RLB - Added Indent. -- 2/19/07 - RLB - Added Title format. -- 4/23/10 - RLB - Added Ada 2005 header. -- 8/ 8/11 - RLB - Added Aspect DB. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 3/12/12 - RLB - Lengthened unit name so -- "Ada.Strings.Wide_Wide_Unbounded.Wide_Wide_Equal_Case_Insensitive" -- would fit (have we lost our minds??). -- 8/31/12 - RLB - Put glossary components into a subrecord to prevent -- inappropriate usage. -- 10/18/12 - RLB - Put impdef components into a subrecord to prevent -- inappropriate usage. -- - RLB - Added more specific hanging_indent formats, along with -- small. -- 11/26/12 - RLB - Added subdivision names. -- 12/17/12 - RLB - Added Ada 2012 AARM sections. type Format_Type is tagged limited private; type Change_Kind is (Old_Only, New_Only, Changes_Only, Show_Changes, New_Changes); -- Which changes to show? -- If Old_Only, we will get the original Ada Reference Manual or AARM. -- If New_Only, we will get the reference documents with the updates -- up to the Change_Version specified included. -- If Changes_Only, we will get the reference documents with the updates -- up to the Change_Version specified included; and insertions and -- deletions will be shown for Change_Version. -- If Show_Changes, original RM text will be shown as deleted, -- and new RM text will be shown as inserted, up to and including the -- Change_Version specified. -- If New_Changes, original RM text removed, but new RM text will be -- shown as inserted, up to and including the Change_Version specified. -- In all cases, changes with versions newer than Change_Version are -- ignored. Thus Change_Version = '0' is the same as Old_Only no -- matter what command is given. procedure Create (Format_Object : in out Format_Type; Changes : in ARM_Format.Change_Kind; Change_Version : in ARM_Contents.Change_Version_Type; Display_Index_Entries : in Boolean; Include_Annotations : in Boolean; Include_ISO : in Boolean; Link_Non_Terminals : in Boolean; Number_Paragraphs : in Boolean; Examples_Font : in ARM_Output.Font_Family_Type; Use_ISO_2004_Note_Format : in Boolean; Use_ISO_2004_Contents_Format : in Boolean; Use_ISO_2004_List_Format : in Boolean; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind); -- Initialize an input object. Changes and Change_Version determine -- which changes should be displayed. If Display_Index_Entries is True, -- index entries will be printed in the document; otherwise, they -- will not generate any visible text (although they might generate -- a link anchor). If Include_Annotations is True, annotations (AARM -- text) will be included in the output; otherwise it will not be. -- If Include_ISO is True, ISOOnly text will be included in the output -- (and NotISO text will not); otherwise the reverse is true. -- If Link_Non_Terminals is True, links will be generated for -- each Non_Terminal, linking it to its definition. -- If Number_Paragraphs is true, paragraphs will be numbered (per -- subclause); otherwise they will not be. -- Example_Font specifies the font that examples will be set in. -- If Use_ISO_2004_Note_Format is true, that format will be used; -- else the Ada95 standard's format will be used for notes. -- If Use_ISO_2004_Contents_Format is true, that format will be used; -- else the Ada95 standard's format will be used for the table of contents. -- If Use_ISO_2004_List_Format is true, then lists will be lettered; -- else the Ada95 standard's numbering format will be used for -- enumerated lists. -- The top-level (and other) subdivision names are as specified -- in Top_Level_Subdivision_Name. procedure Destroy (Format_Object : in out Format_Type); -- Destroy a format object, releasing any resources. procedure Scan (Format_Object : in out Format_Type; File_Name : in String; Section_Number : in ARM_Contents.Section_Number_Type; Starts_New_Section : in Boolean); -- Scans the contents for File_Name, determining the table of contents -- for the section. The results are written to the contents package. -- Starts_New_Section is True if the file starts a new section. -- Section_Number is the number (or letter) of the section. -- Note: We need this scanning pass so we can process @SeeSec, -- @SeeSecNum, and similar commands. For that, we need the full names -- of the sections and clauses. procedure Write_Table_of_Contents ( Format_Object : in out Format_Type; Output_Object : in out ARM_Output.Output_Type'Class); -- Writes the table of contents for the document. (It will have -- a section name of "TOC"). procedure Process (Format_Object : in out Format_Type; File_Name : in String; Output_Object : in out ARM_Output.Output_Type'Class; Section_Name : in String; Section_Number : in ARM_Contents.Section_Number_Type; Starts_New_Section : in Boolean); -- Process the contents for File_Name, writing the results to -- Output_Object. (Output_Object uses dispatching calls to provide -- the correct formatting). Section_Name is the name of the section -- for this file. Starts_New_Section is True if the file starts -- a new section. Section_Number is the number (or letter) of the -- section. Values > 20 represent annex letters (21 => A, 22 => B, etc.) procedure Format (Format_Object : in out Format_Type; Text : in String; Output_Object : in out ARM_Output.Output_Type'Class; Text_Name : in String; No_Annotations : in Boolean); -- Format the contents of Text, writing the results to -- Output_Object. (Output_Object uses dispatching calls to provide -- the correct formatting). Text is assumed to be a component of -- a larger section. Text_Name is an identifying name for error messages. -- If No_Annotations is true, we don't want any annotations even if we -- are generating a document with annotations. private type Paragraph_Type is (Plain, Introduction, Language_Design, -- AARM-only. Syntax, Resolution, Legality, Static_Semantics, Link_Time, Run_Time, Bounded_Errors, Erroneous, Requirements, Documentation, Metrics, Permissions, Advice, Notes, Single_Note, Examples, Ada83_Inconsistencies, Ada83_Incompatibilities, -- AARM-only. Ada83_Extensions, Ada83_Wording, -- AARM-only. Ada95_Inconsistencies, Ada95_Incompatibilities, -- AARM-only. Ada95_Extensions, Ada95_Wording, -- AARM-only. Ada2005_Inconsistencies, Ada2005_Incompatibilities, -- AARM-only. Ada2005_Extensions, Ada2005_Wording, -- AARM-only. Ada2012_Inconsistencies, Ada2012_Incompatibilities, -- AARM-only. Ada2012_Extensions, Ada2012_Wording, -- AARM-only. Element_Ref, Child_Ref, Usage_Note, -- For ASIS (AASIS-only). -- AARM annotations (no headers) Reason, Ramification, Proof, Imp_Note, Corr_Change, Discussion, Honest, Glossary_Marker, Bare_Annotation, -- Format only: Wide_Above, Example_Text, Child_Example_Text, Indented_Example_Text, Code_Indented, Indent, Bulleted, Nested_Bulleted, Nested_X2_Bulleted, Display, Syntax_Display, Syntax_Indented, Syntax_Production, Enumerated, Nested_Enumerated, Hanging_Indented_1, Hanging_Indented_2, Hanging_Indented_3, Hanging_Indented_4, Small, Title, In_Table); type Reference; type Reference_Ptr is access Reference; type Reference is record Ref_Name : ARM_Input.Command_Name_Type; Ref_Len : Natural; -- Length of the reference. Is_DR_Ref : Boolean; -- True for a DR reference; False for an AI reference. Next : Reference_Ptr; end record; type Glossary_Info_Type (Active : Boolean := False; Change_Kind : ARM_Database.Paragraph_Change_Kind_Type := ARM_Database.None) is record -- The Change_Kind of ToGlossary. case Active is when False => null; -- No glossary entry in use. when True => -- Glossary actively being processed; used only when -- processing [Chg]ToGlossary[Also] commands. Term : String (1..50); -- Glossary term. Term_Len : Natural := 0; Add_to_Glossary : Boolean; -- Add this item to the Glossary. (Not the same -- as "Active"; when generating older versions -- of a document, this would be False for a -- new glossary entry.) Displayed : Boolean; -- The text was displayed in the document. case Change_Kind is when ARM_Database.None => null; when others => Version : ARM_Contents.Change_Version_Type; -- The version number of the changed paragraph. end case; end case; end record; type Impdef_Command_Type is (None, Aspect, Impdef, Docreq, ImplAdv); type Impdef_Info_Type (Command : Impdef_Command_Type := None) is record case Command is when None => null; -- No impdef, docreq, impladv, aspectdesc in use. when others => -- Impdef, Docreq, Impladv, Aspectdesc actively being processed; -- used only when processing ImplDef, ChgImplDef, -- ChgDocReq, ChgImplAdv, and ChgAspectDesc. Change_Kind : ARM_Database.Paragraph_Change_Kind_Type := ARM_Database.None; -- The Change_Kind of the command. Version : ARM_Contents.Change_Version_Type; -- If the kind is not "None", this is the version -- number of the changed paragraph. Initial_Version : ARM_Contents.Change_Version_Type; -- This is the version number of the original paragraph. Paragraph_String : String (1 .. 10); -- Paragraph number. Paragraph_Len : Natural; Add_to_DB : Boolean; -- Add this item to the appropriate DB. (Not the same -- as "Active"; when generating older versions -- of a document, this would be False for a -- new impdef, docreq, etc. entry.) case Command is when Aspect => Aspect_Name : String (1..30); -- Aspect name text Aspect_Name_Len : Natural := 0; when others => null; end case; end case; end record; type Format_Type is tagged limited record -- Document information: Changes : ARM_Format.Change_Kind; -- No Both here. Change_Version : ARM_Contents.Change_Version_Type; Display_Index_Entries : Boolean; Include_Annotations : Boolean; Include_ISO : Boolean; Link_Non_Terminals : Boolean; Number_Paragraphs : Boolean; Examples_Font : ARM_Output.Font_Family_Type; Use_ISO_2004_Note_Format : Boolean; Use_ISO_2004_Contents_Format : Boolean; Use_ISO_2004_List_Format : Boolean; Top_Level_Subdivision_Name : ARM_Output.Top_Level_Subdivision_Name_Kind; -- Clause numbers: Clause_Number : ARM_Contents.Clause_Number_Type; -- The current clause number (Section, clause, subclause, subsubclause). Unnumbered_Section : Natural; -- The current (if any) clause number -- for unnumbered sections. -- Paragraph format info: Next_Paragraph_Change_Kind : ARM_Database.Paragraph_Change_Kind_Type; -- The change kind of the next paragraph. This is -- reset to none after each paragraph. Next_Paragraph_Version : ARM_Contents.Change_Version_Type; -- If the kind is not "None", this is the version -- number of the changed paragraph. Last_Paragraph_Subhead_Type : Paragraph_Type; -- The last paragraph subhead generated. Next_Paragraph_Subhead_Type : Paragraph_Type; -- The next paragraph subhead to generate (not -- necessarily the same as Next_Paragraph_Format_Type). -- This indicates the current paragraph type. Next_Paragraph_Format_Type : Paragraph_Type; -- The format type of the next paragraph to -- generate. We keep this separately so that the -- first paragraph of a grouping can be in a -- different format than the standard one, and -- still generate a subheading. Paragraph_Tab_Stops : ARM_Output.Tab_Info := ARM_Output.NO_TABS; -- The tab stops for the next paragraph. In_Bundle : Boolean := False; -- Are we in a bundle? References : Reference_Ptr := null; -- Any references to generate at the start of the -- next paragraph. -- Paragraph numbering info: Next_Note : Natural; -- The number of the next note. These are -- per-section, not per-clause (unless ISO 2004 is set). Next_Paragraph : Positive; -- The number of the next paragraph. These -- are per-(sub)clause. Next_Insert_Para : Positive; -- The subnumber of the next inserted -- paragraph. Next_AARM_Sub : Character; -- The letter of the next AARM subclause. -- These are reset when the paragraph number -- changes. Next_AARM_Insert_Para : Positive; -- The subnumber of the next inserted -- AARM paragraph. Next_Enumerated_Num : Positive; -- If the format is enumerated, this is the -- number of the next paragraph. Enumerated_Level : Natural; -- Number of enumerated formats that we're in. Current_Paragraph_String : String (1 .. 10); -- The current paragraph number string (only -- valid if In_Paragraph is True). Current_Paragraph_Len : Natural; -- Text format info: Text_Format : ARM_Output.Format_Type; -- Holds the current text format. Style : ARM_Output.Paragraph_Style_Type; -- What is the current paragraph style? Indent : ARM_Output.Paragraph_Indent_Type; -- What is the current paragraph indent? In_Paragraph : Boolean; -- Are we currently in a paragraph? No_Start_Paragraph : Boolean; -- Did we suppress "Start_Paragraph"? No_Prefix : Boolean; -- Should we suppress any prefix on the next paragraph? No_Para_Num : Boolean; -- Should we suppress the paragraph number on the next paragraph? Keep_with_Next : Boolean; -- Should we force this paragraph to bind to the next -- (disallowing a page break between)? Space_After : ARM_Output.Space_After_Type; -- Space following this -- paragraph. No_Breaks : Boolean; -- Should we allow page breaks in this paragraph? In_Change : Boolean; -- Are we in a change region? Last_Non_Space : Boolean; -- Is the last character written into the -- paragraph a non-space? (If nothing has been -- written into the paragraph, then this is False). -- Indexing: Unit : String (1..72); -- Unit for predefined definitions. Used only -- by a handful of indexing commands. Unit_Len : Natural := 0; -- Syntax: Syntax_NT : String (1..80); -- Syntax non-terminal; used only during the -- processing of the Syn command. Syntax_NT_Len : Natural := 0; Syntax_Tab : String (1..40); -- Syntax tab string; used only during the -- processing of the Syn command. Syntax_Tab_Len : Natural := 0; -- Attributes: Prefix_Text : String (1..160) := "@b{NONE!}" & (10..160 => ' '); -- This text is used as part of the attribute list text. -- It is shared between multiple attributes, which is why it is -- handled this way. Prefix_Text_Len : Natural := 9; Attr_Prefix : String (1..10); -- Attribute prefix text Attr_Prefix_Len : Natural := 0; Attr_Prefix_Change_Kind : ARM_Database.Paragraph_Change_Kind_Type; Attr_Prefix_Version : ARM_Contents.Change_Version_Type; Attr_Name : String (1..30); -- Attribute name text Attr_Name_Len : Natural := 0; Attr_Leading : Boolean := False; -- Attribute leading flag Attr_Change_Kind : ARM_Database.Paragraph_Change_Kind_Type; Attr_Prefix_Text_Change_Kind : ARM_Database.Paragraph_Change_Kind_Type; Attr_Version : ARM_Contents.Change_Version_Type; -- The above ten items are used only when processing Attribute -- and Attribute_Leading commands. Attr_DB : ARM_Database.Database_Type; -- Pragmas: Pragma_DB : ARM_Database.Database_Type; -- Glossary: Glossary_Info : Glossary_Info_Type; Glossary_DB : ARM_Database.Database_Type; -- Aspects: Aspect_DB : ARM_Database.Database_Type; -- Also see Impdef_Info, below. -- Implementation advice: Impladv_DB : ARM_Database.Database_Type; -- Also see Impdef_Info, below. -- Documentation requirements: Docreq_DB : ARM_Database.Database_Type; -- Also see Impdef_Info, below. -- Implementation-defined: Impdef_DB : ARM_Database.Database_Type; -- Also see Impdef_Info, below. -- For all of the above four: Impdef_Info : Impdef_Info_Type; -- Used only during processing of ImplDef, ChgImplDef, -- ChgDocReq, ChgImplAdv, and ChgAspectDesc. -- Language-Defined entity subindexes: Package_Index : ARM_Subindex.Subindex_Type; Type_Index : ARM_Subindex.Subindex_Type; Subprogram_Index : ARM_Subindex.Subindex_Type; Exception_Index : ARM_Subindex.Subindex_Type; Object_Index : ARM_Subindex.Subindex_Type; end record; end ARM_Format; ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/arm_frmd.adb���������������������������������������������������������������0000755�0001752�0001001�00000050355�12273462240�017054� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������with Ada.Characters.Handling, Ada.Strings.Fixed; package body ARM_Format.Data is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains various data used by the input file parser. -- -- --------------------------------------- -- Copyright 2011, 2012 AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 8/ 8/11 - RLB - Split from base package, mainly to reduce the -- size of that package. -- - RLB - Added aspect index commands. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added AspectDefn command. -- 10/20/11 - RLB - Added DeletedPragmaSyn command. -- 10/26/11 - RLB - Added versioned break commands. -- 3/27/12 - RLB - Added more versioned break commands. -- 12/17/12 - RLB - Added Ada 2012 AARM headings. function Command (Name : in ARM_Input.Command_Name_Type) return Command_Type is -- Return the command value for a particular command name: Canonical_Name : constant String := Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Name, Ada.Strings.Right)); begin if Canonical_Name = "begin" then return Text_Begin; elsif Canonical_Name = "end" then return Text_End; elsif Canonical_Name = "redundant" then return Redundant; elsif Canonical_Name = "comment" then return Comment; elsif Canonical_Name = "noprefix" then return No_Prefix; elsif Canonical_Name = "noparanum" then return No_Para_Num; elsif Canonical_Name = "keepnext" then return Keep_with_Next; elsif Canonical_Name = "leading" then return Leading; elsif Canonical_Name = "trailing" then return Trailing; elsif Canonical_Name = "+" then -- Can't happen directly, but can happen through stacking. return Up; elsif Canonical_Name = "-" then -- Can't happen directly, but can happen through stacking. return Down; elsif Canonical_Name = "thinline" then return Thin_Line; elsif Canonical_Name = "thickline" then return Thick_Line; elsif Canonical_Name = "tabclear" then return Tab_Clear; elsif Canonical_Name = "tabset" then return Tab_Set; elsif Canonical_Name = "table" then return Table; elsif Canonical_Name = "picturealone" then return Picture_Alone; elsif Canonical_Name = "pictureinline" then return Picture_Inline; elsif Canonical_Name = "last" then return Table_Last; elsif Canonical_Name = "part" then return Part; elsif Canonical_Name = "newpage" then return New_Page; elsif Canonical_Name = "rmnewpage" then return RM_New_Page; elsif Canonical_Name = "softpage" then return Soft_Page; elsif Canonical_Name = "newcolumn" then return New_Column; elsif Canonical_Name = "newpagever" then return New_Page_for_Version; elsif Canonical_Name = "rmnewpagever" then return RM_New_Page_for_Version; elsif Canonical_Name = "notisormnewpagever" then return Not_Iso_RM_New_Page_for_Version; elsif Canonical_Name = "isoonlyrmnewpagever" then return Iso_Only_RM_New_Page_for_Version; elsif Canonical_Name = "newcolumnver" then return New_Column_for_Version; elsif Canonical_Name = "b" or else Canonical_Name = "bold" then return Bold; elsif Canonical_Name = "i" or else Canonical_Name = "italics" then return Italic; elsif Canonical_Name = "r" or else Canonical_Name = "roman" then return Roman; elsif Canonical_Name = "s" or else Canonical_Name = "swiss" then return Swiss; elsif Canonical_Name = "f" or else Canonical_Name = "fixed" then return Fixed; elsif Canonical_Name = "ri" then return Roman_Italic; elsif Canonical_Name = "shrink" then return Shrink; elsif Canonical_Name = "grow" then return Grow; elsif Canonical_Name = "black" then return Black; elsif Canonical_Name = "red" then return Red; elsif Canonical_Name = "green" then return Green; elsif Canonical_Name = "blue" then return Blue; elsif Canonical_Name = "key" then return Keyword; elsif Canonical_Name = "nt" then return Non_Terminal; elsif Canonical_Name = "ntf" then return Non_Terminal_Format; elsif Canonical_Name = "exam" then return Example_Text; elsif Canonical_Name = "examcom" then return Example_Comment; elsif Canonical_Name = "indexlist" then return Index_List; elsif Canonical_Name = "defn" then return Defn; elsif Canonical_Name = "defn2" then return Defn2; elsif Canonical_Name = "rootdefn" then return RootDefn; elsif Canonical_Name = "rootdefn2" then return RootDefn2; elsif Canonical_Name = "pdefn" then return PDefn; elsif Canonical_Name = "pdefn2" then return PDefn2; elsif Canonical_Name = "indexsee" then return Index_See; elsif Canonical_Name = "indexseealso" then return Index_See_Also; elsif Canonical_Name = "seeother" then return See_Other; elsif Canonical_Name = "seealso" then return See_Also; elsif Canonical_Name = "rootlibunit" then return Index_Root_Unit; elsif Canonical_Name = "childunit" then return Index_Child_Unit; elsif Canonical_Name = "subchildunit" then return Index_Subprogram_Child_Unit; elsif Canonical_Name = "adatypedefn" then return Index_Type; elsif Canonical_Name = "adasubtypedefn" then return Index_Subtype; elsif Canonical_Name = "adasubdefn" then return Index_Subprogram; elsif Canonical_Name = "adaexcdefn" then return Index_Exception; elsif Canonical_Name = "adaobjdefn" then return Index_Object; elsif Canonical_Name = "adapackdefn" then return Index_Package; elsif Canonical_Name = "adadefn" then return Index_Other; elsif Canonical_Name = "indexcheck" then return Index_Check; elsif Canonical_Name = "attr" then return Index_Attr; elsif Canonical_Name = "prag" then return Index_Pragma; elsif Canonical_Name = "aspectdefn" then return Index_Aspect; elsif Canonical_Name = "syn" then return Syntax_Rule; elsif Canonical_Name = "syn2" then return Syntax_Term; elsif Canonical_Name = "synf" then return Syntax_Term_Undefined; elsif Canonical_Name = "syni" then return Syntax_Prefix; elsif Canonical_Name = "syntaxsummary" then return Syntax_Summary; elsif Canonical_Name = "syntaxxref" then return Syntax_Xref; elsif Canonical_Name = "addedsyn" then return Added_Syntax_Rule; elsif Canonical_Name = "deletedsyn" then return Deleted_Syntax_Rule; elsif Canonical_Name = "toglossary" then return To_Glossary; elsif Canonical_Name = "toglossaryalso" then return To_Glossary_Also; elsif Canonical_Name = "chgtoglossary" then return Change_To_Glossary; elsif Canonical_Name = "chgtoglossaryalso" then return Change_To_Glossary_Also; elsif Canonical_Name = "glossarylist" then return Glossary_List; elsif Canonical_Name = "prefixtype" then return Prefix_Type; elsif Canonical_Name = "chgprefixtype" then return Change_Prefix_Type; elsif Canonical_Name = "endprefixtype" then return Reset_Prefix_Type; elsif Canonical_Name = "attribute" then return Attribute; elsif Canonical_Name = "attributeleading" then return Attribute_Leading; elsif Canonical_Name = "chgattribute" then return Change_Attribute; elsif Canonical_Name = "attributelist" then return Attribute_List; elsif Canonical_Name = "pragmasyn" then return Pragma_Syntax; elsif Canonical_Name = "pragmalist" then return Pragma_List; elsif Canonical_Name = "addedpragmasyn" then return Added_Pragma_Syntax; elsif Canonical_Name = "deletedpragmasyn" then return Deleted_Pragma_Syntax; elsif Canonical_Name = "impldef" then return Implementation_Defined; elsif Canonical_Name = "chgimpldef" then return Change_Implementation_Defined; elsif Canonical_Name = "impldeflist" then return Implementation_Defined_List; elsif Canonical_Name = "chgimpladvice" then return Change_Implementation_Advice; elsif Canonical_Name = "addedimpladvicelist" then return Added_Implementation_Advice_List; elsif Canonical_Name = "chgdocreq" then return Change_Documentation_Requirement; elsif Canonical_Name = "addeddocreqlist" then return Added_Documentation_Requirements_List; elsif Canonical_Name = "chgaspectdesc" then return Change_Aspect_Description; elsif Canonical_Name = "addedaspectlist" then return Added_Aspect_Description_List; elsif Canonical_Name = "packagelist" then return Package_List; elsif Canonical_Name = "typelist" then return Type_List; elsif Canonical_Name = "subprogramlist" then return Subprogram_List; elsif Canonical_Name = "exceptionlist" then return Exception_List; elsif Canonical_Name = "objectlist" then return Object_List; elsif Canonical_Name = "labeledsection" then return Labeled_Section; elsif Canonical_Name = "labeledsectionnobreak" then return Labeled_Section_No_Break; elsif Canonical_Name = "labeledclause" then return Labeled_Clause; elsif Canonical_Name = "labeledsubclause" then return Labeled_Subclause; elsif Canonical_Name = "labeledsubsubclause" then return Labeled_Subsubclause; elsif Canonical_Name = "labeledannex" then return Labeled_Annex; elsif Canonical_Name = "labeledinformativeannex" then return Labeled_Informative_Annex; elsif Canonical_Name = "labelednormativeannex" then return Labeled_Normative_Annex; elsif Canonical_Name = "unnumberedsection" then return Unnumbered_Section; elsif Canonical_Name = "labeledrevisedannex" then return Labeled_Revised_Annex; elsif Canonical_Name = "labeledrevisedinformativeannex" then return Labeled_Revised_Informative_Annex; elsif Canonical_Name = "labeledrevisednormativeannex" then return Labeled_Revised_Normative_Annex; elsif Canonical_Name = "labeledaddedannex" then return Labeled_Added_Annex; elsif Canonical_Name = "labeledaddedinformativeannex" then return Labeled_Added_Informative_Annex; elsif Canonical_Name = "labeledaddednormativeannex" then return Labeled_Added_Normative_Annex; elsif Canonical_Name = "labeledrevisedsection" then return Labeled_Revised_Section; elsif Canonical_Name = "labeledrevisedclause" then return Labeled_Revised_Clause; elsif Canonical_Name = "labeledrevisedsubclause" then return Labeled_Revised_Subclause; elsif Canonical_Name = "labeledrevisedsubsubclause" then return Labeled_Revised_Subsubclause; elsif Canonical_Name = "labeledaddedsection" then return Labeled_Added_Section; elsif Canonical_Name = "labeledaddedclause" then return Labeled_Added_Clause; elsif Canonical_Name = "labeledaddedsubclause" then return Labeled_Added_Subclause; elsif Canonical_Name = "labeledaddedsubsubclause" then return Labeled_Added_Subsubclause; elsif Canonical_Name = "labeleddeletedclause" then return Labeled_Deleted_Clause; elsif Canonical_Name = "labeleddeletedsubclause" then return Labeled_Deleted_Subclause; elsif Canonical_Name = "labeleddeletedsubsubclause" then return Labeled_Deleted_Subsubclause; elsif Canonical_Name = "subheading" then return Subheading; elsif Canonical_Name = "addedsubheading" then return Added_Subheading; elsif Canonical_Name = "heading" then return Heading; elsif Canonical_Name = "center" then return Center; elsif Canonical_Name = "right" then return Right; elsif Canonical_Name = "prefacesection" then return Preface_Section; elsif Canonical_Name = "refsec" then return Ref_Section; elsif Canonical_Name = "refsecnum" then return Ref_Section_Number; elsif Canonical_Name = "refsecbynum" then return Ref_Section_By_Number; elsif Canonical_Name = "locallink" then return Local_Link; elsif Canonical_Name = "localtarget" then return Local_Target; elsif Canonical_Name = "urllink" then return URL_Link; elsif Canonical_Name = "ailink" then return AI_Link; elsif Canonical_Name = "chg" then return Change; elsif Canonical_Name = "chgadded" then return Change_Added; elsif Canonical_Name = "chgdeleted" then return Change_Deleted; elsif Canonical_Name = "chgref" then return Change_Reference; elsif Canonical_Name = "chgnote" then return Change_Note; elsif Canonical_Name = "introname" then return Intro_Name; elsif Canonical_Name = "syntaxname" then return Syntax_Name; elsif Canonical_Name = "resolutionname" then return Resolution_Name; elsif Canonical_Name = "legalityname" then return Legality_Name; elsif Canonical_Name = "staticsemname" then return Static_Name; elsif Canonical_Name = "linktimename" then return Link_Name; elsif Canonical_Name = "runtimename" then return Run_Name; elsif Canonical_Name = "boundedname" then return Bounded_Name; elsif Canonical_Name = "erronname" then return Erroneous_Name; elsif Canonical_Name = "implreqname" then return Req_Name; elsif Canonical_Name = "docreqname" then return Doc_Name; elsif Canonical_Name = "metricsname" then return Metrics_Name; elsif Canonical_Name = "implpermname" then return Permission_Name; elsif Canonical_Name = "impladvicename" then return Advice_Name; elsif Canonical_Name = "notesname" then return Notes_Name; elsif Canonical_Name = "singlenotename" then return Single_Note_Name; elsif Canonical_Name = "examplesname" then return Examples_Name; elsif Canonical_Name = "metarulesname" then return Meta_Name; elsif Canonical_Name = "inconsistent83name" then return Inconsistent83_Name; elsif Canonical_Name = "incompatible83name" then return Incompatible83_Name; elsif Canonical_Name = "extend83name" then return Extend83_Name; elsif Canonical_Name = "diffword83name" then return Wording83_Name; elsif Canonical_Name = "inconsistent95name" then return Inconsistent95_Name; elsif Canonical_Name = "incompatible95name" then return Incompatible95_Name; elsif Canonical_Name = "extend95name" then return Extend95_Name; elsif Canonical_Name = "diffword95name" then return Wording95_Name; elsif Canonical_Name = "inconsistent2005name" then return Inconsistent2005_Name; elsif Canonical_Name = "incompatible2005name" then return Incompatible2005_Name; elsif Canonical_Name = "extend2005name" then return Extend2005_Name; elsif Canonical_Name = "diffword2005name" then return Wording2005_Name; elsif Canonical_Name = "inconsistent2012name" then return Inconsistent2012_Name; elsif Canonical_Name = "incompatible2012name" then return Incompatible2012_Name; elsif Canonical_Name = "extend2012name" then return Extend2012_Name; elsif Canonical_Name = "diffword2012name" then return Wording2012_Name; elsif Canonical_Name = "syntaxtitle" then return Syntax_Title; elsif Canonical_Name = "resolutiontitle" then return Resolution_Title; elsif Canonical_Name = "legalitytitle" then return Legality_Title; elsif Canonical_Name = "staticsemtitle" then return Static_Title; elsif Canonical_Name = "linktimetitle" then return Link_Title; elsif Canonical_Name = "runtimetitle" then return Run_Title; elsif Canonical_Name = "boundedtitle" then return Bounded_Title; elsif Canonical_Name = "errontitle" then return Erroneous_Title; elsif Canonical_Name = "implreqtitle" then return Req_Title; elsif Canonical_Name = "docreqtitle" then return Doc_Title; elsif Canonical_Name = "metricstitle" then return Metrics_Title; elsif Canonical_Name = "implpermtitle" then return Permission_Title; elsif Canonical_Name = "impladvicetitle" then return Advice_Title; elsif Canonical_Name = "notestitle" then return Notes_Title; elsif Canonical_Name = "singlenotetitle" then return Single_Note_Title; elsif Canonical_Name = "examplestitle" then return Examples_Title; elsif Canonical_Name = "metarulestitle" then return Meta_Title; elsif Canonical_Name = "inconsistent83title" then return Inconsistent83_Title; elsif Canonical_Name = "incompatible83title" then return Incompatible83_Title; elsif Canonical_Name = "extend83title" then return Extend83_Title; elsif Canonical_Name = "diffword83title" then return Wording83_Title; elsif Canonical_Name = "inconsistent95title" then return Inconsistent95_Title; elsif Canonical_Name = "incompatible95title" then return Incompatible95_Title; elsif Canonical_Name = "extend95title" then return Extend95_Title; elsif Canonical_Name = "diffword95title" then return Wording95_Title; elsif Canonical_Name = "inconsistent2005title" then return Inconsistent2005_Title; elsif Canonical_Name = "incompatible2005title" then return Incompatible2005_Title; elsif Canonical_Name = "extend2005title" then return Extend2005_Title; elsif Canonical_Name = "diffword2005title" then return Wording2005_Title; elsif Canonical_Name = "inconsistent2012title" then return Inconsistent2012_Title; elsif Canonical_Name = "incompatible2012title" then return Incompatible2012_Title; elsif Canonical_Name = "extend2012title" then return Extend2012_Title; elsif Canonical_Name = "diffword2012title" then return Wording2012_Title; elsif Canonical_Name = "em" then return EM_Dash; elsif Canonical_Name = "en" then return EN_Dash; elsif Canonical_Name = "lt" then return LT; elsif Canonical_Name = "leq" then return LE; elsif Canonical_Name = "gt" then return GT; elsif Canonical_Name = "geq" then return GE; elsif Canonical_Name = "neq" then return NE; elsif Canonical_Name = "pi" then return PI; elsif Canonical_Name = "times" then return Times; elsif Canonical_Name = "porm" then return PorM; elsif Canonical_Name = "singlequote" then return Single_Quote; elsif Canonical_Name = "latin1" then return LATIN_1; elsif Canonical_Name = "unicode" then return Unicode; elsif Canonical_Name = "ceiling" then return Ceiling; elsif Canonical_Name = "floor" then return Floor; elsif Canonical_Name = "abs" then return Absolute; elsif Canonical_Name = "log" then return Log; elsif Canonical_Name = "thin" then return Thin_Space; elsif Canonical_Name = "lquote" then return Left_Quote; elsif Canonical_Name = "lquotes" then return Left_Quote_Pair; elsif Canonical_Name = "ldquote" then return Left_Double_Quote; elsif Canonical_Name = "rquote" then return Right_Quote; elsif Canonical_Name = "rquotes" then return Right_Quote_Pair; elsif Canonical_Name = "rdquote" then return Right_Double_Quote; elsif Canonical_Name = "smldotlessi" then return Small_Dotless_I; elsif Canonical_Name = "capdottedi" then return Capital_Dotted_I; else return Unknown; end if; end Command; end ARM_Format.Data; �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/arm_frmd.ads���������������������������������������������������������������0000755�0001752�0001001�00000047655�12273462240�017106� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������private package ARM_Format.Data is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains various data used by the input file parser. -- -- --------------------------------------- -- Copyright 2011, 2012 AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 8/ 8/11 - RLB - Split from base package, mainly to reduce the -- size of that package. -- - RLB - Added aspect index commands. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added AspectDefn command. -- 10/20/11 - RLB - Added DeletedPragmaSyn command. -- 10/26/11 - RLB - Added versioned break commands. -- 3/27/12 - RLB - Added more versioned break commands. -- 10/18/12 - RLB - Added more specific hanging_indent commands. -- 12/17/12 - RLB - Added Ada 2012 AARM headings. type LString is record Length : Natural; Str : String(1..40); end record; Paragraph_Kind_Name : constant array (Paragraph_Type) of LString := (Plain => (Length => 0, Str => (others => ' ')), -- Not used. Introduction => (Length => 17, Str => "Introductory Text "), -- IntroName Language_Design => (Length => 25, Str => "Language Design Principle "), -- MetaRulesName Syntax => (Length => 11, Str => "Syntax Rule "), -- SyntaxName Resolution => (Length => 20, Str => "Name Resolution Rule "), -- ResolutionName Legality => (Length => 13, Str => "Legality Rule "), -- LegalityName Static_Semantics=> (Length => 20, Str => "Static Semantic Item "), -- StaticSemName Link_Time => (Length => 21, Str => "Post-Compilation Rule "), -- LinkTimeName Run_Time => (Length => 21, Str => "Dynamic Semantic Item "), -- RunTimeName Bounded_Errors => (Length => 24, Str => "Bounded (Run-Time) Error "), -- BoundedName Erroneous => (Length => 19, Str => "Erroneous Execution "), -- ErronName Requirements => (Length => 26, Str => "Implementation Requirement "), -- ImplReqName Documentation => (Length => 25, Str => "Documentation Requirement "), -- DocReqName Metrics => (Length => 6, Str => "Metric "), -- MetricsName Permissions => (Length => 25, Str => "Implementation Permission "), -- ImplPermName Advice => (Length => 21, Str => "Implementation Advice "), -- ImplAdviceName Notes => (Length => 4, Str => "Note "), -- NotesName Single_Note => (Length => 4, Str => "Note "), -- SimpleNoteName Examples => (Length => 7, Str => "Example "), -- ExamplesName Ada83_Inconsistencies => (Length => 25, Str => "Inconsistency with Ada 83 "), -- Inconsistent83Name Ada83_Incompatibilities => (Length => 27, Str => "Incompatibility with Ada 83 "), -- Incompatible83Name Ada83_Extensions=> (Length => 19, Str => "Extension to Ada 83 "), -- Extend83Name Ada83_Wording => (Length => 26, Str => "Wording Change from Ada 83 "), -- DiffWord83Name Ada95_Inconsistencies => (Length => 25, Str => "Inconsistency with Ada 95 "), -- Inconsistent95Name Ada95_Incompatibilities => (Length => 27, Str => "Incompatibility with Ada 95 "), -- Incompatible95Name Ada95_Extensions=> (Length => 19, Str => "Extension to Ada 95 "), -- Extend95Name Ada95_Wording => (Length => 26, Str => "Wording Change from Ada 95 "), -- DiffWord95Name Ada2005_Inconsistencies => (Length => 27, Str => "Inconsistency with Ada 2005 "), -- Inconsistent2005Name Ada2005_Incompatibilities => (Length => 29, Str => "Incompatibility with Ada 2005 "), -- Incompatible2005Name Ada2005_Extensions => (Length => 21, Str => "Extension to Ada 2005 "), -- Extend2005Name Ada2005_Wording => (Length => 28, Str => "Wording Change from Ada 2005 "), -- DiffWord2005Name Ada2012_Inconsistencies => (Length => 27, Str => "Inconsistency with Ada 2012 "), -- Inconsistent2012Name Ada2012_Incompatibilities => (Length => 29, Str => "Incompatibility with Ada 2012 "), -- Incompatible2012Name Ada2012_Extensions => (Length => 21, Str => "Extension to Ada 2012 "), -- Extend2012Name Ada2012_Wording => (Length => 28, Str => "Wording Change from Ada 2012 "), -- DiffWord2012Name Element_Ref => (Length => 0, Str => (others => ' ')), -- Not used. Child_Ref => (Length => 0, Str => (others => ' ')), -- Not used. Usage_Note => (Length => 0, Str => (others => ' ')), -- Not used. Reason => (Length => 0, Str => (others => ' ')), -- Not used. Ramification => (Length => 0, Str => (others => ' ')), -- Not used. Proof => (Length => 0, Str => (others => ' ')), -- Not used. Imp_Note => (Length => 0, Str => (others => ' ')), -- Not used. Corr_Change => (Length => 0, Str => (others => ' ')), -- Not used. Discussion => (Length => 0, Str => (others => ' ')), -- Not used. Honest => (Length => 0, Str => (others => ' ')), -- Not used. Glossary_Marker => (Length => 0, Str => (others => ' ')), -- Not used. Bare_Annotation => (Length => 0, Str => (others => ' ')), -- Not used. Wide_Above => (Length => 0, Str => (others => ' ')), -- Not used. Example_Text => (Length => 0, Str => (others => ' ')), -- Not used. Child_Example_Text => (Length => 0, Str => (others => ' ')), -- Not used. Indented_Example_Text=>(Length => 0, Str => (others => ' ')), -- Not used. Code_Indented => (Length => 0, Str => (others => ' ')), -- Not used. Indent => (Length => 0, Str => (others => ' ')), -- Not used. Bulleted => (Length => 0, Str => (others => ' ')), -- Not used. Nested_Bulleted => (Length => 0, Str => (others => ' ')), -- Not used. Nested_X2_Bulleted=>(Length=> 0, Str => (others => ' ')), -- Not used. Display => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Display => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Indented => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Production=>(Length => 0, Str => (others => ' ')), -- Not used. Enumerated => (Length => 0, Str => (others => ' ')), -- Not used. Nested_Enumerated=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_1=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_2=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_3=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_4=>(Length => 0, Str => (others => ' ')), -- Not used. Small => (Length => 0, Str => (others => ' ')), -- Not used. Title => (Length => 0, Str => (others => ' ')), -- Not used. In_Table => (Length => 0, Str => (others => ' '))); -- Not used. Paragraph_Kind_Title : constant array (Paragraph_Type) of LString := (Plain => (Length => 0, Str => (others => ' ')), Introduction => (Length => 0, Str => (others => ' ')), -- IntroTitle (deleted). Language_Design => (Length => 26, Str => "Language Design Principles "), -- MetaRulesTitle Syntax => (Length => 6, Str => "Syntax "), -- SyntaxTitle Resolution => (Length => 21, Str => "Name Resolution Rules "), -- ResolutionTitle Legality => (Length => 14, Str => "Legality Rules "), -- LegalityTitle Static_Semantics=> (Length => 16, Str => "Static Semantics "), -- StaticSemTitle Link_Time => (Length => 22, Str => "Post-Compilation Rules "), -- LinkTimeTitle Run_Time => (Length => 17, Str => "Dynamic Semantics "), -- RunTimeTitle Bounded_Errors => (Length => 25, Str => "Bounded (Run-Time) Errors "), -- BoundedTitle Erroneous => (Length => 19, Str => "Erroneous Execution "), -- ErronTitle Requirements => (Length => 27, Str => "Implementation Requirements "), -- ImplReqTitle Documentation => (Length => 26, Str => "Documentation Requirements "), -- DocReqTitle Metrics => (Length => 7, Str => "Metrics "), -- MetricsTitle Permissions => (Length => 26, Str => "Implementation Permissions "), -- ImplPermTitle Advice => (Length => 21, Str => "Implementation Advice "), -- ImplAdviceTitle Notes => (Length => 5, Str => "NOTES "), -- NotesTitle Single_Note => (Length => 5, Str => "NOTES "), -- SimpleNoteTitle Examples => (Length => 8, Str => "Examples "), -- ExamplesTitle Ada83_Inconsistencies => (Length => 27, Str => "Inconsistencies With Ada 83 "), -- Inconsistent83Title Ada83_Incompatibilities => (Length => 29, Str => "Incompatibilities With Ada 83 "), -- Incompatible83Title Ada83_Extensions=> (Length => 20, Str => "Extensions to Ada 83 "), -- Extend83Title Ada83_Wording => (Length => 27, Str => "Wording Changes from Ada 83 "), -- DiffWord83Title Ada95_Inconsistencies => (Length => 27, Str => "Inconsistencies With Ada 95 "), -- Inconsistent95Title Ada95_Incompatibilities => (Length => 29, Str => "Incompatibilities With Ada 95 "), -- Incompatible95Title Ada95_Extensions=> (Length => 20, Str => "Extensions to Ada 95 "), -- Extend95Title Ada95_Wording => (Length => 27, Str => "Wording Changes from Ada 95 "), -- DiffWord95Title Ada2005_Inconsistencies => (Length => 29, Str => "Inconsistencies With Ada 2005 "), -- Inconsistent2005Title Ada2005_Incompatibilities => (Length => 31, Str => "Incompatibilities With Ada 2005 "), -- Incompatible2005Title Ada2005_Extensions => (Length => 22, Str => "Extensions to Ada 2005 "), -- Extend2005Title Ada2005_Wording => (Length => 29, Str => "Wording Changes from Ada 2005 "), -- DiffWord2005Title Ada2012_Inconsistencies => (Length => 29, Str => "Inconsistencies With Ada 2012 "), -- Inconsistent2012Title Ada2012_Incompatibilities => (Length => 31, Str => "Incompatibilities With Ada 2012 "), -- Incompatible2012Title Ada2012_Extensions => (Length => 22, Str => "Extensions to Ada 2012 "), -- Extend2012Title Ada2012_Wording => (Length => 29, Str => "Wording Changes from Ada 2012 "), -- DiffWord2012Title Element_Ref => (Length => 19, Str => "Element Reference: "), -- Paragraph start. Child_Ref => (Length => 28, Str => "Child Elements returned by: "), -- Paragraph start. Usage_Note => (Length => 12, Str => "Usage Note: "), -- Paragraph start. Reason => (Length => 8, Str => "Reason: "), -- Paragraph start. Ramification => (Length => 14, Str => "Ramification: "), -- Paragraph start. Proof => (Length => 7, Str => "Proof: "), -- Paragraph start. Imp_Note => (Length => 21, Str => "Implementation Note: "), -- Paragraph start. Corr_Change => (Length => 8, Str => "Change: "), -- Paragraph start. Discussion => (Length => 12, Str => "Discussion: "), -- Paragraph start. Honest => (Length => 14, Str => "To be honest: "), -- Paragraph start. Glossary_Marker => (Length => 16, Str => "Glossary entry: "), -- Paragraph start. Bare_Annotation => (Length => 0, Str => (others => ' ')), -- Not used. Wide_Above => (Length => 0, Str => (others => ' ')), -- Not used. Example_Text => (Length => 0, Str => (others => ' ')), -- Not used. Child_Example_Text => (Length => 0, Str => (others => ' ')), -- Not used. Indented_Example_Text=>(Length => 0, Str => (others => ' ')), -- Not used. Code_Indented => (Length => 0, Str => (others => ' ')), -- Not used. Indent => (Length => 0, Str => (others => ' ')), -- Not used. Bulleted => (Length => 0, Str => (others => ' ')), -- Not used. Nested_Bulleted => (Length => 0, Str => (others => ' ')), -- Not used. Nested_X2_Bulleted=>(Length=> 0, Str => (others => ' ')), -- Not used. Display => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Display => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Indented => (Length => 0, Str => (others => ' ')), -- Not used. Syntax_Production=>(Length => 0, Str => (others => ' ')), -- Not used. Enumerated => (Length => 0, Str => (others => ' ')), -- Not used. Nested_Enumerated=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_1=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_2=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_3=>(Length => 0, Str => (others => ' ')), -- Not used. Hanging_Indented_4=>(Length => 0, Str => (others => ' ')), -- Not used. Small => (Length => 0, Str => (others => ' ')), -- Not used. Title => (Length => 0, Str => (others => ' ')), -- Not used. In_Table => (Length => 0, Str => (others => ' '))); -- Not used. type Command_Type is ( -- Paragraphs: Text_Begin, Text_End, Redundant, Comment, Part, New_Page, Soft_Page, New_Column, RM_New_Page, New_Page_for_Version, New_Column_for_Version, RM_New_Page_for_Version, Not_Iso_RM_New_Page_for_Version, Iso_Only_RM_New_Page_for_Version, -- Basic text formatting: Bold, Italic, Roman, Swiss, Fixed, Roman_Italic, Shrink, Grow, Black, Red, Green, Blue, Keyword, Non_Terminal, Non_Terminal_Format, Example_Text, Example_Comment, No_Prefix, No_Para_Num, Keep_with_Next, Leading, Trailing, Up, Down, Thin_Line, Thick_Line, Tab_Clear, Tab_Set, -- Tables: Table, Table_Param_Caption, Table_Param_Header, Table_Param_Body, Table_Last, -- Pictures: Picture_Alone, Picture_Inline, -- Indexing: Index_List, Defn, RootDefn, PDefn, Defn2, RootDefn2, PDefn2, Index_See, Index_See_Also, See_Other, See_Also, Index_Root_Unit, Index_Child_Unit, Index_Subprogram_Child_Unit, Index_Type, Index_Subtype, Index_Subprogram, Index_Exception, Index_Object, Index_Package, Index_Other, Index_Check, Index_Attr, Index_Pragma, Index_Aspect, -- Clause labels: Labeled_Section, Labeled_Section_No_Break, Labeled_Clause, Labeled_Subclause, Labeled_Subsubclause, Labeled_Revised_Section, Labeled_Revised_Clause, Labeled_Revised_Subclause, Labeled_Revised_Subsubclause, Labeled_Added_Section, Labeled_Added_Clause, Labeled_Added_Subclause, Labeled_Added_Subsubclause, Labeled_Deleted_Clause, Labeled_Deleted_Subclause, Labeled_Deleted_Subsubclause, Preface_Section, Labeled_Annex, Labeled_Revised_Annex, Labeled_Added_Annex, Labeled_Informative_Annex, Labeled_Revised_Informative_Annex, Labeled_Added_Informative_Annex, Labeled_Normative_Annex, Labeled_Revised_Normative_Annex, Labeled_Added_Normative_Annex, Unnumbered_Section, Subheading, Heading, Center, Right, Added_Subheading, -- Clause references: Ref_Section, Ref_Section_Number, Ref_Section_by_Number, -- Links: Local_Target, Local_Link, URL_Link, AI_Link, -- Information: Syntax_Rule, Syntax_Rule_RHS, Syntax_Term, Syntax_Term_Undefined, Syntax_Prefix, Syntax_Summary, Syntax_Xref, Added_Syntax_Rule, Deleted_Syntax_Rule, Implementation_Defined, Implementation_Defined_List, To_Glossary, To_Glossary_Also, Change_To_Glossary, Change_To_Glossary_Also, Glossary_Text_Param, -- This is a parameter of the last four. Glossary_List, Prefix_Type, Reset_Prefix_Type, Attribute, Attribute_Leading, Attribute_Text_Param, -- The last is a parameter of Attribute. Attribute_List, Pragma_Syntax, Pragma_List, Added_Pragma_Syntax, Deleted_Pragma_Syntax, Package_List, Type_List, Subprogram_List, Exception_List, Object_List, -- Corrigendum changes: Change, Change_Param_Old, Change_Param_New, -- The latter are the parameters of "Change". Change_Reference, Change_Note, Change_Added, Change_Added_Param, Change_Deleted, Change_Deleted_Param, Change_Implementation_Defined, Change_Impdef_Text_Param, -- This is a parameter of the previous. Change_Implementation_Advice, Change_Impladv_Text_Param, -- This is a parameter of the previous. Added_Implementation_Advice_List, Change_Documentation_Requirement, Change_DocReq_Text_Param, -- This is a parameter of the previous. Added_Documentation_Requirements_List, Change_Aspect_Description, Change_AspectDesc_Text_Param, -- This is a parameter of the previous. Added_Aspect_Description_List, Change_Attribute, Change_Prefix_Type, Change_Prefix_Text_Param, -- This is a parameter of the previous. -- Text macros: Intro_Name, Syntax_Name, Resolution_Name, Legality_Name, Static_Name, Link_Name, Run_Name, Bounded_Name, Erroneous_Name, Req_Name, Doc_Name, Metrics_Name, Permission_Name, Advice_Name, Notes_Name, Single_Note_Name, Examples_Name, Meta_Name, Inconsistent83_Name, Incompatible83_Name, Extend83_Name, Wording83_Name, Inconsistent95_Name, Incompatible95_Name, Extend95_Name, Wording95_Name, Inconsistent2005_Name, Incompatible2005_Name, Extend2005_Name, Wording2005_Name, Inconsistent2012_Name, Incompatible2012_Name, Extend2012_Name, Wording2012_Name, Syntax_Title, Resolution_Title, Legality_Title, Static_Title, Link_Title, Run_Title, Bounded_Title, Erroneous_Title, Req_Title, Doc_Title, Metrics_Title, Permission_Title, Advice_Title, Notes_Title, Single_Note_Title, Examples_Title, Meta_Title, Inconsistent83_Title, Incompatible83_Title, Extend83_Title, Wording83_Title, Inconsistent95_Title, Incompatible95_Title, Extend95_Title, Wording95_Title, Inconsistent2005_Title, Incompatible2005_Title, Extend2005_Title, Wording2005_Title, Inconsistent2012_Title, Incompatible2012_Title, Extend2012_Title, Wording2012_Title, -- Character macros: EM_Dash, EN_Dash, LE, LT, GE, GT, NE, PI, Times, PorM, Single_Quote, Latin_1, Unicode, Ceiling, Floor, Absolute, Log, Thin_Space, Left_Quote, Right_Quote, Left_Double_Quote, Right_Double_Quote, Left_Quote_Pair, Right_Quote_Pair, Small_Dotless_I, Capital_Dotted_I, Unknown); function Command (Name : in ARM_Input.Command_Name_Type) return Command_Type; -- Return the command value for a particular command name: end ARM_Format.Data;�����������������������������������������������������������������������������������org.adaic.arm_form/progs/arm_frms.adb���������������������������������������������������������������0000755�0001752�0001001�00000123144�12066554512�017074� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� -- -- Ada reference manual formatter (ARM_Form). -- -- This subprogram is part of the command processor. -- -- We use dispatching calls to call the formatter, so the details of -- formatting are insulated from the code that reads the source and -- determines the details of the text. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2006, 2007, 2009, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 2/10/06 - RLB - Split from base package. -- 9/22/06 - RLB - Revised to use Clause_Number_Type, and to support -- Subsubclauses. -- 10/16/06 - RLB - Added definition of old non-terminals for NT linking. -- 2/16/07 - RLB - Added missing code to handle comments here. -- 7/31/07 - RLB - Added code to detect duplicated titles. -- 12/18/07 - RLB - Added Plain_Annex and associated commands. -- 5/06/09 - RLB - Added Labeled_Deleted_xxx. -- 5/07/09 - RLB - Changed above to load dead clauses. -- 10/18/11 - RLB - Changed to GPLv3 license. separate(ARM_Format) procedure Scan (Format_Object : in out Format_Type; File_Name : in String; Section_Number : in ARM_Contents.Section_Number_Type; Starts_New_Section : in Boolean) is -- Scans the contents for File_Name, determining the table of contents -- for the section. The results are written to the contents package. -- Starts_New_Section is True if the file starts a new section. -- Section_Number is the number (or letter) of the section. type Items is record Command : Command_Type; Close_Char : Character; -- Ought to be }, ], >, or ). end record; Nesting_Stack : array (1 .. 60) of Items; Nesting_Stack_Ptr : Natural := 0; Saw_a_Section_Header : Boolean := False; Input_Object : ARM_File.File_Input_Type; procedure Set_Nesting_for_Command (Command : in Command_Type; Param_Ch : in Character) is -- Push the command onto the nesting stack. begin if Nesting_Stack_Ptr < Nesting_Stack'Last then Nesting_Stack_Ptr := Nesting_Stack_Ptr + 1; Nesting_Stack (Nesting_Stack_Ptr) := (Command => Command, Close_Char => ARM_Input.Get_Close_Char (Param_Ch)); --Ada.Text_IO.Put_Line (" &Stack (" & Command_Type'Image(Command) & "); Close-Char=" & -- Nesting_Stack(Nesting_Stack_Ptr).Close_Char); else Ada.Text_IO.Put_Line ("** Nesting stack overflow on line" & ARM_File.Line_String (Input_Object)); for I in reverse Nesting_Stack'range loop Ada.Text_IO.Put_Line ("-- Command at" & Natural'Image(I) & " has a close char of '" & Nesting_Stack (Nesting_Stack_Ptr).Close_Char & "' for " & Command_Type'Image(Nesting_Stack (Nesting_Stack_Ptr).Command)); end loop; raise Program_Error; end if; end Set_Nesting_for_Command; procedure Scan_Command_with_Parameter is -- Scan the start of a command with a parameter. -- The parameter character has been scanned, and -- a stack item pushed. Title : ARM_Contents.Title_Type; Title_Length : Natural; procedure Get_Change_Version (Is_First : in Boolean; Version : out ARM_Contents.Change_Version_Type) is -- Get a parameter named "Version", containing a character -- representing the version number. Ch, Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Version" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => Is_First, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the version character: ARM_File.Get_Char (Input_Object, Ch); Version := ARM_Contents.Change_Version_Type(Ch); ARM_File.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for change version on line " & ARM_File.Line_String (Input_Object)); ARM_File.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; end Get_Change_Version; begin case Nesting_Stack(Nesting_Stack_Ptr).Command is when Labeled_Section | Labeled_Section_No_Break | Labeled_Annex | Labeled_Informative_Annex | Labeled_Normative_Annex | Labeled_Clause | Labeled_Subclause | Labeled_Subsubclause => -- Load the title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Nesting_Stack(Nesting_Stack_Ptr).Close_Char, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); elsif Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); else Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); end if; begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package: if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Subclause then ARM_Contents.Add (Title, ARM_Contents.Subclause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Subsubclause then ARM_Contents.Add (Title, ARM_Contents.Subsubclause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Clause then ARM_Contents.Add (Title, ARM_Contents.Clause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Section or else Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Section_No_Break then ARM_Contents.Add (Title, ARM_Contents.Section, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Annex then ARM_Contents.Add (Title, ARM_Contents.Plain_Annex, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Normative_Annex then ARM_Contents.Add (Title, ARM_Contents.Normative_Annex, Format_Object.Clause_Number); else ARM_Contents.Add (Title, ARM_Contents.Informative_Annex, Format_Object.Clause_Number); end if; end; Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); when Unnumbered_Section => -- Load the title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Nesting_Stack(Nesting_Stack_Ptr).Close_Char, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); Format_Object.Unnumbered_Section := Format_Object.Unnumbered_Section + 1; -- This section will be numbered 0.Unnumbered_Section: Format_Object.Clause_Number := (Section => 0, Clause => Format_Object.Unnumbered_Section, Subclause => 0, Subsubclause => 0); begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package: ARM_Contents.Add (Title, ARM_Contents.Unnumbered_Section, Format_Object.Clause_Number); end; Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); when Labeled_Revised_Annex | Labeled_Revised_Informative_Annex | Labeled_Revised_Normative_Annex | Labeled_Revised_Section | Labeled_Revised_Clause | Labeled_Revised_Subclause | Labeled_Revised_Subsubclause => declare Old_Title : ARM_Contents.Title_Type; Old_Title_Length : Natural; Close_Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; Initial_Version : ARM_Contents.Change_Version_Type := '0'; begin Get_Change_Version (Is_First => True, Version => Version); -- Check for the optional "InitialVersion" parameter, -- stopping when we reach "New": declare Which_Param : ARM_Input.Param_Num; Ch : Character; begin -- If there is no InitialVersion command, use the same -- version of the rest of the command. loop ARM_Input.Check_One_of_Parameter_Names (Input_Object, Param_Name_1 => "InitialVersion" & (15..ARM_Input.Command_Name_Type'Last => ' '), Param_Name_2 => "New" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Found => Which_Param, Param_Close_Bracket => Close_Ch); if Which_Param = 1 and then Close_Ch /= ' ' then -- Found InitialVersion ARM_File.Get_Char (Input_Object, Ch); Initial_Version := Ch; ARM_File.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for InitialVersion parameter on line " & ARM_File.Line_String (Input_Object)); ARM_File.Replace_Char (Input_Object); end if; else -- We found "New" (or an error) exit; -- Handling of New is below. end if; end loop; end; if Close_Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Old" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Old_Title, Old_Title_Length); Old_Title(Old_Title_Length+1 .. Old_Title'Last) := (others => ' '); end if; end if; ARM_File.Get_Char (Input_Object, Close_Ch); if Close_Ch /= Nesting_Stack(Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Revised_(SubClause|Annex) on line " & ARM_File.Line_String (Input_Object)); ARM_File.Replace_Char (Input_Object); end if; if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); elsif Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); else Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); end if; begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package: if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Subclause then ARM_Contents.Add (Title, ARM_Contents.Subclause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Subclause, Format_Object.Clause_Number, Version => Initial_Version); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Subsubclause then ARM_Contents.Add (Title, ARM_Contents.Subsubclause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Subsubclause, Format_Object.Clause_Number, Version => Initial_Version); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Clause then ARM_Contents.Add (Title, ARM_Contents.Clause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Clause, Format_Object.Clause_Number, Version => Initial_Version); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Section then ARM_Contents.Add (Title, ARM_Contents.Section, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Section, Format_Object.Clause_Number, Version => Initial_Version); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Annex then ARM_Contents.Add (Title, ARM_Contents.Plain_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Plain_Annex, Format_Object.Clause_Number, Version => Initial_Version); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Normative_Annex then ARM_Contents.Add (Title, ARM_Contents.Normative_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Normative_Annex, Format_Object.Clause_Number, Version => Initial_Version); else -- Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Revised_Informative_Annex then ARM_Contents.Add (Title, ARM_Contents.Informative_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old (Old_Title, ARM_Contents.Informative_Annex, Format_Object.Clause_Number, Version => Initial_Version); end if; end; Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Labeled_Added_Annex | Labeled_Added_Informative_Annex | Labeled_Added_Normative_Annex | Labeled_Added_Section | Labeled_Added_Clause | Labeled_Added_Subclause | Labeled_Added_Subsubclause => declare Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; How : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Ch, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); end if; ARM_File.Get_Char (Input_Object, Ch); if Ch /= Nesting_Stack(Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Added_(Sub)Clause on line " & ARM_File.Line_String (Input_Object)); ARM_File.Replace_Char (Input_Object); end if; -- Determine the insertion state for this label: Calc_Change_Disposition (Format_Object, Version => Version, Operation => ARM_Output.Insertion, Text_Kind => How); if How = Do_Not_Display_Text then null; -- Nothing to display, so we do *not* number it -- or insert it into the contents database. else begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package: if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Subclause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Subclause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; ARM_Contents.Add (Title, ARM_Contents.Subsubclause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Subsubclause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Clause, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Clause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Section then if Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); end if; Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Section, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Section, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Annex then if Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); end if; Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Plain_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Plain_Annex, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Normative_Annex then if Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); end if; Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Normative_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Normative_Annex, Format_Object.Clause_Number); else -- Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Added_Informative_Annex then if Saw_a_Section_Header then Ada.Text_IO.Put_Line (" ** Multiple section headers in a file, line " & ARM_File.Line_String (Input_Object)); end if; Saw_a_Section_Header := True; Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, -- Will be set elsewhere. Clause => 0, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Informative_Annex, Format_Object.Clause_Number, Version => Version); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Informative_Annex, Format_Object.Clause_Number); end if; end; end if; Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Labeled_Deleted_Clause | Labeled_Deleted_Subclause | Labeled_Deleted_Subsubclause => declare Ch : Character; Version : ARM_Contents.Change_Version_Type := '0'; How : ARM_Output.Change_Type; use type ARM_Output.Change_Type; begin Get_Change_Version (Is_First => True, Version => Version); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Ch); if Ch /= ' ' then -- There is a parameter: -- Load the new title into the Title string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Ch, Title, Title_Length); Title(Title_Length+1 .. Title'Last) := (others => ' '); end if; ARM_File.Get_Char (Input_Object, Ch); if Ch /= Nesting_Stack(Nesting_Stack_Ptr).Close_Char then Ada.Text_IO.Put_Line (" ** Bad close for Labeled_Deleted_(Sub)Clause on line " & ARM_File.Line_String (Input_Object)); ARM_File.Replace_Char (Input_Object); end if; -- Determine the insertion state for this label: Calc_Change_Disposition (Format_Object, Version => Version, Operation => ARM_Output.Deletion, Text_Kind => How); --Ada.Text_IO.Put_Line ("Labeled_Deleted disp: " & ARM_Output.Change_Type'Image(How)); if How = ARM_Output.None then -- Normal text, number normally. begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package: if Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Deleted_Subclause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause, Subclause => Format_Object.Clause_Number.Subclause + 1, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Subclause, Format_Object.Clause_Number, Version => '0'); -- Version here is an insertion version, and this was available from the beginning. ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Subclause, Format_Object.Clause_Number); elsif Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Deleted_Subsubclause then Format_Object.Clause_Number.Subsubclause := Format_Object.Clause_Number.Subsubclause + 1; ARM_Contents.Add (Title, ARM_Contents.Subsubclause, Format_Object.Clause_Number, Version => '0'); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Subsubclause, Format_Object.Clause_Number); else -- Nesting_Stack(Nesting_Stack_Ptr).Command = Labeled_Deleted_Clause then Format_Object.Clause_Number := (Section => Format_Object.Clause_Number.Section, Clause => Format_Object.Clause_Number.Clause + 1, Subclause => 0, Subsubclause => 0); ARM_Contents.Add (Title, ARM_Contents.Clause, Format_Object.Clause_Number, Version => '0'); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Clause, Format_Object.Clause_Number); end if; end; elsif How = ARM_Output.Insertion then -- Huh? We're deleting here. raise Program_Error; elsif How = ARM_Output.Deletion then -- We'll just display the header without a number. -- But we need to insert it so that x-refs don't -- fail. begin declare Ref : constant String := ARM_Contents.Lookup_Clause_Number (Title); begin -- If we get here, this title is already defined. Oops. Ada.Text_IO.Put_Line (" ** Title """ & Title(1..Title_Length) & """ is multiply defined on line " & ARM_File.Line_String (Input_Object)); Ada.Text_IO.Put_Line (" Initial use is for clause " & Ref); end; exception when ARM_Contents.Not_Found_Error => -- OK, not previously defined. -- Load the title into the contents package as a dead clause: ARM_Contents.Add (Title, ARM_Contents.Dead_Clause, (Section => 0, Clause => 1, Subclause => 0, Subsubclause => 0), Version => '0'); ARM_Contents.Add_Old ((others => ' '), ARM_Contents.Dead_Clause, (Section => 0, Clause => 1, Subclause => 0, Subsubclause => 0)); end; elsif How = Do_Not_Display_Text then null; -- Nothing to display/number. end if; Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; --Ada.Text_IO.Put_Line (" &Unstack (Header)"); end; when Syntax_Rule | Added_Syntax_Rule | Deleted_Syntax_Rule => -- @Syn{[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} -- @AddedSyn{Version=[<Version>],[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} -- @DeletedSyn{Version=[<Version>],[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} -- We need to index the non-terminal, so we can link to it -- later. (If we didn't do this here, we wouldn't be able -- to handle forward references.) -- We only care about the non-terminal, so we skip the other -- parts. declare Close_Ch, Ch : Character; Seen_First_Param : Boolean := False; Non_Terminal : String (1..120); NT_Len : Natural := 0; begin if Nesting_Stack(Nesting_Stack_Ptr).Command /= Syntax_Rule then -- Get and skip the Version parameter. Seen_First_Param := True; Get_Change_Version (Is_First => True, Version => Ch); end if; -- Peek to see if Tabs parmeter is present, and skip it if -- it is: ARM_File.Get_Char (Input_Object, Ch); ARM_File.Replace_Char (Input_Object); if Ch = 'T' or else Ch = 't' then ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Tabs" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => (not Seen_First_Param), Param_Close_Bracket => Close_Ch); Seen_First_Param := True; if Close_Ch /= ' ' then -- Grab the tab string: ARM_Input.Skip_until_Close_Char ( Input_Object, Close_Ch); -- else no parameter. Weird. end if; end if; -- Get the LHS parameter and save it: ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "LHS" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => (not Seen_First_Param), Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Copy over the non-terminal: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Non_Terminal, NT_Len); -- else no parameter. Weird. end if; -- Skip the RHS parameter: ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "RHS" & (4..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Close_Ch); Seen_First_Param := True; if Close_Ch /= ' ' then -- Grab the tab string: ARM_Input.Skip_until_Close_Char ( Input_Object, Close_Ch); -- else no parameter. Weird. end if; declare The_Non_Terminal : constant String := Ada.Characters.Handling.To_Lower ( Get_Current_Item (Format_Object, Input_Object, Non_Terminal(1..NT_Len))); -- Handle embedded @Chg. The_Old_Non_Terminal : constant String := Ada.Characters.Handling.To_Lower ( Get_Old_Item (Format_Object, Input_Object, Non_Terminal(1..NT_Len))); -- Handle embedded @Chg. begin if Ada.Strings.Fixed.Index (The_Non_Terminal, "@") /= 0 then -- Still embedded commands, do not register. Ada.Text_IO.Put_Line ("** Saw Non-Terminal with embedded commands: " & Non_Terminal(1..NT_Len) & " in " & Clause_String (Format_Object)); elsif The_Non_Terminal = "" then null; -- Deleted Non-Terminal, nothing to do. else -- Save the non-terminal: declare Link_Target : ARM_Syntax.Target_Type; begin ARM_Syntax.Add_Non_Terminal (NT_Name => The_Non_Terminal, For_Clause => Clause_String (Format_Object), Link_Target => Link_Target); end; --Ada.Text_IO.Put_Line ("%% Saw simple Non-Terminal: " & The_Non_Terminal & " in " -- & Clause_String (Format_Object)); end if; if The_Old_Non_Terminal = "" then null; -- No old Non-Terminal, nothing to do. elsif ARM_Syntax.Non_Terminal_Clause (The_Old_Non_Terminal) /= "" then null; -- This non-terminal is already defined; -- that presumably is a *new* definition, -- we'll use that instead of this one. else -- Save the non-terminal: declare Link_Target : ARM_Syntax.Target_Type; begin ARM_Syntax.Add_Non_Terminal (NT_Name => The_Old_Non_Terminal, For_Clause => Clause_String (Format_Object), Link_Target => Link_Target); end; --Ada.Text_IO.Put_Line ("%% Saw simple old Non-Terminal: " & The_Old_Non_Terminal & " in " -- & Clause_String (Format_Object)); end if; end; end; when Comment => --Ada.Text_IO.Put_Line("Comment with Close=" & Nesting_Stack(Nesting_Stack_Ptr).Close_Char & -- " on line " & ARM_File.Line_String (Input_Object)); -- Skip the contents of this command. ARM_Input.Skip_until_Close_Char (Input_Object, Nesting_Stack(Nesting_Stack_Ptr).Close_Char); ARM_File.Replace_Char (Input_Object); -- Put the close character back. --Ada.Text_IO.Put_Line("Comment done"); when others => null; -- Not in scanner. end case; end Scan_Command_with_Parameter; procedure Handle_End_of_Command is -- Unstack and handle the end of Commands. begin case Nesting_Stack(Nesting_Stack_Ptr).Command is when others => -- No special handling needed. null; end case; --Ada.Text_IO.Put_Line (" &Unstack (Normal-"& Command_Type'Image(Nesting_Stack(Nesting_Stack_Ptr).Command) & ")"); Nesting_Stack_Ptr := Nesting_Stack_Ptr - 1; end Handle_End_of_Command; procedure Scan_Special is -- Scan a special command/macro/tab. -- These all start with '@'. -- @xxxx is a command. It may have parameters delimited by -- (), {}, [], or <>. There does not appear to be an escape, so -- we don't have to worry about '}' being used in {} brackets, -- for example. (Must be a pain to write, though.) Command_Name : ARM_Input.Command_Name_Type; Ch : Character; begin ARM_File.Get_Char (Input_Object, Ch); if Ch = '\' then -- This represents a tab (or the end of centered text). We're -- done here. return; elsif Ch = '=' then -- This marks the beginning of centered text. -- We're done here. return; elsif Ch = '^' then -- This represented a tab stop (these should have been -- deleted from the input). We're done here. return; elsif Ch = '@' then -- This represents @ in the text. We're done here. return; elsif Ch = ' ' then -- This represents a hard space in the text. We're done here. return; elsif Ch = ';' then -- This seems to be an end of command (or substitution) marker. -- For instance, it is used in Section 1: -- .. the distinction between @ResolutionName@;s and ... -- This converts to: -- .. the distinction between Name Resolution Rules and ... -- Without it, the 's' would append to the command name, and -- we would get the wrong command. Thus, it itself does nothing -- at all, so we're done here. return; elsif Ch = '-' then -- This represents a subscript. It has an argument. ARM_File.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Command => Unknown, Param_Ch => Ch); else -- No parameter. Weird. ARM_File.Replace_Char (Input_Object); end if; return; elsif Ch = '+' then -- This represents a superscript. It has an argument. ARM_File.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Command => Unknown, Param_Ch => Ch); else -- No parameter. Weird. ARM_File.Replace_Char (Input_Object); end if; return; elsif Ch = ':' then -- This is a period type marker. We're done here. return; elsif Ch = '*' then -- This is a line break. We're done here. return; elsif Ch = '|' then -- This is a soft line break. We're done here. return; elsif Ch = '!' then -- This is a soft hyphen break. We're done here. return; elsif Ch = Ascii.LF then -- Stand alone '@'. -- I now believe this is an error. It appears in -- Infosys.MSS, and seems to have something to do with formatting. return; end if; ARM_File.Replace_Char (Input_Object); Arm_Input.Get_Name (Input_Object, Command_Name); --Ada.Text_IO.Put_Line("Command=" & Command_Name & " Nesting=" & Natural'Image(Nesting_Stack_Ptr)); ARM_File.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Set_Nesting_for_Command (Command => Command (Ada.Characters.Handling.To_Lower (Command_Name)), Param_Ch => Ch); Scan_Command_with_Parameter; else ARM_File.Replace_Char (Input_Object); -- We're not interested in commands with no parameters. end if; end Scan_Special; begin Ada.Text_IO.Put_Line ("-- Scanning " & File_Name); begin Arm_File.Open (Input_Object, File_Name); exception when others => Ada.Text_IO.Put_Line ("** Unable to open file " & File_Name); raise; end; if Starts_New_Section then Format_Object.Clause_Number := (Section => Section_Number, others => 0); end if; loop declare Char : Character; begin ARM_File.Get_Char (Input_Object, Char); --Ada.Text_IO.Put_Line("Char=" & Char & " Nesting=" & Natural'Image(Nesting_Stack_Ptr)); case Char is when '@' => Scan_Special; when Ascii.SUB => exit; -- End of file. when others => if Nesting_Stack_Ptr /= 0 and then Nesting_Stack (Nesting_Stack_Ptr).Close_Char /= ' ' and then Nesting_Stack (Nesting_Stack_Ptr).Close_Char = Char then -- Closing a command, remove it from the stack. Handle_End_of_Command; else null; -- Ordinary characters, nothing to do. end if; end case; end; end loop; -- Reached end of the file. Ada.Text_IO.Put_Line (" Lines scanned: " & ARM_File.Line_String (Input_Object)); ARM_File.Close (Input_Object); if Nesting_Stack_Ptr /= 0 then Ada.Text_IO.Put_Line (" ** Unfinished commands detected."); end if; end Scan; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/arm_html.adb���������������������������������������������������������������0000755�0001752�0001001�00000751030�12273462240�017066� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������with -- ARM_Output, -- ARM_Contents, -- Ada.Text_IO, Ada.Exceptions, Ada.Strings.Maps.Constants, Ada.Strings.Fixed, Ada.Unchecked_Deallocation; package body ARM_HTML is -- -- Ada reference manual formatter (ARM_Form). -- -- This package defines the HTML output object. -- Output objects are responsible for implementing the details of -- a particular format. -- -- --------------------------------------- -- Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, -- 2008, 2009, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/19/00 - RLB - Created base package. -- 4/21/00 - RLB - Added line break and hard space routines. -- 4/24/00 - RLB - Added DR references and Insert/Delete text formats. -- 4/25/00 - RLB - Added size to format. -- 4/26/00 - RLB - Added paragraph formats. -- 4/29/00 - RLB - Added more paragraph formats. -- 5/10/00 - RLB - Added even more formats. -- - RLB - Added End_Hang_Item. -- 5/12/00 - RLB - Added No_Prefix to Start_Paragraph. -- 5/13/00 - RLB - Added Special_Character. -- 5/16/00 - RLB - Added additional special characters. -- 5/17/00 - RLB - Added New_Page. -- 5/22/00 - RLB - Added Includes_Changes to Create. -- 5/23/00 - RLB - Added multi-column formats and New_Column. -- - Added Tab_Info and Tab_Stops. -- 5/24/00 - RLB - Added Location to Text_Format. -- - RLB - Added No_Breaks and Keep_with_Next to Start_Paragraph. -- 5/25/00 - RLB - Added Big_Files to Create. Added Justification. -- - RLB - Added Separator_Lines and TOC routines. -- - RLB - Added "Legal" to the footer, pointing at the title page. -- 5/26/00 - RLB - Added table operations. -- 5/28/00 - RLB - Added index references. -- 6/ 2/00 - RLB - Added Soft_Line_Break. -- 8/ 2/00 - RLB - Added Soft_Hyphen_Break and left and right quote -- characters. -- - RLB - Added additional styles. -- 8/ 7/00 - RLB - Added Leading flag to Start_Paragraph, removed "Leading" -- styles. -- 8/11/00 - RLB - Added Hanging_in_Bulleted styles. -- 8/16/00 - RLB - Added Code_Indented_Nested_Bulleted. -- 8/17/00 - RLB - Replaced "Leading" by "Space_After". -- - RLB - Added Nested_Enumerated. -- 8/22/00 - RLB - Added Revised_Clause_Header. -- 9/ 8/00 - RLB - Removed soft hyphen, as this does not work on either -- browser I tried. -- 9/26/00 - RLB - Added Syntax_Summary style. -- 9/27/00 - RLB - Added tab emulation when in the fixed font. -- 9/28/00 - RLB - Added some style sheets. -- - RLB - Updated to use absolute positioning for paragraph -- numbers (this looks much better than floating). -- 7/18/01 - RLB - Added "Indented" style to supported styles for -- multi-column. -- - RLB - Implemented single "Big-File" support. -- 7/18/02 - RLB - Removed Document parameter from Create, replaced by -- three strings and For_ISO boolean. -- - RLB - Added AI_Reference. -- - RLB - Added Change_Version_Type and uses. -- 1/15/03 - RLB - Removed space from DIV.paranum, as it doesn't validate -- with it. -- 4/10/03 - RLB - Updated to add access to search pages (not generated -- here; make them by hand, it only needs to be done once). -- - RLB - Updated to insure that changes are separated by a space. -- 4/11/03 - RLB - Changed some formats to meet WC3 validation requirements. -- 9/09/04 - RLB - Removed unused junk noted by Stephen Leake. -- 9/10/04 - RLB - Added "Both" to possible changes to handle -- replacement of changed text. -- 9/14/04 - RLB - Moved Change_Version_Type to ARM_Contents. -- - RLB - Changed to use left/right quotes whether or not Unicode -- is being used. (These work on IE, but not on old -- Netscape.) -- 9/16/04 - RLB - Added a charset meta in the header, so that browsers -- can't misinterpret these documents. -- 11/03/04 - RLB - Added Nested_X2_Bulleted. -- 11/15/04 - RLB - Added Indented_Nested_Bulleted. -- 12/15/04 - RLB - Added wider columns. -- 1/24/05 - RLB - Added Inner_Indented. -- 2/ 1/05 - RLB - Added Turkish chars to allow an AARM note. -- 3/15/05 - RLB - Turned on Unicode characters at Pascal's insistence. -- 3/17/05 - RLB - Removed ceiling and floor characters because they don't -- work on Windows. -- 4/ 7/05 - RLB - Added "Related Documents" link, so users can go between -- the RM and AARM (and also so that they see the ARA -- sponsor ads). -- 5/27/05 - RLB - Added arbitrary Unicode characters. -- 1/11/06 - RLB - Eliminated dispatching Create in favor of tailored -- versions. -- 1/12/06 - RLB - Added a number of parameters to Create. -- 1/16/06 - RLB - Reduced space around button bars. -- 1/18/06 - RLB - Added additional styles. -- 1/19/06 - RLB - Added code so that only styles that are used are -- included in the result (this decreases the minimum -- file size by a lot). -- 1/21/06 - RLB - Specified leading for Swiss example styles, because -- they are too close otherwise. -- 1/28/06 - RLB - Changed so that button highlights are removed correctly. -- - RLB - Added tab emulation settings. -- 2/ 8/06 - RLB - Added additional parameters to the table command. -- 2/10/06 - RLB - Added even more additional parameters to the -- table command. -- - RLB - Added picture command. -- 2/19/06 - RLB - Added Number_Paragraphs flag and large letter count. -- 3/01/06 - RLB - Fixed bug in Text_Format when changing fonts. -- 3/03/06 - RLB - Moved paragraph numbers down slightly; this looks a lot -- better on Firefox, and better even on IE. -- - RLB - Added Optimize_for_Firefox flag, and associated style -- changes. -- - RLB - Added code so that spaces after an opening tag -- and before a closing tag are converted to non-breaking. -- 3/28/06 - RLB - Removed unnecessary space from headers. -- 3/30/06 - RLB - Added a bit of space around inline pictures. -- 9/21/06 - RLB - Added Body_Font. -- 9/22/06 - RLB - Added Subsubclause. -- 9/23/06 - RLB - Fixed bug in borderless tables. -- 9/25/06 - RLB - Handled optional renaming of TOC. -- - RLB - Added Last_Column_Width to Start_Table. -- - RLB - Fixed broken enumerated style. -- 10/13/06 - RLB - Added specifiable colors. -- - RLB - Added Local_Link_Start and Local_Link_End to allow -- formatting in the linked text. -- 11/10/06 - RLB - Fixed nesting of text formatting *again*. (AARM 13.11 -- failed WC 3 validation.) -- 2/ 9/07 - RLB - Changed comments on AI_Reference. -- 2/14/07 - RLB - Revised to separate style and indent information -- for paragraphs. -- 2/15/07 - RLB - Redid enumeration and bullet indenting to make the -- formats work consistently on Firefox and IE. -- 2/19/07 - RLB - Added Title style. -- 12/14/07 - RLB - Added code to support multi-column text without -- requiring New_Column calls. -- 12/18/07 - RLB - Added Plain_Annex. -- 12/19/07 - RLB - Added DOS_Filename flag. -- - RLB - Added limited colors to Text_Format. -- 1/02/08 - RLB - Made DOS filenames into all CAPS. -- 5/ 7/09 - RLB - Added code to prevent making links to dead clauses. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/25/11 - RLB - Added old insertion version to Revised_Clause_Header. -- 2/15/12 - RLB - Removed horizontal rules from page breaks in HTML; -- they never are necessary and cause weird looks for -- breaks put in solely to make the "final" version look -- good in PDF form. -- 5/18/12 - RLB - Added anchors to each paragraph number as suggested -- on comp.lang.ada. -- 8/31/12 - RLB - Added Output_Path. -- 10/18/12 - RLB - Added additional hanging styles. -- 11/26/12 - RLB - Added subdivision names to Clause_Header and -- Revised_Clause_Header. -- 12/17/12 - RLB - Added AI12 references. Defined a change color for -- "version 4" (Ada 202x). -- 3/26/13 - RLB - Added Script_HTML. LINE_LENGTH : constant := 78; -- Maximum intended line length. SWISS_FONT_CODE : constant String := "<font face=""Arial, Helvetica"">"; SMALL_SWISS_FONT_CODE : constant String := "<font face=""Arial, Helvetica"" size=-1>"; TINY_SWISS_FONT_CODE : constant String := "<font face=""Arial, Helvetica"" size=-2>"; LEADING_PERCENT : constant := 70; -- Leading is 70% of normal height. TRAILING_PERCENT : constant := 150; -- Leading is 150% of normal height. INDENT_EMS_FOR_PARANUMS : constant := 12; -- Indent *all* text (for HTML 4) this amount to leave (some) room for -- the paragraph numbers. In 0.1 EMs. OPTIMIZE_FOR_FIREFOX : constant Boolean := True; -- If True, we'll optimize for Firefox; otherwise, we'll optimize for -- IE 6. Note that IE generally shows the Firefox code better than -- Firefox shows the IE code, so we generally recommend setting to -- True unless IE must be perfect. type Tag_Kind is (DIV, UL, DL); type Format_Info_Type is record Defined: Boolean := False; Tag : Tag_Kind; Size : Integer; -- In relative "units" (based on the normal size). A unit is 125%/80% of normal. Font : ARM_Output.Font_Family_Type; Indent : Natural; -- In "units". (A unit is = 2EM of the full sized font). Right_Indent : Natural; -- In "units". (A unit is = 2EM of the full sized font). Hang_Outdent : Natural; -- In "units". (A unit is = 2EM of the full sized font). -- This is the amount that the hanging text hangs out. Normal -- text starts at Hang_Outdent + Indent "units". Before : Integer; -- Vertical space before in 0.1 EM. After : Natural; -- Vertical space after in 0.1 EM. end record; -- In the following, "Default" means the Body_Font. Paragraph_Info : array (ARM_Output.Paragraph_Style_Type, ARM_Output.Paragraph_Indent_Type) of Format_Info_Type; -- Defined below in the body of the package. -- Are the various styles used?? Paragraph_Used : array (ARM_Output.Paragraph_Style_Type, ARM_Output.Paragraph_Indent_Type) of Boolean; Revision_Used : array (ARM_Contents.Change_Version_Type) of Boolean; Paranum_Used : Boolean; procedure Free is new Ada.Unchecked_Deallocation (Column_Text_Item_Type, Column_Text_Ptr); function Make_Clause_Anchor_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the Clause anchor name for the current output object and -- Clause_Number. Clause_Name : String(1..10); Clause_Name_Len : Natural; begin if Clause_Number'Length >= 7 and then Clause_Number(Clause_Number'First .. Clause_Number'First + 5) = "Annex " then Clause_Name(1) := Clause_Number(Clause_Number'First + 6); -- We only want the letter. Clause_Name_Len := 1; else Clause_Name_Len := Clause_Number'Length; Clause_Name(1..Clause_Name_Len) := Clause_Number; for I in 1 .. Clause_Name_Len loop if Clause_Name(I) = '.' then Clause_Name(I) := '-'; end if; end loop; end if; if Output_Object.DOS_Filenames and (not Output_Object.Big_Files) then -- If the section number is a single character, then -- prefix it with '-': if Clause_Name_Len = 1 then Clause_Name(2) := Clause_Name(1); Clause_Name(1) := '-'; Clause_Name_Len := 2; elsif Clause_Name_Len = 2 then null; else if Clause_Name(2) = '-' then Clause_Name(2..Clause_Name_Len+1) := Clause_Name(1..Clause_Name_Len); Clause_Name(1) := '-'; Clause_Name_Len := Clause_Name_Len + 1; end if; -- OK, the section name is exactly two characters. -- Figure out the Clause name. if Clause_Name_Len < 4 or else Clause_Name(3) /= '-' or else Clause_Name(4) not in '0'..'9' or else (Clause_Name_Len >= 5 and then Clause_Name(5) /= '-' and then Clause_Name(5) not in '0'..'9') or else (Clause_Name_Len >= 6 and then Clause_Name(5) /= '-' and then Clause_Name(6) /= '-') then -- The clause number is 1 or 2 digits following a '-', -- and is either the end of the string or followed by a '-'. Ada.Exceptions.Raise_Exception (Program_Error'Identity, "Weird clause number:" & Clause_Number); elsif Clause_Name_Len = 4 or else Clause_Name(5) = '-' then -- Clause is a single digit. Clause_Name(3..Clause_Name_Len-1) := Clause_Name(4..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 1; elsif Clause_Name(4) = '1' then -- Clause is 10..19 Clause_Name(3) := Character'Val( Character'Pos(Clause_Name(5))-Character'Pos('0')+Character'Pos('A')); Clause_Name(4..Clause_Name_Len-2) := Clause_Name(6..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; elsif Clause_Name(4) = '2' then -- Clause is 20..29 Clause_Name(3) := Character'Val( Character'Pos(Clause_Name(5))-Character'Pos('0')+Character'Pos('A')+10); Clause_Name(4..Clause_Name_Len-2) := Clause_Name(6..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; elsif Clause_Name(4) = '3' then -- Clause is 30..39 if Clause_Name(5) > '5' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Clause too large=" & Clause_Number); end if; Clause_Name(3) := Character'Val( Character'Pos(Clause_Name(5))-Character'Pos('0')+Character'Pos('A')+20); Clause_Name(4..Clause_Name_Len-2) := Clause_Name(6..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; else Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Clause too large=" & Clause_Number); end if; -- OK, the section number is exactly two characters, and the -- clause number is exactly one. Figure out the subclause -- name: if Clause_Name_Len = 3 then null; -- We're done, no subclause. elsif Clause_Name_Len < 5 or else Clause_Name(4) /= '-' or else Clause_Name(5) not in '0'..'9' or else (Clause_Name_Len >= 6 and then Clause_Name(6) /= '-' and then Clause_Name(6) not in '0'..'9') or else (Clause_Name_Len >= 7 and then Clause_Name(6) /= '-' and then Clause_Name(7) /= '-') then -- The subclause number is 1 or 2 digits following a '-', -- and is either the end of the string or followed by a '-'. Ada.Exceptions.Raise_Exception (Program_Error'Identity, "Weird subclause number:" & Clause_Number); elsif Clause_Name_Len = 5 or else Clause_Name(6) = '-' then -- SubClause is a single digit. Clause_Name(4..Clause_Name_Len-1) := Clause_Name(5..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 1; elsif Clause_Name(5) = '1' then -- SubClause is 10..19 Clause_Name(4) := Character'Val( Character'Pos(Clause_Name(6))-Character'Pos('0')+Character'Pos('A')); Clause_Name(5..Clause_Name_Len-2) := Clause_Name(7..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; elsif Clause_Name(5) = '2' then -- SubClause is 20..29 Clause_Name(4) := Character'Val( Character'Pos(Clause_Name(6))-Character'Pos('0')+Character'Pos('A')+10); Clause_Name(5..Clause_Name_Len-2) := Clause_Name(7..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; elsif Clause_Name(5) = '3' then -- SubClause is 30..39 if Clause_Name(6) > '5' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Subclause too large=" & Clause_Number); end if; Clause_Name(4) := Character'Val( Character'Pos(Clause_Name(6))-Character'Pos('0')+Character'Pos('A')+20); Clause_Name(5..Clause_Name_Len-2) := Clause_Name(7..Clause_Name_Len); Clause_Name_Len := Clause_Name_Len - 2; else Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Subclause too large=" & Clause_Number); end if; -- OK, the section number is exactly two characters, and the -- clause number is one, and the subclause number is one or zero. -- Figure out the subsubclause name: if Clause_Name_Len < 5 then null; -- We're done, no subsubclause. elsif Clause_Name_Len < 6 or else Clause_Name(5) /= '-' or else Clause_Name(6) not in '0'..'9' or else (Clause_Name_Len >= 7 and then Clause_Name(7) not in '0'..'9') or else (Clause_Name_Len >= 8) then -- The subsubclause number is 1 or 2 digits following a '-', -- and is the end of the string Ada.Exceptions.Raise_Exception (Program_Error'Identity, "Weird subclause number:" & Clause_Number); elsif Clause_Name_Len = 6 then -- SubSubClause is a single digit. Clause_Name(5) := Clause_Name(6); Clause_Name_Len := 5; elsif Clause_Name(6) = '1' then -- SubSubClause is 10..19 Clause_Name(5) := Character'Val( Character'Pos(Clause_Name(7))-Character'Pos('0')+Character'Pos('A')); Clause_Name_Len := 5; elsif Clause_Name(5) = '2' then -- SubSubClause is 20..29 Clause_Name(5) := Character'Val( Character'Pos(Clause_Name(7))-Character'Pos('0')+Character'Pos('A')+10); Clause_Name_Len := 5; elsif Clause_Name(5) = '3' then -- SubSubClause is 30..39 if Clause_Name(6) > '5' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Subsubclause too large=" & Clause_Number); end if; Clause_Name(5) := Character'Val( Character'Pos(Clause_Name(7))-Character'Pos('0')+Character'Pos('A')+20); Clause_Name_Len := 5; else Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "MS-DOS filename: Subsubclause too large=" & Clause_Number); end if; end if; end if; return Clause_Name(1..Clause_Name_Len); end Make_Clause_Anchor_Name; function Make_Clause_File_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the Clause file name for the current output object and -- Clause_Number. This does not include any path or extension. begin if Output_Object.Big_Files then -- One big file. return Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right); else -- Clause files. if Output_Object.DOS_Filenames then return Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & Make_Clause_Anchor_Name (Output_Object, Clause_Number); else return Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-" & Make_Clause_Anchor_Name (Output_Object, Clause_Number); end if; end if; end Make_Clause_File_Name; function Make_Clause_Link_Name (Output_Object : in HTML_Output_Type; Clause_Number : in String) return String is -- Internal routine. -- Returns the link name for a link to the given clause. begin if Output_Object.Big_Files then -- One big file. -- Note this is a self-reference, so the file name is not needed. return "#" & Make_Clause_Anchor_Name (Output_Object, Clause_Number); else -- Clause files. if Output_Object.DOS_Filenames then return Make_Clause_File_Name (Output_Object, Clause_Number) & ".HTM"; else return Make_Clause_File_Name (Output_Object, Clause_Number) & ".html"; end if; end if; end Make_Clause_Link_Name; procedure Put_EMs (Fyle : in Ada.Text_IO.File_Type; Value : in Natural) is -- Put an EMs Value (Value is in 0.1 EM). begin if Value <= 9 then Ada.Text_IO.Put (Fyle, '0'); elsif Value <= 99 then Ada.Text_IO.Put (Fyle, Character'Val(Character'Pos('0') + (Value / 10))); else Ada.Text_IO.Put (Fyle, Natural'Image (Value / 10)); end if; Ada.Text_IO.Put (Fyle, '.'); Ada.Text_IO.Put (Fyle, Character'Val(Character'Pos('0') + (Value Mod 10))); Ada.Text_IO.Put (Fyle, "em"); end Put_EMs; procedure Make_Navigation_Bar (Output_Object : in out HTML_Output_Type; Is_Top : in Boolean) is -- Internal routine. -- Generate a properly formatted navigation bar. Clause : constant String := Ada.Strings.Unbounded.To_String(Output_Object.Current_Clause); begin if Output_Object.Use_Buttons then if Is_Top and then Output_Object.HTML_Kind > HTML_3 then Ada.Text_IO.Put (Output_Object.Output_File, "<div style=""margin-top: 0.6em; margin-bottom: 0.0em"">"); elsif (not Is_Top) and then Output_Object.HTML_Kind > HTML_3 then Ada.Text_IO.Put (Output_Object.Output_File, "<div style=""margin-top: 0.0em; margin-bottom: 0.6em"">"); else Ada.Text_IO.Put (Output_Object.Output_File, "<P>"); end if; Ada.Text_IO.Put (Output_Object.Output_File, "<A HREF="""); if Output_Object.Big_Files then Ada.Text_IO.Put (Output_Object.Output_File, "#TOC"); elsif Output_Object.DOS_Filenames then Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-TOC.HTM"); else Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-TOC.html"); end if; if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""CONT.GIF"" ALT=""Contents"" BORDER=0></A> "); -- Border=0 prevents the link highlight from being applied. else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""cont.gif"" ALT=""Contents"" BORDER=0></A> "); -- Border=0 prevents the link highlight from being applied. end if; if Ada.Strings.Unbounded.Length(Output_Object.Index_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, " <A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Index_URL)); if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""INDEX.GIF"" ALT=""Index"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""index.gif"" ALT=""Index"" BORDER=0></A> "); end if; else -- Link to the section named "Index". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Index" & (6 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""INDEX.GIF"" ALT=""Index"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Index" & (6 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""index.gif"" ALT=""Index"" BORDER=0></A> "); end if; exception when ARM_Contents.Not_Found_Error => null; -- No section named "Index". end; end if; if Ada.Strings.Unbounded.Length(Output_Object.Ref_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, " <A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Ref_URL)); if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""LIB.GIF"" ALT=""References"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""lib.gif"" ALT=""References"" BORDER=0></A> "); end if; else -- Link to the section named "References". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("References" & (11 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""LIB.GIF"" ALT=""References"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("References" & (11 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""lib.gif"" ALT=""References"" BORDER=0></A> "); end if; exception when ARM_Contents.Not_Found_Error => null; -- No section named "References". end; end if; if Ada.Strings.Unbounded.Length(Output_Object.Srch_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, " <A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Srch_URL)); if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""FIND.GIF"" ALT=""Search"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""find.gif"" ALT=""Search"" BORDER=0></A> "); end if; else -- Link to the section named "References". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Search" & (7 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""FIND.GIF"" ALT=""Search"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Search" & (7 .. ARM_Contents.Title_Type'Last => ' '))) & """><IMG SRC=""find.gif"" ALT=""Search"" BORDER=0></A> "); end if; exception when ARM_Contents.Not_Found_Error => null; -- No section named "Index". end; end if; if Clause /= "" then begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Previous_Clause(Clause))); if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""PREV.GIF"" ALT=""Previous"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""prev.gif"" ALT=""Previous"" BORDER=0></A> "); end if; exception when ARM_Contents.Not_Found_Error => null; -- Probably the first section. end; begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, " <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Next_Clause(Clause))); if Output_Object.DOS_Filenames then Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""NEXT.GIF"" ALT=""Next"" BORDER=0></A> "); else Ada.Text_IO.Put_Line (Output_Object.Output_File, """><IMG SRC=""next.gif"" ALT=""Next"" BORDER=0></A> "); end if; exception when ARM_Contents.Not_Found_Error => null; -- Probably the last section. end; end if; if Output_Object.HTML_Kind > HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "</div>"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, "</P>"); end if; else -- Use text navigation Ada.Text_IO.Put (Output_Object.Output_File, "<P><A HREF="""); if Output_Object.Big_Files then Ada.Text_IO.Put (Output_Object.Output_File, "#TOC"); elsif Output_Object.DOS_Filenames then Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-TOC.HTM"); else Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-TOC.html"); end if; Ada.Text_IO.Put (Output_Object.Output_File, """>Contents</A>"); if Ada.Strings.Unbounded.Length(Output_Object.Index_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "<A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Index_URL)); Ada.Text_IO.Put (Output_Object.Output_File, """>Index</A>"); else -- Link to the section named "Index". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put_Line (Output_Object.Output_File, "   <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Index" & (6 .. ARM_Contents.Title_Type'Last => ' '))) & """>Index</A>"); exception when ARM_Contents.Not_Found_Error => null; -- No section named "Index". end; end if; if Ada.Strings.Unbounded.Length(Output_Object.Srch_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "<A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Srch_URL)); Ada.Text_IO.Put (Output_Object.Output_File, """>Search</A>"); else -- Link to the section named "Search". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put_Line (Output_Object.Output_File, "   <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("Search" & (7 .. ARM_Contents.Title_Type'Last => ' '))) & """>Search</A>"); exception when ARM_Contents.Not_Found_Error => null; -- No section named "Search". end; end if; if Ada.Strings.Unbounded.Length(Output_Object.Ref_URL) /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "   "); Ada.Text_IO.Put (Output_Object.Output_File, "<A HREF="""); Ada.Text_IO.Put (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Ref_URL)); Ada.Text_IO.Put (Output_Object.Output_File, """>Reference Documents</A>"); else -- Link to the section named "References". begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put_Line (Output_Object.Output_File, "   <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Lookup_Clause_Number ("References" & (11 .. ARM_Contents.Title_Type'Last => ' '))) & """>Reference Documents</A>"); exception when ARM_Contents.Not_Found_Error => null; -- No section named "References". end; end if; if Clause /= "" then begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, "   <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Previous_Clause(Clause))); Ada.Text_IO.Put (Output_Object.Output_File, """>Previous</A>"); exception when ARM_Contents.Not_Found_Error => null; -- Probably the first section. end; begin -- Note: We do the following in one big glup so that if -- Not_Found_Error is raised, nothing is output. Ada.Text_IO.Put (Output_Object.Output_File, "   <A HREF=""" & Make_Clause_Link_Name (Output_Object, ARM_Contents.Next_Clause(Clause))); Ada.Text_IO.Put (Output_Object.Output_File, """>Next</A>"); exception when ARM_Contents.Not_Found_Error => null; -- Probably the last section. end; end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, "</P>"); end if; end Make_Navigation_Bar; type Special_Style_Kinds is (None, Hanging_Term, Hanging_Body, Bulleted_Item, Bulleted_No_Prefix); procedure Make_Style (Output_Object : in out HTML_Output_Type; Name : in String; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Kind : Special_Style_Kinds := None; Enumerated_Adjustment : in Boolean := False) is -- Internal routine. -- Generate the style needed. function Units_to_EMs (Value : in Natural) return Natural is -- Convert Value from indentation units to EMs. (0.1 EMs, really). Normal : Boolean; begin if Output_Object.HTML_Kind = HTML_4_Only then case Paragraph_Info(Style, Indent).Font is when ARM_Output.Default => Normal := ARM_Output."=" (Output_Object.Body_Font, ARM_Output.Roman); when ARM_Output.Roman => Normal := True; when ARM_Output.Fixed | ARM_Output.Swiss => -- Start at 90% (otherwise they are huge!) Normal := False; end case; if Normal then case Paragraph_Info(Style, Indent).Size is when 0 => return Value * 20; when 1 => return Value * 16; -- 20/1.25. when 2 => return Value * 13; -- 20/1.56. when 3 => return Value * 10; -- 20/1.93. when -1 => return Value * 25; -- 20/0.80. when -2 => return Value * 31; -- 20/0.64. when -3 => return Value * 40; -- 20/0.50. when others => return Value; -- Out of range. end case; else -- Start at 90% (otherwise they are huge!) case Paragraph_Info(Style, Indent).Size is when 0 => return Value * 22; -- 20/0.90 when 1 => return Value * 18; -- 20/1.13. when 2 => return Value * 14; -- 20/1.40. when 3 => return Value * 11; -- 20/1.75. when -1 => return Value * 28; -- 20/0.72. when -2 => return Value * 34; -- 20/0.58. when -3 => return Value * 44; -- 20/0.45. when others => return Value; -- Out of range. end case; end if; elsif ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed) then -- Special case, see below. case Paragraph_Info(Style, Indent).Size is when 0 => return Value * 20; when 1 => return Value * 16; -- 20/1.25. when 2 => return Value * 13; -- 20/1.56. when 3 => return Value * 10; -- 20/1.93. when -1 => return Value * 25; -- 20/0.80. when -2 => return Value * 31; -- 20/0.64. when -3 => return Value * 40; -- 20/0.50. when others => return Value; -- Out of range. end case; else return Value * 20; -- No font sizes here. end if; end Units_to_EMs; begin if not Paragraph_Used (Style, Indent) then return; -- Not used, so don't generate. end if; if Kind = Hanging_Term and then Output_Object.HTML_Kind = HTML_4_Only then -- Special case for better hanging. Ada.Text_IO.Put (Output_Object.Output_File, " DIV."); Ada.Text_IO.Put (Output_Object.Output_File, Name & "-Term {"); if OPTIMIZE_FOR_FIREFOX then -- Tested on Firefox 1.5. Ada.Text_IO.Put (Output_Object.Output_File, "float: left; "); -- This does not work on IE: it adds extra spaces, and leaves -- it effective after a <BR>. We could probably work around -- those, but then Firefox would look like crap again. else Ada.Text_IO.Put (Output_Object.Output_File, "position: absolute; top: auto; left: 0.6em; "); -- This does not work on Firefox: the text is too high by -- about half a line and thus doesn't line up properly. end if; elsif Kind = Hanging_Body and then Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put (Output_Object.Output_File, " DIV."); Ada.Text_IO.Put (Output_Object.Output_File, Name & "-Body {"); elsif (Kind = Bulleted_Item or else Kind = Bulleted_No_Prefix) and then Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put (Output_Object.Output_File, " DIV."); Ada.Text_IO.Put (Output_Object.Output_File, Name & " {"); else case Paragraph_Info(Style, Indent).Tag is when DIV => Ada.Text_IO.Put (Output_Object.Output_File, " DIV."); when UL => Ada.Text_IO.Put (Output_Object.Output_File, " UL."); when DL => Ada.Text_IO.Put (Output_Object.Output_File, " DL."); end case; Ada.Text_IO.Put (Output_Object.Output_File, Name & " {"); end if; case Paragraph_Info(Style, Indent).Font is when ARM_Output.Default => if ARM_Output."=" (Output_Object.Body_Font, ARM_Output.Roman) then Ada.Text_IO.Put (Output_Object.Output_File, "font-family: ""Times New Roman"", Times, serif"); else Ada.Text_IO.Put (Output_Object.Output_File, "font-family: Arial, Helvetica, sans-serif"); end if; when ARM_Output.Roman => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: ""Times New Roman"", Times, serif"); when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: Arial, Helvetica, sans-serif"); when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, "font-family: ""Courier New"", monospace"); end case; if Output_Object.HTML_Kind = HTML_4_Only then -- The font size is set by the outer item. declare Normal : Boolean; begin case Paragraph_Info(Style, Indent).Font is when ARM_Output.Default => Normal := ARM_Output."=" (Output_Object.Body_Font, ARM_Output.Roman); when ARM_Output.Roman => Normal := True; when ARM_Output.Fixed | ARM_Output.Swiss => -- Start at 90% (otherwise they are huge!) Normal := False; end case; if Normal then case Paragraph_Info(Style, Indent).Size is when 0 => null; -- Default. when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 125%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 156%"); when 3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 195%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 80%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 64%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 50%"); when others => null; -- Out of range. end case; else -- Start at 90% (otherwise they are huge!) -- Note: This size adjustment is for sections of text, not for in-line text. case Paragraph_Info(Style, Indent).Size is when 0 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 90%"); when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 113%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 140%"); when 3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 175%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 72%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 58%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 45%"); when others => null; -- Out of range. end case; end if; end; -- Set the leading, because otherwise the lines are too close on IE. Ada.Text_IO.Put (Output_Object.Output_File, "; line-height: 122%"); elsif ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed) then -- Special case because the font otherwise gets too small and -- loses bold-facing. case Paragraph_Info(Style, Indent).Size is when 0 => null; -- Default. when 1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 125%"); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 156%"); when 3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 195%"); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 80%"); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 64%"); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, "; font-size: 50%"); when others => null; -- Out of range. end case; -- else the size will be set explicitly for HTML_4_Compatible. end if; if Kind = Hanging_Body then if Output_Object.Number_Paragraphs then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Style, Indent).Indent + Paragraph_Info(Style, Indent).Hang_Outdent) + INDENT_EMS_FOR_PARANUMS); else if Paragraph_Info(Style, Indent).Indent + Paragraph_Info(Style, Indent).Hang_Outdent /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Style, Indent).Indent + Paragraph_Info(Style, Indent).Hang_Outdent)); end if; end if; elsif Enumerated_Adjustment then -- Adjust the left margin to indent the prefix slightly (1/4 of a unit): declare Org_Margin : Natural := Units_to_EMs(Paragraph_Info(Style, Indent).Indent); Prefix_Indent : Natural := Units_to_EMs(1) / 4; begin Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); if Output_Object.Number_Paragraphs then Put_Ems (Output_Object.Output_File, Org_Margin + Prefix_Indent + INDENT_EMS_FOR_PARANUMS); else Put_Ems (Output_Object.Output_File, Org_Margin + Prefix_Indent); end if; end; else if Output_Object.Number_Paragraphs then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Style, Indent).Indent) + INDENT_EMS_FOR_PARANUMS); else if Paragraph_Info(Style, Indent).Indent /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-left: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Style, Indent).Indent)); end if; end if; end if; if Kind = Hanging_Term and then Output_Object.HTML_Kind = HTML_4_Only then -- We let the body provide the necessary right margin. If we don't -- do this, the following item can end up with an inappropriate indent. null; --Ada.Text_IO.Put (Output_Object.Output_File, "; margin-bottom: 0em"); elsif Paragraph_Info(Style, Indent).Right_Indent /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-right: "); Put_Ems (Output_Object.Output_File, Units_to_EMs(Paragraph_Info(Style, Indent).Right_Indent)); end if; if Paragraph_Info(Style, Indent).Before /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-top: "); Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Before); elsif Paragraph_Info(Style, Indent).Tag /= DIV then -- The default is non-zero. Ada.Text_IO.Put (Output_Object.Output_File, "; margin-top: 0em"); end if; if Kind = Hanging_Term and then Output_Object.HTML_Kind = HTML_4_Only then -- We let the body provide the necessary space below. If we don't -- do this, the next line can end up with an inappropriate indent. Ada.Text_IO.Put (Output_Object.Output_File, "; margin-bottom: 0em"); elsif Paragraph_Info(Style, Indent).After /= 0 then Ada.Text_IO.Put (Output_Object.Output_File, "; margin-bottom: "); Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).After); end if; if Kind = Bulleted_Item and then Output_Object.HTML_Kind = HTML_4_Only then -- Set the list item and "disc" format: Ada.Text_IO.Put (Output_Object.Output_File, "; display: list-item; list-style-type: disc"); end if; -- Done, close it. Ada.Text_IO.Put_Line (Output_Object.Output_File, "}"); end Make_Style; procedure Make_Hung_Text_Style (Output_Object : in out HTML_Output_Type; Name : in String; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type) is -- Internal routine. -- Generate the style needed. begin if Output_Object.HTML_Kind = HTML_4_Only then if ARM_Output."=" (Style, ARM_Output.Enumerated) or else ARM_Output."=" (Style, ARM_Output.Small_Enumerated) then Make_Style (Output_Object, Name, Style, Indent, Kind => Hanging_Term, Enumerated_Adjustment => True); else Make_Style (Output_Object, Name, Style, Indent, Kind => Hanging_Term); end if; else -- HTML_4_Compatible Ada.Text_IO.Put (Output_Object.Output_File, " DD." & Name & " {"); Ada.Text_IO.Put (Output_Object.Output_File, "margin-left: "); case Paragraph_Info(Style, Indent).Size is when 0 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 20); when 1 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 16); -- 20/1.25. when 2 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 13); -- 20/1.56. when -1 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 25); -- 20/0.80. when -2 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 31); -- 20/0.64. when -3 => Put_Ems (Output_Object.Output_File, Paragraph_Info(Style, Indent).Hang_Outdent * 40); -- 20/0.50. when others => null; -- Out of range. end case; -- Done, close it. Ada.Text_IO.Put_Line (Output_Object.Output_File, "}"); end if; end Make_Hung_Text_Style; function Paragraph_Name (Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type) return String is -- Internal routine. -- Create the name for the Style and Indent. -- These had better be unique, and all possibilities (including impossible -- ones) had better have names. use type ARM_Output.Paragraph_Indent_Type; begin case Style is when ARM_Output.Normal => if Indent = 0 then return "Normal"; else -- This was: Indent 1: "SyntaxIndented"; Indent 2: -- "CodeIndented"; Indent 3: "Indented"; Indent 4: "InnerIndented". return "Indented" & Character'Val(Character'Pos('0') + Indent); end if; when ARM_Output.Wide_Above => if Indent = 0 then return "WideAbove"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "WideAbove"; end if; when ARM_Output.Small => if Indent = 0 then return "Small"; elsif Indent = 1 then return "Notes"; elsif Indent = 2 then return "Annotations"; else -- This was: Indent 3: "SmallSyntaxIndented"; Indent 4: -- "SmallCodeIndented"; Indent 5: "SmallIndented"; Indent 6: "SmallInnerIndented". return "SmallIndented" & Character'Val(Character'Pos('0') + Indent); end if; when ARM_Output.Small_Wide_Above => if Indent = 0 then return "SmallWideAbove"; elsif Indent = 2 then return "AnnotationsWideAbove"; else return "SmallIndented" & Character'Val(Character'Pos('0') + Indent) & "WideAbove"; end if; when ARM_Output.Header => if Indent = 0 then return "Header"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "Header"; end if; when ARM_Output.Small_Header => if Indent = 0 then return "SmallHeader"; elsif Indent = 1 then return "NotesHeader"; else return "SmallIndented" & Character'Val(Character'Pos('0') + Indent) & "Header"; end if; when ARM_Output.Index => if Indent = 0 then return "Index"; else -- Should be not used. return "IndexIndented" & Character'Val(Character'Pos('0') + Indent); end if; when ARM_Output.Syntax_Summary => if Indent = 1 then return "SyntaxSummary"; else -- Should be not used. return "SynSumInd" & Character'Val(Character'Pos('0') + Indent); end if; when ARM_Output.Title => if Indent = 0 then return "Title"; else -- Should be not used. return "TitleIndented" & Character'Val(Character'Pos('0') + Indent); end if; when ARM_Output.Examples => if Indent = 1 then return "Examples"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "Examples"; end if; when ARM_Output.Small_Examples => if Indent = 3 then return "SmallExamples"; else return "SmallIndented" & Character'Val(Character'Pos('0') + Indent) & "Examples"; end if; when ARM_Output.Swiss_Examples => if Indent = 1 then return "SwissExamples"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SwissExamples"; end if; when ARM_Output.Small_Swiss_Examples => if Indent = 3 then return "SmallSwissExamples"; else return "SmallIndented" & Character'Val(Character'Pos('0') + Indent) & "SwissExamples"; end if; when ARM_Output.Bulleted => if Indent = 1 then return "Bulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "Bulleted"; end if; when ARM_Output.Small_Bulleted => if Indent = 3 then return "SmallBulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallBulleted"; end if; when ARM_Output.Nested_Bulleted => if Indent = 1 then return "NestedBulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "NestedBulleted"; end if; when ARM_Output.Small_Nested_Bulleted => if Indent = 3 then return "SmallNestedBulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallNestedBulleted"; end if; when ARM_Output.Enumerated => if Indent = 1 then return "Enumerated"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "Enumerated"; end if; when ARM_Output.Small_Enumerated => if Indent = 3 then return "SmallEnumerated"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallEnumerated"; end if; when ARM_Output.Giant_Hanging => if Indent = 4 then return "GiantHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "GiantHanging"; end if; when ARM_Output.Small_Giant_Hanging => if Indent = 6 then return "SmallGiantHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallGiantHanging"; end if; when ARM_Output.Wide_Hanging => if Indent = 3 then return "WideHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "WideHanging"; end if; when ARM_Output.Small_Wide_Hanging => if Indent = 5 then return "SmallWideHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallWideHanging"; end if; when ARM_Output.Medium_Hanging => if Indent = 2 then return "MediumHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "MediumHanging"; end if; when ARM_Output.Small_Medium_Hanging => if Indent = 4 then return "SmallMediumHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallMediumHanging"; end if; when ARM_Output.Narrow_Hanging => if Indent = 1 then return "NarrowHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "NarrowHanging"; end if; when ARM_Output.Small_Narrow_Hanging => if Indent = 3 then return "SmallNarrowHanging"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallNarrowHanging"; end if; when ARM_Output.Hanging_in_Bulleted => if Indent = 3 then return "Hanging_in_Bulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "Hanging_in_Bulleted"; end if; when ARM_Output.Small_Hanging_in_Bulleted => if Indent = 5 then return "SmallHanging_in_Bulleted"; else return "Indented" & Character'Val(Character'Pos('0') + Indent) & "SmallHanging_in_Bulleted"; end if; end case; end Paragraph_Name; procedure Make_Paragraph_Styles (Output_Object : in out HTML_Output_Type) is -- Internal routine. -- Generate all of the paragraph and related styles. begin -- Basic element styles: if Paranum_Used then if Output_Object.HTML_Kind = HTML_4_Compatible then if OPTIMIZE_FOR_FIREFOX then Ada.Text_IO.Put_Line (Output_Object.Output_File, " DIV.paranum {float: left; font-family: Arial, Helvetica, sans-serif; width: 2.8em; " & "margin-left: -0.4em; margin-right: -3.0em; margin-top: 0.2em}"); -- Uses floating items. These usually don't work on IE (it -- adds extra spaces for no reason). However, with the -- indents, this seems to work properly on IE, too. else -- Absolute positioning (CSS2) works better on IE, but -- Firefox tends to draw these too high. Ada.Text_IO.Put_Line (Output_Object.Output_File, " DIV.paranum {position: absolute; font-family: Arial, Helvetica, sans-serif; left: 0.5em; top: auto; margin-top: 0.2em}"); end if; -- If these are completely ignored, the paragraph number will -- end up on a line by itself. That's fine. else if OPTIMIZE_FOR_FIREFOX then Ada.Text_IO.Put_Line (Output_Object.Output_File, " DIV.paranum {float: left; font-family: Arial, Helvetica, sans-serif; font-size: 64%; width: 2.8em; " & "margin-left: -0.4em; margin-right: -3.0em; margin-top: 0.2em}"); -- Uses floating elements; see above. else Ada.Text_IO.Put_Line (Output_Object.Output_File, " DIV.paranum {position: absolute; font-family: Arial, Helvetica, sans-serif; font-size: 64%; " & "left: 0.5em; top: auto; margin-top: 0.2em}"); -- Uses absolute positioning; see above. end if; end if; end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, " TT {font-family: ""Courier New"", monospace}"); Ada.Text_IO.Put_Line (Output_Object.Output_File, " DT {display: compact}"); -- CSS2. This doesn't seem to work on IE 4.01, but it is harmless. -- Revision styles: if Revision_Used ('0') then Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.insert0 {text-decoration: underline; color: black}"); Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.delete0 {text-decoration: line-through; color: black }"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.both0 {text-decoration: underline, line-through; color: black }"); -- Both doesn't seem to work, so forget it. -- else not used, don't generate it. end if; if Revision_Used ('1') then Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.insert1 {text-decoration: underline; color: rgb(0,51,51) }"); -- Dark turquoise. Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.delete1 {text-decoration: line-through; color: rgb(0,51,51) }"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.both1 {text-decoration: underline, line-through; color: rgb(0,51,51) }"); -- Both doesn't seem to work, so forget it. -- else not used, don't generate it. end if; if Revision_Used ('2') then Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.insert2 {text-decoration: underline; color: rgb(0,102,0) }"); -- Dark green. Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.delete2 {text-decoration: line-through; color: rgb(0,102,0) }"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.both2 {text-decoration: underline, line-through; color: rgb(0,102,0) }"); -- Both doesn't seem to work, so forget it. -- else not used, don't generate it. end if; if Revision_Used ('3') then Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.insert3 {text-decoration: underline; color: rgb(102,51,0) }"); -- Dark brown. Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.delete3 {text-decoration: line-through; color: rgb(102,51,0) }"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.both3 {text-decoration: underline, line-through; color: rgb(102,51,0) }"); -- Both doesn't seem to work, so forget it. -- else not used, don't generate it. end if; if Revision_Used ('4') then Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.insert4 {text-decoration: underline; color: rgb(153,0,0) }"); -- Dark red. Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.delete4 {text-decoration: line-through; color: rgb(153,0,0) }"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " SPAN.both4 {text-decoration: underline, line-through; color: rgb(153,0,0) }"); -- Both doesn't seem to work, so forget it. -- else not used, don't generate it. end if; -- Link styles: -- We don't need these (they're given in the BODY command), but I've -- kept them in case we want to change these in the future. --Ada.Text_IO.Put_Line (Output_Object.Output_File, " A:link {color: rgb(0,0,255)}"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, " A:visited {color: rgb(128,0,128)}"); -- Paragraph styles: for S in ARM_Output.Unprefixed_Style_Subtype loop for I in ARM_Output.Paragraph_Indent_Type loop Make_Style (Output_Object, Paragraph_Name (S, I), S, I); end loop; end loop; for S in ARM_Output.Bullet_Prefixed_Style_Subtype loop -- These styles do not allow Indent 0. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop if Output_Object.HTML_Kind = HTML_4_Only then Make_Style (Output_Object, Paragraph_Name (S, I) & "-NoPrefix", S, I, Kind => Bulleted_No_Prefix); Make_Style (Output_Object, Paragraph_Name (S, I), S, I, Kind => Bulleted_Item); else Make_Style (Output_Object, Paragraph_Name (S, I), S, I); end if; end loop; end loop; for S in ARM_Output.Text_Prefixed_Style_Subtype loop -- These styles do not allow Indent 0. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop if Paragraph_Used (S, I) then Make_Style (Output_Object, Paragraph_Name (S, I), S, I, Kind => Hanging_Body); Make_Hung_Text_Style (Output_Object, Paragraph_Name (S, I), S, I); -- else not used. end if; end loop; end loop; end Make_Paragraph_Styles; MAGIC_STYLE_MARKER : constant String := "&%$# STYLES GO HERE #$%&"; procedure Start_HTML_File (Output_Object : in out HTML_Output_Type; File_Name : in String; Title : in String; Clause : in String) is -- Internal routine. -- Create an HTML file, and generate the needed text to start an HTML -- file. The file name is just the name portion, not the path or -- extension. Clause is the properly formatted Clause number for -- this file, if known. begin --Ada.Text_IO.Put_Line ("--Creating " & File_Name & ".html"); if Output_Object.HTML_Kind > HTML_3 then Ada.Text_IO.Create (Output_Object.Output_File, Ada.Text_IO.Out_File, Ada.Strings.Unbounded.To_String (Output_Object.Output_Path) & File_Name & ".$$$"); elsif Output_Object.DOS_Filenames then Ada.Text_IO.Create (Output_Object.Output_File, Ada.Text_IO.Out_File, Ada.Strings.Unbounded.To_String (Output_Object.Output_Path) & File_Name & ".HTM"); else Ada.Text_IO.Create (Output_Object.Output_File, Ada.Text_IO.Out_File, Ada.Strings.Unbounded.To_String (Output_Object.Output_Path) & File_Name & ".html"); end if; -- Save the current clause: Output_Object.Current_Clause := Ada.Strings.Unbounded.To_Unbounded_String(Clause); -- File introduction: if Output_Object.HTML_Kind > HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.01 Transitional//EN"""); Ada.Text_IO.Put_Line (Output_Object.Output_File, """http://www.w3.org/TR/html4/loose.dtd"">"); -- HTML 4.01 (with depreciated features) else Ada.Text_IO.Put_Line (Output_Object.Output_File, "<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 3.2//EN"">"); -- HTML 3.2 end if; -- so the result can be used on version 3 browsers.) Ada.Text_IO.Put_Line (Output_Object.Output_File, "<HTML>"); -- Header information: Ada.Text_IO.Put_Line (Output_Object.Output_File, "<HEAD>"); Ada.Text_IO.Put_Line (Output_Object.Output_File, " <TITLE>" & Title & ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); if Output_Object.HTML_Kind = HTML_4_Only then -- The style sheet. Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); elsif Output_Object.HTML_Kind = HTML_4_Compatible then -- The style sheet. Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); end if; if Ada.Strings.Unbounded.Length(Output_Object.Script_HTML) /= 0 then Ada.Text_IO.Put_Line (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Script_HTML)); end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); if Ada.Strings.Unbounded.Length(Output_Object.Header_HTML) /= 0 then Ada.Text_IO.Put_Line (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Header_HTML)); end if; if Output_Object.Nav_on_Top then Make_Navigation_Bar (Output_Object, Is_Top => True); -- else no navigation bar end if; if Output_Object.Nav_on_Top or else Ada.Strings.Unbounded.Length(Output_Object.Header_HTML) /= 0 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line (rule). -- else nothing on top at all. end if; end Start_HTML_File; procedure End_HTML_File (Output_Object : in out HTML_Output_Type) is -- Internal routine. -- Generate the needed text to end an HTML file. Also closes the file. begin Ada.Text_IO.New_Line (Output_Object.Output_File); -- Blank line to set off paragraphs. if Output_Object.Nav_on_Bottom or else Ada.Strings.Unbounded.Length(Output_Object.Footer_HTML) /= 0 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line (rule). -- else nothing on top at all. end if; if Output_Object.Nav_on_Bottom then Make_Navigation_Bar (Output_Object, Is_Top => False); -- else no navigation bar. end if; if Ada.Strings.Unbounded.Length(Output_Object.Footer_HTML) /= 0 then Ada.Text_IO.Put_Line (Output_Object.Output_File, Ada.Strings.Unbounded.To_String(Output_Object.Footer_HTML)); end if; Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); if Output_Object.HTML_Kind <= HTML_3 then Ada.Text_IO.Close (Output_Object.Output_File); else -- Close and reread the file to add JUST the styles used by the -- file; this decreases the minimum size of the files (by as -- much as 7K as of this writing [1/2006]), which matters when -- there are hundreds. -- We also check spaces before end tags and after opening tags; -- these should be  . (See 9.1 in HTML 4.0: "In order to -- avoid problems with SGML line break rules and inconsistencies -- among extant implementations, authors should not rely on user -- agents to render white space immediately after a start tag or -- immediately before an end tag.") We haven't seen a problem -- with this, but why ask for trouble? -- Note that we assume that all occurrences of "<" and ">" in -- the literal text are written as "<" and ">"; violations -- might cause the conversion of spaces to non-breaking spaces, -- which should not cause problems in general. We also assume that -- all end tags are on one line (they are all very short), so -- any ">" is the end of a start tag unless there is a " " then -- Candidate; check that this isn't an end tag. for I in reverse 1..Loc-1 loop if Buffer(I) = '/' then -- End tag, nothing to do. Loc := Loc + 2; exit; elsif Buffer(I) = '<' or else I = 1 then -- Start tag (including reaching the -- start of the line), replace. Buffer(Loc+7..Len+5) := Buffer(Loc+2..Len); Buffer(Loc+1..Loc+6) := " "; Len := Len+5; Loc := Loc + 7; -- If these is the *last* character on the -- line, we have to "unbreak" the line, else we'd get an extra space. if Loc > Len then Ada.Text_IO.Put (Output_Object.Output_File, Buffer(1..Len)); goto Skip_Write; end if; exit; -- else continue. end if; end loop; else Loc := Loc + 1; end if; end loop; Ada.Text_IO.Put_Line (Output_Object.Output_File, Buffer(1..Len)); <> null; end if; end loop; exception when Ada.Text_IO.End_Error => null; -- Done copying. end; Ada.Text_IO.Close (Output_Object.Output_File); Ada.Text_IO.Delete (Reading_File); -- This was temporary. end; end if; end End_HTML_File; procedure Create (Output_Object : in out HTML_Output_Type; Big_Files : in Boolean; File_Prefix : in String; Output_Path : in String; DOS_Filenames : in Boolean; HTML_Kind : in HTML_Type; Use_Unicode : in Boolean; Number_Paragraphs : in Boolean; Ref_URL : in String; Srch_URL : in String; Index_URL : in String; Use_Buttons : Boolean; Nav_On_Top : Boolean; Nav_On_Bottom : Boolean; Tab_Emulation : Tab_Emulation_Type; Script_HTML : String; Header_HTML : String; Footer_HTML : String; Title : in String := ""; Body_Font : ARM_Output.Font_Family_Type; Text_Color : Color_String; Background_Color : Color_String; Link_Color : Color_String; VLink_Color : Color_String; ALink_Color : Color_String) is -- Create an Output_Object for a document. -- Generate a few large output files if -- Big_Files is True; otherwise generate smaller output files. -- The prefix of the output file names is File_Prefix - this -- should be no more than 5 characters allowed in file names. -- The files will be written into Output_Path. -- If DOS_Filename is true, use 8.3 file names; -- in that case, File_Prefix must be less than 4 characters in length; -- and no clause or subclause number may exceed 35 if Big_Files is False. -- The title of the document is Title. -- HTML_Kind determines the kind of HTML generated; HTML_3 works on -- every browser but has little control over formatting; -- HTML_4_Compatible has better control, but tries to make the results -- look good on older browsers; HTML_4_Only uses maximum formatting, -- but makes no attempt to look good on browsers older than IE 5.0 and -- Firefox 1.0. -- If Use_Unicode is true, Unicode characters available on US versions -- of Windows 2000 are used when appropriate; otherwise, Unicode -- characters are only used when explicitly requested with -- Unicode_Character (other characters are replaced with reasonable -- equivalents). [Note: It's known that IE on Windows 95/98/ME cannot -- display Unicode characters.] Use_Unicode has no effect if HTML_Kind -- is set to HTML_3. -- Number_Paragraphs means that paragraph numbers will be used; -- otherwise, the Number parameter to Start_Paragraph must be "". -- Ref_URL, Srch_URL, and Index_URL are the URLs (possibly relative) -- for the "References", "Search", and "Index" buttons/labels, -- respectively. If null, these buttons/labels link to sections named -- "References", "Search", and "Index"; if these do not exist, the -- buttons/labels are omitted. -- If Use_Buttons is true, button images are used, otherwise text labels -- are used for the navigation bar. -- If Nav_On_Top is true, the navigation bar will appear in the header -- of each page. If Nav_On_Bottom is true, the navigation bar will -- appear in the footer of each page. -- Tab_Emulation determines how tabs are emulated. -- Script_HTML gives self-contained HTML that will appear immediately -- before the of every page. This usually will contain -- Javascript scripts or CSS styles. The original intent was to allow -- adding the Google Analytics script to each page. -- Header_HTML gives self-contained HTML that will appear before the -- navigation bar in the header. Footer_HTML gives self-contained HTML -- that will appear after the navigation bar in the footer. -- Body_Font selects the default font for the document body. -- Text_Color specifies the default text color; Background_Color -- specifies the default background color; Link_Color specifies the -- default color of normal links; VLink_Color specifies the -- default color of visited links; and ALink_Color specifies the -- default color of active (in the act of clinking) links. begin if Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already valid object"); end if; Output_Object.Is_Valid := True; Ada.Strings.Fixed.Move (Target => Output_Object.File_Prefix, Source => File_Prefix); Output_Object.Title := Ada.Strings.Unbounded.To_Unbounded_String (Title); Output_Object.Big_Files := Big_Files; Output_Object.Output_Path := Ada.Strings.Unbounded.To_Unbounded_String(Output_Path); Output_Object.DOS_Filenames := DOS_Filenames; Output_Object.HTML_Kind := HTML_Kind; Output_Object.Use_Unicode := Use_Unicode; Output_Object.Number_Paragraphs := Number_Paragraphs; Output_Object.Ref_URL := Ada.Strings.Unbounded.To_Unbounded_String(Ref_URL); Output_Object.Srch_URL := Ada.Strings.Unbounded.To_Unbounded_String(Srch_URL); Output_Object.Index_URL := Ada.Strings.Unbounded.To_Unbounded_String(Index_URL); Output_Object.Use_Buttons := Use_Buttons; Output_Object.Nav_on_Top := Nav_on_Top; Output_Object.Nav_on_Bottom := Nav_on_Bottom; Output_Object.Tab_Emulation := Tab_Emulation; Output_Object.Script_HTML := Ada.Strings.Unbounded.To_Unbounded_String(Script_HTML); Output_Object.Header_HTML := Ada.Strings.Unbounded.To_Unbounded_String(Header_HTML); Output_Object.Footer_HTML := Ada.Strings.Unbounded.To_Unbounded_String(Footer_HTML); Output_Object.Body_Font := Body_Font; Output_Object.Text_Color := Text_Color; Output_Object.Background_Color := Background_Color; Output_Object.Link_Color := Link_Color; Output_Object.VLink_Color := VLink_Color; Output_Object.ALink_Color := ALink_Color; if DOS_Filenames then if File_Prefix'Length > 3 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "HTML File Prefix too long - MS-DOS mode"); end if; else if File_Prefix'Length > 5 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "HTML File Prefix too long"); end if; end if; if Output_Object.Big_Files then Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right), Ada.Strings.Unbounded.To_String (Output_Object.Title), Clause => ""); -- Insert an anchor for the title page: Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); end if; end Create; procedure Close (Output_Object : in out HTML_Output_Type) is -- Close an Output_Object. No further output to the object is -- allowed after this call. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Ada.Text_IO.Is_Open (Output_Object.Output_File) then End_HTML_File (Output_Object); end if; Output_Object.Is_Valid := False; end Close; procedure Section (Output_Object : in out HTML_Output_Type; Section_Title : in String; Section_Name : in String) is -- Start a new section. The title is Section_Title (this is -- intended for humans). The name is Section_Name (this is -- intended to be suitable to be a portion of a file name). begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Section in paragraph"); end if; -- We don't generate a file here for HTML. We generate a file for each -- clause. if Section_Name'Length > 3 then Output_Object.Section_Name := Section_Name (Section_Name'First .. Section_Name'First + 2); else Output_Object.Section_Name := (others => '-'); Output_Object.Section_Name (1 .. Section_Name'Length) := Section_Name; end if; end Section; procedure Set_Columns (Output_Object : in out HTML_Output_Type; Number_of_Columns : in ARM_Output.Column_Count) is -- Set the number of columns. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; if Number_of_Columns >= 4 then -- We have special processing for 4 or more columns. Note that we -- assume do not contain any nested paragraph formats. Output_Object.Current_Column := 1; Output_Object.Current_Item := 1; elsif Output_Object.Column_Count >= 4 and then Number_of_Columns = 1 then -- Finished processing columns, output the columns as a table. if Output_Object.Current_Column = 1 then -- No New_Column calls; break this into columns ourselves. -- Current_Item represents the total number of items + 2 -- (there is a double count for the end of the paragraph). declare Col_Count : Natural := Output_Object.Current_Item - 2; Where : Column_Text_Ptr; begin Col_Count := (Col_Count + Output_Object.Column_Count - 1) / Output_Object.Column_Count; Ada.Text_IO.Put_Line(" @@ Calc columns for" & Natural'Image(Output_Object.Column_Count) & " columns;" & Natural'Image(Output_Object.Current_Item - 1) & " total items;" & Natural'Image(Col_Count) & " per column."); -- Split the item list into the appropriate columns. -- Note that this list is stored in reverse order. for I in reverse 2 .. Output_Object.Column_Count loop --Ada.Text_IO.Put_Line(" @@ For column" & Natural'Image(I) & " split at item" & --Natural'Image(Col_Count*(I-1))); Where := Output_Object.Column_Text(1); exit when Where = null; -- No columns to look at. if Where.Item <= Col_Count*(I-1) then -- This column is empty. null; else Output_Object.Column_Text(I) := Where; while Where.Next /= null and then Where.Next.Item > Col_Count*(I-1) loop Where.Item := Where.Item - Col_Count*(I-1); Where := Where.Next; end loop; if Where = null then Output_Object.Column_Text(1) := null; else Output_Object.Column_Text(1) := Where.Next; Where.Next := null; --Ada.Text_IO.Put_Line(" split item=" & Natural'Image(Where.Item)); Where.Item := Where.Item - Col_Count*(I-1); end if; end if; end loop; end; --else there were explicit New_Column calls; no need to --do anything here. end if; if Output_Object.HTML_Kind = HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
      "); -- Table with no border or caption, takes up 70% of the screen. else Ada.Text_IO.Put_Line (Output_Object.Output_File, "
      "); -- Table with no border or caption, takes up 70% of the screen. Paragraph_Used(ARM_Output.Normal, 2) := True; end if; -- And start the first row: Ada.Text_IO.Put (Output_Object.Output_File, "
      "); for Item in 1 .. 5000 loop for Col in 1 .. Output_Object.Column_Count loop declare Find : Column_Text_Ptr := Output_Object.Column_Text(Col); Temp : Column_Text_Ptr; begin -- We're going to free this item after outputting it. if Find = null then null; elsif Find.Next = null then if Find.Item /= Item then Find := null; else Output_Object.Column_Text(Col) := null; end if; else while Find.Next /= null and then Find.Next.Item /= Item loop Find := Find.Next; end loop; Temp := Find; Find := Find.Next; Temp.Next := null; end if; if Find /= null then Ada.Text_IO.Put (Output_Object.Output_File, Find.Text (1 .. Find.Length)); -- This should always be the last item: if Find.Next /= null then Ada.Text_IO.Put_Line ("** Column Item invariant failure!"); end if; Free (Find); else -- No item, make a blank. Ada.Text_IO.Put (Output_Object.Output_File, " "); end if; end; Ada.Text_IO.Put (Output_Object.Output_File, ""); end loop; if Output_Object.Column_Text = Column_Text_Ptrs_Type'(others => null) then -- We've output everything. Ada.Text_IO.New_Line (Output_Object.Output_File); if Output_Object.HTML_Kind = HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); end if; exit; end if; -- End the row: Ada.Text_IO.New_Line (Output_Object.Output_File); Ada.Text_IO.Put (Output_Object.Output_File, ""); end loop; Output_Object.Current_Column := 0; Output_Object.Current_Item := 0; -- else Two and Three column formats are displayed without any columns. -- This is mainly used for the syntax cross-reference and index, and -- these definitely look better without columns. end if; Output_Object.Column_Count := Number_of_Columns; end Set_Columns; procedure Check_Clause_File (Output_Object : in out HTML_Output_Type) is -- Check that a Clause file has been made for this clause; if not, -- create one. begin if not Ada.Text_IO.Is_Open (Output_Object.Output_File) then if (not Output_Object.Big_Files) and then Output_Object.DOS_Filenames and then Output_Object.Section_Name(1) = '-' then Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & Make_Clause_Anchor_Name (Output_Object, Output_Object.Section_Name(2..3)), "", Clause => ""); else Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-" & Output_Object.Section_Name, "", Clause => ""); end if; end if; end Check_Clause_File; procedure Put_Compatibility_Font_Info (Output_Object : in out HTML_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type) is -- Internal: -- Output the font information for HTML 4.0 compatibility mode. begin if Output_Object.HTML_Kind = HTML_4_Compatible then case Paragraph_Info(Style, Indent).Font is when ARM_Output.Default => if ARM_Output."=" (Output_Object.Body_Font, ARM_Output.Swiss) then Ada.Text_IO.Put (Output_Object.Output_File, SWISS_FONT_CODE); Output_Object.Char_Count := Output_Object.Char_Count + SWISS_FONT_CODE'Length; -- else nothing for Roman. end if; when ARM_Output.Roman => null; when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, SWISS_FONT_CODE); Output_Object.Char_Count := Output_Object.Char_Count + SWISS_FONT_CODE'Length; when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 4; end case; if ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed) then null; -- No font change here. else case Paragraph_Info(Style, Indent).Size is when 0 => null; when 1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when 2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when 3 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when -3 => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; when others => null; -- Not supported. end case; end if; end if; end Put_Compatibility_Font_Info; procedure Put_End_Compatibility_Font_Info (Output_Object : in out HTML_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type) is -- Internal: -- Output the font information for HTML 4.0 compatibility mode. begin if Output_Object.HTML_Kind = HTML_4_Compatible then if ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed) then null; -- No font change here. else case Paragraph_Info(Style, Indent).Size is when 0 => null; when 1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when 2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -1 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -2 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when -3 => Ada.Text_IO.Put (Output_Object.Output_File, ""); when others => null; -- Not supported. end case; end if; case Paragraph_Info(Style, Indent).Font is when ARM_Output.Default => if ARM_Output."=" (Output_Object.Body_Font, ARM_Output.Swiss) then Ada.Text_IO.Put (Output_Object.Output_File, ""); -- else nothing for Roman. end if; when ARM_Output.Roman => null; when ARM_Output.Swiss => Ada.Text_IO.Put (Output_Object.Output_File, ""); when ARM_Output.Fixed => Ada.Text_IO.Put (Output_Object.Output_File, ""); end case; end if; end Put_End_Compatibility_Font_Info; procedure Start_Paragraph (Output_Object : in out HTML_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Number : in String; No_Prefix : in Boolean := False; Tab_Stops : in ARM_Output.Tab_Info := ARM_Output.NO_TABS; No_Breaks : in Boolean := False; Keep_with_Next : in Boolean := False; Space_After : in ARM_Output.Space_After_Type := ARM_Output.Normal; Justification : in ARM_Output.Justification_Type := ARM_Output.Default) is -- Start a new paragraph. The style and indent of the paragraph is as -- specified. The (AA)RM paragraph number (which might include update -- and version numbers as well: [12.1/1]) is Number. If the format is -- a type with a prefix (bullets, hangining items), the prefix is -- omitted if No_Prefix is true. Tab_Stops defines the tab stops for -- the paragraph. If No_Breaks is True, we will try to avoid page breaks -- in the paragraph. If Keep_with_Next is true, we will try to avoid -- separating this paragraph and the next one. (These may have no -- effect in formats that don't have page breaks). Space_After -- specifies the amount of space following the paragraph. Justification -- specifies the text justification for the paragraph. Not_Valid_Error -- is raised if Tab_Stops /= NO_TABS for a hanging or bulleted format. procedure Put_Style (Name : in String; Include_Compatibility : in Boolean := True; Use_DIV : in Boolean := False) is -- Output a style for HTML 4.0; if Include_Compatibility is True, -- include compatibility font information as well. -- If Use_DIV is true, ignore the contents of the -- style data and use a DIV. begin if Use_DIV then Ada.Text_IO.Put (Output_Object.Output_File, " Ada.Text_IO.Put (Output_Object.Output_File, " Ada.Text_IO.Put (Output_Object.Output_File, " Ada.Text_IO.Put (Output_Object.Output_File, " null; when ARM_Output.Center => Ada.Text_IO.Put (Output_Object.Output_File, " style=""text-align: center"""); Output_Object.Char_Count := Output_Object.Char_Count + 27; when ARM_Output.Right => Ada.Text_IO.Put (Output_Object.Output_File, " style=""text-align: right"""); Output_Object.Char_Count := Output_Object.Char_Count + 26; end case; case Space_After is when ARM_Output.Normal => null; when ARM_Output.Narrow => Ada.Text_IO.Put (Output_Object.Output_File, " style=""margin-bottom: "); Output_Object.Char_Count := Output_Object.Char_Count + 24; Put_EMs(Output_Object.Output_File, (Paragraph_Info(Style, Indent).After * LEADING_PERCENT) / 100); Ada.Text_IO.Put (Output_Object.Output_File, """"); Output_Object.Char_Count := Output_Object.Char_Count + 6; when ARM_Output.Wide => Ada.Text_IO.Put (Output_Object.Output_File, " style=""margin-bottom: "); Output_Object.Char_Count := Output_Object.Char_Count + 24; Put_EMs(Output_Object.Output_File, (Paragraph_Info(Style, Indent).After * TRAILING_PERCENT) / 100); Ada.Text_IO.Put (Output_Object.Output_File, """"); Output_Object.Char_Count := Output_Object.Char_Count + 6; end case; Ada.Text_IO.Put (Output_Object.Output_File, ">"); Output_Object.Char_Count := Output_Object.Char_Count + 1; if Output_Object.HTML_Kind = HTML_4_Compatible and then Include_Compatibility then Put_Compatibility_Font_Info (Output_Object, Style, Indent); end if; end Put_Style; function Paranum_Anchor (Number : in String) return String is -- Create the string for an anchor from a paragraph number. -- Note that anchors cannot use "/", so we strip the -- slash part. "." is allowed (as well as "-", "_", and ":", but -- nothing else). We don't need the slash part (the version number), -- as paragraph numbers are unique without it, and the version -- is specified by the enclosing document (given by the rest of -- the page). Where : constant Natural := Ada.Strings.Fixed.Index (Number, "/"); begin if Where = 0 then return Number; else return Number(Number'First..Where-1); end if; end Paranum_Anchor; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already in paragraph"); end if; if not Output_Object.Number_Paragraphs and then Number /= "" then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Paragraph number when none used"); end if; if not Paragraph_Info(Style, Indent).Defined then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Undefined style " & ARM_Output.Paragraph_Style_Type'Image(Style) & " and indent" & ARM_Output.Paragraph_Indent_Type'Image(Indent)); end if; Output_Object.Is_In_Paragraph := True; Output_Object.Had_Prefix := not No_Prefix; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line Output_Object.Conditional_Space := False; Output_Object.Saw_Hang_End := False; Output_Object.In_Local_Link := False; Check_Clause_File (Output_Object); -- Note: We only support Justification for the Normal and Wide styles. if Output_Object.Column_Count >= 4 then -- Formatting is deferred; only a few formats are supported. if Tab_Stops.Number /= 0 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tabs in 4+ column text"); end if; case Style is when ARM_Output.Normal => null; when others => Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unsupported format in 4+ column text - " & ARM_Output.Paragraph_Style_Type'Image(Style)); end case; if Number /= "" then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "No paragraph numbers in 4+ column text"); end if; return; -- Nothing more to do here. end if; -- Set up tabs: case Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Header | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Small_Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Swiss_Examples => Output_Object.Tab_Stops := Tab_Stops; -- No tabs in HTML; we'll emulate them for fixed fonts. -- We'll expand proportional stops here (text characters -- are larger than the variable ones these are set up for). Output_Object.Can_Emulate_Tabs := ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed); for I in 1 .. Tab_Stops.Number loop if ARM_Output."=" (Tab_Stops.Stops(I).Kind, ARM_Output.Left_Proportional) then if ARM_Output."=" (Paragraph_Info(Style, Indent).Font, ARM_Output.Fixed) then Output_Object.Tab_Stops.Stops(I).Stop := (Tab_Stops.Stops(I).Stop * 13 / 12); else -- Proportional characters are smaller. Output_Object.Tab_Stops.Stops(I).Stop := (Tab_Stops.Stops(I).Stop * 5 / 4); end if; else Output_Object.Tab_Stops.Stops(I).Stop := Tab_Stops.Stops(I).Stop; end if; end loop; when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted | ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Enumerated => if Tab_Stops.Number /= 0 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tabs in hanging/bulleted paragraph"); end if; Output_Object.Can_Emulate_Tabs := False; end case; if Output_Object.HTML_Kind = HTML_3 then -- Note: We can't control the space below the paragraphs here, so -- Space_After is ignored. -- Make any indents: for I in 1 .. Indent loop Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 4; end loop; case Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header => if ARM_Output."=" (Indent, 0) then case Justification is when ARM_Output.Default | ARM_Output.Left | ARM_Output.Justified => Ada.Text_IO.Put (Output_Object.Output_File, "

    "); Output_Object.Char_Count := 3; when ARM_Output.Center => Ada.Text_IO.Put (Output_Object.Output_File, "

    "); Output_Object.Char_Count := 16; when ARM_Output.Right => Ada.Text_IO.Put (Output_Object.Output_File, "

    "); Output_Object.Char_Count := 15; end case; else null; -- Formatting is hard in HTML 3! end if; when ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 14; when ARM_Output.Index => -- Note: We don't put this in a smaller font. if ARM_Output."=" (Indent, 0) then Ada.Text_IO.Put (Output_Object.Output_File, "

    "); Output_Object.Char_Count := 3; else null; -- Formatting is hard in HTML 3! end if; when ARM_Output.Syntax_Summary => -- Note: We don't put this in a smaller font. null; when ARM_Output.Title => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 14; when ARM_Output.Examples => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 4; when ARM_Output.Small_Examples => Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 18; when ARM_Output.Swiss_Examples => Ada.Text_IO.Put (Output_Object.Output_File, SWISS_FONT_CODE); Output_Object.Char_Count := Output_Object.Char_Count + SWISS_FONT_CODE'Length; when ARM_Output.Small_Swiss_Examples => Ada.Text_IO.Put (Output_Object.Output_File, SMALL_SWISS_FONT_CODE); Output_Object.Char_Count := Output_Object.Char_Count + SMALL_SWISS_FONT_CODE'Length; when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted => if No_Prefix then null; else Ada.Text_IO.Put (Output_Object.Output_File, "

  • "); Output_Object.Char_Count := Output_Object.Char_Count + 14; end if; when ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => if No_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 14; else Ada.Text_IO.Put (Output_Object.Output_File, "
  • "); Output_Object.Char_Count := Output_Object.Char_Count + 28; end if; when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated => if No_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 8; Output_Object.Saw_Hang_End := True; else -- Has prefix. Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 8; Output_Object.Saw_Hang_End := False; end if; when ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => if No_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 22; Output_Object.Saw_Hang_End := True; else -- Has prefix. Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 22; Output_Object.Saw_Hang_End := False; end if; end case; Output_Object.Paragraph_Style := Style; Output_Object.Paragraph_Indent := Indent; Output_Object.Font := ARM_Output.Default; Output_Object.Is_Bold := False; Output_Object.Is_Italic := False; Output_Object.Size := 0; Output_Object.Color := ARM_Output.Default; Output_Object.Change := ARM_Output.None; Output_Object.Version := '0'; Output_Object.Added_Version := '0'; if Number /= "" then -- Has paragraph number. Ada.Text_IO.Put (Output_Object.Output_File, ""); Ada.Text_IO.Put (Output_Object.Output_File, TINY_SWISS_FONT_CODE); Ada.Text_IO.Put (Output_Object.Output_File, Number); Ada.Text_IO.Put (Output_Object.Output_File, Number); Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + TINY_SWISS_FONT_CODE'Length + Number'Length + 8; Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + ((Number'Length+1)/2) + 1; -- Note: Count these as half characters, as the font is so small. --Output_Object.Disp_Large_Char_Count := ; end if; elsif Output_Object.HTML_Kind = HTML_4_Compatible then if Number /= "" then -- Has paragraph number. Paranum_Used := True; Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Ada.Text_IO.Put (Output_Object.Output_File, ""); Ada.Text_IO.Put (Output_Object.Output_File, Number); Ada.Text_IO.Put (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, "
    "); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line Output_Object.Conditional_Space := False; -- Don't need it here. end if; case Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Examples | ARM_Output.Small_Swiss_Examples => Put_Style (Paragraph_Name (Style, Indent)); when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => Put_Style (Paragraph_Name (Style, Indent), Include_Compatibility => False); if No_Prefix then null; else Ada.Text_IO.Put (Output_Object.Output_File, "
  • "); Output_Object.Char_Count := Output_Object.Char_Count + 14; end if; Put_Compatibility_Font_Info (Output_Object, Style, Indent); when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => declare PName : constant String := Paragraph_Name (Style, Indent); begin Put_Style (PName, Include_Compatibility => False); if No_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 13 + PName'Length; Output_Object.Saw_Hang_End := True; else -- Has prefix. Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Output_Object.Char_Count := Output_Object.Char_Count + 4; Output_Object.Saw_Hang_End := False; end if; Put_Compatibility_Font_Info (Output_Object, Style, Indent); end; end case; Output_Object.Paragraph_Style := Style; Output_Object.Paragraph_Indent := Indent; Output_Object.Font := ARM_Output.Default; Output_Object.Is_Bold := False; Output_Object.Is_Italic := False; Output_Object.Size := 0; Output_Object.Color := ARM_Output.Default; Output_Object.Change := ARM_Output.None; Output_Object.Version := '0'; Output_Object.Added_Version := '0'; if Number /= "" then -- Has paragraph number. if Paragraph_Info(Style, Indent).Indent = 0 and then ((not No_Prefix) or else Style in ARM_Output.Unprefixed_Style_Subtype) then -- No indent, either a prefix or a style that doesn't -- have a prefix. -- We may have to make a space for the paragraph number, -- as absolute positioned or floating items can overlap -- others. for I in 1 .. (Number'Length+2)-(INDENT_EMS_FOR_PARANUMS/5) loop -- We assume that each space is roughly equal to -- 0.5em (that should be conservative). Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end loop; -- else is indented, so we don't need to make space. end if; end if; else -- HTML_4_Only. if Number /= "" then -- Has paragraph number. Paranum_Used := True; Ada.Text_IO.Put (Output_Object.Output_File, "
    "); Ada.Text_IO.Put (Output_Object.Output_File, ""); Ada.Text_IO.Put (Output_Object.Output_File, Number); Ada.Text_IO.Put (Output_Object.Output_File, ""); Ada.Text_IO.Put_Line (Output_Object.Output_File, "
    "); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line Output_Object.Conditional_Space := False; -- Don't need it here. end if; case Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Examples | ARM_Output.Small_Swiss_Examples => Put_Style (Paragraph_Name (Style, Indent)); when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => -- We use formatted DIVs here, as otherwise the indenting -- varies wildly between Firefox and IE (and does not -- match similar enumerated lists). if No_Prefix then Put_Style (Paragraph_Name (Style, Indent) & "-NoPrefix", Use_DIV => True); else Put_Style (Paragraph_Name (Style, Indent), Use_DIV => True); end if; when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => if No_Prefix then Put_Style (Paragraph_Name (Style, Indent) & "-Body", Use_DIV => True); Output_Object.Saw_Hang_End := True; else -- Has prefix. Put_Style (Paragraph_Name (Style, Indent) & "-Term", Use_DIV => True); Output_Object.Saw_Hang_End := False; end if; end case; Output_Object.Paragraph_Style := Style; Output_Object.Paragraph_Indent := Indent; Output_Object.Font := ARM_Output.Default; Output_Object.Is_Bold := False; Output_Object.Is_Italic := False; Output_Object.Size := 0; Output_Object.Color := ARM_Output.Default; Output_Object.Change := ARM_Output.None; Output_Object.Version := '0'; Output_Object.Added_Version := '0'; if Number /= "" then -- Has paragraph number. if Paragraph_Info(Style, Indent).Indent = 0 and then ((not No_Prefix) or else Style in ARM_Output.Unprefixed_Style_Subtype) then -- No indent, either a prefix or a style that doesn't -- have a prefix. -- We may have to make a space for the paragraph number, -- as absolute positioned or floating items can overlap -- others. for I in 1 .. (Number'Length+2)-((INDENT_EMS_FOR_PARANUMS+5)*3/10) loop -- We assume that each space is roughly equal to -- 0.33em (that should be conservative). We also assume -- that the normal left edge space is 1.0em (this is -- true on IE 5&6). Paragraph numbers are positioned -- at 0.5ems, so the additional difference is +5. Ada.Text_IO.Put (Output_Object.Output_File, " "); Output_Object.Char_Count := Output_Object.Char_Count + 1; Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end loop; -- else is indented, so we don't need to make space. end if; end if; end if; Paragraph_Used(Style, Indent) := True; -- Note: No_Breaks and Keep_with_Next have no effect here, because -- HTML doesn't have page breaks. end Start_Paragraph; procedure End_Paragraph (Output_Object : in out HTML_Output_Type) is -- End a paragraph. procedure Put_End_Style (Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Include_Compatibility : in Boolean := True) is -- Output a end style for HTML 4.0; if Include_Compatibility is True, -- include compatibility font information as well. begin if Output_Object.HTML_Kind = HTML_4_Compatible and then Include_Compatibility then Put_End_Compatibility_Font_Info (Output_Object, Style, Indent); end if; case Paragraph_Info(Style, Indent).Tag is when DIV => Ada.Text_IO.Put (Output_Object.Output_File, ""); when UL => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when DL => Ada.Text_IO.Put (Output_Object.Output_File, ""); end case; end Put_End_Style; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; Output_Object.Is_In_Paragraph := False; if Output_Object.In_Local_Link then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unclosed Local_Link"); Output_Object.In_Local_Link := False; end if; if Output_Object.Column_Count >= 4 then -- Formatting is deferred; only a few formats are supported. if Output_Object.Column_Text (Output_Object.Current_Column) /= null and then Output_Object.Column_Text (Output_Object.Current_Column).Item = Output_Object.Current_Item then Output_Object.Column_Text (Output_Object.Current_Column).End_Para := True; end if; Output_Object.Current_Item := Output_Object.Current_Item + 2; -- Skip an item. Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. return; -- Nothing else to do here. end if; if Output_Object.HTML_Kind = HTML_3 then case Output_Object.Paragraph_Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header | ARM_Output.Index => if ARM_Output."=" (Output_Object.Paragraph_Indent, 0) then Ada.Text_IO.Put (Output_Object.Output_File, "

"); -- else let the indent nesting handling it. end if; when ARM_Output.Syntax_Summary => null; when ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when ARM_Output.Title => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when ARM_Output.Examples => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when ARM_Output.Small_Examples => Ada.Text_IO.Put (Output_Object.Output_File, "
"); when ARM_Output.Swiss_Examples => Ada.Text_IO.Put (Output_Object.Output_File, ""); when ARM_Output.Small_Swiss_Examples => Ada.Text_IO.Put (Output_Object.Output_File, ""); when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted => if Output_Object.Had_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, ""); -- else nothing to do. end if; when ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => if Output_Object.Had_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, ""); else Ada.Text_IO.Put (Output_Object.Output_File, ""); end if; when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated => Ada.Text_IO.Put (Output_Object.Output_File, ""); when ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => Ada.Text_IO.Put (Output_Object.Output_File, ""); end case; -- Reverse any indents: for I in reverse 1 .. Output_Object.Paragraph_Indent loop Ada.Text_IO.Put (Output_Object.Output_File, ""); end loop; Ada.Text_IO.New_Line (Output_Object.Output_File, 2); elsif Output_Object.HTML_Kind = HTML_4_Only then case Output_Object.Paragraph_Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Examples | ARM_Output.Small_Swiss_Examples => Put_End_Style (Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => -- We've overridden the style class here. Ada.Text_IO.Put (Output_Object.Output_File, ""); when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => -- We've overridden the style class here. Ada.Text_IO.Put (Output_Object.Output_File, ""); end case; Ada.Text_IO.New_Line (Output_Object.Output_File); else -- if Output_Object.HTML_Kind = HTML_4_Compatible case Output_Object.Paragraph_Style is when ARM_Output.Normal | ARM_Output.Wide_Above | ARM_Output.Header | ARM_Output.Small | ARM_Output.Small_Wide_Above | ARM_Output.Small_Header | ARM_Output.Index | ARM_Output.Syntax_Summary | ARM_Output.Title | ARM_Output.Examples | ARM_Output.Swiss_Examples | ARM_Output.Small_Examples | ARM_Output.Small_Swiss_Examples => Put_End_Style (Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); when ARM_Output.Bulleted | ARM_Output.Nested_Bulleted | ARM_Output.Small_Bulleted | ARM_Output.Small_Nested_Bulleted => Put_End_Compatibility_Font_Info (Output_Object, Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); if Output_Object.Had_Prefix then Ada.Text_IO.Put (Output_Object.Output_File, ""); -- else null; end if; Put_End_Style (Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent, Include_Compatibility => False); when ARM_Output.Giant_Hanging | ARM_Output.Wide_Hanging | ARM_Output.Medium_Hanging | ARM_Output.Narrow_Hanging | ARM_Output.Hanging_in_Bulleted | ARM_Output.Enumerated | ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => Put_End_Style (Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); end case; Ada.Text_IO.New_Line (Output_Object.Output_File); end if; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. end End_Paragraph; procedure Category_Header (Output_Object : in out HTML_Output_Type; Header_Text : String) is -- Output a Category header (that is, "Legality Rules", -- "Dynamic Semantics", etc.) -- (Note: We did not use a enumeration here to insure that these -- headers are spelled the same in all output versions). -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); if Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); end if; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. end Category_Header; procedure Clause_Header (Output_Object : in out HTML_Output_Type; Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False) is -- Output a Clause header. The level of the header is specified -- in Level. The Clause Number is as specified; the top-level (and -- other) subdivision names are as specified. These should appear in -- the table of contents. -- For hyperlinked formats, this should generate a link target. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; if not Output_Object.Big_Files then if Ada.Text_IO.Is_Open (Output_Object.Output_File) then End_HTML_File (Output_Object); end if; -- Special for table of contents: if Clause_Number = "" and then (Header_Text = "Table of Contents" or else -- Ada 95 format Header_Text = "Contents") then -- ISO 2004 format. Start_HTML_File (Output_Object, Ada.Strings.Fixed.Trim (Output_Object.File_Prefix, Ada.Strings.Right) & "-TOC", Header_Text, ""); if Header_Text = "Table of Contents" then -- Ada 95 format Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Table of Contents

"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Contents

"); end if; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. return; end if; Start_HTML_File (Output_Object, Make_Clause_File_Name (Output_Object, Clause_Number), Header_Text, Clause_Number); else -- Big Files: if Clause_Number = "" and then (Header_Text = "Table of Contents" or else -- Ada 95 format Header_Text = "Contents") then -- ISO 2004 format. -- Insert an anchor: Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); if Header_Text = "Table of Contents" then -- Ada 95 format Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Table of Contents

"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Contents

"); end if; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. return; end if; -- Insert an anchor: Ada.Text_IO.Put (Output_Object.Output_File, ""); end if; case Level is when ARM_Contents.Plain_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "
"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text & "

"); when ARM_Contents.Normative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "

"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "

(normative)

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); when ARM_Contents.Informative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "

"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "

(informative)

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); when ARM_Contents.Unnumbered_Section => if Header_Text /= "" then Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); end if; when ARM_Contents.Section => case Top_Level_Subdivision_Name is when ARM_Output.Chapter => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Chapter " & Clause_Number & ": " & Header_Text & "

"); when ARM_Output.Section => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Section " & Clause_Number & ": " & Header_Text & "

"); when ARM_Output.Clause => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "   " & Header_Text & "

"); end case; when ARM_Contents.Clause | ARM_Contents.Subclause | ARM_Contents.Subsubclause => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & ' ' & Header_Text & "

"); when ARM_Contents.Dead_Clause => raise Program_Error; -- No headers for dead clauses. end case; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. -- No page breaks in HTML, so we don't need to look at No_Page_Break. end Clause_Header; procedure Revised_Clause_Header (Output_Object : in out HTML_Output_Type; New_Header_Text : in String; Old_Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Version : in ARM_Contents.Change_Version_Type; Old_Version : in ARM_Contents.Change_Version_Type; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False) is -- Output a revised clause header. Both the original and new text will -- be output. The level of the header is specified in Level. The Clause -- Number is as specified; the top-level (and other) subdivision names -- are as specified. These should appear in the table of contents. -- For hyperlinked formats, this should generate a link target. -- Version is the insertion version of the new text; Old_Version is -- the insertion version of the old text. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. function Header_Text return String is begin if Output_Object.HTML_Kind = HTML_3 then if Old_Version = '0' then -- Old text is original text return "" & New_Header_Text & "" & Old_Header_Text & ""; else return "" & New_Header_Text & "" & Old_Header_Text & ""; end if; elsif Old_Version = '0' then -- Old text is original text Revision_Used(Version) := True; return "" & New_Header_Text & "" & Old_Header_Text & ""; else Revision_Used(Version) := True; Revision_Used(Old_Version) := True; return "" & New_Header_Text & "" & Old_Header_Text & ""; end if; end Header_Text; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Header in paragraph"); end if; if not Output_Object.Big_Files then if Ada.Text_IO.Is_Open (Output_Object.Output_File) then End_HTML_File (Output_Object); end if; Start_HTML_File (Output_Object, Make_Clause_File_Name (Output_Object, Clause_Number), New_Header_Text, Clause_Number); else -- Big Files: -- Insert an anchor: Ada.Text_IO.Put (Output_Object.Output_File, ""); end if; case Level is when ARM_Contents.Plain_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "
"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, Header_Text & "

"); when ARM_Contents.Normative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "

"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "

(normative)

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); when ARM_Contents.Informative_Annex => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "

"); -- Note: Clause_Number includes "Annex" Ada.Text_IO.Put_Line (Output_Object.Output_File, "

(informative)

"); Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); when ARM_Contents.Unnumbered_Section => if Header_Text /= "" then Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Header_Text & "

"); end if; when ARM_Contents.Section => case Top_Level_Subdivision_Name is when ARM_Output.Chapter => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Chapter " & Clause_Number & ": " & Header_Text & "

"); when ARM_Output.Section => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

Section " & Clause_Number & ": " & Header_Text & "

"); when ARM_Output.Clause => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & "   " & Header_Text & "

"); end case; when ARM_Contents.Clause | ARM_Contents.Subclause | ARM_Contents.Subsubclause => Ada.Text_IO.Put_Line (Output_Object.Output_File, "

" & Clause_Number & ' ' & Header_Text & "

"); when ARM_Contents.Dead_Clause => raise Program_Error; -- No headers for dead clauses. end case; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. -- No page breaks in HTML, so we don't need to look at No_Page_Break. end Revised_Clause_Header; procedure TOC_Marker (Output_Object : in out HTML_Output_Type; For_Start : in Boolean) is -- Mark the start (if For_Start is True) or end (if For_Start is -- False) of the table of contents data. Output objects that -- auto-generate the table of contents can use this to do needed -- actions. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; null; -- We don't care about this. end TOC_Marker; procedure New_Page (Output_Object : in out HTML_Output_Type; Kind : ARM_Output.Page_Kind_Type := ARM_Output.Any_Page) is -- Output a page break. -- Note that this has no effect on non-printing formats. -- Any_Page breaks to the top of the next page (whatever it is); -- Odd_Page_Only breaks to the top of the odd-numbered page; -- Soft_Page allows a page break but does not force one (use in -- "No_Breaks" paragraphs.) -- Raises Not_Valid_Error if in a paragraph if Kind = Any_Page or -- Odd_Page, and if not in a paragraph if Kind = Soft_Page. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; case Kind is when ARM_Output.Any_Page | ARM_Output.Odd_Page_Only => if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Page in paragraph"); end if; -- No real page breaks supported. --Ada.Text_IO.Put_Line (Output_Object.Output_File, "



"); --Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line. --Ada.Text_IO.Put_Line (Output_Object.Output_File, "


"); -- This horizontal rule looks awful when inserted solely to -- make PDF formats look good; and it doesn't make much sense -- any other time, either. (Why would we want to start a page -- with this?) So it's been removed completely; and we have no -- other page breaks in HTML. when ARM_Output.Soft_Page => if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Soft page not in paragraph"); end if; null; -- No page breaks in HTML. end case; end New_Page; procedure Separator_Line (Output_Object : in out HTML_Output_Type; Is_Thin : Boolean := True) is -- Output a separator line. It is thin if "Is_Thin" is true. -- Raises Not_Valid_Error if in a paragraph. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Separator in paragraph"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); if Is_Thin then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line. else Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- Horizontal line. end if; Ada.Text_IO.New_Line (Output_Object.Output_File); end Separator_Line; procedure Start_Table (Output_Object : in out HTML_Output_Type; Columns : in ARM_Output.Column_Count; First_Column_Width : in ARM_Output.Column_Count; Last_Column_Width : in ARM_Output.Column_Count; Alignment : in ARM_Output.Column_Text_Alignment; No_Page_Break : in Boolean; Has_Border : in Boolean; Small_Text_Size : in Boolean; Header_Kind : in ARM_Output.Header_Kind_Type) is -- Starts a table. The number of columns is Columns; the first -- column has First_Column_Width times the normal column width, and -- the last column has Last_Column_Width times the normal column width. -- Alignment is the horizontal text alignment within the columns. -- No_Page_Break should be True to keep the table intact on a single -- page; False to allow it to be split across pages. -- Has_Border should be true if a border is desired, false otherwise. -- Small_Text_Size means that the contents will have the AARM size; -- otherwise it will have the normal size. -- Header_Kind determines whether the table has headers. -- This command starts a paragraph; the entire table is a single -- paragraph. Text will be considered part of the caption until the -- next table marker call. -- Raises Not_Valid_Error if in a paragraph. use type ARM_Output.Header_Kind_Type; use type ARM_Output.Column_Text_Alignment; begin -- No_Page_Break, First_Column_Width, and Last_Column_Width not used, -- the latter two because column width is calculated based on the -- contents. if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Table in paragraph"); end if; if Output_Object.HTML_Kind /= HTML_3 then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Paragraph_Used(ARM_Output.Normal, 1) := True; end if; if Has_Border then Ada.Text_IO.Put (Output_Object.Output_File, ""); else Ada.Text_IO.Put (Output_Object.Output_File, "
"); end if; if Header_Kind = ARM_Output.Both_Caption_and_Header then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 9; Output_Object.In_Header := True; elsif Header_Kind = ARM_Output.Header_Only then if Alignment = ARM_Output.Center_All then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 24; else Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 22; end if; Output_Object.In_Header := True; else -- Header_Kind = ARM_Output.No_Headers then if Alignment = ARM_Output.Center_All then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 24; else Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 22; end if; Output_Object.In_Header := False; end if; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. Output_Object.Is_In_Paragraph := True; Output_Object.Is_In_Table := True; Output_Object.Table_Column_Alignment := Alignment; Output_Object.Table_Has_Small_Text := Small_Text_Size; if Output_Object.Table_Has_Small_Text then if Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 29; else Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; end if; end if; end Start_Table; procedure Table_Marker (Output_Object : in out HTML_Output_Type; Marker : in ARM_Output.Table_Marker_Type) is -- Marks the end of an entity in a table. -- If Marker is End_Caption, the table caption ends and the -- future text is part of the table header. -- If Marker is End_Header, the table header ends and the -- future text is part of the table body. -- If Marker is End_Row, a row in the table is completed, and another -- row started. -- If Marker is End_Row_Next_Is_Last, a row in the table is completed, -- and another row started. That row is the last row in the table. -- If Marker is End_Item, an item in the table header or body is ended, -- and another started. -- If Marker is End_Table, the entire table is finished. -- Raises Not_Valid_Error if not in a table. use type ARM_Output.Column_Text_Alignment; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if (not Output_Object.Is_In_Paragraph) or (not Output_Object.Is_In_Table) then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Table marker not in table"); end if; -- Close the small fonts (we always need to do this): if Output_Object.Table_Has_Small_Text then if Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 7; else Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 7; end if; end if; case Marker is when ARM_Output.End_Item => -- Note: This isn't the first item on a row. if Output_Object.In_Header then if Output_Object.Table_Column_Alignment = ARM_Output.Left_All then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 18; else Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 20; end if; else if Output_Object.Table_Column_Alignment = ARM_Output.Left_All then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 18; else Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 20; end if; end if; when ARM_Output.End_Caption => Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); if Output_Object.Table_Column_Alignment = ARM_Output.Center_All then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 24; else Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 22; end if; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. when ARM_Output.End_Header => Ada.Text_IO.New_Line (Output_Object.Output_File); if Output_Object.Table_Column_Alignment = ARM_Output.Center_All then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 24; else Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 22; end if; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. Output_Object.In_Header := False; when ARM_Output.End_Row | ARM_Output.End_Row_Next_Is_Last => Ada.Text_IO.New_Line (Output_Object.Output_File); if Output_Object.Table_Column_Alignment = ARM_Output.Center_All then Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 24; else Ada.Text_IO.Put (Output_Object.Output_File, "
"); Output_Object.Char_Count := 22; end if; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. when ARM_Output.End_Table => Ada.Text_IO.New_Line (Output_Object.Output_File); if Output_Object.HTML_Kind /= HTML_3 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); else Ada.Text_IO.Put_Line (Output_Object.Output_File, ""); end if; Output_Object.Is_In_Paragraph := False; Output_Object.Is_In_Table := False; end case; if Output_Object.Table_Has_Small_Text and then ARM_Output."/=" (Marker, ARM_Output.End_Table) then if Output_Object.HTML_Kind = HTML_4_Only then Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 29; else Ada.Text_IO.Put (Output_Object.Output_File, ""); Output_Object.Char_Count := Output_Object.Char_Count + 16; end if; end if; end Table_Marker; -- Text output: These are only allowed after a Start_Paragraph and -- before any End_Paragraph. Raises Not_Valid_Error if not allowed. Special_Set : constant Ada.Strings.Maps.Character_Set := Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (Ada.Strings.Maps.Character_Range'(Low => Character'Val(127), High => Character'Val(255))), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('<'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('>'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('"'), Ada.Strings.Maps.To_Set ('&'))))); No_Conditional_Set : constant Ada.Strings.Maps.Character_Set := Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (' '), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('.'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (','), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (':'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (';'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('!'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('('), Ada.Strings.Maps.To_Set (')')))))))); Large_Char_Set : constant Ada.Strings.Maps.Character_Set := Ada.Strings.Maps."or" (Ada.Strings.Maps.Constants.Upper_Set, Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set (Ada.Strings.Maps.Character_Range'(Low => '0', High => '9')), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('m'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('w'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('<'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('>'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('&'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('%'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('@'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('$'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('*'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('+'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('='), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('?'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('/'), Ada.Strings.Maps."or" (Ada.Strings.Maps.To_Set ('\'), Ada.Strings.Maps.To_Set ('#'))))))))))))))))); procedure Output_Text (Output_Object : in out HTML_Output_Type; Text : in String) is -- Output the text to the current output place. begin if Output_Object.Column_Count >= 4 then if (Output_Object.Column_Text(Output_Object.Current_Column) = null) or else -- No items stored. (Output_Object.Column_Text(Output_Object.Current_Column).Item /= Output_Object.Current_Item) then -- Start a new item. Output_Object.Column_Text(Output_Object.Current_Column) := new Column_Text_Item_Type'(Text => (others => ' '), Length => 0, Item => Output_Object.Current_Item, End_Para => False, Next => Output_Object.Column_Text(Output_Object.Current_Column)); end if; if Output_Object.Column_Text(Output_Object.Current_Column).Length + Text'Length > Output_Object.Column_Text(Output_Object.Current_Column).Text'Length then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Column item full, but more text! - " & Output_Object.Column_Text(Output_Object.Current_Column).Text(1..Output_Object.Column_Text(Output_Object.Current_Column).Length) & Text); else Output_Object.Column_Text(Output_Object.Current_Column).Text( Output_Object.Column_Text(Output_Object.Current_Column).Length+1.. Output_Object.Column_Text(Output_Object.Current_Column).Length+Text'Length) := Text; Output_Object.Column_Text(Output_Object.Current_Column).Length := Output_Object.Column_Text(Output_Object.Current_Column).Length + Text'Length; end if; else -- Normal, use Text_IO. Ada.Text_IO.Put (Output_Object.Output_File, Text); Output_Object.Char_Count := Output_Object.Char_Count + Text'Length; end if; end Output_Text; procedure Ordinary_Text (Output_Object : in out HTML_Output_Type; Text : in String) is -- Output ordinary text. -- The text must end at a word break, never in the middle of a word. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Text'Length = 0 then return; -- Nothing to do. end if; if Ada.Strings.Fixed.Count (Text, Special_Set) = 0 then if Output_Object.Char_Count + Text'Length >= LINE_LENGTH - 10 then -- We can only break on a space. for I in Text'range loop Ordinary_Character (Output_Object, Text(I)); end loop; else if Output_Object.Conditional_Space then Output_Object.Conditional_Space := False; if Ada.Strings.Maps.Is_In (Text(Text'First), No_Conditional_Set) then null; -- Don't need the conditional space. else Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; end if; Output_Text (Output_Object, Text); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + Text'Length; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + Ada.Strings.Fixed.Count (Text, Large_Char_Set); Output_Object.Any_Nonspace := True; Output_Object.Last_was_Space := Text(Text'Last) = ' '; end if; else for I in Text'range loop Ordinary_Character (Output_Object, Text(I)); end loop; end if; end Ordinary_Text; procedure Ordinary_Character (Output_Object : in out HTML_Output_Type; Char : in Character) is -- Output an ordinary character. -- Spaces will be used to break lines as needed. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Conditional_Space then Output_Object.Conditional_Space := False; if Ada.Strings.Maps.Is_In (Char, No_Conditional_Set) then null; -- Don't need the conditional space. else Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; end if; Output_Object.Last_was_Space := False; if Char = ' ' then if Output_Object.Char_Count >= LINE_LENGTH - 10 and then Output_Object.Column_Count < 4 then if Output_Object.HTML_Kind > HTML_3 then -- Note: We leave the space here so that later code can tell -- the difference between a line broken on a space, and a -- line broken for because it's convinient. Ada.Text_IO.Put_Line (Output_Object.Output_File, " "); else -- No later code. Ada.Text_IO.New_Line (Output_Object.Output_File); end if; Output_Object.Char_Count := 0; Output_Object.Last_was_Space := True; else Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; -- Output_Object.Any_Nonspace := ; Output_Object.Last_was_Space := True; elsif Char = '<' then Output_Text (Output_Object, "<"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; Output_Object.Any_Nonspace := True; elsif Char = '>' then Output_Text (Output_Object, ">"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; Output_Object.Any_Nonspace := True; elsif Char = '"' then Output_Text (Output_Object, """); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- No change in Disp_Large_Char_Count. Output_Object.Any_Nonspace := True; elsif Char = '&' then Output_Text (Output_Object, "&"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; Output_Object.Any_Nonspace := True; elsif Char >= Character'Val(126) then -- All higher Latin-1 characters. case Character'Pos(Char) is when 160 => Output_Text (Output_Object, " "); when 161 => Output_Text (Output_Object, "¡"); when 162 => Output_Text (Output_Object, "¢"); when 163 => Output_Text (Output_Object, "£"); when 164 => Output_Text (Output_Object, "¤"); when 165 => Output_Text (Output_Object, "¥"); when 166 => Output_Text (Output_Object, "¦"); when 167 => Output_Text (Output_Object, "§"); when 168 => Output_Text (Output_Object, "¨"); when 169 => Output_Text (Output_Object, "©"); when 170 => Output_Text (Output_Object, "ª"); when 171 => Output_Text (Output_Object, "«"); when 172 => Output_Text (Output_Object, "¬"); when 173 => Output_Text (Output_Object, "­"); when 174 => Output_Text (Output_Object, "®"); when 175 => Output_Text (Output_Object, "¯"); when 176 => Output_Text (Output_Object, "°"); when 177 => Output_Text (Output_Object, "±"); when 178 => Output_Text (Output_Object, "²"); when 179 => Output_Text (Output_Object, "³"); when 180 => Output_Text (Output_Object, "´"); when 181 => Output_Text (Output_Object, "µ"); when 182 => Output_Text (Output_Object, "¶"); when 183 => Output_Text (Output_Object, "·"); when 184 => Output_Text (Output_Object, "¸"); when 185 => Output_Text (Output_Object, "¹"); when 186 => Output_Text (Output_Object, "º"); when 187 => Output_Text (Output_Object, "»"); when 188 => Output_Text (Output_Object, "¼"); when 189 => Output_Text (Output_Object, "½"); when 190 => Output_Text (Output_Object, "¾"); when 191 => Output_Text (Output_Object, "¿"); when 192 => Output_Text (Output_Object, "À"); when 193 => Output_Text (Output_Object, "Á"); when 194 => Output_Text (Output_Object, "Â"); when 195 => Output_Text (Output_Object, "Ã"); when 196 => Output_Text (Output_Object, "Ä"); when 197 => Output_Text (Output_Object, "Å"); when 198 => Output_Text (Output_Object, "Æ"); when 199 => Output_Text (Output_Object, "Ç"); when 200 => Output_Text (Output_Object, "È"); when 201 => Output_Text (Output_Object, "É"); when 202 => Output_Text (Output_Object, "Ê"); when 203 => Output_Text (Output_Object, "Ë"); when 204 => Output_Text (Output_Object, "Ì"); when 205 => Output_Text (Output_Object, "Í"); when 206 => Output_Text (Output_Object, "Î"); when 207 => Output_Text (Output_Object, "Ï"); when 208 => Output_Text (Output_Object, "Ð"); when 209 => Output_Text (Output_Object, "Ñ"); when 210 => Output_Text (Output_Object, "Ò"); when 211 => Output_Text (Output_Object, "Ó"); when 212 => Output_Text (Output_Object, "Ô"); when 213 => Output_Text (Output_Object, "Õ"); when 214 => Output_Text (Output_Object, "Ö"); when 215 => Output_Text (Output_Object, "×"); when 216 => Output_Text (Output_Object, "Ø"); when 217 => Output_Text (Output_Object, "Ù"); when 218 => Output_Text (Output_Object, "Ú"); when 219 => Output_Text (Output_Object, "Û"); when 220 => Output_Text (Output_Object, "Ü"); when 221 => Output_Text (Output_Object, "Ý"); when 222 => Output_Text (Output_Object, "Þ"); when 223 => Output_Text (Output_Object, "ß"); when 224 => Output_Text (Output_Object, "à"); when 225 => Output_Text (Output_Object, "á"); when 226 => Output_Text (Output_Object, "â"); when 227 => Output_Text (Output_Object, "ã"); when 228 => Output_Text (Output_Object, "ä"); when 229 => Output_Text (Output_Object, "å"); when 230 => Output_Text (Output_Object, "æ"); when 231 => Output_Text (Output_Object, "ç"); when 232 => Output_Text (Output_Object, "è"); when 233 => Output_Text (Output_Object, "é"); when 234 => Output_Text (Output_Object, "ê"); when 235 => Output_Text (Output_Object, "ë"); when 236 => Output_Text (Output_Object, "ì"); when 237 => Output_Text (Output_Object, "í"); when 238 => Output_Text (Output_Object, "î"); when 239 => Output_Text (Output_Object, "ï"); when 240 => Output_Text (Output_Object, "ð"); when 241 => Output_Text (Output_Object, "ñ"); when 242 => Output_Text (Output_Object, "ò"); when 243 => Output_Text (Output_Object, "ó"); when 244 => Output_Text (Output_Object, "ô"); when 245 => Output_Text (Output_Object, "õ"); when 246 => Output_Text (Output_Object, "ö"); when 247 => Output_Text (Output_Object, "÷"); when 248 => Output_Text (Output_Object, "ø"); when 249 => Output_Text (Output_Object, "ù"); when 250 => Output_Text (Output_Object, "ú"); when 251 => Output_Text (Output_Object, "û"); when 252 => Output_Text (Output_Object, "ü"); when 253 => Output_Text (Output_Object, "ý"); when 254 => Output_Text (Output_Object, "þ"); when 255 => Output_Text (Output_Object, "ÿ"); when others => declare Code : constant String := Natural'Image(Character'Pos(Char)); begin Output_Text (Output_Object, "&#" & Code(2..4) & ';'); end; end case; Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; if Ada.Strings.Maps.Is_In (Char, Large_Char_Set) then Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; -- else not a large character. end if; Output_Object.Any_Nonspace := True; else Output_Text (Output_Object, Char & ""); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; if Ada.Strings.Maps.Is_In (Char, Large_Char_Set) then Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; -- else not a large character. end if; Output_Object.Any_Nonspace := True; end if; end Ordinary_Character; procedure Hard_Space (Output_Object : in out HTML_Output_Type) is -- Output a hard space. No line break should happen at a hard space. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- Output_Object.Disp_Large_Char_Count := ; -- Output_Object.Any_Nonspace := ; Output_Object.Last_was_Space := True; Output_Object.Conditional_Space := False; -- Never need a conditional space here. end Hard_Space; procedure Line_Break (Output_Object : in out HTML_Output_Type) is -- Output a line break. This does not start a new paragraph. -- This corresponds to a "
" in HTML. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Column_Count >= 4 then -- Output is deferred; mark the end of an item. if Output_Object.Column_Text (Output_Object.Current_Column) /= null and then Output_Object.Column_Text (Output_Object.Current_Column).Item = Output_Object.Current_Item then Output_Object.Column_Text (Output_Object.Current_Column).End_Para := False; end if; Output_Object.Current_Item := Output_Object.Current_Item + 1; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. else -- Normal. Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. end if; end Line_Break; procedure Index_Line_Break (Output_Object : in out HTML_Output_Type; Clear_Keep_with_Next : in Boolean) is -- Output a line break for the index. This does not start a new -- paragraph in terms of spacing. This corresponds to a "
" -- in HTML. If Clear_Keep_with_Next is true, insure that the next -- line does not require the following line to stay with it. -- Raises Not_Valid_Error if the paragraph is not in the index format. begin if ARM_Output."/=" (Output_Object.Paragraph_Style, ARM_Output.Index) then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not index format"); end if; Line_Break (Output_Object); end Index_Line_Break; procedure Soft_Line_Break (Output_Object : in out HTML_Output_Type) is -- Output a soft line break. This is a place (in the middle of a -- "word") that we allow a line break. It is usually used after -- underscores in long non-terminals. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.HTML_Kind > HTML_3 and then Output_Object.Use_Unicode then Output_Text (Output_Object, "​"); -- else no Soft break in HTML 3.2. end if; end Soft_Line_Break; procedure Soft_Hyphen_Break (Output_Object : in out HTML_Output_Type) is -- Output a soft line break, with a hyphen. This is a place (in the middle of -- a "word") that we allow a line break. If the line break is used, -- a hyphen will be added to the text. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; null; -- Soft hyphens exist, but don't work on either Internet Exploder 4 -- or Netcrash 3. That is, they are always displayed. (They should -- only be displayed at the location of a line break). --Output_Text (Output_Object, "­"); -- A Latin-1 char. end Soft_Hyphen_Break; procedure Tab (Output_Object : in out HTML_Output_Type) is -- Output a tab, inserting space up to the next tab stop. -- Raises Not_Valid_Error if the paragraph was created with -- Tab_Stops = ARM_Output.NO_TABS. begin -- HTML does not have tabs. Emulation is not successful on proportional -- fonts, so we let the user select how to do it. if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if ARM_Output."="(Output_Object.Tab_Stops, ARM_Output.NO_TABS) then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Tab, but none set"); end if; Output_Object.Conditional_Space := False; -- Never need a conditional space here. Output_Object.Last_was_Space := True; -- Treat this as a space. if Output_Object.Tab_Emulation = Single_Space then -- Don't emulate these, just use a single space. Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- Output_Object.Disp_Large_Char_Count := ; elsif Output_Object.Tab_Emulation = Quad_Space then -- Don't emulate these, just use a single space. Output_Text (Output_Object, "    "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 4; -- Output_Object.Disp_Large_Char_Count := ; elsif Output_Object.Tab_Emulation = Emulate_Fixed_Only or else Output_Object.Tab_Emulation = Emulate_Fixed_Only_Quad then if Output_Object.Can_Emulate_Tabs or else (not Output_Object.Any_Nonspace) then -- Always can emulate if they're first on a line. Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- Output_Object.Disp_Large_Char_Count := ; for I in 1 .. Output_Object.Tab_Stops.Number loop if Output_Object.Tab_Stops.Stops(I).Stop >= Output_Object.Disp_Char_Count then for J in Output_Object.Disp_Char_Count+1 .. Output_Object.Tab_Stops.Stops(I).Stop loop Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- Output_Object.Disp_Large_Char_Count := ; end loop; exit; end if; end loop; -- If we drop out without finding a tab, we just use the single -- space already written. elsif Output_Object.Tab_Emulation = Emulate_Fixed_Only then -- Put in a space. Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; if ARM_Output."=" (Output_Object.Paragraph_Style, ARM_Output.Syntax_Summary) and then Output_Object.Column_Count > 1 then -- Special case (hack!) to make Syntax cross-reference look better: Output_Text (Output_Object, "  "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; end if; -- Output_Object.Disp_Large_Char_Count := ; elsif Output_Object.Tab_Emulation = Emulate_Fixed_Only_Quad then -- Put in four hard spaces. Output_Text (Output_Object, "    "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 4; -- Output_Object.Disp_Large_Char_Count := ; end if; else -- Emulate all. Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; for I in 1 .. Output_Object.Tab_Stops.Number loop if Output_Object.Tab_Stops.Stops(I).Stop >= Output_Object.Disp_Char_Count then for J in Output_Object.Disp_Char_Count+1 .. Output_Object.Tab_Stops.Stops(I).Stop loop Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end loop; exit; end if; end loop; -- If we drop out without finding a tab, we just use the -- single space already written. -- Output_Object.Disp_Large_Char_Count := ; end if; end Tab; procedure Special_Character (Output_Object : in out HTML_Output_Type; Char : in ARM_Output.Special_Character_Type) is -- Output an special character. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Conditional_Space then Output_Object.Conditional_Space := False; Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; -- Output_Object.Disp_Large_Char_Count := ; end if; case Char is when ARM_Output.EM_Dash => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "—"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "--"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 2; end if; when ARM_Output.EN_Dash => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "–"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "-"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; when ARM_Output.GEQ => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "≥"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, ">="); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 2; end if; when ARM_Output.LEQ => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "≤"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "<="); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 2; end if; when ARM_Output.NEQ => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "≠"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "/="); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 2; end if; when ARM_Output.PI => if Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode then Output_Text (Output_Object, "π"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "PI"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 2; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 2; end if; when ARM_Output.Left_Ceiling => if FALSE and (Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode) then -- This character doesn't display on US Windows 2000/XP. Output_Text (Output_Object, "⌈"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "Ceiling("); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 8; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; end if; when ARM_Output.Right_Ceiling => if FALSE and (Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode) then -- This character doesn't display on US Windows 2000/XP. Output_Text (Output_Object, "⌉"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, ")"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; when ARM_Output.Left_Floor => if FALSE and (Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode) then -- This character doesn't display on US Windows 2000/XP. Output_Text (Output_Object, "⌊"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, "Floor("); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 6; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; end if; when ARM_Output.Right_Floor => if FALSE and (Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode) then -- This character doesn't display on US Windows 2000/XP. Output_Text (Output_Object, "⌋"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; else Output_Text (Output_Object, ")"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; when ARM_Output.Thin_Space => if FALSE and (Output_Object.HTML_Kind > HTML_3 and Output_Object.Use_Unicode) then -- This character doesn't display on US Windows 2000/XP. Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Left_Quote => if Output_Object.HTML_Kind > HTML_3 then Output_Text (Output_Object, "‘"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, "`"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Right_Quote => if Output_Object.HTML_Kind > HTML_3 then Output_Text (Output_Object, "’"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, "'"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Left_Double_Quote => if Output_Object.HTML_Kind > HTML_3 then Output_Text (Output_Object, "“"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, """"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Right_Double_Quote => if Output_Object.HTML_Kind > HTML_3 then Output_Text (Output_Object, "”"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, """"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Small_Dotless_I => if Output_Object.HTML_Kind > HTML_3 then --and Output_Object.Use_Unicode then -- We'll use it if it might be supported. Output_Text (Output_Object, "ı"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, "i"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; --Output_Object.Disp_Large_Char_Count := ; when ARM_Output.Capital_Dotted_I => if Output_Object.HTML_Kind > HTML_3 then --and Output_Object.Use_Unicode then -- We'll use it if it might be supported. Output_Text (Output_Object, "İ"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; else Output_Text (Output_Object, "I"); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; end if; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; end case; Output_Object.Any_Nonspace := True; Output_Object.Last_was_Space := False; end Special_Character; procedure Unicode_Character (Output_Object : in out HTML_Output_Type; Char : in ARM_Output.Unicode_Type) is -- Output a Unicode character, with code position Char. Char_Code : constant String := ARM_Output.Unicode_Type'Image(Char); begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.HTML_Kind = HTML_3 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unicode not available for HTML 3"); end if; if Output_Object.Conditional_Space then Output_Object.Conditional_Space := False; Output_Text (Output_Object, " "); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; --Output_Object.Disp_Large_Char_Count := ; end if; -- We don't check if this is valid, we just use it. So be sparing! Output_Text (Output_Object, "&#" & Char_Code(2..Char_Code'Length) & ';'); Output_Object.Disp_Char_Count := Output_Object.Disp_Char_Count + 1; Output_Object.Disp_Large_Char_Count := Output_Object.Disp_Large_Char_Count + 1; -- Assume it is large. Output_Object.Any_Nonspace := True; Output_Object.Last_was_Space := False; end Unicode_Character; procedure End_Hang_Item (Output_Object : in out HTML_Output_Type) is -- Marks the end of a hanging item. Call only once per paragraph. -- Raises Not_Valid_Error if the paragraph style is not in -- Text_Prefixed_Style_Subtype, or if this has already been -- called for the current paragraph, or if the paragraph was started -- with No_Prefix = True. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.Paragraph_Style not in ARM_Output.Text_Prefixed_Style_Subtype then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not a hanging paragraph - " & ARM_Output.Paragraph_Style_Type'Image(Output_Object.Paragraph_Style)); end if; if Output_Object.Saw_Hang_End then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already saw the end of the hanging part"); end if; Output_Object.Saw_Hang_End := True; if Output_Object.HTML_Kind = HTML_3 then case Output_Object.Paragraph_Style is -- Part of a definition list. when ARM_Output.Small_Giant_Hanging | ARM_Output.Small_Wide_Hanging | ARM_Output.Small_Medium_Hanging | ARM_Output.Small_Narrow_Hanging | ARM_Output.Small_Hanging_in_Bulleted | ARM_Output.Small_Enumerated => Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); when others => Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); end case; elsif Output_Object.HTML_Kind = HTML_4_Only then declare Saved_Format : ARM_Output.Format_Type; begin -- Save original format: Saved_Format := (Bold => Output_Object.Is_Bold, Italic => Output_Object.Is_Italic, Font => Output_Object.Font, Size => Output_Object.Size, Color => Output_Object.Color, Change => Output_Object.Change, Version => Output_Object.Version, Added_Version => Output_Object.Added_Version, Location => Output_Object.Location); -- Close any open formatting (can't leave it open across a DIV): Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Size => 0, Color => ARM_Output.Default, Change => ARM_Output.None, Version => '0', Added_Version => '0', Location => ARM_Output.Normal)); -- This has to be a hanging style, so we ignore other cases: Ada.Text_IO.Put (Output_Object.Output_File, "
"); -- If the prefix is too long, add a
. A "unit" is 2.0 ems; -- a large character is 0.65 ems; and a small character is 0.4 ems. -- That should be quite conservative. --Ada.Text_IO.Put_Line("Break hang check: large chars=" & Natural'Image(Output_Object.Disp_Large_Char_Count) & --" small chars=" & Natural'Image(Output_Object.Disp_Char_Count - Output_Object.Disp_Large_Char_Count) & --" Hang_Outdent=" & Natural'Image(Paragraph_Info(Output_Object.Paragraph_Format).Hang_Outdent)); if (Output_Object.Disp_Large_Char_Count*13) + ((Output_Object.Disp_Char_Count-Output_Object.Disp_Large_Char_Count)*8) > Paragraph_Info(Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent).Hang_Outdent*40 then Ada.Text_IO.Put_Line (Output_Object.Output_File, "
"); -- We use "clear=left" so that the next line always -- starts at the left margin. This shouldn't be necessary, -- but I've seen cases where it was. else Ada.Text_IO.New_Line (Output_Object.Output_File); end if; -- Reopen any formatting (using the previously saved values): Text_Format (Output_Object, Format => Saved_Format); end; else -- HTML 4 Compatibility -- We have to close and reopen the font info here, so that we -- properly nest these operations to pass the WC3 validator. Put_End_Compatibility_Font_Info (Output_Object, Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); -- This has to be a hanging style, so we ignore other cases: Ada.Text_IO.Put (Output_Object.Output_File, "
"); Put_Compatibility_Font_Info (Output_Object, Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent); end if; Paragraph_Used(Output_Object.Paragraph_Style, Output_Object.Paragraph_Indent) := True; Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. end End_Hang_Item; procedure New_Column (Output_Object : in out HTML_Output_Type) is -- Output a column break. -- Raises Not_Valid_Error if in a paragraph, or if the number of -- columns is 1. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "New Column in paragraph"); end if; if Output_Object.Column_Count <= 1 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in a multi-column area"); end if; if Output_Object.Column_Count >= 4 then Output_Object.Current_Column := Output_Object.Current_Column + 1; Output_Object.Current_Item := 1; -- else ignore it, no columns will be used. end if; end New_Column; procedure Text_Format (Output_Object : in out HTML_Output_Type; Format : in ARM_Output.Format_Type) is -- Change the text format so that all of the properties are as specified. -- Note: Changes to these properties ought be stack-like; that is, -- Bold on, Italic on, Italic off, Bold off is OK; Bold on, Italic on, -- Bold off, Italic off should be avoided (as separate commands). use type ARM_Output.Change_Type; use type ARM_Output.Location_Type; use type ARM_Output.Size_Type; use type ARM_Output.Color_Type; function Change_Needs_Close_or_Open return Boolean is -- Returns True if "Change" needs to open or close something, based -- on the current values of Output_Object. begin return (Format.Change /= Output_Object.Change or else Format.Version /= Output_Object.Version or else Format.Added_Version /= Output_Object.Added_Version); end Change_Needs_Close_or_Open; function Font_Needs_Close_or_Open return Boolean is -- Returns True if "Font" needs to close something, based -- on the current values of Output_Object and the new value. -- Note that this depends on whether the Change needs to open -- or close something; if it does, we need to close and reopen -- the font even if it is not changing. begin return (ARM_Output."/=" (Format.Font, Output_Object.Font) or else Change_Needs_Close_or_Open); end Font_Needs_Close_or_Open; function Location_Needs_Close_or_Open return Boolean is -- Returns True if "Location" needs to close something, based -- on the current values of Output_Object and the new value. -- Note that this depends on whether the Change or Font needs -- to open or close something; if they do, we need to close and -- reopen the location even if it is not changing. begin return Format.Location /= Output_Object.Location or else Change_Needs_Close_or_Open or else Font_Needs_Close_or_Open; end Location_Needs_Close_or_Open; function Color_Needs_Close_or_Open return Boolean is -- Returns True if "Color" needs to close something, based -- on the current values of Output_Object, and the new value. -- Note that this depends on whether the Change, Font, -- or Location needs to open or close something; if they do, -- we need to close the size even if it is not changing. begin return (Format.Color /= Output_Object.Color or else Change_Needs_Close_or_Open or else Font_Needs_Close_or_Open or else Location_Needs_Close_or_Open); end Color_Needs_Close_or_Open; function Size_Needs_Close_or_Open return Boolean is -- Returns True if "Size" needs to close something, based -- on the current values of Output_Object, and the new value. -- Note that this depends on whether the Change, Color, Font, -- or Location needs to open or close something; if they do, -- we need to close the size even if it is not changing. begin return (Format.Size /= Output_Object.Size or else Change_Needs_Close_or_Open or else Font_Needs_Close_or_Open or else Location_Needs_Close_or_Open or else Color_Needs_Close_or_Open); end Size_Needs_Close_or_Open; function Italic_Needs_Close_or_Open return Boolean is -- Returns True if "Italic" needs to close something, based -- on the current values of Output_Object, and the new value. -- Note that this depends on whether the Change, Font, Color, -- Location, or Size needs to open or close something; if they do, -- we need to close the italics even if it is not changing. begin return (Format.Italic /= Output_Object.Is_Italic or else Change_Needs_Close_or_Open or else Font_Needs_Close_or_Open or else Location_Needs_Close_or_Open or else Size_Needs_Close_or_Open or else Color_Needs_Close_or_Open); end Italic_Needs_Close_or_Open; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- We do these in this order so that the changes are stacked properly. -- Note that we have to open and close stuff that is not changing -- in order to get proper nesting in all cases. if Output_Object.Is_Bold and then ((not Format.Bold) or else Italic_Needs_Close_or_Open) then -- The latter so that nesting is preserved; we'll reopen -- the boldfacing on the other side if needed. Otherwise, when -- Bold remains on, we'd leave the markup open but close some outer -- item. That's wrong (even though many browsers can handle it). Output_Text (Output_Object, ""); Output_Object.Is_Bold := False; end if; if Output_Object.Is_Italic and then ((not Format.Italic) or else Size_Needs_Close_or_Open) then -- The latter so that nesting is preserved; we'll reopen -- the italics on the other side in that case. Output_Text (Output_Object, ""); Output_Object.Is_Italic := False; end if; if Format.Size /= Output_Object.Size or else Color_Needs_Close_or_Open then -- The latter so that nesting is preserved; we'll reopen -- the size on the other side in that case. if Output_Object.Size /= 0 then if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; Output_Object.Size := 0; -- That's the size now. end if; end if; if Format.Color /= Output_Object.Color or else Location_Needs_Close_or_Open then -- The latter so that nesting is preserved; we'll reopen -- the size on the other side in that case. if Output_Object.Color /= ARM_Output.Default then if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; Output_Object.Color := ARM_Output.Default; -- That's the color now. end if; end if; if Format.Location /= Output_Object.Location or else Change_Needs_Close_or_Open then -- The latter so that nesting is preserved; we'll reopen -- the location on the other side in that case. case Output_Object.Location is when ARM_Output.Superscript => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; when ARM_Output.Subscript => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; when ARM_Output.Normal => null; end case; Output_Object.Location := ARM_Output.Normal; -- That's the location now. end if; if ARM_Output."/=" (Format.Font, Output_Object.Font) or else Change_Needs_Close_or_Open then -- The latter so that nesting is preserved; we'll reopen -- the font on the other side in that case. case Output_Object.Font is when ARM_Output.Default => null; when ARM_Output.Fixed => Output_Text (Output_Object, ""); when ARM_Output.Roman => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else null; -- Default, currently. --Output_Text (Output_Object, ""); end if; when ARM_Output.Swiss => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; end case; Output_Object.Font := ARM_Output.Default; -- We're now in the default state. end if; if Format.Change /= Output_Object.Change or else Format.Version /= Output_Object.Version or else Format.Added_Version /= Output_Object.Added_Version then case Output_Object.Change is when ARM_Output.Insertion => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); Output_Text (Output_Object, ""); end if; -- Note: We need to follow these with a space so that -- we don't get words running together for indexing -- purposes (Google, Ada Indexer). That's only a concern -- for deletions directly following insertions (at least in -- the absence of nesting), so we only add the extra space -- after insertions. RTF needs insertions and deletions -- without spaces to work properly, thus the source does not -- have them. -- If the last character of the displayed text is a space, -- we don't need this, and don't generate it. We do -- generate it for punctuation, as we want a space following -- that in general. -- If the next visible character is not in some sort of -- change section, we'd prefer to not generate -- the space, but there is no obvious way to determine that -- (we don't know when the command ends here). -- We can, however, generate a conditional space that is -- not generated if the next visible character is a space -- or punctuation (we don't usually want a space *before* -- punctuation). if Output_Object.Last_was_Space then null; else Output_Object.Conditional_Space := True; end if; when ARM_Output.Deletion => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); Output_Text (Output_Object, ""); end if; when ARM_Output.Both => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); --Output_Text (Output_Object, ""); -- CSS2 doesn't allow multiple decorations in a single definition, so we have -- to nest them. But that might not be right, either (it works on IE). Output_Text (Output_Object, ""); end if; if Output_Object.Last_was_Space then -- See above for reasons for this. null; else Output_Object.Conditional_Space := True; end if; when ARM_Output.None => null; end case; case Format.Change is when ARM_Output.Insertion => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); Output_Text (Output_Object, ""); Revision_Used(Format.Version) := True; end if; when ARM_Output.Deletion => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); Output_Text (Output_Object, ""); Revision_Used(Format.Version) := True; end if; when ARM_Output.Both => if Output_Object.HTML_Kind = HTML_3 then Output_Text (Output_Object, ""); else --Output_Text (Output_Object, ""); --Output_Text (Output_Object, ""); -- CSS2 doesn't allow multiple decorations in a single definition, so we have -- to nest them. But that might not be right, either (it works on IE). Output_Text (Output_Object, ""); Output_Text (Output_Object, ""); Revision_Used(Format.Added_Version) := True; Revision_Used(Format.Version) := True; end if; when ARM_Output.None => null; end case; Output_Object.Change := Format.Change; Output_Object.Version := Format.Version; Output_Object.Added_Version := Format.Added_Version; end if; if ARM_Output."/=" (Format.Font, Output_Object.Font) then case Format.Font is when ARM_Output.Default => null; when ARM_Output.Fixed => Output_Text (Output_Object, ""); when ARM_Output.Roman => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else null; -- Default, currently. --Output_Text (Output_Object, ""); end if; when ARM_Output.Swiss => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); else Output_Text (Output_Object, SWISS_FONT_CODE); end if; end case; Output_Object.Font := Format.Font; end if; if Format.Location /= Output_Object.Location then -- Note: Location needs to be changed before size, as they -- typically are changed together, and and reset the -- size. case Format.Location is when ARM_Output.Superscript => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); -- This is a bit larger than +1; the text is usually too small. else Output_Text (Output_Object, ""); end if; when ARM_Output.Subscript => if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, ""); -- This is a bit larger than +1; the text is usually too small. else Output_Text (Output_Object, ""); end if; when ARM_Output.Normal => null; end case; Output_Object.Location := Format.Location; end if; if Format.Color /= Output_Object.Color then if Output_Object.HTML_Kind = HTML_4_Only then case Format.Color is when ARM_Output.Default => null; when ARM_Output.Black => Output_Text (Output_Object, ""); when ARM_Output.Red => Output_Text (Output_Object, ""); when ARM_Output.Green => Output_Text (Output_Object, ""); when ARM_Output.Blue => Output_Text (Output_Object, ""); end case; else case Format.Color is when ARM_Output.Default => null; when ARM_Output.Black => Output_Text (Output_Object, ""); when ARM_Output.Red => Output_Text (Output_Object, ""); when ARM_Output.Green => Output_Text (Output_Object, ""); when ARM_Output.Blue => Output_Text (Output_Object, ""); end case; end if; Output_Object.Color := Format.Color; end if; if Format.Size /= Output_Object.Size then if Output_Object.HTML_Kind = HTML_4_Only then case Format.Size is when 0 => null; -- Do nothing. when 1 => Output_Text (Output_Object, ""); when 2 => Output_Text (Output_Object, ""); when 3 => Output_Text (Output_Object, ""); when 4 => Output_Text (Output_Object, ""); when 5 => Output_Text (Output_Object, ""); when -1 => Output_Text (Output_Object, ""); when -2 => Output_Text (Output_Object, ""); when -3 => Output_Text (Output_Object, ""); when -4 => Output_Text (Output_Object, ""); when -5 => Output_Text (Output_Object, ""); when others => -- Too much change: if Format.Size > 0 then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; end case; else -- HTML sizes are 1..7, with a default of 3. So we limit the changes. if Format.Size > 0 then if Format.Size > 5 then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; elsif Format.Size < 0 then if Format.Size < -4 then Output_Text (Output_Object, ""); else Output_Text (Output_Object, ""); end if; -- else Format.Size=0, nothing to do. end if; end if; Output_Object.Size := Format.Size; end if; if Format.Italic and (not Output_Object.Is_Italic) then Output_Text (Output_Object, ""); Output_Object.Is_Italic := True; end if; if Format.Bold and (not Output_Object.Is_Bold) then Output_Text (Output_Object, ""); Output_Object.Is_Bold := True; end if; end Text_Format; procedure Clause_Reference (Output_Object : in out HTML_Output_Type; Text : in String; Clause_Number : in String) is -- Generate a reference to a clause in the standard. The text of -- the reference is "Text", and the number of the clause is -- Clause_Number. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Clause_Number = "X.X" then -- Link to a dead clause, just output the text (presumably this -- is deleted). Ordinary_Text (Output_Object, Text); else Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end if; end Clause_Reference; procedure Index_Target (Output_Object : in out HTML_Output_Type; Index_Key : in Natural) is -- Generate a index target. This marks the location where an index -- reference occurs. Index_Key names the index item involved. -- For hyperlinked formats, this should generate a link target; -- for other formats, nothing is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- Insert an anchor: Output_Text (Output_Object, ""); end Index_Target; procedure Index_Reference (Output_Object : in out HTML_Output_Type; Text : in String; Index_Key : in Natural; Clause_Number : in String) is -- Generate a reference to an index target in the standard. The text -- of the reference is "Text", and Index_Key and Clause_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end Index_Reference; procedure DR_Reference (Output_Object : in out HTML_Output_Type; Text : in String; DR_Number : in String) is -- Generate a reference to an DR from the standard. The text -- of the reference is "Text", and DR_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; declare Num : Integer := Integer'Value(DR_Number(DR_Number'Last-3 .. DR_Number'Last)); begin Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end DR_Reference; function Folded_AI95_Number (AI_String : in String) return String is -- Internal routine. -- Calculate the "folded" AI number from the full version. -- AI_String should be in the form "AIzz-00xxx-yy", where -yy, 00, -- and zz are optional, and 'zz' = 95 if given. Result : String(1..5); Hyphen_1 : Natural := Ada.Strings.Fixed.Index (AI_String, "-"); Hyphen_2 : Natural; begin if Hyphen_1 = 0 or else AI_String'Last < Hyphen_1+3 then Result := "00001"; Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad AI reference " & AI_String); elsif Hyphen_1 = AI_String'First+4 and then AI_String(AI_String'First..Hyphen_1-1) /= "AI95" then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unknown AI reference " & AI_String); Result := "00001"; elsif Hyphen_1 = AI_String'First+2 and then AI_String(AI_String'First..Hyphen_1-1) /= "AI" then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Unknown short AI reference " & AI_String); Result := "00001"; else Hyphen_2 := Ada.Strings.Fixed.Index (AI_String(Hyphen_1+1..AI_String'Last), "-"); if Hyphen_2 = 0 then if AI_String'Last = Hyphen_1+5 then Result := AI_String(Hyphen_1+1 .. Hyphen_1+5); elsif AI_String'Last = Hyphen_1+4 then Result(2..5) := AI_String(Hyphen_1+1 .. Hyphen_1+4); Result(1) := '0'; elsif AI_String'Last = Hyphen_1+3 then Result(3..5) := AI_String(Hyphen_1+1 .. Hyphen_1+3); Result(1) := '0'; Result(2) := '0'; else Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "AI reference too wrong length " & AI_String); Result := "00001"; end if; else if (Hyphen_2-1) - (Hyphen_1+1) = 5-1 then Result := AI_String (Hyphen_1+1 .. Hyphen_2-1); elsif (Hyphen_2-1) - (Hyphen_1+1) = 4-1 then Result(2..5) := AI_String (Hyphen_1+1 .. Hyphen_2-1); Result(1) := '0'; elsif (Hyphen_2-1) - (Hyphen_1+1) = 3-1 then Result(3..5) := AI_String (Hyphen_1+1 .. Hyphen_2-1); Result(1) := '0'; Result(2) := '0'; else Result := "00001"; Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad AI reference (hyphen dist) " & AI_String); end if; if AI_String'Last < Hyphen_2+1 or else AI_String'Last > Hyphen_2+2 then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad AI alternative reference " & AI_String); elsif AI_String'Last = Hyphen_2+1 then Result(1) := Character'Pred(AI_String(Hyphen_2+1)); elsif AI_String'Last = Hyphen_2+2 and then AI_String(Hyphen_2+1) = '0' then Result(1) := Character'Pred(AI_String(Hyphen_2+2)); elsif AI_String'Last = Hyphen_2+2 and then AI_String(Hyphen_2+1) = '1' then if AI_String(Hyphen_2+2) = '0' then Result(1) := '9'; else Result(1) := Character'Val(Character'Pos(AI_String(Hyphen_2+2)) - Character'Pos('1') + Character'Pos('A')); end if; elsif AI_String'Last = Hyphen_2+2 and then AI_String(Hyphen_2+1) = '2' then Result(1) := Character'Val(Character'Pos(AI_String(Hyphen_2+2)) - Character'Pos('1') + Character'Pos('A') + 10); else Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad AI alternative reference " & AI_String); end if; end if; end if; return Result; end Folded_AI95_Number; procedure AI_Reference (Output_Object : in out HTML_Output_Type; Text : in String; AI_Number : in String) is -- Generate a reference to an AI from the standard. The text -- of the reference is "Text", and AI_Number denotes -- the target (in unfolded format). For hyperlinked formats, this should -- generate a link; for other formats, the text alone is generated. -- -- We assume AI number is of the form: -- ZZZZ-nnnn-m whre ZZZZ=AI05, AI12, or SI99, nnnn is a four digit number, -- and -m is an optional number (-1 is used if it is omitted); or -- AIzz-nnnnn-mm where AIzz=AI95 or AI (meaning AI95); -- nnnnn is a five digit number, and -mm is an optional two digit number. -- We raise Not_Valid_Error otherwise. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if AI_Number'Length > 5 and then AI_Number(AI_Number'First..AI_Number'First+4) = "AI12-" then -- AI12: if AI_Number'Length >= 9 then if AI_Number(AI_Number'First+5) not in '0'..'9' or else AI_Number(AI_Number'First+6) not in '0'..'9' or else AI_Number(AI_Number'First+7) not in '0'..'9' or else AI_Number(AI_Number'First+8) not in '0'..'9' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad number in AI12 number: " & AI_Number); end if; end if; if AI_Number'Length = 9 then Output_Text (Output_Object, " 5 and then AI_Number(AI_Number'First..AI_Number'First+4) = "AI05-" then -- AI05: if AI_Number'Length >= 9 then if AI_Number(AI_Number'First+5) not in '0'..'9' or else AI_Number(AI_Number'First+6) not in '0'..'9' or else AI_Number(AI_Number'First+7) not in '0'..'9' or else AI_Number(AI_Number'First+8) not in '0'..'9' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad number in AI05 number: " & AI_Number); end if; end if; if AI_Number'Length = 9 then Output_Text (Output_Object, " 5 and then AI_Number(AI_Number'First..AI_Number'First+4) = "SI99-" then if AI_Number'Length >= 9 then if AI_Number(AI_Number'First+5) not in '0'..'9' or else AI_Number(AI_Number'First+6) not in '0'..'9' or else AI_Number(AI_Number'First+7) not in '0'..'9' or else AI_Number(AI_Number'First+8) not in '0'..'9' then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Bad number in SI99 number: " & AI_Number); end if; end if; if AI_Number'Length = 9 then Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end AI_Reference; procedure Local_Target (Output_Object : in out HTML_Output_Type; Text : in String; Target : in String) is -- Generate a local target. This marks the potential target of local -- links identified by "Target". Text is the text of the target. -- For hyperlinked formats, this should generate a link target; -- for other formats, only the text is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- Insert an anchor: Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end Local_Target; procedure Local_Link (Output_Object : in out HTML_Output_Type; Text : in String; Target : in String; Clause_Number : in String) is -- Generate a local link to the target and clause given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- Insert an anchor: Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end Local_Link; procedure Local_Link_Start (Output_Object : in out HTML_Output_Type; Target : in String; Clause_Number : in String) is -- Generate a local link to the target and clause given. -- The link will surround text until Local_Link_End is called. -- Local_Link_End must be called before this routine can be used again. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.In_Local_Link then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Already in a local link"); end if; Output_Object.In_Local_Link := True; -- Insert an anchor: Output_Text (Output_Object, ""); end Local_Link_Start; procedure Local_Link_End (Output_Object : in out HTML_Output_Type; Target : in String; Clause_Number : in String) is -- End a local link for the target and clause given. -- This must be in the same paragraph as the Local_Link_Start. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if not Output_Object.In_Local_Link then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in a local link"); end if; Output_Text (Output_Object, ""); Output_Object.In_Local_Link := False; end Local_Link_End; procedure URL_Link (Output_Object : in out HTML_Output_Type; Text : in String; URL : in String) is -- Generate a link to the URL given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; -- Insert an anchor: Output_Text (Output_Object, ""); Ordinary_Text (Output_Object, Text); Output_Text (Output_Object, ""); end URL_Link; procedure Picture (Output_Object : in out HTML_Output_Type; Name : in String; Descr : in String; Alignment : in ARM_Output.Picture_Alignment; Height, Width : in Natural; Border : in ARM_Output.Border_Kind) is -- Generate a picture. -- Name is the (simple) file name of the picture; Descr is a -- descriptive name for the picture (it will appear in some web -- browsers). -- We assume that it is a .PNG or .JPG and that it will be present -- in the same directory as the output files. -- Alignment specifies the picture alignment. -- Height and Width specify the picture size in pixels. -- Border specifies the kind of border. procedure Make_Img (Extra_Attribs : in String) is H : constant String := Natural'Image(Height); W : constant String := Natural'Image(Width); begin Output_Text (Output_Object, " Output_Text (Output_Object, " border=""0"">"); when ARM_Output.Thin => Output_Text (Output_Object, " border=""1"">"); when ARM_Output.Thick => Output_Text (Output_Object, " border=""2"">"); end case; end Make_Img; begin if not Output_Object.Is_Valid then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not valid object"); end if; case Alignment is when ARM_Output.Inline => if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.HTML_Kind = HTML_3 then Make_Img (""); else Make_Img (" style=""margin-left: 0.3em; margin-right: 0.3em"""); end if; when ARM_Output.Float_Left => if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.HTML_Kind = HTML_3 then Make_Img (" align=""left"""); else Make_Img (" align=""left"" style=""margin-right: 0.3em"""); -- Space on right only; left should align with containing -- margin. end if; when ARM_Output.Float_Right => if not Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "Not in paragraph"); end if; if Output_Object.HTML_Kind = HTML_3 then Make_Img (" align=""right"""); else Make_Img (" align=""right"" style=""margin-left: 0.3em"""); -- Space on right only; left should align with containing -- margin. end if; when ARM_Output.Alone_Left => if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "
"); else Output_Text (Output_Object, "

"); end if; Make_Img(""); if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "

"); else Output_Text (Output_Object, "

"); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. when ARM_Output.Alone_Right => if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "
"); else Output_Text (Output_Object, ""); end if; Make_Img(""); if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "
"); else Output_Text (Output_Object, ""); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. when ARM_Output.Alone_Center => if Output_Object.Is_In_Paragraph then Ada.Exceptions.Raise_Exception (ARM_Output.Not_Valid_Error'Identity, "In paragraph"); end if; if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "
"); else Output_Text (Output_Object, "
"); end if; Make_Img(""); if Output_Object.HTML_Kind = HTML_4_Only then Output_Text (Output_Object, "
"); else Output_Text (Output_Object, ""); end if; Ada.Text_IO.New_Line (Output_Object.Output_File); Output_Object.Char_Count := 0; Output_Object.Disp_Char_Count := 0; Output_Object.Disp_Large_Char_Count := 0; Output_Object.Any_Nonspace := False; Output_Object.Last_Was_Space := True; -- Start of line. Output_Object.Conditional_Space := False; -- Don't need it here. end case; end Picture; begin -- Define the styles: -- Normal: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Normal, I) := (Defined => True, Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Wide_Above: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Wide_Above, I) := (Defined => True, Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 6, After => 6); end loop; -- Header: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Header, I) := (Defined => True, Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 0); end loop; -- Small: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Small, I) := (Defined => True, Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Small_Wide_Above: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Small_Wide_Above, I) := (Defined => True, Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 6, After => 6); end loop; -- Small Header: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Small_Header, I) := (Defined => True, Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 0); end loop; -- Examples: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Examples, I) := (Defined => True, Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Fixed, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Small Examples: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Small_Examples, I) := (Defined => True, Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Fixed, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Swiss Examples: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Swiss_Examples, I) := (Defined => True, Tag => DIV, Size => 0, -- 18 Font => ARM_Output.Swiss, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Small Swiss Examples: for I in ARM_Output.Paragraph_Indent_Type loop Paragraph_Info(ARM_Output.Small_Swiss_Examples, I) := (Defined => True, Tag => DIV, Size => -1, -- 15 Font => ARM_Output.Swiss, Indent => Natural(I), Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 6); -- 120 end loop; -- Bulleted: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Bulleted, I) := (Defined => True, Tag => UL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 1, Hang_Outdent => 0, Before => 0, After => 5); end loop; -- Nested Bulleted: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Nested_Bulleted, I) := (Defined => True, Tag => UL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 1, Hang_Outdent => 0, Before => 0, After => 5); end loop; -- Small Bulleted: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Bulleted, I) := (Defined => True, Tag => UL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 1, Hang_Outdent => 0, Before => 0, After => 5); end loop; -- Small Nested Bulleted: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Nested_Bulleted, I) := (Defined => True, Tag => UL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I), Right_Indent => 1, Hang_Outdent => 0, Before => 0, After => 5); end loop; -- Enumerated: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Enumerated, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-1, Right_Indent => 1, Hang_Outdent => 1, Before => 0, After => 5); end loop; -- Small Enumerated: -- Note: Indent = 0 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Enumerated, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-1, Right_Indent => 1, Hang_Outdent => 1, Before => 0, After => 5); end loop; -- Giant Hanging -- Note: Indent < 4 is not allowed. for I in 4 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Giant_Hanging, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-4, Right_Indent => 0, Hang_Outdent => 4, Before => 0, After => 6); end loop; -- Small Giant Hanging: -- Note: Indent < 4 is not allowed. for I in 4 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Giant_Hanging, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-4, Right_Indent => 0, Hang_Outdent => 4, Before => 0, After => 6); end loop; -- Wide Hanging -- Note: Indent < 3 is not allowed. for I in 3 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Wide_Hanging, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-3, Right_Indent => 0, Hang_Outdent => 3, Before => 0, After => 6); end loop; -- Small Wide Hanging: -- Note: Indent < 3 is not allowed. for I in 3 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Wide_Hanging, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-3, Right_Indent => 0, Hang_Outdent => 3, Before => 0, After => 6); end loop; -- Medium Hanging -- Note: Indent < 2 is not allowed. for I in 2 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Medium_Hanging, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-2, Right_Indent => 0, Hang_Outdent => 2, Before => 0, After => 6); end loop; -- Small Medium Hanging: -- Note: Indent < 2 is not allowed. for I in 2 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Medium_Hanging, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-2, Right_Indent => 0, Hang_Outdent => 2, Before => 0, After => 6); end loop; -- Narrow Hanging -- Note: Indent < 1 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Narrow_Hanging, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-1, Right_Indent => 0, Hang_Outdent => 1, Before => 0, After => 6); end loop; -- Small Narrow Hanging: -- Note: Indent < 1 is not allowed. for I in 1 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Narrow_Hanging, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-1, Right_Indent => 0, Hang_Outdent => 1, Before => 0, After => 6); end loop; -- Hanging in Bulleted -- Note: Indent < 2 is not allowed. for I in 2 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Hanging_in_Bulleted, I) := (Defined => True, Tag => DL, Size => 0, -- 18 Font => ARM_Output.Default, Indent => Natural(I)-2, Right_Indent => 1, Hang_Outdent => 2, Before => 0, After => 5); end loop; -- Small Hanging in Bulleted -- Note: Indent < 2 is not allowed. for I in 2 .. ARM_Output.Paragraph_Indent_Type'Last loop Paragraph_Info(ARM_Output.Small_Hanging_in_Bulleted, I) := (Defined => True, Tag => DL, Size => -1, -- 15 Font => ARM_Output.Default, Indent => Natural(I)-2, Right_Indent => 1, Hang_Outdent => 2, Before => 0, After => 5); end loop; -- Index. Only define the form that we'll use. Paragraph_Info(ARM_Output.Index, 0) := (Defined => True, Tag => DIV, Size => 0, Font => ARM_Output.Default, Indent => 0, Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 0); -- Syntax Summary. Only define the form that we'll use. Paragraph_Info(ARM_Output.Syntax_Summary, 1) := (Defined => True, Tag => DIV, Size => -1, Font => ARM_Output.Default, Indent => 1, Right_Indent => 0, Hang_Outdent => 0, Before => 0, After => 4); -- Title. Only define the form that we'll use. Paragraph_Info(ARM_Output.Title, 0) := (Defined => True, Tag => DIV, Size => 3, -- 36 Font => ARM_Output.Default, Indent => 0, Right_Indent => 0, Hang_Outdent => 0, Before => 6, After => 6); end ARM_HTML; org.adaic.arm_form/progs/arm_html.ads0000755000175200010010000007251712273462240017115 0ustar stepheNonewith ARM_Output, ARM_Contents, Ada.Text_IO; -- private with Ada.Strings.Unbounded; package ARM_HTML is -- -- Ada reference manual formatter (ARM_Form). -- -- This package defines the HTML output object. -- Output objects are responsible for implementing the details of -- a particular format. -- -- --------------------------------------- -- Copyright 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 4/19/00 - RLB - Created base package. -- 4/21/00 - RLB - Added line break and hard space routines. -- 4/24/00 - RLB - Added DR references and Insert/Delete text formats. -- 4/25/00 - RLB - Added size to format. -- 5/10/00 - RLB - Added End_Hang_Item. -- 5/12/00 - RLB - Added No_Prefix to Start_Paragraph. -- 5/13/00 - RLB - Added Special_Character. -- 5/17/00 - RLB - Added New_Page. -- 5/22/00 - RLB - Added Includes_Changes to Create. -- 5/23/00 - RLB - Added Set_Column and New_Column. -- - Added Tab_Info and Tab_Stops. -- 5/24/00 - RLB - Added Location to Text_Format. -- - RLB - Added No_Breaks and Keep_with_Next to Start_Paragraph. -- 5/25/00 - RLB - Added Big_Files to Create. Added Justification. -- - RLB - Added Separator_Lines and TOC routines. -- 5/26/00 - RLB - Added table operations. -- 6/ 2/00 - RLB - Added Soft_Line_Break. -- 8/ 2/00 - RLB - Added Soft_Hyphen_Break. -- 8/ 7/00 - RLB - Added Leading flag to Start_Paragraph. -- 8/17/00 - RLB - Replaced "Leading" by "Space_After". -- 8/22/00 - RLB - Added Revised_Clause_Header. -- 9/27/00 - RLB - Added tab emulation when in the fixed font. -- - RLB - Added column emulation. -- 9/29/00 - RLB - Added Any_Nonspace flag. -- 7/18/01 - RLB - Added support for Big_Files. -- 7/18/02 - RLB - Removed Document parameter from Create, replaced by -- three strings and For_ISO boolean. -- - RLB - Added AI_Reference. -- - RLB - Added Change_Version_Type and uses. -- 9/10/04 - RLB - Added "Both" to possible changes to handle -- replacement of changed text. -- 9/14/04 - RLB - Moved Change_Version_Type to ARM_Contents. -- 5/27/05 - RLB - Added arbitrary Unicode characters. -- 1/11/06 - RLB - Eliminated dispatching Create in favor of tailored -- versions. -- 1/12/06 - RLB - Added a number of parameters to Create. -- 1/13/06 - RLB - Added new Link operations. -- 1/16/06 - RLB - Added Index_URL to Create. -- 1/27/06 - RLB - Added Tab_Emulation. -- 2/ 8/06 - RLB - Added additional parameters to the table command. -- 2/10/06 - RLB - Added even more additional parameters to the -- table command. -- - RLB - Added picture command. -- 2/19/06 - RLB - Added Number_Paragraphs flag and large letter count. -- 9/21/06 - RLB - Added Body_Font. -- 9/25/06 - RLB - Added Last_Column_Width to Start_Table. -- 10/13/06 - RLB - Added specifiable colors. -- - RLB - Added Local_Link_Start and Local_Link_End to allow -- formatting in the linked text. -- 2/ 9/07 - RLB - Changed comments on AI_Reference. -- 2/13/07 - RLB - Revised to separate style and indent information -- for paragraphs. -- 12/19/07 - RLB - Added DOS_Filename flag. -- - RLB - Added limited colors to Text_Format. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/25/11 - RLB - Added old insertion version to Revised_Clause_Header. -- 8/31/12 - RLB - Added Output_Path. -- 11/26/12 - RLB - Added subdivision names to Clause_Header and -- Revised_Clause_Header. -- 3/26/13 - RLB - Added HTML_Script to allow adding Google Analytics -- code as needed. type HTML_Output_Type is new ARM_Output.Output_Type with private; type HTML_Type is (HTML_3, -- Use only HTML 3 elements. HTML_4_Compatible, -- Use HTML 4 when needed, but try to look good on old browsers. HTML_4_Only); -- Use only HTML 4 elements (no attempt to look good on old browsers). type Tab_Emulation_Type is (Single_Space, -- Replace all tabs by a single space. Quad_Space, -- Replace all tabs by four hard spaces. Emulate_Fixed_Only, -- Emulate tabs in fixed font styles; -- replace others by a single space. Emulate_Fixed_Only_Quad,--Emulate tabs in fixed font styles; -- replace others by four hard spaces. Emulate_All); -- Replace tabs in all styles; note that -- it is unlikely that they will line -- up perfectly for non-fixed fonts. subtype Color_String is String (1..7); -- "#hhhhhh" to specify a color. procedure Create (Output_Object : in out HTML_Output_Type; Big_Files : in Boolean; File_Prefix : in String; Output_Path : in String; DOS_Filenames : in Boolean; HTML_Kind : in HTML_Type; Use_Unicode : in Boolean; Number_Paragraphs : in Boolean; Ref_URL : in String; Srch_URL : in String; Index_URL : in String; Use_Buttons : Boolean; Nav_On_Top : Boolean; Nav_On_Bottom : Boolean; Tab_Emulation : Tab_Emulation_Type; Script_HTML : String; Header_HTML : String; Footer_HTML : String; Title : in String := ""; Body_Font : ARM_Output.Font_Family_Type; Text_Color : Color_String; Background_Color : Color_String; Link_Color : Color_String; VLink_Color : Color_String; ALink_Color : Color_String); -- Create an Output_Object for a document. -- Generate a few large output files if -- Big_Files is True; otherwise generate smaller output files. -- The prefix of the output file names is File_Prefix - this -- should be no more than 5 characters allowed in file names. -- The files will be written into Output_Path. -- If DOS_Filename is true, use 8.3 file names; -- in that case, File_Prefix must be less than 4 characters in length; -- and no clause or subclause number may exceed 35 if Big_Files is False. -- The title of the document is Title. -- HTML_Kind determines the kind of HTML generated; HTML_3 works on -- every browser but has little control over formatting; -- HTML_4_Compatible has better control, but tries to make the results -- look good on older browsers; HTML_4_Only uses maximum formatting, -- but makes no attempt to look good on browsers older than IE 5.0 and -- Firefox 1.0. -- If Use_Unicode is true, Unicode characters available on US versions -- of Windows 2000 are used when appropriate; otherwise, Unicode -- characters are only used when explicitly requested with -- Unicode_Character (other characters are replaced with reasonable -- equivalents). [Note: It's known that IE on Windows 95/98/ME cannot -- display Unicode characters.] Use_Unicode has no effect if HTML_Kind -- is set to HTML_3. -- Number_Paragraphs means that paragraph numbers will be used; -- otherwise, the Number parameter to Start_Paragraph must be "". -- Ref_URL, Srch_URL, and Index_URL are the URLs (possibly relative) -- for the "References", "Search", and "Index" buttons/labels, -- respectively. If null, these buttons/labels link to sections named -- "References", "Search", and "Index"; if these do not exist, the -- buttons/labels are omitted. -- If Use_Buttons is true, button images are used, otherwise text labels -- are used for the navigation bar. -- If Nav_On_Top is true, the navigation bar will appear in the header -- of each page. If Nav_On_Bottom is true, the navigation bar will -- appear in the footer of each page. -- Tab_Emulation determines how tabs are emulated. -- Script_HTML gives self-contained HTML that will appear immediately -- before the of every page. This usually will contain -- Javascript scripts or CSS styles. The original intent was to allow -- adding the Google Analytics script to each page. -- Header_HTML gives self-contained HTML that will appear before the -- navigation bar in the header. Footer_HTML gives self-contained HTML -- that will appear after the navigation bar in the footer. -- Body_Font selects the default font for the document body. -- Text_Color specifies the default text color; Background_Color -- specifies the default background color; Link_Color specifies the -- default color of normal links; VLink_Color specifies the -- default color of visited links; and ALink_Color specifies the -- default color of active (in the act of clinking) links. procedure Close (Output_Object : in out HTML_Output_Type); -- Close an Output_Object. No further output to the object is -- allowed after this call. procedure Section (Output_Object : in out HTML_Output_Type; Section_Title : in String; Section_Name : in String); -- Start a new section. The title is Section_Title (this is -- intended for humans). The name is Section_Name (this is -- intended to be suitable to be a portion of a file name). procedure Set_Columns (Output_Object : in out HTML_Output_Type; Number_of_Columns : in ARM_Output.Column_Count); -- Set the number of columns. -- Raises Not_Valid_Error if in a paragraph. procedure Start_Paragraph (Output_Object : in out HTML_Output_Type; Style : in ARM_Output.Paragraph_Style_Type; Indent : in ARM_Output.Paragraph_Indent_Type; Number : in String; No_Prefix : in Boolean := False; Tab_Stops : in ARM_Output.Tab_Info := ARM_Output.NO_TABS; No_Breaks : in Boolean := False; Keep_with_Next : in Boolean := False; Space_After : in ARM_Output.Space_After_Type := ARM_Output.Normal; Justification : in ARM_Output.Justification_Type := ARM_Output.Default); -- Start a new paragraph. The style and indent of the paragraph is as -- specified. The (AA)RM paragraph number (which might include update -- and version numbers as well: [12.1/1]) is Number. If the format is -- a type with a prefix (bullets, hangining items), the prefix is -- omitted if No_Prefix is true. Tab_Stops defines the tab stops for -- the paragraph. If No_Breaks is True, we will try to avoid page breaks -- in the paragraph. If Keep_with_Next is true, we will try to avoid -- separating this paragraph and the next one. (These may have no -- effect in formats that don't have page breaks). Space_After -- specifies the amount of space following the paragraph. Justification -- specifies the text justification for the paragraph. Not_Valid_Error -- is raised if Tab_Stops /= NO_TABS for a hanging or bulleted format. procedure End_Paragraph (Output_Object : in out HTML_Output_Type); -- End a paragraph. procedure Category_Header (Output_Object : in out HTML_Output_Type; Header_Text : String); -- Output a Category header (that is, "Legality Rules", -- "Dynamic Semantics", etc.) -- (Note: We did not use a enumeration here to insure that these -- headers are spelled the same in all output versions). -- Raises Not_Valid_Error if in a paragraph. procedure Clause_Header (Output_Object : in out HTML_Output_Type; Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False); -- Output a Clause header. The level of the header is specified -- in Level. The Clause Number is as specified; the top-level (and -- other) subdivision names are as specified. These should appear in -- the table of contents. -- For hyperlinked formats, this should generate a link target. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. procedure Revised_Clause_Header (Output_Object : in out HTML_Output_Type; New_Header_Text : in String; Old_Header_Text : in String; Level : in ARM_Contents.Level_Type; Clause_Number : in String; Version : in ARM_Contents.Change_Version_Type; Old_Version : in ARM_Contents.Change_Version_Type; Top_Level_Subdivision_Name : in ARM_Output.Top_Level_Subdivision_Name_Kind; No_Page_Break : in Boolean := False); -- Output a revised clause header. Both the original and new text will -- be output. The level of the header is specified in Level. The Clause -- Number is as specified; the top-level (and other) subdivision names -- are as specified. These should appear in the table of contents. -- For hyperlinked formats, this should generate a link target. -- Version is the insertion version of the new text; Old_Version is -- the insertion version of the old text. -- If No_Page_Break is True, suppress any page breaks. -- Raises Not_Valid_Error if in a paragraph. procedure TOC_Marker (Output_Object : in out HTML_Output_Type; For_Start : in Boolean); -- Mark the start (if For_Start is True) or end (if For_Start is -- False) of the table of contents data. Output objects that -- auto-generate the table of contents can use this to do needed -- actions. procedure New_Page (Output_Object : in out HTML_Output_Type; Kind : ARM_Output.Page_Kind_Type := ARM_Output.Any_Page); -- Output a page break. -- Note that this has no effect on non-printing formats. -- Any_Page breaks to the top of the next page (whatever it is); -- Odd_Page_Only breaks to the top of the odd-numbered page; -- Soft_Page allows a page break but does not force one (use in -- "No_Breaks" paragraphs.) -- Raises Not_Valid_Error if in a paragraph if Kind = Any_Page or -- Odd_Page, and if not in a paragraph if Kind = Soft_Page. procedure New_Column (Output_Object : in out HTML_Output_Type); -- Output a column break. -- Raises Not_Valid_Error if in a paragraph, or if the number of -- columns is 1. procedure Separator_Line (Output_Object : in out HTML_Output_Type; Is_Thin : Boolean := True); -- Output a separator line. It is thin if "Is_Thin" is true. -- Raises Not_Valid_Error if in a paragraph. procedure Start_Table (Output_Object : in out HTML_Output_Type; Columns : in ARM_Output.Column_Count; First_Column_Width : in ARM_Output.Column_Count; Last_Column_Width : in ARM_Output.Column_Count; Alignment : in ARM_Output.Column_Text_Alignment; No_Page_Break : in Boolean; Has_Border : in Boolean; Small_Text_Size : in Boolean; Header_Kind : in ARM_Output.Header_Kind_Type); -- Starts a table. The number of columns is Columns; the first -- column has First_Column_Width times the normal column width, and -- the last column has Last_Column_Width times the normal column width. -- Alignment is the horizontal text alignment within the columns. -- No_Page_Break should be True to keep the table intact on a single -- page; False to allow it to be split across pages. -- Has_Border should be true if a border is desired, false otherwise. -- Small_Text_Size means that the contents will have the AARM size; -- otherwise it will have the normal size. -- Header_Kind determines whether the table has headers. -- This command starts a paragraph; the entire table is a single -- paragraph. Text will be considered part of the caption until the -- next table marker call. -- Raises Not_Valid_Error if in a paragraph. procedure Table_Marker (Output_Object : in out HTML_Output_Type; Marker : in ARM_Output.Table_Marker_Type); -- Marks the end of an entity in a table. -- If Marker is End_Caption, the table caption ends and the -- future text is part of the table header. -- If Marker is End_Header, the table header ends and the -- future text is part of the table body. -- If Marker is End_Row, a row in the table is completed, and another -- row started. -- If Marker is End_Item, an item in the table header or body is ended, -- and another started. -- If Marker is End_Table, the entire table is finished. -- Raises Not_Valid_Error if not in a table. -- Text output: These are only allowed after a Start_Paragraph and -- before any End_Paragraph. Raises Not_Valid_Error if not in a paragraph, -- or another error. procedure Ordinary_Text (Output_Object : in out HTML_Output_Type; Text : in String); -- Output ordinary text. -- The text must end at a word break, never in the middle of a word. procedure Ordinary_Character (Output_Object : in out HTML_Output_Type; Char : in Character); -- Output an ordinary character. -- Spaces will be used to break lines as needed. procedure Hard_Space (Output_Object : in out HTML_Output_Type); -- Output a hard space. No line break should happen at a hard space. procedure Line_Break (Output_Object : in out HTML_Output_Type); -- Output a line break. This does not start a new paragraph. -- This corresponds to a "
" in HTML. procedure Index_Line_Break (Output_Object : in out HTML_Output_Type; Clear_Keep_with_Next : in Boolean); -- Output a line break for the index. This does not start a new -- paragraph in terms of spacing. This corresponds to a "
" -- in HTML. If Clear_Keep_with_Next is true, insure that the next -- line does not require the following line to stay with it. -- Raises Not_Valid_Error if the paragraph is not in the index format. procedure Soft_Line_Break (Output_Object : in out HTML_Output_Type); -- Output a soft line break. This is a place (in the middle of a -- "word") that we allow a line break. It is usually used after -- underscores in long non-terminals. procedure Soft_Hyphen_Break (Output_Object : in out HTML_Output_Type); -- Output a soft line break, with a hyphen. This is a place (in the middle of -- a "word") that we allow a line break. If the line break is used, -- a hyphen will be added to the text. procedure Tab (Output_Object : in out HTML_Output_Type); -- Output a tab, inserting space up to the next tab stop. -- Raises Not_Valid_Error if the paragraph was created with -- Tab_Stops = ARM_Output.NO_TABS. procedure Special_Character (Output_Object : in out HTML_Output_Type; Char : in ARM_Output.Special_Character_Type); -- Output an special character. procedure Unicode_Character (Output_Object : in out HTML_Output_Type; Char : in ARM_Output.Unicode_Type); -- Output a Unicode character, with code position Char. procedure End_Hang_Item (Output_Object : in out HTML_Output_Type); -- Marks the end of a hanging item. Call only once per paragraph. -- Raises Not_Valid_Error if the paragraph style is not in -- Text_Prefixed_Style_Subtype, or if this has already been -- called for the current paragraph, or if the paragraph was started -- with No_Prefix = True. procedure Text_Format (Output_Object : in out HTML_Output_Type; Format : in ARM_Output.Format_Type); -- Change the text format so that all of the properties are as specified. -- Note: Changes to these properties ought be stack-like; that is, -- Bold on, Italic on, Italic off, Bold off is OK; Bold on, Italic on, -- Bold off, Italic off should be avoided (as separate commands). procedure Clause_Reference (Output_Object : in out HTML_Output_Type; Text : in String; Clause_Number : in String); -- Generate a reference to a clause in the standard. The text of -- the reference is "text", and the number of the clause is -- Clause_Number. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure Index_Target (Output_Object : in out HTML_Output_Type; Index_Key : in Natural); -- Generate a index target. This marks the location where an index -- reference occurs. Index_Key names the index item involved. -- For hyperlinked formats, this should generate a link target; -- for other formats, nothing is generated. procedure Index_Reference (Output_Object : in out HTML_Output_Type; Text : in String; Index_Key : in Natural; Clause_Number : in String); -- Generate a reference to an index target in the standard. The text -- of the reference is "Text", and Index_Key and Clause_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure DR_Reference (Output_Object : in out HTML_Output_Type; Text : in String; DR_Number : in String); -- Generate a reference to an DR from the standard. The text -- of the reference is "Text", and DR_Number denotes -- the target. For hyperlinked formats, this should generate -- a link; for other formats, the text alone is generated. procedure AI_Reference (Output_Object : in out HTML_Output_Type; Text : in String; AI_Number : in String); -- Generate a reference to an AI from the standard. The text -- of the reference is "Text", and AI_Number denotes -- the target (in folded format). For hyperlinked formats, this should -- generate a link; for other formats, the text alone is generated. procedure Local_Target (Output_Object : in out HTML_Output_Type; Text : in String; Target : in String); -- Generate a local target. This marks the potential target of local -- links identified by "Target". Text is the text of the target. -- For hyperlinked formats, this should generate a link target; -- for other formats, only the text is generated. procedure Local_Link (Output_Object : in out HTML_Output_Type; Text : in String; Target : in String; Clause_Number : in String); -- Generate a local link to the target and clause given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Local_Link_Start (Output_Object : in out HTML_Output_Type; Target : in String; Clause_Number : in String); -- Generate a local link to the target and clause given. -- The link will surround text until Local_Link_End is called. -- Local_Link_End must be called before this routine can be used again. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Local_Link_End (Output_Object : in out HTML_Output_Type; Target : in String; Clause_Number : in String); -- End a local link for the target and clause given. -- This must be in the same paragraph as the Local_Link_Start. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure URL_Link (Output_Object : in out HTML_Output_Type; Text : in String; URL : in String); -- Generate a link to the URL given. -- Text is the text of the link. -- For hyperlinked formats, this should generate a link; -- for other formats, only the text is generated. procedure Picture (Output_Object : in out HTML_Output_Type; Name : in String; Descr : in String; Alignment : in ARM_Output.Picture_Alignment; Height, Width : in Natural; Border : in ARM_Output.Border_Kind); -- Generate a picture. -- Name is the (simple) file name of the picture; Descr is a -- descriptive name for the picture (it will appear in some web -- browsers). -- We assume that it is a .PNG or .JPG and that it will be present -- in the same directory as the output files. -- Alignment specifies the picture alignment. -- Height and Width specify the picture size in pixels. -- Border specifies the kind of border. private type Column_Text_Item_Type; type Column_Text_Ptr is access Column_Text_Item_Type; type Column_Text_Item_Type is record Text : String (1..120); Length : Natural; Item : Natural; -- Which item. End_Para : Boolean; -- True if this item is an end paragraph. Next : Column_Text_Ptr; end record; type Column_Text_Ptrs_Type is array (1..5) of Column_Text_Ptr; subtype Prefix_String is String(1..5); type HTML_Output_Type is new ARM_Output.Output_Type with record Is_Valid : Boolean := False; -- Global properties: File_Prefix : Prefix_String; -- Blank padded. Output_Path : Ada.Strings.Unbounded.Unbounded_String; Big_Files : Boolean; -- For HTML, this means to generate a single monster file. DOS_Filenames : Boolean; -- Generate 8.3 MS-DOS filenames. Title : Ada.Strings.Unbounded.Unbounded_String; HTML_Kind : HTML_Type; Use_Unicode : Boolean; Number_Paragraphs : Boolean; Ref_URL : Ada.Strings.Unbounded.Unbounded_String; Srch_URL : Ada.Strings.Unbounded.Unbounded_String; Index_URL : Ada.Strings.Unbounded.Unbounded_String; Use_Buttons : Boolean := True; Nav_On_Top : Boolean := True; Nav_On_Bottom : Boolean := True; Tab_Emulation : Tab_Emulation_Type; Script_HTML : Ada.Strings.Unbounded.Unbounded_String; Header_HTML : Ada.Strings.Unbounded.Unbounded_String; Footer_HTML : Ada.Strings.Unbounded.Unbounded_String; Body_Font : ARM_Output.Font_Family_Type := ARM_Output.Roman; Text_Color : Color_String; Background_Color : Color_String; Link_Color : Color_String; VLink_Color : Color_String; ALink_Color : Color_String; -- Current formatting properties: Is_In_Paragraph : Boolean := False; Paragraph_Style : ARM_Output.Paragraph_Style_Type; Paragraph_Indent : ARM_Output.Paragraph_Indent_Type; Had_Prefix : Boolean := False; -- If in paragraph, value of not No_Prefix. Column_Count : ARM_Output.Column_Count := 1; Output_File : Ada.Text_IO.File_Type; Section_Name : String(1..3); Char_Count : Natural := 0; -- Characters on current line. Disp_Char_Count : Natural := 0; -- Displayed characters on current line. Disp_Large_Char_Count : Natural := 0; -- Displayed large characters on current line (others are "small" characters). -- Large characters are capitals, 'm', 'w', and numbers. Any_Nonspace : Boolean := False; -- Have we output any non-space on this line? Last_was_Space : Boolean := False; -- True if the last visible character -- output was a space (any kind), or this is the -- start of a line. Conditional_Space : Boolean := False; -- If True, output a space if the -- next *visible* character is not a space or -- punctuation. Saw_Hang_End : Boolean := False; -- If we are in a hanging paragraph, -- have we seen the end of the hanging part yet? Is_Bold : Boolean; -- Is the text currently bold? Is_Italic : Boolean; -- Is the text current italics? Font : ARM_Output.Font_Family_Type; -- What is the current font family? Size : ARM_Output.Size_Type; -- What is the current relative size? Color : ARM_Output.Color_Type := ARM_Output.Default; Change : ARM_Output.Change_Type := ARM_Output.None; Version : ARM_Contents.Change_Version_Type := '0'; Added_Version : ARM_Contents.Change_Version_Type := '0'; Location : ARM_Output.Location_Type := ARM_Output.Normal; Tab_Stops : ARM_Output.Tab_Info := ARM_Output.NO_TABS; Can_Emulate_Tabs : Boolean := False; -- Can we emulate tabs in the current style? Is_In_Table : Boolean := False; -- Are we processing a table? In_Header : Boolean := False; -- If Is_In_Table, are we processing the header? Table_Column_Alignment : ARM_Output.Column_Text_Alignment; -- If Is_In_Table, specifies the column alignment. Table_Has_Small_Text : Boolean := False; -- If Is_In_Table, specifies the text size. Current_Column : Natural := 0; -- When processing 4-column+ text, the current column number. Current_Item : Natural := 0; -- When processing 4-column+ text, the current item within the column. Column_Text : Column_Text_Ptrs_Type := (others => null); -- If we are processing 4-column+ text, the text for the columns. In_Local_Link : Boolean := False; Current_Clause : Ada.Strings.Unbounded.Unbounded_String; -- The name of the clause of the currently open file (for -- Big_Files = False); used to generate the navigation bar. end record; end ARM_HTML; org.adaic.arm_form/progs/arm_indx.adb0000755000175200010010000011710512066652506017071 0ustar stepheNonewith -- ARM_Output, redundant with spec ARM_Contents, Ada.Exceptions, Ada.Characters.Handling, Ada.Strings.Fixed, Ada.Text_IO, Ada.Calendar, Ada.Unchecked_Deallocation; package body ARM_Index is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to manage and generate the index. -- -- --------------------------------------- -- Copyright 2000, 2002, 2003, 2004, 2005, 2006, 2007, 2010, 2011, 2012 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/28/00 - RLB - Created package. -- 8/ 7/00 - RLB - Improved sorting of entries. -- 1/31/02 - RLB - Added missing with of Unchecked_Deallocation. -- 4/11/03 - RLB - Added a hard space in the indexing routine, in order -- that the empty paragraph isn't ignored. -- 9/09/04 - RLB - Removed unused junk noted by Stephen Leake. -- 10/28/05 - RLB - Added key reuse. -- 10/30/05 - RLB - Added subtype declaration. -- 1/16/06 - RLB - Fixed so a letter header is output if the first -- indexed item starts with a letter. -- 2/17/06 - RLB - Added Remove_Soft_Hyphens flag to Clean (for output). -- 9/22/06 - RLB - Changed to use Clause_Number_Type. -- 2/13/07 - RLB - Changed Start_Paragraph to use explicit indents. -- 12/19/07 - RLB - Revised Text_Format calls. -- 3/31/10 - RLB - Fixed sorting to ignore embedded commands (like -- soft hyphens). -- 10/18/11 - RLB - Changed to GPLv3 license. -- 3/12/12 - RLB - Lengthened indexing so that -- "Ada.Strings.Wide_Wide_@!Unbounded.Wide_Wide_@!Equal_Case_Insensitive" -- would fit. (Don't ask.) -- 8/31/12 - RLB - Fixed to avoid reading uninitialized section numbers. Next_Index_Key : Index_Key; type Term_Type; type Term_Ptr is access Term_Type; type Term_Type is record Clause : String (1..10); Clause_Len : Natural; Clause_Number : ARM_Contents.Clause_Number_Type; Paragraph : String (1..10); Paragraph_Len : Natural; Term : String (1..72); Term_Len : Natural; Subterm : String (1..80); Subterm_Len : Natural; Kind : Index_Item_Kind_Type; Key : Index_Key; Next : Term_Ptr; end record; procedure Free is new Ada.Unchecked_Deallocation (Term_Type, Term_Ptr); Index_List : Term_Ptr; Term_Count : Natural := 0; procedure Create is -- Initialize this package. begin Index_List := null; Next_Index_Key := 1001; Term_Count := 0; end Create; procedure Destroy is -- Finalize this package; make sure the index is empty. TTemp : Term_Ptr; begin while Index_List /= null loop TTemp := Index_List; Index_List := TTemp.Next; Free (TTemp); end loop; end Destroy; function Clean (Item : in String; Remove_Soft_Hyphens : in Boolean) return String is -- Remove any commands from Item. (Except for soft hyphens -- if Remove_Soft_Hyphens is False.) We keep the contents of any -- commands (we assume the commands are basic formatting). Result : String (1 .. Item'Length); Len : Natural := 0; In_Command : Boolean := False; Skip_Next_Char : Boolean := False; Close_Char : Character := ' '; begin for I in Item'Range loop if Item(I) = '@' then if I < Item'Last and then (Item(I+1) = '!' or else -- Soft hyphen Item(I+1) = '|' or else -- Soft linebreak Item(I+1) = ';' or else -- "nothing" Item(I+1) = '\' or else -- tab Item(I+1) = ' ' or else -- hard space Item(I+1) = '*') then -- hard return if Remove_Soft_Hyphens then Skip_Next_Char := True; else -- Allow soft hyphens and other simple commands. Len := Len + 1; Result(Len) := Item(I); end if; elsif I < Item'Last and then Item(I+1) = '@' then -- Literal '@' command. if Remove_Soft_Hyphens then Len := Len + 1; Result(Len) := '@'; Skip_Next_Char := True; else -- Leave these markers, as we'll format the -- resulting string. Len := Len + 1; Result(Len) := Item(I); end if; else In_Command := True; Close_Char := ' '; -- Skip it. end if; elsif Skip_Next_Char then Skip_Next_Char := False; elsif In_Command then if Item(I) = '{' then Close_Char := '}'; In_Command := False; -- Finished command header. elsif Item(I) = '[' then Close_Char := ']'; In_Command := False; elsif Item(I) = '(' then Close_Char := ')'; In_Command := False; elsif Item(I) = '<' then Close_Char := '>'; In_Command := False; elsif Item(I) = '`' then Close_Char := '''; In_Command := False; elsif Ada.Characters.Handling.Is_Alphanumeric (Item(I)) then -- Skip character (part of the command name). null; else -- End of parameterless command (note: '@' already -- was recognized). Close_Char := ' '; In_Command := False; Len := Len + 1; Result(Len) := Item(I); end if; elsif Close_Char /= ' ' and then Close_Char = Item(I) then -- Skip the close character. Close_Char := ' '; elsif Item(I) = Ascii.LF then Len := Len + 1; Result(Len) := ' '; else Len := Len + 1; Result(Len) := Item(I); end if; end loop; return Result (1..Len); end Clean; function Get_Key return Index_Key is -- Returns a Key value to refer to one or more index entries -- (for a single entity). Temp : Index_Key := Next_Index_Key; begin Next_Index_Key := Next_Index_Key + 1; return Temp; end Get_Key; procedure Add_Reusing_Key (Term : in String; Subterm : in String := ""; Kind : in Index_Item_Kind_Type := Primary_Term; Clause : in String := ""; Paragraph : in String := ""; Key : in Index_Key) is -- Add an index reference to the index, (re)using the specified Key -- to refer to this index entry. Key must have previously -- returned by Add or Get_Key. Temp_Term : Term_Type; CTerm : constant String := Clean(Term, Remove_Soft_Hyphens => False); CSubterm : constant String := Clean(Subterm, Remove_Soft_Hyphens => False); begin Temp_Term.Kind := Kind; Ada.Strings.Fixed.Move (Target => Temp_Term.Term, Source => CTerm, Drop => Ada.Strings.Error, Pad => ' '); Temp_Term.Term_Len := CTerm'Length; if Kind /= Primary_Term_and_Subterm and then Kind /= Partial_Term_with_Subterm and then Kind /= Child_Unit_Parent and then Kind /= Declaration_in_Package and then Kind /= Subdeclaration_in_Package and then Kind /= Subtype_Declaration_in_Package and then Kind /= See_Term and then Kind /= See_Also_Term and then Kind /= See_Other_Term and then Kind /= See_Also_Other_Term then if Subterm /= "" then Ada.Exceptions.Raise_Exception (Not_Valid_Error'Identity, "Subterm used in kind without subterm"); else Temp_Term.Subterm_Len := 0; end if; else Ada.Strings.Fixed.Move (Target => Temp_Term.Subterm, Source => CSubterm, Drop => Ada.Strings.Error, Pad => ' '); Temp_Term.Subterm_Len := CSubterm'Length; end if; if (Kind = See_Other_Term or else Kind = See_Also_Other_Term) then if Clause /= "" or else Paragraph /= "" then raise Not_Valid_Error with "Clause used in kind without reference"; else Temp_Term.Clause_Len := 0; Temp_Term.Paragraph_Len := 0; -- Note: These have no clause numbers. end if; else Ada.Strings.Fixed.Move (Target => Temp_Term.Clause, Source => Clause, Drop => Ada.Strings.Error, Pad => ' '); Temp_Term.Clause_Len := Clause'Length; Ada.Strings.Fixed.Move (Target => Temp_Term.Paragraph, Source => Paragraph, Drop => Ada.Strings.Error, Pad => ' '); Temp_Term.Paragraph_Len := Paragraph'Length; ARM_Contents.Make_Clause (Clause, Temp_Term.Clause_Number); end if; Temp_Term.Key := Key; Temp_Term.Next := Index_List; Index_List := new Term_Type'(Temp_Term); Term_Count := Term_Count + 1; exception when Ada.Strings.Length_Error => Ada.Text_IO.Put_Line ("**** Index doesn't fit: Term: " & CTerm & " [Subterm: " & CSubterm & "]"); end Add_Reusing_Key; procedure Add (Term : in String; Subterm : in String := ""; Kind : in Index_Item_Kind_Type := Primary_Term; Clause : in String := ""; Paragraph : in String := ""; Key : out Index_Key) is -- Add an index reference to the index. Returns a Key value to -- refer to this index entry. -- Raises Not_Valid_Error if Subterm, Clause, or Paragraph is not -- empty when the kind does not use it. begin Key := Get_Key; Add_Reusing_Key (Term, Subterm, Kind, Clause, Paragraph, Key); end Add; procedure Generate_Index_Body (Output_Object : in out ARM_Output.Output_Type'Class; Use_Paragraphs : in Boolean := True) is -- Generate the index body. (The section header has already been -- generated). References include paragraph numbers if Use_Paragraphs -- is true. -- Note: This should not leave us in a paragraph. Temp : Term_Ptr; Last : Term_Ptr := null; Items : array (1..Term_Count) of Term_Ptr; Keep_Set : Boolean := False; Start : Ada.Calendar.Time := Ada.Calendar.Clock; function To_Lower (A : in String) return String renames Ada.Characters.Handling.To_Lower; function To_Lower (A : in Character) return Character renames Ada.Characters.Handling.To_Lower; procedure Clause_Ref (Item : Term_Ptr) is -- Generate a clause reference: begin if Item.Clause_Len > 5 and then Item.Clause (1..5) = "Annex" then -- Strip off the "Annex". if Use_Paragraphs and then Item.Paragraph_Len /= 0 then ARM_Output.Index_Reference (Output_Object, Text => Item.Clause (Item.Clause_Len) & '(' & Item.Paragraph (1..Item.Paragraph_Len) & ')', Index_Key => Item.Key, Clause_Number => Item.Clause (1..Item.Clause_Len)); else ARM_Output.Index_Reference (Output_Object, Text => Item.Clause (Item.Clause_Len) & "", Index_Key => Item.Key, Clause_Number => Item.Clause (1..Item.Clause_Len)); end if; elsif Use_Paragraphs and then Item.Paragraph_Len /= 0 then ARM_Output.Index_Reference (Output_Object, Text => Item.Clause (1..Item.Clause_Len) & '(' & Item.Paragraph (1..Item.Paragraph_Len) & ')', Index_Key => Item.Key, Clause_Number => Item.Clause (1..Item.Clause_Len)); else ARM_Output.Index_Reference (Output_Object, Text => Item.Clause (1..Item.Clause_Len), Index_Key => Item.Key, Clause_Number => Item.Clause (1..Item.Clause_Len)); end if; end Clause_Ref; procedure Italic_Text (Text : in String) is begin ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => True, Font => ARM_Output.Default, Size => 0, Color => ARM_Output.Default, Change => ARM_Output.None, Version | Added_Version => '0', Location => ARM_Output.Normal)); ARM_Output.Ordinary_Text (Output_Object, Text); ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Size => 0, Color => ARM_Output.Default, Change => ARM_Output.None, Version | Added_Version => '0', Location => ARM_Output.Normal)); end Italic_Text; procedure Term_Text (Text : in String) is A_Soft_Hyphen : Natural := Ada.Strings.Fixed.Index (Text, "@!"); begin if A_Soft_Hyphen = 0 then ARM_Output.Ordinary_Text (Output_Object, Text); else ARM_Output.Ordinary_Text (Output_Object, Text(Text'First .. A_Soft_Hyphen-1)); ARM_Output.Soft_Hyphen_Break (Output_Object); Term_Text (Text(A_Soft_Hyphen+2 .. Text'Last)); -- In case there is more than one soft hyphen. end if; end Term_Text; procedure New_Kind (Item : Term_Ptr; Reset_Keep : in Boolean) is -- Generate and item of a new kind. Note that the term has already -- been generated (at some point). begin case Item.Kind is when Primary_Term => -- ** Must be first, so can't get here. Italic_Text ("*SORT ERROR*"); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Partial_Term => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, '['); Italic_Text ("partial"); ARM_Output.Ordinary_Character (Output_Object, ']'); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Primary_Term_and_Subterm => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Partial_Term_with_Subterm => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Term_Text (Item.Subterm (1..Item.Subterm_Len)); --[The "partial" does not seem to appear on subterms.] --ARM_Output.Hard_Space (Output_Object); --ARM_Output.Ordinary_Character (Output_Object, '['); --Italic_Text ("partial"); --ARM_Output.Ordinary_Character (Output_Object, ']'); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Syntax_NT_Used => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("used"); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Child_Unit_Parent => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("child of"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Declaration_In_Package => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("in"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when SubDeclaration_In_Package => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); declare In_Loc : Natural := Ada.Strings.Fixed.Index (Item.Subterm (1..Item.Subterm_Len), " in "); begin if In_Loc = 0 then -- Weird, "in" not found. Term_Text (Item.Subterm (1..Item.Subterm_Len)); else Term_Text (Item.Subterm (1 .. In_Loc)); Italic_Text ("in"); Term_Text (Item.Subterm (In_Loc+3 .. Item.Subterm_Len)); end if; end; ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when Subtype_Declaration_In_Package => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("in"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when See_Term => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("See"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when See_Also_Term => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("See also"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Item); when See_Other_Term => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("See"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); -- No clause reference here. when See_Also_Other_Term => ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => Reset_Keep); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); Italic_Text ("See also"); ARM_Output.Ordinary_Character (Output_Object, ' '); Term_Text (Item.Subterm (1..Item.Subterm_Len)); -- No clause reference here. end case; end New_Kind; function Is_Last_for_Term (Item : in Term_Ptr) return Boolean is -- Returns True if this is the last line for Item's Term. begin if Item.Next = null then return True; elsif To_Lower (Item.Term (1..Item.Term_Len)) /= To_Lower (Item.Next.Term (1..Item.Next.Term_Len)) then -- The next item has a different term. return True; elsif Temp.Kind /= Temp.Next.Kind then -- The next item has a different kind, so another line will -- be generated. return False; elsif To_Lower (Item.Subterm (1..Item.Subterm_Len)) /= To_Lower (Item.Next.Subterm (1..Item.Next.Subterm_Len)) then -- The next item has a different subterm, so another line will -- be generated. return False; else -- The following term will just add another clause reference. -- So we must look at the term following that: return Is_Last_for_Term (Item.Next); end if; end Is_Last_for_Term; begin Ada.Text_IO.Put_Line (" -- Start index sorting - " & Natural'Image(Term_Count) & " items."); -- Sort the items: -- Load the items: Temp := Index_List; for I in Items'range loop Items(I) := Temp; Temp := Temp.Next; end loop; -- Sort the items array: declare function "<" (Left, Right : Term_Ptr) return Boolean is function To_Lower (A : in String) return String renames Ada.Characters.Handling.To_Lower; use type ARM_Contents.Clause_Number_Type; type Compare_Result is (Less, Greater, Equal); function Compare (Left, Right : in String) return Compare_Result is -- Compare two items; the compare is case insensitive and -- ignores embedded commands. begin -- Simple cases in order to increase performance. -- Check for null cases so we don't have to worry about them -- later. if Left = Right then return Equal; elsif Left'Length = 0 then return Less; -- Right can't be null or they'd be equal. elsif Right'Length = 0 then return Greater; end if; -- Both strings are non-null. if Left(Left'First) in '0'..'9' or else Left(Left'First) in 'A'..'Z' then if Right(Right'First) in '0'..'9' or else Right(Right'First) in 'A'..'Z' then if Left(Left'First) < Right(Right'First) then return Less; elsif Left(Left'First) > Right(Right'First) then return Greater; -- else continue below. end if; elsif Right(Right'First) in 'a'..'z' then if Left(Left'First) < Character'Val(Character'Pos(Right(Right'First))+Character'Pos('A')-Character'Pos('a')) then return Less; elsif Left(Left'First) > Character'Val(Character'Pos(Right(Right'First))+Character'Pos('A')-Character'Pos('a')) then return Greater; end if; -- else continue below. end if; elsif Left(Left'First) in 'a'..'z' then if Right(Right'First) in '0'..'9' or else Right(Right'First) in 'A'..'Z' then if Character'Val(Character'Pos(Left(Left'First))+Character'Pos('A')-Character'Pos('a')) < Right(Right'First) then return Less; elsif Character'Val(Character'Pos(Left(Left'First))+Character'Pos('A')-Character'Pos('a')) > Right(Right'First) then return Greater; -- else continue below. end if; elsif Right(Right'First) in 'a'..'z' then -- Both lower. if Left(Left'First) < Right(Right'First) then return Less; elsif Left(Left'First) > Right(Right'First) then return Greater; end if; -- else continue below. end if; -- else continue below. end if; -- OK, do a full compare: declare -- %% Warning: This has terrible performance, too much heap use. L : constant String := Clean (To_Lower (Left), Remove_Soft_Hyphens => True); R : constant String := Clean (To_Lower (Right), Remove_Soft_Hyphens => True); begin --Ada.Text_IO.Put_Line("Full compare: Left=" & Left & "; Right=" & Right); --Ada.Text_IO.Put_Line(" Clean Left=" & L & "; Clean Right=" & R); if L < R then --Ada.Text_IO.Put_Line(" Result=Less"); return Less; elsif L > R then --Ada.Text_IO.Put_Line(" Result=Greater"); return Greater; else --Ada.Text_IO.Put_Line(" Result=Equal"); return Equal; end if; end; end Compare; begin -- We sort first on "Term", then on "Kind", then on "Subterm", -- then on "Clause", and finally on "Paragraph". case Compare (Left.Term (1..Left.Term_Len), Right.Term (1..Right.Term_Len)) is when Less => return True; when Greater => return False; when Equal => null; -- Continue to next compare. end case; -- Partial_Term_with_Subterm and Primary_Term_and_Subterm -- look identical, so they should compare equal for this -- purpose: if Left.Kind = Right.Kind or else (Left.Kind = Partial_Term_with_Subterm and then Right.Kind = Primary_Term_and_Subterm) or else (Left.Kind = Primary_Term_and_Subterm and then Right.Kind = Partial_Term_with_Subterm) then null; -- Continue to next compare. elsif Left.Kind < Right.Kind then return True; else --if Left.Kind > Right.Kind then return False; end if; case Compare (Left.Subterm (1..Left.Subterm_Len), Right.Subterm (1..Right.Subterm_Len)) is when Less => return True; when Greater => return False; when Equal => null; -- Continue to next compare. end case; if Left.Kind = See_Other_Term or else Left.Kind = See_Also_Other_Term then -- These have no clause or paragraph number to compare, -- and the Kinds must match, so they are equal. -- Since this is "<" and not "<=", the result is False. return False; end if; -- Note: We use the numbers, because the references don't -- sort right (11.1 comes before 2.8, etc.) if Left.Clause_Number < Right.Clause_Number then return True; elsif Left.Clause_Number = Right.Clause_Number then -- Make sure that single digit paragraph numbers sort before -- multiple digit ones: if Left.Paragraph_Len <= 1 or else Left.Paragraph(2) = '.' or else Left.Paragraph(2) = '/' then -- Single digit number: if Right.Paragraph_Len <= 1 or else Right.Paragraph(2) = '.' or else Right.Paragraph(2) = '/' then -- Single digit number, normal compare: return Left.Paragraph (1..Left.Paragraph_Len) < Right.Paragraph (1..Right.Paragraph_Len); else -- Single digit is always less than multiple digits: return True; end if; else -- Not single digit number: if Right.Paragraph_Len <= 1 or else Right.Paragraph(2) = '.' or else Right.Paragraph(2) = '/' then -- Single digit number, always less than multiple digits: return False; else -- Else both multiple, use normal compare: return Left.Paragraph (1..Left.Paragraph_Len) < Right.Paragraph (1..Right.Paragraph_Len); end if; end if; else -- Left.Clause_Number > Right.Clause_Number return False; end if; end "<"; --procedure Final_Sort_Slice (Left, Right : in Natural) is -- -- Use an insertion sort to sort the slice between Left and Right. -- Working_Left : Natural; -- Working Left sorting stop -- Temp : Term_Ptr; --begin -- for Working_Right In Left+1 .. Right loop -- Right sorting stop -- Temp := Items(Working_Right); -- Working_Left := Working_Right - 1; -- while Temp < Items(Working_Left) loop -- Switch items -- Items(Working_Left + 1) := Items(Working_Left); -- Working_Left := Working_Left - 1; -- exit when Working_Left = 0; -- end loop; -- Items(Working_Left + 1) := Temp; -- end loop; --end Final_Sort_Slice; procedure Partition_Sort_Slice (Start_Index, End_Index : Natural) is -- Use quicksort partition sort to sort the slice between -- Start_Index and End_Index. Temp_Item : Term_Ptr; begin case ((End_Index - Start_Index) + 1) is when 0 | 1 => null; -- A single element is obviously sorted (trivially). when 2 => -- Unrolled Insertion Sort. if Items(Start_Index+1) < Items(Start_Index) then -- Move the record down. Temp_Item := Items(Start_Index+1); Items(Start_Index+1) := Items(Start_Index ); Items(Start_Index ) := Temp_Item; -- Put at beginning. -- else Doesn't need to move. end if; when 3 => -- Unrolled Insertion Sort. if Items(Start_Index+1) < Items(Start_Index) then -- Move the record down. Temp_Item := Items(Start_Index+1); Items(Start_Index+1) := Items(Start_Index ); Items(Start_Index ) := Temp_Item; -- Put at beginning. -- else Doesn't need to move. end if; if Items(Start_Index+2) < Items(Start_Index+1) then -- Move the record down. Temp_Item := Items(Start_Index+2); Items(Start_Index+2) := Items(Start_Index+1); if Temp_Item < Items(Start_Index) then -- Move the record down. Items(Start_Index+1) := Items(Start_Index); Items(Start_Index) := Temp_Item; -- Put at beginning. else -- Put the record here. Items(Start_Index+1) := Temp_Item; end if; -- else Doesn't need to move. end if; when 4 => -- Unrolled Insertion Sort. if Items(Start_Index+1) < Items(Start_Index) then -- Move the record down. Temp_Item := Items(Start_Index+1); Items(Start_Index+1) := Items(Start_Index ); Items(Start_Index ) := Temp_Item; -- Put at beginning. -- else Doesn't need to move. end if; if Items(Start_Index+2) < Items(Start_Index+1) then -- Move the record down. Temp_Item := Items(Start_Index+2); Items(Start_Index+2) := Items(Start_Index+1); if Temp_Item < Items(Start_Index) then -- Move the record down. Items(Start_Index+1) := Items(Start_Index); Items(Start_Index) := Temp_Item; -- Put at beginning. else -- Put the record here. Items(Start_Index+1) := Temp_Item; end if; -- else Doesn't need to move. end if; if Items(Start_Index+3) < Items(Start_Index+2) then -- Move the record down. Temp_Item := Items(Start_Index+3); Items(Start_Index+3) := Items(Start_Index+2); if Temp_Item < Items(Start_Index+1) then -- Move the record down. Items(Start_Index+2) := Items(Start_Index+1); if Temp_Item < Items(Start_Index) then -- Move the record down. Items(Start_Index+1) := Items(Start_Index); Items(Start_Index) := Temp_Item; -- Put at beginning. else -- Put the record here. Items(Start_Index+1) := Temp_Item; end if; else -- Put the record here. Items(Start_Index+2) := Temp_Item; end if; -- else Don't move the record. end if; when others => -- Longer partitions, quicksort. declare Left_Index, Right_Index : Natural; Pivot_Item : Term_Ptr; begin -- Split into partitions, and sort them. Left_Index := Start_Index; Right_Index := End_Index; -- Use the middle element for the pivot, in case the items are -- somewhat sorted. Pivot_Item := Items ((End_Index - Start_Index) / 2 + Start_Index); loop loop exit when not (Items(Left_Index) < Pivot_Item); -- >= Left_Index := Left_Index + 1; end loop; loop exit when not (Pivot_Item < Items(Right_Index)); Right_Index := Right_Index - 1; end loop; if Left_Index <= Right_Index then if Left_Index < Right_Index then Temp_Item := Items(Left_Index); Items(Left_Index) := Items(Right_Index); Items(Right_Index) := Temp_Item; end if; Left_Index := Left_Index + 1; Right_Index := Right_Index - 1; end if; exit when Left_Index > Right_Index; end loop; -- Repeat Loop -- Recursive calls on partitions. Partition_Sort_Slice (Left_Index, End_Index); Partition_Sort_Slice (Start_Index, Right_Index); end; end case; end Partition_Sort_Slice; begin -- Debug: (This should only print Kinds that have no clause number). --for Idx in Items'range loop -- if Arm_Contents."=" (Items(Idx).Clause_Number.Section, Arm_Contents.UNKNOWN) then -- Ada.Text_IO.Put_Line ("For index item" & Natural'Image(Idx) & -- " Clause.Section=" & Arm_Contents.Section_Number_Type'Image(Items(Idx).Clause_Number.Section) & -- " Kind=" & Index_Item_Kind_Type'Image(Items(Idx).Kind)); -- -- else OK. -- end if; --end loop; -- Use quicksort to handle most of the array, then -- insertion sort for the final slices. Partition_Sort_Slice (Items'First, Items'Last); end; -- Relink the items in the sorted order: for I in Items'First .. Items'Last - 1 loop Items(I).Next := Items(I+1); end loop; if Items'Length > 0 then Items(Items'Last).Next := null; Index_List := Items(1); else Index_List := null; end if; Ada.Text_IO.Put_Line (" -- Finish index sorting - " & Duration'Image ( Ada.Calendar."-" (Ada.Calendar.Clock, Start)) & " secs."); ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Index, Indent => 0, Number => "", No_Breaks => True); Keep_Set := False; Temp := Index_List; while Temp /= null loop -- First, check if we've changed to a new group: if (Last /= null and then To_Lower (Last.Term(1)) /= To_Lower(Temp.Term(1))) or else (Last = null and then To_Lower(Temp.Term(1)) in 'a' .. 'z') then -- The first character has changed, or this is the first item. -- We only generate letters, so we try not to come here for -- non-letters. ARM_Output.End_Paragraph (Output_Object); ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Index, Indent => 0, Number => ""); Keep_Set := False; if To_Lower(Temp.Term(1)) in 'a' .. 'z' then ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => False); ARM_Output.Text_Format (Output_Object, Format => (Bold => True, Italic => False, Font => ARM_Output.Default, Size => 2, Color => ARM_Output.Default, Change => ARM_Output.None, Version | Added_Version => '0', Location => ARM_Output.Normal)); ARM_Output.Ordinary_Character (Output_Object, Ada.Characters.Handling.To_Upper(Temp.Term(1))); ARM_Output.Text_Format (Output_Object, Format => (Bold => False, Italic => False, Font => ARM_Output.Default, Size => 0, Color => ARM_Output.Default, Change => ARM_Output.None, Version | Added_Version => '0', Location => ARM_Output.Normal)); ARM_Output.Index_Line_Break (Output_Object, Clear_Keep_with_Next => False); else ARM_Output.Hard_Space (Output_Object); -- So the paragraph isn't empty (which causes it to be -- ignored in HTML). end if; end if; if Last = null or else To_Lower(Last.Term (1..Last.Term_Len)) /= To_Lower(Temp.Term (1..Temp.Term_Len)) then -- New term: (Note that we ignore case differences here. Perhaps -- there ought to be a warning?) if Last /= null then ARM_Output.End_Paragraph (Output_Object); if Temp.Kind = Primary_Term then ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Index, Indent => 0, Number => "", No_Breaks => True); Keep_Set := False; else -- The item has at least two lines; keep them together. ARM_Output.Start_Paragraph (Output_Object, ARM_Output.Index, Indent => 0, Number => "", No_Breaks => True, Keep_with_Next => True); Keep_Set := True; end if; end if; if Temp.Kind /= Subtype_Declaration_in_Package then Term_Text (Temp.Term (1..Temp.Term_Len)); else declare Of_Loc : Natural := Ada.Strings.Fixed.Index (Temp.Term (1..Temp.Term_Len), " subtype of "); begin if Of_Loc = 0 then -- Weird, "subtype of" not found. Term_Text (Temp.Term (1..Temp.Term_Len)); else Term_Text (Temp.Term (1 .. Of_Loc)); Italic_Text ("subtype of"); Term_Text (Temp.Term (Of_Loc+11 .. Temp.Term_Len)); end if; end; end if; if Temp.Kind = Primary_Term then ARM_Output.Hard_Space (Output_Object); ARM_Output.Hard_Space (Output_Object); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Temp); else if Is_Last_for_Term(Temp) then -- Last (only) item of this term, always clear Keep: New_Kind (Temp, Reset_Keep => True); Keep_Set := False; else -- Leave keep set: New_Kind (Temp, Reset_Keep => False); end if; end if; elsif Last.Kind /= Temp.Kind then New_Kind (Temp, Reset_Keep => Keep_Set); Keep_Set := False; elsif (Temp.Kind = Primary_Term_and_Subterm or else Temp.Kind = Partial_Term_with_Subterm or else Temp.Kind = Syntax_NT_Used or else Temp.Kind = Child_Unit_Parent or else Temp.Kind = Declaration_in_Package or else Temp.Kind = SubDeclaration_in_Package or else Temp.Kind = Subtype_Declaration_in_Package) and then Last.Subterm (1..Last.Subterm_Len) /= Temp.Subterm (1..Temp.Subterm_Len) then New_Kind (Temp, Reset_Keep => Keep_Set); Keep_Set := False; elsif (Temp.Kind = See_Other_Term or else Temp.Kind = See_Also_Other_Term) then -- Just add the next reference. ARM_Output.Ordinary_Character (Output_Object, ','); ARM_Output.Ordinary_Character (Output_Object, ' '); ARM_Output.Ordinary_Text (Output_Object, Temp.Subterm (1..Temp.Subterm_Len)); -- No clause references here. elsif (Temp.Kind = See_Term or else Temp.Kind = See_Also_Term) then -- Just add the next reference. We'll just use New_Kind for -- this, so we don't get the formats slightly different. New_Kind (Temp, Reset_Keep => Keep_Set); Keep_Set := False; elsif Last.Clause (1..Last.Clause_Len) = Temp.Clause (1..Temp.Clause_Len) and then Last.Paragraph (1..Last.Paragraph_Len) = Temp.Paragraph (1..Temp.Paragraph_Len) then -- The reference and everything else is the same, so just -- forget this item. null; else -- Just add the next clause. ARM_Output.Ordinary_Character (Output_Object, ','); ARM_Output.Ordinary_Character (Output_Object, ' '); Clause_Ref (Temp); end if; Last := Temp; Temp := Temp.Next; end loop; ARM_Output.End_Paragraph (Output_Object); end Generate_Index_Body; end ARM_Index; org.adaic.arm_form/progs/arm_indx.ads0000755000175200010010000001120411776511201017074 0ustar stepheNonewith ARM_Output; package ARM_Index is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to manage and generate the index. -- -- --------------------------------------- -- Copyright 2000, 2005, 2006, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/28/00 - RLB - Created package. -- 8/11/00 - RLB - Made Clean visible. -- 10/28/05 - RLB - Added key reuse. -- 10/30/05 - RLB - Added subtype declaration. -- 2/17/06 - RLB - Added Remove_Soft_Hyphens flag to Clean (for output). -- 10/18/11 - RLB - Changed to GPLv3 license. Not_Valid_Error : exception; subtype Index_Key is Natural range 0 .. 20000; procedure Create; -- Initialize this package. procedure Destroy; -- Finalize this package; make sure the index is empty. type Index_Item_Kind_Type is ( Primary_Term, -- A primary index term. Partial_Term, -- A partial index term. Primary_Term_and_Subterm, -- A primary index term with a subterm. Partial_Term_with_Subterm, -- A partial index term with a subterm. Syntax_NT_Used, -- A non-terminal, with a subterm of "Used". Child_Unit_Parent, -- A child unit, with a subterm of "child of ". Declaration_in_Package, -- A declaration, with a subterm of "in ". SubDeclaration_in_Package, -- A term, with a subterm of " in ". Subtype_Declaration_in_Package, -- A term (of the form " subtype of , with a subterm of "in ". See_Term, -- A "see " with reference. See_Also_Term, -- A "see also " with reference. See_Other_Term, -- A "see " without reference. See_Also_Other_Term); -- A "see also " without reference. -- Note: These are declared in the sorting order. function Get_Key return Index_Key; -- Returns a Key value to refer to one or more index entries -- (for a single entity). procedure Add (Term : in String; Subterm : in String := ""; Kind : in Index_Item_Kind_Type := Primary_Term; Clause : in String := ""; Paragraph : in String := ""; Key : out Index_Key); -- Add an index reference to the index. Returns a Key value to -- refer to this index entry. -- Raises Not_Valid_Error if Subterm, Clause, or Paragraph is not -- empty when the kind does not use it. procedure Add_Reusing_Key (Term : in String; Subterm : in String := ""; Kind : in Index_Item_Kind_Type := Primary_Term; Clause : in String := ""; Paragraph : in String := ""; Key : in Index_Key); -- Add an index reference to the index, (re)using the specified Key -- to refer to this index entry. Key must have previously -- returned by Add or Get_Key. -- Raises Not_Valid_Error if Subterm, Clause, or Paragraph is not -- empty when the kind does not use it. function Clean (Item : in String; Remove_Soft_Hyphens : in Boolean) return String; -- Remove any commands from Item. (Except for soft hyphens -- if Remove_Soft_Hyphens is False.) procedure Generate_Index_Body (Output_Object : in out ARM_Output.Output_Type'Class; Use_Paragraphs : in Boolean := True); -- Generate the index body. (The section header has already been -- generated). References include paragraph numbers if Use_Paragraphs -- is true. end ARM_Index; org.adaic.arm_form/progs/arm_inp.adb0000755000175200010010000004745512273462240016721 0ustar stepheNonewith Ada.Text_IO, Ada.Characters.Handling, Ada.Strings.Fixed; package body ARM_Input is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the abstract definition of reading an input file -- or other entity, and routines to lex the input entities. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2005, 2011, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/15/00 - RLB - Created base package. -- 5/16/00 - RLB - Added `' as a open/close pairing. -- 7/18/02 - RLB - Added Check_One_of_Parameter_Names. -- 12/06/04 - RLB - Expanded Check_One_of_Parameter_Names to take up to -- five names. -- 1/26/05 - RLB - Fixed so that quoted parameters can be skipped. -- 8/16/11 - RLB - Added code so that looping operations stop when -- the input is empty. (Otherwise, bad comments cause -- an infinite loop.) -- 10/18/11 - RLB - Changed to GPLv3 license. -- 3/26/13 - RLB - Added %% as a bracket pairing, so the Google -- Analytics snippett can be inserted. function Is_Open_Char (Open_Char : in Character) return Boolean is -- Return True if character is a parameter opening character -- ('<', '[', '{', '(', '`'), and False otherwise. begin case Open_Char is when '<' | '[' | '{' | '(' | '`' | '%' => return True; when others => return False; end case; end Is_Open_Char; function Get_Close_Char (Open_Char : in Character) return Character is -- Return the parameter closing character for an opening character. -- Raises Not_Valid_Error if Open_Char is not an opening character -- ('<', '[', '{', '(', '`'). begin case Open_Char is when '<' => return '>'; when '[' => return ']'; when '{' => return '}'; when '(' => return ')'; when '`' => return '''; when '%' => return '%'; when others => Ada.Text_IO.Put_Line ("** Not an Open_Char - " & Open_Char); raise ARM_Input.Not_Valid_Error; end case; end Get_Close_Char; function Get_Open_Char (Close_Char : in Character) return Character is -- Return the parameter opening character for an closing character. -- Raises Not_Valid_Error if Open_Char is not an closing character -- ('>', ']', '}', ')', '''). begin case Close_Char is when '>' => return '<'; when ']' => return '['; when '}' => return '{'; when ')' => return '('; when ''' => return '`'; when '%' => return '%'; when others => Ada.Text_IO.Put_Line ("** Not a Close_Char - " & Close_Char); raise ARM_Input.Not_Valid_Error; end case; end Get_Open_Char; procedure Get_Name (Input_Object : in out Input_Type'Class; Name : out ARM_Input.Command_Name_Type; Null_Name_Allowed : in Boolean := False) is -- Get a name from the Input_Object. "Names" are sequences of -- alphanumeric characters. If Null_Name_Allowed is False, -- an error is produced if no name is found. Ch : Character; Len : Natural := 0; begin Name := (others => ' '); loop Get_Char (Input_Object, Ch); if Ada.Characters.Handling.Is_Alphanumeric (Ch) then Len := Len + 1; Name(Len) := Ch; else -- End of the name. Replace_Char (Input_Object); if Len = 0 and then (not Null_Name_Allowed) then Ada.Text_IO.Put_Line (" ** Failed to find command name on line " & Line_String (Input_Object)); end if; return; end if; end loop; end Get_Name; procedure Copy_to_String_until_Close_Char (Input_Object : in out Input_Type'Class; Close_Char : in Character; Buffer : out String; Len : out Natural) is -- Copy text from Input_Object to Buffer until the matching -- Close_Char is found. Len is the number of characters copied. -- Use this when we only need a string; use recording when we -- need the string *and* we still must process the type. -- Note that we watch for matching opening characters, in -- case a nested command uses one. Ch : Character; Start_Ch : Character; Start_Ch_Count : Natural := 0; begin if Close_Char = '"' then Start_Ch := Character'Val(128); -- This character shouldn't occur in input text. -- Buglet: We don't have a way to tell whether this is an inner -- command or just the end; best to avoid nesting of -- quoted parameters. elsif Close_Char = '%' then Start_Ch := Character'Val(129); -- This character shouldn't occur in input text. -- Buglet: We don't have a way to tell whether this is an inner -- command or just the end; best to avoid nesting of -- quoted parameters. else Start_Ch := ARM_Input.Get_Open_Char (Close_Char); end if; ARM_Input.Get_Char (Input_Object, Ch); Len := 0; loop if Ch = Start_Ch then -- In case an inner command uses the same -- start/end character. Start_Ch_Count := Start_Ch_Count + 1; elsif Ch = Close_Char then exit when Start_Ch_Count = 0; Start_Ch_Count := Start_Ch_Count - 1; elsif Ch = Ascii.SUB then -- End of file, quit immediately. Ada.Text_IO.Put_Line (" ** End of file when recording string on line " & ARM_Input.Line_String (Input_Object)); exit; end if; if Len >= Buffer'Length then Ada.Text_IO.Put_Line (" ** String buffer overflow on line " & ARM_Input.Line_String (Input_Object)); ----Debug: --raise Program_Error; -- Where the heck are we?? else Buffer (Buffer'First + Len) := Ch; Len := Len + 1; end if; ARM_Input.Get_Char (Input_Object, Ch); end loop; end Copy_to_String_until_Close_Char; procedure Skip_until_Close_Char (Input_Object : in out Input_Type'Class; Close_Char : in Character) is -- Skip text from Input_Object until the matching Close_Char is found. -- Note that we watch for matching opening characters, in -- case a nested command uses one. Ch : Character; Start_Ch : Character; Start_Ch_Count : Natural := 0; Start_Line : constant String := ARM_Input.Line_String (Input_Object); -- Save this in case of severe error. begin if Close_Char = '"' then Start_Ch := Character'Val(128); -- This character shouldn't occur in input text. -- Buglet: We don't have a way to tell whether this is an inner -- command or just the end; best to avoid nesting of -- quoted parameters. else Start_Ch := ARM_Input.Get_Open_Char (Close_Char); end if; --Ada.Text_IO.Put_Line ("?? Skip: Start=" & Start_Ch & "; Close=" & Close_Char & " on line " & -- ARM_Input.Line_String (Input_Object)); ARM_Input.Get_Char (Input_Object, Ch); loop if Ch = Start_Ch then -- In case an inner command uses the same -- start/end character. Start_Ch_Count := Start_Ch_Count + 1; --Ada.Text_IO.Put_Line ("?? Skip: Start found, cnt=" & Natural'Image(Start_Ch_Count) & " on line " & -- ARM_Input.Line_String (Input_Object)); elsif Ch = Close_Char then --if Start_Ch_Count = 0 then --Ada.Text_IO.Put_Line ("?? Skip: Close found on line " & -- ARM_Input.Line_String (Input_Object)); --end if; exit when Start_Ch_Count = 0; Start_Ch_Count := Start_Ch_Count - 1; --Ada.Text_IO.Put_Line ("?? Skip: Close found, cnt=" & Natural'Image(Start_Ch_Count) & " on line " & -- ARM_Input.Line_String (Input_Object)); elsif Ch = Ascii.SUB then -- End of file, quit immediately. Ada.Text_IO.Put_Line (" ** End of file when skipping to end, started on line " & Start_Line); exit; end if; -- Ignore everything until the end character -- turns up (or the end of file). ARM_Input.Get_Char (Input_Object, Ch); end loop; end Skip_until_Close_Char; procedure Check_Parameter_Name (Input_Object : in out Input_Type'Class; Param_Name : in ARM_Input.Command_Name_Type; Is_First : in Boolean; Param_Close_Bracket : out Character) is -- Check that the name of a parameter (if any) is Param_Name. -- This is the first parameter is Is_First is True; otherwise -- it is a later parameter. (For a later parameter, we'll skip -- the comma and any whitespace.) -- If the parameter has an argument, the opening character will -- be read, and the closing character will be returned in -- in Param_Close_Bracket. If the parameter wasn't found, an -- error message will be produced, and Param_Close_Bracket will -- be set to ' '. Our_Param_Name : ARM_Input.Command_Name_Type; Ch : Character; begin if not Is_First then -- Skip over the comma and any whitespace: ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then Ada.Text_IO.Put_Line (" ** Bad parameter separator for " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & ": " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); else ARM_Input.Get_Char (Input_Object, Ch); end if; while (Ch = ' ' or else Ch = Ascii.LF) loop ARM_Input.Get_Char (Input_Object, Ch); end loop; ARM_Input.Replace_Char (Input_Object); -- else nothing to clean up. end if; Arm_Input.Get_Name (Input_Object, Our_Param_Name, Null_Name_Allowed => True); if Ada.Characters.Handling.To_Lower (Param_Name) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; elsif Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) = "" then null; -- No parameter name. else Ada.Text_IO.Put_Line (" ** Bad parameter name: " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " expected on line " & ARM_Input.Line_String (Input_Object)); end if; -- Now, open the parameter section: ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Param_Close_Bracket := ARM_Input.Get_Close_Char (Ch); elsif Ch = '"' then -- Start quoted parameter: Param_Close_Bracket := '"'; else -- No parameter. Weird. ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find parameter text for " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & ", line " & ARM_Input.Line_String (Input_Object)); Param_Close_Bracket := ' '; end if; end Check_Parameter_Name; procedure Check_One_of_Parameter_Names ( Input_Object : in out Input_Type'Class; Param_Name_1 : in ARM_Input.Command_Name_Type; Param_Name_2 : in ARM_Input.Command_Name_Type; Param_Name_3 : in ARM_Input.Command_Name_Type := (others => ' '); Param_Name_4 : in ARM_Input.Command_Name_Type := (others => ' '); Param_Name_5 : in ARM_Input.Command_Name_Type := (others => ' '); Is_First : in Boolean; Param_Close_Bracket : out Character; Param_Found : out Param_Num) is -- Check that the name of a parameter (if any) is one of the given -- names. If the parameter is set to all blanks, it is not used. -- This is the first parameter is Is_First is True; -- otherwise it is a later parameter. (For a later parameter, we'll -- skip the comma and any whitespace.) -- Param_Found will be set to the number of the parameter that was -- found. -- If the parameter has an argument, the opening character will -- be read, and the closing character will be returned in -- in Param_Close_Bracket. If the parameter wasn't found, an -- error message will be produced, Param_Close_Bracket will -- be set to ' ', and Param_Found will be set to 0. Our_Param_Name : ARM_Input.Command_Name_Type; Ch : Character; begin if not Is_First then -- Skip over the comma and any whitespace: ARM_Input.Get_Char (Input_Object, Ch); if Ch /= ',' then Ada.Text_IO.Put_Line (" ** Bad parameter separator for " & Ada.Strings.Fixed.Trim (Param_Name_1, Ada.Strings.Right) & " or " & Ada.Strings.Fixed.Trim (Param_Name_2, Ada.Strings.Right) & ": " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); else ARM_Input.Get_Char (Input_Object, Ch); end if; while (Ch = ' ' or else Ch = Ascii.LF) loop ARM_Input.Get_Char (Input_Object, Ch); end loop; ARM_Input.Replace_Char (Input_Object); -- else nothing to clean up. end if; Arm_Input.Get_Name (Input_Object, Our_Param_Name, Null_Name_Allowed => True); if Param_Name_1 /= ARM_Input.Command_Name_Type'(others => ' ') and then Ada.Characters.Handling.To_Lower (Param_Name_1) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 1; elsif Param_Name_2 /= ARM_Input.Command_Name_Type'(others => ' ') and then Ada.Characters.Handling.To_Lower (Param_Name_2) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 2; elsif Param_Name_3 /= ARM_Input.Command_Name_Type'(others => ' ') and then Ada.Characters.Handling.To_Lower (Param_Name_3) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 3; elsif Param_Name_4 /= ARM_Input.Command_Name_Type'(others => ' ') and then Ada.Characters.Handling.To_Lower (Param_Name_4) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 4; elsif Param_Name_5 /= ARM_Input.Command_Name_Type'(others => ' ') and then Ada.Characters.Handling.To_Lower (Param_Name_5) = Ada.Characters.Handling.To_Lower (Our_Param_Name) then ARM_Input.Get_Char (Input_Object, Ch); if Ch /= '=' then Ada.Text_IO.Put_Line (" ** Bad parameter character for " & Ada.Strings.Fixed.Trim(Our_Param_Name, Ada.Strings.Right) & " parameter: " & Ch & " on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 5; else if Param_Name_5 /= ARM_Input.Command_Name_Type'(others => ' ') then Ada.Text_IO.Put_Line (" ** Bad parameter name: " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & "; but " & Ada.Strings.Fixed.Trim (Param_Name_1, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_2, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_3, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_4, Ada.Strings.Right) & ", or " & Ada.Strings.Fixed.Trim (Param_Name_5, Ada.Strings.Right) & " expected on line " & ARM_Input.Line_String (Input_Object)); elsif Param_Name_4 /= ARM_Input.Command_Name_Type'(others => ' ') then Ada.Text_IO.Put_Line (" ** Bad parameter name: " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & "; but " & Ada.Strings.Fixed.Trim (Param_Name_1, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_2, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_3, Ada.Strings.Right) & ", or " & Ada.Strings.Fixed.Trim (Param_Name_4, Ada.Strings.Right) & " expected on line " & ARM_Input.Line_String (Input_Object)); elsif Param_Name_3 /= ARM_Input.Command_Name_Type'(others => ' ') then Ada.Text_IO.Put_Line (" ** Bad parameter name: " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & "; but " & Ada.Strings.Fixed.Trim (Param_Name_1, Ada.Strings.Right) & ", " & Ada.Strings.Fixed.Trim (Param_Name_2, Ada.Strings.Right) & ", or " & Ada.Strings.Fixed.Trim (Param_Name_3, Ada.Strings.Right) & " expected on line " & ARM_Input.Line_String (Input_Object)); else Ada.Text_IO.Put_Line (" ** Bad parameter name: " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & "; but " & Ada.Strings.Fixed.Trim (Param_Name_1, Ada.Strings.Right) & " or " & Ada.Strings.Fixed.Trim (Param_Name_2, Ada.Strings.Right) & " expected on line " & ARM_Input.Line_String (Input_Object)); end if; Param_Found := 0; end if; -- Now, open the parameter section: ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Param_Close_Bracket := ARM_Input.Get_Close_Char (Ch); elsif Ch = '"' then -- Start quoted parameter: Param_Close_Bracket := '"'; else -- No parameter. Weird. ARM_Input.Replace_Char (Input_Object); Ada.Text_IO.Put_Line (" ** Failed to find parameter text for " & Ada.Strings.Fixed.Trim (Our_Param_Name, Ada.Strings.Right) & ", line " & ARM_Input.Line_String (Input_Object)); Param_Close_Bracket := ' '; end if; end Check_One_of_Parameter_Names; end ARM_Input; org.adaic.arm_form/progs/arm_inp.ads0000755000175200010010000001726011776511201016730 0ustar stepheNonepackage ARM_Input is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the abstract definition of reading an input file -- or other entity, and routines to lex the input entities. -- -- --------------------------------------- -- Copyright 2000, 2002, 2004, 2011 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 5/15/00 - RLB - Created base package. -- 7/18/02 - RLB - Added Check_One_of_Parameter_Names. -- 12/06/04 - RLB - Expanded Check_One_of_Parameter_Names to take up to -- five names. -- 10/18/11 - RLB - Changed to GPLv3 license. type Input_Type is abstract tagged limited null record; MAX_RECORDING_SIZE : constant := 4000; Not_Valid_Error : exception; -- The Input_Object is not valid. -- procedure Open (Input_Object : in out Input_Type; -- -- Other parameters) is abstract; -- Open an input object for an entity. -- Each concrete type has its own Open routine, with possibly -- different parameters. procedure Close (Input_Object : in out Input_Type) is abstract; -- Close the input object (entity). -- May propagate exceptions from the underlying implementation -- (that is, I/O exceptions). procedure Get_Char (Input_Object : in out Input_Type; Char : out Character) is abstract; -- We represent end of line by Ascii.LF, and end of file by -- Ascii.SUB. -- Raises: Not_Valid_Error if Input_Object is not valid (open). procedure Replace_Char (Input_Object : in out Input_Type) is abstract; -- Replaces the last character read (with Get_Char); the next call -- to Get_Char will return it. -- Raises: Not_Valid_Error if Input_Object is not valid (open). function Line_String (Input_Object : in Input_Type) return String is abstract; -- Returns a string representing the line number and entity. -- Usually used in error messages. -- Raises: Not_Valid_Error if Input_Object is not valid (open). procedure Start_Recording (Input_Object : in out Input_Type) is abstract; -- Start recording all characters read into a local buffer. -- Use this when text needs to be formatted into the output -- file *and* be saved for future use. -- Raises: Not_Valid_Error if Input_Object is not valid (open). procedure Stop_Recording_and_Read_Result (Input_Object : in out Input_Type; Result : out String; Len : out Natural) is abstract; -- Stop recording characters read. Put the result into Result, -- and the number of characters written into Len. -- Raises: Not_Valid_Error if Input_Object is not valid (open). -- Lexical routines: subtype Command_Name_Type is String (1 .. 40); function Is_Open_Char (Open_Char : in Character) return Boolean; -- Return True if character is a parameter opening character -- ('<', '[', '{', '('), and False otherwise. function Get_Close_Char (Open_Char : in Character) return Character; -- Return the parameter closing character for an opening character. -- Raises Not_Valid_Error if Open_Char is not an opening character -- ('<', '[', '{', '('). function Get_Open_Char (Close_Char : in Character) return Character; -- Return the parameter opening character for an closing character. -- Raises Not_Valid_Error if Open_Char is not an closing character -- ('>', ']', '}', ')'). procedure Get_Name (Input_Object : in out Input_Type'Class; Name : out ARM_Input.Command_Name_Type; Null_Name_Allowed : in Boolean := False); -- Get a name from the Input_Object. "Names" are sequences of -- alphanumeric characters. If Null_Name_Allowed is False, -- an error is produced if no name is found. procedure Copy_to_String_until_Close_Char (Input_Object : in out Input_Type'Class; Close_Char : in Character; Buffer : out String; Len : out Natural); -- Copy text from Input_Object to Buffer until the matching -- Close_Char is found. Len is the number of characters copied. -- Use this when we only need a string; use recording when we -- need the string *and* we still must process the type. procedure Skip_until_Close_Char (Input_Object : in out Input_Type'Class; Close_Char : in Character); -- Skip text from Input_Object until the matching Close_Char is found. procedure Check_Parameter_Name (Input_Object : in out Input_Type'Class; Param_Name : in ARM_Input.Command_Name_Type; Is_First : in Boolean; Param_Close_Bracket : out Character); -- Check that the name of a parameter (if any) is Param_Name. -- This is the first parameter is Is_First is True; otherwise -- it is a later parameter. (For a later parameter, we'll skip -- the comma and any whitespace.) -- If the parameter has an argument, the opening character will -- be read, and the closing character will be returned in -- in Param_Close_Bracket. If the parameter wasn't found, an -- error message will be produced, and Param_Close_Bracket will -- be set to ' '. subtype Param_Num is Natural range 0 .. 5; procedure Check_One_of_Parameter_Names ( Input_Object : in out Input_Type'Class; Param_Name_1 : in ARM_Input.Command_Name_Type; Param_Name_2 : in ARM_Input.Command_Name_Type; Param_Name_3 : in ARM_Input.Command_Name_Type := (others => ' '); Param_Name_4 : in ARM_Input.Command_Name_Type := (others => ' '); Param_Name_5 : in ARM_Input.Command_Name_Type := (others => ' '); Is_First : in Boolean; Param_Close_Bracket : out Character; Param_Found : out Param_Num); -- Check that the name of a parameter (if any) is one of the given -- names. If the parameter is set to all blanks, it is not used. -- This is the first parameter is Is_First is True; -- otherwise it is a later parameter. (For a later parameter, we'll -- skip the comma and any whitespace.) -- Param_Found will be set to the number of the parameter that was -- found. -- If the parameter has an argument, the opening character will -- be read, and the closing character will be returned in -- in Param_Close_Bracket. If the parameter wasn't found, an -- error message will be produced, Param_Close_Bracket will -- be set to ' ', and Param_Found will be set to 0. end ARM_Input; org.adaic.arm_form/progs/arm_mast.adb0000755000175200010010000015205012273462240017063 0ustar stepheNonewith Ada.Text_IO, Ada.Characters.Handling, Ada.Strings.Fixed, Ada.Strings.Unbounded; with ARM_Input, ARM_File, --ARM_Format, redundant ARM_Output, ARM_Text, ARM_Texinfo, ARM_HTML, ARM_RTF, ARM_Corr; --ARM_Master, --ARM_Contents; package body ARM_Master is -- -- Ada reference manual formatter (ARM_Form). -- -- This package contains the routines to parse the master file, and -- execute it. -- -- --------------------------------------- -- Copyright 2006, 2007, 2009, 2011, 2012, 2013 -- AXE Consultants. All rights reserved. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see . -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 1/05/06 - RLB - Created base package to replace hard-coded main program. -- 1/11/06 - RLB - Continued expanding this; revised to handle separate -- creations for the various kinds of output objects. -- 1/12/06 - RLB - Added more commands for additional properties. -- 1/18/06 - RLB - Added the ExampleFont command. -- 1/27/06 - RLB - Added HTMLTabs command. -- 2/19/06 - RLB - Set Number_Paragraphs for HTML. -- 6/22/06 - RLB - Added LinkNonTerminals command. -- 9/21/06 - RLB - Added the Body_Font command. -- 9/22/06 - RLB - Added the Note_Format command. -- 9/25/06 - RLB - Added the Contents_Format command. -- 10/04/06 - RLB - Added the List_Format command. -- 10/13/06 - RLB - Added specifiable default HTML colors. -- 12/19/07 - RLB - Added MS-DOS file names. -- 5/04/09 - RLB - Added the RTFFooter command. -- 5/06/09 - RLB - Added the RTFVersionName command. -- 10/18/11 - RLB - Changed to GPLv3 license. -- 10/19/11 - RLB - Added Texinfo output (from Stephen Leake). -- 8/31/12 - RLB - Added Output_Path. -- 11/26/12 - RLB - Added Subdivision_Names. -- 3/26/13 - RLB - Added HTMLScript. type Command_Type is ( -- Source commands: Source, TOC, -- Global properties: Show_Index_Entries, Hide_Index_Entries, Show_Annotations, Hide_Annotations, Show_ISO, Hide_ISO, Link_Non_Terminals, Number_Paragraphs, Title, File_Prefix, Example_Font, Body_Font, Note_Format, Contents_Format, List_Format, Subdivision_Names, -- HTML properties: Single_HTML_Output_File, Use_MS_DOS_Names, HTML_Kind_Command, HTML_Nav_Bar, HTML_Tabs, HTML_Script, HTML_Header, HTML_Footer, HTML_Color, -- RTF properties: Single_RTF_Output_File, RTF_Header_Prefix, RTF_Footer_Text, RTF_Footer, RTF_Page_Size, RTF_Fonts, RTF_Version_Name, -- Other commands: Comment, Unknown); type Source_Kind is (A_File, TOC, Empty); type Source_Item (Kind : Source_Kind := Empty) is record case Kind is when Empty => null; -- This item includes no source item. when TOC => null; -- No info for this, it just holds a -- place in the collating order. when A_File => File_Name : String(1..80); File_Name_Len : Natural; Section_Name : String(1..10); Section_Name_Len : Natural; Section_Number : ARM_Contents.Section_Number_Type; Starts_New_Section : Boolean; end case; end record; subtype Source_Count is Integer range 0 .. 100; subtype Source_Index is Source_Count range 1 .. Source_Count'Last; Source_Data : array (Source_Index) of Source_Item; Source_Length : Source_Count := 0; -- Command line (global) properties: Change_Kind : ARM_Format.Change_Kind; -- Changes to generate. Change_Version : ARM_Contents.Change_Version_Type; -- Change version. -- Global properties: Display_Index_Entries : Boolean := False; -- Should Index entries be displayed? Document_Title : ARM_Contents.Versioned_String; -- Document title. Output_File_Prefix : Ada.Strings.Unbounded.Unbounded_String; -- Output file prefix. Include_Annotations : Boolean := False; -- Should annotations be included in the output? Include_ISO_Text : Boolean := False; -- Should ISO text be included in the output? Should_Link_Non_Terminals : Boolean := False; -- Should non-terminals be linked? Should_Number_Paragraphs : Boolean := False; -- Should paragraphs be numbered? Font_of_Examples : ARM_Output.Font_Family_Type := ARM_Output.Fixed; -- Which font should be used for examples? Font_of_Body : ARM_Output.Font_Family_Type := ARM_Output.Roman; -- Which font should be used for the body? Use_ISO_2004_Note_Format : Boolean := True; -- Should we use the ISO 2004 note format, or the one used in the -- Ada 95 standard?? Use_ISO_2004_Contents_Format : Boolean := True; -- Should we use the ISO 2004 contents format, or the one used in the -- Ada 95 standard?? Use_ISO_2004_List_Format : Boolean := True; -- Should we use the ISO 2004 list format, or the one used in the -- Ada 95 standard?? Subdivision_Name_Kind : ARM_Output.Top_Level_Subdivision_Name_Kind := ARM_Output.Section; -- HTML properties: Use_Large_HTML_Files : Boolean := False; -- Use small output files by default. Use_MS_DOS_Filenames : Boolean := False; -- Use long file names by default. HTML_Kind : ARM_HTML.HTML_Type := ARM_HTML.HTML_4_Compatible; HTML_Use_Unicode : Boolean := False; HTML_Index_URL : Ada.Strings.Unbounded.Unbounded_String; HTML_Ref_URL : Ada.Strings.Unbounded.Unbounded_String; HTML_Srch_URL : Ada.Strings.Unbounded.Unbounded_String; HTML_Use_Buttons : Boolean := True; HTML_Nav_On_Top : Boolean := True; HTML_Nav_On_Bottom : Boolean := True; HTML_Tab_Emulation : ARM_HTML.Tab_Emulation_Type := ARM_HTML.Emulate_Fixed_Only; HTML_Script_Text : Ada.Strings.Unbounded.Unbounded_String; -- Empty by default. HTML_Header_Text : Ada.Strings.Unbounded.Unbounded_String; -- Empty by default. HTML_Footer_Text : Ada.Strings.Unbounded.Unbounded_String; -- Empty by default. HTML_Text_Color : ARM_HTML.Color_String := "#000000"; HTML_Background_Color : ARM_HTML.Color_String := "#FFFFF0"; HTML_Link_Color : ARM_HTML.Color_String := "#0000FF"; HTML_VLink_Color : ARM_HTML.Color_String := "#800080"; HTML_ALink_Color : ARM_HTML.Color_String := "#FF0000"; -- RTF properties: Use_Large_RTF_Files : Boolean := False; -- Use small output files by default. Header_Prefix : ARM_Contents.Versioned_String; Footer_Text : ARM_Contents.Versioned_String; Footer_Use_Date : Boolean := True; -- Use the date by default. Footer_Use_Clause_Name : Boolean := True; -- Use the clause name rather than the text above by default. Footer_Use_ISO_Format : Boolean := False; -- Use the normal format. Version_Name : ARM_Contents.Versioned_String; Page_Size : ARM_RTF.Page_Size := ARM_RTF.Letter; -- Use Letter size by default. Serif_Font : ARM_RTF.Serif_Fonts := ARM_RTF.Times_New_Roman; -- Use Times by default. Sans_Serif_Font : ARM_RTF.Sans_Serif_Fonts := ARM_RTF.Arial; -- Use Arial by default. function "+" (Source : Ada.Strings.Unbounded.Unbounded_String) return String renames Ada.Strings.Unbounded.To_String; function "+" (Source : String) return Ada.Strings.Unbounded.Unbounded_String renames Ada.Strings.Unbounded.To_Unbounded_String; function Decode_Command (Name : in ARM_Input.Command_Name_Type) return Command_Type is -- Return the command value for a particular command name: Canonical_Name : constant String := Ada.Characters.Handling.To_Lower (Ada.Strings.Fixed.Trim (Name, Ada.Strings.Right)); begin if Canonical_Name = "source" then return Source; elsif Canonical_Name = "toc" then return TOC; elsif Canonical_Name = "showindexentries" then return Show_Index_Entries; elsif Canonical_Name = "hideindexentries" then return Hide_Index_Entries; elsif Canonical_Name = "showannotations" then return Show_Annotations; elsif Canonical_Name = "hideannotations" then return Hide_Annotations; elsif Canonical_Name = "showiso" then return Show_ISO; elsif Canonical_Name = "hideiso" then return Hide_ISO; elsif Canonical_Name = "linknonterminals" then return Link_Non_Terminals; elsif Canonical_Name = "numberparagraphs" then return Number_Paragraphs; elsif Canonical_Name = "title" then return Title; elsif Canonical_Name = "fileprefix" then return File_Prefix; elsif Canonical_Name = "examplefont" then return Example_Font; elsif Canonical_Name = "bodyfont" then return Body_Font; elsif Canonical_Name = "noteformat" then return Note_Format; elsif Canonical_Name = "contentsformat" then return Contents_Format; elsif Canonical_Name = "listformat" then return List_Format; elsif Canonical_Name = "subdivisionnames" then return Subdivision_Names; elsif Canonical_Name = "singlehtmloutputfile" then return Single_HTML_Output_File; elsif Canonical_Name = "usemsdosfilenames" then return Use_MS_DOS_Names; elsif Canonical_Name = "htmlkind" then return HTML_Kind_Command; elsif Canonical_Name = "htmlnavbar" then return HTML_Nav_Bar; elsif Canonical_Name = "htmltabs" then return HTML_Tabs; elsif Canonical_Name = "htmlscript" then return HTML_Script; elsif Canonical_Name = "htmlheader" then return HTML_Header; elsif Canonical_Name = "htmlfooter" then return HTML_Footer; elsif Canonical_Name = "htmlcolor" then return HTML_Color; elsif Canonical_Name = "singlertfoutputfile" then return Single_RTF_Output_File; elsif Canonical_Name = "rtfheaderprefix" then return RTF_Header_Prefix; elsif Canonical_Name = "rtffootertext" then return RTF_Footer_Text; elsif Canonical_Name = "rtffooter" then return RTF_Footer; elsif Canonical_Name = "rtfpagesize" then return RTF_Page_Size; elsif Canonical_Name = "rtffonts" then return RTF_Fonts; elsif Canonical_Name = "rtfversionname" then return RTF_Version_Name; elsif Canonical_Name = "comment" then return Comment; else return Unknown; end if; end Decode_Command; function Get_Versioned_String (Item_Details : in ARM_Contents.Versioned_String; For_Version : in ARM_Contents.Change_Version_Type) return String is -- Get a versioned item for the appropriate version. use type Ada.Strings.Unbounded.Unbounded_String; begin for I in reverse ARM_Contents.Change_Version_Type'First .. For_Version loop if Item_Details(I) /= Ada.Strings.Unbounded.Null_Unbounded_String then return +Item_Details(I); -- else keep looking, not defined for this version. end if; end loop; return ""; -- Not defined for any version. end Get_Versioned_String; procedure Read_Master_File (Input_Object : in out ARM_Input.Input_Type'Class) is -- Read the master file, saving the information into data structures -- here. procedure Process_Command is Command_Name : ARM_Input.Command_Name_Type; Ch : Character; use type ARM_Output.Size_Type; Command : Command_Type; Close_Ch : Character; procedure Get_Open_Char is -- Get an open character, setting Close_Ch appropriately; -- generate an error if there isn't one. Ch : Character; begin ARM_Input.Get_Char (Input_Object, Ch); if ARM_Input.Is_Open_Char (Ch) then -- Start parameter: Close_Ch := ARM_Input.Get_Close_Char (Ch); else Ada.Text_IO.Put_Line ("** Parameter missing for command on line" & ARM_Input.Line_String (Input_Object)); Close_Ch := ' '; end if; end Get_Open_Char; function Get_Single_String return String is -- Returns the (single) parameter of a command. Item : String(1..2000); ILen : Natural := 0; begin Get_Open_Char; if Close_Ch /= ' ' then -- Copy over the string: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Close_Ch, Item, ILen); return Item(1..ILen); else -- didn't find an opening character. return ""; end if; end Get_Single_String; procedure Get_Boolean (Param_Name : in ARM_Input.Command_Name_Type; Result : out Boolean; Is_First : in Boolean := False) is -- Get a boolean value from a parameter named Param_Name. Ch, Close_Ch : Character; begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => Param_Name, Is_First => Is_First, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the Boolean character: ARM_Input.Get_Char (Input_Object, Ch); --Ada.Text_IO.Put_Line(" Bool=" & Ch); case Ch is when 'F' | 'f' | 'N' | 'n' => Result := False; when 'T' | 't' | 'Y' | 'y' => Result := True; when others => Ada.Text_IO.Put_Line (" ** Bad value for boolean parameter " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); end case; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for boolean parameter " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; end Get_Boolean; procedure Process_Versioned_String (Item : in out ARM_Contents.Versioned_String) is -- @Command{Version=[],Text=[]} Param_Close_Ch, Ch : Character; Text : String(1..80); TLen : Natural := 0; Version : ARM_Contents.Change_Version_Type; begin --Ada.Text_IO.Put_Line("Process versioned item command"); Get_Open_Char; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Version" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Get the version character: ARM_Input.Get_Char (Input_Object, Ch); Version := ARM_Contents.Change_Version_Type(Ch); --Ada.Text_IO.Put_Line(" Version=" & Version); ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Param_Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for change version on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Text, TLen); --Ada.Text_IO.Put_Line(" Text=" & Text(1..TLen)); Item(Version) := +Text(1..TLen); -- else no parameter, error already produced. end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end Process_Versioned_String; procedure Process_RTF_Fonts is -- @RTFFonts{Serif=[Times|Souvenir]},SansSerif=[Arial|Helvetica]} Param_Close_Ch : Character; Item : String(1..80); ILen : Natural := 0; begin Get_Open_Char; --Ada.Text_IO.Put_Line("Process RTF Fonts"); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Serif" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the font name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("RTF Serif Font=" & Item(1..ILen)); declare Name : constant String := Ada.Characters.Handling.To_Lower (Item(1..ILen)); begin if Name = "times" then Serif_Font := ARM_RTF.Times_New_Roman; elsif Name = "souvenir" then Serif_Font := ARM_RTF.Souvenir; else Ada.Text_IO.Put_Line ("** Unknown serif font name: " & Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; -- else no parameter, error already produced. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "SansSerif" & (10..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the font name: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("RTF Sans_Serif Font=" & Item(1..ILen)); declare Name : constant String := Ada.Characters.Handling.To_Lower (Item(1..ILen)); begin if Name = "arial" then Sans_Serif_Font := ARM_RTF.Arial; elsif Name = "helvetica" then Sans_Serif_Font := ARM_RTF.Helvetica; else Ada.Text_IO.Put_Line ("** Unknown serif font name: " & Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; -- else no parameter, error already produced. end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end Process_RTF_Fonts; procedure Process_HTML_Kind is -- @HTMLKind{Version=[3|4Comp|4],Unicode=[T|F]} Param_Close_Ch : Character; Item : String(1..80); ILen : Natural := 0; begin Get_Open_Char; --Ada.Text_IO.Put_Line("Process HTML Kind"); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Version" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the version: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("HTML version and kind=" & Item(1..ILen)); declare Kind : constant String := Ada.Characters.Handling.To_Lower (Item(1..ILen)); begin if Kind = "3" then HTML_Kind := ARM_HTML.HTML_3; elsif Kind = "4comp" then HTML_Kind := ARM_HTML.HTML_4_Compatible; elsif Kind = "4" then HTML_Kind := ARM_HTML.HTML_4_Only; else Ada.Text_IO.Put_Line ("** Unknown HTML version: " & Kind & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; -- else no parameter, error already produced. end if; Get_Boolean ("Unicode" & (8..ARM_Input.Command_Name_Type'Last => ' '), HTML_Use_Unicode); if HTML_Use_Unicode then Ada.Text_IO.Put_Line("HTML will use Unicode characters where appropriate"); else Ada.Text_IO.Put_Line("HTML will use Unicode characters only when explicitly requested"); end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end Process_HTML_Kind; procedure Process_HTML_Nav_Bar is --@HTMLNavBar{RefName=[],SrchName=[], -- UseButtons=[T|F],OnTop=[T|F],OnBottom=[T|F]} Param_Close_Ch : Character; Item : String(1..80); ILen : Natural := 0; begin Get_Open_Char; --Ada.Text_IO.Put_Line("Process HTML Nav Bar"); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "RefName" & (8..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the version: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("HTML reference URL=" & Item(1..ILen)); HTML_Ref_Url := + Item(1..ILen); -- else no parameter, error already produced. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "SrchName" & (9..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the version: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("HTML search URL=" & Item(1..ILen)); HTML_Srch_Url := + Item(1..ILen); -- else no parameter, error already produced. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "IndexName" & (10..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the version: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); Ada.Text_IO.Put_Line("HTML index URL=" & Item(1..ILen)); HTML_Index_Url := + Item(1..ILen); -- else no parameter, error already produced. end if; Get_Boolean ("UseButtons" & (11..ARM_Input.Command_Name_Type'Last => ' '), HTML_Use_Buttons); if HTML_Use_Buttons then Ada.Text_IO.Put_Line("HTML navigation will use buttons"); else Ada.Text_IO.Put_Line("HTML navigation will use text labels"); end if; Get_Boolean ("OnTop" & (6..ARM_Input.Command_Name_Type'Last => ' '), HTML_Nav_On_Top); if HTML_Nav_On_Top then Ada.Text_IO.Put_Line("HTML navigation bar will appear on top of pages"); end if; Get_Boolean ("OnBottom" & (9..ARM_Input.Command_Name_Type'Last => ' '), HTML_Nav_On_Bottom); if HTML_Nav_On_Bottom then Ada.Text_IO.Put_Line("HTML navigation bar will appear on bottom of pages"); end if; ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end Process_HTML_Nav_Bar; procedure Process_HTML_Color is --@HTMLColor{Text=[,Background=[], -- Link=[],VLink=[],ALink=[]} procedure Get_Color (Param_Name : in ARM_Input.Command_Name_Type; Is_First : in Boolean; Result : out ARM_HTML.Color_String) is -- Get a color value from a parameter named Param_Name. Ch, Close_Ch : Character; Color : ARM_HTML.Color_String := (others => ' '); begin ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => Param_Name, Is_First => Is_First, Param_Close_Bracket => Close_Ch); if Close_Ch /= ' ' then -- Get the color characters: for I in ARM_HTML.Color_String'range loop ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then Ada.Text_IO.Put_Line (" ** HTML color too short for " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); exit; end if; Color(I) := Ch; end loop; --Ada.Text_IO.Put_Line(" Color=" & Color); Result := Color; ARM_Input.Get_Char (Input_Object, Ch); if Ch /= Close_Ch then Ada.Text_IO.Put_Line (" ** Bad close for color parameter " & Ada.Strings.Fixed.Trim (Param_Name, Ada.Strings.Right) & " on line " & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; -- else no parameter. Weird. end if; end Get_Color; begin Get_Open_Char; --Ada.Text_IO.Put_Line("Process HTML Color"); Get_Color ("Text" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Result => HTML_Text_Color); Ada.Text_IO.Put_Line("HTML text color is " & HTML_Text_Color); Get_Color ("Background" & (11..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Result => HTML_Background_Color); Ada.Text_IO.Put_Line("HTML background color is " & HTML_Background_Color); Get_Color ("Link" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Result => HTML_Link_Color); Ada.Text_IO.Put_Line("HTML link color is " & HTML_Link_Color); Get_Color ("VLink" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Result => HTML_VLink_Color); Ada.Text_IO.Put_Line("HTML visited link color is " & HTML_VLink_Color); Get_Color ("ALink" & (6..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Result => HTML_ALink_Color); Ada.Text_IO.Put_Line("HTML active link color is " & HTML_ALink_Color); ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end Process_HTML_Color; procedure Process_Source_Command is -- @Source{Name=,SectionName=, -- SectionNumber=,NewSection=[T|F]} Param_Close_Ch : Character; Item : String(1..80); ILen : Natural := 0; use type ARM_Contents.Section_Number_Type; begin Get_Open_Char; if Source_Length = Source_Count'Last then Ada.Text_IO.Put_Line ("** Too many source files on line" & ARM_Input.Line_String (Input_Object)); else Source_Length := Source_Length + 1; --Ada.Text_IO.Put_Line("Process source command - Length =" & Source_Count'Image(Source_Length)); Source_Data(Source_Length) := (Kind => A_File, File_Name => (others => ' '), File_Name_Len => 0, Section_Name => (others => ' '), Section_Name_Len => 0, Section_Number => 0, Starts_New_Section => True); ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "Name" & (5..ARM_Input.Command_Name_Type'Last => ' '), Is_First => True, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); --Ada.Text_IO.Put_Line(" Name=" & Item(1..ILen)); if Ada.Strings.Fixed.Index (Item(1..ILen), ".") = 0 then -- Append the extension: Source_Data(Source_Length).File_Name_Len := ILen + 4; Ada.Strings.Fixed.Move ( Target => Source_Data(Source_Length).File_Name, Source => Ada.Characters.Handling.To_Lower (Item(1..ILen)) & ".mss"); else Source_Data(Source_Length).File_Name_Len := ILen; Ada.Strings.Fixed.Move ( Target => Source_Data(Source_Length).File_Name, Source => Ada.Characters.Handling.To_Lower (Item(1..ILen))); end if; -- else no parameter, error already produced. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "SectionName" & (12..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); --Ada.Text_IO.Put_Line(" Section_Name=" & Item(1..ILen)); Source_Data(Source_Length).Section_Name_Len := ILen; Ada.Strings.Fixed.Move ( Target => Source_Data(Source_Length).Section_Name, Source => Item(1..ILen)); -- else no parameter, error already produced. end if; ARM_Input.Check_Parameter_Name (Input_Object, Param_Name => "SectionNumber" & (14..ARM_Input.Command_Name_Type'Last => ' '), Is_First => False, Param_Close_Bracket => Param_Close_Ch); if Param_Close_Ch /= ' ' then -- Copy over the term: ARM_Input.Copy_to_String_until_Close_Char ( Input_Object, Param_Close_Ch, Item, ILen); --Ada.Text_IO.Put_Line(" Section_Number=" & Item(1..ILen)); if ILen = 1 and then Item(1) in 'A'..'Z' then Source_Data(Source_Length).Section_Number := 31 + Character'Pos(Item(1)) - Character'Pos('A'); elsif ILen = 1 and then Item(1) in 'a'..'z' then Source_Data(Source_Length).Section_Number := 31 + Character'Pos(Item(1)) - Character'Pos('a'); else begin Source_Data(Source_Length).Section_Number := ARM_Contents.Section_Number_Type'Value(Item(1..Ilen)); exception when Constraint_Error => Ada.Text_IO.Put_Line ("** Illegal section number " & Item(1..ILen) & " on line" & ARM_Input.Line_String (Input_Object)); end; end if; -- else no parameter, error already produced. end if; Get_Boolean ("NewSection" & (11..ARM_Input.Command_Name_Type'Last => ' '), Source_Data(Source_Length).Starts_New_Section); ARM_Input.Get_Char (Input_Object, Ch); if Ch = Close_Ch then null; else Ada.Text_IO.Put_Line ("** Missing closing character for command on line" & ARM_Input.Line_String (Input_Object)); ARM_Input.Replace_Char (Input_Object); end if; end if; end Process_Source_Command; begin -- We don't have any non-identifier commands here, so we can -- go directly to getting the name: ARM_Input.Get_Name (Input_Object, Command_Name); Command := Decode_Command (Command_Name); --Ada.Text_IO.Put_Line("Process command=" & Command_Type'Image(Command)); --Ada.Text_IO.Put_Line("Process command=" & Command_Type'Image(Command) & " Name=" & Command_Name); case Command is when Comment => -- @Comment{} -- Skip the parameter. Get_Open_Char; if Close_Ch /= ' ' then ARM_Input.Skip_until_Close_Char (Input_Object, Close_Ch); end if; -- Global properties: when Show_Index_Entries => -- @ShowIndexEntries Display_Index_Entries := True; Ada.Text_IO.Put_Line("Show Index Entries"); when Hide_Index_Entries => -- @HideIndexEntries Display_Index_Entries := False; Ada.Text_IO.Put_Line("Hide Index Entries"); when Show_Annotations => -- @ShowAnnotations Include_Annotations := True; Ada.Text_IO.Put_Line("Show Annotations"); when Hide_Annotations => -- @HideAnnotations Include_Annotations := False; Ada.Text_IO.Put_Line("Hide Annotations"); when Show_ISO => -- @ShowISO Include_ISO_Text := True; Ada.Text_IO.Put_Line("Show ISO Text"); when Hide_ISO => -- @HideISO Include_ISO_Text := False; Ada.Text_IO.Put_Line("Hide ISO Text"); when Link_Non_Terminals => -- @LinkNonTerminals Should_Link_Non_Terminals := True; Ada.Text_IO.Put_Line("Link Non-Terminals"); when Number_Paragraphs => -- @NumberParagraphs Should_Number_Paragraphs := True; Ada.Text_IO.Put_Line("Number Paragraphs"); when Title => -- @Title{Version=[],Text=[]} Process_Versioned_String (Document_Title); when File_Prefix => -- @FilePrefix{} Output_File_Prefix := +Ada.Characters.Handling.To_Lower (Get_Single_String); Ada.Text_IO.Put_Line("File Prefix is " & (+Output_File_Prefix)); when Example_Font => -- @ExampleFont{Swiss|Fixed|Roman} declare Font_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if Font_Name = "swiss" then Font_of_Examples := ARM_Output.Swiss; Ada.Text_IO.Put_Line("Examples in swiss font"); elsif Font_Name = "fixed" then Font_of_Examples := ARM_Output.Fixed; Ada.Text_IO.Put_Line("Examples in fixed-width font"); elsif Font_Name = "roman" then Font_of_Examples := ARM_Output.Roman; Ada.Text_IO.Put_Line("Examples in roman font"); else Ada.Text_IO.Put_Line ("** Unknown example font name: " & Font_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; when Body_Font => -- @BodyFont{Swiss|Roman} declare Font_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if Font_Name = "swiss" then Font_of_Body := ARM_Output.Swiss; Ada.Text_IO.Put_Line("Body in swiss font"); elsif Font_Name = "roman" then Font_of_Body := ARM_Output.Roman; Ada.Text_IO.Put_Line("Body in roman font"); else Ada.Text_IO.Put_Line ("** Unknown body font name: " & Font_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; when Note_Format => -- @NoteFormat{Ada95|ISO2004} declare Format_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if Format_Name = "ada95" then Use_ISO_2004_Note_Format := False; Ada.Text_IO.Put_Line("Notes in Ada 95 standard format"); elsif Format_Name = "iso2004" then Use_ISO_2004_Note_Format := True; Ada.Text_IO.Put_Line("Notes in ISO 2004 standard format"); else Ada.Text_IO.Put_Line ("** Unknown note format name: " & Format_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; when Contents_Format => -- @ContentsFormat{Ada95|ISO2004} declare Format_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if Format_Name = "ada95" then Use_ISO_2004_Contents_Format := False; Ada.Text_IO.Put_Line("Table of Contents in Ada 95 standard format"); elsif Format_Name = "iso2004" then Use_ISO_2004_Contents_Format := True; Ada.Text_IO.Put_Line("Table of Contents in ISO 2004 standard format"); else Ada.Text_IO.Put_Line ("** Unknown contents format name: " & Format_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; when List_Format => -- @ListFormat{Ada95|ISO2004} declare Format_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if Format_Name = "ada95" then Use_ISO_2004_List_Format := False; Ada.Text_IO.Put_Line("Lists in Ada 95 standard format"); elsif Format_Name = "iso2004" then Use_ISO_2004_List_Format := True; Ada.Text_IO.Put_Line("Lists in ISO 2004 standard format"); else Ada.Text_IO.Put_Line ("** Unknown list format name: " & Format_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; when Subdivision_Names => -- @SubdivisionNames{Chapter|Section|Clause} declare SD_Name : constant String := Ada.Characters.Handling.To_Lower ( Get_Single_String); begin if SD_Name = "chapter" then Subdivision_Name_Kind := ARM_Output.Chapter; Ada.Text_IO.Put_Line("Top-level subdivisions known as Chapters"); elsif SD_Name = "section" then Subdivision_Name_Kind := ARM_Output.Section; Ada.Text_IO.Put_Line("Top-level subdivisions known as Sections"); elsif SD_Name = "clause" then Subdivision_Name_Kind := ARM_Output.Clause; Ada.Text_IO.Put_Line("Top-level subdivisions known as Clauses"); else Ada.Text_IO.Put_Line ("** Unknown subdivision name: " & SD_Name & " on line" & ARM_Input.Line_String (Input_Object)); end if; end; -- HTML properties: when Single_HTML_Output_File => -- @Single_HTML_Output_File Use_Large_HTML_Files := True; Ada.Text_IO.Put_Line("Single HTML Output File"); when Use_MS_DOS_Names => -- @Single_HTML_Output_File Use_MS_DOS_Filenames := True; Ada.Text_IO.Put_Line("Use MS-DOS (8.3) file names for HTML output files"); when HTML_Kind_Command => --@HTMLKind{Version=[3|4Comp|4],Unicode=[T|F]} Process_HTML_Kind; when HTML_Nav_Bar => --@HTMLNavBar{RefName=[],SrchName=[],UseButtons=[T|F],OnTop=[T|F],OnBottom=[T|F]} Process_HTML_Nav_Bar; when HTML_Tabs => -- @HTMLTabs{[SingleSpace|QuadSpace|EmulateFixedOnly|EmulateFixedOnlyQuad|EmulateAll]} declare Tabs : constant String := Ada.Characters.Handling.To_Lower (Get_Single_String); begin if Tabs = "singlespace" then HTML_Tab_Emulation := ARM_HTML.Single_Space; elsif Tabs = "quadspace" then HTML_Tab_Emulation := ARM_HTML.Quad_Space; elsif Tabs = "emulatefixedonly" then HTML_Tab_Emulation := ARM_HTML.Emulate_Fixed_Only; elsif Tabs = "emulatefixedonlyquad" then HTML_Tab_Emulation := ARM_HTML.Emulate_Fixed_Only_Quad; elsif Tabs = "emulateall" then HTML_Tab_Emulation := ARM_HTML.Emulate_All; else Ada.Text_IO.Put_Line ("** Unknown tab emulation name: " & Tabs & " on line" & ARM_Input.Line_String (Input_Object)); end if; Ada.Text_IO.Put_Line("HTML Tab Emulation is " & ARM_HTML.Tab_Emulation_Type'Image(HTML_Tab_Emulation)); end; when HTML_Script => --@HTMLHeader{ tags) that should go directly before the on each page. By default, this is empty. This command was designed to allow placing Google Analytics code on each page for web sites that use that for tracking. @HTMLHeader{} Specifies HTML markup for the header of the the document. This will be repeated on every page, and needs to be a self-contained HTML fragment. By default, this is empty. @HTMLFooter{} Specifies HTML markup for the footer of the the document. This will be repeated on every page, and needs to be a self-contained HTML fragment. By default, this is empty. @HTMLColor{Text=[,Background=[],Link=[],VLink=[], ALink=[]} Specifies the default text, background and link colors for the document. is a color in standard HTML format ("#rrggbb", with each letter replaced by a hex digit). VLink is the color for visited links; ALink is the color for links being clicked. The default is: @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#0000FF], VLink=[#800080],ALink=[#FF0000]} That is, black text, cream background, blue links, purple visited links, and red active links. RTF Output properties: @SingleRTFOutputFile If given in the master file, generate a single large file for the output, rather than one file per section. If this is not given, smaller files are generated. @RTFHeaderPrefix{Version=[],Text=[]} The text given in the header before the title; this is *RTF* text; no embedded commands can be given here. If no header prefix is given for the current version, the prefix of the previous version is used; to use the same prefix for all versions, give the prefix for Version=[0]. If this is empty, only the title will be used. @RTFFooterText{Version=[],Text=[]} The fixed text given in the footer; this is *RTF* text; no embedded commands can be given here. If no footer text is given for the current version, the text of the previous version is used; to use the same text for all versions, give the prefix for Version=[0]. This text will not be used if UseClauseName is True. @RTFFooter{UseDate=[T|F],UseClauseName=[T|F],UseISOFormat=[T|F]} Specifies the format of the footer. The date will be included if UseDate is true (T), otherwise it will be omitted; by default it is included. The footer text will be the name of the clause that starts the page (other clauses may start on the page) if UseClauseName is true (T), otherwise it will be the FooterText. The defailt is to use clause names. The text font and size will match the ISO requirements if UseISOFormat is true (T) - this means the footer will be in a Swiss font with multiple sizes; otherwise (and this is the default) the footer will be in the body font with a single size. @RTFPageSize{Letter|A4|HalfLetter|Ada95} Specifies the size of the RTF output; Letter is used if this is not specified. Letter is 8.5"x11"; A4 is European standard size; HalfLetter is 5.5"x8.5"; Ada95 is 7"x9". @RTFFonts{Serif=[Times|Souvenir],SansSerif=[Arial|Helvetica]} Specifies the specific fonts used for the Serif and Sans Serif fonts. If not specified, Times ("Times New Roman") and Arial are used. @RTFVersionName{Version=[],Text=[]} The specified text names the version as the "author" of any revisions. For instance, for the Ada Standard, @RTFVersionName{Version=[2],Text=[Amendment 1]} gives the author name "Amendment 1" to all version 2 revisions. Other commands: @comment{} - The text is a comment to the master file, and is ignored on output. --------------------- Source file (.MSS) command summary: Meta-commands: @; - Signifies nothing. Used to break a parameterless command from following text: "@LegalityName@;s" (otherwise the command "LegalityNames" would be looked for). @: - After a period, signifies an sentence ending period, rather than a initial period. Not used currently, but remains in text in case someone cares eventually. (Only matters if the amount of space after sentences is different than the amount between words within a sentence.) @| - Marks a potential line break point, without inserting a hyphen. (Scribe says that it is a "zero-length word".) Not used currently, as the RTF command (\zwbo) prints a square box in both Word 97 and Word 2000 -- and no break. Similarly, zero-width space in HTML 4.0 doesn't work on Internet Exploder 4.1 - it also prints a square box and no break. @! - Marks a potential line break point, inserting a hyphen if the break is used. (A so-called "soft-hyphen"). Unlike the above, this actually works in Word 97 and HTML. ­. Text commands: @@ - the literal character '@'. @\ - A tab, or end of centered text. Also used to mark the separation between hanging text and the rest of the paragraph. @^ - Sets a tab stop at the current text location. (*Can't implement in RTF and HTML does not have tabs at all; has been removed from the text *) @ - [@] - A hard space; cannot be used to insert a line break. @* - Line break inside a paragraph. @+{} - Superscript text (text size will be smaller). @-{} - Subscript text (text size will be smaller). @b{} - Bold text. @i{} - Italic text. @r{} - Roman font text. @ri{} -Roman italic text (use for comments in examples). @s{} - Swiss font text. @f{} - Fixed-width font text. @shrink{} - Text is one size smaller. (Typically 1 point smaller). @grow{} - Text is one size larger. (Typically 1 point larger). @black{} - Text is in a black color. @red{} - Text is in a red color. @green{} - Text is in a green color. @blue{} - Text is in a blue color. @comment{} - The text is a comment to the input files, and is ignored on output. @newpage - Insert a page break. Ends a paragraph. @rmnewpage - Insert a page break in the RM (that is, when HideAnnotations is used), ignored otherwise. Ends a paragraph. Use to insert page breaks to make the printed RM look better. @newcolumn - Insert a column break. Only allowed in a multi-column formats. Ends a paragraph. @newpagever{Version=[} - Insert a page break if we are generating (and ends a paragraph). Otherwise, does nothing. @rmnewpagever{Version=[} - Insert a page break in the RM (that is, when HideAnnotations is used) and we are generating , ignored otherwise. Ends a paragraph. Use to insert page breaks to make the printed RM look better. @isoonlyrmnewpagever{Version=[} - Insert a page break in the RM (that is, when HideAnnotations is used), @ShowISO was given in the master file, and we are generating , ignored otherwise. Ends a paragraph. Use to insert page breaks to make the printed RM look better. @notisormnewpagever{Version=[} - Insert a page break in the RM (that is, when HideAnnotations is used), @ShowISO was not given in the master file, and we are generating , ignored otherwise. Ends a paragraph. Use to insert page breaks to make the printed RM look better. @newcolumnver{Version=[} - - Insert a column break if we are generating , otherwise does nothing. Only allowed in a multi-column formats. Ends a paragraph. @softpage - Insert a soft page break in a format that does not generally allow one. A page is allowed (but not required) at this point. [Note: This doesn't seem to work in Word 97, but we've kept it anyway.] @noprefix - The following paragraph does not have a prefix (that is, hanging text, numbers, or bullets). For example, if the paragraph is in a bulleted list, it will not have a bullet. This command must be given before any text for the paragraph (including index entries and even spaces in example formats). @keepnext - Keep this paragraph with the next one (usually used on leadins, like "The following example shows...:"). This command must be given before any text for the paragraph. @leading - This paragraph leads in an example or list. Cut the space following the paragraph (usually by 30%). This command must be given before any text for the paragraph. @trailing - This paragraph ends an item of some sort. Increase the space following the paragraph (usually by 50%). This command must be given before any text for the paragraph. @noparanum - This paragraph has no number. This command must be given before any text for the paragraph. @thinline - Draw a thin separator line across the page. Ends any paragraph. @thickline - Draw a thick separator line across the page. Ends any paragraph. -- Section/Clause commands: @LabeledSection{} - Start a labeled section (chapter). The title will be "text". The formatter assigns section numbers. @LabeledSectionNoBreak{} - Start a labeled section (chapter). The title will be "text". The formatter assigns section numbers. No page break before it. @LabeledAnnex{} - Start a labeled (unqualified) annex. The title will be "text". The formatter assigns annex letters. @LabeledInformativeAnnex{} - Start a labeled informative annex. The title will be "text". The formatter assigns annex letters. @LabeledNormativeAnnex{} - Start a labeled normative annex. The title will be "text". The formatter assigns annex letters. @LabeledClause{} - Start a labeled clause. The title will be "text". The formatter assigns clause numbers. @LabeledSubClause{} - Start a labeled subclause. The title will be "text". The formatter assigns subclause numbers. @LabeledSubSubClause{} - Start a labeled subsubclause. The title will be "text". The formatter assigns subsubclause numbers. @LabeledRevisedAnnex{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled (unqualified) annex. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that annex references in commands always use the new_text name.) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedNormativeAnnex{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled normative annex. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that annex references in commands always use the new_text name.) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedInformativeAnnex{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled informative annex. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that annex references in commands always use the new_text name.) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedSection{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled section (chapter). The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that clause references in commands always use the new_text name.) The formatter assigns clause numbers. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedClause{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled clause. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that clause references in commands always use the new_text name.) The formatter assigns clause numbers. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedSubClause{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled subclause. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that clause references in commands always use the new_text name.) The formatter assigns subclause numbers. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledRevisedSubSubClause{Version=[], [InitialVersion=[],]New=[],Old=[]} - Start a labeled subsubclause. The title will be "new_text". If we are generating an old version of the document, the title is "old_text" instead. (Note that clause references in commands always use the new_text name.) The formatter assigns subsubclause numbers. Version is the version number of the change (see @ChgRef for details); InitialVersion is the original insertion version of the Old text (this defaults to 0 if not given). @LabeledAddedSection{Version=[],Name=[]} - Start a labeled section (chapter). The title will be "new_text". If we are generating an old version of the document, this clause does not exist. (Any clause references ought to be in new text.) The formatter assigns clause numbers. Version is the version number of the change (see @ChgRef for details). @LabeledAddedClause{Version=[],Name=[]} - Start a labeled clause. The title will be "new_text". If we are generating an old version of the document, this clause does not exist. (Any clause references ought to be in new text.) The formatter assigns clause numbers. Version is the version number of the change (see @ChgRef for details). @LabeledAddedSubClause{Version=[],Name=[]} - Start a labeled subclause. The title will be "new_text". If we are generating an old version of the document, this subclause does not exist. (Any subclause references ought to be in new text.) The formatter assigns subclause numbers. Version is the version number of the change (see @ChgRef for details). @LabeledAddedSubSubClause{Version=[],Name=[]} - Start a labeled subsubclause. The title will be "new_text". If we are generating an old version of the document, this subsubclause does not exist. (Any subsubclause references ought to be in new text.) The formatter assigns subsubclause numbers. Version is the version number of the change (see @ChgRef for details). @LabeledAddedAnnex{Version=[],Name=[]]} - Start a labeled (unqualified) annex. The title will be "new_text". If we are generating an old version of the document, this annex does not appear. (Any annex references in commands ought to be "new text".) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details). @LabeledAddedNormativeAnnex{Version=[],Name=[]]} - Start a labeled normative annex. The title will be "new_text". If we are generating an old version of the document, this annex does not appear. (Any annex references in commands ought to be "new text".) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details). @LabeledAddedInformativeAnnex{Version=[],Name=[]} - Start a labeled informative annex. The title will be "new_text". If we are generating an old version of the document, this annex does not appear. (Any annex references in commands ought to be "new text".) The formatter assigns annex letters. Version is the version number of the change (see @ChgRef for details). @LabeledDeletedClause{Version=[],Name=[]} - Start a labeled clause. The title will be "old_text". If we are generating a new version of the document, this clause does not exist. (Any clause references ought to be in old deleted text.) The formatter assigns clause numbers. Version is the version number of the change (see @ChgRef for details). [Note: We do not support deleting sections or annexes.] @LabeledDeletedSubClause{Version=[],Name=[]} - Start a labeled subclause. The title will be "old_text". If we are generating a new version of the document, this subclause does not exist. (Any subclause references ought to be in old deleted text.) The formatter assigns subclause numbers. Version is the version number of the change (see @ChgRef for details). @LabeledDeletedSubSubClause{Version=[],Name=[]} - Start a labeled subsubclause. The title will be "old_text". If we are generating a new version of the document, this subsubclause does not exist. (Any subsubclause references ought to be in old deleted text.) The formatter assigns subsubclause numbers. Version is the version number of the change (see @ChgRef for details). @UnnumberedSection{} - Start an unnumbered section. (These are the Forward and Introduction). This *can* be referenced by a reference, and will appear in the table of contents. @Subheading{} - Start an unnumbered subclause (a subclause of an unnumbered section). These are formatting only, they cannot be referenced, nor do they appear in the table of contents. @Heading{} - Start an unnumbered clause (a clause of an unnumbered section). These are formatting only, they cannot be referenced, nor do they appear in the table of contents. @Center{} - Center the otherwise normal text. Note that this is a paragraph style and is treated like a header. @Right{} - Right justify the otherwise normal text. Note that this is a paragraph style and is treated like a header. @PrefaceClause{} - Start a new clause without numbering or title - just a page break to an odd page. @RefSec{} - Generates a reference to the clause "title". (This must match exactly except for case). The reference is of the form "<clause number>, ``<title>''". (The ARG has directed that this be changed to '<clause number>, "<title>"'). @RefSecNum{<title>} - Generates a reference to the clause "title". (This must match exactly except for case). The reference is of the form "<clause number>". @RefSecbyNum{<num>} - Generates a reference to the clause with <num> as a clause number. This is intended to be used internally to the tool, not in document source (the tool assigns the clause numbers). @LocalTarget{Target=[<target-text>],Text=[<text>]} - Generates a target for future @LocalLink commands at the current location. <target-text> should be short, using alphanumeric characters. <text> will be generated normally, using the current formatting (no formatting is allowed in <text>). @LocalLink{Target=[<target-text>],Sec=[<title>],Text=[<text>]} - Generates a link to the target specifed in the section given by "title" (this should have been defined by a @LocalTarget command). <text> will be generated as the body of the link, using the current formatting (no formatting in <text>). @URLLink{URL=[<URL>],Text=[<text>]} - Generates a link to the URL specified; <text> will be the body of the link, using the current formatting (no formatting in <text>). The URL should be a complete URL, including "http://". @AILink{AI=[<AI>],Text=[<text>]} - Generates a link to the AI specified; <text> will be the body of the link, using the current formatting (no formatting in <text>). The AI should be an AI number in the full format (AI95-0yyyy-zz, AI05-yyyy-z, or SI99-yyyy-z). -- Ada specific commands: @nt{<text>} - A non-terminal in normal text. This will be set in a Swiss (sans-serif) font. Also, for HTML, this will linked to the definition text; use @ntf instead if this is not a real non-terminal. @ntf{<text>} - Format as a non-terminal in normal text. This will be set in a Swiss (sans-serif) font. @key{<text>} - A keyword in normal text. This will be set in boldface. @exam{<text>} - Example text occurring in normal text. This will be set in the example font (which is selected in the master file). @examcom{<text>} - The body of an example comment; this is shown in the roman font in italics. (This is the same as the @RI command, but by using a separate name, we can change the format in the future.) @redundant{<text>} - Marks text thought to be unnecessary in the RM. That is, the rules are explained elsewhere. The text is formatted normally. When annotations are shown, this text is surrounded in brackets. When annotations are not shown, no special formatting is used. @syn{[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} - Marks a syntax production. <Production> contains @syn2 (and @synf) commands for RHS non-terminals. <Tabset> defines any tabs needed by the <Production>. The <Non-terminal> is indexed. The <Non-Terminal> and <Production> (and the clause number) are sent to the syntax manager. Also, saves <Non-terminal> for any following @Syn2 to use. The command also writes @nt<Non-Terminal> ::= <Production> to the output. Note: <Non-Terminal> and <Production> allow @Chg commands. @syni{<prefix>} - Generates <prefix> in the italics of a non-terminal prefix. @syn2{<name>} - Marks a non-terminal name in the production of a syntax rule. If the current non-terminal is not null, generates a cross reference entry: <Name> in <Non-Terminal> at <ClauseNum>. Also, generate an index entry for the item: @Defn2(Term=<Name>,Sec=@i{used}). (For the purposes of the index, all of Annex P is a single paragraph). Otherwise, is the same as @nt. @synf{<name>} - Marks a non-terminal name in the production of a syntax rule, for which there is no formal definition in the document. (Character set names in Ada fall into this category). If the current non-terminal is not null, generates a cross reference entry: <Name> in <Non-Terminal> at <ClauseNum>. Also, generate an index entry for the item: @Defn2(Term=<Name>,Sec=@i{used}). (For the purposes of the index, all of Annex P is a single paragraph). Otherwise, is the same as @ntf. @syntaxsummary -- Generate the syntax summary at this point. *No paragraph numbers*! @syntaxxref -- Generate the syntax cross-reference at this point. *No paragraph numbers*! @AddedSyn{Version=[<Version>],[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} Add a syntax production for Version. Otherwise, the meaning is the same as for @Syn, above. Note: <Non-terminal> and <Production> need @Chg commands; this command only adds processing for "::=" and overall inclusion or skipping when necessary. @DeletedSyn{Version=[<Version>],[Tabs=<Tabset>, ]LHS=<Non-terminal>, RHS=<Production>} Delete a syntax production for version. Otherwise, the meaning is the same as for @Syn, above. Note: <Non-terminal> and <Production> need @Chg commands; this command only adds processing for "::=" and overall inclusion or skipping when necessary. @Attribute{Prefix=<Prefix>,AttrName=<Name>,Text=<Text>} Defines an attribute. Creates a hanging text item <Prefix>'<Name>, with the specified text. The text can contain arbitrary commands; it will be run through the full evaluation code. The attribute and text is also sent to a database used to later create Annex K. (This uses the current value of PrefixType.) Finally, the attribute <Name> is indexed as by calling @Defn2{Term=[Attribute], Sec=<Name>}, and as by calling @Defn{<Name> attribute}. See also ChgAttribute. @AttributeLeading{Prefix=<Prefix>,AttrName=<Name>,Text=<Text>} Same as attribute, except that the first paragraph is a "Leading" paragraph. (Use when the second paragraph is a DescExample, such as when a function specification is given.) @AttributeList Dumps the summary list of all attributes from the attribute database to the output file. @PrefixType{text} Save the indicated text to use as part of any following attribute definitions. The text is also written to the output. The text should fit in the phrase: "For {text}:". For instance, the text could be "every scalar subtype S". See also ChgPrefixType. @EndPrefixType{} (The parameter list must exist and be empty) Set the saved attribute text to "@b{NONE!}". This exists to ensure that the prefixes are set properly, and aren't just set by accident. @PragmaSyn{<Text>} Defines a pragma. The text is displayed in the current format. The text should contain an @prag command (which specifies and indexes the name - see below.) The text can contain arbitrary commands; it will be run through the full evaluation code. The text is also sent to a database used to later create Annex L. @AddedPragmaSyn{Version=[<Version>],<Text>} Defines a pragma added by <Version>. Otherwise, the text is as described for PragmaSyntax. Text includes an appropriate @Chg; the purpose of the Version number here is to determine whether (and how) this is entered into Annex L, along with the cross-reference text. @DeletedPragmaSyn{Version=[<Version>],InitialVersion=[<InitialVersion>],<Text>} Defines a pragma deleted by <Version>, originally added by <InitialVersion>. Otherwise, the text is as described for PragmaSyntax. Text includes an appropriate @Chg; the purpose of the Version number here is to determine whether (and how) this is entered into Annex L, along with the cross-reference text. @PragmaList Dumps the summary list of all pragmas from the pragma database to the output file. -- Indexing: If Show-Index-Entries is not used on the command line, indexing entries are transparent (this is usually the case for the RM). If Show-Index-Entries is used on the command line, indexing entries show as italized in curly brackets. RootDefn adds "[distributed]", PDefn adds "[partial]", IndexSee adds ": see <OtherTerm>", and IndexSeeAlso adds ": see also <OtherTerm>" to the reference. @IndexList - Generates the index at this point. @defn{<text>} - Defines a term, where the entire definition is given in the referenced paragraph. @rootdefn{<text>} - Defines a term, where the definition is given in several paragraphs. This is the primary definition. @pdefn{<text>} - Defines a term, where the definition is given in several paragraphs. This is one of the secondary definitions. @defn2{Term=[<term>],Sec=(<subterm>)} - Same as Defn, except a subterm is allowed. The subterm will be indexed under the primary term. @rootdefn2{Term=[<term>],Sec=(<subterm>)} - Same as RootDefn, except a subterm is allowed. @pdefn2{Term=[<term>],Sec=(<subterm>)} - Same as PDefn, except a subterm is allowed. @seeother{Primary=[<term>],Other=(<other_term>)} - Generates a See reference to <other_term> in the index. No page/clause reference is generated. @seealso{Primary=[<term>],Other=(<other_term>)} - Generates a See also reference to <other_term> in the index. No page/clause reference is generated. @indexsee{Term=[<term>],See=(<other_term>)} - Generates a See reference to <other_term> in the index. A page/clause reference is generated. @indexseealso{Term=[<term>],See=(<other_term>)} - Generates a See also reference to <other_term> in the index. A page/clause reference is generated. @ChildUnit{Parent=[<parent>],Child=[<child>]} Generates three index entries: An index entry for <child>, with a secondary of "@i{child of} <parent>", an index entry for "Language-Defined Library Units" with a secondary entry of <parent>.<child>, and an index entry for <parent>.<child>. The Unit is set to <parent>.<child>. (For version 2 or later, the Language-Defined entry is not generated.) The first entry is added to the package list as well. @SubChildUnit{Parent=[<parent>],Child=[<child>]} Same as @ChildUnit, except that the first entry is added to the subprogram list, rather than the package list. @RootLibUnit{<unit>} - Generates two index entries: An index entry for "Language-Defined Library Units" with a secondary entry of <unit>, and an index entry for <unit>. The Unit is set to <parent>.<child>. (For version 2 or later, the Language-Defined entry is not generated.) The first entry is added to the package list as well. @AdaDefn{<defn>} - Generates an index entry for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.) Also outputs the <defn> to the output file. @AdaSubDefn{<defn>} - Generates two index entries: one for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.), and second for "Language-Defined Subprogram" with a secondary entry of "<defn> @i{in} <Unit>". (For version 2 or later, the Language-Defined entry is not generated.) The first entry is added to the subprogram list as well. Also outputs the <defn> to the output file. @AdaTypeDefn{<defn>} - Generates two index entries: one for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.), and second for "Language-Defined Type" with a secondary entry of "<defn> @i{in} <Unit>". (For version 2 or later, the Language-Defined entry is not generated.) The first entry is added to the type list as well. Also outputs the <defn> to the output file. @AdaSubTypeDefn{Name=<defn>,Of=<type>} - Generates an index entry of "<defn> @i{subtype of} <type>" with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.) The entry is added to the type list as well. Also outputs the <defn> to the output file. @AdaExcDefn{<defn>} - Generates an index entry for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.) The entry is added to the exception list as well. Also outputs the <defn> to the output file. @AdaObjDefn{<defn>} - Generates an index entry for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.) The entry is added to the object list as well. Also outputs the <defn> to the output file. @AdaPackDefn{<defn>} - Generates an index entry for <defn> with a secondary entry of "@i{in} <Unit>" (where Unit is the unit saved by a previous RootLibUnit or ChildUnit.) The entry is added to the package list as well. Also outputs the <defn> to the output file. Use this for *nested* packages. @IndexCheck{<check>} - Generates an index entry for "check, language defined" with a secondary entry of <check>. (Essentially a Defn2). Also, indexes <check> as a partial definition. (PDefn). @Attr{<name>} -- Generates an index entry for "attributes" with a secondary entry of <name>. (Essentially a Defn2). Also with a secondary entry of <name> (a Defn2), and also an index entry of "<name> attribute" (a Defn). Also puts <name> to the output. @Prag{<name>} -- Generates an index entry for "pragmas" with a secondary entry of <name> (a Defn2), and also an index entry of "<name> pragma" (a Defn). Also puts <name> to the output. @AspectDefn{<name>} -- Generates an index entry for "aspects" with a secondary entry of <name> (a Defn2), and also an index entry of "<name> aspect" (a Defn). @PackageList -- Generates the list of language-defined packages. @TypeList -- Generates the list of language-defined types and subtypes. @SubprogramList -- Generates the list of language-defined subprograms. @ExceptionList -- Generates the list of language-defined exceptions. @ObjectList -- Generates the list of language-defined objects. -- Glossary: @ToGlossary(Term=[<term>], Text=[<text>]) Creates a glossary entry for <term> with the value <text>. The item is shown as a annotation in the AARM. The term is also indexed (and displayed as such if appropriate) with @Defn immediately after the annotation header. @ToGlossaryAlso(Term=[<term>], Text=[<text>]) Creates a glossary entry for <term> with the value <text>. The text is part of the current paragraph. If Show-Index-Entries is used on the command line, a "[Glossary Entry]" marker is shown; otherwise nothing is. The term is also indexed (and displayed as such if appropriate) with @Defn immediately after the marker. @GlossaryList Generates the glossary. -- Implementation-defined annex: @ImplDef{<text>} Creates an implementation-defined entry for <text>. The clause and paragraph references are saved to create part of Annex M. For the AARM, <text> is an annotation; otherwise, it is discarded. See also ChgImplDef. @ImplDefList Generates the implementation-defined list. -- Changes: @chgref{Version=[<version>],Kind=(<kind>){,Ref=(<DR_Number>)}{,ARef=(<AI_Number>)}} - Marks a paragraph changed in a corrigendu or amendment. This command precedes any text of the paragraph. The version number of the change is <version>. [This is "1" for technical corrigenum 1; "2" for amendment 1]. Kind is either "Revised" (an ordinary change), "Added" (for a paragraph added by the change), "AddedNormal" (for a paragraph added by the change which gets a normal paragraph number - used for insertions at the end of clauses and added to new clauses), "Deleted" (for a paragraph deleted by the change), "DeletedAdded" (for an added paragraph which is later deleted), "DeletedNoDelMsg" (for a paragraph deleted by the change; the "This paragraph was deleted" message is suppressed), "DeletedAddedNoDelMsg" (combines the last two kinds), or "RevisedAdded" (for an added paragraph which is later revised). [These control the paragraph numbering of the following paragraph.] The <DR_Number>(s) and/or <AI_Number>(s) that triggered the change are given. As many references as necessary can be given. (Zero is allowed). The format of the AI numbers is as described for @AILink. Note: If there are changes to the same paragraph in multiple versions, each version should have their own chgref. The ChgRefs should be in the order of the versions (first version 1, then version 2, etc.) The Kind should be consistent for all chgrefs - the numbering is the same no matter when the paragraph was added or deleted. That means "RevisedAdded" after "Added", etc. @chgnote{<text>} Notes on particular change. This is treated as a comment; it has a separate command solely so that stripped easily in the future. @chg{[Version=[<Version>],]New=[<new text>],Old=[<old text>]} Marks a particular change. The new text and the old text are given. (We have both sets of text so we can generate useful differences). @chg commands can be nested; it recommended that they be nested with the newest changes inside of older changes. The text may not contain any command that ends the paragraph. The Version is assumed to be '1' if that parameter is not given. Version is interpreted as for ChgRef. @ChgAdded{Version=[<Version>],[NoPrefix=[T|F],][NoParamnum=[T|F],] [Type=[Leading|Trailing|Normal],][Keepnext=[T|F],]Text=[text]} Marks an insertion of a complete paragraph consisting of 'text'. This cannot be nested in other commands. The AARM prefix (if any) also is marked as an insertion. The optional parameters (conditionally) set the paragraph properties; NoPrefix, Noparanum, and KeepNext work the same as the @NoPrefix, @NoParanum, and @KeepNext commands if set to T, except that they're conditional on the paragraph text being inserted. Similarly, Type works the same as @Leading and @Trailing if set to those values, except that they are conditional. If omitted, NoPrefix is set to F, NoParanum is set to F, KeepNext is set to F, and Type is set to Normal. @ChgDeleted{Version=[<Version>],[NoPrefix=[T|F],][NoParamnum=[T|F],] [Type=[Leading|Trailing|Normal],][Keepnext=[T|F],]Text=[text]} Marks a deletion of a complete paragraph consisting of 'text'. This cannot be nested in other commands. The AARM prefix (if any) also is marked as a deletion. The optional parameters (conditionally) set the paragraph properties; they work as described in ChgAdded. Note that they're conditional on the paragraph text being included in the document (even if it is marked as deleted). @ChgImplDef{Version=[<version>],Kind=(<kind>), [InitialVersion=[<version>],]Text=<text>} Marks a changed implementation-defined entry. (Essentially a combination of ChgRef and Impldef.) <text> is the implementation-defined entry. See ChgRef and Impldef for details on the handling of the arguments. The optional InitialVersion parameter specifies the version number for the originally inserted text; if not specified, the Version number is used. (This is appropriate for added items, others should explicitly give an initial version.) @ChgImplAdvice{Version=[<version>],Kind=(<kind>), [InitialVersion=[<version>],]Text=<text>} Marks a new or changed implementation advice entry. All IA entries are new with version 2. The clause and paragraph references (along with <text>) are saved to create part of Annex M. For the AARM, <text> is an annotation; otherwise, it is discarded. See ChgRef for details on the handling of Version and Kind arguments. The optional InitialVersion parameter specifies the version number for the originally inserted text; if not specified, the Version number is used. @AddedImplAdviceList{Version=[2]} Generates the implementation advice list; it is inserted with the given version number. @ChgDocReq{Version=[<version>],Kind=(<kind>), [InitialVersion=[<version>],]Text=<text>} Marks a new or changed documentation requirements entry. All DocReq entries are new with version 2. The clause and paragraph references (along with <text>) are saved to create part of Annex M. For the AARM, <text> is an annotation; otherwise, it is discarded. See ChgRef for details on the handling of Version and Kind arguments. The optional InitialVersion parameter specifies the version number for the originally inserted text; if not specified, the Version number is used. @AddedDocReqList{Version=[2]} Generates the documentation requirements list; it is inserted with the given version number. @ChgAspectDesc{Version=[<version>],Kind=(<kind>),Aspect=[<name>], [InitialVersion=[<version>],]Text=<text>} Marks a new or changed aspect description entry. All aspect descriptions are new with version 3. The clause and paragraph references (along with <name> and <text>) are saved to create part of Annex K. For the AARM, <text> is an annotation; otherwise, it is discarded. See ChgRef for details on the handling of Version and Kind arguments. The optional InitialVersion parameter specifies the version number for the originally inserted text; if not specified, the Version number is used. @AddedDocReqList{Version=[3]} Generates the aspect description list; it is inserted with the given version number. @ChgAttribute{Version=[<version>],Kind=(<kind>),ChginAnnex=[T|F], Leading=[T|F],Prefix=<Prefix>,AttrName=<Name>, {[Ref={<DR_Number>}|ARef={<AI_Number>}]},Text=<Text>} Marks a changed attribute entry. (Essentially a combination of ChgRef and Attribute.) ChginAnnex controls whether the change is reflected in the Annex. (Set this to F when the change is in text "glued" onto the annex paragraph.) Leading controls whether the first paragraph is leading or not. See ChgRef and Attribute for the meaning of the other parameters. @ChgPrefixType{Version=[<version>],Kind=(<kind>),Text=[<text>]} Marks a changed prefix type text. Also, saves the indicated text to use as part of any following attribute definitions. The text is also written to the output. See ChgRef and PrefixType for more information. @AddedSubheading{Version=[<version>],<text>} Same as Subheading, except that this heading is present only in new versions of the document. @ChgToGlossary{Version=[<version>],Kind=(<kind>),Term=[<term>],Text=[<text>]} Marks a changed glossary entry. (Essentially a combination of ChgRef and ToGlossary.) <term> and <text> are the glossary entry; they can contain @Chg commands. See ChgRef and ToGlossary for details on the handling of the arguments. @ChgToGlossaryAlso{Version=[<version>],Kind=(<kind>),Term=[<term>],Text=[<text>]} Marks a changed glossary entry. (Essentially a combination of ChgRef and ToGlossaryAlso.) <term> and <text> are the glossary entry; they can contain @Chg commands. See ChgRef and ToGlossaryAlso for details on the handling of the arguments. -- Tabs: @tabclear() - Clears all tab settings. Tabs are also cleared by leaving the @begin region that contains the tabstop command. Also ends any paragraphs. @tabset(<list>) - Sets tab stops at the indicated values, in picas. The list is increasing (each value is larger than the one to its right), and separated by commas. Each value can be preceeded by a modifier: L - fixed left tab; P - proporational left tab. (Other modifiers are possible, but are hard to implement in text mode.) Proportional tab values are based on the font size; the values given are for 12 point fonts (in picas); the value is then adjusted for the actual (default) font size of the paragraph. Tab stops can only be set in formats that preserve breaks (i.e. Display). Also ends any paragraphs. @\ - Move to the next tab stop. -- Paragraphs: @begin{<kind>} Marks the beginning of a group of paragraphs of a particular kind. See the definition of the kinds below. Most groupings have a subheading. @end{<kind>} Marks the ending of a group of paragraphs of a particular kind. -- Paragraph kinds (nesting is allowed; characteristics are not preserved -- unless specifically marked below): Pure formatting: Comment - The text is never output into the document. WideAbove- The paragraph has wider than usual space above, but is otherwise normal. DescribeCode - The text is indented 2 units. Example - The text is formatted in the example font (which is selected in the master file) with an indent of 1 unit; spaces and breaks are preserved. This format preserves size characteristics of its parent (if any), except that if the parent is "DescribeCode", the normal characteristics are used. No page breaks are allowed within a paragraph. Do not confuse this with "Examples", which is a text grouping. ChildExample - The text is formatted in the example font (which is selected in the master file); spaces and breaks are preserved. This format preserves size and indenting characteristics of its parent (if any); with the exception that the text here is indented one additional unit. Itemize - The text is indented and bulleted (with solid circle bullets). The text preserves the size and indenting of its parent (if any). InnerItemize - The text is indented to fit inside an Itemize or Enumerate paragraph, and bulleted (with [smaller] solid circle bullets). InnerInnerItemize - The text is indented to fit inside an InnerItemize paragraph, and bulleted (with [smaller] solid circle bullets). Enumerate - The text is indented and numbered (that is, each paragraph has a prefix number). The text preserves the size and indenting of its parent (if any). The format of the number depends on the ListFormat master setting: for RM, a number followed by a period is used ["1."], for ISO2004 a letter followed by a paren is used for the main list ["a)"]; nested lists use a number ["1)"]. InnerEnumerate - The text is indented to fit inside an Itemize or Enumerate paragraph, and numbered as for Enumerate. (These should only be used inside of regular Enumerate blocks if ISO 2004 formatting is desired.) Display - A normal paragraph indented one level from its parent, except that spaces and breaks are preserved. The text preserves the size of its parent (if any). No page breaks are allowed within a paragraph. Indent - A normal paragraph indented one level from its parent. The text preserves the size of its parent (if any). SyntaxDisplay - The text is in a smaller font, is indented one level, and spaces and breaks are preserved. No page breaks are allowed within a paragraph. Description - A paragraph with text indented 3 units; but the item is a hanging undent to the normal paragraph level. Usually used for attributes, but sometimes used for other items. Same as Hang3List. DescExample - The text is formatted in a fixed-width example font with an indent of 4 units; spaces and breaks are preserved. No page breaks are allowed within a paragraph. SyntaxText - The text is indented 1 unit. This is intended to match the indentation of syntax and is usually used in the syntax grouping; however syntax is usually in the swiss font. Hang1List - A paragraph with text indented 1 unit; but the item is a hanging undent to the normal paragraph level. Hang2List - A paragraph with text indented 2 units; but the item is a hanging undent to the normal paragraph level. Hang3List - A paragraph with text indented 3 units; but the item is a hanging undent to the normal paragraph level. Hang4List - A paragraph with text indented 4 units; but the item is a hanging undent to the normal paragraph level. Small - The text has the size of an AARM note, but doesn't have any headers or extra indentation. Title - The text is 5 size units (usually 5 points) larger than normal. Bundle - The text in the 'bundle' should never be page-breaked. The format is unchanged. TwoCol - Sets the text to a two-column format. The text format is unchanged. FourCol - Sets the text to a four-column format. The text format is unchanged. RM groupings: Intro - Introductory text. No heading. Syntax - Syntax. Resolution- Name resolution rules. Legality - Legality rules. StaticSem - Static Semantics. LinkTime - Post-Compilation Rules. RunTime - Dynamic Semantics. Bounded - Bounded (Run-Time) errors. Erron - Erroneous Execution. ImplReq - Implementation Requirements. DocReq - Documentation Requirements. Metrics - Metrics. ImplPerm - Implementation Permissions. ImplAdvice- Implementation Advice. Notes - Notes. (Each of these is numbered and indented 1 unit. The format is controlled by the @NoteFormat command in the master file.) SingleNote - A single note (it is indented 1 unit, but not numbered. The format is controlled by the @NoteFormat command in the master file.) Examples - Examples. (Do not confuse this with the text format "Example". This is a grouping with a subhead. It is in the normal font by default; often an "Example" is found inside of "Examples".) NotIso - Text that is not included in ISO documents. No format is implied. IsoOnly - Text that is included only in ISO documents. No format is implied. RMOnly - Text that is not included in the AARM (that is, it is only included in the output if HideAnnotations is used). No format is implied. AARM-only groupings: (not shown if HideAnnotations is used) MetaRules - Language Design Principles. Inconsistent83 - Inconsistencies with Ada 83. Incompatible83 - Incompatibilities with Ada 83. Extend83 - Extensions to Ada 83. DiffWord83- Wording Changes from Ada 83. Inconsistent95 - Inconsistencies with Ada 95. Incompatible95 - Incompatibilities with Ada 95. Extend95 - Extensions to Ada 95. DiffWord95- Wording Changes from Ada 95. Inconsistent2005 - Inconsistencies with Ada 2005. Incompatible2005 - Incompatibilities with Ada 2005. Extend2005 - Extensions to Ada 2005. DiffWord2005- Wording Changes from Ada 2005. Inconsistent2012 - Inconsistencies with Ada 2012. Incompatible2012 - Incompatibilities with Ada 2012. Extend2012 - Extensions to Ada 2012. DiffWord2012- Wording Changes from Ada 2012. AARMOnly - Text that is not included in the RM. No format is implied. AARM annotations: (not shown if HideAnnotations is used) Reason - Why a rule is necessary. Ramification- Consequences of rules. (Important ones should be Notes). Discussion - General annotations. TheProof - Informal proof as to why Notes or Redundant text follows from the language. ImplNote - A note on implementation. Honest - To be Honest: Only pedants need apply. GlossaryMarker - Looks like a glossary entry in the AARM (but isn't really one). (Also internally used by the formatter for real glossary entries.) ElementRef - (For ASIS) Marks an Element Reference. ChildRef - (For ASIS) Marks child references for the preceding Element Reference. UsageNote - (For ASIS) Marks a Usage Note. -- Text Macros: <Grouping>Name - The name of a kind of rule (as in "This is a @ResolutionName."). <Grouping>Title - The title of a kind of rule (as in "This belongs under "@ResolutionTitle"."). where <Grouping> is any of the paragraph grouping kinds listed above. -- Character Macros: These represent characters not available in the lower 128 of Latin-1, including various mathematical symbols. @em - EM dash (a very long dash) @en - EN dash (a long dash) @thin - A thin space (quarter em if possible) @geq - Greater than or equal symbol @gt - Greater than symbol @leq - Less than or equal symbol @lt - Less than symbol @neq - Not equal symbol @pi - Pi @smldotlessi -- Small Dotless I (for examples). Use @Unicode(305) if we ever implement that. @capdottedi -- Capital Dotted I (for examples). Use @Unicode(304) if we ever implement that. @singlequote - Single quote ('''). Used to avoid confusion in syntax rules. @latin1{<number>} - Generate the Latin-1 character with the decimal code "number". @unicode{<number>} - Generate the Unicode character with the decimal code "number". Careful: this is unchecked; usually, the characters used should be limited to the 615 generally supported by Windows. @times - The middle dot multiply symbol. @porm - The plus or minus symbol. @ceiling{<text>} - The ceiling operator, surrounding <text>. @floor{<text>} - The floor operator, surrounding <text>. @abs{<text>} - The mathematical absolute value operation, surrounding <text>. @log{<text>} - The log operation, surrounding <text>. (In practice, this is always translated "log(<text>)"). @lquote - Left (directed) single quote. @rquote - Right (directed) single quote. @ldquote - Left (directed) double quote. @rdquote - Right (directed) double quote. @lquotes - Pair of left (directed) single quotes. (Note: The ARG has directed that these be changed to a left double quote, so this is now the same as ldquote.) @rquotes - Pair of right (directed) single quotes. (Note: The ARG has directed that these be changed to a right double quote, so this is now the same as rdquote.) -- Tables: @table(Columns=<number>, Alignment=<AllLeft|AllCenter|CenterExceptFirst>, FirstColWidth=<number>, LastColWidth=<number>, NoBreak=<T|F>, Border=<T|F>, SmallSize=<T|F>, Caption=<text>, Headers=<text>, Body=<row_text>) Defines a table. - Columns must be a single digit (2-9). - Alignment defines the column text alignment (centered or left edge). - FirstColWidth defines the width of the first column compared to the rest - it's in multiples of the standard column width. Note that some target formats with self-sizing columns (i.e. HTML) ignore this value. It must be a single digit from 1 to 9. - LastColWidth defines the width of the last column compared to the rest - it's in multiples of the standard column width. Note that some target formats with self-sizing columns (i.e. HTML) ignore this value. It must be a single digit from 1 to 9. - If NoBreak is T, the table will be formatted on a single page. Otherwise, it will be allowed to be split across pages. This must be F if the table is larger than a single page! - If Border is T, then a border will be drawn around the table; otherwise, not border will be used. - If SmallSize is T, then the text size will be small (AARM-sized); else the text size will be normal. - Caption defines the table caption. This spans the entire table. - Headers defines the table headers. Each header is separated by a tab stop (@\). This should be a single line. - Body defines the table body. Each row should be a single line, with each item separated by a tab stop. The text may contain character and text formatting commands, but no paragraph commands. But no text command may extend across the tab marking the end of an item. @Last - Marks the end of the second last row of the table. (If left out, the bottom line of the table may be missing). -- Pictures: (Graphics, Images) @PictureInline(Alignment=<Inline|FloatLeft|FloatRight>, Border=<None|Thin|Thick>, Height=<nnn>, Width=<nnn>, Name=<name>, Descr=<descr>) @PictureAlone(Alignment=<Left|Right|Center>, Border=<None|Thin|Thick>, Height=<nnn>, Width=<nnn>, Name=<name>, Descr=<descr>) Includes a picture in the output. PictureAlone is a stand-alone picture with the appropriate alignment; it must appear outside of a paragraph. PictureInline occurs in the flow of text (Inline), or floats to the appropriate margin; it must appear inside of a paragraph. Otherwise, these are the same. The picture file's simple name is "name"; the file is assumed to be a .PNG or .JPG, found in the output directory. (It needs to be included with the HTML output.) "descr" is a description of the picture; it's used for the popups in HTML. Height and Width are the picture size in pixels. Border specifies the border of the picture. [Note: Inline alignment is not recommended; the picture location cannot be controlled, especially on RTF, it can appear in margins and other bad locations.] ------------------- Use to create Ada standard documents. The master file AARM.MSM specifies the Annotated Ada Reference Manual. This is mainly intended for implementors and language lawyers. It includes annotations. (In the past, it also included visible index entries, but that has been turned off by popular demand). The master file RM.MSM specifies the Ada Reference Manual. This is the version used by most users. The master file ISO-RM.MSM specifies Ada Reference Manual in ISO format. This version lacks some sections, paragraph numbers, and is formatted for A4 paper. Versions: 0-Original Ada 95 (equivalent to No-Changes) 1-Technical Corrigendum 1 2-Amendment 1 [Ada 2005 (standard published 2007, so could be considered Ada 2007)] 3-3rd Edition (Ada 2012) 4-4th Edition (Ada 202x) - Not official yet. Please note that there some changes to earlier versions (mostly typographical, but there are some that are significant) that are not preserved in the Ada 2012 source code (.MSM and .MSS files), so to get an exact match to one of the previous versions, you must use the source code appropriate for that version. One specific change; the MSM files for Ada 2012 have @SubdivisionNames{Clause} (as this is required by ITTF) while the MSM files for Ada 95 and Ada 2005 have @SubdivisionNames{Section} (as this was required when those standards were current). In addition, several clauses were moved to different numbers within the Standard (for both Ada 2012 and Ada 2005); usually, these were done by by just renaming the clause (and changing the @Label command) and the original location is not preserved. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/gpl-3-0.txt����������������������������������������������������������������0000755�0001752�0001001�00000105755�12273462240�016442� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. <one line to give the program's name and a brief idea of what it does.> Copyright (C) <year> <name of author> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: <program> Copyright (C) <year> <name of author> This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <http://www.gnu.org/licenses/>. The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <http://www.gnu.org/philosophy/why-not-lgpl.html>. �������������������org.adaic.arm_form/progs/makeana.bat����������������������������������������������������������������0000755�0001752�0001001�00000000161�12273462240�016670� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������corder arm_analyzer /i/z/w/b'ana.bat'/c'/w3/c/zt/t/sc:\windows\temp'/jb'/t/l'/q'/w'/r.\object/jx'alkc arm_anal' ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/makearm.bat����������������������������������������������������������������0000755�0001752�0001001�00000000173�12273462240�016713� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������corder arm_formatter /t/z/w/k255/b'arm.bat'/l'ads'/n'adb'/n'ada'/n'a'/c'/zt/t'/jb'/t/l'/q'/w'/r.\object/jx'alkc arm_form' �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/mklnk.bat������������������������������������������������������������������0000755�0001752�0001001�00000000221�12273462240�016404� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Del .\Object\_Janus.Prj Jmanager Add_Project (.\Object\,Default) Jmanager Add_Link (.\Object\,Default,C:\Jnt312\Rts\Console, JNT_RTS_CONSOLE) �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/progs/rtf2form.ada���������������������������������������������������������������0000755�0001752�0001001�00000072224�12273462240�017024� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������with Ada.Text_IO, Ada.Strings.Fixed, Ada.Strings.Unbounded, Ada.Characters.Handling, Ada.Command_Line; procedure Rtf2Form is -- -- Convert an RTF file (as in the Rationale) to a roughly formatted .MSS -- file. This tool is part of ARM_Form, the Ada Reference Manual formatter. -- -- --------------------------------------- -- Copyright 2006, 2011 AXE Consultants. -- P.O. Box 1512, Madison WI 53701 -- E-Mail: randy@rrsoftware.com -- -- ARM_Form is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License version 3 -- as published by the Free Software Foundation. -- -- AXE CONSULTANTS MAKES THIS TOOL AND SOURCE CODE AVAILABLE ON AN "AS IS" -- BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, -- CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR FUNCTIONING OF THIS TOOL. -- IN NO EVENT WILL AXE CONSULTANTS BE LIABLE FOR ANY GENERAL, -- CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, -- EVEN IF AXE CONSULTANTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -- DAMAGES. -- -- A copy of the GNU General Public License is available in the file -- gpl-3-0.txt in the standard distribution of the ARM_Form tool. -- Otherwise, see <http://www.gnu.org/licenses/>. -- -- If the GPLv3 license is not satisfactory for your needs, a commercial -- use license is available for this tool. Contact Randy at AXE Consultants -- for more information. -- -- --------------------------------------- -- -- Edit History: -- -- 1/19/06 - RLB - Created program. -- 1/20/06 - RLB - Changed to generate tab markers for tabs, as John -- wants to preserve tabs where possible. -- 10/18/11 - RLB - Changed to GPLv3 license. use Ada.Strings.Unbounded; -- Declarations stolen from Trash-Finder: type Line_Count is range 0 .. 1_000_000; -- 1 million lines ought to be enough. type Line_Type; type Line_Access is access Line_Type; type Line_Type is record Number : Line_Count; Text : Ada.Strings.Unbounded.Unbounded_String; Next : Line_Access; end record; procedure Free is new Ada.Unchecked_Deallocation (Line_Type, Line_Access); -- Free an individual line. procedure Free_All (List : in out Line_Access) is -- Free the entire list. Temp : Line_Access; begin while List /= null loop Temp := List; List := List.Next; Free (Temp); end loop; end Free_All; procedure Load_File (File_Name : in String; Data : in out Line_Access) is -- Read the file, breaking at each paragraph end (to keep the lines from -- getting too long). The original line breaks are irrelevant. File : Ada.Text_IO.File_Type; Last, Working : Line_Access := null; Count : Line_Count := 0; Buffer : String (1..1000); -- Since line endings aren't significant, the -- length doesn't matter much, other than we -- might miss a "\par" that way. BLength : Natural; Break_Loc, Start_Loc : Natural; begin Ada.Text_IO.Open (File, Ada.Text_IO.In_File, File_Name); loop Ada.Text_IO.Get_Line (File, Buffer, BLength); Count := Count + 1; --Ada.Text_IO.Put_Line("Line" & Line_Count'Image(Count) & ": read=" & Buffer(1..BLength)); Start_Loc := 1; Break_Loc := Start_Loc; while Break_Loc <= BLength-4 loop -- Look for "\par " or "\par\", only (in particular, not "\pard"). exit when Buffer(Break_Loc..Break_Loc+3) = "\par" and then (Buffer(Break_Loc+4) = ' ' or else Buffer(Break_Loc+4) = '\'); -- Found it. Break_Loc := Break_Loc + 1; end loop; if Break_Loc > BLength-4 then Break_Loc := BLength+1; end if; if Last = null then Working := new Line_Type; Working.Number := Count; Working.Next := null; Working.Text := To_Unbounded_String (Buffer(1..Break_Loc-1)); Data := Working; Last := Working; --Ada.Text_IO.Put_Line("Line" & Line_Count'Image(Count) & ": initial=" & Buffer(1..Break_Loc-1)); elsif Length(Last.Text) > 30000 and then Break_Loc > BLength then -- Break at the original place, as this is too long. -- This is fine so long as the length of Buffer < 2768/2 (1386) Last.Text := Last.Text & To_Unbounded_String (Buffer(1..Break_Loc-1)); --Ada.Text_IO.Put_Line("Line" & Line_Count'Image(Count) & ": append, then break=" & Buffer(1..Break_Loc-1)); Break_Loc := BLength - 3; -- Force a new line here. (This will make -- Start_Loc small enough to enter the -- loop below and create an empty line.) else Last.Text := Last.Text & To_Unbounded_String (Buffer(1..Break_Loc-1)); --Ada.Text_IO.Put_Line("Line" & Line_Count'Image(Count) & ": append=" & Buffer(1..Break_Loc-1)); end if; Start_Loc := Break_Loc + 4; -- Skip \par. if Start_Loc <= BLength and then Buffer(Start_Loc) = ' ' then Start_Loc := Start_Loc + 1; -- Skip trailling space, too. end if; --Ada.Text_IO.Put_Line("Start_Loc = " & Natural'Image(Start_Loc) & " Blength=" & Natural'Image(BLength)); while Start_Loc <= BLength+1 loop -- +1 so we handle end of line "\par" properly. -- Create a new line: Working := new Line_Type; Working.Number := Count; Working.Next := null; Last.Next := Working; Last := Working; Break_Loc := Start_Loc; while Break_Loc <= BLength-4 loop -- Look for "\par " or "\par\", only (in particular, not "\pard"). exit when Buffer(Break_Loc..Break_Loc+3) = "\par" and then (Buffer(Break_Loc+4) = ' ' or else Buffer(Break_Loc+4) = '\'); -- Found it. Break_Loc := Break_Loc + 1; end loop; if Break_Loc > BLength-4 then Break_Loc := BLength+1; end if; Working.Text := To_Unbounded_String (Buffer(Start_Loc..Break_Loc-1)); --Ada.Text_IO.Put_Line("Line" & Line_Count'Image(Count) & ": startp=" & Buffer(Start_Loc..Break_Loc-1)); Start_Loc := Break_Loc + 4; -- Skip \par. if Start_Loc <= BLength and then Buffer(Start_Loc) = ' ' then Start_Loc := Start_Loc + 1; -- Skip trailling space, too. end if; end loop; -- Done with line when we get here. end loop; exception when Ada.Text_IO.End_Error => -- Done reading. Ada.Text_IO.Close (File); end Load_File; -- Stack of RTF command information: type RTF_Group_Kind is (Unknown, Empty, Bold, Italic, Tab, Line_Break, Exam, ExamCom, Key); -- Type of RTF command. type Brace_Info is record Kind : RTF_Group_Kind; end record; Brace_Info_Stack : array (1..1000) of Brace_Info; Current_Brace : Natural := 0; type Paragraph_Styles is (Unknown, None, Normal, Example, Description); Current_Paragraph_Style : Paragraph_Styles := Unknown; procedure Process_and_Write_File (File_Name : in String; Data : in out Line_Access) is File : Ada.Text_IO.File_Type; Cursor : Line_Access := Data; Chars_on_Line : Natural; -- Number of characters output on the current line. -- Data: Deepest_Brace_Nesting : Natural := 0; Paragraphs : Natural := 0; Escaped_Chars : Natural := 0; EM_Dashes : Natural := 0; EN_Dashes : Natural := 0; Intraparagraph_Line_Breaks : Natural := 0; Intraparagraph_Tabs : Natural := 0; Brace_Kinds_Found : array (RTF_Group_Kind) of Natural := (others => 0); Styles_Found : array (Paragraph_Styles) of Natural := (others => 0); procedure Close_Old_Style is -- Close the current paragraph style in preparation for a new one. begin case Current_Paragraph_Style is when Unknown => null; when None => null; when Normal => null; --Ada.Text_IO.Put_Line (File, "@end[Intro]"); -- ** Temp (no style needed for these). when Example => Ada.Text_IO.Put_Line (File, "@end[Example]"); when Description => Ada.Text_IO.Put_Line (File, "@end[Description]"); end case; end Close_Old_Style; begin Ada.Text_IO.Create (File, Ada.Text_IO.Out_File, File_Name); -- Header stuff (ignored, really). Ada.Text_IO.Put_Line (File, "@Part(xxx, Root=""rat.msm"")"); Ada.Text_IO.Put_Line (File, ""); Ada.Text_IO.Put_Line (File, "@comment($Source: e:\\cvsroot/ARM/Progs/rtf2form.ada,v $)"); Ada.Text_IO.Put_Line (File, "@comment($Revision: 1.4 $ $Date: 2012/05/19 01:00:26 $)"); Ada.Text_IO.Put_Line (File, ""); while Cursor /= null loop declare Our_Line : constant String := To_String(Cursor.Text); Working : Natural := Our_Line'First; Last_Output : Natural := Working - 1; procedure Clean_Buffer_and_Close_Old_Style is -- Close the current paragraph style in preparation for a new one. begin Ada.Text_IO.Put_Line (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Close style on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working-1)); Chars_on_Line := 0; -- Start over. Last_Output := Working-1; Close_Old_Style; end Clean_Buffer_and_Close_Old_Style; function Possible_Style (Head, Tail : Natural) return Boolean is -- Check that the stuff between Head and Tail -- can *only* be a style, with nothing extra. begin --Ada.Text_IO.Put_Line ("Possible style=" & Our_Line(Head..Tail)); for I in Head .. Tail loop if Our_Line(I) = '{' then --Ada.Text_IO.Put_Line (" NO - open group"); return False; -- Starts some group, not part of a style. elsif Our_Line(I) = '{' then --Ada.Text_IO.Put_Line (" NO - close group"); return False; -- Ends some group, not part of a style. elsif Our_Line(I) = ' ' then if I = Tail then --Ada.Text_IO.Put_Line (" OK"); return True; elsif Our_Line(I+1) = '\' then null; -- OK. else -- We have to have another command, not text, immediately following. --Ada.Text_IO.Put_Line (" NO - plain text found"); return False; end if; elsif Our_Line(I) in 'a'..'z' or else Our_Line(I) in '0'..'9' or else Our_Line(I) = '-' or else Our_Line(I) = '\' then null; -- OK. else --Ada.Text_IO.Put_Line (" NO - odd character at" & Natural'Image(I)); return False; -- Don't know what this is. end if; end loop; --Ada.Text_IO.Put_Line (" OK"); return True; -- OK if we get here. end Possible_Style; procedure Start_Style (Style_Code_Loc, End_of_Style : Natural) is -- Generate an appropriate style operation. -- We've already checked the basic legality of the style. -- Set Working and Last_Output as needed. begin -- We can assume that the style code has enough room. if Our_Line(Style_Code_Loc..Style_Code_Loc+4) = "\s15\" then -- Normal style (called "TP Text para") --Ada.Text_IO.Put_Line (" Normal style"); if Current_Paragraph_Style /= Normal then Clean_Buffer_and_Close_Old_Style; --Ada.Text_IO.Put_Line (File, "@begin[Intro]"); -- ** Temp. Current_Paragraph_Style := Normal; -- else no change needed. end if; Styles_Found(Normal) := Styles_Found(Normal) + 1; -- We just discard the entire style mess. Last_Output := End_of_Style; Working := Last_Output + 1; elsif Our_Line(Style_Code_Loc..Style_Code_Loc+4) = "\s25\" then -- Example style (called "PP Program para") --Ada.Text_IO.Put_Line (" Example style"); if Current_Paragraph_Style /= Example then Clean_Buffer_and_Close_Old_Style; Ada.Text_IO.Put_Line (File, "@begin[Example]"); Current_Paragraph_Style := Example; -- else no change needed. end if; Styles_Found(Example) := Styles_Found(Example) + 1; -- We just discard the entire style mess. Last_Output := End_of_Style; Working := Last_Output + 1; elsif Our_Line(Style_Code_Loc..Style_Code_Loc+4) = "\s32\" then -- Description style (called "BP Bullet", but often -- not used for bullets) --Ada.Text_IO.Put_Line (" Description style"); if Current_Paragraph_Style /= Description then Clean_Buffer_and_Close_Old_Style; Ada.Text_IO.Put_Line (File, "@begin[Description]"); Current_Paragraph_Style := Description; -- else no change needed. end if; Styles_Found(Description) := Styles_Found(Description) + 1; -- We just discard the entire style mess. Last_Output := End_of_Style; Working := Last_Output + 1; else -- Unknown style. --Ada.Text_IO.Put_Line (" Unknown style: code = " & Our_Line(Style_Code_Loc..Style_Code_Loc+4)); if Current_Paragraph_Style /= Unknown then Clean_Buffer_and_Close_Old_Style; Current_Paragraph_Style := Unknown; -- else no change needed. end if; Styles_Found(Unknown) := Styles_Found(Unknown) + 1; -- We leave the style mess for analysis. Working := Working + 1; end if; end Start_Style; begin Paragraphs := Paragraphs + 1; Chars_on_Line := 0; while Working <= Our_Line'Last loop if Our_Line(Working) = '{' then -- Start an RTF section. -- Output everything to here: Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Open Brace on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working-1)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); -- Stack this opening: Current_Brace := Current_Brace + 1; if Current_Brace > Deepest_Brace_Nesting then Deepest_Brace_Nesting := Current_Brace; end if; if Working+1 > Our_Line'Last or else Our_Line(Working+1) /= '\' then -- No command here, so it is not interesting (ever) -- and we might as well remove it. Brace_Info_Stack(Current_Brace).Kind := Empty; Last_Output := Working; -- Skip the brace. --Ada.Text_IO.Put_Line("Empty Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+3 <= Our_Line'Last and then Our_Line(Working..Working+3) = "{\b " then Brace_Info_Stack(Current_Brace).Kind := Bold; Ada.Text_IO.Put (File, "@b["); Chars_on_Line := Chars_on_Line + 3; Last_Output := Working+3; --Ada.Text_IO.Put_Line("Bold Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+3 <= Our_Line'Last and then Our_Line(Working..Working+3) = "{\i " then Brace_Info_Stack(Current_Brace).Kind := Italic; Ada.Text_IO.Put (File, "@i["); Chars_on_Line := Chars_on_Line + 3; Last_Output := Working+3; --Ada.Text_IO.Put_Line("Italic Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+6 <= Our_Line'Last and then Our_Line(Working..Working+6) = "{\line " then Brace_Info_Stack(Current_Brace).Kind := Line_Break; Ada.Text_IO.New_Line (File); Chars_on_Line := 0; -- Start over. Last_Output := Working+6; --Ada.Text_IO.Put_Line("Line_Break Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+5 <= Our_Line'Last and then Our_Line(Working..Working+5) = "{\tab " then Brace_Info_Stack(Current_Brace).Kind := Tab; Ada.Text_IO.Put (File, "@\"); Chars_on_Line := Chars_on_Line + 2; Last_Output := Working+5; --Ada.Text_IO.Put_Line("Tab Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+14 <= Our_Line'Last and then Our_Line(Working..Working+14) = "{\cs16\f1\fs20 " then -- \cs16 = "PC Program char" style. Could look for -- that early on to find the number. Same with -- "\f1" (Arial). But they might be constant, and -- that would be wasted work. Brace_Info_Stack(Current_Brace).Kind := Exam; Ada.Text_IO.Put (File, "@exam["); Chars_on_Line := Chars_on_Line + 6; Last_Output := Working+14; --Ada.Text_IO.Put_Line("Exam Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+8 <= Our_Line'Last and then Our_Line(Working..Working+8) = "{\cs20\b " then -- \cs20 = "RW Reserved word" style. Could look for -- that early on to find the number. Brace_Info_Stack(Current_Brace).Kind := Key; Ada.Text_IO.Put (File, "@key["); Chars_on_Line := Chars_on_Line + 5; Last_Output := Working+8; --Ada.Text_IO.Put_Line("Key (in example) Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+16 <= Our_Line'Last and then Our_Line(Working..Working+16) = "{\cs20\b\f1\fs20 " then -- \cs20 = "RW Reserved word" style. \f1 = Arial -- font. Brace_Info_Stack(Current_Brace).Kind := Key; Ada.Text_IO.Put (File, "@key["); Chars_on_Line := Chars_on_Line + 5; Last_Output := Working+16; --Ada.Text_IO.Put_Line("Key (in text) Open Brace on Line" & Line_Count'Image(Cursor.Number)); elsif Working+8 <= Our_Line'Last and then Our_Line(Working..Working+8) = "{\cs24\i " then -- \cs24 = "CT Comment" style. Brace_Info_Stack(Current_Brace).Kind := ExamCom; Ada.Text_IO.Put (File, "@examcom["); Chars_on_Line := Chars_on_Line + 9; Last_Output := Working+8; --Ada.Text_IO.Put_Line("ExamCom Open Brace on Line" & Line_Count'Image(Cursor.Number)); else Brace_Info_Stack(Current_Brace).Kind := Unknown; Ada.Text_IO.Put (File, '{'); Chars_on_Line := Chars_on_Line + 1; Last_Output := Working; --Ada.Text_IO.Put_Line("Unknown Open Brace on Line" & Line_Count'Image(Cursor.Number)); end if; Brace_Kinds_Found(Brace_Info_Stack(Current_Brace).Kind) := Brace_Kinds_Found(Brace_Info_Stack(Current_Brace).Kind) + 1; Working := Last_Output + 1; elsif Our_Line(Working) = '}' then -- End an RTF section. -- Output everything to here: Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Close Brace on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working-1)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); Last_Output := Working; -- We're including this character. case Brace_Info_Stack(Current_Brace).Kind is when Unknown => Ada.Text_IO.Put (File, '}'); --Ada.Text_IO.Put_Line("Unknown Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; when Empty => -- Just remove this one. --Ada.Text_IO.Put_Line("Empty Close Brace on Line" & Line_Count'Image(Cursor.Number)); null; when Bold => Ada.Text_IO.Put (File, ']'); --Ada.Text_IO.Put_Line("Bold Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; when Italic => Ada.Text_IO.Put (File, ']'); --Ada.Text_IO.Put_Line("Italic Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; when Line_Break => null; --Ada.Text_IO.Put_Line("Link_Break Close Brace on Line" & Line_Count'Image(Cursor.Number)); when Tab => null; --Ada.Text_IO.Put_Line("Tab Close Brace on Line" & Line_Count'Image(Cursor.Number)); when Exam => Ada.Text_IO.Put (File, ']'); --Ada.Text_IO.Put_Line("Exam Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; when ExamCom => Ada.Text_IO.Put (File, ']'); --Ada.Text_IO.Put_Line("ExamCom Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; when Key => Ada.Text_IO.Put (File, ']'); --Ada.Text_IO.Put_Line("Key Close Brace on Line" & Line_Count'Image(Cursor.Number)); Chars_on_Line := Chars_on_Line + 1; end case; Current_Brace := Current_Brace - 1; Working := Working + 1; elsif Our_Line(Working) = ' ' then -- Possible break here. if Chars_on_Line + (Working - (Last_Output+1) + 1) > 65 then -- We need a break here; write it. Ada.Text_IO.Put_Line (File, Our_Line(Last_Output+1..Working)); --Ada.Text_IO.Put_Line("Soft line break on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Chars_on_Line := 0; -- Start over. Last_Output := Working; Working := Working + 1; else -- Don't need a break. Working := Working + 1; end if; elsif Our_Line(Working) = '\' then -- RTF control word or symbol; see whether it is -- interesting. if Working+5 <= Our_Line'Last and then Our_Line(Working..Working+5) = "\line " then -- Line break in a paragraph (without an open -- brace). Output a New_line. Ada.Text_IO.Put_Line (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Line break on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Intraparagraph_Line_Breaks := Intraparagraph_Line_Breaks + 1; Chars_on_Line := 0; -- Start over. Last_Output := Working+5; Working := Last_Output + 1; elsif Working+4 <= Our_Line'Last and then Our_Line(Working..Working+4) = "\tab " then -- Tab inside of a paragraph. Output the previous text and a tab command. -- (Note: We don't define any tabstops here; that -- will need to be done by hand as needed). Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Tab on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); Ada.Text_IO.Put (File, "@\"); Chars_on_Line := Chars_on_Line + 2; Intraparagraph_Tabs := Intraparagraph_Tabs + 1; Last_Output := Working+4; Working := Last_Output + 1; elsif Working+1 <= Our_Line'Last and then (Our_Line(Working+1) = '\' or else Our_Line(Working+1) = '{' or else Our_Line(Working+1) = '}') then -- Escaped character. Output the previous text and -- the literal character. (We have to do this to -- prevent the escaped character from being -- acted on as if it is a control or group marker). Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Escaped char on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); Escaped_Chars := Escaped_Chars + 1; Last_Output := Working; Working := Working + 2; -- We leave the literal character in the output buffer for later writing. elsif Working+7 <= Our_Line'Last and then Our_Line(Working..Working+7) = "\endash " then -- Line break in a paragraph. Output a New_line. Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Endash on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); Ada.Text_IO.Put (File, "@en"); Chars_on_Line := Chars_on_Line + 3; EN_Dashes := EN_Dashes + 1; Last_Output := Working+7; Working := Last_Output + 1; elsif Working+7 <= Our_Line'Last and then Our_Line(Working..Working+7) = "\emdash " then -- Line break in a paragraph. Output a New_line. Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Working-1)); --Ada.Text_IO.Put_Line("Emdash on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Working)); Chars_on_Line := Chars_on_Line + ((Working-1) - (Last_Output+1) + 1); Ada.Text_IO.Put (File, "@em"); Chars_on_Line := Chars_on_Line + 3; EM_Dashes := EM_Dashes + 1; Last_Output := Working+7; Working := Last_Output + 1; elsif Working+5 <= Our_Line'Last and then Our_Line(Working..Working+5) = "\pard\" then -- Starts a (full) paragraph style. --Ada.Text_IO.Put_Line("Paragraph style on Line" & Line_Count'Image(Cursor.Number)); declare End_of_Style : Natural := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\langfenp1033 ") + 13; -- For some reason, all of the styles end with this. Style_Code : Natural := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\s"); -- The style code is generally first. begin --Ada.Text_IO.Put_Line("Style_Code=" & Natural'Image(Style_Code) & -- "; End_of_Style=" & Natural'Image(End_of_Style)); if Style_Code = 0 or else End_of_Style = 13 or else Style_Code > End_of_Style or else (not Possible_Style (Working, End_of_Style)) then -- No style code, no end of style, the style -- code comes after the end of the style, or -- the style has problems. (In which case, we are -- probably taking too much as the style). -- This is unknown. Do nothing and just output the character. Working := Working + 1; else Start_Style (Style_Code, End_of_Style); -- This sets Working and Last_Output appropriately. end if; end; elsif Working+5 <= Our_Line'Last and then Our_Line(Working..Working+5) = "\pard " then -- Starts a (short) paragraph style. --Ada.Text_IO.Put_Line("Short paragraph style on Line" & Line_Count'Image(Cursor.Number)); declare End_of_Style : Natural := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\lin0\itap0 "); -- For some reason, all of the styles end with this. Style_Code : Natural := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\s"); -- The style code is generally first. begin if End_of_Style = 0 then End_of_Style := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\lin480\itap0 "); if End_of_Style = 0 then End_of_Style := Ada.Strings.Fixed.Index (Our_Line(Working..Our_Line'Last), "\lin360\itap0 "); if End_of_Style /= 0 then End_of_Style := End_of_Style + 13; end if; else End_of_Style := End_of_Style + 13; end if; else End_of_Style := End_of_Style + 11; end if; if Style_Code = 0 or else End_of_Style = 0 or else Style_Code > End_of_Style or else (not Possible_Style (Working, End_of_Style)) then -- No style code, no end of style, the style -- code comes after the end of the style, or -- the style has problems. (In which case, we are -- probably taking too much as the style). -- This is unknown. Do nothing and just output the character. Working := Working + 1; else Start_Style (Style_Code, End_of_Style); -- This sets Working and Last_Output appropriately. end if; end; else -- Don't recognize it, just output it (later). Working := Working + 1; end if; else -- Just output it (later). Working := Working + 1; end if; end loop; -- Output any remaining text (it can't need to be broken): Ada.Text_IO.Put (File, Our_Line(Last_Output+1..Our_Line'Last)); --Ada.Text_IO.Put_Line("Remaining text on Line" & Line_Count'Image(Cursor.Number) & ": output=" & Our_Line(Last_Output+1..Our_Line'Last)); end; Ada.Text_IO.New_Line (File, 2); -- Double space. Cursor := Cursor.Next; end loop; Close_Old_Style; -- Close the last style. Ada.Text_IO.Close (File); Free_All (Data); -- Display statistics: Ada.Text_IO.Put_Line ("Conversion statistics:"); Ada.Text_IO.Put_Line (" Total paragraphs:" & Natural'Image(Paragraphs)); Ada.Text_IO.Put_Line (" Deepest nesting:" & Natural'Image(Deepest_Brace_Nesting)); for I in RTF_Group_Kind loop Ada.Text_IO.Put_Line (" Kind " & RTF_Group_Kind'Image(I) & ":" & Natural'Image(Brace_Kinds_Found(I))); end loop; Ada.Text_IO.Put_Line (" Escaped characters found:" & Natural'Image(Escaped_Chars)); Ada.Text_IO.Put_Line (" EM Dashes found:" & Natural'Image(EM_Dashes)); Ada.Text_IO.Put_Line (" EN Dashes found:" & Natural'Image(EN_Dashes)); Ada.Text_IO.Put_Line (" Line breaks inside of paragraphs:" & Natural'Image(Intraparagraph_Line_Breaks)); Ada.Text_IO.Put_Line (" Tabs inside of paragraphs:" & Natural'Image(Intraparagraph_Tabs)); for I in Paragraph_Styles loop Ada.Text_IO.Put_Line (" Style " & Paragraph_Styles'Image(I) & ":" & Natural'Image(Styles_Found(I))); end loop; end Process_and_Write_File; File_Contents : Line_Access; begin Ada.Text_IO.Put_Line ("Convert " & Ada.Command_Line.Argument(1) & ".rtf to " & Ada.Command_Line.Argument(1) & ".mss"); Load_File (Ada.Command_Line.Argument(1) & ".rtf", File_Contents); Process_and_Write_File (Ada.Command_Line.Argument(1) & ".mss", File_Contents); Ada.Text_IO.Put_Line ("Conversion completed"); end Rtf2Form; ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/README.txt�����������������������������������������������������������������������0000755�0001752�0001001�00000007067�12302611423�015153� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������Project to serve as a convenient packaging of the Ada Reference Manual formatter and sources. What is the Ada Reference Manual? ================================= The Ada Reference Manual is the free (libre) version of the international standard ISO/IEC 8652:2012(E). It describes a programming language called "Ada". The Ada Reference Manual was last revised in 2012, and approved by ISO in 2013; it is called "Ada 2012". Previous versions are labeled Ada 95 and Ada 2005. The official version of the Ada Reference Manual is available at http://www.adaic.com/standards/. It provides versions of the manual with change markup. For each year version, there are two different versions of manual, one that contains just the text of the official standard, and one which contains additional annotations for compiler writers, language lawyers etc. The latter version is called the "Annotated Ada Reference Manual" (or AARM for short). Both versions are provided by this package. Why aren't these files the same as upstream? ================================================ The text and HTML files are the same as upstream (processed by the same tool from the same Scribe sources). The upstream release does not include an info version; this package uses the upstream tool to produce texinfo format from the upstream Scribe sources, and then standard tools to produce info format. The upstream PDF files are produced from the Scribe sources using Microsoft word as an intermediate step. The PDF file built by this package is produced from the texinfo intermediate; it is intended for paper printing only, since it has no hyperlinks. Why don't these PDF files have hyperlinks? ========================================== The upstream PDF files don't have hyperlinks either. The problem is the intermediate processors; they don't generate proper hyperlinks for PDF (they do for HTML and info). To get hyperlinks in PDF, we would need to adapt the Ada code to produce PDF directly from the original source. Where do these files come from? =============================== The "upstream" for this distribution is in two pieces: - Source files for the Ada Reference Manual are released as a ZIP archive at http://www.ada-auth.org/arm-files/2012-SRC.zip. - Source files for the formatter are available via a CVSWeb HTML interface at http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ARM/. Usage ===== There are two monotone branches in the ada-france monotone server at www.ada-france.org (contact Ludovic Brenta <ludovic at ludovic dash brenta dot org> for access): org.adaic.arm_form.upstream Verbatim copy of the sources in the AdaIC CVS web server http://www.ada-auth.org/cgi-bin/cvsweb.cgi/arm/ except that: the file names are converted to lowercase. the line endings in the source directory are converted to unix. org.adaic.arm_form Local branch with minor changes, the texinfo generator, and a Makefile that builds everything. To do a release: build/Makefile if necessary, update AVAILABLE_YEARS for latest version if no new version, bump trailing digit in ZIP_VERSION otherwise, reset digit to 1 update-upstream (dvc-status "../org.adaic.arm_form.upstream") commit message "update from upstream" (xmtn-propagate-one "../org.adaic.arm_form.upstream" ".") build/Makefile all publish verify the following in progs/arm_texi.adb: Z:: no entries for Z? look near end of arm<version>.texinfo Update web page /Projects/Web/stephe-leake/ada/arm.html ~/Web/Makefile edit ARM_INFO_ZIP_VERSION arm_info sync (dvc-status ".") �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/���������������������������������������������������������������������0000755�0001752�0001001�00000000000�12273462240�015416� 5����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/01.mss���������������������������������������������������������������0000755�0001752�0001001�00000234535�12273462240�016401� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(01, Root="ada.mss") @PrefaceSection{} @Comment{Go to odd page.} @begin{Comment} The following stuff is to get the "INTERNATIONAL STANDARD" title between two horizontal rules at the top of page 1. (RLB-The following is a hack: I probably ought to add a style just for this purpose) @end{Comment} @thickline @begin{Wide} @noparanum@leading@tabclear()@tabset(P45) @Swiss<@Grow[@B{INTERNATIONAL STANDARD@\ISO/IEC 8652:@Chg{Version=[2],New=[2007(E), Ed. 3],Old=[@Chg{Version=[1], New=[1995(E) with COR.1:2001], Old=[]}]}}]> @end{Wide} @thickline @noparanum@ @*@comment{Some vertical whitespace} @ @* @ @* @noparanum@Swiss{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@b{Information technology @Em Programming}}}}}}}}}} @noparanum@Swiss{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@Grow{@b{Languages @Em Ada}}}}}}}}}} @noparanum@ @*@comment{Some vertical whitespace} @ @* @ @* @LabeledSectionNoBreak{General} @Comment{$Date: 2006/10/19 20:44:08 $} @Comment{$Source: e:\\cvsroot/ARM/Source/01.mss,v $} @Comment{$Revision: 1.57 $} @begin{Intro} Ada is a programming language designed to support the construction of long-lived, highly reliable software systems. The language includes facilities to define packages of related types, objects, and operations. The packages may be parameterized and the types may be extended to support the construction of libraries of reusable, adaptable software components. The operations may be implemented as subprograms using conventional sequential control structures, or as entries that include synchronization of concurrent threads of control as part of their invocation. The language treats modularity in the physical sense as well, with a facility to support separate compilation. The language includes a complete facility for the support of real-time, concurrent programming. Errors can be signaled as exceptions and handled explicitly. The language also covers systems programming; this requires precise control over the representation of data and access to system-dependent properties. Finally, a predefined environment of standard packages is provided, including facilities for, among others, input-output, string manipulation, numeric elementary functions, and random number generation. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} This Annotated Ada Reference Manual (AARM) contains the entire text of the Ada Reference Manual @Chg{Version=[2],New=[ with Amendment 1 (the Ada 2005 RM],Old=[(RM95]}), plus certain annotations. The annotations give a more in-depth analysis of the language. They describe the reason for each non-obvious rule, and point out interesting ramifications of the rules and interactions among the rules (interesting to language lawyers, that is). Differences between Ada 83@Chg{Version=[2],New=[, Ada 95, and Ada 2005],Old=[ and Ada 95]} are listed. (The text you are reading now is an annotation.) @ChgRef{Version=[2],Kind=[Revised]} The AARM stresses detailed correctness and uniformity over readability and understandability. We're not trying to make the language @lquotes@;appear@rquotes@; simple here; on the contrary, we're trying to expose hidden complexities, so we can more easily detect language bugs. The @Chg{Version=[2],New=[Ada 2005 RM],Old=[RM95]}, on the other hand, is intended to be a more readable document for programmers. @Leading@keepnext@;The annotations in the AARM are as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised]} Text that is logically redundant is shown @Redundant[in square brackets, like this]. Technically, such text could be written as a @NotesName in the @Chg{Version=[2],New=[Ada 2005 RM (and the Ada 95 RM before it)],Old=[RM95]}, since it is really a theorem that can be proven from the non-redundant rules of the language. We use the square brackets instead when it seems to make the @Chg{Version=[2],New=[Ada 2005 RM],Old=[RM95]} more readable. The rules of the language (and some AARM-only text) are categorized, and placed under certain @i{sub-headings} that indicate the category. For example, the distinction between @ResolutionName@;s and @LegalityName@;s is particularly important, as explained in @RefSecNum{The Context of Overload Resolution}. Text under the following sub-headings appears in both documents: @begin(Inneritemize) The unlabeled text at the beginning of each clause or subclause, @SyntaxTitle, @ResolutionTitle, @LegalityTitle, @StaticSemTitle, @LinkTimeTitle, @RunTimeTitle, @BoundedTitle, @ErronTitle, @ImplReqTitle, @DocReqTitle, @MetricsTitle, @ImplPermTitle, @ImplAdviceTitle, @NotesTitle, @ExamplesTitle. @end(Inneritemize) @ChgRef{Version=[2],Kind=[Revised]} Text under the following sub-headings does not appear in the @Chg{Version=[2],New=[Ada 2005 RM],Old=[RM95]}: @begin(Inneritemize) @MetaRulesTitle, @Inconsistent83Title, @Incompatible83Title, @Extend83Title, @ChgRef{Version=[2],Kind=[Revised]} @DiffWord83Title@Chg{Version=[2],New=[,],Old=[.]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@Inconsistent95Title,],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@Incompatible95Title,],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@Extend95Title,],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@DiffWord95Title.],Old=[]} @end(Inneritemize) The AARM also includes the following kinds of annotations. These do not necessarily annotate the immediately preceding rule, although they often do. @end{Itemize} @end{Discussion} @begin{Reason} An explanation of why a certain rule is necessary, or why it is worded in a certain way. @end{Reason} @begin{Ramification} An obscure ramification of the rules that is of interest only to language lawyers. (If a ramification of the rules is of interest to programmers, then it appears under @NotesTitle.) @end{Ramification} @begin{TheProof} An informal proof explaining how a given @NotesName or @Redundant[marked-as-redundant] piece of text follows from the other rules of the language. @end{TheProof} @begin{ImplNote} A hint about how to implement a feature, or a particular potential pitfall that an implementer needs to be aware of. @b{Change:} Change annotations are not used in this version. Changes from previous versions have been removed. Changes in this version are marked with versioned paragraph numbers, as explained in the @lquotes@;Corrigendum Changes@rquotes@; clause of the @lquotes@;Introduction@rquotes@;. @end{ImplNote} @begin{Discussion} Other annotations not covered by the above. @end{Discussion} @begin{Honest} A rule that is considered logically necessary to the definition of the language, but which is so obscure or pedantic that only a language lawyer would care. These are the only annotations that could be considered part of the language definition. @end{Honest} @begin{GlossaryMarker} The text of a Glossary entry @em this text will also appear in @RefSec{Glossary}. @end{GlossaryMarker} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} In general, @Chg{Version=[2],New=[the Ada 2005 RM],Old=[RM95]} text appears in the normal font, whereas AARM-only text appears in a smaller font. @NotesName@;s also appear in the smaller font, as recommended by ISO/IEC style guidelines. Ada examples are also usually printed in a smaller font. If you have trouble finding things, be sure to use the index. @Defn{italics, like this} Each defined term appears there, and also in @i{italics, like this}. Syntactic categories defined in BNF are also indexed. A definition marked @lquotes@;[distributed]@rquotes@; is the main definition for a term whose complete definition is given in pieces distributed throughout the document. The pieces are marked @lquotes@;[partial]@rquotes@; or with a phrase explaining what cases the partial definition applies to. @end{Discussion} @end{Intro} @LabeledClause{Scope} @begin{Intro} This International Standard specifies the form and meaning of programs written in Ada. Its purpose is to promote the portability of Ada programs to a variety of data processing systems. @end{Intro} @LabeledSubClause{Extent} @begin{Intro} @Leading@keepnext@;This International Standard specifies: @begin(Itemize) The form of a program written in Ada; The effect of translating and executing such a program; The manner in which program units may be combined to form Ada programs; The language-defined library units that a conforming implementation is required to supply; The permissible variations within the standard, and the manner in which they are to be documented; Those violations of the standard that a conforming implementation is required to detect, and the effect of attempting to translate or execute a program containing such violations; Those violations of the standard that a conforming implementation is not required to detect. @end(Itemize) @begin{Wide} @Leading@keepnext@;This International Standard does not specify: @end{Wide} @begin(Itemize) The means whereby a program written in Ada is transformed into object code executable by a processor; The means whereby translation or execution of programs is invoked and the executing units are controlled; The size or speed of the object code, or the relative execution speed of different language constructs; The form or contents of any listings produced by implementations; in particular, the form or contents of error or warning messages; The effect of unspecified execution. The size of a program or program unit that will exceed the capacity of a particular conforming implementation. @end(Itemize) @end{Intro} @LabeledSubClause{Structure} @begin{Intro} This International Standard contains thirteen sections, fourteen annexes, and an index. @Leading@Defn{core language} The @i{core} of the Ada language consists of: @begin{Itemize} Sections 1 through 13 @RefSec{Predefined Language Environment} @RefSec{Interface to Other Languages} @RefSec{Obsolescent Features} @end{Itemize} @begin{Wide} @Leading@Defn{Specialized Needs Annexes} @Defn2{Term=[Annex],Sec=(Specialized Needs)} @Defn{application areas} The following @i{Specialized Needs Annexes} define features that are needed by certain application areas: @end{Wide} @begin{Itemize} @RefSec{Systems Programming} @RefSec{Real-Time Systems} @RefSec{Distributed Systems} @RefSec{Information Systems} @RefSec{Numerics} @RefSec{High Integrity Systems} @end{Itemize} @begin{Wide} @Leading@Defn{normative} @Defn2{Term=[Annex],Sec=(normative)} The core language and the Specialized Needs Annexes are normative, except that the material in each of the items listed below is informative: @end{Wide} @begin(Itemize) Text under a NOTES or Examples heading. Each clause or subclause whose title starts with the word @lquotes@;Example@rquotes@; or @lquotes@;Examples@rquotes@;. @end(Itemize) All implementations shall conform to the core language. In addition, an implementation may conform separately to one or more Specialized Needs Annexes. @begin{Wide} @Leading@Keepnext@Defn{informative} @IndexSee{Term=[non-normative],See=(informative)} @Defn2{Term=[Annex],Sec=(informative)} The following Annexes are informative: @end{Wide} @begin{Itemize} @RefSec{Language-Defined Attributes} @RefSec{Language-Defined Pragmas} @RefSec{Implementation-Defined Characteristics} @RefSec{Glossary} @RefSec{Syntax Summary} @end{Itemize} @begin(Discussion) The idea of the Specialized Needs Annexes is that implementations can choose to target certain application areas. For example, an implementation specifically targeted to embedded machines might support the application-specific features for Real-time Systems, but not the application-specific features for Information Systems. The Specialized Needs Annexes extend the core language only in ways that users, implementations, and standards bodies are allowed to extend the language; for example, via additional library units, attributes, representation items (see @RefSecNum{Operational and Representation Items}), @nt{pragma}s, and constraints on semantic details that are left unspecified by the core language. Many implementations already provide much of the functionality defined by Specialized Needs Annexes; our goal is to increase uniformity among implementations by defining standard ways of providing the functionality. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]}@ChgNote{Make consistent with 18009} We recommend that the @Chg{Version=[2],New=[certification],Old=[validation]} procedures allow implementations to @Chg{Version=[2],New=[certify],Old=[validate]} the core language, plus any set of the Specialized Needs Annexes. We recommend that implementations @i{not} be allowed to @Chg{Version=[2],New=[certify],Old=[validate]} a portion of one of the Specialized Needs Annexes, although implementations can, of course, provide @Chg{Version=[2], New=[uncertified],Old=[unvalidated]} support for such portions. We have designed the Specialized Needs Annexes assuming that this recommendation is followed. Thus, our decisions about what to include and what not to include in those annexes are based on the assumption that each annex is @Chg{Version=[2],New=[certified],Old=[validated]} in an @lquotes@;all-or-nothing@rquotes@; manner. An implementation may, of course, support extensions that are different from (but possibly related to) those defined by one of the Specialized Needs Annexes. We recommend that, where appropriate, implementations do this by adding library units that are children of existing language-defined library packages. An implementation should not provide extensions that conflict with those defined in the Specialized Needs Annexes, in the following sense: Suppose an implementation supports a certain error-free program that uses only functionality defined in the core and in the Specialized Needs Annexes. The implementation should ensure that that program will still be error free in some possible full implementation of all of the Specialized Needs Annexes, and that the semantics of the program will not change. For example, an implementation should not provide a package with the same name as one defined in one of the Specialized Needs Annexes, but that behaves differently, @i{even if that implementation does not claim conformance to that Annex}. Note that the Specialized Needs Annexes do not conflict with each other; it is the intent that a single implementation can conform to all of them. @end(Discussion) @begin{Wide} Each section is divided into clauses and subclauses that have a common structure. Each section, clause, and subclause first introduces its subject. After the introductory text, text is labeled with the following headings: @end{Wide} @end{Intro} @begin{MetaRules} These are not rules of the language, but guiding principles or goals used in defining the rules of the language. In some cases, the goal is only partially met; such cases are explained. @ChgRef{Version=[2],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 2005 RM],Old=[RM95]}. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Defn2{Term=[syntax], Sec=(under Syntax heading)} @Defn2{Term=[grammar], Sec=(under Syntax heading)} @Defn2{Term=[context free grammar], Sec=(under Syntax heading)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(under Syntax heading)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(under Syntax heading)} Syntax rules (indented). @end{SyntaxText} @end{Syntax} @begin{Resolution} @Defn{name resolution rules} @Defn{overloading rules} @Defn{resolution rules} Compile-time rules that are used in name resolution, including overload resolution. @begin{Discussion} These rules are observed at compile time. (We say @lquotes@;observed@rquotes@; rather than @lquotes@;checked,@rquotes@; because these rules are not individually checked. They are really just part of the @LegalityName@;s in Section 8 that require exactly one interpretation of each constituent of a complete context.) The only rules used in overload resolution are the @SyntaxName@;s and the @ResolutionName@;s. When dealing with non-overloadable declarations it sometimes makes no semantic difference whether a given rule is a @ResolutionName or a @LegalityName, and it is sometimes difficult to decide which it should be. We generally make a given rule a @ResolutionName only if it has to be. For example, @lquotes@;The @nt{name}, if any, in a @nt{raise_statement} shall be the @nt{name} of an exception.@rquotes@; is under @lquotes@;@LegalityTitle.@rquotes@; @end{Discussion} @end{Resolution} @begin{Legality} @Defn{legality rules} @Defn{compile-time error} @Defn2{Term=[error], Sec=(compile-time)} Rules that are enforced at compile time. @Defn2{Term=[legal], Sec=(construct)} @Defn2{Term=[illegal], Sec=(construct)} A construct is @i{legal} if it obeys all of the @LegalityName@;s. @begin{Discussion} These rules are not used in overload resolution. Note that run-time errors are always attached to exceptions; for example, it is not @lquotes@;illegal@rquotes@; to divide by zero, it just raises an exception. @end{Discussion} @end{Legality} @begin{StaticSem} @Defn{static semantics} @Defn{compile-time semantics} A definition of the compile-time effect of each construct. @begin{Discussion} The most important compile-time effects represent the effects on the symbol table associated with declarations (implicit or explicit). In addition, we use this heading as a bit of a grab bag for equivalences, package specifications, etc. For example, this is where we put statements like so-and-so is equivalent to such-and-such. (We ought to try to really mean it when we say such things!) Similarly, statements about magically-generated implicit declarations go here. These rules are generally written as statements of fact about the semantics, rather than as a you-shall-do-such-and-such sort of thing. @end{Discussion} @end{StaticSem} @begin{LinkTime} @Defn{post-compilation error} @Defn{post-compilation rules} @IndexSee{Term=[link-time error],See=(post-compilation error)} @Defn2{Term=[error], Sec=(link-time)} Rules that are enforced before running a partition. @Defn2{Term=[legal], Sec=(partition)} @Defn2{Term=[illegal], Sec=(partition)} A partition is legal if its compilation units are legal and it obeys all of the @LinkTimeName@;s. @begin{Discussion} It is not specified exactly when these rules are checked, so long as they are checked for any given partition before that partition starts running. An implementation may choose to check some such rules at compile time, and reject @nt{compilation_unit}s accordingly. Alternatively, an implementation may check such rules when the partition is created (usually known as @lquotes@;link time@rquotes@;), or when the partition is mapped to a particular piece of hardware (but before the partition starts running). @end{Discussion} @end{LinkTime} @begin{RunTime} @Defn{dynamic semantics} @Defn{run-time semantics} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} A definition of the run-time effect of each construct. @begin{Discussion} This heading describes what happens at run time. Run-time checks, which raise exceptions upon failure, are described here. Each item that involves a run-time check is marked with the name of the check @em these are the same check names that are used in a @nt{pragma} Suppress. Principle: Every check should have a name, usable in a @nt{pragma} Suppress. @end{Discussion} @end{RunTime} @begin{Bounded} @Defn{bounded error} @SeeAlso{Primary=[error], Other=(bounded error)} Situations that result in bounded (run-time) errors (see @RefSecNum{Classification of Errors}). @begin{Discussion} The @lquotes@;bounds@rquotes@; of each such error are described here @em that is, we characterize the set of all possible behaviors that can result from a bounded error occurring at run time. @end{Discussion} @end{Bounded} @begin{Erron} @Defn{erroneous execution} @SeeAlso{Primary=[error], Other=(erroneous execution)} Situations that result in erroneous execution (see @RefSecNum{Classification of Errors}). @end{Erron} @begin{ImplReq} @Defn{implementation requirements} Additional requirements for conforming implementations. @begin{Discussion} ...as opposed to rules imposed on the programmer. An example might be, @lquotes@;The smallest representable duration, Duration'Small, shall not be greater than twenty milliseconds.@rquotes@; It's really just an issue of how the rule is worded. We could write the same rule as @lquotes@;The smallest representable duration is an implementation-defined value less than or equal to 20 milliseconds@rquotes@; and then it would be under @lquotes@;@StaticSemTitle.@rquotes@; @end{Discussion} @end{ImplReq} @begin{DocReq} @Defn{documentation requirements} Documentation requirements for conforming implementations. @begin{Discussion} These requirements are beyond those that are implicitly specified by the phrase @lquotes@;implementation defined@rquotes@;. The latter require documentation as well, but we don't repeat these cases under this heading. Usually this heading is used for when the description of the documentation requirement is longer and does not correspond directly to one, narrow normative sentence. @end{Discussion} @end{DocReq} @begin{Metrics} @Defn{metrics} Metrics that are specified for the time/space properties of the execution of certain language constructs. @end{Metrics} @begin{ImplPerm} @Defn{implementation permissions} Additional permissions given to the implementer. @begin{Discussion} For example, @lquotes@;The implementation is allowed to impose further restrictions on the record aggregates allowed in code statements.@rquotes@; When there are restrictions on the permission, those restrictions are given here also. For example, @lquotes@;An implementation is allowed to restrict the kinds of subprograms that are allowed to be main subprograms. However, it shall support at least parameterless procedures.@rquotes@; @em we don't split this up between here and @lquotes@;@ImplReqTitle.@rquotes@; @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} @Defn{implementation advice} @Defn{advice} Optional advice given to the implementer. The word @lquotes@;should@rquotes@; is used to indicate that the advice is a recommendation, not a requirement. It is implementation defined whether or not a given recommendation is obeyed. @ChgImplDef{Version=[2],Kind=[Revised],Text=[Whether or not each recommendation given in @ImplAdviceTitle is followed@Chg{Version=[2], New=[ @em see @RefSec{Implementation Advice} for a listing],Old=[]}.]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised]} The advice generally shows the intended implementation, but the implementer is free to ignore it. The implementer is the sole arbiter of whether or not the advice has been obeyed, if not, whether the reason is a good one, and whether the required documentation is sufficient. @Chg{Version=[1],New=[],Old=[@PDefn2{Term=[ACVC],Sec=(Ada Compiler Validation Capability)} @PDefn2{Term=[Ada Compiler Validation Capability],Sec=(ACVC)}]} It would be wrong for the @Chg{Version=[1],New=[ACATS],Old=[ACVC]} to enforce any of this advice. For example, @lquotes@;Whenever possible, the implementation should choose a value no greater than fifty microseconds for the smallest representable duration, Duration'Small.@rquotes@; We use this heading, for example, when the rule is so low level or implementation-oriented as to be untestable. We also use this heading when we wish to encourage implementations to behave in a certain way in most cases, but we do not wish to burden implementations by requiring the behavior. @end{Discussion} @end{ImplAdvice} @begin{Notes} @Defn{notes} Notes emphasize consequences of the rules described in the (sub)clause or elsewhere. This material is informative. @end{Notes} @begin{Examples} Examples illustrate the possible forms of the constructs described. This material is informative. @begin{Discussion} @ @* @Comment{Two blank lines: why? Because it was in the original.} @* The next three headings list all language changes between Ada 83 and Ada 95. Language changes are any change that changes the set of text strings that are legal Ada programs, or changes the meaning of any legal program. Wording changes, such as changes in terminology, are not language changes. Each language change falls into one of the following three categories: @end{Discussion} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} This heading lists all of the upward inconsistencies between Ada 83 and Ada 95. Upward inconsistencies are situations in which a legal Ada 83 program is a legal Ada 95 program with different semantics. This type of upward incompatibility is the worst type for users, so we only tolerate it in rare situations. (Note that the semantics of a program is not the same thing as the behavior of the program. Because of Ada's indeterminacy, the @lquotes@;semantics@rquotes@; of a given feature describes a @i{set} of behaviors that can be exhibited by that feature. The set can contain more than one allowed behavior. Thus, when we ask whether the semantics changes, we are asking whether the set of behaviors changes.) @ChgRef{Version=[2],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95 or Ada 2005 RM],Old=[RM95]}. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} This heading lists all of the upward incompatibilities between Ada 83 and Ada 95, except for the ones listed under @lquotes@;@Inconsistent83Title@rquotes@; above. These are the situations in which a legal Ada 83 program is illegal in Ada 95. We do not generally consider a change that turns erroneous execution into an exception, or into an illegality, to be upwardly incompatible. @ChgRef{Version=[2],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95 or Ada 2005 RM],Old=[RM95]}. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 95 program is not a legal Ada 83 program. The vast majority of language changes fall into this category. @ChgRef{Version=[2],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95 or Ada 2005 RM],Old=[RM95]}. @Leading@ @* @Comment{Two blank lines: why? Because it was in the original.} @* As explained above, the next heading does not represent any language change: @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised]} @Defn{wording changes from Ada 83} This heading lists some of the non-semantic changes between @Chg{Version=[2], New=[the Ada 83 RM],Old=[RM83]} and the @Chg{Version=[2],New=[the Ada 95 RM],Old=[RM95]}. It is incomplete; we have not attempted to list all wording changes, but only the @lquotes@;interesting@rquotes@; ones. @ChgRef{Version=[2],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95 or Ada 2005 RM],Old=[RM95]}. @end{DiffWord83} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* The next three headings list all language changes between Ada 95 and Ada 2005 (the language defined by the Ada 95 standard plus Technical Corrigendum 1 plus Amendment 1). Each language change falls into one of the following three categories:]} @end{Discussion} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} This heading lists all of the upward inconsistencies between Ada 95 and Ada 2005. Upward inconsistencies are situations in which a legal Ada 95 program is a legal Ada 2005 program with different semantics.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Inconsistencies marked with @b[Corrigendum:]@Defn{Corrigendum} are corrections to the original Ada 95 definition introduced by Corrigendum 1. Inconsistencies marked with @b[Amendment Correction:]@Defn{Amendment Correction} are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are inconsistencies caused by Ada Issues classified as Binding Interpretations; implementations of Ada 95 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not inconsistencies between Ada 95 and Ada 2005. Practically, however, they very well may be, as early Ada 95 implementations may not follow the recommendation. Inconsistencies so marked are not portable between Ada 95 implementations, while usually Ada 2005 will have more clearly defined behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 RM.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} This heading lists all of the upward incompatibilities between Ada 95 and Ada 2005, except for the ones listed under @lquotes@;@Inconsistent95Title@rquotes@; above. These are the situations in which a legal Ada 95 program is illegal in Ada 2005.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As with inconsistencies, incompatibilities marked with @b[Corrigendum:] are corrections to the original Ada 95 definition introduced by Corrigendum 1. Incompatibilities marked with @b[Amendment Correction:] are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are incompatibilities caused by Ada Issues classified as Binding Interpretations; implementations of Ada 95 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not incompatibilities between Ada 95 and Ada 2005. Practically, however, they very well may be, as early Ada 95 implementations may not follow the recommendation. Therefore, some Ada 95 implementations may be able to compile the examples, while others may not. In constrast, Ada 2005 compilers will have consistent behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 RM.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Defn{extensions to Ada 95} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 2005 program is not a legal Ada 95 program. The vast majority of language changes fall into this category.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As with incompatibilities, extensions marked with @b[Corrigendum:] are corrections to the original Ada 95 definition introduced by Corrigendum 1. Extensions marked with @b[Amendment Correction:] are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are extensions allowed by Ada Issues classified as Binding Interpretations. As corrections, implementations of Ada 95 are allowed to implement these extensions. Thus, these strictly speaking are not extensions of Ada 95; they're part of Ada 95. Practically, however, they very well may be extensions, as early Ada 95 implementations may not implement the extension. Therefore, some Ada 95 implementations may be able to compile the examples, while others may not. In constrast, Ada 2005 compilers will always support the extensions. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[This is not part of the definition of the language, and does not appear in the Ada 2005 RM.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* As explained above, the next heading does not represent any language change:]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Defn{wording changes from Ada 95} This heading lists some of the non-semantic changes between the Ada 95 RM and the Ada 2005 RM. This heading lists only @lquotes@;interesting@rquotes@; changes (for instance, editorial corrections are not listed). Changes which come from Technical Corrigendum 1 are marked @b{Corrigendum}; unmarked changes come from Amendment 1.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[This is not part of the definition of the language, and does not appear in the Ada 2005 RM.],Old=[]} @end{DiffWord95} @LabeledSubClause{Conformity of an Implementation with the Standard} @begin{ImplReq} @Leading@Keepnext@Defn2{Term=[conformance],Sec=(of an implementation with the Standard)} A conforming implementation shall: @begin{Discussion} @Defn{implementation} The @i{implementation} is the software and hardware that implements the language. This includes compiler, linker, operating system, hardware, etc. We first define what it means to @lquotes@;conform@rquotes@; in general @em basically, the implementation has to properly implement the normative rules given throughout the standard. Then we define what it means to conform to a Specialized Needs Annex @em the implementation must support the core features plus the features of that Annex. Finally, we define what it means to @lquotes@;conform to the Standard@rquotes@; @em this requires support for the core language, and allows partial (but not conflicting) support for the Specialized Needs Annexes. @end{Discussion} @begin(Itemize) Translate and correctly execute legal programs written in Ada, provided that they are not so large as to exceed the capacity of the implementation; Identify all programs or program units that are so large as to exceed the capacity of the implementation (or raise an appropriate exception at run time); @ImplDef{Capacity limitations of the implementation.} Identify all programs or program units that contain errors whose detection is required by this International Standard; @begin{Discussion} Note that we no longer use the term @lquotes@;rejection@rquotes@; of programs or program units. We require that programs or program units with errors or that exceed some capacity limit be @lquotes@;identified@rquotes@;. The way in which errors or capacity problems are reported is not specified. An implementation is allowed to use standard error-recovery techniques. We do not disallow such techniques from being used across @nt{compilation_unit} or @nt{compilation} boundaries. See also the @ImplReqTitle of @RefSecNum{Program Execution}, which disallow the execution of illegal partitions. @end{Discussion} Supply all language-defined library units required by this International Standard; @begin{ImplNote} An implementation cannot add to or modify the visible part of a language-defined library unit, except where such permission is explicitly granted, unless such modifications are semantically neutral with respect to the client compilation units of the library unit. An implementation defines the contents of the private part and body of language-defined library units. An implementation can add @nt{with_clause}s and @nt{use_clause}s, since these modifications are semantically neutral to clients. (The implementation might need @nt{with_clause}s in order to implement the private part, for example.) Similarly, an implementation can add a private part even in cases where a private part is not shown in the standard. Explicit declarations can be provided implicitly or by renaming, provided the changes are semantically neutral. @Defn2{Term=[italics],Sec=(implementation-defined)} Wherever in the standard the text of a language-defined library unit contains an italicized phrase starting with @lquotes@;@i{implementation-defined}@rquotes@;, the implementation's version will replace that phrase with some implementation-defined text that is syntactically legal at that place, and follows any other applicable rules. Note that modifications are permitted, even if there are other tools in the environment that can detect the changes (such as a program library browser), so long as the modifications make no difference with respect to the static or dynamic semantics of the resulting programs, as defined by the standard. @end{ImplNote} Contain no variations except those explicitly permitted by this International Standard, or those that are impossible or impractical to avoid given the implementation's execution environment; @ImplDef{Variations from the standard that are impractical to avoid given the implementation's execution environment.} @begin{Reason} The @lquotes@;impossible or impractical@rquotes@; wording comes from AI-325. It takes some judgement and common sense to interpret this. Restricting compilation units to less than 4 lines is probably unreasonable, whereas restricting them to less than 4 billion lines is probably reasonable (at least given today's technology). We do not know exactly where to draw the line, so we have to make the rule vague. @end{Reason} Specify all such variations in the manner prescribed by this International Standard. @end(Itemize) @begin{Wide} @Leading@keepnext@Defn2{Term=[external effect], Sec=(of the execution of an Ada program)} @Defn2{Term=[effect], Sec=(external)} The @i(external effect) of the execution of an Ada program is defined in terms of its interactions with its external environment. @Defn{external interaction} The following are defined as @i(external interactions): @end{Wide} @begin(Itemize) Any interaction with an external file (see @RefSecNum(External Files and File Objects)); The execution of certain @nt<code_statement>s (see @RefSecNum{Machine Code Insertions}); which @nt{code_statement}s cause external interactions is implementation defined. @ImplDef{Which @nt{code_statement}s cause external interactions.} Any call on an imported subprogram (see @RefSecNum(Interface to Other Languages)), including any parameters passed to it; Any result returned or exception propagated from a main subprogram (see @RefSecNum(Program Execution)) or an exported subprogram (see @RefSecNum(Interface to Other Languages)) to an external caller; @begin{Discussion} By @lquotes@;result returned@rquotes@; we mean to include function results and values returned in [@key(in)] @key(out) parameters. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0094],ARef=[AI95-00119-01]} @Chg{Version=[1],New=[The lack of a result from a program that does not terminate is also included here.],Old=[]} @end{Discussion} @Redundant[Any read or update of an atomic or volatile object (see @RefSecNum(Shared Variable Control));] The values of imported and exported objects (see @RefSecNum(Interface to Other Languages)) at the time of any other interaction with the external environment. @begin{Honest} Also other uses of imported and exported entities, as defined by the implementation, if the implementation supports such @nt{pragma}s. @end{Honest} @end(Itemize) @begin{Wide} A conforming implementation of this International Standard shall produce for the execution of a given Ada program a set of interactions with the external environment whose order and timing are consistent with the definitions and requirements of this International Standard for the semantics of the given program. @end{Wide} @begin{Ramification} There is no need to produce any of the @lquotes@;internal effects@rquotes@; defined for the semantics of the program @em all of these can be optimized away @em so long as an appropriate sequence of external interactions is produced. @end{Ramification} @begin{Discussion} See also @RefSecNum(Exceptions and Optimization) which specifies various liberties associated with optimizations in the presence of language-defined checks, that could change the external effects that might be produced. These alternative external effects are still consistent with the standard, since @RefSecNum(Exceptions and Optimization) is part of the standard. Note also that we only require @lquotes@;@i(an appropriate) sequence of external interactions@rquotes@; rather than @lquotes@;@i(the same) sequence...@rquotes@; An optimizer may cause a different sequence of external interactions to be produced than would be produced without the optimizer, so long as the new sequence still satisfies the requirements of the standard. For example, optimization might affect the relative rate of progress of two concurrent tasks, thereby altering the order in which two external interactions occur. @ChgRef{Version=[2],Kind=[Revised]} Note that @Chg{Version=[2],New=[the Ada 83 RM],Old=[RM83]} explicitly mentions the case of an @lquotes@;exact effect@rquotes@; of a program, but since so few programs have their effects defined that exactly, we don't even mention this @lquotes@;special@rquotes@; case. In particular, almost any program that uses floating point or tasking has to have some level of inexactness in the specification of its effects. And if one includes aspects of the timing of the external interactions in the external effect of the program (as is appropriate for a real-time language), no @lquotes@;exact effect@rquotes@; can be specified. For example, if two external interactions initiated by a single task are separated by a @lquotes@;@key(delay) 1.0;@rquotes@; then the language rules imply that the two external interactions have to be separated in time by at least one second, as defined by the clock associated with the @nt<delay_relative_statement>. This in turn implies that the time at which an external interaction occurs is part of the characterization of the external interaction, at least in some cases, again making the specification of the required @lquotes@;exact effect@rquotes@; impractical. @end{Discussion} An implementation that conforms to this Standard shall support each capability required by the core language as specified. In addition, an implementation that conforms to this Standard may conform to one or more Specialized Needs Annexes (or to none). Conformance to a Specialized Needs Annex means that each capability required by the Annex is provided as specified. @begin{Discussion} The last sentence defines what it means to say that an implementation conforms to a Specialized Needs Annex, namely, only by supporting all capabilities required by the Annex. @end{Discussion} An implementation conforming to this International Standard may provide additional attributes, library units, and pragmas. However, it shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in a Specialized Needs Annex unless the provided construct is either as specified in the Specialized Needs Annex or is more limited in capability than that required by the Annex. A program that attempts to use an unsupported capability of an Annex shall either be identified by the implementation before run time or shall raise an exception at run time. @begin{Discussion} The last sentence of the preceding paragraph defines what an implementation is allowed to do when it does not "conform" to a Specialized Needs Annex. In particular, the sentence forbids implementations from providing a construct with the same name as a corresponding construct in a Specialized Needs Annex but with a different syntax (e.g., an extended syntax) or quite different semantics. The phrase concerning "more limited in capability" is intended to give permission to provide a partial implementation, such as not implementing a subprogram in a package or having a restriction not permitted by an implementation that conforms to the Annex. For example, a partial implementation of the package Ada.Decimal might have Decimal.Max_Decimal_Digits as 15 (rather than the required 18). This allows a partial implementation to grow to a fully conforming implementation. A restricted implementation might be restricted by not providing some subprograms specified in one of the packages defined by an Annex. In this case, a program that tries to use the missing subprogram will usually fail to compile. Alternatively, the implementation might declare the subprogram as abstract, so it cannot be called. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Alternatively, a subprogram body might be implemented just to raise Program_Error. The advantage of this approach is that a program to be run under a fully conforming Annex implementation can be checked syntactically and semantically under an implementation that only partially supports the Annex. Finally, an implementation might provide a package declaration without the corresponding body, so that programs can be compiled, but partitions cannot be built and executed. To ensure against wrong answers being delivered by a partial implementation, implementers are required to raise an exception when a program attempts to use an unsupported capability and this can be detected only at run time. For example, a partial implementation of Ada.Decimal might require the length of the Currency string to be 1, and hence, an exception would be raised if a subprogram were called in the package Edited_Output with a length greater than 1. @end{Discussion} @end{ImplReq} @begin{DocReq} @Defn{implementation defined} @Defn{unspecified} @Defn{specified (not!)} @IndexSee{Term=[implementation-dependent],See=(unspecified)} @Defn{documentation (required of an implementation)} Certain aspects of the semantics are defined to be either @i{implementation defined} or @i{unspecified}. In such cases, the set of possible effects is specified, and the implementation may choose any effect in the set. Implementations shall document their behavior in implementation-defined situations, but documentation is not required for unspecified situations. The implementation-defined characteristics are summarized in @RefSecNum{Implementation-Defined Characteristics}. @begin{Discussion} We used to use the term @lquotes@;implementation dependent@rquotes@; instead of @lquotes@;unspecified@rquotes@;. However, that sounded too much like @lquotes@;implementation defined@rquotes@;. Furthermore, the term @lquotes@;unspecified@rquotes@; is used in the ANSI C and POSIX standards for this purpose, so that is another advantage. We also use @lquotes@;not specified@rquotes@; and @lquotes@;not specified by the language@rquotes@; as synonyms for @lquotes@;unspecified.@rquotes@; The documentation requirement is the only difference between implementation defined and unspecified. Note that the @lquotes@;set of possible effects@rquotes@; can be @lquotes@;all imaginable effects@rquotes@;, as is the case with erroneous execution. @end{Discussion} The implementation may choose to document implementation-defined behavior either by documenting what happens in general, or by providing some mechanism for the user to determine what happens in a particular case. @begin(Discussion) For example, if the standard says that library unit elaboration order is implementation defined, the implementation might describe (in its user's manual) the algorithm it uses to determine the elaboration order. On the other hand, the implementation might provide a command that produces a description of the elaboration order for a partition upon request from the user. It is also acceptable to provide cross references to existing documentation (for example, a hardware manual), where appropriate. Note that dependence of a program on implementation-defined or unspecified functionality is not defined to be an error; it might cause the program to be less portable, however. @end(Discussion) @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The behavior of implementations in implementation-defined situations shall be documented @em see @RefSec{Implementation-Defined Characteristics} for a listing.]}]} @end{DocReq} @begin{ImplAdvice} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If an implementation detects the use of an unsupported Specialized Needs Annex feature at run time, it should raise Program_Error if feasible. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Program_Error should be raised when an unsupported Specialized Needs Annex feature is used at run time.]}]} @begin{Reason} The reason we don't @i{require} Program_Error is that there are situations where other exceptions might make sense. For example, if the Real Time Systems Annex requires that the range of System.Priority include at least 30 values, an implementation could conform to the Standard (but not to the Annex) if it supported only 12 values. Since the rules of the language require Constraint_Error to be raised for out-of-range values, we cannot require Program_Error to be raised instead. @end{Reason} If an implementation wishes to provide implementation-defined extensions to the functionality of a language-defined library unit, it should normally do so by adding children to the library unit. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined extensions to the functionality of a language-defined library unit should be provided by adding children to the library unit.]}]} @begin(ImplNote) If an implementation has support code (@lquotes@;run-time system code@rquotes@;) that is needed for the execution of user-defined code, it can put that support code in child packages of System. Otherwise, it has to use some trick to avoid polluting the user's namespace. It is important that such tricks not be available to user-defined code (not in the standard mode, at least) @em that would defeat the purpose. @end(ImplNote) @end{ImplAdvice} @begin{Notes} The above requirements imply that an implementation conforming to this Standard may support some of the capabilities required by a Specialized Needs Annex without supporting all required capabilities. @begin{Discussion} A conforming implementation can partially support a Specialized Needs Annex. Such an implementation does not conform to the Annex, but it does conform to the Standard. @end{Discussion} @end{Notes} @LabeledSubClause{Method of Description and Syntax Notation} @begin{Intro} The form of an Ada program is described by means of a context-free syntax together with context-dependent requirements expressed by narrative rules. The meaning of Ada programs is described by means of narrative rules defining both the effects of each construct and the composition rules for constructs. @Leading@keepnext@;@Defn2{Term=[syntax], Sec=(notation)} @Defn2{Term=[grammar], Sec=(notation)} @Defn2{Term=[context free grammar], Sec=(notation)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(notation)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(notation)} The context-free syntax of the language is described using a simple variant of Backus-Naur Form. In particular: @begin(Itemize) @leading@keepnext@;Lower case words in a sans-serif font, some containing embedded underlines, are used to denote syntactic categories, for example: @begin(Display) @nt<case_statement> @end(Display) @leading@keepnext@;Boldface words are used to denote reserved words, for example: @begin(Display) @key(array) @end(Display) @leading@keepnext@;Square brackets enclose optional items. Thus the two following rules are equivalent. @begin(Display) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]}@Chg{Version=[2],New=[@nt<simple_return_statement>],Old=[@nt<return_statement>]} ::= @key(return) [@nt<expression>]; @Chg{Version=[2],New=[@nt<simple_return_statement>],Old=[@nt<return_statement>]} ::= @key(return); | @key(return) @nt<expression>; @end(Display) @leading@keepnext@;Curly brackets enclose a repeated item. The item may appear zero or more times; the repetitions occur from left to right as with an equivalent left-recursive rule. Thus the two following rules are equivalent. @begin(Display) @nt<term> ::= @nt<factor> {@nt<multiplying_operator> @nt<factor>} @nt<term> ::= @nt<factor> | @nt<term> @nt<multiplying_operator> @nt<factor> @end(Display) @leading@keepnext@;A vertical line separates alternative items unless it occurs immediately after an opening curly bracket, in which case it stands for itself: @begin(Display) @nt<constraint> ::= @nt<scalar_constraint> | @nt<composite_constraint> @nt<discrete_choice_list> ::= @nt<discrete_choice> {| @nt<discrete_choice>} @end(Display) @Defn2{Term=[italics],Sec=(syntax rules)} If the name of any syntactic category starts with an italicized part, it is equivalent to the category name without the italicized part. The italicized part is intended to convey some semantic information. For example @i(subtype_)@nt<name> and @i(task_)@nt<name> are both equivalent to @nt<name> alone. @end(Itemize) @begin(Discussion) @Defn{LR(1)} @Defn{ambiguous grammar} @Defn2{Term=[grammar],Sec=(resolution of ambiguity)} @Defn2{Term=[grammar],Sec=(ambiguous)} The grammar given in @Chg{Version=[2],New=[this International Standard], old=[the RM95]} is not LR(1). In fact, it is ambiguous; the ambiguities are resolved by the overload resolution rules (see @RefSecNum{The Context of Overload Resolution}). We often use @lquotes@;if@rquotes@; to mean @lquotes@;if and only if@rquotes@; in definitions. For example, if we define @lquotes@;photogenic@rquotes@; by saying, @lquotes@;A type is photogenic if it has the following properties...,@rquotes@; we mean that a type is photogenic if @i{and only if} it has those properties. It is usually clear from the context, and adding the @lquotes@;and only if@rquotes@; seems too cumbersome. When we say, for example, @lquotes@;a @nt{declarative_item} of a @nt{declarative_part}@rquotes@;, we are talking about a @nt{declarative_item} immediately within that @nt{declarative_part}. When we say @lquotes@;a @nt{declarative_item} in, or within, a @nt{declarative_part}@rquotes@;, we are talking about a @nt{declarative_item} anywhere in the @nt{declarative_part}, possibly deeply nested within other @nt{declarative_part}s. (This notation doesn't work very well for @nt{name}s, since the name @lquotes@;of@rquotes@; something also has another meaning.) When we refer to the name of a language-defined entity (for example, Duration), we mean the language-defined entity even in programs where the declaration of the language-defined entity is hidden by another declaration. For example, when we say that the expected type for the @nt<expression> of a @nt<delay_relative_statement> is Duration, we mean the language-defined type Duration that is declared in Standard, not some type Duration the user might have declared. @end(Discussion) @begin{Wide} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The delimiters, compound delimiters, reserved words, and @nt{numeric_literal}s are exclusively made of the characters whose code position is between 16#20# and 16#7E#, inclusively. The special characters for which names are defined in this International Standard (see @RefSecNum{Character Set}) belong to the same range. @Redundant[For example, the character E in the definition of exponent is the character whose name is @lquotes@;LATIN CAPITAL LETTER E@rquotes@;, not @lquotes@;GREEK CAPITAL LETTER EPSILON@rquotes@;.]]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This just means that programs can be written in plain ASCII characters; no characters outside of the 7-bit range are required.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[When this International Standard mentions the conversion of some character or sequence of characters to upper case, it means the character or sequence of characters obtained by using locale-independent full case folding, as defined by documents referenced in the note in section 1 of ISO/IEC 10646:2003.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unless otherwise specified for sequences of characters, case folding is applied to the sequence, not to individual characters. It sometimes can make a difference.]} @end{Discussion} @end{Wide} @begin{Wide} @Defn{syntactic category} A @i{syntactic category} is a nonterminal in the grammar defined in BNF under @lquotes@;@SyntaxTitle.@rquotes@; Names of syntactic categories are set in a different font, @ntf{like_this}. @end{Wide} @ToGlossaryAlso{Term=<Construct>, Text=<A @i(construct) is a piece of text (explicit or implicit) that is an instance of a syntactic category defined under @lquotes@;@SyntaxTitle@rquotes@;.>} @begin{Ramification} For example, an @nt{expression} is a construct. A declaration is a construct, whereas the thing declared by a declaration is an @lquotes@;entity.@rquotes@; @end{Ramification} @begin{Discussion} @lquotes@;Explicit@rquotes@; and @lquotes@;implicit@rquotes@; don't mean exactly what you might think they mean: The text of an instance of a generic is considered explicit, even though it does not appear explicitly (in the non-technical sense) in the program text, and even though its meaning is not defined entirely in terms of that text. @end{Discussion} @Defn2{term=<constituent>, Sec=<of a construct>} A @i{constituent} of a construct is the construct itself, or any construct appearing within it. @Defn{arbitrary order} Whenever the run-time semantics defines certain actions to happen in an @i{arbitrary order}, this means that the implementation shall arrange for these actions to occur in a way that is equivalent to some sequential order, following the rules that result from that sequential order. When evaluations are defined to happen in an arbitrary order, with conversion of the results to some subtypes, or with some run-time checks, the evaluations, conversions, and checks may be arbitrarily interspersed, so long as each expression is evaluated before converting or checking its value. @PDefn2{Term=[type conversion],Sec=(arbitrary order)} @PDefn2{Term=[conversion],Sec=(arbitrary order)} @Redundant[Note that the effect of a program can depend on the order chosen by the implementation. This can happen, for example, if two actual parameters of a given call have side effects.] @begin{Discussion} Programs will be more portable if their external effect does not depend on the particular order chosen by an implementation. @end{Discussion} @begin{Ramification} Additional reordering permissions are given in @RefSec(Exceptions and Optimization). There is no requirement that the implementation always choose the same order in a given kind of situation. In fact, the implementation is allowed to choose a different order for two different executions of the same construct. However, we expect most implementations will behave in a relatively predictable manner in most situations. @end{Ramification} @begin{Reason} The @lquotes@;sequential order@rquotes@; wording is intended to allow the programmer to rely on @lquotes@;benign@rquotes@; side effects. For example, if F is a function that returns a unique integer by incrementing some global and returning the result, a call such as P(F, F) is OK if the programmer cares only that the two results of F are unique; the two calls of F cannot be executed in parallel, unless the compiler can prove that parallel execution is equivalent to some sequential order. @end{Reason} @end{Intro} @begin{Notes} The syntax rules describing structured constructs are presented in a form that corresponds to the recommended paragraphing. For example, an @nt{if_statement} is defined as: @begin(Example) @nt<if_statement> ::= @key(if) @nt<condition> @key(then) @nt<sequence_of_statements> {@key(elsif) @nt<condition> @key(then) @nt<sequence_of_statements>} [@key(else) @nt<sequence_of_statements>] @key(end if); @end(Example) The line breaks and indentation in the syntax rules indicate the recommended line breaks and indentation in the corresponding constructs. The preferred places for other line breaks are after semicolons. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We now explicitly say that the lexical elements of the language (with a few exceptions) are made up of characters in the lower half of the Latin-1 character set. This is needed to avoid confusion given the new capability to use most ISO 10646 characters in identifiers and strings.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[We now explicitly define what the Standard means by upper case, as there are many possibilities for ISO 10646 characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The example for square brackets has been changed as there is no longer a @ntf{return_statement} syntax rule.]} @end{DiffWord95} @LabeledSubClause{Classification of Errors} @begin{ImplReq} @Leading@Keepnext@;The language definition classifies errors into several different categories: @begin(Itemize) @Keepnext@;Errors that are required to be detected prior to run time by every Ada implementation; @NoPrefix@;These errors correspond to any violation of a rule given in this International Standard, other than those listed below. In particular, violation of any rule that uses the terms shall, allowed, permitted, legal, or illegal belongs to this category. Any program that contains such an error is not a legal Ada program; on the other hand, the fact that a program is legal does not mean, @i(per se), that the program is free from other forms of error. @NoPrefix@Defn{compile-time error} @Defn2{Term=[error], Sec=(compile-time)} @IndexSee{Term=[link-time error],See=(post-compilation error)} @Defn2{Term=[error], Sec=(link-time)} The rules are further classified as either compile time rules, or post compilation rules, depending on whether a violation has to be detected at the time a compilation unit is submitted to the compiler, or may be postponed until the time a compilation unit is incorporated into a partition of a program. @begin{Ramification} See, for example, @RefSec(Subunits of Compilation Units), for some errors that are detected only after compilation. Implementations are allowed, but not required, to detect post compilation rules at compile time when possible. @end{Ramification} @Keepnext@;Errors that are required to be detected at run time by the execution of an Ada program; @NoPrefix@Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} The corresponding error situations are associated with the names of the predefined exceptions. Every Ada compiler is required to generate code that raises the corresponding exception if such an error situation arises during program execution. @Redundant[If such an error situation is certain to arise in every execution of a construct, then an implementation is allowed (although not required) to report this fact at compilation time.] @Keepnext@;Bounded errors; @NoPrefix@;The language rules define certain kinds of errors that need not be detected either prior to or during run time, but if not detected, the range of possible effects shall be bounded. @Defn{bounded error} The errors of this category are called @i{bounded errors}. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible effects of a given bounded error are specified for each such error, but in any case one possible effect of a bounded error is the raising of the exception Program_Error. @Keepnext@;Erroneous execution. @NoPrefix@Defn{erroneous execution} In addition to bounded errors, the language rules define certain kinds of errors as leading to @i{erroneous execution}. Like bounded errors, the implementation need not detect such errors either prior to or during run time. Unlike bounded errors, there is no language-specified bound on the possible effect of erroneous execution; the effect is in general not predictable. @begin{Ramification} Executions are erroneous, not programs or parts of programs. Once something erroneous happens, the execution of the entire program is erroneous from that point on, and potentially before given possible reorderings permitted by @RefSecNum(Exceptions and Optimization) and elsewhere. We cannot limit it to just one partition, since partitions are not required to live in separate address spaces. (But implementations are encouraged to limit it as much as possible.) Suppose a program contains a pair of things that will be executed @lquotes@;in an arbitrary order.@rquotes@; It is possible that one order will result in something sensible, whereas the other order will result in erroneous execution. If the implementation happens to choose the first order, then the execution is not erroneous. This may seem odd, but it is not harmful. Saying that something is erroneous is semantically equivalent to saying that the behavior is unspecified. However, @lquotes@;erroneous@rquotes@; has a slightly more disapproving flavor. @end{Ramification} @end(Itemize) @end{ImplReq} @begin{ImplPerm} @Redundant[@Defn2{Term={mode of operation}, Sec=(nonstandard)} @Defn{nonstandard mode}An implementation may provide @i(nonstandard modes) of operation. Typically these modes would be selected by a @nt<pragma> or by a command line switch when the compiler is invoked. When operating in a nonstandard mode, the implementation may reject @nt<compilation_unit>s that do not conform to additional requirements associated with the mode, such as an excessive number of warnings or violation of coding style guidelines. Similarly, in a nonstandard mode, the implementation may apply special optimizations or alternative algorithms that are only meaningful for programs that satisfy certain criteria specified by the implementation. @Defn2{Term={mode of operation}, Sec=(standard)} @Defn{standard mode} In any case, an implementation shall support a @i(standard) mode that conforms to the requirements of this International Standard; in particular, in the standard mode, all legal @nt<compilation_unit>s shall be accepted.] @begin{Discussion} These permissions are designed to authorize explicitly the support for alternative modes. Of course, nothing we say can prevent them anyway, but this (redundant) paragraph is designed to indicate that such alternative modes are in some sense @lquotes@;approved@rquotes@; and even encouraged where they serve the specialized needs of a given user community, so long as the standard mode, designed to foster maximum portability, is always available. @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If an implementation detects a bounded error or erroneous execution, it should raise Program_Error. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If a bounded error or erroneous execution is detected, Program_Error should be raised.]}]} @end{ImplAdvice} @begin{DiffWord83} Some situations that are erroneous in Ada 83 are no longer errors at all. For example, depending on the parameter passing mechanism when unspecified is possibly non-portable, but not erroneous. Other situations that are erroneous in Ada 83 are changed to be bounded errors. In particular, evaluating an uninitialized scalar variable is a bounded error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible results are to raise Program_Error (as always), or to produce a machine-representable value (which might not be in the subtype of the variable). @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Violating a Range_Check or Overflow_Check raises Constraint_Error, even if the value came from an uninitialized variable. This means that optimizers can no longer @lquotes@;assume@rquotes@; that all variables are initialized within their subtype's range. Violating a check that is suppressed remains erroneous. The @lquotes@;incorrect order dependences@rquotes@; category of errors is removed. All such situations are simply considered potential non-portabilities. This category was removed due to the difficulty of defining what it means for two executions to have a @lquotes@;different effect.@rquotes@; For example, if a function with a side-effect is called twice in a single expression, it is not in principle possible for the compiler to decide whether the correctness of the resulting program depends on the order of execution of the two function calls. A compile time warning might be appropriate, but raising of Program_Error at run time would not be. @end{DiffWord83} @LabeledClause{Normative References} @begin{Intro} @Defn{references} @Defn{bibliography} The following standards contain provisions which, through reference in this text, constitute provisions of this International Standard. At the time of publication, the editions indicated were valid. All standards are subject to revision, and parties to agreements based on this International Standard are encouraged to investigate the possibility of applying the most recent editions of the standards indicated below. Members of IEC and ISO maintain registers of currently valid International Standards. @Defn{ISO/IEC 646:1991} @Defn{646:1991, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(7-bit)} ISO/IEC 646:1991, @i{Information technology @em ISO 7-bit coded character set for information interchange}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Chg{Version=[2],New=[@Defn{ISO/IEC 1539-1:2004} @Defn{1539-1:2004, ISO/IEC standard} @Defn{Fortran standard}], Old=[@Defn{ISO/IEC 1539:1991} @Defn{1539:1991, ISO/IEC standard} @Defn{FORTRAN standard}]} ISO/IEC @Chg{Version=[2],New=[1539-1:2004],Old=[1539:1991]}, @i{Information technology @em Programming languages @em @Chg{Version=[2], New=[Fortran @em Part 1: Base language],Old=[FORTRAN]}}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Chg{Version=[2],New=[@Defn{ISO 1989:2002} @Defn{1989:2002, ISO standard}],Old=[@Defn{ISO 1989:1985} @Defn{1989:1985, ISO standard}]} @Defn{COBOL standard} ISO@Chg{Version=[2],New=[/IEC],Old=[]} 1989:@Chg{Version=[2],New=[2002],Old=[1985]}, @i{@Chg{Version=[2],New=[Information technology @em ],Old=[]}Programming languages @em COBOL}. @Defn{ISO/IEC 6429:1992} @Defn{6429:1992, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(control functions)} ISO/IEC 6429:1992, @i{Information technology @em Control functions for coded graphic character sets}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[@Defn{ISO 8601:2004} @Defn{date and time formatting standard} ISO 8601:2004, @i{Data elements and interchange formats @em Information interchange @em Representation of dates and times}.]} @Defn{ISO/IEC 8859-1:1987} @Defn{8859-1:1987, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(8-bit)} ISO/IEC 8859-1:1987, @i{Information processing @em 8-bit single-byte coded character sets @em Part 1: Latin alphabet No. 1}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Chg{Version=[2],New=[@Defn{ISO/IEC 9899:1999} @Defn{9899:1999, ISO/IEC standard}], Old=[@Defn{ISO/IEC 9899:1990} @Defn{9899:1990, ISO/IEC standard}]} @Defn{C standard} ISO/IEC 9899:@Chg{Version=[2],New=[1999],Old=[1990]}, @i{Programming languages @em C}@Chg{Version=[2],New=[, supplemented by Technical Corrigendum 1:2001 and Technical Corrigendum 2:2004],Old=[]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike Fortran and COBOL, which added the @i{Information technology} prefix to the titles of their standard, C did not. This was confirmed in the list of standards titles on the ISO web site. No idea why ISO allowed that@Comment{, or whether C is planning to secede from SC22}.]} @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0001],ARef=[AI95-00124-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{ISO/IEC 10646:2003} @Defn{10646:2003, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(16 and 32-bit)} ISO/IEC 10646:2003, @i{Information technology @em Universal Multiple-Octet Coded Character Set (UCS)}.], Old=[@Defn{ISO/IEC 10646-1:1993} @Defn{10646-1:1993, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(16-bit)} ISO/IEC 10646-1:1993, @i{Information technology @em Universal Multiple-Octet Coded Character Set (UCS) @em Part 1: Architecture and Basic Multilingual Plane}@Chg{Version=[1],New=[, supplemented by Technical Corrigendum 1:1996], Old=[]}.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0001],ARef=[AI95-00124-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00285-01]} @ChgNote{This is of only historical interest, so it was deleted; we use the Unicode characterization now.} @ChgDeleted{Version=[2],Text=[ @Chg{Version=[1],New=[The Technical Corrigendum 1:1996 is needed so that character codes C6 and E6 (the ligatures @latin1(198) and @latin1(230)) are considered letters. These were named Latin Ligature AE in the original 1993 version, which would exclude them from being letters as defined in @RefSec{Character Set}.], Old=[]}]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00376-01]} @ChgAdded{Version=[2],Text=[@Defn{ISO/IEC 14882:2003} @Defn{14882:2003, ISO/IEC standard} @Defn{C++ standard} ISO/IEC 14882:2003, @i{Programming languages @em C++}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This title is also missing the @i{Information technology} part. That was confirmed in the list of standards titles on the ISO web site.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{ISO/IEC TR 19769:2004} @Defn{19769:2004, ISO/IEC technical report} ISO/IEC TR 19769:2004, @i{Information technology @em Programming languages, their environments and system software interfaces @em Extensions for the programming language C to support new character data types}.]} @begin{Discussion} @Defn{POSIX} POSIX, @i{Portable Operating System Interface (POSIX) @em Part 1: System Application Program Interface (API) [C Language]}, The Institute of Electrical and Electronics Engineers, 1990. @end{Discussion} @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00376-01],ARef=[AI95-00415-01]} @ChgAdded{Version=[2],Text=[Updated references to the most recent versions of these standards. Added C++ and time standards. Added C character set technical report.]} @end{DiffWord95} @LabeledClause{Definitions} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Defn2{Term=[italics],Sec=(terms introduced or defined)} Terms are defined throughout this International Standard, indicated by @i(italic) type. Terms explicitly defined in this International Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. @Chg{Version=[2],New=[Mathematical terms not defined in this International Standard are to be interpreted according to the @i<CRC Concise Encyclopedia of Mathematics, Second Edition>. Other terms],Old=[Terms]} not defined in this International Standard are to be interpreted according to the @i(Webster's Third New International Dictionary of the English Language). Informal descriptions of some terms are also given in @RefSec{Glossary}. @Comment{These are here to avoid a blank paragraph at the end, and because they have to be somewhere.} @SeeAlso{Primary=[library unit], Other=(language-defined library units)} @SeeOther{Primary=[predefined library unit], Other=(language-defined library units)} @SeeAlso{Primary=[type], Other=(language-defined types)} @SeeOther{Primary=[predefined type], Other=(language-defined types)} @begin{Discussion} The index contains an entry for every defined term. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00415-01]} @ChgAdded{Version=[2],Text=[The contents of the @i<CRC Concise Encyclopedia of Mathematics, Second Edition> can be accessed on @URLLink{URL=[http://www.mathworld.com],Text=[http://www.mathworld.com]}. The ISBN number of the book is ISBN 1584883472.]} @end{Discussion} @begin{GlossaryMarker} Each term defined in @RefSecNum{Glossary} is marked like this. @end{GlossaryMarker} @end{Intro} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[2],Kind=[Revised]} Here are some AARM-only definitions: @Defn{Ada Rapporteur Group (ARG)} @Defn(ARG) The Ada Rapporteur Group (ARG) interprets the @Chg{Version=[1],New=<Ada Reference Manual>,Old=<RM83>}. @Defn{Ada Issue (AI)} @Defn(AI) An Ada Issue (AI) is a numbered ruling from the ARG.@Chg{Version=[1],New=< Ada Issues created for Ada 83 are denoted as "AI83", while Ada Issues created for Ada 95 are denoted as "AI95" in this document.>,Old=<>} @Defn{Ada Commentary Integration Document (ACID)} @Defn(ACID) The Ada Commentary Integration Document (ACID) is an edition of @Chg{Version=[2],New=[the Ada 83 RM],Old=[RM83]} in which clearly marked insertions and deletions indicate the effect of integrating the approved AIs. @Defn{Uniformity Rapporteur Group (URG)} @Defn(URG) The Uniformity Rapporteur Group (URG) @Chg{Version=[1],New=<issued>,Old=<issues>} recommendations intended to increase uniformity across Ada implementations. @Chg{Version=[1],New=<The functions of the URG have been assumed by the ARG.>,Old=<>} @Defn{Uniformity Issue (UI)} @Defn(UI) A Uniformity Issue (UI) @Chg{Version=[1],New=<was>,Old=<is>} a numbered recommendation from the URG. @Chg{Version=[1],New=<A Defect Report and Response is an official query to WG9 about an error in the standard. Defect Reports are processed by the ARG, and are referenced here by their ISO numbers: 8652/nnnn. Most changes to the Ada 95 standard include reference(s) to the Defect Report(s) that prompted the change.>,Old=<>} @Chg{Version=[1],New=[@PDefn2{Term=[ACVC],Sec=(Ada Compiler Validation Capability)} @PDefn2{Term=[Ada Compiler Validation Capability],Sec=(ACVC)} @PDefn2{Term=[ACATS],Sec=(Ada Conformity Assessment Test Suite)} @PDefn2{Term=[Ada Conformity Assessment Test Suite],Sec=(ACATS)} The @i<Ada Conformity Assessment Test Suite (ACATS)> is a set of tests intended to check the conformity of Ada implementations to this standard. This set of tests was previously known as the Ada Compiler Validation Capability (ACVC).],Old=[]} @end{Discussion} �������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/02.mss���������������������������������������������������������������0000755�0001752�0001001�00000212602�12273462240�016371� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(02, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:23 $} @LabeledSection{Lexical Elements} @Comment{$Source: e:\\cvsroot/ARM/Source/02.mss,v $} @Comment{$Revision: 1.60 $} @begin{Intro} @redundant[The text of a program consists of the texts of one or more @nt<compilation>s. The text of a @nt<compilation> is a sequence of lexical elements, each composed of characters; the rules of composition are given in this section. @nt{Pragma}s, which provide certain information for the compiler, are also described in this section.] @end{Intro} @LabeledClause{Character Set} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Defn{character set} The @Chg{Version=[2],New=[character repertoire for the text of an Ada program consists of the entire coding space described by the ISO/IEC 10646:2003 Universal Multiple-Octet Coded Character Set. This coding space is organized in @i<planes>, each plane comprising 65536 characters.@Defn2{Term=[plane],Sec=[character]} @Defn{character plane}],Old=[only characters allowed outside of @nt{comment}s are the @nt{graphic_character}s and @ntf{format_effector}s.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[Any character, including an @ntf<other_control_function>, is allowed in a comment.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]}@ChgNote{Moved below} @ChgDeleted{Version=[2],Text=[Note that this rule doesn't really have much force, since the implementation can represent characters in the source in any way it sees fit. For example, an implementation could simply define that what seems to be a non-graphic, non-format-effector character is actually a representation of the space character.]} @end{Ramification} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} It is our intent to follow the terminology of @Chg{Version=[2],New=[ISO/IEC 10646:2003],Old=[ISO 10646 BMP]} where appropriate, and to remain compatible with the character classifications defined in @RefSec{Character Handling}.@Chg{Version=[2], New=[],Old=[Note that our definition for @nt<graphic_character> is more inclusive than that of ISO 10646-1.]} @end(Discussion) @end{Intro} @begin{Syntax} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 and 3 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<character>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Syn2{graphic_character} | @Synf{format_effector} | @Synf{other_control_function}>}"} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<graphic_character>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Synf{identifier_letter} | @Synf{digit} | @Synf{space_character} | @Synf{special_character}>}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[A @ntf{character} is defined by this International Standard for each cell in the coding space described by ISO/IEC 10646:2003, regardless of whether or not ISO/IEC 10646:2003 allocates a character to that cell.]} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} The@Chg{Version=[2],New=[],Old=[ character repertoire for the text of an Ada program consists of the collection of characters @Chg{Version=[2],New=[described by the ISO/IEC 10646:2003], Old=[called the Basic Multilingual Plane (BMP) of the ISO 10646]} Universal Multiple-Octet Coded Character Set, plus a set of @ntf<format_effector>s and, in comments only, a set of @ntf<other_control_function>s; the]} coded representation for @Chg{Version=[2],New=[],Old=[these ]}characters is implementation defined @Redundant[(it need not be a representation defined within @Chg{Version=[2],New=[ISO/IEC 10646:2003], Old=[ISO-10646-1]})].@Chg{Version=[2],New=[ A character whose relative code position in its plane is 16#FFFE# or 16#FFFF# is not allowed anywhere in the text of a program.],Old=[]} @ImplDef{The coded representation for the text of an Ada program.} @begin{Ramification}@ChgNote{Moved from above} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Note that this rule doesn't really have much force, since the implementation can represent characters in the source in any way it sees fit. For example, an implementation could simply define that what seems to be an @ntf{other_private_use} character is actually a representation of the space character.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The semantics of an Ada program whose text is not in Normalization Form KC (as defined by section 24 of ISO/IEC 10646:2003) is implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The semantics of an Ada program whose text is not in Normalization Form KC.]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The description of the language definition in this International Standard uses the @Chg{Version=[2], New=[character properties General Category, Simple Uppercase Mapping, Uppercase Mapping, and Special Case Condition of the documents referenced by the note in section 1 of ISO/IEC 10646:2003],Old=[graphic symbols defined for Row 00: Basic Latin and Row 00: Latin-1 Supplement of the ISO 10646 BMP; these correspond to the graphic symbols of ISO 8859-1 (Latin-1); no graphic symbols are used in this International Standard for characters outside of Row 00 of the BMP]}. The actual set of graphic symbols used by an implementation for the visual representation of the text of an Ada program is not specified. @PDefn{unspecified} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@keepnext@;@Chg{Version=[2],New=[Characters],Old=[The categories of characters]} are @Chg{Version=[2],New=[categorized],Old=[defined]} as follows: @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Our character classification considers that the cells not allocated in ISO/IEC 10646:2003 are graphic characters, except for those whose relative code position in their plane is 16#FFFE# or 16#FFFF#. This seems to provide the best compatibility with future versions of ISO/IEC 10646, as future characters can be already be used in Ada character and string literals.]} @end{Discussion} @begin{Description} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{identifier_letter}@ntf<identifier_letter>@\@ntf{upper_case_identifier_letter} | @ntf{lower_case_identifier_letter}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[We use @ntf<identifier_letter> instead of simply @ntf<letter> because ISO 10646 BMP includes many other characters that would generally be considered "letters."]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{letter_uppercase}@ntf{letter_uppercase}], Old=[@Defn{upper_case_identifier_letter}@ntf<upper_case_identifier_letter>]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Letter, Uppercase@rquotes@;], Old=[of Row 00 of ISO 10646 BMP whose name begins @lquotes@;Latin Capital Letter@rquotes@;]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{letter_lowercase}@ntf{letter_lowercase}], Old=[@Defn{lower_case_identifier_letter}@ntf<lower_case_identifier_letter>]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Letter, Lowercase@rquotes@;], Old=[of Row 00 of ISO 10646 BMP whose name begins @lquotes@;Latin Small Letter@rquotes@;]}. @begin{Honest} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0001],ARef=[AI95-00124-01]} @Comment{The change in clause 1.3 for 8652/0001 handles this problem.} @ChgDeleted{Version=[1],Text=[The above rules do not include the ligatures @latin1(198) and @latin1(230). However, the intent is to include these characters as identifier letters. This problem was pointed out by a comment from the Netherlands.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_titlecase}@ntf{letter_titlecase}@\Any character whose General Category is defined to be @lquotes@;Letter, Titlecase@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_modifier}@ntf{letter_modifier}@\Any character whose General Category is defined to be @lquotes@;Letter, Modifier@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_other}@ntf{letter_other}@\Any character whose General Category is defined to be @lquotes@;Letter, Other@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{mark_non_spacing}@ntf{mark_non_spacing}@\Any character whose General Category is defined to be @lquotes@;Mark, Non-Spacing@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{mark_non_spacing}@ntf{mark_spacing_combining}@\Any character whose General Category is defined to be @lquotes@;Mark, Spacing Combining@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{number_decimal}@ntf{number_decimal}], Old=[@Defn{digit}@nt{digit}]}@\@Chg{Version=[2],New=[Any character whose General Category is defined to be @lquotes@;Number, Decimal@rquotes@;], Old=[One of the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{number_letter}@ntf{number_letter}@\Any character whose General Category is defined to be @lquotes@;Number, Letter@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{punctuation_connector}@ntf{punctuation_connector}@\Any character whose General Category is defined to be @lquotes@;Punctuation, Connector@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_format}@ntf{other_format}@\Any character whose General Category is defined to be @lquotes@;Other, Format@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{separator_space}@ntf<separator_space>], Old=[@Defn{space_character}@ntf{space_character}]}@\@Chg{Version=[2],New=[Any character whose General Category is defined to be @lquotes@;Separator, Space@rquotes@;.],Old=[The character of ISO 10646 BMP named @lquotes@;Space@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{separator_line}@ntf{separator_line}], Old=[@Defn{special_character}@ntf{special_character}]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Separator, Line@rquotes@;.], Old=[of the ISO 10646 BMP that is not reserved for a control function, and is not the @ntf<space_character>, an @ntf<identifier_letter>, or a @ntf<digit>.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that the no break space and soft hyphen are @ntf<special_character>s, and therefore @nt<graphic_character>s. They are not the same characters as space and hyphen-minus.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{separator_paragraph}@ntf{separator_paragraph}@\Any character whose General Category is defined to be @lquotes@;Separator, Paragraph@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn{format_effector}@ntf<format_effector>@\The @Chg{Version=[2],New=[characters whose code positions are 16#09# (CHARACTER TABULATION), 16#0A# (LINE FEED), 16#0B# (LINE TABULATION), 16#0C# (FORM FEED), 16#0D# (CARRIAGE RETURN), 16#85# (NEXT LINE), and the characters in categories @ntf{separator_line} and @ntf{separator_paragraph}], Old=[control functions of ISO 6429 called character tabulation (HT), line tabulation (VT), carriage return (CR), line feed (LF), and form feed (FF)]}. @IndexSeeAlso{Term=[control character],See=(format_effector)} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC 10646:2003 does not define the names of control characters, but rather refers to the names defined by ISO/IEC 6429:1992. These are the names that we use here.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_control}@ntf{other_control}@\Any character whose General Category is defined to be @lquotes@;Other, Control@rquotes@;, and which is not defined to be a @ntf<format_effector>.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_private_use}@ntf{other_private_use}@\Any character whose General Category is defined to be @lquotes@;Other, Private Use@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_surrogate}@ntf{other_surrogate}@\Any character whose General Category is defined to be @lquotes@;Other, Surrogate@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Chg{Version=[2],New=[@Defn{graphic_character}@ntf{graphic_character}], Old=[@Defn{other_control_function}@ntf<other_control_function>]}@\@Chg{Version=[2], New=[Any character that is not in the categories @ntf{other_control}, @ntf{other_private_use}, @ntf{other_surrogate}, @ntf{format_effector}, and whose relative code position in its plane is neither 16#FFFE# nor 16#FFFF#.], Old=[Any control function, other than a @ntf<format_effector>, that is allowed in a comment; the set of @ntf<other_control_function>s allowed in comments is implementation defined. @IndexSeeAlso{Term=[control character],See=(other_control_function)}]} @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2],Text=[The control functions allowed in comments.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=`We considered basing the definition of lexical elements on Annex A of ISO/IEC TR 10176 (4th edition), which lists the characters which should be supported in identifiers for all programming languages, but we finally decided against this option. Note that it is not our intent to diverge from ISO/IEC TR 10176, except to the extent that ISO/IEC TR 10176 itself diverges from ISO/IEC 10646:2003 (which is the case at the time of this writing [January 2005]).'} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[More precisely, we intend to align strictly with ISO/IEC 10646:2003. It must be noted that ISO/IEC TR 10176 is a Technical Report while ISO/IEC 10646:2003 is a Standard. If one has to make a choice, one should conform with the Standard rather than with the Technical Report. And, it turns out that one @i<must> make a choice because there are important differences between the two:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC TR 10176 is still based on ISO/IEC 10646:2000 while ISO/IEC 10646:2003 has already been published for a year. We cannot afford to delay the adoption of our amendment until ISO/IEC TR 10176 has been revised.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are considerable differences between the two editions of ISO/IEC 10646, notably in supporting characters beyond the BMP (this might be significant for some languages, e.g. Korean).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC TR 10176 does not define case conversion tables, which are essential for a case-insensitive language like Ada. To get case conversion tables, we would have to reference either ISO/IEC 10646:2003 or Unicode, or we would have to invent our own.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For the purpose of defining the lexical elements of the language, we need character properties like categorization, as well as case conversion tables. These are mentioned in ISO/IEC 10646:2003 as useful for implementations, with a reference to Unicode. Machine-readable tables are available on the web at URLs:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@URLLink{URL=[http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt], Text=[http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt]} @URLLink{URL=[http://www.unicode.org/Public/4.0-Update/CaseFolding-4.0.0.txt], Text=[http://www.unicode.org/Public/4.0-Update/CaseFolding-4.0.0.txt]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[with an explanatory document found at URL:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@URLLink{URL=[http://www.unicode.org/Public/4.0-Update/UCD-4.0.0.html], Text=[http://www.unicode.org/Public/4.0-Update/UCD-4.0.0.html]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual text of the standard only makes specific references to the corresponding clauses of ISO/IEC 10646:2003, not to Unicode.]} @end{Discussion} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@Chg{Version=[2],New=[],Old=[@Defn{names of @ntf{special_character}s} @Defn2{Term=[special_character],Sec=(names)}]}The following names are used when referring to certain @Chg{Version=[2],New=[characters (the first name is that given in ISO/IEC 10646:2003)],Old=[@ntf{special_character}s]}: @Defn{quotation mark} @Defn{number sign} @Defn{ampersand} @Defn{apostrophe} @Defn{tick} @Defn{left parenthesis} @Defn{right parenthesis} @Defn{asterisk} @Defn{multiply} @Defn{plus sign} @Defn{comma} @Defn{hyphen-minus} @Defn{minus} @Defn{full stop} @Defn{dot} @Defn{point} @Defn{solidus} @Defn{divide} @Defn{colon} @Defn{semicolon} @Defn{less-than sign} @Defn{equals sign} @Defn{greater-than sign} @Defn{low line} @Defn{underline} @Defn{vertical line} @Chg{Version=[2],New=[@Defn{exclamation point} @Defn{percent sign}], Old=[@Defn{left square bracket} @Defn{right square bracket} @Defn{left curly bracket} @Defn{right curly bracket}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{graphic symbols}@Defn{glyphs}This table serves to show the correspondence between ISO/IEC 10646:2003 names and the graphic symbols (glyphs) used in this International Standard. These are the characters], Old=[These are the ones]} that play a special role in the syntax of Ada@Chg{Version=[2],New=[], Old=[ 95, or in the syntax rules; we don't bother to define names for all characters. The first name given is the name from ISO 10646-1; the subsequent names, if any, are those used within the standard, depending on context]}. @end{Discussion} @Comment{The original version follows here (commented out) @begin{Display} @TabClear()@TabSet(P9) @begin(TwoCol) @NoParanum@;symbol @\name @NoParanum@; " @\quotation mark # @\number sign & @\ampersand ' @\apostrophe, tick ( @\left parenthesis ) @\right parenthesis * @\asterisk, multiply + @\plus sign , @\comma @en@; @\hyphen-minus, minus . @\full stop, dot, point / @\solidus, divide @NewColumn @NoParanum@;symbol @\name @NoParanum@; : @\colon ; @\semicolon < @\less-than sign = @\equals sign > @\greater-than sign _ @\low line, underline | @\vertical line [ @\left square bracket ] @\right square bracket { @\left curly bracket } @\right curly bracket @end(TwoCol) @end{Display}} @Comment{We use this (weird) four column version to make the HTML look much better. WARNING: The items that go together are in separate columns!!} @begin(FourCol) @NoParanum@;@ @ @Chg{Version=[2],New=[graphic ],Old=[@ @ @ @ ]}symbol @NoParanum@;@ @ @ @ @ @ @ @ @ "@* @ @ @ @ @ @ @ @ @ #@* @ @ @ @ @ @ @ @ @ &@* @ @ @ @ @ @ @ @ @ '@* @ @ @ @ @ @ @ @ @ (@* @ @ @ @ @ @ @ @ @ )@* @ @ @ @ @ @ @ @ @ *@* @ @ @ @ @ @ @ @ @ +@* @ @ @ @ @ @ @ @ @ ,@* @ @ @ @ @ @ @ @ @ @en@;@* @ @ @ @ @ @ @ @ @ .@Chg{Version=[2],New=[],Old=[@*]}@Chg{Version=[2],New=[],Old=[@ @ @ @ @ @ @ @ @ /]}@ChgNote{Funny layout so HTML and RTF look right} @NewColumn @NoParanum@;name @NoParanum@;quotation mark@* number sign@* ampersand@* apostrophe, tick@* left parenthesis@* right parenthesis@* asterisk, multiply@* plus sign@* comma@* hyphen-minus, minus@* full stop, dot, point@Chg{Version=[2],New=[],Old=[@*]}@Chg{Version=[2],New=[],Old=[solidus, divide]}@ChgNote{Funny layout so HTML and RTF look right} @NewColumn @NoParanum@;@ @ @Chg{Version=[2],New=[graphic ],Old=[@ @ @ @ ]}symbol @NoParanum@;@ @ @ @ @ @ @ @ @ :@* @ @ @ @ @ @ @ @ @ ;@* @ @ @ @ @ @ @ @ @ <@* @ @ @ @ @ @ @ @ @ =@* @ @ @ @ @ @ @ @ @ >@* @ @ @ @ @ @ @ @ @ _@* @ @ @ @ @ @ @ @ @ |@* @ @ @ @ @ @ @ @ @ @Chg{Version=[2],New=[/],Old=<[>}@* @ @ @ @ @ @ @ @ @ @Chg{Version=[2],New=[!],Old=<]>}@* @ @ @ @ @ @ @ @ @ @Chg<Version=[2],New=[%],Old=<{>>@* @Chg<Version=[2],New=[],Old=<@ @ @ @ @ @ @ @ @ }>> @NewColumn @NoParanum@;name @NoParanum@;colon@* semicolon@* less-than sign@* equals sign@* greater-than sign@* low line, underline@* vertical line@* @Chg{Version=[2],New=[solidus, divide],Old=[left square bracket]}@* @Chg{Version=[2],New=[exclamation point],Old=[right square bracket]}@* @Chg{Version=[2],New=[percent sign],Old=[left curly bracket]}@* @Chg{Version=[2],New=[],Old=[right curly bracket]} @end(FourCol) @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[In a nonstandard mode, the implementation may support a different character repertoire@Redundant[; in particular, the set of characters that are considered @ntf<identifier_letter>s can be extended or changed to conform to local conventions].]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If an implementation supports other character sets, it defines which characters fall into each category, such as @lquotes@;@ntf{identifier_letter},@rquotes@; and what the corresponding rules of this section are, such as which characters are allowed in the text of a program.]} @end{Ramification} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[The characters in categories @ntf{other_control}, @ntf{other_private_use}, and @ntf{other_surrogate} are only allowed in comments], Old=[Every code position of ISO 10646 BMP that is not reserved for a control function is defined to be a @nt<graphic_character> by this International Standard. This includes all code positions other than 0000 - 001F, 007F - 009F, and FFFE - FFFF]}. The language does not specify the source representation of programs. @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised]} Any source representation is valid so long as the implementer can produce an (information-preserving) algorithm for translating both directions between the representation and the standard character set. (For example, every character in the standard character set has to be representable, even if the output devices attached to a given computer cannot print all of those characters properly.) From a practical point of view, every implementer will have to provide some way to process the @Chg{Version=[2],New=[ACATS],Old=[ACVC]}. It is the intent to allow source representations, such as parse trees, that are not even linear sequences of characters. It is also the intent to allow different fonts: reserved words might be in bold face, and that should be irrelevant to the semantics. @end(Discussion) @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Ada 95 allows 8-bit and 16-bit characters, as well as implementation-specified character sets. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The syntax rules in this clause are modified to remove the emphasis on basic characters vs. others. (In this day and age, there is no need to point out that you can write programs without using (for example) lower case letters.) In particular, @ntf{character} (representing all characters usable outside comments) is added, and @ntf{basic_graphic_character}, @ntf{other_special_character}, and @ntf{basic_character} are removed. @ntf{Special_character} is expanded to include Ada 83's @ntf{other_special_character}, as well as new 8-bit characters not present in Ada 83.@Chg{Version=[2],New=[ Ada 2005 removes @ntf{special_character} altogether; we want to stick to ISO/IEC 10646:2003 character classifications.],Old=[]} Note that the term @lquotes@;basic letter@rquotes@; is used in @RefSec{Character Handling} to refer to letters without diacritical marks. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Character names now come from @Chg{Version=[2],New=[ISO/IEC 10646:2003],Old=[ISO 10646]}. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[We use @ntf<identifier_letter> rather than @ntf<letter> since ISO 10646 BMP includes many "letters' that are not permitted in identifiers (in the standard mode).]} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Program text can use most characters defined by ISO-10646:2003. This clause has been rewritten to use the categories defined in that Standard. This should ease programming in languages other than English.]} @end{Extend95} @LabeledClause{Lexical Elements, Separators, and Delimiters} @begin{StaticSem} @Defn{text of a program} The text of a program consists of the texts of one or more @nt<compilation>s. @Defn{lexical element} @IndexSee{Term=[token],See=(lexical element)} The text of each @nt<compilation> is a sequence of separate @i(lexical elements). Each lexical element is formed from a sequence of characters, and is either a delimiter, an @nt<identifier>, a reserved word, a @nt<numeric_literal>, a @nt<character_literal>, a @nt<string_literal>, or a comment. The meaning of a program depends only on the particular sequences of lexical elements that form its @nt{compilation}s, excluding @nt{comment}s. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The text of a @nt<compilation> is divided into @Defn{line}@i{lines}. @Defn{end of a line} In general, the representation for an end of line is implementation defined. However, a sequence of one or more @ntf<format_effector>s other than @Chg{Version=[2],New=[the character whose code position is 16#09# (CHARACTER TABULATION)],Old=[character tabulation (HT)]} signifies at least one end of line. @ImplDef{The representation for an end of line.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@Defn{separator} @Redundant[In some cases an explicit @i(separator) is required to separate adjacent lexical elements.] A separator is any of a @Chg{Version=[2],New=[@ntf{separator_space}],Old=[space character]}, a @Chg{Version=[2],New=[@ntf{format_effector}],Old=[format effector]}, or the end of a line, as follows: @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[It might be useful to define @lquotes@;white space@rquotes@; and use it here.]}@ChgNote{No one can figure out why, and it wouldn't match the Unicode def of whitespace.} @end(Discussion) @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} A @Chg{Version=[2],New=[@ntf{separator_space}],Old=[space character]} is a separator except within a @nt{comment}, a @nt{string_literal}, or a @nt{character_literal}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[The character whose code position is 16#09# (CHARACTER TABULATION)],Old=[Character tabulation (HT)]} is a separator except within a @nt{comment}. The end of a line is always a separator. @end{Itemize} One or more separators are allowed between any two adjacent lexical elements, before the first of each @nt{compilation}, or after the last. At least one separator is required between an @nt{identifier}, a reserved word, or a @nt{numeric_literal} and an adjacent @nt{identifier}, reserved word, or @nt{numeric_literal}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn{delimiter} A @i{delimiter} is either one of the following@Chg{Version=[2],New=[],Old=[ special]} characters@Chg{Version=[2],New=[:],Old=[]} @begin{Display} &@ @ @ @ '@ @ @ @ (@ @ @ @ )@ @ @ @ *@ @ @ @ +@ @ @ @ ,@ @ @ @ @en@ @ @ @ .@ @ @ @ /@ @ @ @ :@ @ @ @ ;@ @ @ @ <@ @ @ @ =@ @ @ @ >@ @ @ @ | @end{Display} @Defn{compound delimiter} or one of the following @i{compound delimiters} each composed of two adjacent special characters @begin{Display} =>@ @ @ @ ..@ @ @ @ **@ @ @ @ :=@ @ @ @ /=@ @ @ @ >=@ @ @ @ <=@ @ @ @ <<@ @ @ @ >>@ @ @ @ <> @end{Display} Each of the special characters listed for single character delimiters is a single delimiter except if this character is used as a character of a compound delimiter, or as a character of a @nt{comment}, @nt{string_literal}, @nt{character_literal}, or @nt{numeric_literal}. @rmnewpage@ChgNote{Ada 2005 only} @Leading@keepnext@;The following names are used when referring to compound delimiters:@table{Columns=[2], Alignment=[Allleft],FirstColWidth=[1],LastColWidth=[4], NoBreak=[F],Border=[F],SmallSize=[F],Caption=[], Headers=[delimiter@ @\name], Body=[=>@\arrow ..@\double dot **@\double star, exponentiate :=@\assignment (pronounced: @lquotes@;becomes@rquotes@;) /=@\inequality (pronounced: @lquotes@;not equal@rquotes@;) >=@\greater than or equal <=@\less than or equal <<@\left label bracket >>@\right label bracket <>@\box]} @end{StaticSem} @begin{ImplReq} An implementation shall support lines of at least 200 characters in length, not counting any characters used to signify the end of a line. An implementation shall support lexical elements of at least 200 characters in length. The maximum supported line length and lexical element length are implementation defined. @ImplDef{Maximum supported line length and lexical element length.} @begin{Discussion} From URG recommendation. @end{Discussion} @end{ImplReq} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The wording was updated to use the new character categories defined in the preceding clause.]} @end{Diffword95} @LabeledClause{Identifiers} @begin{Intro} @nt<Identifier>s are used as names. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Syn{lhs=<identifier>,rhs=" @Chg{Version=[2],New=<@Syn2{identifier_start} {@Syn2{identifier_start} | @Syn2{identifier_extend}}>, Old=<@Synf{identifier_letter} {[@Synf{underline}] @Syn2{letter_or_digit}}>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Syn{lhs=<@Chg{Version=[2],New=<identifier_start>,Old=<letter_or_digit>}>, rhs="@Chg{Version=[2],New=< @Synf{letter_uppercase} | @Synf{letter_lowercase} | @Synf{letter_titlecase} | @Synf{letter_modifier} | @Synf{letter_other} | @Synf{number_letter}>,Old=<@Synf{identifier_letter} | @Synf{digit}>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<identifier_extend>,Old=<>}>, rhs="@Chg{Version=[2],New=< @Synf{mark_non_spacing} | @Synf{mark_spacing_combining} | @Synf{number_decimal} | @Synf{punctuation_connector} | @Synf{other_format}>,Old=<>}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00395-01]} @Chg{Version=[2],New=[After eliminating the characters in category @ntf{other_format}, an @nt{identifier} shall not contain two consecutive characters in category punctuation_connector, or end with a character in that category.],Old=[An @nt{identifier} shall not be a reserved word.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule was stated in the syntax in Ada 95, but that has gotten too complex in Ada 2005. Since @ntf{other_format} characters usually do not display, we do not want to count them as separating two underscores.]} @end{Reason} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Two @nt{identifier}s are ]}@Chg{Version=[2], New=[considered the same if they consist of the same sequence of characters after applying the following transformations (in this order):],Old=[All characters of an @nt{identifier} are significant, including any underline character. @Defn{case insensitive} @nt{Identifier}s differing only in the use of corresponding upper and lower case letters are considered the same.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The characters in category @ntf{other_format} are eliminated.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The remaining sequence of characters is converted to upper case. @Defn{case insensitive}]} @end{Itemize} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Two of the letters of ISO 8859-1 appear only as lower case, "sharp s" and "y with diaeresis." These two letters have no corresponding upper case letter (in particular, they are not considered equivalent to one another).]} @end(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[After applying these transformations, an @nt{identifier} shall not be identical to a reserved word (in upper case).]} @begin(ImplNote) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We match the reserved words after doing these transformations so that the rules for @nt{identifier}s and reserved words are the same. (This allows @ntf{other_format} characters, which usually don't display, in a reserved word without changing it to an @nt{identifier}.) Since a compiler usually will lexically process @nt{identifier}s and reserved words the same way (often with the same code), this will prevent a lot of headaches.]} @end(ImplNote) @begin(Ramification) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rules for reserved words differ in one way: they define case conversion on letters rather than sequences. This means that some unusual sequences are neither @nt{identifier}s nor reserved words. For instance, @lquotes@;@smldotlessi@;f@rquotes@; and @lquotes@;acce@latin1(223)@rquotes@; have upper case conversions of @lquotes@;IF@rquotes@; and @lquotes@;ACCESS@rquotes@; respectively. These are not @nt{identifier}s, because the transformed values are identical to a reserved word. But they are not reserved words, either, because the original values do not match any reserved word as defined or with any number of characters of the reserved word in upper case. Thus, these odd constructions are just illegal, and should not appear in the source of a program.]} @end(Ramification) @end{StaticSem} @begin{ImplPerm} In a nonstandard mode, an implementation may support other upper/lower case equivalence rules for @nt<identifier>s@Redundant[, to accommodate local conventions]. @end{ImplPerm} @begin(Discussion) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For instance, in most languages, the uppercase equivalent of LATIN SMALL LETTER I (a lower case letter with a dot above) is LATIN CAPITAL LETTER I (an upper case letter without a dot above). In Turkish, though, LATIN SMALL LETTER I and LATIN SMALL LETTER DOTLESS I are two distinct letters, so the upper case equivalent of LATIN SMALL LETTER I is LATIN CAPITAL LETTER I WITH DOT ABOVE, and the upper case equivalent of LATIN SMALL LETTER DOTLESS I is LATIN CAPITAL LETTER I. Take for instance the following identifier (which is the name of a city on the Tigris river in Eastern Anatolia):]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[diyarbak@smldotlessi@;r -- @RI[The first i is dotted, the second isn't.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Locale-independent conversion to upper case results in:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[DIYARBAKIR -- @RI[Both Is are dotless.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This means that the four following sequences of characters represent the same identifier, even though for a locutor of Turkish they would probably be considered distinct words:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[diyarbakir diyarbak@smldotlessi@;r d@smldotlessi@;yarbakir d@smldotlessi@;yarbak@smldotlessi@;r]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[An implementation targeting the Turkish market is allowed (in fact, expected) to provide a nonstandard mode where case folding is appropriate for Turkish. This would cause the original identifier to be converted to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[D@capdottedi@;YARBAKIR -- @RI[The first I is dotted, the second isn't.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[and the four sequences of characters shown above would represent four distinct identifiers.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Lithuanian and Azeri are two other languages that present similar idiosyncrasies.]} @end{Discussion} @begin{Notes} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@nt{Identifier}s differing only in the use of corresponding upper and lower case letters are considered the same.]} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of identifiers:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote{Old version:@begin{Display} Count X Get_Symbol Ethelyn Marion @Comment{Blank line} Snobol_4 X1 Page_Count Store_Next_Item @end{Display}} @begin{Example} Count X Get_Symbol Ethelyn Marion Snobol_4 X1 Page_Count Store_Next_Item@Chg{Version=[2],New=[ @unicode(928)@unicode(955)@unicode(940)@unicode(964)@unicode(969)@unicode(957) --@RI[ Plato] @unicode(1063)@unicode(1072)@unicode(1081)@unicode(1082)@unicode(1086)@unicode(1074)@unicode(1089)@unicode(1082)@unicode(1080)@unicode(1081) --@RI[ Tchaikovsky] @unicode(952) @unicode(966) --@RI[ Angles]],Old=[]} @end{Example} @end{Examples} @begin{DiffWord83} We no longer include reserved words as @nt<identifier>s. This is not a language change. In Ada 83, @nt{identifier} included reserved words. However, this complicated several other rules (for example, regarding implementation-defined attributes and pragmas, etc.). We now explicitly allow certain reserved words for attribute designators, to make up for the loss. @begin{Ramification} Because syntax rules are relevant to overload resolution, it means that if it looks like a reserved word, it is not an @nt<identifier>. As a side effect, implementations cannot use reserved words as implementation-defined attributes or pragma names. @end{Ramification} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{identifier} can use any letter defined by ISO-10646:2003, along with several other categories. This should ease programming in languages other than English.]} @end{Extend95} @LabeledClause{Numeric Literals} @begin{Intro} @Defn2{Term=[literal], Sec=(numeric)} There are two kinds of @nt<numeric_literal>s, @i(real literals) and @i(integer literals). @Defn{real literal} A real literal is a @nt{numeric_literal} that includes a point; @Defn{integer literal} an integer literal is a @nt{numeric_literal} without a point. @end{Intro} @begin{Syntax} @Syn{lhs=<numeric_literal>,rhs="@Syn2{decimal_literal} | @Syn2{based_literal}"} @end{Syntax} @begin{Notes} The type of an integer literal is @i{universal_integer}. The type of a real literal is @i{universal_real}. @end{Notes} @LabeledSubClause{Decimal Literals} @begin{Intro} @Defn2{Term=[literal], Sec=(decimal)} A @nt<decimal_literal> is a @nt<numeric_literal> in the conventional decimal notation (that is, the base is ten). @end{Intro} @begin{Syntax} @Syn{lhs=<decimal_literal>,rhs="@Syn2{numeral} [.@Syn2{numeral}] [@Syn2{exponent}]"} @Syn{lhs=<numeral>,rhs="@Syn2{digit} {[@Synf{underline}] @Syn2{digit}}"} @Syn{lhs=<exponent>,rhs="E [+] @Syn2{numeral} | E @en@; @Syn2{numeral}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<digit>,Old=<>}>, rhs="@Chg{Version=[2],New=<0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9>,Old=<>}"} @begin{SyntaxText} An @nt{exponent} for an integer literal shall not have a minus sign. @begin{Ramification} Although this rule is in this subclause, it applies also to the next subclause. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{StaticSem} An underline character in a @nt{numeric_literal} does not affect its meaning. The letter E of an @nt{exponent} can be written either in lower case or in upper case, with the same meaning. @begin{Ramification} Although these rules are in this subclause, they apply also to the next subclause. @end{Ramification} An @nt{exponent} indicates the power of ten by which the value of the @nt{decimal_literal} without the @nt{exponent} is to be multiplied to obtain the value of the @nt{decimal_literal} with the @nt{exponent}. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of decimal literals:} @ChgNote{ Old version: @begin{Display} @tabclear()@tabset(P31) 12 0 1E6 123_456 @\--@i{ integer literals} @Comment{Blank line} 12.0 0.0 0.456 3.14159_26 @\--@i{ real literals} @end{Display}} @begin{Example} 12 0 1E6 123_456 --@RI{ integer literals} @Comment{Blank line} 12.0 0.0 0.456 3.14159_26 --@RI{ real literals} @end{Example} @end{Examples} @begin{DiffWord83} We have changed the syntactic category name @ntf{integer} to be @nt{numeral}. We got this idea from ACID. It avoids the confusion between this and integers. (Other places don't offer similar confusions. For example, a @nt{string_literal} is different from a string.) @end{DiffWord83} @LabeledSubClause{Based Literals} @begin{Intro} @Redundant[ @Defn2{Term=[literal], Sec=(based)} @Defn{binary literal} @Defn{base 2 literal} @Defn2{Term=[binary], Sec=(literal)} @Defn{octal literal} @Defn{base 8 literal} @Defn2{Term=[octal], Sec=(literal)} @Defn{hexadecimal literal} @Defn{base 16 literal} @Defn2{Term=[hexadecimal], Sec=(literal)} A @nt<based_literal> is a @nt<numeric_literal> expressed in a form that specifies the base explicitly.] @end{Intro} @begin{Syntax} @Syn{lhs=<based_literal>,rhs=" @Syn2{base} # @Syn2{based_numeral} [.@Syn2{based_numeral}] # [@Syn2{exponent}]"} @Syn{lhs=<base>,rhs="@Syn2{numeral}"} @Syn{lhs=<based_numeral>,rhs=" @Syn2{extended_digit} {[@Synf{underline}] @Syn2{extended_digit}}"} @Syn{lhs=<extended_digit>,rhs="@Syn2{digit} | A | B | C | D | E | F"} @end{Syntax} @begin{Legality} @Defn{base} The @i(base) (the numeric value of the decimal @nt<numeral> preceding the first #) shall be at least two and at most sixteen. The @nt{extended_digit}s A through F represent the digits ten through fifteen, respectively. The value of each @nt{extended_digit} of a @nt{based_literal} shall be less than the base. @end{Legality} @begin{StaticSem} The conventional meaning of based notation is assumed. An @nt{exponent} indicates the power of the base by which the value of the @nt{based_literal} without the @nt{exponent} is to be multiplied to obtain the value of the @nt{based_literal} with the @nt{exponent}. The @nt{base} and the @nt{exponent}, if any, are in decimal notation. The @nt{extended_digit}s A through F can be written either in lower case or in upper case, with the same meaning. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of based literals:} @ChgNote{ Old version: @begin{Display} @tabclear()@tabset(P16, P45) 2#1111_1111# @\16#FF# 016#0ff# @\--@i{ integer literals of value 255} 16#E#E1 @\2#1110_0000# @\--@i{ integer literals of value 224} 16#F.FF#E+2 @\2#1.1111_1111_1110#E11 @\--@i{ real literals of value 4095.0} @end{Display}} @begin{Example} 2#1111_1111# 16#FF# 016#0ff# --@RI{ integer literals of value 255} 16#E#E1 2#1110_0000# --@RI{ integer literals of value 224} 16#F.FF#E+2 2#1.1111_1111_1110#E11 --@RI{ real literals of value 4095.0} @end{Example} @end{Examples} @begin{DiffWord83} The rule about which letters are allowed is now encoded in BNF, as suggested by Mike Woodger. This is clearly more readable. @end{DiffWord83} @LabeledClause{Character Literals} @begin{Intro} @Redundant[A @nt<character_literal> is formed by enclosing a graphic character between two apostrophe characters.] @end{Intro} @begin{Syntax} @Syn{lhs=<character_literal>,rhs="@SingleQuote@Synf{graphic_character}@SingleQuote"} @end{Syntax}@Comment{graphic_character is defined syntactically in Ada 95, but not in Ada 2007} @begin{Notes} A @nt{character_literal} is an enumeration literal of a character type. See @RefSecNum(Character Types). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of character literals:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote{ Orginal version: @begin{Display} 'A'@ @ @ @ @ '*'@ @ @ @ @ '''@ @ @ @ @ '@ ' @end{Display}} @begin{Example} 'A' '*' ''' ' '@Chg{Version=[2],New=[ 'L' '@Unicode(1051)' '@Unicode(923)' --@RI[ Various els.] '@Unicode(8734)' '@Unicode(1488)' --@RI[ Big numbers - infinity and aleph.]],Old=[]} @end{Example} @end{Examples} @begin{DiffWord83} The definitions of the values of literals are in Sections 3 and 4, rather than here, since it requires knowledge of types. @end{DiffWord83} @LabeledClause{String Literals} @begin{Intro} @redundant[A @nt<string_literal> is formed by a sequence of graphic characters (possibly none) enclosed between two quotation marks used as string brackets. They are used to represent @nt<operator_symbol>s (see @RefSecNum(Subprogram Declarations)), values of a string type (see @RefSecNum(Literals)), and array subaggregates (see @RefSecNum(Array Aggregates)). @IndexSee{Term=[quoted string],See=(string_literal)}] @end{Intro} @begin{Syntax} @Syn{lhs=<string_literal>,rhs=<"{@Syn2{string_element}}">} @Syn{lhs=<string_element>, rhs=<"" | @SynI{non_quotation_mark_}@Synf{graphic_character}>} @begin{SyntaxText} A @nt{string_element} is either a pair of quotation marks (""), or a single @ntf{graphic_character} other than a quotation mark. @end{SyntaxText} @end{Syntax} @begin{StaticSem} @Defn2{Term=[sequence of characters], Sec=(of a @nt<string_literal>)} The @i(sequence of characters) of a @nt<string_literal> is formed from the sequence of @nt<string_element>s between the bracketing quotation marks, in the given order, with a @nt<string_element> that is "" becoming a single quotation mark in the sequence of characters, and any other @nt<string_element> being reproduced in the sequence. @Defn{null string literal} A @i(null string literal) is a @nt<string_literal> with no @nt<string_element>s between the quotation marks. @end{StaticSem} @begin{Notes} An end of line cannot appear in a @nt{string_literal}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[No transformation is performed on the sequence of characters of a @nt{string_literal}.]} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of string literals:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote< Original version: @begin{Display} @tabclear()@tabset(P16) "Message of the day:" @comment{Blank line} "" @\--@i{ a null string literal} "@ " "A" """" @\--@i{ three string literals of length 1} @comment{Blank line} "Characters such as $, %, and } are allowed in string literals" @end{Display}> @begin{Example} "Message of the day:" @comment{Blank line} "" --@RI{ a null string literal} " " "A" """" --@RI{ three string literals of length 1} @comment{Blank line} "Characters such as $, %, and } are allowed in string literals" "Archimedes said ""@unicode(917)@unicode(973)@unicode(961)@unicode(951)@unicode(954)@unicode(945)""" "Volume of cylinder (@pi@;r@latin1(178)h) = " @end{Example} @end{Examples} @begin{DiffWord83} The wording has been changed to be strictly lexical. No mention is made of string or character values, since @nt<string_literal>s are also used to represent @nt<operator_symbol>s, which don't have a defined value. The syntax is described differently. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We explicitly say that the characters of a @nt{string_literal} should be used as is. In particular, no normalization or folding should be performed on a @nt{string_literal}.]} @end{DiffWord95} @LabeledClause{Comments} @begin{Intro} A @nt{comment} starts with two adjacent hyphens and extends up to the end of the line. @end{Intro} @begin{Syntax} @Syn{lhs=<comment>, rhs=<--{@SynI{non_end_of_line_}@Synf{character}}>}@Comment{character is defined syntactically in Ada 95, but not in Ada 2007. We assume the worst here.} @begin{SyntaxText} A @nt{comment} may appear on any line of a program. @end{SyntaxText} @end{Syntax} @begin{StaticSem} The presence or absence of @nt{comment}s has no influence on whether a program is legal or illegal. Furthermore, @nt{comment}s do not influence the meaning of a program; their sole purpose is the enlightenment of the human reader. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of comments:} @ChgNote{Original version: @begin{Display} --@i{ the last sentence above echoes the Algol 68 report } @comment{Blank line} @key[end]; --@i{ processing of Line is complete } @comment{Blank line} --@i{ a long comment may be split onto} --@i{ two or more consecutive lines } @comment{Blank line} ----------------@i{ the first two hyphens start the comment } @end{Display}} @begin{Example} --@RI[ the last sentence above echoes the Algol 68 report ] @comment{Blank line} @key[end]; --@RI[ processing of Line is complete ] @comment{Blank line} --@RI[ a long comment may be split onto] --@RI[ two or more consecutive lines ] @comment{Blank line} ----------------@RI[ the first two hyphens start the comment ] @end{Example} @end{Examples} @LabeledClause{Pragmas} @begin{Intro} @ToGlossaryAlso{Term=<Pragma>, Text=<A pragma is a compiler directive. There are language-defined pragmas that give instructions for optimization, listing control, etc. An implementation may support additional (implementation-defined) pragmas.>} @end{Intro} @begin{Syntax} @Syn{lhs=<pragma>,rhs=" @key{pragma} @Syn2{identifier} [(@Syn2{pragma_argument_association} {, @Syn2{pragma_argument_association}})];"} @Syn{lhs=<pragma_argument_association>,rhs=" [@SynI{pragma_argument_}@Syn2{identifier} =>] @Syn2{name} | [@SynI{pragma_argument_}@Syn2{identifier} =>] @Syn2{expression}"} @begin{SyntaxText} In a @nt<pragma>, any @nt<pragma_argument_association>s without a @i{pragma_argument_}@nt<identifier> shall precede any associations with a @i{pragma_argument_}@nt<identifier>. @Leading@keepnext@nt{Pragma}s are only allowed at the following places in a program: @begin{Itemize} After a semicolon delimiter, but not within a @nt{formal_part} or @nt{discriminant_part}. At any place where the syntax rules allow a construct defined by a syntactic category whose name ends with "@ntf{declaration}", "@ntf{statement}", "@ntf{clause}", or "@ntf{alternative}", or one of the syntactic categories @nt{variant} or @nt{exception_handler}; but not in place of such a construct. Also at any place where a @nt{compilation_unit} would be allowed. @end{Itemize} Additional syntax rules and placement restrictions exist for specific pragmas. @end{SyntaxText} @begin{Discussion} The above rule is written in text, rather than in BNF; the syntactic category @nt{pragma} is not used in any BNF syntax rule. @end{Discussion} @begin{Ramification} A @nt{pragma} is allowed where a @nt<generic_formal_parameter_declaration> is allowed. @end{Ramification} @end{Syntax} @begin{Intro} @Defn2{Term=[name], Sec=(of a @nt{pragma})} @Defn{pragma name} The @i{name} of a @nt{pragma} is the identifier following the reserved word @key{pragma}. @Defn{pragma argument} @Defn{argument of a pragma} The @nt{name} or @nt{expression} of a @nt{pragma_argument_association} is a @i{pragma argument}. @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[For compatibility with Ada 83, the name of a pragma may also be @lquotes@key{interface}@rquotes@;, which is not an identifier (because it is a reserved word). See @RefSecNum{Pragma Interface}.]} @end{Honest} @Defn{identifier specific to a pragma} @Defn{pragma, identifier specific to} An @i{identifier specific to a pragma} is an identifier that is used in a pragma argument with special meaning for that pragma. @begin{Honest} Whenever the syntax rules for a given pragma allow "@nt{identifier}" as an argument of the @nt{pragma}, that @nt{identifier} is an identifier specific to that pragma. @end{Honest} @end{Intro} @begin{StaticSem} If an implementation does not recognize the name of a @nt{pragma}, then it has no effect on the semantics of the program. Inside such a @nt{pragma}, the only rules that apply are the @SyntaxName@;s. @begin{Honest} This rule takes precedence over any other rules that imply otherwise. @end{Honest} @begin{Ramification} Note well: this rule applies only to @nt{pragma}s whose name is not recognized. If anything else is wrong with a @nt{pragma} (at compile time), the @nt{pragma} is illegal. This is true whether the @nt{pragma} is language defined or implementation defined. For example, an expression in an unrecognized @nt{pragma} does not cause freezing, even though the rules in @RefSec{Freezing Rules} say it does; the above rule overrules those other rules. On the other hand, an expression in a recognized @nt{pragma} causes freezing, even if this makes something illegal. For another example, an expression that would be ambiguous is not illegal if it is inside an unrecognized @nt{pragma}. Note, however, that implementations have to recognize @key[pragma] Inline(Foo) and freeze things accordingly, even if they choose to never do inlining. Obviously, the contradiction needs to be resolved one way or the other. The reasons for resolving it this way are: The implementation is simple @em the compiler can just ignore the @nt{pragma} altogether. The interpretation of constructs appearing inside implementation-defined @nt{pragma}s is implementation defined. For example: @lquotes@;@key[pragma] Mumble(X);@rquotes@;. If the current implementation has never heard of Mumble, then it doesn't know whether X is a name, an expression, or an identifier specific to the pragma Mumble. @end{Ramification} @begin{Honest} The syntax of individual pragmas overrides the general syntax for @nt{pragma}. @end{Honest} @begin{Ramification} Thus, an identifier specific to a pragma is not a @nt{name}, syntactically; if it were, the visibility rules would be invoked, which is not what we want. This also implies that named associations do not allow one to give the arguments in an arbitrary order @em the order given in the syntax rule for each individual pragma must be obeyed. However, it is generally possible to leave out earlier arguments when later ones are given; for example, this is allowed by the syntax rule for pragma Import (see @RefSec{Interfacing Pragmas}). As for subprogram calls, positional notation precedes named notation. Note that Ada 83 had no pragmas for which the order of named associations mattered, since there was never more than one argument that allowed named associations. @end{Ramification} @begin{Honest} The interpretation of the arguments of implementation-defined pragmas is implementation defined. However, the syntax rules have to be obeyed. @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(pragma)} @PDefn2{Term=[elaboration], Sec=(pragma)} Any @nt{pragma} that appears at the place of an executable construct is executed. Unless otherwise specified for a particular pragma, this execution consists of the evaluation of each evaluable pragma argument in an arbitrary order. @begin{Ramification} For a @nt{pragma} that appears at the place of an elaborable construct, execution is elaboration. An identifier specific to a pragma is neither a @nt{name} nor an @nt{expression} @em such identifiers are not evaluated (unless an implementation defines them to be evaluated in the case of an implementation-defined @nt{pragma}). The @lquotes@;unless otherwise specified@rquotes@; part allows us (and implementations) to make exceptions, so a @nt{pragma} can contain an expression that is not evaluated. Note that @nt{pragma}s in @nt{type_definition}s may contain expressions that depend on discriminants. When we wish to define a pragma with some run-time effect, we usually make sure that it appears in an executable context; otherwise, special rules are needed to define the run-time effect and when it happens. @end{Ramification} @end{RunTime} @begin{ImplReq} The implementation shall give a warning message for an unrecognized pragma name. @begin{Ramification} An implementation is also allowed to have modes in which a warning message is suppressed, or in which the presence of an unrecognized @nt{pragma} is a compile-time error. @end{Ramification} @end{ImplReq} @begin{ImplPerm} An implementation may provide implementation-defined pragmas; the name of an implementation-defined pragma shall differ from those of the language-defined pragmas. @ImplDef{Implementation-defined pragmas.} @begin{Ramification} The semantics of implementation-defined pragmas, and any associated rules (such as restrictions on their placement or arguments), are, of course, implementation defined. Implementation-defined pragmas may have run-time effects. @end{Ramification} An implementation may ignore an unrecognized pragma even if it violates some of the @SyntaxName@;s, if detecting the syntax error is too complex. @begin{Reason} Many compilers use extra post-parsing checks to enforce the syntax rules, since the Ada syntax rules are not LR(k) (for any k). (The grammar is ambiguous, in fact.) This paragraph allows them to ignore an unrecognized pragma, without having to perform such post-parsing checks. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} Normally, implementation-defined pragmas should have no semantic effect for error-free programs; that is, if the implementation-defined pragmas are removed from a working program, the program should still be legal, and should still have the same semantics. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined pragmas should have no semantic effect for error-free programs.]}]} @begin{Ramification} Note that @lquotes@;semantics@rquotes@; is not the same as @lquotes@;effect;@rquotes@; as explained in @RefSecNum{Conformity of an Implementation With the Standard}, the semantics defines a set of possible effects. Note that adding a @nt{pragma} to a program might cause an error (either at compile time or at run time). On the other hand, if the language-specified semantics for a feature are in part implementation defined, it makes sense to support pragmas that control the feature, and that have real semantics; thus, this paragraph is merely a recommendation. @end{Ramification} @Leading@;Normally, an implementation should not define pragmas that can make an illegal program legal, except as follows: @begin(Itemize) A @nt<pragma> used to complete a declaration, such as a @nt{pragma} Import; A @nt<pragma> used to configure the environment by adding, removing, or replacing @nt{library_item}s. @end(Itemize) @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined pragmas should not make an illegal program legal, unless they complete a declaration or configure the @nt{library_item}s in an environment.]}]} @begin(Ramification) For example, it is OK to support Interface, System_Name, Storage_Unit, and Memory_Size @nt{pragma}s for upward compatibility reasons, even though all of these @nt{pragma}s can make an illegal program legal. (The latter three can affect legality in a rather subtle way: They affect the value of named numbers in System, and can therefore affect the legality in cases where static expressions are required.) On the other hand, adding implementation-defined pragmas to a legal program can make it illegal. For example, a common kind of implementation-defined pragma is one that promises some property that allows more efficient code to be generated. If the promise is a lie, it is best if the user gets an error message. @end(Ramification) @end{ImplAdvice} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 83, @lquotes@;bad@rquotes@; @nt{pragma}s are ignored. In Ada 95, they are illegal, except in the case where the name of the @nt{pragma} itself is not recognized by the implementation. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Implementation-defined @nt{pragma}s may affect the legality of a program. @end{Extend83} @begin{DiffWord83} Implementation-defined @nt{pragma}s may affect the run-time semantics of the program. This was always true in Ada 83 (since it was not explicitly forbidden by RM83), but it was not clear, because there was no definition of @lquotes@;executing@rquotes@; or @lquotes@;elaborating@rquotes@; a @nt{pragma}. @end{DiffWord83} @begin{Syntax} @Leading@keepnext@;The forms of List, Page, and Optimize @nt{pragma}s are as follows: @PragmaSyn`@key{pragma} @prag(List)(@Syn2{identifier});' @PragmaSyn`@key{pragma} @prag(Page);' @PragmaSyn`@key{pragma} @prag(Optimize)(@Syn2{identifier});' @begin{SyntaxText} @Redundant[Other pragmas are defined throughout this International Standard, and are summarized in @RefSecNum{Language-Defined Pragmas}.] @begin{Ramification} The language-defined pragmas are supported by every implementation, although @lquotes@;supporting@rquotes@; some of them (for example, Inline) requires nothing more than checking the arguments, since they act only as advice to the implementation. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{StaticSem} A @nt{pragma} List takes one of the @nt{identifier}s On or Off as the single argument. This pragma is allowed anywhere a @nt{pragma} is allowed. It specifies that listing of the compilation is to be continued or suspended until a List @nt{pragma} with the opposite argument is given within the same compilation. The @nt{pragma} itself is always listed if the compiler is producing a listing. A @nt{pragma} Page is allowed anywhere a @nt{pragma} is allowed. It specifies that the program text which follows the @nt{pragma} should start on a new page (if the compiler is currently producing a listing). A @nt{pragma} Optimize takes one of the @nt{identifier}s Time, Space, or Off as the single argument. This @nt{pragma} is allowed anywhere a @nt<pragma> is allowed, and it applies until the end of the immediately enclosing declarative region, or for a @nt{pragma} at the place of a @nt{compilation_unit}, to the end of the @nt<compilation>. It gives advice to the implementation as to whether time or space is the primary optimization criterion, or that optional optimizations should be turned off. @Redundant[It is implementation defined how this advice is followed.] @ImplDef{Effect of pragma Optimize.} @begin{Discussion} For example, a compiler might use Time vs. Space to control whether generic instantiations are implemented with a macro-expansion model, versus a shared-generic-body model. We don't define what constitutes an @lquotes@;optimization@rquotes@; @em in fact, it cannot be formally defined in the context of Ada. One compiler might call something an optional optimization, whereas another compiler might consider that same thing to be a normal part of code generation. Thus, the programmer cannot rely on this pragma having any particular portable effect on the generated code. Some compilers might even ignore the pragma altogether. @end{Discussion} @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of pragmas:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[pragma] List(Off); --@RI{ turn off listing generation} @key[pragma] Optimize(Off); --@RI{ turn off optional optimizations} @key[pragma] Inline(Set_Mask); --@RI{ generate code for Set_Mask inline} @Chg{Version=[2],New=[@key[pragma] Import(C, Put_Char, External_Name => "putchar"); --@RI{ import C putchar function}], Old=[@key[pragma] Suppress(Range_Check, On => Index); --@RI{ turn off range checking on Index}]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The Optimize @nt<pragma> now allows the identifier Off to request that normal optimization be turned off. An Optimize @nt<pragma> may appear anywhere pragmas are allowed. @end{Extend83} @begin{DiffWord83} We now describe the pragmas Page, List, and Optimize here, to act as examples, and to remove the normative material from @RefSec{Language-Defined Pragmas}, so it can be entirely an informative annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[Updated the example of named pragma parameters, because the second parameter of @nt{pragma} Suppress is obsolescent.]} @end{DiffWord95} @LabeledClause{Reserved Words} @begin{Syntax} @begin{Bundle} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Type=[Leading],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00284-02],ARef=[AI95-00395-01]} @ChgNote{The table of words has no paragraph number, so we need to put the change here} @Leading @Defn{reserved word} The following are the @i{reserved words}@Chg{Version=[2],New=[. Within a program, some or all of the letters of a reserved word may be in upper case, and one or more characters in category @ntf{other_format} may be inserted within or at the end of the reserved word.],Old=[ (ignoring upper/lower case distinctions):]} @begin{Discussion} Reserved words have special meaning in the syntax. In addition, certain reserved words are used as attribute names. The syntactic category @nt{identifier} no longer allows reserved words. We have added the few reserved words that are legal explicitly to the syntax for @nt{attribute_reference}. Allowing identifier to include reserved words has been a source of confusion for some users, and differs from the way they are treated in the C and Pascal language definitions. @end{Discussion} @* @begin{Display} @begin{FourCol} @noparanum@key{abort} @key{abs} @key{abstract} @key{accept} @key{access} @key{aliased} @key{all} @key{and} @key{array} @key{at} @noparanum@key{begin} @key{body} @noparanum@key{case} @key{constant} @noparanum@key{declare} @key{delay} @key{delta} @key{digits} @key{do} @NewColumn @noparanum@key{else} @key{elsif} @key{end} @key{entry} @key{exception} @key{exit} @noparanum@key{for} @key{function} @noparanum@key{generic} @key{goto} @noparanum@key{if} @key{in} @Chg{Version=[2],New=[@key{interface}],Old=[]} @key{is} @noparanum@key{limited} @key{loop} @noparanum@key{mod} @NewColumn @noparanum@key{new} @key{not} @key{null} @noparanum@key{of} @key{or} @key{others} @key{out} @Chg{Version=[2],New=[@key{overriding}],Old=[]} @noparanum@key{package} @key{pragma} @key{private} @key{procedure} @key{protected} @noparanum@key{raise} @key{range} @key{record} @key{rem} @key{renames} @key{requeue} @NewColumn @noparanum@key{return} @key{reverse} @noparanum@key{select} @key{separate} @key{subtype} @Chg{Version=[2],New=[@key{synchronized}],Old=[]} @noparanum@key{tagged} @key{task} @key{terminate} @key{then} @key{type} @noparanum@key{until} @key{use} @noparanum@key{when} @key{while} @key{with} @noparanum@key{xor} @end{FourCol} @end{Display} @end{Bundle} @end{Syntax} @begin{Notes} The reserved words appear in @key{lower case boldface} in this International Standard, except when used in the @nt{designator} of an attribute (see @RefSecNum(Attributes)). Lower case boldface is also used for a reserved word in a @nt{string_literal} used as an @nt{operator_symbol}. This is merely a convention @em programs may be written in whatever typeface is desired and available. @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The following words are not reserved in Ada 83, but are reserved in Ada 95: @key{abstract}, @key{aliased}, @key{protected}, @key{requeue}, @key{tagged}, @key{until}. @end{Incompatible83} @begin{DiffWord83} The clause entitled @lquotes@;Allowed Replacements of Characters@rquotes@; has been moved to @RefSec(Obsolescent Features). @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The following words are not reserved in Ada 95, but are reserved in Ada 2005: @key{interface}, @key{overriding}, @key{synchronized}. A special allowance is made for @key{pragma} Interface (see @RefSecNum{Pragma Interface}). Uses of these words as identifiers will need to be changed, but we do not expect them to be common.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The definition of upper case equivalence has been modified to allow identifiers using all of the characters of ISO 10646. This change has no effect on the character sequences that are reserved words, but does make some unusual sequences of characters illegal.]} @end{DiffWord95} ������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/03a.mss��������������������������������������������������������������0000755�0001752�0001001�00001032416�12273462240�016537� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2006/10/17 05:29:41 $} @LabeledSection{Declarations and Types} @Comment{$Source: e:\\cvsroot/ARM/Source/03a.mss,v $} @Comment{$Revision: 1.83 $} @begin{Intro} This section describes the types in the language and the rules for declaring constants, variables, and named numbers. @end{Intro} @LabeledClause{Declarations} @begin{Intro} @PDefn{entity} The language defines several kinds of named @i(entities) that are declared by declarations. @PDefn{name} The entity's @i(name) is defined by the declaration, usually by a @nt<defining_@!identifier>, but sometimes by a @nt{defining_@!character_@!literal} or @nt{defining_@!operator_@!symbol}. There are several forms of declaration. A @nt<basic_declaration> is a form of declaration defined as follows. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Syn{tabs=[P27], lhs=<basic_declaration>,rhs=" @Syn2{type_declaration}@\| @Syn2{subtype_declaration} | @Syn2{object_declaration}@\| @Syn2{number_declaration} | @Syn2{subprogram_declaration}@\| @Syn2{abstract_subprogram_declaration} | @Chg{Version=[2],New=[@Syn2{null_procedure_declaration}@\| ],Old=[]}@Syn2{package_declaration}@Chg{Version=[2],New=[ |],Old=[@\|]} @Syn2{renaming_declaration}@Chg{Version=[2],New=[@\|],Old=[ |]} @Syn2{exception_declaration}@Chg{Version=[2],New=[ |],Old=[@\|]} @Syn2{generic_declaration}@Chg{Version=[2],New=[@\|],Old=[ |]} @Syn2{generic_instantiation}"} @Syn{lhs=<defining_identifier>,rhs="@Syn2{identifier}"} @end{Syntax} @begin{StaticSem} @ToGlossaryAlso{Term=<Declaration>, Text=<A @i(declaration) is a language construct that associates a name with (a view of) an entity. @Defn(explicit declaration) @Defn(implicit declaration) A declaration may appear explicitly in the program text (an @i(explicit) declaration), or may be supposed to occur at a given place in the text as a consequence of the semantics of another construct (an @i(implicit) declaration).>} @begin{Discussion} An implicit declaration generally declares a predefined or inherited operation associated with the definition of a type. This term is used primarily when allowing explicit declarations to override implicit declarations, as part of a type declaration. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{declaration} Each of the following is defined to be a declaration: any @nt{basic_@!declaration}; an @nt{enumeration_@!literal_@!specification}; a @nt{discriminant_@!specification}; a @nt{component_@!declaration}; a @nt{loop_@!parameter_@!specification}; a @nt{parameter_@!specification}; a @nt{subprogram_@!body}; an @nt{entry_@!declaration}; an @nt{entry_@!index_@!specification}; a @nt{choice_@!parameter_@!specification}; a @nt{generic_@!formal_@!parameter_@!declaration}.@Chg{Version=[2],New=[ In addition, an @nt{extended_return_statement} is a declaration of its @nt{defining_identifier}.],Old=[]} @begin(Discussion) This list (when @nt<basic_declaration> is expanded out) contains all syntactic categories that end in "_declaration" or "_specification", except for program unit _specifications. Moreover, it contains @nt{subprogram_body}. A @nt{subprogram_body} is a declaration, whether or not it completes a previous declaration. This is a bit strange, @nt{subprogram_body} is not part of the syntax of @nt{basic_declaration} or @nt{library_unit_declaration}. A renaming-as-body is considered a declaration. An @nt{accept_statement} is not considered a declaration. Completions are sometimes declarations, and sometimes not. @end(Discussion) @Defn(view)@Defn(definition) All declarations contain a @i(definition) for a @i(view) of an entity. A view consists of an identification of the entity (the entity @i(of) the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a @nt(renaming_declaration) is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity (see @RefSecNum(Renaming Declarations))). @ChgToGlossary{Version=[2],Kind=[Revised],Term=<View>, Text=<@Chg{Version=[2],New=[A view of an entity reveals some or all of the properties of the entity. A single entity may have multiple views.], Old=[(See @b[Definition].)]}>} @begin{Discussion} Most declarations define a view (of some entity) whose view-specific characteristics are unchanging for the life of the view. However, subtypes are somewhat unusual in that they inherit characteristics from whatever view of their type is currently visible. Hence, a subtype is not a @i(view) of a type; it is more of an indirect reference. By contrast, a private type provides a single, unchanging (partial) view of its full type. @end{Discussion} @ChgToGlossary{Version=[2],Kind=[Deleted],Term=<Definition>, Text=<@ChgDeleted{Version=[2],Text=[@Defn(view) All declarations contain a @i(definition) for a @i(view) of an entity. A view consists of an identification of the entity (the entity @i(of) the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a @nt(renaming_declaration) is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity (see @RefSecNum(Renaming Declarations))).]}>} @PDefn2{Term=[scope], Sec=(informal definition)} For each declaration, the language rules define a certain region of text called the @i(scope) of the declaration (see @RefSecNum(Scope of Declarations)). Most declarations associate an @nt<identifier> with a declared entity. Within its scope, and only there, there are places where it is possible to use the @nt<identifier> to refer to the declaration, the view it defines, and the associated entity; these places are defined by the visibility rules (see @RefSecNum(Visibility)). @Defn2{Term=[name], Sec={of (a view of) an entity}} At such places the @nt<identifier> is said to be a @i(name) of the entity (the @nt<direct_name> or @nt<selector_name>); @PDefn2{Term=[denote], Sec={informal definition}} the name is said to @i(denote) the declaration, the view, and the associated entity (see @RefSecNum{The Context of Overload Resolution}). @Defn{declare} The declaration is said to @i(declare) the name, the view, and in most cases, the entity itself. As an alternative to an @nt<identifier>, an enumeration literal can be declared with a @nt<character_literal> as its name (see @RefSecNum(Enumeration Types)), and a function can be declared with an @nt<operator_symbol> as its name (see @RefSecNum(Subprogram Declarations)). @Defn{defining name} The syntax rules use the terms @nt<defining_identifier>, @nt<defining_@!character_@!literal>, and @nt<defining_@!operator_@!symbol> for the defining occurrence of a name; these are collectively called @i(defining names). @Defn{usage name} The terms @nt<direct_name> and @nt<selector_name> are used for usage occurrences of @nt<identifier>s, @nt<character_literal>s, and @nt<operator_symbol>s. These are collectively called @i(usage names). @begin(Honest) The terms @nt<identifier>, @nt<character_literal>, and @nt<operator_symbol> are used directly in contexts where the normal visibility rules do not apply (such as the @nt<identifier> that appears after the @key(end) of a @nt<task_body>). Analogous conventions apply to the use of @nt<designator>, which is the collective term for @nt<identifier> and @nt<operator_symbol>. @end(Honest) @end{StaticSem} @begin{RunTime} @RootDefn{execution} The process by which a construct achieves its run-time effect is called @i(execution). @RootDefn{elaboration} @RootDefn{evaluation} This process is also called @i(elaboration) for declarations and @i(evaluation) for expressions. One of the terms execution, elaboration, or evaluation is defined by this International Standard for each construct that has a run-time effect. @ToGlossary{Term=<Execution>, Text=<The process by which a construct achieves its run-time effect is called @i(execution). @Defn(elaboration) @Defn(evaluation) Execution of a declaration is also called @i(elaboration). Execution of an expression is also called @i(evaluation).>} @begin{Honest} The term elaboration is also used for the execution of certain constructs that are not declarations, and the term evaluation is used for the execution of certain constructs that are not expressions. For example, @nt{subtype_indication}s are elaborated, and @nt{range}s are evaluated. For bodies, execution and elaboration are both explicitly defined. When we refer specifically to the execution of a body, we mean the explicit definition of execution for that kind of body, not its elaboration. @end{Honest} @begin(Discussion) Technically, "the execution of a declaration" and "the elaboration of a declaration" are synonymous. We use the term "elaboration" of a construct when we know the construct is elaborable. When we are talking about more arbitrary constructs, we use the term "execution". For example, we use the term "erroneous execution", to refer to any erroneous execution, including erroneous elaboration or evaluation. When we explicitly define evaluation or elaboration for a construct, we are implicitly defining execution of that construct. We also use the term "execution" for things like @nt{statement}s, which are executable, but neither elaborable nor evaluable. We considered using the term "execution" only for non-elaborable, non-evaluable constructs, and defining the term "action" to mean what we have defined "execution" to mean. We rejected this idea because we thought three terms that mean the same thing was enough @em four would be overkill. Thus, the term "action" is used only informally in the standard (except where it is defined as part of a larger term, such as "protected action"). @end(Discussion) @ChgToGlossary{Version=[2],Kind=[Added],Term=<Elaboration>, Text=<@ChgAdded{Version=[2],Text=[The process by which a declaration achieves its run-time effect is called elaboration. Elaboration is one of the forms of execution.]}>} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Evaluation>, Text=<@ChgAdded{Version=[2],Text=[The process by which an expression achieves its run-time effect is called evaluation. Evaluation is one of the forms of execution.]}>} @begin{Honest} @Defn{elaborable} A construct is @i(elaborable) if elaboration is defined for it. @Defn{evaluable} A construct is @i(evaluable) if evaluation is defined for it. @Defn{executable} A construct is @i(executable) if execution is defined for it. @end{Honest} @begin(Discussion) Don't confuse @lquotes@;elaborable@rquotes@; with @lquotes@;preelaborable@rquotes@; (defined in @RefSecNum(Elaboration Control)). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Evaluation of an evaluable construct produces a result that is either a value, a denotation, or a range. The following are evaluable: expression; @nt{name} @nt{prefix}; @nt{range}; @Chg{Version=[2],New=[@nt{entry_index_specification}],Old=[@ntf{entry_list_iterator}]}; and possibly @nt{discrete_range}. The last one is curious @em RM83 uses the term @lquotes@;evaluation of a @nt{discrete_range},@rquotes@; but never defines it. One might presume that the evaluation of a @nt{discrete_range} consists of the evaluation of the @nt{range} or the @nt{subtype_indication}, depending on what it is. But @nt{subtype_indication}s are not evaluated; they are elaborated. Intuitively, an @i(executable) construct is one that has a defined run-time effect (which may be null). Since execution includes elaboration and evaluation as special cases, all elaborable and all evaluable constructs are also executable. Hence, most constructs in Ada are executable. An important exception is that the constructs inside a generic unit are not executable directly, but rather are used as a template for (generally) executable constructs in instances of the generic. @end(Discussion) @end{RunTime} @begin{Notes} @Defn{declare} At compile time, the declaration of an entity @i(declares) the entity. @Defn{create} At run time, the elaboration of the declaration @i(creates) the entity. @begin{Ramification} Syntactic categories for declarations are named either @i(entity_)@ntf<declaration> (if they include a trailing semicolon) or @i(entity_)@ntf<specification> (if not). @Defn{entity} The various kinds of named entities that can be declared are as follows: an object (including components and parameters), a named number, a type (the name always refers to its first subtype), a subtype, a subprogram (including enumeration literals and operators), a single entry, an entry family, a package, a protected or task unit (which corresponds to either a type or a single object), an exception, a generic unit, a label, and the name of a statement. Identifiers are also associated with names of pragmas, arguments to pragmas, and with attributes, but these are not user-definable. @end{Ramification} @end{Notes} @begin{DiffWord83} The syntax rule for @nt{defining_identifier} is new. It is used for the defining occurrence of an @nt{identifier}. Usage occurrences use the @nt{direct_name} or @nt{selector_name} syntactic categories. @Leading@;Each occurrence of an @nt{identifier} (or @ntf{simple_name}), @nt{character_literal}, or @nt{operator_symbol} in the Ada 83 syntax rules is handled as follows in Ada 95: @begin{itemize} It becomes a @nt{defining_identifier}, @nt{defining_character_literal}, or @nt{defining_operator_symbol} (or some syntactic category composed of these), to indicate a defining occurrence; It becomes a @nt{direct_name}, in usage occurrences where the usage is required (in Section 8) to be directly visible; It becomes a @nt{selector_name}, in usage occurrences where the usage is required (in Section 8) to be visible but not necessarily directly visible; It remains an @nt{identifier}, @nt{character_literal}, or @nt{operator_symbol}, in cases where the visibility rules do not apply (such as the @nt{designator} that appears after the @key{end} of a @nt{subprogram_body}). @end{itemize} For declarations that come in @lquotes@;two parts@rquotes@; (program unit declaration plus body, private or incomplete type plus full type, deferred constant plus full constant), we consider both to be defining occurrences. Thus, for example, the syntax for @nt{package_body} uses @nt{defining_identifier} after the reserved word @key{body}, as opposed to @nt{direct_name}. The defining occurrence of a statement name is in its implicit declaration, not where it appears in the program text. Considering the statement name itself to be the defining occurrence would complicate the visibility rules. The phrase @lquotes@;visible by selection@rquotes@; is not used in Ada 95. It is subsumed by simply @lquotes@;visible@rquotes@; and the Name Resolution Rules for @nt<selector_name>s. (Note that in Ada 95, a declaration is visible at all places where one could have used a @nt{selector_name}, not just at places where a @nt{selector_name} was actually used. Thus, the places where a declaration is directly visible are a subset of the places where it is visible. See Section 8 for details.) We use the term @lquotes@;declaration@rquotes@; to cover @ntf<_specification>s that declare (views of) objects, such as @nt<parameter_specification>s. In Ada 83, these are referred to as a @lquotes@;form of declaration,@rquotes@; but it is not entirely clear that they are considered simply @lquotes@;declarations.@rquotes@; RM83 contains an incomplete definition of "elaborated" in this clause: it defines "elaborated" for declarations, @nt{declarative_part}s, @nt{declarative_item}s and @nt{compilation_unit}s, but "elaboration" is defined elsewhere for various other constructs. To make matters worse, Ada 95 has a different set of elaborable constructs. Instead of correcting the list, it is more maintainable to refer to the term "elaborable," which is defined in a distributed manner. RM83 uses the term @lquotes@;has no other effect@rquotes@; to describe an elaboration that doesn't do anything except change the state from not-yet-elaborated to elaborated. This was a confusing wording, because the answer to @lquotes@;other than what?@rquotes@; was to be found many pages away. In Ada 95, we change this wording to @lquotes@;has no effect@rquotes@; (for things that truly do nothing at run time), and @lquotes@;has no effect other than to establish that so-and-so can happen without failing the Elaboration_Check@rquotes@; (for things where it matters). We make it clearer that the term "execution" covers elaboration and evaluation as special cases. This was implied in RM83. For example, "erroneous execution" can include any execution, and RM83-9.4(3) has, "The task designated by any other task object depends on the master whose execution creates the task object;" the elaboration of the master's @nt{declarative_part} is doing the task creation. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Added @nt{extended_return_statement} to the list of declarations.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Added null procedures (see @RefSecNum{Null Procedures}) to the syntax.]} @end{DiffWord95} @LabeledClause{Types and Subtypes} @begin{StaticSem} @Defn{type} @PDefn{primitive operation} A @i(type) is characterized by a set of values, and a set of @i(primitive operations) which implement the fundamental aspects of its semantics. @PDefn{object} An @i(object) of a given type is a run-time entity that contains (has) a value of the type. @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Type>, Text=<Each object has a type. A @i(type) has an associated set of values, and a set of @i(primitive operations) which implement the fundamental aspects of its semantics. Types are grouped into @Chg{Version=[2],New=[@i(categories)], Old=[@i(classes)]}. @Chg{Version=[2],New=[Most language-defined categories of types are also @i<classes> of types],Old=[The types of a given class share a set of primitive operations. @Defn(closed under derivation) Classes are closed under derivation; that is, if a type is in a class, then all of its derivatives are in that class]}.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Subtype>, Text=<A subtype is a type together with a constraint@Chg{Version=[2], New=[ or null exclusion],Old=[]}, which constrains the values of the subtype to satisfy a certain condition. The values of a subtype are a subset of the values of its type.>} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[@Defn2{Term=[category], Sec=(of types)}], Old=[]}@Defn2{Term=[class], Sec=(of types)} Types are grouped into @Chg{Version=[2],New=[@i(categories)], Old=[@i(classes)]} of types@Chg{Version=[2],New=[],Old=[, reflecting the similarity of their values and primitive operations]}. @Defn2{Term=[language-defined class], Sec=(of types)} There exist several @i(language-defined @Chg{Version=[2],New=[categories], Old=[classes]}) of types (see NOTES below)@Chg{Version=[2],New=[, reflecting the similarity of their values and primitive operations],Old=[]}.@Chg{Version=[2], New=[@Defn2{Term=[language-defined category], Sec=(of types)} @Redundant[Most categories of types form @i(classes) of types.]],Old=[]} @Defn{elementary type} @i(Elementary) types are those whose values are logically indivisible; @Defn{composite type} @Defn{component} @i(composite) types are those whose values are composed of @i(component) values. @IndexSeeAlso{Term={aggregate},See=(composite type)} @begin{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The formal definition of @i<category> and @i<class> is found in @RefSecNum{Derived Types and Classes}.]} @end{TheProof} @ChgNote<The following ought to have the Term be: Class@Chg{Version=[2],New=[ (of types)],Old=[]} but that doesn't index properly and it is too much work to fix. See if anyone complains.> @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Class (of types)>, Text=<@Defn(closed under derivation) A class is a set of types that is closed under derivation, which means that if a given type is in the class, then all types derived from that type are also in the class. The set of types of a class share common properties, such as their primitive operations.>} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Category (of types)>, Text=<@ChgAdded{Version=[2],Text=[A category of types is a set of types with one or more common properties, such as primitive operations. A category of types that is closed under derivation is also known as a @i<class>.]}>} @ToGlossary{Term=<Elementary type>, Text=<An elementary type does not have components.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Composite type>, Text=<A composite type @Chg{Version=[2],New=[may have],Old=[has]} components.>} @ToGlossary{Term=<Scalar type>, Text=<A scalar type is either a discrete type or a real type.>} @ToGlossary{Term=<Access type>, Text=<An access type has values that designate aliased objects. Access types correspond to @lquotes@;pointer types@rquotes@; or @lquotes@;reference types@rquotes@; in some other languages.>} @ToGlossary{Term=<Discrete type>, Text=<A discrete type is either an integer type or an enumeration type. Discrete types may be used, for example, in @nt(case_statement)s and as array indices.>} @ToGlossary{Term=<Real type>, Text=<A real type has values that are approximations of the real numbers. Floating point and fixed point types are real types.>} @ToGlossary{Term=<Integer type>, Text=<Integer types comprise the signed integer types and the modular types. A signed integer type has a base range that includes both positive and negative numbers, and has operations that may raise an exception when the result is outside the base range. A modular type has a base range whose lower bound is zero, and has operations with @lquotes@;wraparound@rquotes@; semantics. Modular types subsume what are called @lquotes@;unsigned types@rquotes@; in some other languages.>} @ToGlossary{Term=<Enumeration type>, Text=<An enumeration type is defined by an enumeration of its values, which may be named by identifiers or character literals.>} @ToGlossary{Term=<Character type>, Text=<A character type is an enumeration type whose values include characters.>} @ToGlossary{Term=<Record type>, Text=<A record type is a composite type consisting of zero or more named components, possibly of different types.>} @ToGlossary{Term=<Record extension>, Text=<A record extension is a type that extends another type by adding additional components.>} @ToGlossary{Term=<Array type>, Text=<An array type is a composite type whose components are all of the same type. Components are selected by indexing.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Task type>, Text=<A task type is a composite type @Chg{Version=[2],New=[used to represent], Old=[whose values are tasks, which are]} active entities @Chg{Version=[2],New=[which],Old=[that may]} execute concurrently @Chg{Version=[2],New=[and which can communicate via queued task entries], Old=[with other tasks]}. The top-level task of a partition is called the environment task.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Protected type>, Text=<A protected type is a composite type whose components are @Chg{Version=[2],New=[accessible only through one of its protected operations which synchronize], Old=[protected from]} concurrent access by multiple tasks.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Private type>, Text=<A private type @Chg{Version=[2],New=[gives a],Old=[is a partial]} view of a type @Chg{Version=[2],New=[that reveals only some of its properties. The remaining properties are provided by the],Old=[whose]} full view @Chg{Version=[2],New=[given elsewhere. Private types can be used for defining abstractions that hide unnecessary details],Old=[is hidden]} from @Chg{Version=[2],New=[their],Old=[its]} clients.>}@ChgNote{This was changed to parallel "incomplete type"} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Private extension>, Text=<A private extension is @Chg{Version=[2],New=[a type that extends another type, with the additional properties],Old=[like a record extension, except that the components of the extension part are]} hidden from its clients.>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Incomplete type>, Text=<@ChgAdded{Version=[2],Text=[An incomplete type gives a view of a type that reveals only some of its properties. The remaining properties are provided by the full view given elsewhere. Incomplete types can be used for defining recursive data structures.]}>} @Defn{scalar type} The elementary types are the @i(scalar) types (@i(discrete) and @i(real)) and the @i(access) types (whose values provide access to objects or subprograms). @Defn{discrete type} @Defn{enumeration type} Discrete types are either @i(integer) types or are defined by enumeration of their values (@i(enumeration) types). @Defn{real type} Real types are either @i(floating point) types or @i(fixed point) types. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00326-01]} The composite types are the @i(record) types, @i(record extensions), @i(array) types, @Chg{Version=[2],New=[@i(interface) types, ],Old=[]}@i(task) types, and @i(protected) types.@Chg{Version=[2], New=[], Old=[@Defn{private type} @Defn{private extension} A @i(private) type or @i(private extension) represents a partial view (see @RefSecNum{Private Types and Private Extensions}) of a type, providing support for data abstraction. A partial view is a composite type.]} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00442-01]} @ChgDeleted{Version=[2],Text=[The set of all record types do not form a class (because tagged record types can have private extensions), though the set of untagged record types do. In any case, what record types had in common in Ada 83 (component selection) is now a property of the composite class, since all composite types (other than array types) can have discriminants. Similarly, the set of all private types do not form a class (because tagged private types can have record extensions), though the set of untagged private types do. Nevertheless, the set of untagged private types is not particularly @lquotes@;interesting@rquotes@; @em more interesting is the set of all nonlimited types, since that is what a generic formal (nonlimited) private type matches.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incomplete type} @Defn{private type} @Defn{private extension} There can be multiple views of a type with varying sets of operations. @Redundant[An @i(incomplete) type represents an incomplete view (see @RefSecNum{Incomplete Type Declarations}) of a type with a very restricted usage, providing support for recursive data structures. A @i(private) type or @i(private extension) represents a partial view (see @RefSecNum{Private Types and Private Extensions}) of a type, providing support for data abstraction. The full view (see @RefSecNum{Type Declarations}) of a type represents its complete definition.] An incomplete or partial view is considered a composite type@Redundant[, even if the full view is not].]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The real definitions of the views are in the referenced clauses.]} @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Defn{discriminant} Certain composite types (and@Chg{Version=[2],New=[],Old=[ partial]} views thereof) have special components called @i(discriminants) whose values affect the presence, constraints, or initialization of other components. Discriminants can be thought of as parameters of the type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @Defn{subcomponent} The term @i(subcomponent) is used in this International Standard in place of the term component to indicate either a component, or a component of another subcomponent. Where other subcomponents are excluded, the term component is used instead. @Defn2{Term=[part], Sec=(of an object or value)} Similarly, a @i(part) of an object or value is used to mean the whole object or value, or any set of its subcomponents.@Chg{Version=[2], New=[ The terms component, subcomponent, and part are also applied to a type meaning the component, subcomponent, or part of objects and values of the type.],Old=[]} @begin{Discussion} The definition of @lquotes@;part@rquotes@; here is designed to simplify rules elsewhere. By design, the intuitive meaning of @lquotes@;part@rquotes@; will convey the correct result to the casual reader, while this formalistic definition will answer the concern of the compiler-writer. We use the term @lquotes@;part@rquotes@; when talking about the parent part, ancestor part, or extension part of a type extension. In contexts such as these, the part might represent an empty set of subcomponents (e.g. in a null record extension, or a nonnull extension of a null record). We also use @lquotes@;part@rquotes@; when specifying rules such as those that apply to an object with a @lquotes@;controlled part@rquotes@; meaning that it applies if the object as a whole is controlled, or any subcomponent is. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @PDefn{constraint} The set of possible values for an object of a given type can be subjected to a condition that is called a @i(constraint) @Defn{null constraint} (the case of a @i(null constraint) that specifies no restriction is also included)@Redundant[; the rules for which values satisfy a given kind of constraint are given in @RefSecNum(Scalar Types) for @nt<range_constraint>s, @RefSecNum(Index Constraints and Discrete Ranges) for @nt<index_constraint>s, and @RefSecNum(Discriminant Constraints) for @nt<discriminant_constraint>s].@Chg{Version=[2],New=[ The set of possible values for an object of an access type can also be subjected to a condition that excludes the null value (see @RefSecNum{Access Types}).],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00415-01]} @Defn{subtype} A @i(subtype) of a given type is a combination of the type, a constraint on values of the type, and certain attributes specific to the subtype. The given type is called the @Chg{Version=[2],New=[@i(type of the subtype)], Old=[type @i(of) the subtype]}.@Chg{Version=[2],New=[@Defn2{Term=[type], Sec=(of a subtype)} @Defn2{Term=[subtype], Sec=(type of)}],Old=[]} Similarly, the associated constraint is called the @Chg{Version=[2],New=[@i(constraint of the subtype)], Old=[constraint @i(of) the subtype]}.@Chg{Version=[2],New=[@Defn2{Term=[constraint], Sec=(of a subtype)} @Defn2{Term=[subtype], Sec=(constraint of)}],Old=[]} The set of values of a subtype consists of the values of its type that satisfy its constraint@Chg{Version=[2],New=[ and any exclusion of the null value], Old=[]}. @Defn2{Term=[belong], Sec=(to a subtype)} Such values @i(belong) to the subtype.@Chg{Version=[2],New=[@Defn2{Term=[values], Sec=(belonging to a subtype)} @Defn2{Term=[subtype], Sec=(values belonging to)}],Old=[]} @begin{Discussion} We make a strong distinction between a type and its subtypes. In particular, a type is @i(not) a subtype of itself. There is no constraint associated with a type (not even a null one), and type-related attributes are distinct from subtype-specific attributes. @end{Discussion} @begin{Discussion} We no longer use the term "base type." All types were "base types" anyway in Ada 83, so the term was redundant, and occasionally confusing. In the RM95 we say simply "the type @i(of) the subtype" instead of "the base type of the subtype." @end{Discussion} @begin{Ramification} The value subset for a subtype might be empty, and need not be a proper subset. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Any name of a @Chg{Version=[2],New=[category],Old=[class]} of types (such as @lquotes@;discrete@rquotes@;@Chg{Version=[2],New=[, ],Old=[ or]} @lquotes@;real@rquotes@;@Chg{Version=[2],New=[, or],Old=[), or other category of types (such as]} @lquotes@;limited@rquotes@;@Chg{Version=[2],New=[], Old=[ or @lquotes@;incomplete@rquotes@;]}) is also used to qualify its subtypes, as well as its objects, values, declarations, and definitions, such as an @lquotes@;integer type declaration@rquotes@; or an @lquotes@;integer value.@rquotes@; In addition, if a term such as @lquotes@;parent subtype@rquotes@; or @lquotes@;index subtype@rquotes@; is defined, then the corresponding term for the type of the subtype is @lquotes@;parent type@rquotes@; or @lquotes@;index type.@rquotes@; @end{Honest} @begin{Discussion} We use these corresponding terms without explicitly defining them, when the meaning is obvious. @end{Discussion} @Defn{constrained} @Defn{unconstrained} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A subtype is called an @i(unconstrained) subtype if its type has unknown discriminants, or if its type allows range, index, or discriminant constraints, but the subtype does not impose such a constraint; otherwise, the subtype is called a @i(constrained) subtype (since it has no unconstrained characteristics). @begin{Discussion} In an earlier version of Ada 9X, "constrained" meant "has a non-null constraint." However, we changed to this definition since we kept having to special case composite non-array/non-discriminated types. It also corresponds better to the (now obsolescent) attribute 'Constrained. For scalar types, @lquotes@;constrained@rquotes@; means @lquotes@;has a non-null constraint@rquotes@;. For composite types, in implementation terms, @lquotes@;constrained@rquotes@; means that the size of all objects of the subtype is the same, assuming a typical implementation model. Class-wide subtypes are always unconstrained. @end{Discussion} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[Any set of types can be called a @lquotes@;category@rquotes@; of types, and any],Old=[Any]} set of types that is closed under derivation (see @RefSecNum(Derived Types and Classes)) can be called a @lquotes@;class@rquotes@; of types. However, only certain @Chg{Version=[2],New=[categories and ],Old=[]}classes are used in the description of the rules of the language @em generally those that have their own particular set of primitive operations (see @RefSecNum(Classification of Operations)), or that correspond to a set of types that are matched by a given kind of generic formal type (see @RefSecNum(Formal Types)). @PDefn{language-defined class} The following are examples of @lquotes@;interesting@rquotes@; @i(language-defined classes): elementary, scalar, discrete, enumeration, character, boolean, integer, signed integer, modular, real, floating point, fixed point, ordinary fixed point, decimal fixed point, numeric, access, access-to-object, access-to-subprogram, composite, array, string, (untagged) record, tagged, task, protected, nonlimited. Special syntax is provided to define types in each of these classes.@Chg{Version=[2],New=[ In addition to these classes, the following are examples of @lquotes@;interesting@rquotes@; @i(language-defined categories): @PDefn{language-defined categories} abstract, incomplete, interface, limited, private, record.],Old=[]} @begin{Discussion} @Defn{value} A @i(value) is a run-time entity with a given type which can be assigned to an object of an appropriate subtype of the type. @Defn{operation} An @i(operation) is a program entity that operates on zero or more operands to produce an effect, or yield a result, or both. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Note that a type's @Chg{Version=[2],New=[category (and ],Old=[]}class@Chg{Version=[2],New=[)],Old=[]} depends on the place of the reference @em a private type is composite outside and possibly elementary inside. It's really the @i{view} that is elementary or composite. Note that although private types are composite, there are some properties that depend on the corresponding full view @em for example, parameter passing modes, and the constraint checks that apply in various places. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[Every property of types forms a category, but not], Old=[Not]} every property of types represents a class. For example, the set of all abstract types does not form a class, because this set is not closed under derivation.@Chg{Version=[2],New=[ Similarly, the set of all interface types does not form a class.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The set of limited types @Chg{Version=[2],New=[does not form a class (since nonlimited types can inherit from limited interfaces), but the set of nonlimited types does. The set of tagged record types and the set of tagged private types do not form a class (because each of them can be extended to create a type of the other category); that implies that the set of record types and the set of private types also do not form a class (even though untagged record types and untagged private types do form a class). In all of these cases, we can talk about the category of the type; for instance, we can talk about the @lquotes@;category of limited types@rquotes.], Old=[forms a class in the sense that it is closed under derivation, but the more interesting class, from the point of generic formal type matching, is the set of all types, limited and nonlimited, since that is what matches a generic formal @lquotes@;limited@rquotes@; private type. Note also that a limited type can @lquotes@;become nonlimited@rquotes@; under certain circumstances, which makes @lquotes@;limited@rquotes@; somewhat problematic as a class of types]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Normatively, the @i<language-defined classes> are those that are defined to be inherited on derivation by @RefSecNum{Derived Types and Classes}; other properties either aren't interesting or form categories, not classes.]} @end{Ramification} @noprefix@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} These language-defined @Chg{Version=[2],New=[categories],Old=[classes]} are organized like this: @begin{Display} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @TabClear{} @TabSet{3, 6, 9, 12, 15, 18, 21} all types @\elementary @\@\scalar @\@\@\discrete @\@\@\@\enumeration @\@\@\@\@\character @\@\@\@\@\boolean @\@\@\@\@\other enumeration @\@\@\@\integer @\@\@\@\@\signed integer @\@\@\@\@\modular integer @\@\@\real @\@\@\@\floating point @\@\@\@\fixed point @\@\@\@\@\ordinary fixed point @\@\@\@\@\decimal fixed point @\@\access @\@\@\access-to-object @\@\@\access-to-subprogram @\composite@Chg{Version=[2],New=[ @\@\untagged],Old=[]} @Chg{Version=[2],New=[@\],Old=[]}@\@\array @Chg{Version=[2],New=[@\],Old=[]}@\@\@\string @Chg{Version=[2],New=[@\],Old=[]}@\@\@\other array @\@\@Chg{Version=[2],New=[@\],Old=[untagged ]}record@Chg{Version=[2],New=[],Old=[ @\@\tagged]} @Chg{Version=[2],New=[@\],Old=[]}@\@\task @Chg{Version=[2],New=[@\],Old=[]}@\@\protected@Chg{Version=[2],New=[ @\@\tagged (including interfaces) @\@\@\nonlimited tagged record @\@\@\limited tagged @\@\@\@\limited tagged record @\@\@\@\synchronized tagged @\@\@\@\@\tagged task @\@\@\@\@\tagged protected],Old=[]} @end{Display} @noprefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[There are other categories, such as],Old=[The classes]} @lquotes@;numeric@rquotes@; and @lquotes@;@Chg{Version=[2],New=[discriminated],Old=[nonlimited]}@rquotes@;@Chg{Version=[2], New=[, which],Old=[]} represent other @Chg{Version=[2],New=[categorization],Old=[classification]} dimensions@Chg{Version=[2],New=[, but], Old=[ and]} do not fit into the above strictly hierarchical picture. @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Note that this is also true for some categories mentioned in the chart. The category @lquotes@;task@rquotes@; includes both untagged tasks and tagged tasks. Similarly for @lquotes@;protected@rquotes@;, @lquotes@;limited@rquotes@;, and @lquotes@;nonlimited@rquotes@; (note that limited and nonlimited are not shown for untagged composite types).]} @end{Discussion} @end{Notes} @begin{DiffWord83} This clause and its subclauses now precede the clause and subclauses on objects and named numbers, to cut down on the number of forward references. We have dropped the term "base type" in favor of simply "type" (all types in Ada 83 were "base types" so it wasn't clear when it was appropriate/necessary to say "base type"). Given a subtype S of a type T, we call T the "type of the subtype S." @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a mention of null exclusions when we're talking about constraints (these are not constraints, but they are similar).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Defined an interface type to be a composite type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Revised the wording so that it is clear that an incomplete view is similar to a partial view in terms of the language.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Added a definition of component of a type, subcomponent of a type, and part of a type. These are commonly used in the standard, but they were not previously defined.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Reworded most of this clause to use category rather than class, since so many interesting properties are not, strictly speaking, classes. Moreover, there was no normative description of exactly which properties formed classes, and which did not. The real definition of class, along with a list of properties, is now in @RefSecNum{Derived Types and Classes}.]} @end{DiffWord95} @LabeledSubClause{Type Declarations} @begin{Intro} A @nt<type_declaration> declares a type and its first subtype. @end{Intro} @begin{Syntax} @Syn{lhs=<type_declaration>,rhs=" @Syn2{full_type_declaration} | @Syn2{incomplete_type_declaration} | @Syn2{private_type_declaration} | @Syn2{private_extension_declaration}"} @Syn{lhs=<full_type_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}] @key{is} @Syn2{type_definition}; | @Syn2{task_type_declaration} | @Syn2{protected_type_declaration}"} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Syn{tabs=[P29], lhs=<type_definition>,rhs=" @Syn2{enumeration_type_definition}@\| @Syn2{integer_type_definition} | @Syn2{real_type_definition}@\| @Syn2{array_type_definition} | @Syn2{record_type_definition}@\| @Syn2{access_type_definition} | @Syn2{derived_type_definition}@Chg{Version=[2],New=[@\| @Syn2{interface_type_definition}],Old=[]}"} @end{Syntax} @begin{Legality} A given type shall not have a subcomponent whose type is the given type itself. @end{Legality} @begin{StaticSem} @Defn{first subtype} The @nt{defining_@!identifier} of a @nt{type_@!declaration} denotes the @i(first subtype) of the type. The @nt<known_@!discriminant_@!part>, if any, defines the discriminants of the type (see @RefSec(Discriminants)). The remainder of the @nt<type_@!declaration> defines the remaining characteristics of (the view of) the type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{named type} A type defined by a @nt<type_@!declaration> is a @i(named) type; such a type has one or more nameable subtypes. @Defn{anonymous type} Certain other forms of declaration also include type definitions as part of the declaration for an object@Chg{Version=[2],New=[], Old=[ (including a parameter or a discriminant)]}. The type defined by such a declaration is @i(anonymous) @em it has no nameable subtypes. @Defn2{Term=[italics],Sec=(pseudo-names of anonymous types)} For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an @nt<identifier>. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply @lquotes@;the type T@rquotes@;. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The only user-defined types that can be anonymous in the above sense are array, access, task, and protected types. An anonymous array, task, or protected type can be defined as part of an @nt{object_declaration}. An anonymous access type can be defined as part of @Chg{Version=[2],New=[numerous other constructs],Old=[a parameter or discriminant specification]}. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00326-01]} @Defn{full type} A named type that is declared by a @nt<full_type_@!declaration>, or an anonymous type that is defined @Chg{Version=[2],New=[by an @nt{access_definition} or ],Old=[]}as part of declaring an object of the type, is called a @i(full type).@Defn{full type definition} @Chg{Version=[2],New=[The declaration of a full type also declares the @i<full view> of the type.@Defn2{Term=[full view],Sec=(of a type)} ],Old=[]}The @nt<type_@!definition>, @nt<task_@!definition>, @nt<protected_@!definition>, or @nt<access_@!definition> that defines a full type is called a @i(full type definition). @redundant[Types declared by other forms of @nt<type_@!declaration> are not separate types; they are partial or incomplete views of some full type.] @begin{Honest} Class-wide, universal, and root numeric types are full types. @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[We need to mention @nt{access_definition} separately, as it may occur in renames, which do not declare objects.]} @end{Reason} @PDefn{predefined operator} The definition of a type implicitly declares certain @i(predefined operators) that operate on the type, according to what classes the type belongs, as specified in @RefSec(Operators and Expression Evaluation). @begin{Discussion} We no longer talk about the implicit declaration of basic operations. These are treated like an @nt{if_statement} @em they don't need to be declared, but are still applicable to only certain classes of types. @end{Discussion} @Defn{predefined type} The @i{predefined types} @Redundant[(for example the types Boolean, Wide_Character, Integer, @i{root_integer}, and @i{universal_integer})] are the types that are defined in @Redundant[a predefined library package called] Standard@Redundant[; this package also includes the @Redundant{(implicit)} declarations of their predefined operators]. @Redundant[The package Standard is described in @RefSecNum{The Package Standard}.] @begin{Ramification} We use the term @lquotes@;predefined@rquotes@; to refer to entities declared in the visible part of Standard, to implicitly declared operators of a type whose semantics are defined by the language, to Standard itself, and to the @lquotes@;predefined environment@rquotes@;. We do not use this term to refer to library packages other than Standard. For example Text_IO is a language-defined package, not a predefined package, and Text_IO.Put_Line is not a predefined operation. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(full_type_declaration)} The elaboration of a @nt{full_type_declaration} consists of the elaboration of the full type definition. @PDefn2{Term=[elaboration], Sec=(full type definition)} Each elaboration of a full type definition creates a distinct type and its first subtype. @begin{Reason} The creation is associated with the type @i(definition), rather than the type @i(declaration), because there are types that are created by full type definitions that are not immediately contained within a type declaration (e.g. an array object declaration, a singleton task declaration, etc.). @end{Reason} @begin{Ramification} Any implicit declarations that occur immediately following the full type definition are elaborated where they (implicitly) occur. @end{Ramification} @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of type definitions:) @begin(Example) (White, Red, Yellow, Green, Blue, Brown, Black) @key(range) 1 .. 72 @key(array)(1 .. 10) @key(of) Integer @end(Example) @begin{Wide} @leading@keepnext@i(Examples of type declarations:) @end{Wide} @begin(Example) @key(type) Color @key(is) (White, Red, Yellow, Green, Blue, Brown, Black); @key(type) Column @key(is) @key(range) 1 .. 72; @key(type) Table @key(is) @key(array)(1 .. 10) @key(of) Integer; @end(Example) @end{Examples} @begin{Notes} Each of the above examples declares a named type. The identifier given denotes the first subtype of the type. Other named subtypes of the type can be declared with @nt<subtype_declaration>s (see @RefSecNum{Subtype Declarations}). Although names do not directly denote types, a phrase like @lquotes@;the type Column@rquotes@; is sometimes used in this International Standard to refer to the type of Column, where Column denotes the first subtype of the type. For an example of the definition of an anonymous type, see the declaration of the array Color_Table in @RefSecNum{Object Declarations}; its type is anonymous @em it has no nameable subtypes. @end{Notes} @begin{DiffWord83} The syntactic category @nt{full_type_declaration} now includes task and protected type declarations. We have generalized the concept of first-named subtype (now called simply @lquotes@;first subtype@rquotes@;) to cover all kinds of types, for uniformity of description elsewhere. RM83 defined first-named subtype in Section 13. We define first subtype here, because it is now a more fundamental concept. We renamed the term, because in Ada 95 some first subtypes have no name. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} We no longer elaborate @nt{discriminant_part}s, because there is nothing to do, and it was complex to say that you only wanted to elaborate it once for a private or incomplete type. This is also consistent with the fact that subprogram specifications are not elaborated (neither in Ada 83 nor in Ada 95). Note, however, that an @nt<access_definition> appearing in a @nt<discriminant_part> is elaborated@Chg{Version=[2],New=[ at the @nt{full_type_declaration} (for a nonlimited type) or],Old=[]} when an object with such a discriminant is created@Chg{Version=[2],New=[ (for a limited type)],Old=[]}. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Added wording so that anonymous access types are always full types, even if they appear in renames.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added interface types (see @RefSecNum{Interface Types}) to the syntax.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Added a definition of full view, so that all types have a well-defined full view.]} @end{DiffWord95} @LabeledSubClause{Subtype Declarations} @begin{Intro} A @nt<subtype_declaration> declares a subtype of some previously declared type, as defined by a @nt<subtype_indication>. @end{Intro} @begin{Syntax} @Syn{lhs=<subtype_declaration>,rhs=" @key{subtype} @Syn2{defining_identifier} @key{is} @Syn2{subtype_indication};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<subtype_indication>,rhs=" @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [@Syn2{constraint}]"} @Syn{lhs=<subtype_mark>,rhs="@SynI{subtype_}@Syn2{name}"} @begin{Ramification} Note that @nt{name} includes @nt{attribute_reference}; thus, S'Base can be used as a @nt{subtype_mark}. @end{Ramification} @begin{Reason} We considered changing @nt{subtype_mark} to @ntf{subtype_name}. However, existing users are used to the word "mark," so we're keeping it. @end{Reason} @Syn{lhs=<constraint>,rhs="@Syn2<scalar_constraint> | @Syn2<composite_constraint>"} @Syn{lhs=<scalar_constraint>,rhs=" @Syn2{range_constraint} | @Syn2{digits_constraint} | @Syn2{delta_constraint}"} @Syn{lhs=<composite_constraint>,rhs=" @Syn2{index_constraint} | @Syn2{discriminant_constraint}"} @end{Syntax} @begin{Resolution} A @nt{subtype_mark} shall resolve to denote a subtype. @Defn2{Term=[determines], Sec=(a type by a @nt{subtype_mark})} The type @i(determined by) a @nt<subtype_mark> is the type of the subtype denoted by the @nt{subtype_mark}. @begin{Ramification} Types are never directly named; all @nt{subtype_mark}s denote subtypes @em possibly an unconstrained (base) subtype, but never the type. When we use the term @i(anonymous type) we really mean a type with no namable subtypes. @end{Ramification} @end{Resolution} @begin{RunTime} @Leading@PDefn2{Term=[elaboration], Sec=(subtype_declaration)} The elaboration of a @nt{subtype_declaration} consists of the elaboration of the @nt{subtype_indication}. @PDefn2{Term=[elaboration], Sec=(subtype_indication)} The elaboration of a @nt{subtype_indication} creates a new subtype. If the @nt{subtype_indication} does not include a @nt<constraint>, the new subtype has the same (possibly null) constraint as that denoted by the @nt{subtype_mark}. The elaboration of a @nt{subtype_indication} that includes a @nt<constraint> proceeds as follows: @begin{itemize} The @nt<constraint> is first elaborated. @IndexCheck{Range_Check} A check is then made that the @nt<constraint> is @i(compatible) with the subtype denoted by the @nt{subtype_mark}. @begin{Ramification} The checks associated with constraint compatibility are all Range_Checks. Discriminant_Checks and Index_Checks are associated only with checks that a value satisfies a constraint. @end{Ramification} @end{itemize} The condition imposed by a @nt<constraint> is the condition obtained after elaboration of the @nt<constraint>. @RootDefn2{Term=[compatibility], Sec=(constraint with a subtype)} The rules defining compatibility are given for each form of @nt<constraint> in the appropriate subclause. These rules are such that if a @nt<constraint> is @i(compatible) with a subtype, then the condition imposed by the @nt<constraint> cannot contradict any condition already imposed by the subtype on its values. @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if any check of compatibility fails. @begin{Honest} The condition imposed by a @nt<constraint> is named after it @em a @nt<range_constraint> imposes a range constraint, etc. @end{Honest} @begin{Ramification} A @nt<range_constraint> causes freezing of its type. Other @nt<constraint>s do not. @end{Ramification} @end{RunTime} @begin{Notes} A @nt<scalar_constraint> may be applied to a subtype of an appropriate scalar type (see @RefSecNum{Scalar Types}, @RefSecNum{Fixed Point Types}, and @RefSecNum{Reduced Accuracy Subtypes}), even if the subtype is already constrained. On the other hand, a @nt<composite_constraint> may be applied to a composite subtype (or an access-to-composite subtype) only if the composite subtype is unconstrained (see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Discriminant Constraints}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of subtype declarations:) @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(subtype) Rainbow @key(is) Color @key(range) Red .. Blue; --@RI[ see @RefSecNum(Type Declarations)] @key(subtype) Red_Blue @key(is) Rainbow; @key(subtype) Int @key(is) Integer; @key(subtype) Small_Int @key(is) Integer @key(range) -10 .. 10; @key(subtype) Up_To_K @key(is) Column @key(range) 1 .. K; --@RI[ see @RefSecNum(Type Declarations)] @key(subtype) Square @key(is) Matrix(1 .. 10, 1 .. 10); --@RI[ see @RefSecNum(Array Types)] @key(subtype) Male @key(is) Person(Sex => M); --@RI[ see @RefSecNum(Incomplete Type Declarations)]@Chg{Version=[2],New=[ @key(subtype) Binop_Ref @key(is not null) Binop_Ptr; --@RI[ see @RefSecNum(Access Types)]],Old=[]} @end(Example) @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 95, all @nt<range_constraint>s cause freezing of their type. Hence, a type-related representation item for a scalar type has to precede any @nt<range_constraint>s whose type is the scalar type. @end{Incompatible83} @begin{DiffWord83} @nt{Subtype_mark}s allow only subtype names now, since types are never directly named. There is no need for RM83-3.3.2(3), which says a @nt{subtype_mark} can denote both the type and the subtype; in Ada 95, you denote an unconstrained (base) subtype if you want, but never the type. The syntactic category @ntf{type_mark} is now called @nt{subtype_mark}, since it always denotes a subtype. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An optional @nt{null_exclusion} can be used in a @nt{subtype_indication}. This is described in @RefSecNum{Access Types}]} @end{Extend95} @LabeledSubClause{Classification of Operations} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{operates on a type} An operation @i(operates on a type) @i(T) if it yields a value of type @i(T), if it has an operand whose expected type (see @RefSecNum{The Context of Overload Resolution}) is @i(T), or if it has an access parameter@Chg{Version=[2],New=[ or access result type],Old=[]} (see @RefSecNum(Subprogram Declarations)) designating @i(T). @Defn2{Term=[predefined operation], Sec=(of a type)} A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a @i(predefined operation) of the type. @Defn2{Term=[primitive operations], Sec=(of a type)} The @i(primitive operations) of a type are the predefined operations of the type, plus any user-defined primitive subprograms. @ToGlossary{Term=<Primitive operations>, Text=<The primitive operations of a type are the operations (such as subprograms) declared together with the type declaration. They are inherited by other types in the same class of types. For a tagged type, the primitive subprograms are dispatching subprograms, providing run-time polymorphism. A dispatching subprogram may be called with statically tagged operands, in which case the subprogram body invoked is determined at compile time. Alternatively, a dispatching subprogram may be called using a dispatching call, in which case the subprogram body invoked is determined at run time.>} @begin{Honest} Protected subprograms are not considered to be @lquotes@;primitive subprograms,@rquotes@; even though they are subprograms, and they are inherited by derived types. @end{Honest} @begin{Discussion} We use the term @lquotes@;primitive subprogram@rquotes@; in most of the rest of the manual. The term @lquotes@;primitive operation@rquotes@; is used mostly in conceptual discussions. @end{Discussion} @Leading@Defn2{Term=[primitive subprograms], Sec=(of a type)} The @i(primitive subprograms) of a specific type are defined as follows: @begin{Itemize} The predefined operators of the type (see @RefSecNum{Operators and Expression Evaluation}); For a derived type, the inherited (see @RefSecNum{Derived Types and Classes}) user-defined subprograms; For an enumeration type, the enumeration literals (which are considered parameterless functions @em see @RefSecNum{Enumeration Types}); For a specific type declared immediately within a @nt<package_specification>, any subprograms (in addition to the enumeration literals) that are explicitly declared immediately within the same @nt<package_specification> and that operate on the type; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00200-01]} @Defn2{Term=[override], Sec=(a primitive subprogram)} @Chg{Version=[2],New=[For a nonformal type, any],Old=[Any]} subprograms not covered above @Redundant[that are explicitly declared immediately within the same declarative region as the type] and that override (see @RefSecNum{Visibility}) other implicitly declared primitive subprograms of the type. @end{Itemize} @begin{Discussion} In Ada 83, only subprograms declared in the visible part were @lquotes@;primitive@rquotes@; (i.e. derivable). In Ada 95, mostly because of child library units, we include all operations declared in the private part as well, and all operations that override implicit declarations. @end{Discussion} @begin{Ramification} It is possible for a subprogram to be primitive for more than one type, though it is illegal for a subprogram to be primitive for more than one tagged type. See @RefSecNum(Tagged Types and Type Extensions). @end{Ramification} @begin(Discussion) The order of the implicit declarations when there are both predefined operators and inherited subprograms is described in @RefSec(Derived Types and Classes). @end(Discussion) @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00200-01]} @ChgAdded{Version=[2],Text=[Subprograms declared in a generic package specification are never primitive for a formal type, even if they happen to override an operation of the formal type. This includes formal subprograms, which are never primitive operations (that's true even for an abstract formal subprogram).]} @end{Ramification} @Defn2{Term=[primitive operator], Sec=(of a type)} A primitive subprogram whose designator is an @nt<operator_symbol> is called a @i(primitive operator). @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The attribute S'Base is no longer defined for non-scalar subtypes. Since this was only permitted as the prefix of another attribute, and there are no interesting non-scalar attributes defined for an unconstrained composite or access subtype, this should not affect any existing programs. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The primitive subprograms (derivable subprograms) include subprograms declared in the private part of a package specification as well, and those that override implicitly declared subprograms, even if declared in a body. @end{Extend83} @begin{DiffWord83} We have dropped the confusing term @i<operation of a type> in favor of the more useful @i<primitive operation of a type> and the phrase @i<operates on a type>. The description of S'Base has been moved to @RefSec{Scalar Types} because it is now defined only for scalar types. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00200-01]} @ChgAdded{Version=[2],Text=[Clarified that a formal subprogram that happens to override a primitive operation of a formal type is not a primitive operation (and thus not a dispatching operation) of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added wording to include access result types in the kinds of operations that operate on a type T.]} @end{DiffWord95} @LabeledClause{Objects and Named Numbers} @begin{Intro} @redundant[Objects are created at run time and contain a value of a given type. @Defn2{Term=[creation], Sec=(of an object)} An object can be created and initialized as part of elaborating a declaration, evaluating an @nt<allocator>, @nt<aggregate>, or @nt<function_call>, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary (see @RefSecNum(Completion and Finalization)).] @end{Intro} @begin{StaticSem} @Leading@keepnext@Defn{object} All of the following are objects: @ToGlossary{Term=<Object>, Text=<An object is either a constant or a variable. An object contains a value. An object is created by an @nt(object_declaration) or by an @nt(allocator). A formal parameter is (a view of) an object. A subcomponent of an object is an object.>} @begin(itemize) the entity declared by an @nt<object_declaration>; a formal parameter of a subprogram, entry, or generic subprogram; a generic formal object; a loop parameter; a choice parameter of an @nt<exception_handler>; an entry index of an @nt<entry_body>; the result of dereferencing an access-to-object value (see @RefSecNum{Names}); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} the @Chg{Version=[2],New=[return object created as the ],Old=[]}result of evaluating a @nt<function_call> (or the equivalent operator invocation @em see @RefSecNum{Overloading of Operators}); the result of evaluating an @nt<aggregate>; a component, slice, or view conversion of another object. @end(itemize) @Defn{constant} @Defn{variable} @Defn{constant object} @Defn{variable object} @Defn{constant view} @Defn{variable view} An object is either a @i(constant) object or a @i(variable) object. The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed. Similarly, a view of an object is either a @i(constant) or a @i(variable). All views of a constant object are constant. A constant view of a variable object cannot be used to modify the value of the variable. The terms constant and variable by themselves refer to constant and variable views of objects. @Defn2{Term=[read], Sec=(the value of an object)} The value of an object is @i(read) when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. @Defn2{Term=[update], Sec=(the value of an object)} The value of a variable is @i(updated) when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object. @begin{Ramification} Reading and updating are intended to include read/write references of any kind, even if they are not associated with the evaluation of a particular construct. Consider, for example, the expression @lquotes@;X.@key[all](F)@rquotes@;, where X is an access-to-array object, and F is a function. The implementation is allowed to first evaluate @lquotes@;X.@key[all]@rquotes@; and then F. Finally, a read is performed to get the value of the F'th component of the array. Note that the array is not necessarily read as part of the evaluation of @lquotes@;X.@key[all]@rquotes@;. This is important, because if F were to free X using Unchecked_Deallocation, we want the execution of the final read to be erroneous. @end{Ramification} @Leading@;Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants: @begin(itemize) an object declared by an @nt<object_declaration> with the reserved word @key(constant); @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[We mean the word @key{constant} as defined by the grammar for @nt{object_declaration}, not some random word @key{constant}. Thus,]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[X : @key{access constant} T;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[is not a constant.]} @end{Honest} a formal parameter or generic formal object of mode @key(in); a discriminant; a loop parameter, choice parameter, or entry index; the dereference of an access-to-constant value; the result of evaluating a @nt<function_call> or an @nt<aggregate>; a @nt<selected_component>, @nt<indexed_component>, @nt<slice>, or view conversion of a constant. @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00114-01]} @ChgNote{This is just wrong, even for Ada 95.} @ChgDeleted{Version=[2],Text=[A noninvertible view conversion to a general access type is also defined to be a constant @em see @RefSecNum(Type Conversions).]} @end{Honest} @end(itemize) @Defn{nominal subtype} At the place where a view of an object is defined, a @i(nominal subtype) is associated with the view. @Defn{actual subtype} @IndexSee{Term=[subtype (of an object)],See=(actual subtype of an object)} The object's @i(actual subtype) (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an @i(indefinite subtype). @Defn{indefinite subtype} @Defn{definite subtype} A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see @RefSecNum(Discriminants)); otherwise the subtype is a @i{definite} subtype @Redundant[(all elementary subtypes are definite subtypes)]. @redundant[A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional @nt<constraint> or explicit initialization @nt<expression> is necessary (see @RefSecNum(Object Declarations)). A component cannot have an indefinite nominal subtype.] @Defn{named number} A @i(named number) provides a name for a numeric value known at compile time. It is declared by a @nt<number_declaration>. @end{StaticSem} @begin{Notes} A constant cannot be the target of an assignment operation, nor be passed as an @key(in) @key(out) or @key(out) parameter, between its initialization and finalization, if any. The nominal and actual subtypes of an elementary object are always the same. For a discriminated or array object, if the nominal subtype is constrained then so is the actual subtype. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} There are additional kinds of objects (choice parameters and entry indices of entry bodies). The result of a function and of evaluating an aggregate are considered (constant) objects. This is necessary to explain the action of finalization on such things. Because a @nt<function_call> is also syntactically a @nt<name> (see @RefSecNum(Names)), the result of a @nt{function_call} can be renamed, thereby allowing repeated use of the result without calling the function again. @end{Extend83} @begin{DiffWord83} This clause and its subclauses now follow the clause and subclauses on types and subtypes, to cut down on the number of forward references. The term nominal subtype is new. It is used to distinguish what is known at compile time about an object's constraint, versus what its "true" run-time constraint is. The terms definite and indefinite (which apply to subtypes) are new. They are used to aid in the description of generic formal type matching, and to specify when an explicit initial value is required in an @nt<object_declaration>. We have moved the syntax for @nt<object_declaration> and @nt<number_declaration> down into their respective subclauses, to keep the syntax close to the description of the associated semantics. We talk about variables and constants here, since the discussion is not specific to @nt<object_declaration>s, and it seems better to have the list of the kinds of constants juxtaposed with the kinds of objects. We no longer talk about indirect updating due to parameter passing. Parameter passing is handled in 6.2 and 6.4.1 in a way that there is no need to mention it here in the definition of read and update. Reading and updating now includes the case of evaluating or assigning to an enclosing object. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Clarified that the return object is the object created by a function call.]} @end{DiffWord95} @LabeledSubClause{Object Declarations} @begin{Intro} @RootDefn{stand-alone object} @Defn{explicit initial value} @Defn{initialization expression} An @nt<object_declaration> declares a @i(stand-alone) object with a given nominal subtype and, optionally, an explicit initial value given by an initialization expression. @Defn{anonymous array type} @Defn{anonymous task type} @Defn{anonymous protected type} For an array, task, or protected object, the @nt<object_declaration> may include the definition of the (anonymous) type of the object. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01],ARef=[AI95-00406-01]} @Syn{lhs=<object_declaration>,rhs=" @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{subtype_indication} [:= @Syn2{expression}];@Chg{Version=[2],New=< | @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{access_definition} [:= @Syn2{expression}];>,Old=<>} | @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{array_type_definition} [:= @Syn2{expression}]; | @Syn2{single_task_declaration} | @Syn2{single_protected_declaration}"} @Syn{lhs=<defining_identifier_list>,rhs=" @Syn2{defining_identifier} {, @Syn2{defining_identifier}}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(object_declaration initialization expression)} For an @nt<object_declaration> with an @nt<expression> following the compound delimiter :=, the type expected for the @nt<expression> is that of the object. @Defn{initialization expression} This @nt<expression> is called the @i(initialization expression). @IndexSee{Term=[constructor],See=[initialization expression]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} An @nt<object_declaration> without the reserved word @key(constant) declares a variable object. If it has a @nt<subtype_indication> or an @nt<array_type_definition> that defines an indefinite subtype, then there shall be an initialization expression.@Chg{Version=[2],New=[],Old=[ An initialization expression shall not be given if the object is of a limited type.]} @end{Legality} @begin{StaticSem} An @nt<object_declaration> with the reserved word @key(constant) declares a constant object. @Defn{full constant declaration} If it has an initialization expression, then it is called a @i(full constant declaration). @Defn{deferred constant declaration} Otherwise it is called a @i(deferred constant declaration). The rules for deferred constant declarations are given in clause @RefSecNum(Deferred Constants). The rules for full constant declarations are given in this subclause. Any declaration that includes a @nt{defining_identifier_list} with more than one @nt{defining_identifier} is equivalent to a series of declarations each containing one @nt{defining_identifier} from the list, with the rest of the text of the declaration copied for each declaration in the series, in the same order as the list. The remainder of this International Standard relies on this equivalence; explanations are given for declarations with a single @nt<defining_identifier>. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} @Defn{nominal subtype} The @nt<subtype_indication>@Chg{Version=[2],New=[, @nt{access_definition},],Old=[]} or full type definition of an @nt<object_declaration> defines the nominal subtype of the object. The @nt<object_declaration> declares an object of the type of the nominal subtype. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The phrase @lquotes@;full type definition@rquotes@; here includes the case of an anonymous array, @Chg{Version=[2],New=[access, ],Old=[]}task, or protected type. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[@Defn{requires late initialization} A component of an object is said to @i{require late initialization} if it has an access discriminant value constrained by a per-object expression, or if it has an initialization expression that includes a name denoting the current instance of the type or denoting an access discriminant.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such components can depend on the values of other components of the object. We want to initialize them as late and as reproducibly as possible.]} @end{Reason} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @Defn2{Term=[constraint], Sec=(of an object)} If a composite object declared by an @nt{object_declaration} has an unconstrained nominal subtype, then if this subtype is indefinite or the object is constant @Chg{Version=[2],New=[], Old=[or aliased (see @RefSecNum(Access Types)) ]}the actual subtype of this object is constrained. The constraint is determined by the bounds or discriminants (if any) of its initial value; @Defn{constrained by its initial value} the object is said to be @i(constrained by its initial value). @Defn2{Term=[actual subtype], Sec=(of an object)} @IndexSee{Term=[subtype (of an object)],See=(actual subtype of an object)} @Chg{Version=[2],New=[], Old=[@Redundant[In the case of an aliased object, this initial value may be either explicit or implicit; in the other cases, an explicit initial value is required.] ]}When not constrained by its initial value, the actual and nominal subtypes of the object are the same. @Defn2{Term=[constrained], Sec=(object)} @Defn2{Term=[unconstrained], Sec=(object)} If its actual subtype is constrained, the object is called a @i(constrained object). @Leading@Defn2{Term=[implicit initial values], Sec=(for a subtype)} For an @nt<object_declaration> without an initialization expression, any initial values for the object or its subcomponents are determined by the @i(implicit initial values) defined for its nominal subtype, as follows: @begin(itemize) The implicit initial value for an access subtype is the null value of the access type. The implicit initial (and only) value for each discriminant of a constrained discriminated subtype is defined by the subtype. For a (definite) composite subtype, the implicit initial value of each component with a @nt<default_expression> is obtained by evaluation of this expression and conversion to the component's nominal subtype (which might raise Constraint_Error @em see @RefSec{Type Conversions}), unless the component is a discriminant of a constrained subtype (the previous case), or is in an excluded @nt<variant> (see @RefSecNum(Variant Parts and Discrete Choices)). @PDefn2{Term=[implicit subtype conversion],Sec=(component defaults)} For each component that does not have a @nt<default_expression>, any implicit initial values are those determined by the component's nominal subtype. For a protected or task subtype, there is an implicit component (an entry queue) corresponding to each entry, with its implicit initial value being an empty queue. @begin(ImplNote) The implementation may add implicit components for its own use, which might have implicit initial values. For a task subtype, such components might represent the state of the associated thread of control. For a type with dynamic-sized components, such implicit components might be used to hold the offset to some explicit component. @end(ImplNote) @end(itemize) @Leading@PDefn2{Term=[elaboration], Sec=(object_declaration)} The elaboration of an @nt{object_declaration} proceeds in the following sequence of steps: @begin(enumerate) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The @nt{subtype_@!indication},@Chg{Version=[2],New=[ @nt{access_@!definition},],Old=[]} @nt<array_@!type_@!definition>, @nt{single_@!task_@!declaration}, or @nt{single_@!protected_@!declaration} is first elaborated. This creates the nominal subtype (and the anonymous type in the @Chg{Version=[2],New=[last four],Old=[latter three]} cases). If the @nt<object_declaration> includes an initialization expression, the (explicit) initial value is obtained by evaluating the expression and converting it to the nominal subtype (which might raise Constraint_Error @em see @RefSecNum(Type Conversions)). @PDefn2{Term=[implicit subtype conversion],Sec=(initialization expression)} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} The object is created, and, if there is not an initialization expression, @Chg{Version=[2],New=[the object is @i{initialized by default}. @Defn{initialized by default}When an object is initialized by default, ],Old=[]}any per-object @Chg{New=[constraints],Old=[expressions]} (see @RefSecNum(Record Types)) are @Chg{New=[elaborated], Old=[evaluated]} and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype.@Chg{Version=[2],New=[ @Defn2{Term=[initialization], Sec=(of an object)} @Defn2{Term=[assignment operation], Sec=(during elaboration of an @nt{object_declaration})} Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in @RefSecNum{Assignment Statements} and @RefSecNum{User-Defined Assignment and Finalization}, Initialize and Adjust procedures can be called. @IndexSee{Term=[constructor],See=[initialization]}],Old=[]} @begin(Discussion) For a per-object constraint that contains some per-object expressions and some non-per-object expressions, the values used for the constraint consist of the values of the non-per-object expressions evaluated at the point of the @nt{type_declaration}, and the values of the per-object expressions evaluated at the point of the creation of the object. The elaboration of per-object constraints was presumably performed as part of the dependent compatibility check in Ada 83. If the object is of a limited type with an access discriminant, the @nt<access_definition> is elaborated at this time (see @RefSecNum(Discriminants)). @end(Discussion) @begin{Reason} The reason we say that evaluating an explicit initialization expression happens before creating the object is that in some cases it is impossible to know the size of the object being created until its initial value is known, as in @lquotes@;X: String := Func_Call(...);@rquotes@;. The implementation can create the object early in the common case where the size can be known early, since this optimization is semantically neutral. @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00373-01]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[initialization], Sec=(of an object)} @Defn2{Term=[assignment operation], Sec=(during elaboration of an @nt{object_declaration})} Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in @RefSecNum{Assignment Statements} and @RefSecNum{User-Defined Assignment and Finalization}, Initialize and Adjust procedures can be called. @IndexSee{Term=[constructor],See=[initialization]}]} @begin(Ramification) Since the initial values have already been converted to the appropriate nominal subtype, the only Constraint_Errors that might occur as part of these assignments are for values outside their base range that are used to initialize unconstrained numeric subcomponents. See @RefSecNum{Scalar Types}. @end(Ramification) @end(enumerate) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Just to get conditional Leading here.} For the third step above, @Chg{Version=[2],New=[],Old=[the object creation and any elaborations and ]}evaluations @Chg{Version=[2],New=[and assignments ],Old=[]}are performed in an arbitrary order@Chg{Version=[2],New=[ subject to the following restrictions:],Old=[, except that if the @nt<default_expression> for a discriminant is evaluated to obtain its initial value, then this evaluation is performed before that of the @nt<default_expression> for any component that depends on the discriminant, and also before that of any @nt<default_expression> that includes the name of the discriminant. The evaluations of the third step and the assignments of the fourth step are performed in an arbitrary order, except that each evaluation is performed before the resulting value is assigned.]} @begin(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Assignment to any part of the object is preceded by the evaluation of the value that is to be assigned.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Duh. But we ought to say it. Note that, like any rule in the International Standard, it doesn't prevent an @lquotes@;as-if@rquotes optimization; as long as the semantics as observed from the program are correct, the compiler can generate any code it wants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The evaluation of a @nt{default_expression} that includes the name of a discriminant is preceded by the assignment to that discriminant.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Duh again. But we have to say this, too. It's odd that Ada 95 only required the default expressions to be evaluated before the discriminant is used; it says nothing about discriminant values that come from @nt{subtype_indication}s.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The evaluation of the @nt{default_expression} for any component that depends on a discriminant is preceded by the assignment to that discriminant.]} @begin{Reason} @Leading@keepnext@;For example: @begin{Example} @key[type] R(D : Integer := F) @key[is] @key[record] S : String(1..D) := (@key[others] => G); @key[end] @key[record]; X : R; @end{Example} For the elaboration of the declaration of X, it is important that F be evaluated before the aggregate. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The assignments to any components, including implicit components, not requiring late initialization must precede the initial value evaluations for any components requiring late initialization; if two components both require late initialization, then assignments to parts of the component occurring earlier in the order of the component declarations must precede the initial value evaluations of the component occurring later.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Components that require late initialization can refer to the entire object during their initialization. We want them to be initialized as late as possible to reduce the chance that their initialization depends on uninitialized components. For instance:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} T (D : Natural) @key{is} @key{limited record} C1 : T1 (T'Access); C2 : Natural := F (D); C3 : String (1 .. D) := (others => ' '); @key{end record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Component C1 requires late initialization. The initialization could depend on the values of any component of T, including D, C2, or C3. Therefore, we want to it to be initialized last. Note that C2 and C3 do not require late initialization; they only have to be initialized after D.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is possible for there to be more than one component that requires late initialization. In this case, the language can't prevent problems, because all of the components can't be the last one initialized. In this case, we specify the order of initialization for components requiring late initialization; by doing so, programmers can arrange their code to avoid accessing uninitialized components, and such arrangements are portable. Note that if the program accesses an uninitialized component, @RefSecNum{Data Validity} defines the execution to be erroneous.]} @end{Reason} @end{Itemize} @Redundant[There is no implicit initial value defined for a scalar subtype.] @PDefn{uninitialized variables} In the absence of an explicit initialization, a newly created scalar object might have a value that does not belong to its subtype (see @RefSecNum{Data Validity} and @RefSecNum{Pragma Normalize_Scalars}). @begin{Honest} It could even be represented by a bit pattern that doesn't actually represent any value of the type at all, such as an invalid internal code for an enumeration type, or a NaN for a floating point type. It is a generally a bounded error to reference scalar objects with such @lquotes@;invalid representations@rquotes@;, as explained in @RefSec{Data Validity}. @end{Honest} @begin{Ramification} There is no requirement that two objects of the same scalar subtype have the same implicit initial @lquotes@;value@rquotes@; (or representation). It might even be the case that two elaborations of the same @nt{object_declaration} produce two different initial values. However, any particular uninitialized object is default-initialized to a single value (or invalid representation). Thus, multiple reads of such an uninitialized object will produce the same value each time (if the implementation chooses not to detect the error). @end{Ramification} @end{RunTime} @begin{Notes} Implicit initial values are not defined for an indefinite subtype, because if an object's nominal subtype is indefinite, an explicit initial value is required. @Defn{stand-alone constant} @Defn{stand-alone variable} As indicated above, a stand-alone object is an object declared by an @nt<object_declaration>. Similar definitions apply to @lquotes@;stand-alone constant@rquotes@; and @lquotes@;stand-alone variable.@rquotes@; A subcomponent of an object is not a stand-alone object, nor is an object that is created by an @nt<allocator>. An object declared by a @nt<loop_parameter_specification>, @nt<parameter_specification>, @nt<entry_index_specification>, @nt<choice_parameter_specification>, or a @nt<formal_object_declaration> is not called a stand-alone object. The type of a stand-alone object cannot be abstract (see @RefSecNum{Abstract Types and Subprograms}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a multiple object declaration:) @begin(Example) --@RI[ the multiple object declaration ] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} John, Paul : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); --@RI[ see @RefSecNum(Incomplete Type Declarations)] --@RI[ is equivalent to the two single object declarations in the order given] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} John : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); Paul : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); @end(Example) @begin{Wide} @leading@keepnext@i(Examples of variable declarations:) @end{Wide} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Count, Sum : Integer; Size : Integer @key(range) 0 .. 10_000 := 0; Sorted : Boolean := False; Color_Table : @key(array)(1 .. Max) @key(of) Color; Option : Bit_Vector(1 .. 10) := (@key(others) => True); Hello : @Chg{Version=[2],New=[@key(aliased)],Old=[@key(constant)]} String := "Hi, world.";@Chg{Version=[2],New=[ @unicode(952), @unicode(966) : Float @b<range> -@pi .. +@pi;],Old=[]} @end(Example) @begin{Wide} @leading@keepnext@i(Examples of constant declarations:) @end{Wide} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Limit : @key(constant) Integer := 10_000; Low_Limit : @key(constant) Integer := Limit/10; Tolerance : @key(constant) Real := Dispersion(1.15);@Chg{Version=[2],New=[ Hello_Msg : @key(constant access) String := Hello'Access; --@RI[ see @RefSecNum{Operations of Access Types}]],Old=[]} @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{object_declaration} is modified to allow the @key{aliased} reserved word. A variable declared by an @nt<object_declaration> can be constrained by its initial value; that is, a variable of a nominally unconstrained array subtype, or discriminated type without defaults, can be declared so long as it has an explicit initial value. In Ada 83, this was permitted for constants, and for variables created by allocators, but not for variables declared by @nt<object_declaration>s. This is particularly important for tagged class-wide types, since there is no way to constrain them explicitly, and so an initial value is the only way to provide a constraint. It is also important for generic formal private types with unknown discriminants. We now allow an @nt{unconstrained_array_definition} in an @nt{object_declaration}. This allows an object of an anonymous array type to have its bounds determined by its initial value. This is for uniformity: If one can write @lquotes@;X: @key[constant] @key[array](Integer @key[range] 1..10) @key[of] Integer := ...;@rquotes@; then it makes sense to also allow @lquotes@;X: @key[constant] @key[array](Integer @key[range] <>) @key[of] Integer := ...;@rquotes@;. (Note that if anonymous array types are ever sensible, a common situation is for a table implemented as an array. Tables are often constant, and for constants, there's usually no point in forcing the user to count the number of elements in the value.) @end{Extend83} @begin{DiffWord83} We have moved the syntax for @nt{object_declaration}s into this subclause. Deferred constants no longer have a separate syntax rule, but rather are incorporated in @nt<object_declaration> as constants declared without an initialization expression. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Unconstrained aliased objects of types with discriminants with defaults are no longer constrained by their initial values. This means that a program that raised Constraint_Error from an attempt to change the discriminants will no longer do so. The change only affects programs that depended on the raising of Constraint_Error in this case, so the inconsistency is unlikely to occur outside of the ACATS. This change may however cause compilers to implement these objects differently, possibly taking additional memory or time. This is unlikely to be worse than the differences caused by any major compiler upgrade.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A constant may have a limited type; the initialization @nt{expression} has to be built-in-place (see @RefSecNum{Limited Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01],ARef=[AI95-00406-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A stand-alone object may have an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected wording to say that per-object constraints are elaborated (not evaluated).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The rules for evaluating default initialization have been tightened. In particular, components whose default initialization can refer to the rest of the object are required to be initialized last.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[Added examples of various new constructs.]} @end{DiffWord95} @LabeledSubClause{Number Declarations} @begin{Intro} A @nt<number_declaration> declares a named number. @begin{Discussion} @Defn{static} If a value or other property of a construct is required to be @i(static) that means it is required to be determined prior to execution. A @i(static) expression is an expression whose value is computed at compile time and is usable in contexts where the actual value might affect the legality of the construct. This is fully defined in clause @RefSecNum(Static Expressions and Static Subtypes). @end{Discussion} @end{Intro} @begin{Syntax} @Syn{lhs=<number_declaration>,rhs=" @Syn2{defining_identifier_list} : @key{constant} := @SynI{static_}@Syn2{expression};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(number_declaration expression)} The @SynI(static_)@nt{expression} given for a @nt{number_declaration} is expected to be of any numeric type. @end{Resolution} @begin{Legality} The @i(static_)@nt{expression} given for a number declaration shall be a static expression, as defined by clause @RefSecNum(Static Expressions and Static Subtypes). @end{Legality} @begin{StaticSem} The named number denotes a value of type @i(universal_integer) if the type of the @i(static_)@!@nt{expression} is an integer type. The named number denotes a value of type @i(universal_real) if the type of the @i(static_)@!@nt{expression} is a real type. The value denoted by the named number is the value of the @i(static_)@nt{expression}, converted to the corresponding universal type. @PDefn2{Term=[implicit subtype conversion],Sec=(named number value)} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(number_declaration)} The elaboration of a @nt<number_declaration> has no effect. @begin(TheProof) Since the @i(static_)@nt<expression> was evaluated at compile time. @end(TheProof) @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of number declarations:) @begin(Example) Two_Pi : @key(constant) := 2.0*Ada.Numerics.Pi; --@RI[ a real number (see @RefSecNum{The Numerics Packages})] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Max : @key(constant) := 500; --@RI[ an integer number] Max_Line_Size : @key(constant) := Max/6@Chg{Version=[2],New=[;],Old=[ ]} --@RI[ the integer 83] Power_16 : @key(constant) := 2**16; --@RI[ the integer 65_536] One, Un, Eins : @key(constant) := 1; --@RI[ three different names for 1] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now allow a static expression of any numeric type to initialize a named number. For integer types, it was possible in Ada 83 to use 'Pos to define a named number, but there was no way to use a static expression of some non-universal real type to define a named number. This change is upward compatible because of the preference rule for the operators of the root numeric types. @end{Extend83} @begin{DiffWord83} We have moved the syntax rule into this subclause. AI83-00263 describes the elaboration of a number declaration in words similar to that of an @nt{object_declaration}. However, since there is no expression to be evaluated and no object to be created, it seems simpler to say that the elaboration has no effect. @end{DiffWord83} @LabeledClause{Derived Types and Classes} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @Defn{derived type} A @nt<derived_type_definition> defines a @Chg{Version=[2], New=[@i{derived type}],Old=[new type]} (and its first subtype) whose characteristics are @i(derived) from those of a @Chg{Version=[2],New=[parent type, and possibly from progenitor types], Old=[@i(parent type)]}. @IndexSee{Term=[inheritance],See=[derived types and classes]} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Derived type>, Text=<A derived type is a type defined in terms of @Chg{Version=[2], New=[one or more other types given in a derived type definition. The first of those types],Old=[another type, which]} is the parent type of the derived type@Chg{Version=[2],New=[ and any others are progenitor types],Old=[]}. Each class containing the parent type @Chg{Version=[2],New=[or a progenitor type ],Old=[]}also contains the derived type. The derived type inherits properties such as components and primitive operations from the parent@Chg{Version=[2],New=[ and progenitors],Old=[]}. A type together with the types derived from it (directly or indirectly) form a derivation class.>} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[class],Sec=[of types]} @Defn2{Term=[category],Sec=[of types]} A @i<class of types> is a set of types that is closed under derivation; that is, if the parent or a progenitor type of a derived type belongs to a class, then so does the derived type. By saying that a particular group of types forms a class, we are saying that all derivatives of a type in the set inherit the characteristics that define that set. The more general term @i<category of types> is used for a set of types whose defining characteristics are not necessarily inherited by derivatives; for example, limited, abstract, and interface are all categories of types, but not classes of types.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A class of types is also a category of types.]} @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01]} @Syn{lhs=<derived_type_definition>,rhs="@Chg{Version=[2],New=< >,Old=<>}[@key{abstract}] @Chg{Version=[2],New=<[@key{limited}] >,Old=<>}@key{new} @SynI{parent_}@Syn2{subtype_indication} [@Chg{Version=[2],New=<[@key{and} @Syn2{interface_list}] >,Old=<>}@Syn2{record_extension_part}]"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @Defn{parent subtype} @Defn{parent type} The @Syni(parent_)@nt<subtype_indication> defines the @i(parent subtype); its type is the @Chg{Version=[2],New=[@i(parent type)],Old=[parent type]}. @Chg{Version=[2],New=[The @nt{interface_list} defines the progenitor types (see @RefSecNum{Interface Types}). A derived type has one parent type and zero or more progenitor types.],Old=[]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Parent>, Text=<@ChgAdded{Version=[2],Text=[The parent of a derived type is the first type given in the definition of the derived type. The parent can be almost any kind of type, including an interface type.]}>} A type shall be completely defined (see @RefSecNum(Completions of Declarations)) prior to being specified as the parent type in a @nt<derived_type_definition> @em @Redundant[the @nt<full_type_declaration>s for the parent type and any of its subcomponents have to precede the @nt<derived_type_definition>.] @begin{Discussion} This restriction does not apply to the ancestor type of a private extension @em see @RefSecNum(Private Types and Private Extensions); such a type need not be completely defined prior to the @nt<private_extension_declaration>. However, the restriction does apply to record extensions, so the ancestor type will have to be completely defined prior to the @nt<full_type_declaration> corresponding to the @nt<private_extension_declaration>. @end{Discussion} @begin{Reason} We originally hoped we could relax this restriction. However, we found it too complex to specify the rules for a type derived from an incompletely defined limited type that subsequently became nonlimited. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @Defn{record extension} If there is a @nt<record_extension_part>, the derived type is called a @i(record extension) of the parent type. A @nt<record_extension_part> shall be provided if and only if the parent type is a tagged type.@Chg{Version=[2],New=[ @Redundant[An @nt{interface_list} shall be provided only if the parent type is a tagged type.]],Old=[]} @begin(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[The syntax only allows an @nt{interface_list} to appear with a @nt{record_extension_part}, and a @nt{record_extension_part} can only be provided if the parent type is a tagged type. We give the last sentence anyway for completeness.]} @end(TheProof) @begin(ImplNote) We allow a record extension to inherit discriminants; an early version of Ada 9X did not. If the parent subtype is unconstrained, it can be implemented as though its discriminants were repeated in a new @nt{known_discriminant_part} and then used to constrain the old ones one-for-one. However, in an extension aggregate, the discriminants in this case do not appear in the component association list. @end(ImplNote) @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Conditional leading} This rule needs to be rechecked in the visible part of an instance of a generic unit@Chg{Version=[2],New=[ because of the @lquotes@;only if@rquotes@; part of the rule. For example:],Old=[]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T @key{is private}; @key{package} P @key{is} @key{type} Der @key{is new} T; @key{end} P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} I @key{is new} P (Some_Tagged_Type); -- @RI[illegal]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[The instantiation is illegal because a tagged type is being extended in the visible part without a @nt{record_extension_part}. Note that this is legal in the private part or body of an instance, both to avoid a contract model violation, and because no code that can see that the type is actually tagged can also see the derived type declaration.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[No recheck is needed for derived types with a @nt{record_extension_part}, as that has to be derived from something that is known to be tagged (otherwise the template is illegal).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[If the reserved word @key{limited} appears in a @nt{derived_type_definition}, the parent type shall be a limited type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow @key{limited} because we don't inherit limitedness from interfaces, so we must have a way to derive a limited type from interfaces. The word @key{limited} has to be legal when the parent @i{could be} an interface, and that includes generic formal abstract types. Since we have to allow it in this case, we might as well allow it everywhere as documentation, to make it explicit that the type is limited.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[However, we do not want to allow @key{limited} when the parent is nonlimited: limitedness cannot change in a derivation tree.]} @end{Reason} @end{Legality} @begin{StaticSem} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} The first subtype of the derived type is unconstrained if a @nt{known_discriminant_part} is provided in the declaration of the derived type, or if the parent subtype is unconstrained. @Defn{corresponding constraint} Otherwise, the constraint of the first subtype @i(corresponds) to that of the parent subtype in the following sense: it is the same as that of the parent subtype except that for a range constraint (implicit or explicit), the value of each bound of its range is replaced by the corresponding value of the derived type. @begin(Discussion) A @nt<digits_constraint> in a @nt<subtype_indication> for a decimal fixed point subtype always imposes a range constraint, implicitly if there is no explicit one given. See @RefSec(Fixed Point Types). @end(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[The first subtype of the derived type excludes null (see @RefSecNum{Access Types}) if and only if the parent subtype excludes null.]} @Leading@keepnext@;The characteristics of the derived type are defined as follows: @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[@Redundant[If the parent type or a progenitor type belongs to a class of types, then the derived type also belongs to that class.] The following sets of types, as well as any higher-level sets composed from them, are classes in this sense@Redundant[, and hence the characteristics defining these classes are inherited by derived types from their parent or progenitor types]: signed integer, modular integer, ordinary fixed, decimal fixed, floating point, enumeration, boolean, character, access-to-constant, general access-to-variable, pool-specific access-to-variable, access-to-subprogram, array, string, non-array composite, nonlimited, untagged record, tagged, task, protected, and synchronized tagged], Old=[Each class of types that includes the parent type also includes the derived type]}. @begin{Discussion} This is inherent in our notion of a @lquotes@;class@rquotes@; of types. It is not mentioned in the initial definition of @lquotes@;class@rquotes@; since at that point type derivation has not been defined. In any case, this rule ensures that every class of types is closed under derivation. @end{Discussion} If the parent type is an elementary type or an array type, then the set of possible values of the derived type is a copy of the set of possible values of the parent type. For a scalar type, the base range of the derived type is the same as that of the parent type. @begin{Discussion} The base range of a type defined by an @nt<integer_type_definition> or a @nt<real_type_definition> is determined by the @ntf<_definition>, and is not necessarily the same as that of the corresponding root numeric type from which the newly defined type is implicitly derived. Treating numerics types as implicitly derived from one of the two root numeric types is simply to link them into a type hierarchy; such an implicit derivation does not follow all the rules given here for an explicit @nt<derived_type_definition>. @end{Discussion} If the parent type is a composite type other than an array type, then the components, protected subprograms, and entries that are declared for the derived type are as follows: @begin(inneritemize) The discriminants specified by a new @nt{known_discriminant_part}, if there is one; otherwise, each discriminant of the parent type (implicitly declared in the same order with the same specifications) @em @Defn{inherited discriminant} @Defn{inherited component} in the latter case, the discriminants are said to be @i(inherited), or if unknown in the parent, are also unknown in the derived type; Each nondiscriminant component, entry, and protected subprogram of the parent type, implicitly declared in the same order with the same declarations; @Defn{inherited component} @Defn{inherited protected subprogram} @Defn{inherited entry} these components, entries, and protected subprograms are said to be @i(inherited); @begin{Ramification} The profiles of entries and protected subprograms do not change upon type derivation, although the type of the @lquotes@;implicit@rquotes@; parameter identified by the @nt<prefix> of the @nt<name> in a call does.@end{ramification} @begin{Honest} Any name in the parent @nt{type_declaration} that denotes the current instance of the type is replaced with a name denoting the current instance of the derived type, converted to the parent type. @end{Honest} Each component declared in a @nt<record_extension_part>, if any. @end(inneritemize) @noprefix@;Declarations of components, protected subprograms, and entries, whether implicit or explicit, occur immediately within the declarative region of the type, in the order indicated above, following the parent @nt<subtype_indication>. @begin(Discussion) The order of declarations within the region matters for @nt{record_aggregate}s and @nt<extension_aggregate>s. @end(Discussion) @begin{Ramification} In most cases, these things are implicitly declared @i{immediately} following the parent @nt<subtype_indication>. However, @RefSec{Private Operations} defines some cases in which they are implicitly declared later, and some cases in which the are not declared at all. @end{Ramification} @begin{Discussion} The place of the implicit declarations of inherited components matters for visibility @em they are not visible in the @nt<known_discriminant_part> nor in the parent @nt<subtype_indication>, but are usually visible within the @nt<record_extension_part>, if any (although there are restrictions on their use). Note that a discriminant specified in a new @nt<known_discriminant_part> is not considered @lquotes@;inherited@rquotes@; even if it has the same name and subtype as a discriminant of the parent type. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00419-01]} @ChgDeleted{Version=[2],Text=[The derived type is limited if and only if the parent type is limited.]} @ChgNote{This rule is normatively in 7.5, and we don't want it scattered everywhere.} @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00419-01]} @ChgDeleted{Version=[2],Text=[The derived type can become nonlimited if the derivation takes place in the visible part of a child package, and the parent type is nonlimited as viewed from the private part of the child package @em see @RefSecNum(Limited Types).]} @end{Honest} @Redundant[For each predefined operator of the parent type, there is a corresponding predefined operator of the derived type.] @begin(TheProof) This is a ramification of the fact that each class that includes the parent type also includes the derived type, and the fact that the set of predefined operators that is defined for a type, as described in @RefSecNum(Operators and Expression Evaluation), is determined by the classes to which it belongs. @end(TheProof) @begin(Reason) Predefined operators are handled separately because they follow a slightly different rule than user-defined primitive subprograms. In particular the systematic replacement described below does not apply fully to the relational operators for Boolean and the exponentiation operator for Integer. The relational operators for a type derived from Boolean still return Standard.Boolean. The exponentiation operator for a type derived from Integer still expects Standard.Integer for the right operand. In addition, predefined operators "reemerge" when a type is the actual type corresponding to a generic formal type, so they need to be well defined even if hidden by user-defined primitive subprograms. @end(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @Defn{inherited subprogram} For each user-defined primitive subprogram (other than a user-defined equality operator @em see below) of the parent type@Chg{Version=[2],New=[ or of a progenitor type],Old=[]} that already exists at the place of the @nt{derived_type_definition}, there exists a corresponding @i(inherited) primitive subprogram of the derived type with the same defining name. @Defn2{Term=[equality operator],Sec=(special inheritance rule for tagged types)} Primitive user-defined equality operators of the parent type@Chg{Version=[2],New=[ and any progenitor types],Old=[]} are also inherited by the derived type, except when the derived type is a nonlimited record extension, and the inherited operator would have a profile that is type conformant with the profile of the corresponding predefined equality operator; in this case, the user-defined equality operator is not inherited, but is rather incorporated into the implementation of the predefined equality operator of the record extension (see @RefSecNum(Relational Operators and Membership Tests)). @PDefn{type conformance} @begin{Ramification} We say @lquotes@;...already exists...@rquotes@; rather than @lquotes@;is visible@rquotes@; or @lquotes@;has been declared@rquotes@; because there are certain operations that are declared later, but still exist at the place of the @nt{derived_type_definition}, and there are operations that are never declared, but still exist. These cases are explained in @RefSecNum{Private Operations}. Note that nonprivate extensions can appear only after the last primitive subprogram of the parent @em the freezing rules ensure this. @end{Ramification} @begin{Reason} A special case is made for the equality operators on nonlimited record extensions because their predefined equality operators are already defined in terms of the primitive equality operator of their parent type (and of the tagged components of the extension part). Inheriting the parent's equality operator as is would be undesirable, because it would ignore any components of the extension part. On the other hand, if the parent type is limited, then any user-defined equality operator is inherited as is, since there is no predefined equality operator to take its place. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Because user-defined equality operators are not inherited by @Chg{Version=[2],New=[nonlimited ],Old=[]}record extensions, the formal parameter names of = and /= revert to Left and Right, even if different formal parameter names were used in the user-defined equality operators of the parent type. @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[This rule only describes what operations are inherited; the rules that describe what happens when there are conflicting inherited subprograms are found in @RefSecNum{Visibility}.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @noprefix@;The profile of an inherited subprogram (including an inherited enumeration literal) is obtained from the profile of the corresponding (user-defined) primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type, after systematic replacement of each subtype of its profile (see @RefSecNum{Subprogram Declarations}) that is of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type with a @i(corresponding subtype) of the derived type. @Defn{corresponding subtype} For a given subtype of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type, the corresponding subtype of the derived type is defined as follows: @begin(inneritemize) If the declaration of the derived type has neither a @nt<known_discriminant_part> nor a @nt<record_extension_part>, then the corresponding subtype has a constraint that corresponds (as defined above for the first subtype of the derived type) to that of the given subtype. If the derived type is a record extension, then the corresponding subtype is the first subtype of the derived type. If the derived type has a new @nt<known_discriminant_part> but is not a record extension, then the corresponding subtype is constrained to those values that when converted to the parent type belong to the given subtype (see @RefSecNum(Type Conversions)). @PDefn2{Term=[implicit subtype conversion],Sec=(derived type discriminants)} @begin{Reason} An inherited subprogram of an untagged type has an Intrinsic calling convention, which precludes the use of the Access attribute. We preclude 'Access because correctly performing all required constraint checks on an indirect call to such an inherited subprogram was felt to impose an undesirable implementation burden. @end{Reason} @end(inneritemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @noprefix@;The same formal parameters have @nt<default_expression>s in the profile of the inherited subprogram. @Redundant[Any type mismatch due to the systematic replacement of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type by the derived type is handled as part of the normal type conversion associated with parameter passing @em see @RefSecNum(Parameter Associations).] @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} We don't introduce the type conversion explicitly here since conversions to record extensions or on access parameters are not generally legal. Furthermore, any type conversion would just be "undone" since the @Chg{Version=[2],New=[],Old=[parent's ]}subprogram @Chg{Version=[2],New=[of the parent or progenitor ],Old=[]}is ultimately being called anyway.@Chg{Version=[2],New=[ (Null procedures can be inherited from a progenitor without being overridden, so it is possible to call subprograms of an interface.)],Old=[]} @end(Reason) @end(itemize) @Comment{end of characteristics of derived type} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} If a primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor], Old=[]} type is visible at the place of the @nt{derived_type_definition}, then the corresponding inherited subprogram is implicitly declared immediately after the @nt{derived_type_definition}. Otherwise, the inherited subprogram is implicitly declared later or not at all, as explained in @RefSecNum{Private Operations}. @PDefn{derived type} A derived type can also be defined by a @nt<private_@!extension_@!declaration> (see @RefSecNum(Private Types and Private Extensions)) or a @nt<formal_@!derived_@!type_@!definition> (see @RefSecNum(Formal Private and Derived Types)). Such a derived type is a partial view of the corresponding full or actual type. All numeric types are derived types, in that they are implicitly derived from a corresponding root numeric type (see @RefSecNum(Integer Types) and @RefSecNum(Real Types)). @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(derived_type_definition)} The elaboration of a @nt<derived_type_definition> creates the derived type and its first subtype, and consists of the elaboration of the @nt<subtype_@!indication> and the @nt<record_@!extension_@!part>, if any. If the @nt{subtype_@!indication} depends on a discriminant, then only those expressions that do not depend on a discriminant are evaluated. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[We don't mention the @nt{interface_list}, because it does not need elaboration (see @RefSecNum{Interface Types}. This is consistent with the handling of @nt{discriminant_part}s, which aren't elaborated either.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01],ARef=[AI95-00401-01]} @PDefn2{Term=[execution], Sec=(call on an inherited subprogram)} For the execution of a call on an inherited subprogram, a call on the corresponding primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type is performed; the normal conversion of each actual parameter to the subtype of the corresponding formal parameter (see @RefSecNum(Parameter Associations)) performs any necessary type conversion as well. If the result type of the inherited subprogram is the derived type, the result of calling the @Chg{Version=[2],New=[],Old=[parent's ]}subprogram@Chg{Version=[2], New=[ of the parent or progenitor],Old=[]} is converted to the derived type@Chg{Version=[2],New=[, or in the case of a null extension, extended to the derived type using the equivalent of an @nt{extension_aggregate} with the original result as the @nt{ancestor_part} and @key{null record} as the @nt{record_component_association_list}],Old=[]}. @PDefn2{Term=[implicit subtype conversion],Sec=(result of inherited function)} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01]} If an inherited function returns the derived type, and the type is a @Chg{Version=[2],New=[non-null ],Old=[]}record extension, then the inherited function @Chg{Version=[2],New=[shall be overridden, unless the type is abstract (in which case the function ],Old=[]}is abstract, and (unless overridden) cannot be called except via a dispatching call@Chg{Version=[2],New=[)],Old=[]}. See @RefSecNum(Abstract Types and Subprograms). @end(Discussion) @end{RunTime} @begin{Notes} @Defn{closed under derivation} Classes are closed under derivation @em any class that contains a type also contains its derivatives. Operations available for a given class of types are available for the derived types in that class. Evaluating an inherited enumeration literal is equivalent to evaluating the corresponding enumeration literal of the parent type, and then converting the result to the derived type. This follows from their equivalence to parameterless functions. @PDefn2{Term=[implicit subtype conversion],Sec=(inherited enumeration literal)} A generic subprogram is not a subprogram, and hence cannot be a primitive subprogram and cannot be inherited by a derived type. On the other hand, an instance of a generic subprogram can be a primitive subprogram, and hence can be inherited. If the parent type is an access type, then the parent and the derived type share the same storage pool; there is a @key{null} access value for the derived type and it is the implicit initial value for the type. See @RefSecNum(Access Types). If the parent type is a boolean type, the predefined relational operators of the derived type deliver a result of the predefined type Boolean (see @RefSecNum(Relational Operators and Membership Tests)). If the parent type is an integer type, the right operand of the predefined exponentiation operator is of the predefined type Integer (see @RefSecNum(Highest Precedence Operators)). Any discriminants of the parent type are either all inherited, or completely replaced with a new set of discriminants. For an inherited subprogram, the subtype of a formal parameter of the derived type need not have any value in common with the first subtype of the derived type. @begin(TheProof) @Leading@;This happens when the parent subtype is constrained to a range that does not overlap with the range of a subtype of the parent type that appears in the profile of some primitive subprogram of the parent type. For example: @begin(example) @key(type) T1 @key(is range) 1..100; @key(subtype) S1 @key(is) T1 @key(range) 1..10; @key(procedure) P(X : @key[in] S1); @RI{-- P is a primitive subprogram} @key(type) T2 @key(is new) T1 @key(range) 11..20; @RI(-- implicitly declared:) @RI{-- @key(procedure) P(X : @key[in] T2'Base @key(range) 1..10);} @RI{-- X cannot be in T2'First .. T2'Last} @end(example) @end(TheProof) If the reserved word @key{abstract} is given in the declaration of a type, the type is abstract (see @RefSecNum{Abstract Types and Subprograms}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[An interface type that has a progenitor type @lquotes@;is derived from@rquotes@; that type. A @nt{derived_type_definition}, however, never defines an interface type.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[It is illegal for the parent type of a @nt{derived_type_definition} to be a synchronized tagged type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@RefSecNum{Type extensions} prohibits record extensions whose parent type is a synchronized tagged type, and this clause requires tagged types to have a record extension. Thus there are no legal derivations. Note that a synchronized interface can be used as a progenitor in an @nt{interface_type_definition} as well as in task and protected types, but we do not allow concrete extensions of any synchronized tagged type.]} @end{TheProof} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of derived type declarations:) @begin(Example) @key(type) Local_Coordinate @key(is) @key(new) Coordinate; --@RI[ two different types] @key(type) Midweek @key(is) @key(new) Day @key(range) Tue .. Thu; --@RI[ see @RefSecNum(Enumeration Types)] @key(type) Counter @key(is) @key(new) Positive; --@RI[ same range as Positive ] @key(type) Special_Key @key(is) @key(new) Key_Manager.Key; --@RI[ see @RefSecNum(Private Operations)] --@RI[ the inherited subprograms have the following specifications: ] --@RI[ procedure Get_Key(K : out Special_Key);] --@RI[ function "<"(X,Y : Special_Key) return Boolean;] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, if a predefined operator had been overridden prior to the derivation, the derived type will inherit the user-defined operator rather than the predefined operator. The work-around (if the new behavior is not the desired behavior) is to move the definition of the derived type prior to the overriding of any predefined operators. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} @Leading@;When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, a primitive subprogram of the parent type declared before the derived type will be inherited by the derived type. This can cause upward incompatibilities in cases like this: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] (A, B, C, D); @key[function] F( X : T := A ) @key[return] Integer; @key[type] NT @key[is] @key[new] T; --@RI{ inherits F as} --@RI{ function F( X : NT := A ) return Integer;} --@RI{ in Ada 95 only} ... @key[end] P; ... @key[use] P; --@RI{ Only one declaration of F from P is use-visible in} --@RI{ Ada 83; two declarations of F are use-visible in} --@RI{ Ada 95.} @key[begin] ... @key[if] F > 1 @key[then] ... --@RI{ legal in Ada 83, ambiguous in Ada 95} @end{Example} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{derived_type_definition} is amended to include an optional @nt{record_extension_part} (see @RefSecNum(Type Extensions)). A derived type may override the discriminants of the parent by giving a new @nt{discriminant_part}. The parent type in a @nt<derived_type_definition> may be a derived type defined in the same visible part. When deriving from a type in the same visible part in which it is defined, the primitive subprograms declared prior to the derivation are inherited as primitive subprograms of the derived type. See @RefSecNum(Classification of Operations). @end{Extend83} @begin{DiffWord83} We now talk about the classes to which a type belongs, rather than a single class. As explained in Section 13, the concept of "storage pool" replaces the Ada 83 concept of "collection." These concepts are similar, but not the same. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A derived type may inherit from multiple (interface) progenitors, as well as the parent type @em see @RefSec{Interface Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A derived type may specify that it is a limited type. This is required for interface ancestors (from which limitedness is not inherited), but it is generally useful as documentation of limitedness.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[Defined the result of functions for null extensions (which we no longer require to be overridden - see @RefSecNum{Abstract Types and Subprograms}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Defined the term @lquotes@;category of types@rquotes and used it in wording elsewhere; also specified the language-defined categories that form classes of types (this was never normatively specified in Ada 95.]} @end{DiffWord95} @LabeledSubClause{Derivation Classes} @begin{Intro} In addition to the various language-defined classes of types, types can be grouped into @i(derivation classes). @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @Defn2{Term=[derived from], Sec=(directly or indirectly)} A derived type is @i(derived from) its parent type @i(directly); it is derived @i(indirectly) from any type from which its parent type is derived.@Chg{Version=[2], New=[ A derived type, interface type, type extension, task type, protected type, or formal derived type is also derived from every ancestor of each of its progenitor types, if any.],Old=[]} @Defn2{Term=[derivation class], Sec=(for a type)} @Defn2{Term=[root type], Sec=(of a class)} @Defn{rooted at a type} The derivation class of types for a type @i(T) (also called the class @i(rooted) at @i(T)) is the set consisting of @i(T) (the @i(root type) of the class) and all types derived from @i(T) (directly or indirectly) plus any associated universal or class-wide types (defined below). @begin{Discussion} Note that the definition of @lquotes@;derived from@rquotes@; is a recursive definition. We don't define a root type for all interesting language-defined classes, though presumably we could. @end{Discussion} @begin{Honest} By the class-wide type @lquotes@;associated@rquotes@; with a type @i(T), we mean the type @i(T)'Class. Similarly, the universal type associated with @i{root_integer}, @i{root_real}, and @i{root_fixed} are @i{universal_integer}, @i{universal_real}, and @i{universal_fixed}, respectively. @end{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} Every type is either a @i(specific) type, a @i(class-wide) type, or a @i(universal) type. @Defn{specific type} A specific type is one defined by a @nt<type_declaration>, a @nt<formal_type_declaration>, or a full type definition embedded in @Chg{Version=[2],New=[another construct],Old=[a declaration for an object]}. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows: @begin(Honest) The root types @i(root_integer), @i(root_real), and @i(root_fixed) are also specific types. They are declared in the specification of package Standard. @end(Honest) @begin(Description) @Defn{class-wide type}Class-wide types @\Class-wide types are defined for @Redundant[(and belong to)] each derivation class rooted at a tagged type (see @RefSecNum(Tagged Types and Type Extensions)). Given a subtype S of a tagged type @i(T), S'Class is the @nt<subtype_mark> for a corresponding subtype of the tagged class-wide type @i(T)'Class. Such types are called @lquotes@;class-wide@rquotes@; because when a formal parameter is defined to be of a class-wide type @i(T)'Class, an actual parameter of any type in the derivation class rooted at @i(T) is acceptable (see @RefSecNum(The Context of Overload Resolution)). @NoPrefix@Defn{first subtype} The set of values for a class-wide type @i(T)'Class is the discriminated union of the set of values of each specific type in the derivation class rooted at @i(T) (the tag acts as the implicit discriminant @em see @RefSecNum(Tagged Types and Type Extensions)). Class-wide types have no primitive subprograms of their own. However, as explained in @RefSecNum(Dispatching Operations of Tagged Types), operands of a class-wide type @i(T)'Class can be used as part of a dispatching call on a primitive subprogram of the type @i(T). The only components @Redundant[(including discriminants)] of @i(T)'Class that are visible are those of @i(T). If S is a first subtype, then S'Class is a first subtype. @begin{Reason} We want S'Class to be a first subtype when S is, so that an @nt{attribute_@!definition_@!clause} like @lquotes@key[for] S'Class'Output @key[use] ...;@rquotes@; will be legal. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{universal type}Universal types @\Universal types are defined for @Redundant[(and belong to)] the integer, real, @Chg{Version=[2],New=[],Old=[and ]}fixed point@Chg{Version=[2], New=[, and access],Old=[]} classes, and are referred to in this standard as respectively, @i(universal_integer), @i(universal_real), @Chg{Version=[2],New=[], Old=[and ]}@i(universal_fixed)@Chg{Version=[2], New=[, and @i(universal_access)],Old=[]}. These are analogous to class-wide types for these language-defined @Chg{Version=[2],New=[elementary],Old=[numeric]} classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real @nt<numeric_literal>@Chg{Version=[2],New=[, or the literal @key{null}],Old=[]}) is @lquotes@;universal@rquotes@; in that it is acceptable where some particular type in the class is expected (see @RefSecNum(The Context of Overload Resolution)). @NoPrefix@;The set of values of a universal type is the undiscriminated union of the set of values possible for any definable type in the associated class. Like class-wide types, universal types have no primitive subprograms of their own. However, their @lquotes@;universality@rquotes@; allows them to be used as operands with the primitive subprograms of any type in the corresponding class. @begin(Discussion) A class-wide type is only class-wide in one direction, from specific to class-wide, whereas a universal type is class-wide (universal) in both directions, from specific to universal and back. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} We considered defining class-wide or perhaps universal types for all derivation classes, not just tagged classes and these @Chg{Version=[2], New=[four elementary],Old=[three numeric]} classes. However, this was felt to overly weaken the strong-typing model in some situations. Tagged types preserve strong type distinctions thanks to the run-time tag. Class-wide or universal types for untagged types would weaken the compile-time type distinctions without providing a compensating run-time-checkable distinction. We considered defining standard names for the universal numeric types so they could be used in formal parameter specifications. However, this was felt to impose an undue implementation burden for some implementations. @end(Discussion) @begin(Honest) Formally, the set of values of a universal type is actually a @i(copy) of the undiscriminated union of the values of the types in its class. This is because we want each value to have exactly one type, with explicit or implicit conversion needed to go between types. An alternative, consistent model would be to associate a class, rather than a particular type, with a value, even though any given expression would have a particular type. In that case, implicit type conversions would not generally need to change the value, although an associated subtype conversion might need to. @end(Honest) @end(Description) @PDefn{root_integer} @PDefn{root_real} The integer and real numeric classes each have a specific root type in addition to their universal type, named respectively @i(root_integer) and @i(root_real). @Defn2{Term=[cover], Sec=(a type)} A class-wide or universal type is said to @i(cover) all of the types in its class. A specific type covers only itself. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @Defn2{Term=[descendant], Sec=(of a type)} A specific type @i(T2) is defined to be a @i(descendant) of a type @i(T1) if @i(T2) is the same as @i(T1), or if @i(T2) is derived (directly or indirectly) from @i(T1). A class-wide type @i(T2)'Class is defined to be a descendant of type @i(T1) if @i(T2) is a descendant of @i(T1). Similarly, the @Chg{Version=[2],New=[numeric ],Old=[]}universal types are defined to be descendants of the root types of their classes. @Defn2{Term=[ancestor], Sec=(of a type)} If a type @i(T2) is a descendant of a type @i(T1), then @i(T1) is called an @i(ancestor) of @i(T2). @Defn2{Term=[ultimate ancestor], Sec=(of a type)} @Defn2{Term=[ancestor], Sec=(ultimate)} @Chg{Version=[2],New=[An],Old=[The]} @i(ultimate ancestor) of a type is @Chg{Version=[2],New=[an],Old=[the]} ancestor of @Chg{Version=[2],New=[that],Old=[the]} type that is not @Chg{Version=[2],New=[itself ],Old=[]}a descendant of any other type.@Chg{Version=[2],New=[ Every untagged type has a unique ultimate ancestor.],Old=[]} @begin{Ramification} A specific type is a descendant of itself. Class-wide types are considered descendants of the corresponding specific type, and do not have any descendants of their own. A specific type is an ancestor of itself. The root of a derivation class is an ancestor of all types in the class, including any class-wide types in the class. @end{Ramification} @begin(Discussion) @Leading@keepnext@;The terms root, parent, ancestor, and ultimate ancestor are all related. For example: @begin(Itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Each type has at most one parent, and one or more ancestor types; each @Chg{Version=[2],New=[untagged ],Old=[]}type has exactly one ultimate ancestor. In Ada 83, the term @lquotes@;parent type@rquotes@; was sometimes used more generally to include any ancestor type (e.g. RM83-9.4(14)). In Ada 95, we restrict parent to mean the immediate ancestor. A class of types has at most one root type; a derivation class has exactly one root type. The root of a class is an ancestor of all of the types in the class (including itself). The type @i(root_integer) is the root of the integer class, and is the ultimate ancestor of all integer types. A similar statement applies to @i(root_real). @end(Itemize) @end(Discussion) @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Ancestor>, Text=<@ChgAdded{Version=[2],Text=[An ancestor of a type is the type itself or, in the case of a type derived from other types, its parent type or one of its progenitor types or one of their ancestors. Note that ancestor and descendant are inverse relationships.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Descendant>, Text=<@ChgAdded{Version=[2],Text=[A type is a descendant of itself, its parent and progenitor types, and their ancestors. Note that descendant and ancestor are inverse relationships.]}>} @Defn2{Term=[inherited], Sec=(from an ancestor type)} An inherited component @Redundant[(including an inherited discriminant)] of a derived type is inherited @i(from) a given ancestor of the type if the corresponding component was inherited by each derived type in the chain of derivations going back to the given ancestor. @end{StaticSem} @begin{Notes} Because operands of a universal type are acceptable to the predefined operators of any type in their class, ambiguity can result. For @i(universal_integer) and @i(universal_real), this potential ambiguity is resolved by giving a preference (see @RefSecNum{The Context of Overload Resolution}) to the predefined operators of the corresponding root types (@i(root_integer) and @i(root_real), respectively). Hence, in an apparently ambiguous expression like @begin(Display) 1 + 4 < 7 @end(Display) @NoPrefix@;where each of the literals is of type @i(universal_integer), the predefined operators of @i(root_integer) will be preferred over those of other specific integer types, thereby resolving the ambiguity. @begin(Ramification) Except for this preference, a root numeric type is essentially like any other specific type in the associated numeric class. In particular, the result of a predefined operator of a root numeric type is not @lquotes@;universal@rquotes@; (implicitly convertible) even if both operands were. @end(Ramification) @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Updated the wording to define the @i{universal_access} type. This was defined to make @key{null} for anonymous access types sensible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[The definitions of ancestors and descendants were updated to allow multiple ancestors (necessary to support interfaces).]} @end{DiffWord95} @LabeledClause{Scalar Types} @begin{Intro} @Defn{scalar type} @i(Scalar) types comprise enumeration types, integer types, and real types. @Defn{discrete type} Enumeration types and integer types are called @i(discrete) types; @Defn{position number} each value of a discrete type has a @i(position number) which is an integer value. @Defn{numeric type} Integer types and real types are called @i(numeric) types. @Redundant[All scalar types are ordered, that is, all relational operators are predefined for their values.] @end{Intro} @begin{Syntax} @Syn{lhs=<range_constraint>,rhs=" @key{range} @Syn2{range}"} @Syn{lhs=<range>,rhs=" @Syn2{range_attribute_reference} | @Syn2{simple_expression} .. @Syn2{simple_expression}"} @end{Syntax} @begin(Discussion) These need to be @nt<simple_expression>s rather than more general @nt<expression>s because ranges appear in membership tests and other contexts where @nt<expression> .. @nt<expression> would be ambiguous. @end(Discussion) @begin{Intro} @Defn{range} @Defn2{Term=[lower bound], Sec=(of a range)} @Defn2{Term=[upper bound], Sec=(of a range)} @Defn{type of a range} A @i(range) has a @i(lower bound) and an @i(upper bound) and specifies a subset of the values of some scalar type (the @i(type of the range)). A range with lower bound L and upper bound R is described by @lquotes@;L .. R@rquotes@;. @Defn{null range} If R is less than L, then the range is a @i(null range), and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive. @Defn2{Term=[belong], Sec=(to a range)} A value @i(belongs) to a range if it is of the type of the range, and is in the subset of values specified by the range. @PDefn2{Term=[satisfies], Sec=(a range constraint)} A value @i(satisfies) a range constraint if it belongs to the associated range. @Defn2{Term=[included], Sec=(one range in another)} One range is @i(included) in another if all values that belong to the first range also belong to the second. @end{Intro} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(range_constraint range)} For a @nt<subtype_indication> containing a @nt<range_constraint>, either directly or as part of some other @nt<scalar_constraint>, the type of the @nt<range> shall resolve to that of the type determined by the @nt<subtype_mark> of the @nt<subtype_indication>. @PDefn2{Term=[expected type], Sec=(range simple_expressions)} For a @nt<range> of a given type, the @nt<simple_expression>s of the @nt<range> (likewise, the @nt<simple_expression>s of the equivalent @nt<range> for a @nt<range_attribute_reference>) are expected to be of the type of the @nt<range>. @begin(Discussion) In Ada 95, @nt<constraint>s only appear within @nt<subtype_indication>s; things that look like constraints that appear in type declarations are called something else like @nt<real_range_specification>s. We say "the expected type is ..." or "the type is expected to be ..." depending on which reads better. They are fundamentally equivalent, and both feed into the type resolution rules of clause @RefSecNum(The Context of Overload Resolution). In some cases, it doesn't work to use expected types. For example, in the above rule, we say that the @lquotes@;type of the @nt<range> shall resolve to ...@rquotes@; rather than @lquotes@;the expected type for the @nt<range> is ...@rquotes@;. We then use @lquotes@;expected type@rquotes@; for the bounds. If we used @lquotes@;expected@rquotes@; at both points, there would be an ambiguity, since one could apply the rules of @RefSecNum{The Context of Overload Resolution} either on determining the type of the range, or on determining the types of the individual bounds. It is clearly important to allow one bound to be of a universal type, and the other of a specific type, so we need to use @lquotes@;expected type@rquotes@; for the bounds. Hence, we used @lquotes@;shall resolve to@rquotes@; for the type of the range as a whole. There are other situations where @lquotes@;expected type@rquotes@; is not quite right, and we use @lquotes@;shall resolve to@rquotes@; instead. @end(Discussion) @end{Resolution} @begin{StaticSem} @RootDefn2{Term=[base range], Sec=(of a scalar type)} The @i(base range) of a scalar type is the range of finite values of the type that can be represented in every unconstrained object of the type; it is also the range supported at a minimum for intermediate values during the evaluation of expressions involving predefined operators of the type. @begin{ImplNote} Note that in some machine architectures intermediates in an expression (particularly if static), and register-resident variables might accommodate a wider range. The base range does not include the values of this wider range that are not assignable without overflow to memory-resident objects.@end{implnote} @begin(Ramification) @PDefn2{Term=[base range], Sec=(of an enumeration type)} The base range of an enumeration type is the range of values of the enumeration type. @end(Ramification) @begin{Reason} If the representation supports infinities, the base range is nevertheless restricted to include only the representable finite values, so that 'Base'First and 'Base'Last are always guaranteed to be finite.@end{reason} @begin(Honest) By a "value that can be assigned without overflow" we don't mean to restrict ourselves to values that can be represented exactly. Values between machine representable values can be assigned, but on subsequent reading, a slightly different value might be retrieved, as (partially) determined by the number of digits of precision of the type. @end(Honest) @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} @Redundant[A constrained scalar subtype is one to which a range constraint applies.] @Defn2{Term=[range], Sec=(of a scalar subtype)} The @i(range) of a constrained scalar subtype is the range associated with the range constraint of the subtype. The @i(range) of an unconstrained scalar subtype is the base range of its type. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(range with a scalar subtype)} A range is @i(compatible) with a scalar subtype if and only if it is either a null range or each bound of the range belongs to the range of the subtype. @PDefn2{Term=[compatibility], Sec=(range_constraint with a scalar subtype)} A @nt<range_constraint> is @i(compatible) with a scalar subtype if and only if its range is compatible with the subtype. @begin(Ramification) Only @nt<range_constraint>s (explicit or implicit) impose conditions on the values of a scalar subtype. The other @nt<scalar_constraint>s, @nt<digits_constraint>s and @nt<delta_constraint>s impose conditions on the subtype denoted by the @nt<subtype_mark> in a @nt<subtype_indication>, but don't impose a condition on the values of the subtype being defined. Therefore, a scalar subtype is not called @i(constrained) if all that applies to it is a @nt<digits_constraint>. Decimal subtypes are subtle, because a @nt<digits_constraint> without a @nt<range_constraint> nevertheless includes an implicit @nt<range_constraint>. @end(Ramification) @PDefn2{Term=[elaboration], Sec=(range_constraint)} The elaboration of a @nt{range_constraint} consists of the evaluation of the @nt{range}. @PDefn2{Term=[evaluation], Sec=(range)} The evaluation of a @nt{range} determines a lower bound and an upper bound. If @nt<simple_expression>s are given to specify bounds, the evaluation of the @nt<range> evaluates these @nt<simple_expression>s in an arbitrary order, and converts them to the type of the @nt<range>. @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a range)} If a @nt<range_attribute_reference> is given, the evaluation of the @nt<range> consists of the evaluation of the @nt<range_attribute_reference>. @keepnext@i(Attributes) @Leading@keepnext@;For @PrefixType{every scalar subtype S}, the following attributes are defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<First>, Text=[S'First denotes the lower bound of the range of S. The value of this attribute is of the type of S.]} @begin{Ramification} Evaluating S'First never raises Constraint_Error.@end{ramification} @Attribute{Prefix=<S>, AttrName=<Last>, Text=[S'Last denotes the upper bound of the range of S. The value of this attribute is of the type of S.]} @begin{Ramification} Evaluating S'Last never raises Constraint_Error.@end{ramification} @Attribute{Prefix=<S>, AttrName=<Range>, Text=[S'Range is equivalent to the @nt<range> S'First .. S'Last.]} @Attribute{Prefix=<S>, AttrName=<Base>, Text=[S'Base denotes an unconstrained subtype of the type of S. This unconstrained subtype is called the @i(base subtype) of the type. ]}@Defn2{Term=(base subtype), Sec=(of a type)} @AttributeLeading{Prefix=<S>, AttrName=<Min>, Text=[S'Min denotes a function with the following specification: @begin(Descexample) @b(function) S'Min(@RI(Left), @RI(Right) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the lesser of the values of the two parameters.]} @begin{Discussion} @Defn2{Term=[italics],Sec=(formal parameters of attribute functions)} The formal parameter names are italicized because they cannot be used in calls @em see @RefSecNum{Subprogram Calls}. Such a specification cannot be written by the user because an @nt<attribute_reference> is not permitted as the designator of a user-defined function, nor can its formal parameters be anonymous. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Max>, Text=[S'Max denotes a function with the following specification: @begin(Descexample) @b(function) S'Max(@RI(Left), @RI(Right) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the greater of the values of the two parameters.]} @AttributeLeading{Prefix=<S>, AttrName=<Succ>, Text=[S'Succ denotes a function with the following specification: @begin(Descexample) @b(function) S'Succ(@RI(Arg) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one more than that of the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of adding one to the value of @i(Arg). For a fixed point type, the function returns the result of adding @i(small) to the value of @i(Arg). For a floating point type, the function returns the machine number (as defined in @RefSecNum(Floating Point Types)) immediately above the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such machine number.]} @begin{Ramification} S'Succ for a modular integer subtype wraps around if the value of @i(Arg) is S'Base'Last. S'Succ for a signed integer subtype might raise Constraint_Error if the value of @i(Arg) is S'Base'Last, or it might return the out-of-base-range value S'Base'Last+1, as is permitted for all predefined numeric operations.@end{ramification} @AttributeLeading{Prefix=<S>, AttrName=<Pred>, Text=[S'Pred denotes a function with the following specification: @begin(Descexample) @b(function) S'Pred(@RI(Arg) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one less than that of the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of subtracting one from the value of @i(Arg). For a fixed point type, the function returns the result of subtracting @i(small) from the value of @i(Arg). For a floating point type, the function returns the machine number (as defined in @RefSecNum(Floating Point Types)) immediately below the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such machine number.]} @begin{Ramification} S'Pred for a modular integer subtype wraps around if the value of @i(Arg) is S'Base'First. S'Pred for a signed integer subtype might raise Constraint_Error if the value of @i(Arg) is S'Base'First, or it might return the out-of-base-range value S'Base'First@en@;1, as is permitted for all predefined numeric operations.@end{ramification} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Image>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Image denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@b(function) S'Wide_Wide_Image(@RI(Arg) : S'Base) @b(return) Wide_Wide_String]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=[image], Sec=(of a value)} The function returns an @i(image) of the value of @i(Arg), that is, a sequence of characters representing the value in display form.]}]}@Comment{End of Annex text here.} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The lower bound of the result is one.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ If the machine supports negative zeros for signed integer types, it is not specified whether "@ 0" or "@en@;0" should be returned for negative zero. We don't have enough experience with such machines to know what is appropriate, and what other languages do. In any case, the implementation should be consistent.]} @end{implnote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn{nongraphic character} The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a @i(nongraphic character) (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined name in upper case (for example, the image of the nongraphic character identified as @i(nul) is @lquotes@;NUL@rquotes@; @em the quotes are not part of the image).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ For an enumeration type T that has @lquotes@;holes@rquotes@; (caused by an @nt{enumeration_@!representation_@!clause}), @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits@en@;1 (see @RefSecNum(Operations of Floating Point Types)) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or @en), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Leading zeros are present in the exponent only if necessary to make the exponent at least two digits.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see @RefSecNum(Operations of Fixed Point Types)) digits after the decimal point.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Fixed_IO.Put.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For a machine that supports negative zeros, it is not specified whether "@ 0.000" or "@en@;0.000" is returned. See corresponding comment above about integer types with signed zeros.]} @end{implnote} @AttributeLeading{Prefix=<S>, AttrName=<Wide_Image>, Text=[S'Wide_Image denotes a function with the following specification: @begin(Descexample) @b(function) S'Wide_Image(@RI(Arg) : S'Base) @b(return) Wide_String @end(Descexample) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @NoPrefix@Defn2{Term=[image], Sec=(of a value)} The function returns an @Chg{Version=[2],New=[image],Old=[@i(image)]} of the value of @i(Arg)@Chg{Version=[2],New=[ as a Wide_String],Old=[, that is, a sequence of characters representing the value in display form]}.]} The lower bound of the result is one.@Chg{Version=[2], New=[ The image has the same sequence of character as defined for S'Wide_Wide_Image if all the graphic characters are defined in Wide_Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'Wide_Wide_Image for the same value of Arg).],Old=[]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The sequence of characters of the value returned by S'Wide_Image when some of the graphic characters of S'Wide_Wide_Image are not defined in Wide_Character.]}]} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 31 through 34 were moved to Wide_Wide_Image.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[ If the machine supports negative zeros for signed integer types, it is not specified whether "@en@;0" or " 0" should be returned for negative zero. We don't have enough experience with such machines to know what is appropriate, and what other languages do. In any case, the implementation should be consistent.]} @end{implnote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn{nongraphic character} The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a @i(nongraphic character) (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined or implementation-defined name in upper case (for example, the image of the nongraphic character identified as @i(nul) is @lquotes@;NUL@rquotes@; @em the quotes are not part of the image).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[For an enumeration type T that has @lquotes@;holes@rquotes@; (caused by an @nt{enumeration_representation_clause}), @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits@en@;1 (see @RefSecNum(Operations of Floating Point Types)) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or @en), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.]} @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Leading zeros are present in the exponent only if necessary to make the exponent at least two digits.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see @RefSecNum(Operations of Fixed Point Types)) digits after the decimal point.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Fixed_IO.Put.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[For a machine that supports negative zeros, it is not specified whether "@en@;0.000" or " 0.000" is returned. See corresponding comment above about integer types with signed zeros.]} @end{implnote} @AttributeLeading{Prefix=<S>, AttrName=<Image>, Text=[S'Image denotes a function with the following specification: @begin(Descexample) @b(function) S'Image(@RI(Arg) : S'Base) @b(return) String @end(Descexample) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @NoPrefix@;The function returns an image of the value of @i(Arg) as a String.]} The lower bound of the result is one. The image has the same sequence of graphic characters as that defined for S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} if all the graphic characters are defined in Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'@Chg{Version=[2],New=[Wide_Wide_Image], Old=[Wide_Image]} for the same value of @i(Arg)). @ChgImplDef{Version=[2],Kind=[Revised],Text=[The sequence of characters of the value returned by S'Image when some of the graphic characters of S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} are not defined in Character.]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Width>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Width denotes the maximum length of a Wide_Wide_String returned by S'Wide_Wide_Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).],Old=[]}]} @Attribute{Prefix=<S>, AttrName=<Wide_Width>, Text=[S'Wide_Width denotes the maximum length of a Wide_String returned by S'Wide_Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).]} @Attribute{Prefix=<S>, AttrName=<Width>, Text=[S'Width denotes the maximum length of a String returned by S'Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Value>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Value denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@b(function) S'Wide_Wide_Value(@RI(Arg) : Wide_Wide_String) @b(return) S'Base]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[This function returns a value given an image of the value as a Wide_Wide_String, ignoring any leading or trailing spaces.]}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@PDefn2{Term=[evaluation], Sec=(Wide_Wide_Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Wide_Image for a nongraphic character of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise Constraint_Error is raised.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check.]} @end{discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[Added],Ref=[8652/0096],ARef=[AI95-00053-01]} @ChgAdded{Version=[2],Text=[A sequence of characters corresponds to the result of S'Wide_Wide_Image if it is the same ignoring case. Thus, the case of an image of a nongraphic character does not matter. For example, Character'Wide_Wide_Value("nul") does not raise Constraint_Error, even though Character'Wide_Wide_Image returns "NUL" for the nul character.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Wide_Value for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error. However, we currently require (see @RefSecNum(Static Expressions and Static Subtypes)) in an @nt{assignment_statement} like "X := <numeric_literal>;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types).]} @end(Discussion) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Type=[Leading],Text=[For the evaluation of a call on S'Wide_Wide_Value for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:]} @begin[itemize] @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@nt[numeric_literal]]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[numeral].[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<.@nt[numeral][@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[base]#@nt[based_numeral].#[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[base]#.@nt[based_numeral]#[@nt[exponent]]>} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Wide_Value>, Text=[S'Wide_Value denotes a function with the following specification: @begin(Descexample) @b(function) S'Wide_Value(@RI(Arg) : Wide_String) @b(return) S'Base @end(Descexample) @NoPrefix@;This function returns a value given an image of the value as a Wide_String, ignoring any leading or trailing spaces.]}@Comment{This marks the end of the Annex text.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @NoPrefix@PDefn2{Term=[evaluation], Sec=(Wide_Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Image for a @Chg{Version=[2],New=[value],Old=[nongraphic character]} of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise Constraint_Error is raised. @Chg{Version=[2],New=[For a numeric subtype S, the evaluation of a call on S'Wide_Value with @i(Arg) of type Wide_String is equivalent to a call on S'Wide_Wide_Value for a corresponding @i(Arg) of type Wide_Wide_String.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check.]} @end{discussion} @begin{Honest} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0096],ARef=[AI95-00053-01]} @ChgRef{Version=[2],Kind=[DeletedAdded]} @ChgDeleted{Version=[2],Text=[ @Chg{Version=[1],New=[A sequence of characters corresponds to the result of S'Wide_Image if it is the same ignoring case. Thus, the case of an image of a nongraphic character does not matter. For example, Character'Wide_Value("nul") does not raise Constraint_Error, even though Character'Wide_Image returns "NUL" for the nul character.],Old=[]}]} @end{Honest} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[S'Wide_Value is subtly different from S'Wide_Wide_Value for enumeration subtypes since S'Wide_Image might produce a different sequence of characters than S'Wide_Wide_Image if the enumeration literal uses characters outside of the predefined type Wide_Character. That is why we don't just define S'Wide_Value in terms of S'Wide_Wide_Value for enumeration subtypes. S'Wide_Value and S'Wide_Wide_Value for numeric subtypes yield the same result given the same sequence of characters.]} @end(Reason) @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 44 through 51 were moved to Wide_Wide_Value.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error. However, we currently require (see @RefSecNum(Static Expressions and Static Subtypes)) in an @nt{assignment_statement} like "X := <numeric_literal>;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types).]} @end(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],NoPrefix=[T],Type=[Leading],Text=[For the evaluation of a call on S'Wide_Value (or S'Value) for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:]} @begin[itemize] @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[numeric_literal]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[numeral].[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<.@nt[numeral][@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[base]#@nt[based_numeral].#[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@nt[base]#.@nt[based_numeral]#[@nt[exponent]]]} @end{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Value>, Text=[S'Value denotes a function with the following specification: @begin(Descexample) @b(function) S'Value(@RI(Arg) : String) @b(return) S'Base @end(Descexample) @NoPrefix@;This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @NoPrefix@PDefn2{Term=[evaluation], Sec=(Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise Constraint_Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with @i(Arg) of type String is equivalent to a call on S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} for a corresponding @i(Arg) of type @Chg{Version=[2],New=[Wide_Wide_String],Old=[Wide_String]}. @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} S'Value is subtly different from S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} for enumeration subtypes@Chg{Version=[2],New=[; see the discussion under S'Wide_Value], Old=[since S'Image might produce a different sequence of characters than S'Wide_Image if the enumeration literal uses characters outside of the predefined type Character. That is why we don't just define S'Value in terms of S'Wide_Value for enumeration subtypes. S'Value and S'Wide_Value for numeric subtypes yield the same result given the same sequence of characters]}. @end(Reason) @end(description) @EndPrefixType{} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} An implementation may extend the @Chg{Version=[2],New=[Wide_Wide_Value, ], Old=[Wide_Value, ]} @Redundant[@Chg{Version=[2],New=[Wide_Value, ],Old=[]}Value, @Chg{Version=[2],New=[Wide_Wide_Image, ], Old=[]}Wide_Image, and Image] attributes of a floating point type to support special values such as infinities and NaNs. @begin{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The permission is really only necessary for @Chg{Version=[2],New=[Wide_Wide_Value], Old=[Wide_Value]}, because Value @Chg{Version=[2],New=[and Wide_Value are],Old=[is]} defined in terms of @Chg{Version=[2],New=[Wide_Wide_Value], Old=[Wide_Value]}, and because the behavior of @Chg{Version=[2],New=[Wide_Wide_Image, ], Old=[]}Wide_Image@Chg{Version=[2],New=[,],Old=[]} and Image is already unspecified for things like infinities and NaNs. @end{TheProof} @begin{Reason} This is to allow implementations to define full support for IEEE arithmetic. See also the similar permission for Get in @RefSecNum{Input-Output for Real Types}. @end{Reason} @end{ImplPerm} @begin{Notes} The evaluation of S'First or S'Last never raises an exception. If a scalar subtype S has a nonnull range, S'First and S'Last belong to this range. These values can, for example, always be assigned to a variable of subtype S. @begin(Discussion) This paragraph addresses an issue that came up with Ada 83, where for fixed point types, the end points of the range specified in the type definition were not necessarily within the base range of the type. However, it was later clarified (and we reconfirm it in @RefSec(Fixed Point Types)) that the First and Last attributes reflect the true bounds chosen for the type, not the bounds specified in the type definition (which might be outside the ultimately chosen base range). @end(Discussion) For a subtype of a scalar type, the result delivered by the attributes Succ, Pred, and Value might not belong to the subtype; similarly, the actual parameters of the attributes Succ, Pred, and Image need not belong to the subtype. For any value V (including any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V)) equals V, as @Chg{Version=[2],New=[do],Old=[does]} S'Wide_Value(S'Wide_Image(V))@Chg{Version=[2], New=[ and S'Wide_Wide_Value(S'Wide_Wide_Image(V))],Old=[]}. @Chg{Version=[2],New=[None of these expressions],Old=[Neither expression]} ever @Chg{Version=[2],New=[raise],Old=[raises]} Constraint_Error. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of ranges:) @begin{Example} -10 .. 10 X .. X + 1 0.0 .. 2.0*Pi Red .. Green --@RI[ see @RefSecNum{Enumeration Types}] 1 .. 0 --@RI[ a null range] Table'Range --@RI[ a range attribute reference (see @RefSecNum{Array Types})] @end{Example} @Leading@keepnext@i(Examples of range constraints:) @begin{Example} @key(range) -999.0 .. +999.0 @key(range) S'First+1 .. S'Last-1 @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Defn{incompatibilities with Ada 83} S'Base is no longer defined for nonscalar types. One conceivable existing use of S'Base for nonscalar types is S'Base'Size where S is a generic formal private type. However, that is not generally useful because the actual subtype corresponding to S might be a constrained array or discriminated type, which would mean that S'Base'Size might very well overflow (for example, S'Base'Size where S is a constrained subtype of String will generally be 8 * (Integer'Last + 1)). For derived discriminated types that are packed, S'Base'Size might not even be well defined if the first subtype is constrained, thereby allowing some amount of normally required @lquotes@;dope@rquotes@; to have been squeezed out in the packing. Hence our conclusion is that S'Base'Size is not generally useful in a generic, and does not justify keeping the attribute Base for nonscalar types just so it can be used as a @Chg{New=[@nt{prefix}],Old=[prefix]}. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The attribute S'Base for a scalar subtype is now permitted anywhere a @nt{subtype_mark} is permitted. S'Base'First .. S'Base'Last is the base range of the type. Using an @nt{attribute_@!definition_@!clause}, one cannot specify any subtype-specific attributes for the subtype denoted by S'Base (the base subtype). The attribute S'Range is now allowed for scalar subtypes. The attributes S'Min and S'Max are now defined, and made available for all scalar types. The attributes S'Succ, S'Pred, S'Image, S'Value, and S'Width are now defined for real types as well as discrete types. Wide_String versions of S'Image and S'Value are defined. These are called S'Wide_Image and S'Wide_Value to avoid introducing ambiguities involving uses of these attributes with string literals. @end{Extend83} @begin{DiffWord83} We now use the syntactic category @nt<range_attribute_reference> since it is now syntactically distinguished from other attribute references. The definition of S'Base has been moved here from 3.3.3 since it now applies only to scalar types. More explicit rules are provided for nongraphic characters. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The attributes Wide_Wide_Image, Wide_Wide_Value, and Wide_Wide_Width are new. Note that Wide_Image and Wide_Value are now defined in terms of Wide_Wide_Image and Wide_Wide_Value, but the image of types other than characters have not changed.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ The Wide_Image and Wide_Value attributes are now defined in terms of Wide_Wide_Image and Wide_Wide_Value, but the images of numeric types have not changed.]} @end{DiffWord95} @LabeledSubClause{Enumeration Types} @begin{Intro} @Redundant[@Defn{enumeration type} An @nt<enumeration_type_definition> defines an enumeration type.] @end{Intro} @begin{Syntax} @Syn{lhs=<enumeration_type_definition>,rhs=" (@Syn2{enumeration_literal_specification} {, @Syn2{enumeration_literal_specification}})"} @Syn{lhs=<enumeration_literal_specification>, rhs=" @Syn2{defining_identifier} | @Syn2{defining_character_literal}"} @Syn{lhs=<defining_character_literal>,rhs="@Syn2{character_literal}"} @end{Syntax} @begin{Legality} @Redundant[The @nt<defining_identifier>s and @nt<defining_character_literal>s listed in an @nt<enumeration_type_definition> shall be distinct.] @begin{TheProof} This is a ramification of the normal disallowance of homographs explicitly declared immediately in the same declarative region.@end{theproof} @end{Legality} @begin{StaticSem} @Defn{enumeration literal} Each @nt<enumeration_literal_specification> is the explicit declaration of the corresponding @i(enumeration literal): it declares a parameterless function, whose defining name is the @nt<defining_@!identifier> or @nt<defining_@!character_@!literal>, and whose result type is the enumeration type. @begin{Reason} This rule defines the profile of the enumeration literal, which is used in the various types of conformance. @end{Reason} @begin{Ramification} The parameterless function associated with an enumeration literal is fully defined by the @nt<enumeration_type_definition>; a body is not permitted for it, and it never fails the Elaboration_Check when called. @end{Ramification} Each enumeration literal corresponds to a distinct value of the enumeration type, and to a distinct position number. @PDefn2{Term=[position number], Sec=(of an enumeration value)} The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list. @redundant[The predefined order relations between values of the enumeration type follow the order of corresponding position numbers.] @redundant[@PDefn2{Term=[overloaded], Sec=(enumeration literal)} If the same @nt<defining_identifier> or @nt<defining_character_literal> is specified in more than one @nt<enumeration_@!type_@!definition>, the corresponding enumeration literals are said to be @i(overloaded). At any place where an overloaded enumeration literal occurs in the text of a program, the type of the enumeration literal has to be determinable from the context (see @RefSecNum(The Context of Overload Resolution)).] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(enumeration_type_definition)} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} The elaboration of an @nt<enumeration_type_definition> creates the enumeration type and its first subtype, which is constrained to the base range of the type. @begin{Ramification} The first subtype of a discrete type is always constrained, except in the case of a derived type whose parent subtype is Whatever'Base. @end{Ramification} When called, the parameterless function associated with an enumeration literal returns the corresponding value of the enumeration type. @end{RunTime} @begin{Notes} If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity (see @RefSecNum(Qualified Expressions)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of enumeration types and subtypes: ) @begin(Example) @key(type) Day @key(is) (Mon, Tue, Wed, Thu, Fri, Sat, Sun); @key(type) Suit @key(is) (Clubs, Diamonds, Hearts, Spades); @key(type) Gender @key(is) (M, F); @key(type) Level @key(is) (Low, Medium, Urgent); @key(type) Color @key(is) (White, Red, Yellow, Green, Blue, Brown, Black); @key(type) Light @key(is) (Red, Amber, Green); --@RI[ Red and Green are overloaded] @key(type) Hexa @key(is) ('A', 'B', 'C', 'D', 'E', 'F'); @key(type) Mixed @key(is) ('A', 'B', '*', B, None, '?', '%'); @key(subtype) Weekday @key(is) Day @key(range) Mon .. Fri; @key(subtype) Major @key(is) Suit @key(range) Hearts .. Spades; @key(subtype) Rainbow @key(is) Color @key(range) Red .. Blue; --@RI[ the Color Red, not the Light] @end(Example) @end{Examples} @begin{DiffWord83} The syntax rule for @nt{defining_character_literal} is new. It is used for the defining occurrence of a @nt{character_literal}, analogously to @nt{defining_identifier}. Usage occurrences use the @nt{name} or @nt{selector_name} syntactic categories. We emphasize the fact that an enumeration literal denotes a function, which is called to produce a value. @end{DiffWord83} @LabeledSubClause{Character Types} @begin{StaticSem} @Defn{character type} An enumeration type is said to be a @i(character type) if at least one of its enumeration literals is a @nt<character_literal>. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn{Latin-1} @Defn{BMP} @Chg{Version=[2],New=[@Defn{ISO/IEC 10646:2003}],Old=[@Defn{ISO 10646}]} @Defn{Character} The predefined type Character is a character type whose values correspond to the 256 code positions of Row 00 (also known as Latin-1) of the @Chg{Version=[2],New=[ISO/IEC 10646:2003], Old=[ISO 10646]} Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding @nt<character_literal> in Character. Each of the nongraphic positions of Row 00 (0000-001F and 007F-009F) has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes @Chg{Version=[2],New=[Image, Wide_Image, Wide_Wide_Image, Value, Wide_Value, and Wide_Wide_Value], Old=[(Wide_)Image and (Wide_)Value]}; these names are given in the definition of type Character in @RefSec{The Package Standard}, but are set in @i{italics}. @Defn2{Term=[italics],Sec=(nongraphic characters)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn{Wide_Character} @Defn{BMP} @Chg{Version=[2],New=[@Defn{ISO/IEC 10646:2003}],Old=[@Defn{ISO 10646}]} The predefined type Wide_Character is a character type whose values correspond to the 65536 code positions of the @Chg{Version=[2], New=[ISO/IEC 10646:2003],Old=[ISO 10646]} Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding @nt<character_literal> in Wide_Character. The first 256 values of Wide_Character have the same @nt<character_literal> or language-defined name as defined for Character. @Chg{Version=[2],New=[Each of the @ntf{graphic_character}s has],Old=[The last 2 values of Wide_Character correspond to the nongraphic positions FFFE and FFFF of the BMP, and are assigned the language-defined names @i(FFFE) and @i(FFFF). As with the other language-defined names for nongraphic characters, the names @i(FFFE) and @i(FFFF) are usable only with the attributes (Wide_)Image and (Wide_)Value; they are not usable as enumeration literals. All other values of Wide_Character are considered graphic characters, and have]} a corresponding @nt<character_literal>. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{Wide_Wide_Character} @Defn{BMP} @Chg{Version=[2],New=[@Defn{ISO/IEC 10646:2003}],Old=[@Defn{ISO 10646}]} The predefined type Wide_Wide_Character is a character type whose values correspond to the 2147483648 code positions of the ISO/IEC 10646:2003 character set. Each of the @ntf{graphic_character}s has a corresponding @nt{character_literal} in Wide_Wide_Character. The first 65536 values of Wide_Wide_Character have the same @nt{character_literal} or language-defined name as defined for Wide_Character.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The characters whose code position is larger than 16#FF# and which are not @ntf{graphic_character}s have language-defined names which are formed by appending to the string "Hex_" the representation of their code position in hexadecimal as eight extended digits. As with other language-defined names, these names are usable only with the attributes (Wide_)Wide_Image and (Wide_)Wide_Value; they are not usable as enumeration literals.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The language-defined names are not usable as enumeration literals to avoid "polluting" the name space. Since Wide_Character @Chg{Version=[2],New=[and Wide_Wide_Character ],Old=[]}are defined in Standard, if the @Chg{Version=[2],New=[language-defined ], Old=[]}names @Chg{Version=[2],New=[],Old=[FFFE and FFFF ]}were usable as enumeration literals, they would hide other nonoverloadable declarations with the same names in @key[use]-d packages.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[ISO 10646 has not defined the meaning of all of the code positions from 0100 through FFFD, but they are all considered graphic characters by Ada to simplify the implementation, and to allow for revisions to ISO 10646. In ISO 10646, FFFE and FFFF are special, and will never be associated with graphic characters in any revision.]} @end{Reason} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{localization} In a nonstandard mode, an implementation may provide other interpretations for the predefined types Character and Wide_Character@Redundant[, to conform to local conventions].]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{localization} If an implementation supports a mode with alternative interpretations for Character and Wide_Character, the set of graphic characters of Character should nevertheless remain a proper subset of the set of graphic characters of Wide_Character. Any character set @lquotes@;localizations@rquotes@; should be reflected in the results of the subprograms defined in the language-defined package Characters.Handling (see @RefSecNum{Character Handling}) available in such a mode. In a mode with an alternative interpretation of Character, the implementation should also support a corresponding change in what is a legal @ntf<identifier_letter>.]} @ChgNote{We won't add an ChgImplAdvice here, because we would need to add and remove it in the same command.} @end{ImplAdvice} @begin{Notes} The language-defined library package Characters.Latin_1 (see @RefSecNum(The Package Characters.Latin_1)) includes the declaration of constants denoting control characters, lower case characters, and special characters of the predefined type Character. @begin{Honest} The package ASCII does the same, but only for the first 128 characters of Character. Hence, it is an obsolescent package, and we no longer mention it here. @end{Honest} A conventional character set such as @i(EBCDIC) can be declared as a character type; the internal codes of the characters can be specified by an @nt<enumeration_representation_clause> as explained in clause @RefSecNum(Enumeration Representation Clauses). @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a character type: ) @begin(Example) @key(type) Roman_Digit @key(is) ('I', 'V', 'X', 'L', 'C', 'D', 'M'); @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The declaration of Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the unlikely event that an Ada 83 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Character, the meaning of the program will be different. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The presence of Wide_Character in package Standard means that an expression such as @begin(Example) 'a' = 'b' @end(Example) is ambiguous in Ada 95, whereas in Ada 83 both literals could be resolved to be of type Character. The change in visibility rules (see @RefSecNum(Literals)) for character literals means that additional qualification might be necessary to resolve expressions involving overloaded subprograms and character literals. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The type Character has been extended to have 256 positions, and the type Wide_Character has been added. Note that this change was already approved by the ARG for Ada 83 conforming compilers. The rules for referencing character literals are changed (see @RefSecNum(Literals)), so that the declaration of the character type need not be directly visible to use its literals, similar to @b(null) and string literals. Context is used to resolve their type. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Ada 95 defined most characters in Wide_Character to be graphic characters, while Ada 2005 uses the categorizations from ISO-10646:2003. It also provides language-defined names for all non-graphic characters. That means that in Ada 2005, Wide_Character'Wide_Value will raise Constraint_Error for a string representing a @nt{character_literal} of a non-graphic character, while Ada 95 would have accepted it. Similarly, the result of Wide_Character'Wide_Image will change for such non-graphic characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The language-defined names FFFE and FFFF were replaced by a consistent set of language-defined names for all non-graphic characters with positions greater than 16#FF#. That means that in Ada 2005, Wide_Character'Wide_Value("FFFE") will raise Constraint_Error while Ada 95 would have accepted it. Similarly, the result of Wide_Character'Wide_Image will change for the position numbers 16#FFFE# and 16#FFFF#. It is very unlikely that this will matter in practice, as these names do not represent useable characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Because of the previously mentioned changes to the Wide_Character'Wide_Image of various character values, the value of attribute Wide_Width will change for some subtypes of Wide_Character. However, the new language-defined names were chosen so that the value of Wide_Character'Wide_Width itself does not change.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The declaration of Wide_Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the (very) unlikely event that an Ada 95 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Wide_Character, the meaning of the program will be different.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The type Wide_Wide_Character is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Characters are now defined in terms of the entire ISO/IEC 10646:2003 character set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We dropped the @ImplAdviceTitle for non-standard interpretation of character sets; an implementation can do what it wants in a non-standard mode, so there isn't much point to any advice.]} @end{DiffWord95} @LabeledSubClause{Boolean Types} @begin{StaticSem} @Defn{Boolean} There is a predefined enumeration type named Boolean, @Redundant[declared in the visible part of package Standard]. @Defn{False} @Defn{True} It has the two enumeration literals False and True ordered with the relation False < True. @Defn{boolean type} Any descendant of the predefined type Boolean is called a @i(boolean) type. @begin{ImplNote} An implementation is not required to support enumeration representation clauses on boolean types that impose an unacceptable implementation burden. See @RefSec(Enumeration Representation Clauses). However, it is generally straightforward to support representations where False is zero and True is 2**n @en@; 1 for some n. @end{ImplNote} @end{StaticSem} @LabeledSubClause{Integer Types} @begin{Intro} @Defn{integer type} @Defn{signed integer type} @Defn{modular type} An @nt<integer_type_definition> defines an integer type; it defines either a @i(signed) integer type, or a @i(modular) integer type. The base range of a signed integer type includes at least the values of the specified range. A modular type is an integer type with all arithmetic modulo a specified positive @i(modulus); such a type corresponds to an unsigned type with wrap-around semantics. @IndexSee{Term=[unsigned type],See=(modular type)} @end{Intro} @begin{Syntax} @Syn{lhs=<integer_type_definition>, rhs="@Syn2{signed_integer_type_definition} | @Syn2{modular_type_definition}"} @Syn{lhs=<signed_integer_type_definition>, rhs="@key(range) @SynI{static_}@Syn2{simple_expression} .. @SynI{static_}@Syn2{simple_expression}"} @begin{Discussion} We don't call this a @nt<range_constraint>, because it is rather different @em not only is it required to be static, but the associated overload resolution rules are different than for normal range constraints. A similar comment applies to @nt{real_range_specification}. This used to be @ntf<integer_range_specification> but when we added support for modular types, it seemed overkill to have three levels of syntax rules, and just calling these @ntf<signed_integer_range_specification> and @ntf<modular_range_specification> loses the fact that they are defining different classes of types, which is important for the generic type matching rules. @end{Discussion} @Syn{lhs=<modular_type_definition>, rhs="@key(mod) @SynI{static_}@Syn2{expression}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(signed_integer_type_definition simple_expression)} Each @nt<simple_expression> in a @nt<signed_integer_type_definition> is expected to be of any integer type; they need not be of the same type. @PDefn2{Term=[expected type], Sec=(modular_type_definition expression)} The @nt<expression> in a @nt<modular_type_definition> is likewise expected to be of any integer type. @end{Resolution} @begin{Legality} The @nt<simple_expression>s of a @nt<signed_integer_type_definition> shall be static, and their values shall be in the range System.Min_Int .. System.Max_Int. @Defn2{Term=[modulus], Sec=(of a modular type)} @Defn{Max_Binary_Modulus} @Defn{Max_Nonbinary_Modulus} The @nt<expression> of a @nt<modular_type_definition> shall be static, and its value (the @i(modulus)) shall be positive, and shall be no greater than System.Max_Binary_Modulus if a power of 2, or no greater than System.Max_Nonbinary_Modulus if not. @begin(Reason) For a 2's-complement machine, supporting nonbinary moduli greater than System.Max_Int can be quite difficult, whereas essentially any binary moduli are straightforward to support, up to 2*System.Max_Int+2, so this justifies having two separate limits. @end(Reason) @end{Legality} @begin{StaticSem} The set of values for a signed integer type is the (infinite) set of mathematical integers@Redundant[, though only values of the base range of the type are fully supported for run-time operations]. The set of values for a modular integer type are the values from 0 to one less than the modulus, inclusive. @PDefn2{Term=[base range], Sec=(of a signed integer type)} A @nt<signed_integer_type_definition> defines an integer type whose base range includes at least the values of the @nt<simple_expression>s and is symmetric about zero, excepting possibly an extra negative value. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<signed_integer_type_definition> also defines a constrained first subtype of the type, with a range whose bounds are given by the values of the @nt<simple_expression>s, converted to the type being defined. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The base range of a signed integer type might be much larger than is necessary to satisfy the @Chg{Version=[2],New=[above],Old=[aboved]} requirements. @end{ImplNote} @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of signed integer type)}]} @end{Honest} @PDefn2{Term=[base range], Sec=(of a modular type)} A @nt<modular_type_definition> defines a modular type whose base range is from zero to one less than the given modulus. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<modular_type_definition> also defines a constrained first subtype of the type with a range that is the same as the base range of the type. @Defn{Integer} There is a predefined signed integer subtype named Integer@Redundant[, declared in the visible part of package Standard]. It is constrained to the base range of its type. @begin{Reason} Integer is a constrained subtype, rather than an unconstrained subtype. This means that on assignment to an object of subtype Integer, a range check is required. On the other hand, an object of subtype Integer'Base is unconstrained, and no range check (only overflow check) is required on assignment. For example, if the object is held in an extended-length register, its value might be outside of Integer'First .. Integer'Last. All parameter and result subtypes of the predefined integer operators are of such unconstrained subtypes, allowing extended-length registers to be used as operands or for the result. In an earlier version of Ada 95, Integer was unconstrained. However, the fact that certain Constraint_Errors might be omitted or appear elsewhere was felt to be an undesirable upward inconsistency in this case. Note that for Float, the opposite conclusion was reached, partly because of the high cost of performing range checks when not actually necessary. Objects of subtype Float are unconstrained, and no range checks, only overflow checks, are performed for them. @end{Reason} @Leading@Defn{Natural} @Defn{Positive} Integer has two predefined subtypes, @Redundant[declared in the visible part of package Standard:] @begin{Example} @key[subtype] Natural @key[is] Integer @key[range] 0 .. Integer'Last; @key[subtype] Positive @key[is] Integer @key[range] 1 .. Integer'Last; @end{Example} @Defn{root_integer} @Defn{Min_Int} @Defn{Max_Int} A type defined by an @nt<integer_type_definition> is implicitly derived from @i(root_integer), an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_Int. However, the base range of the new type is not inherited from @i{root_integer}, but is instead determined by the range or modulus specified by the @nt{integer_type_definition}. @PDefn{universal_integer} @Defn{integer literals} @Redundant[Integer literals are all of the type @i(universal_integer), the universal type (see @RefSecNum(Derivation Classes)) for the class rooted at @i(root_integer), allowing their use with the operations of any integer type.] @begin{Discussion} This implicit derivation is not considered exactly equivalent to explicit derivation via a @nt<derived_type_definition>. In particular, integer types defined via a @nt<derived_type_definition> inherit their base range from their parent type. A type defined by an @nt<integer_type_definition> does not necessarily inherit its base range from @i(root_integer). It is not specified whether the implicit derivation from @i(root_integer) is direct or indirect, not that it really matters. All we want is for all integer types to be descendants of @i(root_integer). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0099],ARef=[AI95-00152-01]} @Chg{New=[Note that this derivation does not imply any inheritance of subprograms. Subprograms are inherited only for types derived by a @nt{derived_@!type_@!definition} (see @RefSecNum{Derived Types and Classes}), or a @nt{private_@!extension_@!declaration} (see @RefSecNum{Private Types and Private Extensions}, @RefSecNum{Private Operations}, and @RefSecNum{Formal Private and Derived Types}).],Old=[]} @end{Discussion} @begin{ImplNote} It is the intent that even nonstandard integer types (see below) will be descendants of @i(root_integer), even though they might have a base range that exceeds that of @i(root_integer). This causes no problem for static calculations, which are performed without range restrictions (see @RefSecNum(Static Expressions and Static Subtypes)). However for run-time calculations, it is possible that Constraint_Error might be raised when using an operator of @i(root_integer) on the result of 'Val applied to a value of a nonstandard integer type. @end{ImplNote} @PDefn2{Term=[position number], Sec=(of an integer value)} The @i(position number) of an integer value is equal to the value. @begin{Wide} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00340-01]} @Leading@keepnext@;For @PrefixType{every modular subtype S}, the following @Chg{Version=[2],New=[attributes are],Old=[attribute is]} defined: @end{Wide} @begin(description) @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Mod>, ARef=[AI95-00340-01], Text=[@Chg{Version=[2],New=[S'Mod denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key{function} S'Mod (@RI{Arg} : @RI{universal_integer}) @key{return} S'Base]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[This function returns @i{Arg} @key{mod} S'Modulus, as a value of the type of S.]}]}@Comment{end attribute Mod} @Attribute{Prefix=<S>, AttrName=<Modulus>, Text=[S'Modulus yields the modulus of the type of S, as a value of the type @i(universal_integer).]} @end(description) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(integer_type_definition)} The elaboration of an @nt<integer_type_definition> creates the integer type and its first subtype. For a modular type, if the result of the execution of a predefined operator (see @RefSecNum(Operators and Expression Evaluation)) is outside the base range of the type, the result is reduced modulo the modulus of the type to a value that is within the base range of the type. @IndexCheck{Overflow_Check} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For a signed integer type, the exception Constraint_Error is raised by the execution of an operation that cannot deliver the correct result because it is outside the base range of the type. @redundant[@IndexCheck{Division_Check} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For any integer type, Constraint_Error is raised by the operators "/", "@key(rem)", and "@key(mod)" if the right operand is zero.] @end{RunTime} @begin{ImplReq} @Defn{Integer} In an implementation, the range of Integer shall include the range @en@;2**15+1 .. +2**15@en@;1. @Defn{Long_Integer} If Long_Integer is predefined for an implementation, then its range shall include the range @en@;2**31+1 .. +2**31@en@;1. System.Max_Binary_Modulus shall be at least 2**16. @end{ImplReq} @begin{ImplPerm} For the execution of a predefined operation of a signed integer type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced. @begin{Discussion} Constraint_Error is never raised for operations on modular types, except for divide-by-zero (and @key[rem]/@key[mod]-by-zero). @end{Discussion} @Defn{Long_Integer} @Defn{Short_Integer} An implementation may provide additional predefined signed integer types@Redundant[, declared in the visible part of Standard], whose first subtypes have names of the form Short_Integer, Long_Integer, Short_Short_Integer, Long_Long_Integer, etc. Different predefined integer types are allowed to have the same base range. However, the range of Integer should be no wider than that of Long_Integer. Similarly, the range of Short_Integer (if provided) should be no wider than Integer. Corresponding recommendations apply to any other predefined integer types. There need not be a named integer type corresponding to each distinct base range supported by an implementation. The range of each first subtype should be the base range of its type. @ImplDef{The predefined integer types declared in Standard.} @Defn{nonstandard integer type} An implementation may provide @i(nonstandard integer types), descendants of @i(root_integer) that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by an @nt<integer_type_definition>. For example, a nonstandard integer type might have an asymmetric base range or it might not be allowed as an array or loop index (a very long integer). Any type descended from a nonstandard integer type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for @lquotes@;any integer type@rquotes@; are defined for a particular nonstandard integer type. @Redundant[In any case, such types are not permitted as @nt{explicit_generic_actual_parameter}s for formal scalar types @em see @RefSecNum(Formal Scalar Types).] @ImplDef{Any nonstandard integer types and the operators defined for them.} @PDefn2{Term=[one's complement], Sec=(modular types)} For a one's complement machine, the high bound of the base range of a modular type whose modulus is one less than a power of 2 may be equal to the modulus, rather than one less than the modulus. It is implementation defined for which powers of 2, if any, this permission is exercised. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0003],ARef=[AI95-00095-01]} @Chg{New=[For a one's complement machine, implementations may support non-binary modulus values greater than System.Max_Nonbinary_Modulus. It is implementation defined which specific values greater than System.Max_Nonbinary_Modulus, if any, are supported.],Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[On a one's complement machine, the natural full word type would have a modulus of 2**Word_Size@en@;1. However, we would want to allow the all-ones bit pattern (which represents negative zero as a number) in logical operations. These permissions are intended to allow that and the natural modulus value without burdening implementations with supporting expensive modulus values.]} @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @Defn{Long_Integer} An implementation should support Long_Integer in addition to Integer if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package Standard. Instead, appropriate named integer subtypes should be provided in the library package Interfaces (see @RefSecNum{The Package Interfaces}). @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Long_Integer should be declared in Standard if the target supports 32-bit arithmetic. No other named integer subtypes should be declared in Standard.]}]} @begin{ImplNote} To promote portability, implementations should explicitly declare the integer (sub)types Integer and Long_Integer in Standard, and leave other predefined integer types anonymous. For implementations that already support Byte_Integer, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Integer_8, Integer_16, etc. See @RefSecNum(The Package Interfaces). In any case, if the user declares a subtype (first or not) whose range fits in, for example, a byte, the implementation can store variables of the subtype in a single byte, even if the base range of the type is wider. @end{ImplNote} @PDefn2{Term=[two's complement],Sec=(modular types)} An implementation for a two's complement machine should support modular types with a binary modulus up to System.Max_Int*2+2. An implementation should support a nonbinary modulus up to Integer'Last. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For a two's complement target, modular types with a binary modulus up to System.Max_Int*2+2 should be supported. A nonbinary modulus up to Integer'Last should be supported.]}]} @begin{Reason} Modular types provide bit-wise "@key{and}", "@key{or}", "@key{xor}", and "@key{not}" operations. It is important for systems programming that these be available for all integer types of the target hardware. @end{Reason} @begin{Ramification} Note that on a one's complement machine, the largest supported modular type would normally have a nonbinary modulus. On a two's complement machine, the largest supported modular type would normally have a binary modulus. @end{Ramification} @begin{ImplNote} Supporting a nonbinary modulus greater than Integer'Last can impose an undesirable implementation burden on some machines. @end{ImplNote} @end{ImplAdvice} @begin{Notes} @Defn{universal_integer} @Defn{integer literals} Integer literals are of the anonymous predefined integer type @i(universal_integer). Other integer types have no literals. However, the overload resolution rules (see @RefSec(The Context of Overload Resolution)) allow expressions of the type @i(universal_integer) whenever an integer type is expected. The same arithmetic operators are predefined for all signed integer types defined by a @nt<signed_integer_type_definition> (see @RefSec(Operators and Expression Evaluation)). For modular types, these same operators are predefined, plus bit-wise logical operators (@key(and), @key(or), @key(xor), and @key(not)). In addition, for the unsigned types declared in the language-defined package Interfaces (see @RefSecNum(The Package Interfaces)), functions are defined that provide bit-wise shifting and rotating. Modular types match a @nt{generic_formal_parameter_declaration} of the form "@key(type) T @key(is mod) <>;"; signed integer types match "@key(type) T @key(is range) <>;" (see @RefSecNum{Formal Scalar Types}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of integer types and subtypes: ) @begin(Example) @key(type) Page_Num @key(is) @key(range) 1 .. 2_000; @key(type) Line_Size @key(is) @key(range) 1 .. Max_Line_Size; @key(subtype) Small_Int @key(is) Integer @key(range) -10 .. 10; @key(subtype) Column_Ptr @key(is) Line_Size @key(range) 1 .. 10; @key(subtype) Buffer_Size @key(is) Integer @key(range) 0 .. Max; @key(type) Byte @key(is) @key(mod) 256; --@RI[ an unsigned byte] @key(type) Hash_Index @key(is) @key(mod) 97; --@RI[ modulus is prime] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} An implementation is allowed to support any number of distinct base ranges for integer types, even if fewer integer types are explicitly declared in Standard. Modular (unsigned, wrap-around) types are new. @end{Extend83} @begin{DiffWord83} Ada 83's integer types are now called "signed" integer types, to contrast them with "modular" integer types. Standard.Integer, Standard.Long_Integer, etc., denote constrained subtypes of predefined integer types, consistent with the Ada 95 model that only subtypes have names. We now impose minimum requirements on the base range of Integer and Long_Integer. We no longer explain integer type definition in terms of an equivalence to a normal type derivation, except to say that all integer types are by definition implicitly derived from @i(root_integer). This is for various reasons. First of all, the equivalence with a type derivation and a subtype declaration was not perfect, and was the source of various AIs (for example, is the conversion of the bounds static? Is a numeric type a derived type with respect to other rules of the language?) Secondly, we don't want to require that every integer size supported shall have a corresponding named type in Standard. Adding named types to Standard creates nonportabilities. Thirdly, we don't want the set of types that match a formal derived type "type T is new Integer;" to depend on the particular underlying integer representation chosen to implement a given user-defined integer type. Hence, we would have needed anonymous integer types as parent types for the implicit derivation anyway. We have simply chosen to identify only one anonymous integer type @em @i(root_integer), and stated that every integer type is derived from it. Finally, the @lquotes@;fiction@rquotes@; that there were distinct preexisting predefined types for every supported representation breaks down for fixed point with arbitrary smalls, and was never exploited for enumeration types, array types, etc. Hence, there seems little benefit to pushing an explicit equivalence between integer type definition and normal type derivation. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00340-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Mod attribute is new. It eases mixing of signed and unsigned values in an expression, which can be difficult as there may be no type which can contain all of the values of both of the types involved.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0003],ARef=[AI95-00095-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Added additional permissions for modular types on one's complement machines.],Old=[]} @end{DiffWord95} @LabeledSubClause{Operations of Discrete Types} @begin{StaticSem} @Leading@;For @PrefixType{every discrete subtype S}, the following attributes are defined: @begin(description) @AttributeLeading{Prefix=<S>, AttrName=<Pos>, Text=[S'Pos denotes a function with the following specification: @begin(Descexample) @b(function) S'Pos(@RI(Arg) : S'Base) @b(return) @RI(universal_integer) @end(Descexample) @NoPrefix@;This function returns the position number of the value of @i(Arg), as a value of type @i(universal_integer).]} @AttributeLeading{Prefix=<S>, AttrName=<Val>, Text=[S'Val denotes a function with the following specification: @begin(Descexample) @b(function) S'Val(@RI(Arg) : @RI(universal_integer)) @b(return) S'Base @end(Descexample) @NoPrefix@PDefn2{Term=(evaluation), Sec=(Val)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} This function returns a value of the type of S whose position number equals the value of @i(Arg).]} @IndexCheck{Range_Check} For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised. @begin{Ramification} By the overload resolution rules, a formal parameter of type @i(universal_integer) allows an actual parameter of any integer type.@end{ramification} @begin{Reason} We considered allowing S'Val for a signed integer subtype S to return an out-of-range value, but since checks were required for enumeration and modular types anyway, the allowance didn't seem worth the complexity of the rule.@end{reason} @end(description) @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type @Redundant[(perhaps due to an uninitialized variable)], then the implementation should raise Program_Error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This is particularly important for enumeration types with noncontiguous internal codes specified by an @nt<enumeration_@!representation_@!clause>. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Program_Error should be raised for the evaluation of S'Pos for an enumeration type, if the value of the operand does not correspond to the internal code for any enumeration literal of the type.]}]} @begin{Reason} We say Program_Error here, rather than Constraint_Error, because the main reason for such values is uninitialized variables, and the normal way to indicate such a use (if detected) is to raise Program_Error. (Other reasons would involve the misuse of low-level features such as Unchecked_Conversion.) @end{Reason} @end{ImplAdvice} @begin{Notes} Indexing and loop iteration use values of discrete types. @PDefn2{Term=[predefined operations],Sec=(of a discrete type)} The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators @en@; and +, the multiplying operators, the unary operator @key(abs), and the exponentiation operator. The assignment operation is described in @RefSecNum(Assignment Statements). The other predefined operations are described in Section 4. As for all types, objects of a discrete type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). @Leading@;For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes: @begin(Example) S'Val(S'Pos(X)) = X S'Pos(S'Val(N)) = N @end(Example) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of attributes of discrete subtypes: ) @begin(Example) --@RI[ For the types and subtypes declared in subclause @RefSecNum(Enumeration Types) the following hold: ] -- Color'First = White, Color'Last = Black -- Rainbow'First = Red, Rainbow'Last = Blue -- Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown -- Color'Pos(Blue) = Rainbow'Pos(Blue) = 4 -- Color'Val(0) = Rainbow'Val(0) = White @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The attributes S'Succ, S'Pred, S'Width, S'Image, and S'Value have been generalized to apply to real types as well (see @RefSec{Scalar Types}). @end{Extend83} @LabeledSubClause{Real Types} @begin{Intro} @Defn{real type} Real types provide approximations to the real numbers, with relative bounds on errors for floating point types, and with absolute bounds for fixed point types. @end{Intro} @begin{Syntax} @Syn{lhs=<real_type_definition>,rhs=" @Syn2{floating_point_definition} | @Syn2{fixed_point_definition}"} @end{Syntax} @begin{StaticSem} @Defn{root_real} A type defined by a @nt<real_type_definition> is implicitly derived from @i(root_real), an anonymous predefined (specific) real type. @Redundant[Hence, all real types, whether floating point or fixed point, are in the derivation class rooted at @i(root_real).] @begin{Ramification} It is not specified whether the derivation from @i(root_real) is direct or indirect, not that it really matters. All we want is for all real types to be descendants of @i(root_real). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0099],ARef=[AI95-00152-01]} @Chg{New=[Note that this derivation does not imply any inheritance of subprograms. Subprograms are inherited only for types derived by a @nt{derived_@!type_@!definition} (see @RefSecNum{Derived Types and Classes}), or a @nt{private_@!extension_@!declaration} (see @RefSecNum{Private Types and Private Extensions}, @RefSecNum{Private Operations}, and @RefSecNum{Formal Private and Derived Types}).],Old=[]} @end{Ramification} @redundant[@PDefn{universal_real} @Defn{real literals} Real literals are all of the type @i(universal_real), the universal type (see @RefSecNum(Derivation Classes)) for the class rooted at @i(root_real), allowing their use with the operations of any real type. @PDefn{universal_fixed} Certain multiplying operators have a result type of @i(universal_fixed) (see @RefSecNum{Multiplying Operators}), the universal type for the class of fixed point types, allowing the result of the multiplication or division to be used where any specific fixed point type is expected.] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(real_type_definition)} The elaboration of a @nt<real_type_definition> consists of the elaboration of the @nt<floating_point_definition> or the @nt<fixed_point_definition>. @end{RunTime} @begin{ImplReq} An implementation shall perform the run-time evaluation of a use of a predefined operator of @i(root_real) with an accuracy at least as great as that of any floating point type definable by a @nt<floating_point_definition>. @begin{Ramification} Static calculations using the operators of @i(root_real) are exact, as for all static calculations. See @RefSecNum(Static Expressions and Static Subtypes). @end{Ramification} @begin(ImplNote) The Digits attribute of the type used to represent @i(root_real) at run time is at least as great as that of any other floating point type defined by a @nt<floating_point_definition>, and its safe range includes that of any such floating point type with the same Digits attribute. On some machines, there might be real types with less accuracy but a wider range, and hence run-time calculations with @i(root_real) might not be able to accommodate all values that can be represented at run time in such floating point or fixed point types. @end(ImplNote) @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @Redundant[For the execution of a predefined operation of a real type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced, or the Machine_Overflows attribute of the type is @Chg{Version=[2], New=[False],Old=[false]} (see @RefSecNum{Numeric Performance Requirements}).] @Defn{nonstandard real type} An implementation may provide @i(nonstandard real types), descendants of @i(root_real) that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by a @nt<real_type_definition>. For example, a nonstandard real type might have an asymmetric or unsigned base range, or its predefined operations might wrap around or @lquotes@;saturate@rquotes@; rather than overflow (modular or saturating arithmetic), or it might not conform to the accuracy model (see @RefSecNum{Numeric Performance Requirements}). Any type descended from a nonstandard real type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for @lquotes@;any real type@rquotes@; are defined for a particular nonstandard real type. @Redundant[In any case, such types are not permitted as @nt{explicit_generic_actual_parameter}s for formal scalar types @em see @RefSecNum(Formal Scalar Types).] @ImplDef{Any nonstandard real types and the operators defined for them.} @end{ImplPerm} @begin{Notes} As stated, real literals are of the anonymous predefined real type @i(universal_real). Other real types have no literals. However, the overload resolution rules (see @RefSecNum(The Context of Overload Resolution)) allow expressions of the type @i(universal_real) whenever a real type is expected. @end{Notes} @begin{DiffWord83} The syntax rule for @nt{real_type_definition} is modified to use the new syntactic categories @nt{floating_point_definition} and @nt{fixed_point_definition}, instead of @ntf{floating_point_constraint} and @ntf{fixed_point_constraint}, because the semantics of a type definition are significantly different than the semantics of a constraint. All discussion of model numbers, safe ranges, and machine numbers is moved to @RefSecNum{Floating Point Types}, @RefSecNum{Operations of Floating Point Types}, and @RefSecNum{Numeric Performance Requirements}. Values of a fixed point type are now described as being multiples of the @i(small) of the fixed point type, and we have no need for model numbers, safe ranges, etc. for fixed point types. @end{DiffWord83} @LabeledSubClause{Floating Point Types} @begin{Intro} @Defn{floating point type} For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits. @end{Intro} @begin{Syntax} @Syn{lhs=<floating_point_definition>,rhs=" @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{real_range_specification}]"} @Syn{lhs=<real_range_specification>,rhs=" @key{range} @SynI{static_}@Syn2{simple_expression} .. @SynI{static_}@Syn2{simple_expression}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[requested decimal precision], Sec=(of a floating point type)} The @i(requested decimal precision), which is the minimum number of significant decimal digits required for the floating point type, is specified by the value of the @nt<expression> given after the reserved word @key(digits). @PDefn2{Term=[expected type], Sec=(requested decimal precision)} This @nt<expression> is expected to be of any integer type. @PDefn2{Term=[expected type], Sec=(real_range_specification bounds)} Each @nt<simple_expression> of a @nt<real_range_specification> is expected to be of any real type@Redundant[; the types need not be the same]. @end{Resolution} @begin{Legality} @Defn{Max_Base_Digits} The requested decimal precision shall be specified by a static @nt<expression> whose value is positive and no greater than System.Max_Base_Digits. Each @nt<simple_expression> of a @nt<real_range_specification> shall also be static. @Defn{Max_Digits} If the @nt<real_range_specification> is omitted, the requested decimal precision shall be no greater than System.Max_Digits. @begin(Reason) We have added Max_Base_Digits to package System. It corresponds to the requested decimal precision of @i(root_real). System.Max_Digits corresponds to the maximum value for Digits that may be specified in the absence of a @nt<real_range_specification>, for upward compatibility. These might not be the same if @i<root_real> has a base range that does not include @PorM 10.0**(4*Max_Base_Digits). @end(Reason) A @nt<floating_point_definition> is illegal if the implementation does not support a floating point type that satisfies the requested decimal precision and range. @ImplDef{What combinations of requested decimal precision and range are supported for floating point types.} @end{Legality} @begin{StaticSem} The set of values for a floating point type is the (infinite) set of rational numbers. @Defn2{Term=[machine numbers], Sec=(of a floating point type)} The @i(machine numbers) of a floating point type are the values of the type that can be represented exactly in every unconstrained variable of the type. @PDefn2{Term=[base range], Sec=(of a floating point type)} The base range (see @RefSecNum{Scalar Types}) of a floating point type is symmetric around zero, except that it can include some extra negative values in some implementations.@begin{ImplNote} For example, if a 2's complement representation is used for the mantissa rather than a sign-mantissa or 1's complement representation, then there is usually one extra negative machine number.@end{implnote} @begin{Honest} If the Signed_Zeros attribute is True, then minus zero could in a sense be considered a value of the type. However, for most purposes, minus zero behaves the same as plus zero. @end{Honest} @Defn2{Term=[base decimal precision], Sec=(of a floating point type)} The @i(base decimal precision) of a floating point type is the number of decimal digits of precision representable in objects of the type. @Defn2{Term=[safe range], Sec=(of a floating point type)} The @i(safe range) of a floating point type is that part of its base range for which the accuracy corresponding to the base decimal precision is preserved by all predefined operations. @begin{ImplNote} In most cases, the safe range and base range are the same. However, for some hardware, values near the boundaries of the base range might result in excessive inaccuracies or spurious overflows when used with certain predefined operations. For such hardware, the safe range would omit such values.@end{implnote} @PDefn2{Term=[base decimal precision], Sec=(of a floating point type)} A @nt<floating_point_definition> defines a floating point type whose base decimal precision is no less than the requested decimal precision. @PDefn2{Term=[safe range], Sec=(of a floating point type)} @PDefn2{Term=[base range], Sec=(of a floating point type)} If a @nt<real_range_specification> is given, the safe range of the floating point type (and hence, also its base range) includes at least the values of the simple expressions given in the @nt<real_range_specification>. If a @nt<real_range_specification> is not given, the safe (and base) range of the type includes at least the values of the range @en@;10.0**(4*D) .. +10.0**(4*D) where D is the requested decimal precision. @Redundant[The safe range might include other values as well. The attributes Safe_First and Safe_Last give the actual bounds of the safe range.] A @nt<floating_point_definition> also defines a first subtype of the type. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} If a @nt<real_range_specification> is given, then the subtype is constrained to a range whose bounds are given by a conversion of the values of the @nt<simple_expression>s of the @nt<real_range_specification> to the type being defined. Otherwise, the subtype is unconstrained. @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a floating point type)}]} @end{Honest} @Defn{Float} There is a predefined, unconstrained, floating point subtype named Float@Redundant[, declared in the visible part of package Standard]. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(floating_point_definition)} @Redundant[The elaboration of a @nt<floating_point_definition> creates the floating point type and its first subtype.] @end{RunTime} @begin{ImplReq} @Defn{Float} In an implementation that supports floating point types with 6 or more digits of precision, the requested decimal precision for Float shall be at least 6. @Defn{Long_Float} If Long_Float is predefined for an implementation, then its requested decimal precision shall be at least 11. @end{ImplReq} @begin{ImplPerm} @Defn{Short_Float} @Defn{Long_Float} An implementation is allowed to provide additional predefined floating point types@Redundant[, declared in the visible part of Standard], whose (unconstrained) first subtypes have names of the form Short_Float, Long_Float, Short_Short_Float, Long_Long_Float, etc. Different predefined floating point types are allowed to have the same base decimal precision. However, the precision of Float should be no greater than that of Long_Float. Similarly, the precision of Short_Float (if provided) should be no greater than Float. Corresponding recommendations apply to any other predefined floating point types. There need not be a named floating point type corresponding to each distinct base decimal precision supported by an implementation. @ImplDef{The predefined floating point types declared in Standard.} @end{ImplPerm} @begin{ImplAdvice} @Defn{Long_Float} An implementation should support Long_Float in addition to Float if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package Standard. Instead, appropriate named floating point subtypes should be provided in the library package Interfaces (see @RefSecNum(The Package Interfaces)). @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Long_Float should be declared in Standard if the target supports 11 or more digits of precision. No other named float subtypes should be declared in Standard.]}]} @begin{ImplNote} To promote portability, implementations should explicitly declare the floating point (sub)types Float and Long_Float in Standard, and leave other predefined float types anonymous. For implementations that already support Short_Float, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Float_32, IEEE_Float_64, etc. See @RefSecNum(The Package Interfaces). @end{ImplNote} @end{ImplAdvice} @begin{Notes} If a floating point subtype is unconstrained, then assignments to variables of the subtype involve only Overflow_Checks, never Range_Checks. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of floating point types and subtypes:) @begin(Example) @key(type) Coefficient @key(is) @key(digits) 10 @key(range) -1.0 .. 1.0; @key(type) Real @key(is) @key(digits) 8; @key(type) Mass @key(is) @key(digits) 7 @key(range) 0.0 .. 1.0E35; @key(subtype) Probability @key(is) Real @key(range) 0.0 .. 1.0; --@RI[ a subtype with a smaller range] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} No Range_Checks, only Overflow_Checks, are performed on variables (or parameters) of an unconstrained floating point subtype. This is upward compatible for programs that do not raise Constraint_Error. For those that do raise Constraint_Error, it is possible that the exception will be raised at a later point, or not at all, if extended range floating point registers are used to hold the value of the variable (or parameter). @begin(Reason) This change was felt to be justified by the possibility of improved performance on machines with extended-range floating point registers. An implementation need not take advantage of this relaxation in the range checking; it can hide completely the use of extended range registers if desired, presumably at some run-time expense. @end(Reason) @end{Inconsistent83} @begin{DiffWord83} The syntax rules for @ntf{floating_point_constraint} and @ntf{floating_accuracy_definition} are removed. The syntax rules for @nt{floating_point_definition} and @nt{real_range_specification} are new. A syntax rule for @nt<digits_constraint> is given in @RefSec{Fixed Point Types}. In @RefSecNum{Reduced Accuracy Subtypes} we indicate that a @nt<digits_constraint> may be applied to a floating point @nt<subtype_mark> as well (to be compatible with Ada 83's @ntf<floating_point_constraint>). Discussion of model numbers is postponed to @RefSecNum{Operations of Floating Point Types} and @RefSecNum{Numeric Performance Requirements}. The concept of safe numbers has been replaced by the concept of the safe range of values. The bounds of the safe range are given by T'Safe_First .. T'Safe_Last, rather than -T'Safe_Large .. T'Safe_Large, since on some machines the safe range is not perfectly symmetric. The concept of machine numbers is new, and is relevant to the definition of Succ and Pred for floating point numbers. @end{DiffWord83} @LabeledSubClause{Operations of Floating Point Types} @begin{StaticSem} @Leading@;The following attribute is defined for @PrefixType{every floating point subtype S}: @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<Digits>, Ref=[8652/0004], ARef=[AI95-00203-01], Text=[S'Digits denotes the requested decimal precision for the subtype S. The value of this attribute is of the type @i(universal_integer).]} The requested decimal precision of the base subtype of a floating point type @i{T} is defined to be the largest value of @i{d} for which @chg{New=[@*],Old=[]} ceiling(@i{d} * log(10) / log(T'Machine_Radix)) + @Chg{New=[@i{g}],Old=[1]} <= T'Model_Mantissa@Chg{New=[@* where g is 0 if Machine_Radix is a positive power of 10 and 1 otherwise],Old=[]}. @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} @PDefn2{Term=[predefined operations],Sec=(of a floating point type)} The predefined operations of a floating point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators @en@; and +, certain multiplying operators, the unary operator @key(abs), and the exponentiation operator. As for all types, objects of a floating point type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). Other attributes of floating point types are defined in @RefSecNum{Attributes of Floating Point Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0004],ARef=[AI95-00203-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the formula for Digits when the Machine_Radix is 10.]} @end{DiffWord95} @LabeledSubClause{Fixed Point Types} @begin{Intro} @Defn{fixed point type} @Defn{ordinary fixed point type} @Defn{decimal fixed point type} A fixed point type is either an ordinary fixed point type, or a decimal fixed point type. @Defn2{Term=[delta], Sec=(of a fixed point type)} The error bound of a fixed point type is specified as an absolute value, called the @i(delta) of the fixed point type. @end{Intro} @begin{Syntax} @Syn{lhs=<fixed_point_definition>,rhs="@Syn2{ordinary_fixed_point_definition} | @Syn2{decimal_fixed_point_definition}"} @Syn{lhs=<ordinary_fixed_point_definition>,rhs=" @key{delta} @SynI{static_}@Syn2{expression} @Syn2{real_range_specification}"} @Syn{lhs=<decimal_fixed_point_definition>,rhs=" @key{delta} @SynI{static_}@Syn2{expression} @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{real_range_specification}]"} @Syn{lhs=<digits_constraint>,rhs=" @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{range_constraint}]"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(fixed point type delta)} For a type defined by a @nt<fixed_point_definition>, the @i(delta) of the type is specified by the value of the @nt<expression> given after the reserved word @key(delta); this @nt<expression> is expected to be of any real type. @PDefn2{Term=[expected type], Sec=(decimal fixed point type digits)} @Defn2{Term=[digits], Sec=(of a decimal fixed point subtype)} @Defn{decimal fixed point type} For a type defined by a @nt<decimal_fixed_point_definition> (a @i(decimal) fixed point type), the number of significant decimal digits for its first subtype (the @i(digits) of the first subtype) is specified by the @nt<expression> given after the reserved word @key(digits); this @nt<expression> is expected to be of any integer type. @end{Resolution} @begin{Legality} In a @nt<fixed_point_definition> or @nt<digits_constraint>, the @nt<expression>s given after the reserved words @key(delta) and @key(digits) shall be static; their values shall be positive. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00100-01]} @Defn2{Term=[small], Sec=(of a fixed point type)} The set of values of a fixed point type comprise the integral multiples of a number called the @i(small) of the type.@Chg{Version=[2],New=[@PDefn2{Term=[machine numbers],Sec=[of a fixed point type]} The @i{machine numbers} of a fixed point type are the values of the type that can be represented exactly in every unconstrained variable of the type.],Old=[]} @Defn{ordinary fixed point type} For a type defined by an @nt<ordinary_fixed_point_definition> (an @i(ordinary) fixed point type), the @i(small) may be specified by an @nt<attribute_@!definition_@!clause> (see @RefSecNum{Operational and Representation Attributes}); if so specified, it shall be no greater than the @i(delta) of the type. If not specified, the @i(small) of an ordinary fixed point type is an implementation-defined power of two less than or equal to the @i(delta). @ImplDef{The @i(small) of an ordinary fixed point type.} For a decimal fixed point type, the @i(small) equals the @i(delta); the @i(delta) shall be a power of 10. If a @nt<real_range_specification> is given, both bounds of the range shall be in the range @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). A @nt<fixed_point_definition> is illegal if the implementation does not support a fixed point type with the given @i(small) and specified range or @i(digits). @ImplDef{What combinations of @i(small), range, and @i(digits) are supported for fixed point types.} For a @nt<subtype_indication> with a @nt<digits_constraint>, the @nt<subtype_mark> shall denote a decimal fixed point subtype. @begin(Honest) Or, as an obsolescent feature, a floating point subtype is permitted @em see @RefSecNum(Reduced Accuracy Subtypes). @end(Honest) @end{Legality} @begin{StaticSem} @PDefn2{Term=[base range], Sec=(of a fixed point type)} The base range (see @RefSecNum{Scalar Types}) of a fixed point type is symmetric around zero, except possibly for an extra negative value in some implementations. @Leading@PDefn2{Term=[base range], Sec=(of an ordinary fixed point type)} An @nt<ordinary_fixed_point_definition> defines an ordinary fixed point type whose base range includes at least all multiples of @i(small) that are between the bounds specified in the @nt<real_range_specification>. The base range of the type does not necessarily include the specified bounds themselves. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} An @nt<ordinary_@!fixed_@!point_@!definition> also defines a constrained first subtype of the type, with each bound of its range given by the closer to zero of: @begin(itemize) the value of the conversion to the fixed point type of the corresponding @nt<expression> of the @nt<real_range_specification>; @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a fixed point type)} @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a fixed point type)}]} @end{Honest} the corresponding bound of the base range. @end(itemize) @PDefn2{Term=[base range], Sec=(of a decimal fixed point type)} A @nt<decimal_fixed_point_definition> defines a decimal fixed point type whose base range includes at least the range @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<decimal_fixed_point_definition> also defines a constrained first subtype of the type. If a @nt<real_range_specification> is given, the bounds of the first subtype are given by a conversion of the values of the @nt<expression>s of the @nt<real_range_specification>. @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a decimal fixed point type)} Otherwise, the range of the first subtype is @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a decimal fixed point type)}]} @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(fixed_point_definition)} The elaboration of a @nt<fixed_point_definition> creates the fixed point type and its first subtype. For a @nt<digits_constraint> on a decimal fixed point subtype with a given @i(delta), if it does not have a @nt<range_constraint>, then it specifies an implicit range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta), where @i(D) is the value of the @nt<expression>. @Defn2{Term=[compatibility], Sec=(digits_constraint with a decimal fixed point subtype)} A @nt<digits_constraint> is @i(compatible) with a decimal fixed point subtype if the value of the @nt<expression> is no greater than the @i(digits) of the subtype, and if it specifies (explicitly or implicitly) a range that is compatible with the subtype. @begin(Discussion) Except for the requirement that the @i(digits) specified be no greater than the @i(digits) of the subtype being constrained, a @nt<digits_constraint> is essentially equivalent to a @nt<range_constraint>. @Leading@keepnext@;Consider the following example: @begin{Example} @key[type] D @key[is] @key[delta] 0.01 @key[digits] 7 @key[range] -0.00 .. 9999.99; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00008} The compatibility rule implies that the @nt{digits_constraint} "@key[digits] 6" specifies an implicit range of "@en@;@Chg{New=[9999.99],Old=[99.9999]} .. @Chg{New=[9999.99],Old=[99.9999]}". Thus, "@key[digits] 6" is not compatible with the constraint of D, but "@key[digits] 6 range 0.00 .. 9999.99" is compatible. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A value of a scalar type belongs to a constrained subtype of the type if it belongs to the range of the subtype. Attributes like Digits and Delta have no @Chg{Version=[2],New=[effect],Old=[affect]} on this fundamental rule. So the obsolescent forms of @nt<digits_constraint>s and @nt<delta_constraint>s that are called @lquotes@;accuracy constraints@rquotes@; in RM83 don't really represent constraints on the values of the subtype, but rather primarily affect compatibility of the @lquotes@;constraint@rquotes@; with the subtype being @lquotes@;constrained.@rquotes@; In this sense, they might better be called @lquotes@;subtype assertions@rquotes@; rather than @lquotes@;constraints.@rquotes@; Note that the @nt<digits_constraint> on a decimal fixed point subtype is a combination of an assertion about the @i(digits) of the subtype being further constrained, and a constraint on the range of the subtype being defined, either explicit or implicit. @end(Discussion) @PDefn2{Term=[elaboration], Sec=(digits_constraint)} The elaboration of a @nt<digits_constraint> consists of the elaboration of the @nt<range_constraint>, if any. @IndexCheck{Range_Check} If a @nt<range_constraint> is given, a check is made that the bounds of the range are both in the range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta), where @i(D) is the value of the (static) @nt<expression> given after the reserved word @key(digits). @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If this check fails, Constraint_Error is raised. @end{RunTime} @begin{ImplReq} The implementation shall support at least 24 bits of precision (including the sign bit) for fixed point types. @begin{Reason} This is sufficient to represent Standard.Duration with a @i(small) no more than 50 milliseconds. @end{Reason} @end{ImplReq} @begin{ImplPerm} Implementations are permitted to support only @i(small)s that are a power of two. In particular, all decimal fixed point type declarations can be disallowed. Note however that conformance with the Information Systems Annex requires support for decimal @i(small)s, and decimal fixed point type declarations with @i(digits) up to at least 18. @begin{ImplNote} The accuracy requirements for multiplication, division, and conversion (see @RefSec{Model of Floating Point Arithmetic}) are such that support for arbitrary @i(small)s should be practical without undue implementation effort. Therefore, implementations should support fixed point types with arbitrary values for @i(small) (within reason). One reasonable limitation would be to limit support to fixed point types that can be converted to the most precise floating point type without loss of precision (so that Fixed_IO is implementable in terms of Float_IO). @end{ImplNote} @end{ImplPerm} @begin{Notes} @Leading@;The base range of an ordinary fixed point type need not include the specified bounds themselves so that the range specification can be given in a natural way, such as: @begin(example) @b(type) Fraction @b(is delta) 2.0**(-15) @b(range) -1.0 .. 1.0; @end(example) @NoPrefix@;With 2's complement hardware, such a type could have a signed 16-bit representation, using 1 bit for the sign and 15 bits for fraction, resulting in a base range of @en@;1.0 .. 1.0@en@;2.0**(@en@;15). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of fixed point types and subtypes:) @begin(Example) @key(type) Volt @key(is) @key(delta) 0.125 @key(range) 0.0 .. 255.0; -- @RI[A pure fraction which requires all the available] -- @RI[space in a word can be declared as the type Fraction:] @key(type) Fraction @key(is) @key(delta) System.Fine_Delta @key(range) -1.0 .. 1.0; -- @RI[Fraction'Last = 1.0 @en System.Fine_Delta] @key(type) Money @key(is) @key(delta) 0.01 @key(digits) 15; -- @RI[decimal fixed point] @key(subtype) Salary @key(is) Money @key(digits) 10; -- @RI[Money'Last = 10.0**13 @en 0.01, Salary'Last = 10.0**8 @en 0.01] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} In Ada 95, S'Small always equals S'Base'Small, so if an implementation chooses a @i(small) for a fixed point type smaller than required by the @i(delta), the value of S'Small in Ada 95 might not be the same as it was in Ada 83. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Decimal fixed point types are new, though their capabilities are essentially similar to that available in Ada 83 with a fixed point type whose @i(small) equals its @i(delta) equals a power of 10. However, in the Information Systems Annex, additional requirements are placed on the support of decimal fixed point types (e.g. a minimum of 18 digits of precision). @end{Extend83} @begin{DiffWord83} The syntax rules for @ntf{fixed_point_constraint} and @ntf{fixed_accuracy_definition} are removed. The syntax rule for @nt{fixed_point_definition} is new. A syntax rule for @nt<delta_constraint> is included in the Obsolescent features (to be compatible with Ada 83's @ntf<fixed_point_constraint>). @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00100-01]} @ChgAdded{Version=[2],Text=[Added wording to define the machine numbers of fixed point types; this is needed by the static evaluation rules.]} @end{DiffWord95} @LabeledSubClause{Operations of Fixed Point Types} @begin{StaticSem} @Leading@;The following attributes are defined for @PrefixType{every fixed point subtype S}: @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<Small>, Ref=[8652/0005], ARef=[AI95-00054-01], Text=[S'Small denotes the @i(small) of the type of S. The value of this attribute is of the type @i(universal_real).]} @PDefn2{Term=[specifiable], Sec=(of Small for fixed point types)} @Defn{Small clause} Small may be specified for nonderived@Chg{New=[ ordinary],Old=[]} fixed point types via an @nt{attribute_@!definition_@!clause} (see @RefSecNum{Operational and Representation Attributes}); the expression of such a clause shall be static. @Attribute{Prefix=<S>, AttrName=<Delta>, Text=[S'Delta denotes the @i(delta) of the fixed point subtype S. The value of this attribute is of the type @i(universal_real).]} @begin{Reason} The @i(delta) is associated with the @i(sub)type as opposed to the type, because of the possibility of an (obsolescent) @nt<delta_constraint>.@end{reason} @Attribute{Prefix=<S>, AttrName=<Fore>, Text=[S'Fore yields the minimum number of characters needed before the decimal point for the decimal representation of any value of the subtype S, assuming that the representation does not include an exponent, but includes a one-character prefix that is either a minus sign or a space. (This minimum number does not include superfluous zeros or underlines, and is at least 2.) The value of this attribute is of the type @i(universal_integer).]} @Attribute{Prefix=<S>, AttrName=<Aft>, Text=<S'Aft yields the number of decimal digits needed after the decimal point to accommodate the @i(delta) of the subtype S, unless the @i(delta) of the subtype S is greater than 0.1, in which case the attribute yields the value one. @Redundant[(S'Aft is the smallest positive integer N for which (10**N)*S'Delta is greater than or equal to one.)] The value of this attribute is of the type @i(universal_integer).>} @end(description) @EndPrefixType{} @begin{Wide} @Leading@;The following additional attributes are defined for @PrefixType{every decimal fixed point subtype S}: @end{Wide} @begin(description) @Attribute{Prefix=<S>, AttrName=<Digits>, Text=[S'Digits denotes the @i(digits) of the decimal fixed point subtype S, which corresponds to the number of decimal digits that are representable in objects of the subtype. The value of this attribute is of the type @i(universal_integer).]} Its value is determined as follows: @Defn2{Term=[digits], Sec=(of a decimal fixed point subtype)} @begin(itemize) For a first subtype or a subtype defined by a @nt<subtype_indication> with a @nt<digits_constraint>, the digits is the value of the expression given after the reserved word @key(digits); For a subtype defined by a @nt<subtype_indication> without a @nt<digits_constraint>, the digits of the subtype is the same as that of the subtype denoted by the @nt<subtype_mark> in the @nt<subtype_indication>. @begin(ImplNote) Although a decimal subtype can be both range-constrained and digits-constrained, the digits constraint is intended to control the Size attribute of the subtype. For decimal types, Size can be important because input/output of decimal types is so common. @end(ImplNote) The digits of a base subtype is the largest integer @i(D) such that the range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta) is included in the base range of the type. @end(itemize) @Attribute{Prefix=<S>, AttrName=<Scale>, Text=[S'Scale denotes the @i(scale) of the subtype S, defined as the value N such that S'Delta = 10.0**(@en@;N). @Defn2{Term=[scale], Sec=(of a decimal fixed point subtype)} @Redundant{The scale indicates the position of the point relative to the rightmost significant digits of values of subtype S.} The value of this attribute is of the type @i{universal_integer}.]} @begin{Ramification} S'Scale is negative if S'Delta is greater than one. By contrast, S'Aft is always positive. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Round>, Text=[S'Round denotes a function with the following specification: @begin(Descexample) @b(function) S'Round(@RI(X) : @RI(universal_real)) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the value obtained by rounding X (away from 0, if X is midway between two values of the type of S).]} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} All subtypes of a fixed point type will have the same value for the Delta attribute, in the absence of @nt<delta_constraint>s (see @RefSecNum(Reduced Accuracy Subtypes)). S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0. @PDefn2{Term=[predefined operations],Sec=(of a fixed point type)} The predefined operations of a fixed point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators @en@; and +, multiplying operators, and the unary operator @key(abs). As for all types, objects of a fixed point type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). Other attributes of fixed point types are defined in @RefSecNum{Attributes of Fixed Point Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0005],ARef=[AI95-00054-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that @i<small> may be specified only for ordinary fixed point types.]} @end{DiffWord95} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/03b.mss��������������������������������������������������������������0000755�0001752�0001001�00000311756�12273462240�016546� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2006/10/17 05:29:42 $} @Comment{$Source: e:\\cvsroot/ARM/Source/03b.mss,v $} @Comment{$Revision: 1.66 $} @LabeledClause{Array Types} @begin{Intro} @Defn{array} @Defn{array type} An @i(array) object is a composite object consisting of components which all have the same subtype. The name for a component of an array uses one or more index values belonging to specified discrete types. The value of an array object is a composite value consisting of the values of the components. @end{Intro} @begin{Syntax} @Syn{lhs=<array_type_definition>,rhs=" @Syn2{unconstrained_array_definition} | @Syn2{constrained_array_definition}"} @Syn{lhs=<unconstrained_array_definition>,rhs=" @key{array}(@Syn2{index_subtype_definition} {, @Syn2{index_subtype_definition}}) @key{of} @Syn2{component_definition}"} @Syn{lhs=<index_subtype_definition>,rhs="@Syn2{subtype_mark} @key{range} <>"} @Syn{lhs=<constrained_array_definition>,rhs=" @key{array} (@Syn2{discrete_subtype_definition} {, @Syn2{discrete_subtype_definition}}) @key{of} @Syn2{component_definition}"} @Syn{lhs=<discrete_subtype_definition>,rhs="@SynI{discrete_}@Syn2{subtype_indication} | @Syn2{range}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00406-01]} @Syn{lhs=<component_definition>,rhs="@Chg{Version=[2],New=< >,Old=<>}[@key{aliased}] @Syn2{subtype_indication}@Chg{Version=[2],New=< | [@key{aliased}] @Syn2{access_definition}>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(discrete_subtype_definition range)} For a @nt<discrete_subtype_definition> that is a @nt<range>, the @nt<range> shall resolve to be of some specific discrete type@Redundant[; which discrete type shall be determined without using any context other than the bounds of the @nt<range> itself (plus the preference for @i(root_integer) @em see @RefSecNum(The Context of Overload Resolution)).] @end{Resolution} @begin{Legality} @Defn{index subtype} Each @nt{index_subtype_definition} or @nt{discrete_subtype_definition} in an @nt{array_type_definition} defines an @i(index subtype); @Defn{index type} its type (the @i(index type)) shall be discrete. @begin{Discussion} @Defn2{Term=[index], Sec=(of an array)} An @i(index) is a discrete quantity used to select along a given dimension of an array. A component is selected by specifying corresponding values for each of the indices. @end{Discussion} @Defn{component subtype} The subtype defined by the @nt<subtype_indication> of a @nt<component_definition> (the @i(component subtype)) shall be a definite subtype. @begin{Ramification} This applies to all uses of @nt<component_definition>, including in @nt<record_type_definition>s and @nt<protected_definition>s.@end{ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[Within the definition of a nonlimited composite type (or a limited composite type that later in its immediate scope becomes nonlimited @em see @RefSecNum{Private Operations} and @RefSecNum{Limited Types}), if a @nt{component_definition} contains the reserved word @key[aliased] and the type of the component is discriminated, then the nominal subtype of the component shall be constrained.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgNote{The rule's gone, we might as well clobber all the notes.} @ChgDeleted{Version=[2],Text=[If we allowed the subtype to be unconstrained, then the discriminants might change because of an assignment to the containing (nonlimited) object, thus causing a potential violation of an access subtype constraint of an access value designating the aliased component.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that the rule elsewhere defining all aliased discriminated objects to be constrained does not help @em that rule prevents assignments to the component itself from doing any harm, but not assignments to the containing object.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Type=[Leading],Text=[We allow this for components within limited types since assignment to the enclosing object is not a problem. Furthermore, it is important to be able to use a default expression for a discriminant in arrays of limited components, since that is the only way to give the components different values for their discriminants. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@key[protected] @key[type] Counter_Type(Initial_Value : Integer := 1) @key[is] @key[procedure] Get_Next(Next_Value : @key[out] Integer); --@RI{ Returns the next value on each call, bumping Count} --@RI{ before returning.} @key[private] Count : Integer := Initial_Value; @key[end] Counter_Type; @key[protected] @key[body] Counter_Type @key[is] ...]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@key[function] Next_Id(Counter : @key[access] Counter_Type) @key[return] Integer @key[is] Result : Integer; @key[begin] Counter.Get_Next(Result); @key[return] Result; @key[end] Next_Id;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[C : @key[aliased] Counter_Type; @key[task] @key[type] T(Who_Am_I : Integer := Next_Id(C'Access)); @key[task] @key[body] T @key[is] ...]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Task_Array : @key[array](1..100) @key[of] @key[aliased] T; --@RI{ Array of task elements, each with its own unique ID.} --@RI{ We specify "aliased" so we can use Task_Array(I)'Access.} --@RI{ This is safe because Task_Array is of a limited type,} --@RI{ so there is no way an assignment to it could change} --@RI{ the discriminants of one of its components.}]} @end{Example} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that this rule applies to array components and record components, but not to protected type components (since they are always limited).]} @end{Ramification} @end{Legality} @begin{StaticSem} @Defn2{Term=[dimensionality], Sec=(of an array)} @Defn{one-dimensional array} @Defn{multi-dimensional array} An array is characterized by the number of indices (the @i(dimensionality) of the array), the type and position of each index, the lower and upper bounds for each index, and the subtype of the components. The order of the indices is significant. A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; @Defn{index range} this range of values is called the @i(index range). @Defn2{Term=[bounds], Sec=(of an array)} The @i(bounds) of an array are the bounds of its index ranges. @Defn2{Term=[length], Sec=(of a dimension of an array)} The @i(length) of a dimension of an array is the number of values of the index range of the dimension (zero for a null range). @Defn2{Term=[length], Sec=(of a one-dimensional array)} The @i(length) of a one-dimensional array is the length of its only dimension. An @nt<array_type_definition> defines an array type and its first subtype. For each object of this array type, the number of indices, the type and position of each index, and the subtype of the components are as in the type definition@Redundant[; the values of the lower and upper bounds for each index belong to the corresponding index subtype of its type, except for null arrays (see @RefSecNum(Index Constraints and Discrete Ranges))]. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} An @nt{unconstrained_array_definition} defines an array type with an unconstrained first subtype. Each @nt{index_@!subtype_@!definition} defines the corresponding index subtype to be the subtype denoted by the @nt{subtype_@!mark}. @redundant[@PDefn2{Term=[box], Sec=(compound delimiter)} The compound delimiter <> (called a @i(box)) of an @nt<index_subtype_definition> stands for an undefined range (different objects of the type need not have the same bounds).] @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt{constrained_array_definition} defines an array type with a constrained first subtype. Each @nt{discrete_@!subtype_@!definition} defines the corresponding index subtype, as well as the corresponding index range for the constrained first subtype. @PDefn2{Term=[constraint], Sec=(of a first array subtype)} The @i(constraint) of the first subtype consists of the bounds of the index ranges. @begin{Discussion} Although there is no namable unconstrained array subtype in this case, the predefined slicing and concatenation operations can operate on and yield values that do not necessarily belong to the first array subtype. This is also true for Ada 83. @end{Discussion} @Leading@;The discrete subtype defined by a @nt{discrete_@!subtype_@!definition} is either that defined by the @nt{subtype_@!indication}, or a subtype determined by the @nt{range} as follows: @begin(itemize) If the type of the @nt{range} resolves to @i(root_integer), then the @nt{discrete_subtype_definition} defines a subtype of the predefined type Integer with bounds given by a conversion to Integer of the bounds of the @nt<range>; @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a range)} @begin{Reason} This ensures that indexing over the discrete subtype can be performed with regular Integers, rather than only @i(universal_integer)s. @end{Reason} @begin{Discussion} We considered doing this by simply creating a @lquotes@;preference@rquotes@; for Integer when resolving the @nt<range>. @PDefn{Beaujolais effect} However, this can introduce @i(Beaujolais) effects when the @nt<simple_expression>s involve calls on functions visible due to @key(use) clauses. @end{Discussion} Otherwise, the @nt{discrete_subtype_definition} defines a subtype of the type of the @nt{range}, with the bounds given by the @nt<range>. @end(itemize) @PDefn2{Term=[nominal subtype], Sec=(of a component)} The @nt{component_definition} of an @nt<array_type_definition> defines the nominal subtype of the components. If the reserved word @key(aliased) appears in the @nt{component_definition}, then each component of the array is aliased (see @RefSecNum{Access Types}). @begin(Ramification) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See @RefSecNum{Record Types}.]} @end(Ramification) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(array_type_definition)} The elaboration of an @nt{array_type_definition} creates the array type and its first subtype, and consists of the elaboration of any @nt{discrete_@!subtype_@!definition}s and the @nt{component_@!definition}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @PDefn2{Term=[elaboration], Sec=(discrete_subtype_definition)} The elaboration of a @nt{discrete_subtype_definition} @Chg{New=[that does not contain any per-object expressions],Old=[]} creates the discrete subtype, and consists of the elaboration of the @nt{subtype_@!indication} or the evaluation of the @nt{range}. @Chg{New=[The elaboration of a @nt{discrete_subtype_definition} that contains one or more per-object expressions is defined in @RefSecNum{Record Types}.],Old=[]} @PDefn2{Term=[elaboration], Sec=(component_definition)} The elaboration of a @nt{component_@!definition} in an @nt{array_@!type_@!definition} consists of the elaboration of the @nt{subtype_@!indication}@Chg{Version=[2],New=[ or @nt{access_definition}],Old=[]}. The elaboration of any @nt{discrete_@!subtype_@!definition}s and the elaboration of the @nt{component_@!definition} are performed in an arbitrary order. @end{RunTime} @begin{Notes} All components of an array have the same subtype. In particular, for an array of components that are one-dimensional arrays, this means that all components have the same bounds and hence the same length. Each elaboration of an @nt<array_type_definition> creates a distinct array type. A consequence of this is that each object whose @nt<object_declaration> contains an @nt<array_type_definition> is of its own unique type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of type declarations with unconstrained array definitions: ) @begin(Example) @key(type) Vector @key(is) @key(array)(Integer @key(range) <>) @key(of) Real; @key(type) Matrix @key(is) @key(array)(Integer @key(range) <>, Integer @key(range) <>) @key(of) Real; @key(type) Bit_Vector @key(is) @key(array)(Integer @key(range) <>) @key(of) Boolean; @key(type) Roman @key(is) @key(array)(Positive @key(range) <>) @key(of) Roman_Digit; --@RI[ see @RefSecNum(Character Types)] @end(Example) @begin{Wide} @leading@keepnext@i(Examples of type declarations with constrained array definitions: ) @end{Wide} @begin(Example) @key(type) Table @key(is) @key(array)(1 .. 10) @key(of) Integer; @key(type) Schedule @key(is) @key(array)(Day) @key(of) Boolean; @key(type) Line @key(is) @key(array)(1 .. Max_Line_Size) @key(of) Character; @end(Example) @begin{Wide} @leading@keepnext@i(Examples of object declarations with array type definitions: ) @end{Wide} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Grid @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(1 .. 80, 1 .. 100) @key(of) Boolean; Mix @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(Color @key(range) Red .. Green) @key(of) Boolean;@Chg{Version=[2],New=[ Msg_Table : @key(constant array)(Error_Code) @key(of access constant) String := (Too_Big => @key(new) String'("Result too big"), Too_Small => ...);],Old=[]} Page @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(Positive @key(range) <>) @key(of) Line := --@RI[ an array of arrays] (1 | 50 => Line'(1 | Line'Last => '+', @key(others) => '-'), --@RI[ see @RefSecNum(Array Aggregates)] 2 .. 49 => Line'(1 | Line'Last => '|', @key(others) => ' ')); --@RI[ Page is constrained by its initial value to (1..50)] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{component_definition} is modified to allow the reserved word @key{aliased}. The syntax rules for @nt{unconstrained_array_definition} and @nt{constrained_array_definition} are modified to use @nt{component_definition} (instead of @i(component_)@nt{subtype_indication}). The effect of this change is to allow the reserved word @key{aliased} before the component @nt{subtype_indication}. A @nt{range} in a @nt{discrete_subtype_definition} may use arbitrary universal expressions for each bound (e.g. @en@;1 .. 3+5), rather than strictly "implicitly convertible" operands. The subtype defined will still be a subtype of Integer. @end{Extend83} @begin{DiffWord83} We introduce a new syntactic category, @nt{discrete_subtype_definition}, as distinct from @nt{discrete_range}. These two constructs have the same syntax, but their semantics are quite different (one defines a subtype, with a preference for Integer subtypes, while the other just selects a subrange of an existing subtype). We use this new syntactic category in @key(for) loops and entry families. The syntax for @nt{index_constraint} and @nt{discrete_range} have been moved to their own subclause, since they are no longer used here. The syntax rule for @nt{component_definition} (formerly @ntf<component_subtype_definition>) is moved here from RM83-3.7. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00406-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Array components can have an anonymous access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[The prohibition against unconstrained discriminated aliased components has been lifted. It has been replaced by a prohibition against the actual troublemakers: general access discriminant constraints (see @RefSecNum{Discriminant Constraints}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to allow the elaboration of per-object constraints for constrained arrays.]} @end{DiffWord95} @LabeledSubClause{Index Constraints and Discrete Ranges} @begin{Intro} An @nt<index_constraint> determines the range of possible values for every index of an array subtype, and thereby the corresponding array bounds. @end{Intro} @begin{Syntax} @Syn{lhs=<index_constraint>,rhs=" (@Syn2{discrete_range} {, @Syn2{discrete_range}})"} @Syn{lhs=<discrete_range>,rhs="@SynI{discrete_}@Syn2{subtype_indication} | @Syn2{range}"} @end{Syntax} @begin{Resolution} @Defn{type of a @nt{discrete_range}} The type of a @nt<discrete_range> is the type of the subtype defined by the @nt<subtype_indication>, or the type of the @nt<range>. @PDefn2{Term=[expected type], Sec=(index_constraint discrete_range)} For an @nt{index_constraint}, each @nt{discrete_range} shall resolve to be of the type of the corresponding index. @begin(Discussion) In Ada 95, @nt{index_constraint}s only appear in a @nt{subtype_indication}; they no longer appear in @nt<constrained_array_definition>s. @end(Discussion) @end{Resolution} @begin{Legality} An @nt{index_constraint} shall appear only in a @nt{subtype_indication} whose @nt{subtype_mark} denotes either an unconstrained array subtype, or an unconstrained access subtype whose designated subtype is an unconstrained array subtype; in either case, the @nt{index_constraint} shall provide a @nt{discrete_range} for each index of the array type. @end{Legality} @begin{StaticSem} @Defn2{Term=[bounds], Sec=(of a @nt<discrete_range>)} A @nt{discrete_range} defines a range whose bounds are given by the @nt{range}, or by the range of the subtype defined by the @nt{subtype_indication}. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(index constraint with a subtype)} An @nt{index_constraint} is @i(compatible) with an unconstrained array subtype if and only if the index range defined by each @nt{discrete_range} is compatible (see @RefSecNum(Scalar Types)) with the corresponding index subtype. @Defn{null array} If any of the @nt<discrete_range>s defines a null range, any array thus constrained is a @i(null array), having no components. @PDefn2{Term=[satisfies], Sec=(an index constraint)} An array value @i(satisfies) an @nt{index_constraint} if at each index position the array value and the @nt{index_constraint} have the same index bounds. @begin{Ramification} There is no need to define compatibility with a constrained array subtype, because one is not allowed to constrain it again.@end{ramification} @PDefn2{Term=[elaboration], Sec=(index_constraint)} The elaboration of an @nt{index_constraint} consists of the evaluation of the @nt{discrete_range}(s), in an arbitrary order. @PDefn2{Term=[evaluation], Sec=(discrete_range)} The evaluation of a @nt{discrete_range} consists of the elaboration of the @nt{subtype_indication} or the evaluation of the @nt{range}. @end{RunTime} @begin{Notes} The elaboration of a @nt<subtype_indication> consisting of a @nt<subtype_mark> followed by an @nt<index_constraint> checks the compatibility of the @nt<index_constraint> with the @nt<subtype_mark> (see @RefSecNum(Subtype Declarations)). Even if an array value does not satisfy the index constraint of an array subtype, Constraint_Error is not raised on conversion to the array subtype, so long as the length of each dimension of the array value and the array subtype match. See @RefSecNum(Type Conversions). @end{Notes} @begin{Examples} @leading@keepnext@i(Examples of array declarations including an index constraint: ) @begin(Example) Board : Matrix(1 .. 8, 1 .. 8); --@RI[ see @RefSecNum(Array Types)] Rectangle : Matrix(1 .. 20, 1 .. 30); Inverse : Matrix(1 .. N, 1 .. N); --@RI[ N need not be static ] Filter : Bit_Vector(0 .. 31); @end(Example) @begin{Wide} @leading@keepnext@i(Example of array declaration with a constrained array subtype: ) @end{Wide} @begin(Example) My_Schedule : Schedule; --@RI[ all arrays of type Schedule have the same bounds] @end(Example) @begin{Wide} @leading@keepnext@i(Example of record type with a component that is an array: ) @end{Wide} @begin(Example) @key(type) Var_Line(Length : Natural) @key(is) @key(record) Image : String(1 .. Length); @key(end) @key(record); Null_Line : Var_Line(0); --@RI[ Null_Line.Image is a null array] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We allow the declaration of a variable with a nominally unconstrained array subtype, so long as it has an initialization expression to determine its bounds. @end{Extend83} @begin{DiffWord83} We have moved the syntax for @nt{index_constraint} and @nt{discrete_range} here since they are no longer used in @nt{constrained_array_definition}s. We therefore also no longer have to describe the (special) semantics of @nt{index_constraint}s and @nt{discrete_range}s that appear in @nt{constrained_array_definition}s. The rules given in RM83-3.6.1(5,7-10), which define the bounds of an array object, are redundant with rules given elsewhere, and so are not repeated here. RM83-3.6.1(6), which requires that the (nominal) subtype of an array variable be constrained, no longer applies, so long as the variable is explicitly initialized. @end{DiffWord83} @LabeledSubClause{Operations of Array Types} @begin{Legality} @Redundant[The argument N used in the @nt<attribute_designator>s for the N-th dimension of an array shall be a static @nt<expression> of some integer type.] The value of N shall be positive (nonzero) and no greater than the dimensionality of the array. @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0006],ARef=[AI95-00030-01]} The following attributes are defined for @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}], Old=[prefix]} A that is of an array type @Redundant[(after any implicit dereference)], or denotes a constrained array subtype]}: @begin{Ramification} These attributes are not defined if A is a subtype-mark for an access-to-array subtype. They are defined (by implicit dereference) for access-to-array values.@end{ramification} @begin(description) @Attribute{Prefix=<A>, AttrName=<First>, Text=[A'First denotes the lower bound of the first index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<First(N)>, Text=[A'First(N) denotes the lower bound of the N-th index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Last>, Text=[A'Last denotes the upper bound of the first index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Last(N)>, Text=[A'Last(N) denotes the upper bound of the N-th index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Range>, Text=[A'Range is equivalent to the range A'First .. A'Last, except that the @nt<prefix> A is only evaluated once.]} @Attribute{Prefix=<A>, AttrName=<Range(N)>, Text=[A'Range(N) is equivalent to the range A'First(N) .. A'Last(N), except that the @nt<prefix> A is only evaluated once.]} @Attribute{Prefix=<A>, AttrName=<Length>, Text=[A'Length denotes the number of values of the first index range (zero for a null range); its type is @i(universal_integer).]} @Attribute{Prefix=<A>, AttrName=<Length(N)>, Text=[A'Length(N) denotes the number of values of the N-th index range (zero for a null range); its type is @i(universal_integer).]} @end(description) @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} An implementation should normally represent multidimensional arrays in row-major order, consistent with the notation used for multidimensional array aggregates (see @RefSecNum(Array Aggregates)). However, if a @key<pragma> Convention(Fortran, ...) applies to a multidimensional array type, then column-major order should be used instead (see @RefSec{Interfacing with Fortran}). @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Multidimensional arrays should be represented in row-major order, unless the array has convention Fortran.]}]} @end{ImplAdvice} @begin{Notes} @Leading@;The @nt<attribute_reference>s A'First and A'First(1) denote the same value. A similar relation exists for the @nt<attribute_reference>s A'Last, A'Range, and A'Length. The following relation is satisfied (except for a null array) by the above attributes if the index type is an integer type: @begin(example) A'Length(N) = A'Last(N) - A'First(N) + 1 @end(example) An array type is limited if its component type is limited (see @RefSecNum(Limited Types)). @PDefn2{Term=[predefined operations],Sec=(of an array type)} The predefined operations of an array type include the membership tests, qualification, and explicit conversion. If the array type is not limited, they also include assignment and the predefined equality operators. For a one-dimensional array type, they include the predefined concatenation operators (if nonlimited) and, if the component type is discrete, the predefined relational operators; if the component type is boolean, the predefined logical operators are also included. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A component of an array can be named with an @nt<indexed_component>. A value of an array type can be specified with an @nt<array_aggregate>@Chg{Version=[2],New=[],Old=[, unless the array type is limited]}. For a one-dimensional array type, a slice of the array can be named; also, string literals are defined if the component type is a character type. @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples (using arrays declared in the examples of subclause @RefSecNum(Index Constraints and Discrete Ranges)):} @begin(Example) -- Filter'First = 0 Filter'Last = 31 Filter'Length = 32 -- Rectangle'Last(1) = 20 Rectangle'Last(2) = 30 @end(Example) @end{Examples} @LabeledSubClause{String Types} @begin{StaticSem} @Defn{string type} A one-dimensional array type whose component type is a character type is called a @i(string) type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@redundant[There are @Chg{Version=[2],New=[three],Old=[two]} predefined string types, String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2],New=[, and Wide_Wide_String],Old=[]}, each indexed by values of the predefined subtype Positive; these are declared in the visible part of package Standard:] @begin(example) @redundant[@key(subtype) Positive @key(is) Integer @key(range) 1 .. Integer'Last; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @key(type) String @key(is) @key(array)(Positive @key(range) <>) @key(of) Character; @key(type) Wide_String @key(is) @key(array)(Positive @key(range) <>) @key(of) Wide_Character; @Chg{Version=[2],New=[@key(type) Wide_Wide_String @key(is) @key(array)(Positive @key(range) <>) @key(of) Wide_Wide_Character;],Old=[]} ]@end(example) @end{StaticSem} @begin{Notes} String literals (see @RefSecNum(String Literals) and @RefSecNum(Literals)) are defined for all string types. The concatenation operator & is predefined for string types, as for all nonlimited one-dimensional array types. The ordering operators <, <=, >, and >= are predefined for string types, as for all one-dimensional discrete array types; these ordering operators correspond to lexicographic order (see @RefSecNum(Relational Operators and Membership Tests)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of string objects:) @begin(Example) @TabClear()@TabSet(P50) Stars : String(1 .. 120) := (1 .. 120 => '*' ); Question : @key(constant) String := "How many characters?"; @\--@RI[ Question'First = 1, Question'Last = 20] @\--@RI[ Question'Length = 20 (the number of characters)] Ask_Twice : String := Question & Question;@\--@RI[ constrained to (1..40)] Ninety_Six : @key(constant) Roman := "XCVI";@\--@RI[ see @RefSecNum(Character Types) and @RefSecNum(Array Types)] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The declaration of Wide_String in Standard hides a use-visible declaration with the same @nt<defining_identifier>. In rare cases, this might result in an inconsistency between Ada 83 and Ada 95. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Because both String and Wide_String are always directly visible, an expression like @begin(Example) "a" < "bc" @end(Example) is now ambiguous, whereas in Ada 83 both string literals could be resolved to type String. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The type Wide_String is new (though it was approved by ARG for Ada 83 compilers as well). @end{Extend83} @begin{DiffWord83} We define the term @i(string type) as a natural analogy to the term @i(character type). @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} The declaration of Wide_Wide_String in Standard hides a use-visible declaration with the same @nt<defining_identifier>. In the (very) unlikely event that an Ada 95 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Wide_String, the meaning of the program will be different.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The type Wide_Wide_String is new.]} @end{Extend95} @LabeledClause{Discriminants} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00326-01]} @redundant[@Defn{discriminant} @IndexSee{Term=[type parameter],See=(discriminant)} @IndexSeeAlso{Term=[parameter],See=(discriminant)} A composite type (other than an array@Chg{Version=[2],New=[ or interface],Old=[]} type) can have discriminants, which parameterize the type. A @nt<known_discriminant_part> specifies the discriminants of a composite type. A discriminant of an object is a component of the object, and is either of a discrete type or an access type. An @nt<unknown_discriminant_part> in the declaration of a@Chg{Version=[2],New=[],Old=[ partial]} view of a type specifies that the discriminants of the type are unknown for the given view; all subtypes of such a@Chg{Version=[2],New=[],Old=[ partial]} view are indefinite subtypes.] @ChgRef{Version=[2],Kind=[Revised]} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Discriminant>, Text=<A discriminant is a parameter @Chg{Version=[2],New=[for],Old=[of]} a composite type. It can control, for example, the bounds of a component of the type if @Chg{Version=[2],New=[the component is],Old=[that type is]} an array@Chg{Version=[2],New=[],Old=[ type]}. A discriminant @Chg{Version=[2],New=[for],Old=[of]} a task type can be used to pass data to a task of the type upon creation.>} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @PDefn{unknown discriminants} @PDefn2{Term=[discriminants], Sec=(unknown)} A @Chg{Version=[2],New=[view of a ],Old=[]}type, and all @Chg{Version=[2],New=[], Old=[of its ]}subtypes@Chg{Version=[2],New=[ of the view],Old=[]}, have @i(unknown discriminants) when the number or names of the discriminants, if any, are unknown at the point of the type declaration@Chg{Version=[2],New=[ for the view],Old=[]}. A @nt<discriminant_part> of (<>) is used to indicate unknown discriminants. @end{Discussion} @end{Intro} @begin{Metarules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00402-01]} @ChgAdded{Version=[2],Text=[When an access discriminant is initialized at the time of object creation with an allocator of an anonymous type, the allocated object and the object with the discriminant are tied together for their lifetime. They should be allocated out of the same storage pool, and then at the end of the lifetime of the enclosing object, finalized and reclaimed together. In this case, the allocated object is called a coextension (see @RefSecNum{Operations of Access Types}).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above principle when applied to a nonlimited type implies that such an object may be copied only to a shorter-lived object, because attempting to assign it to a longer-lived object would fail because the access discriminants would not match. In a copy, the lifetime connection between the enclosing object and the allocated object does not exist. The allocated object is tied in the above sense only to the original object. Other copies have only secondary references to it.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that when an @nt{allocator} appears as a constraint on an access discriminant in a @nt{subtype_indication} that is elaborated independently from object creation, no such connection exists. For example, if a named constrained subtype is declared via "@key{subtype} Constr @key{is} Rec(Acc_Discrim => @key{new} T);" or if such an @nt{allocator} appears in the @nt{subtype_indication} for a component, the allocator is evaluated when the @nt{subtype_indication} is elaborated, and hence its lifetime is typically longer than the objects or components that will later be subject to the constraint. In these cases, the allocated object should not be reclaimed until the @nt{subtype_indication} goes out of scope.]} @end{Discussion} @end{Metarules} @begin{Syntax} @Syn{lhs=<discriminant_part>,rhs="@Syn2{unknown_discriminant_part} | @Syn2{known_discriminant_part}"} @Syn{lhs=<unknown_discriminant_part>,rhs="(<>)"} @Syn{lhs=<known_discriminant_part>,rhs=" (@Syn2{discriminant_specification} {; @Syn2{discriminant_specification}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<discriminant_specification>,rhs=" @Syn2{defining_identifier_list} : @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [:= @Syn2{default_expression}] | @Syn2{defining_identifier_list} : @Syn2{access_definition} [:= @Syn2{default_expression}]"} @Syn{lhs=<default_expression>,rhs="@Syn2{expression}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(discriminant default_expression)} The expected type for the @nt{default_expression} of a @nt{discriminant_specification} is that of the corresponding discriminant. @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0007],ARef=[AI95-00098-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} A @Chg{New=[@nt{discriminant_part}],Old=[@nt{known_discriminant_part}]} is only permitted in a declaration for a composite type that is not an array@Chg{Version=[2],New=[ or interface],Old=[]} type @Redundant[(this includes generic formal types)]@Chg{New=[. A],Old=[; a]} type declared with a @nt<known_discriminant_part> is called a @i(discriminated) type,@Defn{discriminated type} as is a type that inherits (known) discriminants. @begin{ImplNote} Discriminants on array types were considered, but were omitted to ease (existing) implementations. @end{implnote} @begin(Discussion) Note that the above definition for @lquotes@;discriminated type@rquotes@; does not include types declared with an @nt<unknown_discriminant_part>. This seems consistent with Ada 83, where such types (in a generic formal part) would not be considered discriminated types. Furthermore, the full type for a type with unknown discriminants need not even be composite, much less have any discriminants. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0007],ARef=[AI95-00098-01]} @Chg{New=[On the other hand, @nt<unknown_discriminant_part>s cannot be applied to type declarations that cannot have a @nt<known_discriminant_part>. There is no point in having unknown discriminants on a type that can never have discriminants (for instance, a formal modular type), even when these are allowed syntactically.],Old=[]} @end(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} The subtype of a discriminant may be defined by@Chg{Version=[2],New=[ an optional @nt{null_exclusion} and],Old=[]} a @nt<subtype_mark>, in which case the @nt<subtype_mark> shall denote a discrete or access subtype, or it may be defined by an @nt<access_definition>@Chg{Version=[2],New=[],Old=[ @Redundant[(in which case the @nt<subtype_mark> of the @nt<access_definition> may denote any kind of subtype)]]}. @Defn{access discriminant} A discriminant that is defined by an @nt<access_definition> is called an @i(access discriminant) and is of an anonymous @Chg{Version=[2],New=[access], Old=[general access-to-variable]} type@Chg{Version=[2],New=[],Old=[ whose designated subtype is denoted by the @nt<subtype_mark> of the @nt<access_definition>]}. @begin(Reason) @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgNote{It still does cause complexities. :-)}@ChgNote{We don't want to delete "Reason:" here, thus we use @Chg and not @ChgDeleted} @Chg{Version=[2],New=[],Old=[In an early version of Ada 9X, we allowed access discriminants on nonlimited types, but this created unpleasant complexities. It turned out to be simpler and more uniform to allow discriminants of a named access type on any discriminated type, and keep access discriminants just for limited types.]} Note that discriminants of a named access type are not considered @lquotes@;access discriminants.@rquotes@; Similarly, @lquotes@;access parameter@rquotes@; only refers to a formal parameter defined by an @nt<access_definition>. @end(Reason) @ChgNote{This paragraph is just moved up} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00402-01]} @ChgAdded{Version=[2],Text=[@nt{Default_expression}s shall be provided either for all or for none of the discriminants of a @nt{known_@!discriminant_@!part}. No @nt<default_@!expression>s are permitted in a @nt<known_@!discriminant_@!part> in a declaration of a tagged type @Redundant[or a generic formal type].]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The all-or-none rule is related to the rule that a discriminant constraint shall specify values for all discriminants. One could imagine a different rule that allowed a constraint to specify only some of the discriminants, with the others provided by default. Having defaults for discriminants has a special significance @em it allows objects of the type to be unconstrained, with the discriminants alterable as part of assigning to the object.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Defaults for discriminants of tagged types are disallowed so that every object of a tagged type is constrained, either by an explicit constraint, or by its initial discriminant values. This substantially simplifies the semantic rules and the implementation of inherited dispatching operations. For generic formal types, the restriction simplifies the type matching rules. If one simply wants a "default" value for the discriminants, a constrained subtype can be declared for future use.]} @end(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00402-01],ARef=[AI95-00419-01]} A @nt<discriminant_specification> for an access discriminant @Chg{Version=[2],New=[may have a @nt{default_expression}],Old=[shall appear]} only in the declaration for a task or protected type, or for a type @Chg{Version=[2],New=[that is a descendant of an explicitly limited record type],Old=[with the reserved word @key[limited] in its @Redundant[(full)] definition or in that of one of its ancestors]}. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.@PDefn{generic contract issue} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} This rule implies that a type can have @Chg{Version=[2], New=[a default for ],Old=[]}an access discriminant if the type is limited, but not if the only reason it's limited is because of a limited component. Compare with the definition of limited type in @RefSecNum{Limited Types}.@Chg{Version=[2],New=[ Also, recall that a @lquotes@;descendant@rquote includes the type itself, so an explicitly limited record type can have defaults.],Old=[]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[ It is a consequence of this rule that only a return-by-reference type can have an access discriminant (see @RefSecNum{Return Statements}). This is important to avoid dangling references to local variables.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Leading@Keepnext@;We @Chg{Version=[2],New=[],Old=[also ]}considered the following rules@Chg{Version=[2],New=[ for access discriminants],Old=[]}: @begin{Itemize} If a type has an access discriminant, this automatically makes it limited, just like having a limited component automatically makes a type limited. This was rejected because it decreases program readability, and because it seemed error prone (two bugs in a previous version of the RM9X were attributable to this rule). @ChgRef{Version=[2],Kind=[Revised]} A type with an access discriminant shall be limited. This is equivalent to the rule we actually chose@Chg{Version=[2],New=[ for Ada 95],Old=[]}, except that it allows a type to have an access discriminant if it is limited just because of a limited component. For example, any record containing a task would be allowed to have an access discriminant, whereas the actual rule requires @lquotes@key[limited] @key[record]@rquotes@;. This rule was also rejected due to readability concerns, and because would interact badly with the rules for limited types that @lquotes@;become nonlimited@rquotes@;. @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A type may have an access discriminant if it is a limited partial view, or a task, protected, or explicitly limited record type. This was the rule chosen for Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant. For nonlimited type, there is no special accessibility for access discriminants; they're the same as any other anonymous access component. For a limited type, they have the special accessibility of Ada 95. However, this doesn't work because a limited partial view can have a nonlimited full view -- giving the two views different accessibility.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, as above. However, special accessibility rules only apply to types that are @lquotes@;really@rquotes@; limited (task, protected, and explicitly limited records). However, this breaks privacy; worse, @LegalityTitle depend on the definition of accessibility.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, as above. Limited types have special accessibility, while nonlimited types have normal accessibility. However, a limited partial view with an access discriminant can only be completed by a task, protected, or explicitly limited record type. That prevents accessibility from changing. A runtime accessibility check is required on generic formal types with access discriminants. However, changing between limited and nonlimited types would have far-reaching consequences for access discriminants @em which is uncomfortable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant. All types have special accessibility. This was considered early during the Ada 9X process, but was dropped for @lquotes@;unpleasant complexities@rquotes@;, which unfortunately aren't recorded. It does seem that an accessibility check would be needed on assignment of such a type, to avoid copying an object with a discriminant pointing to a local object into a more global object (and thus creating a dangling pointer).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, but access discriminants cannot have defaults. All types have special accessibility. This gets rid of the problems on assignment (you couldn't change such a discriminant), but it would be horribly incompatible with Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, but access discriminants may have defaults only if they are a @lquotes@;really@rquotes@; limited type. This is the rule chosen for Ada 2005, as it is not incompatible, and it doesn't require weird accessibility checks.]} @end{Itemize} @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00402-01]} @ChgDeleted{Version=[2],Text=[@nt{Default_expression}s shall be provided either for all or for none of the discriminants of a @nt{known_@!discriminant_@!part}. No @nt<default_@!expression>s are permitted in a @nt<known_@!discriminant_@!part> in a declaration of a tagged type @Redundant[or a generic formal type].]} @begin(Reason) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The all-or-none rule is related to the rule that a discriminant constraint shall specify values for all discriminants. One could imagine a different rule that allowed a constraint to specify only some of the discriminants, with the others provided by default. Having defaults for discriminants has a special significance @em it allows objects of the type to be unconstrained, with the discriminants alterable as part of assigning to the object.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Defaults for discriminants of tagged types are disallowed so that every object of a tagged type is constrained, either by an explicit constraint, or by its initial discriminant values. This substantially simplifies the semantic rules and the implementation of inherited dispatching operations. For generic formal types, the restriction simplifies the type matching rules. If one simply wants a "default" value for the discriminants, a constrained subtype can be declared for future use.]} @end(Reason) @Leading@;For a type defined by a @nt<derived_type_definition>, if a @nt<known_discriminant_part> is provided in its declaration, then: @begin{Itemize} The parent subtype shall be constrained; If the parent type is not a tagged type, then each discriminant of the derived type shall be used in the constraint defining the parent subtype;@begin{ImplNote} This ensures that the new discriminant can share storage with an existing discriminant.@end{implnote} If a discriminant is used in the constraint defining the parent subtype, the subtype of the discriminant shall be statically compatible (see @RefSecNum{Statically Matching Constraints and Subtypes}) with the subtype of the corresponding parent discriminant. @begin(Reason) This ensures that on conversion (or extension via an extension aggregate) to a distantly related type, if the discriminants satisfy the target type's requirements they satisfy all the intermediate types' requirements as well. @end(Reason) @begin(Ramification) There is no requirement that the new discriminant have the same (or any) @nt<default_expression> as the parent's discriminant. @end(Ramification) @end{Itemize} The type of the @nt<default_expression>, if any, for an access discriminant shall be convertible to the anonymous access type of the discriminant (see @RefSecNum{Type Conversions}). @PDefn2{Term=[convertible],Sec=(required)} @begin{Ramification} This requires convertibility of the designated subtypes. @end{ramification} @end{Legality} @begin{StaticSem} A @nt{discriminant_specification} declares a discriminant; the @nt{subtype_mark} denotes its subtype unless it is an access discriminant, in which case the discriminant's subtype is the anonymous access-to-variable subtype defined by the @nt{access_definition}. @Redundant[For a type defined by a @nt<derived_type_definition>, each discriminant of the parent type is either inherited, constrained to equal some new discriminant of the derived type, or constrained to the value of an expression.] @Defn{corresponding discriminants} When inherited or constrained to equal some new discriminant, the parent discriminant and the discriminant of the derived type are said to @i(correspond). Two discriminants also correspond if there is some common discriminant to which they both correspond. A discriminant corresponds to itself as well. @Defn{specified discriminant} If a discriminant of a parent type is constrained to a specific value by a @nt<derived_type_definition>, then that discriminant is said to be @i(specified) by that @nt<derived_type_definition>. @begin{Ramification} The correspondence relationship is transitive, symmetric, and reflexive. That is, if A corresponds to B, and B corresponds to C, then A, B, and C each corresponds to A, B, and C in all combinations.@end{ramification} @Defn2{Term=[depend on a discriminant], Sec=(for a @nt<constraint> or @nt<component_definition>)} A @nt{constraint} that appears within the definition of a discriminated type @i(depends on a discriminant) of the type if it names the discriminant as a bound or discriminant value. A @nt{component_definition} depends on a discriminant if its @nt{constraint} depends on the discriminant, or on a discriminant that corresponds to it. @begin(Ramification) A @nt{constraint} in a @nt{task_body} is not considered to @i(depend) on a discriminant of the task type, even if it names it. It is only the @nt<constraint>s in the type definition itself that are considered dependents. Similarly for protected types. @end(Ramification) @Leading@keepnext@Defn2{Term=[depend on a discriminant], Sec=(for a component)} A component @i(depends on a discriminant) if: @begin(itemize) Its @nt{component_definition} depends on the discriminant; or @begin{Ramification} A component does @i(not) depend on a discriminant just because its @nt<default_expression> refers to the discriminant.@end{ramification} It is declared in a @nt{variant_part} that is governed by the discriminant; or It is a component inherited as part of a @nt<derived_type_definition>, and the @nt<constraint> of the @i(parent_)@nt<subtype_indication> depends on the discriminant; or @begin{Reason} When the parent subtype depends on a discriminant, the parent part of the derived type is treated like a discriminant-dependent component. @end{Reason} @begin{Ramification} Because of this rule, we don't really need to worry about @lquotes@;corresponding@rquotes@; discriminants, since all the inherited components will be discriminant-dependent if there is a new @nt<known_discriminant_part> whose discriminants are used to constrain the old discriminants. @end{Ramification} It is a subcomponent of a component that depends on the discriminant. @end(itemize) @begin{Reason} The concept of discriminant-dependent (sub)components is primarily used in various rules that disallow renaming or 'Access, or specify that certain discriminant-changing assignments are erroneous. The goal is to allow implementations to move around or change the size of discriminant-dependent subcomponents upon a discriminant-changing assignment to an enclosing object. The above definition specifies that all subcomponents of a discriminant-dependent component or parent part are themselves discriminant-dependent, even though their presence or size does not in fact depend on a discriminant. This is because it is likely that they will move in a discriminant-changing assignment if they are a component of one of several discriminant-dependent parts of the same record. @end{Reason} Each value of a discriminated type includes a value for each component of the type that does not depend on a discriminant@Redundant[; this includes the discriminants themselves]. The values of discriminants determine which other component values are present in the value of the discriminated type. @begin{Honest} Which values are present might depend on discriminants of some ancestor type that are constrained in an intervening @nt<derived_type_definition>. That's why we say "values of discriminants" instead of "values of @i(the) discriminants" @em a subtle point.@end{honest} @Defn{known discriminants} @Defn2{Term=[discriminants], Sec=(known)} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A type declared with a @nt<known_discriminant_part> is said to have @i(known discriminants); its first subtype is unconstrained. @Defn{unknown discriminants} @Defn2{Term=[discriminants], Sec=(unknown)} A type declared with an @nt<unknown_discriminant_part> is said to have @i(unknown discriminants). A type declared without a @nt<discriminant_part> has no discriminants, unless it is a derived type; if derived, such a type has the same sort of discriminants (known, unknown, or none) as its parent (or ancestor) type. A tagged class-wide type also has unknown discriminants. @Defn{class-wide type} @Defn{indefinite subtype} @Redundant[Any subtype of a type with unknown discriminants is an unconstrained and indefinite subtype (see @RefSecNum{Types and Subtypes} and @RefSecNum{Objects and Named Numbers}).] @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An @nt<unknown_discriminant_part> @lquotes@;(<>)@rquotes@; is only permitted in the declaration of a (generic or nongeneric) private type, private extension, @Chg{Version=[2],New=[incomplete type, ],Old=[]}or formal derived type.@Comment{That was always intended, but 8652/0007 was needed to make it true.} Hence, only such types, descendants thereof, and class-wide types can have unknown discriminants. An @nt<unknown_discriminant_part> is used to indicate that the corresponding actual or full type might have discriminants without defaults, or be an unconstrained array subtype. Tagged class-wide types are also considered to have unknown discriminants because discriminants can be added by type extensions, so the total number of discriminants of any given value of a tagged class-wide type is not known at compile time. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A subtype with unknown discriminants is indefinite, and hence an object of such a subtype needs explicit initialization.@Chg{Version=[2],New=[],Old=[ If the subtype is limited, no (stand-alone) objects can be declared since initialization is not permitted (though formal parameters are permitted, and objects of the actual/full type will generally be declarable).]} A limited private type with unknown discriminants is @lquotes@;extremely@rquotes@; limited;@Chg{Version=[2],New=[ objects of],Old=[]} such a type @Chg{Version=[2],New=[ can be initialized only by subprograms (either procedures with a parameter of the type, or a function returning the type) declared in the package. Subprograms declared elsewhere can operate on and even return the type, but they can only initialize the object by calling (ultimately) a subprogram in the package declaring the type. Such a type],Old=[]} is useful for keeping complete control over object creation within the package declaring the type. A partial view of a type might have unknown discriminants, while the full view of the same type might have known, unknown, or no discriminants@Chg{New=[.],Old=[,]} @end(Discussion) @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[For an access discriminant, its], Old=[An]} @nt<access_definition> is elaborated when the value of @Chg{Version=[2],New=[the],Old=[a corresponding]} access discriminant is defined@Chg{Version=[2],New=[:],Old=[, either]} by evaluation of its @nt<default_expression>@Chg{Version=[2],New=[,],Old=[ or]} by elaboration of a @nt<discriminant_constraint>@Chg{Version=[2],New=[, or by an assignment that initializes the enclosing object.],Old=[. @Redundant[The elaboration of an @nt<access_definition> creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see @RefSecNum{Type Conversions}).]]} @PDefn2{Term=[implicit subtype conversion],Sec=(access discriminant)} @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[The],Old=[This]} conversion@Chg{Version=[2],New=[ of the @nt{expression} defining the access discriminant to the anonymous access type],Old=[]} raises @Chg{Version=[2],New=[Program_Error], Old=[Constraint_Error if the initial value is @key(null), or,]} for an object created by an allocator of an access type T, if the initial value is an access parameter that designates a view whose accessibility level is deeper than that of T. @end(Ramification) @end{RunTime} @begin{Notes} If a discriminated type has @nt<default_expression>s for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization. @begin(Discussion) This connection between discriminant defaults and unconstrained variables can be a source of confusion. For Ada 95, we considered various ways to break the connection between defaults and unconstrainedness, but ultimately gave up for lack of a sufficiently simple and intuitive alternative. @Defn{mutable} An unconstrained discriminated subtype with defaults is called a @i{mutable} subtype, and a variable of such a subtype is called a mutable variable, because the discriminants of such a variable can change. There are no mutable arrays (that is, the bounds of an array object can never change), because there is no way in the language to define default values for the bounds. Similarly, there are no mutable class-wide subtypes, because there is no way to define the default tag, and defaults for discriminants are not allowed in the tagged case. Mutable tags would also require a way for the maximum possible size of such a class-wide subtype to be known. (In some implementations, all mutable variables are allocated with the maximum possible size. This approach is appropriate for real-time applications where implicit use of the heap is inappropriate.) @end(Discussion) The @nt{default_expression} for a discriminant of a type is evaluated when an object of an unconstrained subtype of the type is created. Assignment to a discriminant of an object (after its initialization) is not allowed, since the name of a discriminant is a constant; neither @nt{assignment_statement}s nor assignments inherent in passing as an @key(in out) or @key(out) parameter are allowed. Note however that the value of a discriminant can be changed by assigning to the enclosing object, presuming it is an unconstrained variable. @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An @nt{unknown_discriminant_part} is permitted only in the declaration of a private type (including generic formal private), private extension, @Chg{Version=[2],New=[incomplete type, ],Old=[]}or generic formal derived type. These are the things that will have a corresponding completion or generic actual, which will either define the discriminants, or say there are none. The (<>) indicates that the actual/full subtype might be an indefinite subtype. An @nt{unknown_discriminant_part} is not permitted in a normal untagged derived type declaration, because there is no separate full type declaration for such a type. Note that (<>) allows unconstrained array bounds; those are somewhat like undefaulted discriminants. For a derived type, either the discriminants are inherited as is, or completely respecified in a new @nt<discriminant_part>. In this latter case, each discriminant of the parent type shall be constrained, either to a specific value, or to equal one of the new discriminants. Constraining a parent type's discriminant to equal one of the new discriminants is like a renaming of the discriminant, except that the subtype of the new discriminant can be more restrictive than that of the parent's one. In any case, the new discriminant can share storage with the parent's discriminant. @end(Discussion) A discriminant that is of a named access type is not called an access discriminant; that term is used only for discriminants defined by an @nt<access_definition>. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of discriminated types:) @begin(Example) @key(type) Buffer(Size : Buffer_Size := 100) @key(is) --@RI[ see @RefSecNum(Integer Types)] @key(record) Pos : Buffer_Size := 0; Value : String(1 .. Size); @key(end) @key(record); @key(type) Matrix_Rec(Rows, Columns : Integer) @key(is) @key(record) Mat : Matrix(1 .. Rows, 1 .. Columns); --@RI[ see @RefSecNum(Array Types)] @key(end) @key(record); @key(type) Square(Side : Integer) @key(is) @key(new) Matrix_Rec(Rows => Side, Columns => Side); @key(type) Double_Square(Number : Integer) @key(is) @key(record) Left : Square(Number); Right : Square(Number); @key(end) @key(record); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @Chg{Version=[2],New=[@key(task type) Worker(Prio : System.Priority; Buf : @key(access) Buffer) @key(is) --@RI[ discriminants used to parameterize the task type (see @RefSecNum{Task Units and Task Objects})] @key(pragma) Priority(Prio); --@RI[ see @RefSecNum{Task Priorities}] @key(entry) Fill; @key(entry) Drain; @key(end) Worker;],Old=[@key(type) Item(Number : Positive) @key(is) @key(record) Content : Integer; --@RI[ no component depends on the discriminant] @key(end) @key(record);]} @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{discriminant_specification} is modified to allow an @i{access discriminant}, with a type specified by an @nt{access_definition} (see @RefSecNum{Access Types}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Discriminants are allowed on all composite types other than array@Chg{Version=[2],New=[ and interface],Old=[]} types. Discriminants may be of an access type. @end{Extend83} @begin{DiffWord83} @nt{Discriminant_part}s are not elaborated, though an @nt<access_definition> is elaborated when the discriminant is initialized. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Access discriminants (anonymous access types used as a discriminant) can be used on any type allowing discriminants. Defaults aren't allowed on discriminants of non-limited types, however, so that accessibility problems don't happen on assignment.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[ @nt{null_exclusion} can be used in the declaration of a discriminant.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0007],ARef=[AI95-00098-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was clarified so that types that cannot have discriminants cannot have an @nt{unknown_discriminant_part}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent interfaces from having discriminants. We don't want interfaces to have any components.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[Removed wording which implied or required an access discriminant to have an access-to-object type (anonymous access types can now be access-to-subprogram types as well).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Fixed the wording of the introduction to this clause to reflect that both incomplete and partial views can have unknown discriminants. That was always true, but for some reason this wording specified partial views.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the new term @lquotes@;explicitly limited record@rquotes, which makes the intent much clearer (and eliminates confusion with derived types that happen to contain the reserved word @key(limited).]} @end{DiffWord95} @LabeledSubClause{Discriminant Constraints} @begin{Intro} A @nt<discriminant_constraint> specifies the values of the discriminants for a given discriminated type. @end{Intro} @begin{MetaRules} The rules in this clause are intentionally parallel to those given in Record Aggregates. @end{MetaRules} @begin{Syntax} @Syn{lhs=<discriminant_constraint>,rhs=" (@Syn2{discriminant_association} {, @Syn2{discriminant_association}})"} @Syn{lhs=<discriminant_association>,rhs=" [@SynI{discriminant_}@Syn2{selector_name} {| @SynI{discriminant_}@Syn2{selector_name}} =>] @Syn2{expression}"} @begin{SyntaxText} @Defn{named discriminant association} A @nt<discriminant_association> is said to be @i(named) if it has one or more @i(discriminant_)@nt<selector_name>s; @Defn{positional discriminant association} it is otherwise said to be @i(positional). In a @nt<discriminant_constraint>, any positional associations shall precede any named associations. @end{SyntaxText} @end{Syntax} @begin{Resolution} Each @nt<selector_name> of a named @nt<discriminant_@!association> shall resolve to denote a discriminant of the subtype being constrained; @Defn2{Term=[associated discriminants], Sec=(of a named @nt<discriminant_association>)} the discriminants so named are the @i(associated discriminants) of the named association. @Defn2{Term=[associated discriminants], Sec=(of a positional @nt<discriminant_association>)} For a positional association, the @i(associated discriminant) is the one whose @nt<discriminant_@!specification> occurred in the corresponding position in the @nt<known_@!discriminant_@!part> that defined the discriminants of the subtype being constrained. @PDefn2{Term=[expected type], Sec=(discriminant_association expression)} The expected type for the @nt{expression} in a @nt{discriminant_association} is that of the associated discriminant(s). @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} A @nt{discriminant_constraint} is only allowed in a @nt{subtype_indication} whose @nt{subtype_mark} denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype. @Chg{New=[However, in the case of @Chg{Version=[2],New=[an],Old=[a general]} access subtype, a @nt{discriminant_@!constraint} is illegal if @Chg{Version=[2],New=[the designated type has a partial view that is constrained or, for a general access subtype, has @nt{default_expression}s for its discriminants. In addition to the places where @LegalityTitle@; normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit. In a generic body, this rule is checked presuming all formal access types of the generic might be general access types, and all untagged discriminated formal types of the generic might have @nt{default_expression}s for their discriminants. @PDefn{generic contract issue}], Old=[there is a place within the immediate scope of the designated subtype where the designated subtype's view is constrained.]}],Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[@Chg{New=[The second rule is necessary to prevent assignments that change the discriminant of a constrained object. See the defect report for examples.],Old=[]}]} @end{Reason} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[The second rule is necessary to prevent objects from changing so that they no longer match their constraint. In Ada 95, we attempted to prevent this by banning every case where an aliased object could be unconstrained or be changed by an enclosing assignment. New ways to cause this problem were being discovered frequently, meaning that new rules had to be dreamed up to cover them. Meanwhile, aliased objects and components were getting more and more limited. In Ada 2005, we sweep away all of that cruft and replace it by a simple rule @lquotes@;thou shalt not create an access subtype that can point to an item whose discriminants can be changed by assignment@rquotes@;.]} @end{Reason} A named @nt<discriminant_association> with more than one @nt<selector_name> is allowed only if the named discriminants are all of the same type. A @nt<discriminant_constraint> shall provide exactly one value for each discriminant of the subtype being constrained. The @nt<expression> associated with an access discriminant shall be of a type convertible to the anonymous access type. @PDefn2{Term=[convertible],Sec=(required)} @begin(Ramification) This implies both convertibility of designated types, and static accessibility. This implies that if an object of type T with an access discriminant is created by an allocator for an access type A, then it requires that the type of the @nt<expression> associated with the access discriminant have an accessibility level that is not statically deeper than that of A. This is to avoid dangling references. @end(Ramification) @end{Legality} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(discriminant constraint with a subtype)} A @nt{discriminant_constraint} is @i(compatible) with an unconstrained discriminated subtype if each discriminant value belongs to the subtype of the corresponding discriminant. @begin{Ramification} The "dependent compatibility check" has been eliminated in Ada 95. Any checking on subcomponents is performed when (and if) an object is created.@end{ramification} @begin{Discussion} There is no need to define compatibility with a constrained discriminated subtype, because one is not allowed to constrain it again.@end{discussion} @PDefn2{Term=[satisfies], Sec=(a discriminant constraint)} A composite value @i(satisfies) a discriminant constraint if and only if each discriminant of the composite value has the value imposed by the discriminant constraint. @PDefn2{Term=[elaboration], Sec=(discriminant_constraint)} For the elaboration of a @nt{discriminant_constraint}, the @nt{expression}s in the @nt{discriminant_association}s are evaluated in an arbitrary order and converted to the type of the associated discriminant (which might raise Constraint_Error @em see @RefSecNum{Type Conversions}); the @nt{expression} of a named association is evaluated (and converted) once for each associated discriminant. @PDefn2{Term=[implicit subtype conversion],Sec=(discriminant values)} The result of each evaluation and conversion is the value imposed by the constraint for the associated discriminant. @begin{Reason} We convert to the type, not the subtype, so that the definition of compatibility of discriminant constraints is not vacuous.@end{reason} @end{RunTime} @begin{Notes} The rules of the language ensure that a discriminant of an object always has a value, either from explicit or implicit initialization. @begin(Discussion) Although it is illegal to constrain a class-wide tagged subtype, it is possible to have a partially constrained class-wide subtype: If the subtype S is defined by T(A => B), then S'Class is partially constrained in the sense that objects of subtype S'Class have to have discriminants corresponding to A equal to B, but there can be other discriminants defined in extensions that are not constrained to any particular value. @end(Discussion) @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples (using types declared above in clause @RefSecNum(Discriminants)):} @begin(Example) Large : Buffer(200); --@RI[ constrained, always 200 characters] --@RI[ (explicit discriminant value)] Message : Buffer; --@RI[ unconstrained, initially 100 characters] --@RI[ (default discriminant value)] Basis : Square(5); --@RI[ constrained, always 5 by 5] Illegal : Square; --@RI[ illegal, a Square has to be constrained] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Dependent compatibility checks are no longer performed on subtype declaration. Instead they are deferred until object creation (see @RefSecNum(Object Declarations)). This is upward compatible for a program that does not raise Constraint_Error. @end{Inconsistent83} @begin{DiffWord83} Everything in RM83-3.7.2(7-12), which specifies the initial values for discriminants, is now redundant with 3.3.1, 6.4.1, 8.5.1, and 12.4. Therefore, we don't repeat it here. Since the material is largely intuitive, but nevertheless complicated to state formally, it doesn't seem worth putting it in a "NOTE." @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0008],ARef=[AI95-00168-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The Corrigendum added a restriction on @nt{discriminant_constraint}s for general access subtypes. Such constraints are prohibited if the designated type can be treated as constrained somewhere in the program. Ada 2005 goes further and prohibits such @nt{discriminant_constraint}s if the designated type has (or might have, in the case of a formal type) defaults for its discriminants. The use of general access subtypes is rare, and this eliminates a boatload of problems that required many restrictions on the use of aliased objects and components (now lifted). Similarly, Ada 2005 prohibits @nt{discriminant_constraint}s on any access type whose designated type has a partial view that is constrained. Such a type will not be constrained in the heap to avoid privacy problems. Again, the use of such subtypes is rare (they can only happen within the package and its child units).]} @end{Incompatible95} @LabeledSubClause{Operations of Discriminated Types} @begin{Intro} @Redundant[If a discriminated type has @nt<default_expression>s for its discriminants, then unconstrained variables of the type are permitted, and the discriminants of such a variable can be changed by assignment to the variable. For a formal parameter of such a type, an attribute is provided to determine whether the corresponding actual parameter is constrained or unconstrained.] @end{Intro} @begin{StaticSem} For @PrefixType{a @nt<prefix> A that is of a discriminated type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @Attribute{Prefix=<A>, AttrName=<Constrained>, Text=[Yields the value True if A denotes a constant, a value, or a constrained variable, and False otherwise.]} @begin(ImplNote) This attribute is primarily used on parameters, to determine whether the discriminants can be changed as part of an assignment. The Constrained attribute is statically True for @key(in) parameters. For @key(in out) and @key(out) parameters of a discriminated type, the value of this attribute needs to be passed as an implicit parameter, in general. However, if the type does not have defaults for its discriminants, the attribute is statically True, so no implicit parameter is needed. Parameters of a limited type with defaulted discriminants need this implicit parameter, unless there are no nonlimited views, because they might be passed to a subprogram whose body has visibility on a nonlimited view of the type, and hence might be able to assign to the object and change its discriminants. @end(ImplNote) @end(description) @EndPrefixType{} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} The execution of a construct is erroneous if the construct has a constituent that is a @nt<name> denoting a subcomponent that depends on discriminants, and the value of any of these discriminants is changed by this execution between evaluating the @nt<name> and the last use (within this execution) of the subcomponent denoted by the @nt<name>. @begin{Ramification} This rule applies to @nt<assignment_statement>s, calls (except when the discriminant-dependent subcomponent is an @key(in) parameter passed by copy), @nt<indexed_component>s, and @nt<slice>s. Ada 83 only covered the first two cases. AI83-00585 pointed out the situation with the last two cases. The cases of @nt<object_renaming_declaration>s and generic formal @key(in out) objects are handled differently, by disallowing the situation at compile time. @end{Ramification} @end{Erron} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Defn{extensions to Ada 83} For consistency with other attributes, we are allowing the @Chg{New=[@nt{prefix}],Old=[prefix]} of Constrained to be a value as well as an object of a discriminated type, and also an implicit dereference. These extensions are not important capabilities, but there seems no reason to make this attribute different from other similar attributes. We are curious what most Ada 83 compilers do with F(1).X'Constrained. We now handle in a general way the cases of erroneousness identified by AI83-00585, where the @nt<prefix> of an @nt<indexed_component> or @nt<slice> is discriminant-dependent, and the evaluation of the index or discrete range changes the value of a discriminant. @end{Extend83} @begin{DiffWord83} We have moved all discussion of erroneous use of @nt<name>s that denote discriminant-dependent subcomponents to this subclause. In Ada 83, it used to appear separately under @nt{assignment_statement}s and subprogram calls. @end{DiffWord83} @LabeledClause{Record Types} @begin{Intro} @Defn{record} @Defn{record type} A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components. @IndexSee{Term=[structure],See=(record type)} @end{Intro} @begin{Syntax} @Syn{lhs=<record_type_definition>,rhs="[[@key{abstract}] @key{tagged}] [@key{limited}] @Syn2{record_definition}"} @Syn{lhs=<record_definition>,rhs=" @key{record} @Syn2{component_list} @key{end} @key{record} | @key{null record}"} @Syn{lhs=<component_list>,rhs=" @Syn2{component_item} {@Syn2{component_item}} | {@Syn2{component_item}} @Syn2{variant_part} | @key{null};"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<component_item>,rhs="@Syn2{component_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @Syn{lhs=<component_declaration>,rhs=" @Syn2{defining_identifier_list} : @Syn2{component_definition} [:= @Syn2{default_expression}];"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(component_declaration default_expression)} The expected type for the @nt<default_expression>, if any, in a @nt<component_declaration> is the type of the component. @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A @nt<default_expression> is not permitted if the component is of a limited type.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]}@ChgNote{This is not THE definition of component} @PDefn2{Term=[components], Sec=(of a record type)} Each @nt<component_declaration> declares a @Chg{Version=[2],New=[component],Old=[@i(component)]} of the record type. Besides components declared by @nt<component_declaration>s, the components of a record type include any components declared by @nt<discriminant_specification>s of the record type declaration. @Redundant[The identifiers of all components of a record type shall be distinct.] @begin{TheProof} The identifiers of all components of a record type have to be distinct because they are all declared immediately within the same declarative region. See Section 8. @end{theproof} Within a @nt{type_declaration}, a @nt{name} that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases: @begin{Itemize} A @nt{name} that denotes any component, protected subprogram, or entry is allowed within a representation item that occurs within the declaration of the composite type. A @nt{name} that denotes a noninherited discriminant is allowed within the declaration of the type, but not within the @nt{discriminant_part}. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in a @nt<derived_type_definition> then its name shall appear alone as a @nt<direct_name> (not as part of a larger expression or expanded name). A discriminant shall not be used to define the constraint of a scalar component.@Defn2{Term=[discriminant],Sec=[use in a record definition]}@ChgNote{New index entry} @begin{Reason} The penultimate restriction simplifies implementation, and allows the outer discriminant and the inner discriminant or bound to possibly share storage. @end{reason} @begin{Ramification} Other rules prevent such a discriminant from being an inherited one. @end{ramification} @begin{Reason} The last restriction is inherited from Ada 83. The restriction is not really necessary from a language design point of view, but we did not remove it, in order to avoid unnecessary changes to existing compilers. @end{Reason} @begin{Discussion} Note that a discriminant can be used to define the constraint for a component that is of an access-to-composite type. @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} The above rules, and a similar one in @RefSecNum{Subprogram Declarations} for formal parameters, are intended to allow initializations of components or parameters to occur in @Chg{Version=[2], New=[a (nearly)],Old=[an]} arbitrary order @em whatever order is most efficient@Chg{Version=[2],New=[ (subject to the restrictions of @RefSecNum{Object Declarations})],Old=[]}, since one @nt{default_expression} cannot depend on the value of another one. @Chg{Version=[2],New=[They],Old=[It]} also prevent circularities. @end{Reason} @begin{Ramification} Inherited discriminants are not allowed to be denoted, except within representation items. However, the @SynI{discriminant_}@nt{selector_name} of the parent @nt{subtype_indication} is allowed to denote a discriminant of the parent. @end{Ramification} @end{Itemize} If the name of the current instance of a type (see @RefSecNum{The Context of Overload Resolution}) is used to define the constraint of a component, then it shall appear as a @nt{direct_name} that is the @nt<prefix> of an @nt{attribute_reference} whose result is of an access type, and the @nt{attribute_reference} shall appear alone. @begin{Reason} This rule allows T'Access or T'Unchecked_Access, but disallows, for example, a range constraint (1..T'Size). Allowing things like (1..T'Size) would mean that a per-object constraint could affect the size of the object, which would be bad. @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{explicitly limited record} @Defn2{Term=[record],Sec=(explicitly limited)} If a @nt{record_type_definition} includes the reserved word @key{limited}, the type is called an @i<explicitly limited record> type.]} @PDefn2{Term=[nominal subtype], Sec=(of a record component)} The @nt{component_definition} of a @nt<component_declaration> defines the (nominal) subtype of the component. If the reserved word @key(aliased) appears in the @nt{component_definition}, then the component is aliased (see @RefSecNum{Access Types}). @begin(Ramification) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See @RefSecNum{Array Types}.]} @end(Ramification) @Defn{null record} If the @nt<component_list> of a record type is defined by the reserved word @key(null) and there are no discriminants, then the record type has no components and all records of the type are @i(null records). A @nt<record_definition> of @key{null record} is equivalent to @key{record null; end record}. @begin{Ramification} This short-hand is available both for declaring a record type and a record extension @em see @RefSecNum(Type Extensions). @end{ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(record_type_definition)} The elaboration of a @nt{record_type_definition} creates the record type and its first subtype, and consists of the elaboration of the @nt<record_definition>. @PDefn2{Term=[elaboration], Sec=(record_definition)} The elaboration of a @nt<record_definition> consists of the elaboration of its @nt{component_list}, if any. @PDefn2{Term=[elaboration], Sec=(component_list)} The elaboration of a @nt{component_list} consists of the elaboration of the @nt{component_item}s and @nt{variant_part}, if any, in the order in which they appear. @PDefn2{Term=[elaboration], Sec=(component_declaration)} The elaboration of a @nt{component_declaration} consists of the elaboration of the @nt{component_definition}. @begin(Discussion) If the @nt<defining_identifier_list> has more than one @nt<defining_identifier>, we presume here that the transformation explained in @RefSecNum(Object Declarations) has already taken place. Alternatively, we could say that the @nt<component_definition> is elaborated once for each @nt<defining_identifier> in the list. @end(Discussion) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{per-object expression} @Defn{per-object constraint} @Defn{entry index subtype} Within the definition of a composite type, if a @nt<component_definition> or @nt<discrete_subtype_definition> (see @RefSecNum{Entries and Accept Statements}) includes a @nt<name> that denotes a discriminant of the type, or that is an @nt<attribute_reference> whose @nt<prefix> denotes the current instance of the type, the expression containing the @nt<name> is called a @i(per-object expression), and the @Chg{New=[@nt{constraint} or @nt{range}],Old=[constraint]} being defined is called a @i(per-object constraint). @PDefn2{Term=[elaboration], Sec=(component_definition)} For the elaboration of a @nt{component_definition} of a @nt<component_declaration>@Chg{New=[ or the @nt{discrete_@!subtype_@!definition} of an @nt{entry_@!declaration} for an entry family (see @RefSecNum{Entries and Accept Statements})],Old=[]},@Chg{Version=[2], New=[ if the component subtype is defined by an @nt{access_definition} or], Old=[]} if the @nt{constraint} @Chg{New=[or @nt{range}],Old=[]} of the @nt{subtype_indication} @Chg{New=[or @nt{discrete_@!subtype_@!definition}],Old=[]} is not a per-object constraint, then the@Chg{Version=[2],New=[ @nt{access_definition},],Old=[]} @nt{subtype_indication}@Chg{Version=[2],New=[,],Old=[]} @Chg{New=[or @nt{discrete_@!subtype_@!definition}],Old=[]} is elaborated. On the other hand, if the @nt{constraint} @Chg{New=[or @nt{range}],Old=[]} is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. @Chg{New=[Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant.],Old=[]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0002],ARef=[AI95-00171-01]} @Chg{New=[@PDefn2{Term=[Elaboration],Sec=(per-object constraint)}When a per-object constraint is elaborated @Redundant[(as part of creating an object)], each per-object expression of the constraint is evaluated. For other expressions, the values determined during the elaboration of the @nt{component_@!definition} or @nt{entry_@!declaration} are used. Any checks associated with the enclosing @nt{subtype_indication} or @nt{discrete_subtype_definition} are performed@Redundant[, including the subtype compatibility check (see @RefSecNum{Subtype Declarations}),] and the associated subtype is created.], Old=[]} @begin(Discussion) The evaluation of other expressions that appear in @nt<component_definition>s and @nt<discrete_subtype_definition>s is performed when the type definition is elaborated. The evaluation of expressions that appear as @nt<default_expression>s is postponed until an object is created. Expressions in representation items that appear within a composite type definition are evaluated according to the rules of the particular representation item. @end(Discussion) @end{RunTime} @begin{Notes} A @nt<component_declaration> with several identifiers is equivalent to a sequence of single @nt<component_declaration>s, as explained in @RefSecNum{Object Declarations}. The @nt<default_expression> of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a @nt<variant_part> @em see @RefSecNum{Object Declarations}). The subtype defined by a @nt<component_definition> (see @RefSecNum(Array Types)) has to be a definite subtype. If a record type does not have a @nt<variant_part>, then the same components are present in all values of the type. A record type is limited if it has the reserved word @key[limited] in its definition, or if any of its components are limited (see @RefSecNum{Limited Types}). @PDefn2{Term=[predefined operations],Sec=(of a record type)} The predefined operations of a record type include membership tests, qualification, and explicit conversion. If the record type is nonlimited, they also include assignment and the predefined equality operators. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A component of a record can be named with a @nt<selected_component>. A value of a record can be specified with a @nt<record_aggregate>@Chg{Version=[2], New=[],Old=[, unless the record type is limited]}. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of record type declarations: ) @begin(Example) @key(type) Date @key(is) @key(record) Day : Integer @key(range) 1 .. 31; Month : Month_Name; Year : Integer @key(range) 0 .. 4000; @key(end) @key(record); @key(type) Complex @key(is) @key(record) Re : Real := 0.0; Im : Real := 0.0; @key(end) @key(record); @end(Example) @begin{Wide} @leading@keepnext@i(Examples of record variables: ) @end{Wide} @begin(Example) Tomorrow, Yesterday : Date; A, B, C : Complex; --@RI[ both components of A, B, and C are implicitly initialized to zero ] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt<component_declaration> is modified to use @nt<component_definition> (instead of @ntf<component_subtype_definition>). The effect of this change is to allow the reserved word @key(aliased) before the @ntf<component_subtype_definition>. A short-hand is provided for defining a null record type (and a null record extension), as these will be more common for abstract root types (and derived types without additional components). The syntax rule for @nt{record_type_definition} is modified to allow the reserved words @key{tagged} and @key{limited}. Tagging is new. Limitedness is now orthogonal to privateness. In Ada 83 the syntax implied that limited private was sort of more private than private. However, limitedness really has nothing to do with privateness; limitedness simply indicates the lack of assignment capabilities, and makes perfect sense for nonprivate types such as record types. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The syntax rules now allow @Chg{New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]} to appear in a @nt{record_definition}. This is not a language extension, because @LegalityName@;s prevent all language-defined representation clauses from appearing there. However, an implementation-defined @nt{attribute_definition_clause} could appear there. The reason for this change is to allow the rules for @Chg{New=[@nt{aspect_clause}s],Old=[@nt{representation_clause}s]} and representation pragmas to be as similar as possible. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Record components can have an anonymous access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Limited components can be initialized, so long as the expression is one that allows building the object in place (such as an @nt{aggregate} or @nt{function_call}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Improved the description of the elaboration of per-object constraints.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Defined @i{explicitly limited record} type to use in other rules.]} @end{DiffWord95} @LabeledSubClause{Variant Parts and Discrete Choices} @begin{Intro} A record type with a @nt<variant_part> specifies alternative lists of components. Each @nt<variant> defines the components for the value or values of the discriminant covered by its @nt<discrete_choice_list>. @begin{Discussion} @RootDefn{cover a value} @nt{Discrete_choice_list}s and @nt{discrete_choice}s are said to @i(cover) values as defined below; which @nt{discrete_choice_list} covers a value determines which of various alternatives is chosen. These are used in @nt{variant_part}s, @nt{array_aggregate}s, and @nt{case_statement}s. @end{Discussion} @end{Intro} @begin{MetaRules} The definition of @lquotes@;cover@rquotes@; in this subclause and the rules about discrete choices are designed so that they are also appropriate for array aggregates and case statements. The rules of this subclause intentionally parallel those for case statements. @end{MetaRules} @begin{Syntax} @Syn{lhs=<variant_part>,rhs=" @key{case} @SynI{discriminant_}@Syn2{direct_name} @key{is} @Syn2{variant} {@Syn2{variant}} @key{end} @key{case};"} @Syn{lhs=<variant>,rhs=" @key{when} @Syn2{discrete_choice_list} => @Syn2{component_list}"} @Syn{lhs=<discrete_choice_list>,rhs="@Syn2{discrete_choice} {| @Syn2{discrete_choice}}"} @Syn{lhs=<discrete_choice>,rhs="@Syn2{expression} | @Syn2{discrete_range} | @key{others}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[discriminant], Sec=(of a @nt<variant_part>)} The @i(discriminant_)@nt{direct_name} shall resolve to denote a discriminant (called the @i(discriminant of the @nt<variant_part>)) specified in the @nt{known_discriminant_part} of the @nt{full_type_declaration} that contains the @nt{variant_part}. @PDefn2{Term=[expected type], Sec=(variant_part discrete_choice)} The expected type for each @nt{discrete_choice} in a @nt<variant> is the type of the discriminant of the @nt{variant_part}. @begin{Ramification} A @nt<full_type_declaration> with a @nt<variant_part> has to have a (new) @nt<known_discriminant_part>; the discriminant of the @nt<variant_part> cannot be an inherited discriminant. @end{Ramification} @end{Resolution} @begin{Legality} The discriminant of the @nt{variant_part} shall be of a discrete type. @begin{Ramification} It shall not be of an access type, named or anonymous.@end{ramification} The @nt{expression}s and @nt{discrete_range}s given as @nt{discrete_choice}s in a @nt{variant_part} shall be static. The @nt{discrete_choice} @key(others) shall appear alone in a @nt{discrete_choice_list}, and such a @nt{discrete_choice_list}, if it appears, shall be the last one in the enclosing construct. @Leading@PDefn2{Term=[cover a value], Sec=(by a @nt{discrete_choice})} A @nt<discrete_choice> is defined to @i(cover a value) in the following cases: @begin(itemize) A @nt{discrete_choice} that is an @nt{expression} covers a value if the value equals the value of the @nt{expression} converted to the expected type. A @nt{discrete_choice} that is a @nt{discrete_range} covers all values (possibly none) that belong to the range. The @nt{discrete_choice} @key{others} covers all values of its expected type that are not covered by previous @nt{discrete_choice_list}s of the same construct. @begin(Ramification) For @nt{case_statement}s, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range. @end(Ramification) @end(itemize) @PDefn2{Term=[cover a value], Sec=(by a @nt{discrete_choice_list})} A @nt{discrete_choice_list} covers a value if one of its @nt{discrete_choice}s covers the value. @Leading@keepnext@;The possible values of the discriminant of a @nt{variant_part} shall be covered as follows: @begin{itemize} If the discriminant is of a static constrained scalar subtype, then each non-@key{others} @nt{discrete_@!choice} shall cover only values in that subtype, and each value of that subtype shall be covered by some @nt{discrete_@!choice} @Redundant[(either explicitly or by @key<others>)]; If the type of the discriminant is a descendant of a generic formal scalar type then the @nt{variant_part} shall have an @key{others} @nt{discrete_choice};@begin{Reason} The base range is not known statically in this case.@end{reason} Otherwise, each value of the base range of the type of the discriminant shall be covered @Redundant[(either explicitly or by @key<others>)]. @end{itemize} Two distinct @nt{discrete_choice}s of a @nt{variant_part} shall not cover the same value. @end{Legality} @begin{StaticSem} If the @nt{component_list} of a @nt{variant} is specified by @key(null), the variant has no components. @Defn{govern a @nt{variant_part}} @Defn{govern a @nt{variant}} The discriminant of a @nt<variant_part> is said to @i(govern) the @nt<variant_part> and its @nt<variant>s. In addition, the discriminant of a derived type governs a @nt<variant_part> and its @nt<variant>s if it corresponds (see @RefSecNum(Discriminants)) to the discriminant of the @nt<variant_part>. @end{StaticSem} @begin{RunTime} A record value contains the values of the components of a particular @nt{variant} only if the value of the discriminant governing the @nt<variant> is covered by the @nt{discrete_choice_list} of the @nt{variant}. This rule applies in turn to any further @nt{variant} that is, itself, included in the @nt{component_list} of the given @nt{variant}. @PDefn2{Term=[elaboration], Sec=(variant_part)} The elaboration of a @nt{variant_part} consists of the elaboration of the @nt{component_list} of each @nt{variant} in the order in which they appear. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Example of record type with a variant part: ) @begin(Example) @key(type) Device @key(is) (Printer, Disk, Drum); @key(type) State @key(is) (Open, Closed); @key(type) Peripheral(Unit : Device := Disk) @key(is) @key(record) Status : State; @key(case) Unit @key(is) @key(when) Printer => Line_Count : Integer @key(range) 1 .. Page_Size; @key(when) @key(others) => Cylinder : Cylinder_Index; Track : Track_Number; @key(end) @key(case); @key(end) @key(record); @end(Example) @begin{Wide} @leading@keepnext@i(Examples of record subtypes:) @end{Wide} @begin(Example) @key(subtype) Drum_Unit @key(is) Peripheral(Drum); @key(subtype) Disk_Unit @key(is) Peripheral(Disk); @end(Example) @begin{Wide} @leading@keepnext@i(Examples of constrained record variables:) @end{Wide} @begin(Example) Writer : Peripheral(Unit => Printer); Archive : Disk_Unit; @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, the discriminant of a @nt{variant_part} is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an @key{others} @nt{discrete_choice} is required in this case. @end{Extend83} @begin{DiffWord83} The syntactic category @ntf{choice} is removed. The syntax rules for @nt{variant}, @nt{array_aggregate}, and @nt{case_statement} now use @nt{discrete_choice_list} or @nt{discrete_choice} instead. The syntax rule for @nt{record_aggregate} now defines its own syntax for named associations. We have added the term Discrete Choice to the title since this is where they are talked about. This is analogous to the name of the subclause "Index Constraints and Discrete Ranges" in the clause on Array Types. The rule requiring that the discriminant denote a discriminant of the type being defined seems to have been left implicit in RM83. @end{DiffWord83} ������������������org.adaic.arm_form/source_2005/03c.mss��������������������������������������������������������������0000755�0001752�0001001�00000774702�12273462240�016553� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:23 $} @Comment{$Source: e:\\cvsroot/ARM/Source/03c.mss,v $} @Comment{$Revision: 1.76 $} @LabeledClause{Tagged Types and Type Extensions} @begin{Intro} @redundant[@PDefn{dispatching operation} @Defn{polymorphism} @IndexSee{Term=[dynamic binding],See=(dispatching operation)} @IndexSeeAlso{Term=[generic unit],See=(dispatching operation)} @IndexSeeAlso{Term=[variant],See=(tagged type)} Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via @i(dispatching operations). @IndexSee{Term=[object-oriented programming (OOP)],See=[tagged types and type extensions]} @IndexSee{Term=[OOP (object-oriented programming)],See=[tagged types and type extensions]} @IndexSeeAlso{Term=[inheritance],See=[tagged types and type extension]}] @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The intended implementation model is for @Chg{Version=[2],New=[the static portion of ],Old=[]}a tag to be represented as a pointer to a statically allocated and link-time initialized type descriptor. The type descriptor contains the address of the code for each primitive operation of the type. It probably also contains other information, such as might make membership tests convenient and efficient.@Chg{Version=[2],New=[ Tags for nested type extensions must also have a dynamic part that identifies the particular elaboration of the type.],Old=[]} The primitive operations of a tagged type are known at its first freezing point; the type descriptor is laid out at that point. It contains linker symbols for each primitive operation; the linker fills in the actual addresses. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Primitive operations of type extensions that are declared at a level deeper than the level of the ultimate ancestor from which they are derived can be represented by wrappers that use the dynamic part of the tag to call the actual primitive operation. The dynamic part would generally be some way to represent the static link or display necessary for making a nested call. One implementation strategy would be to store that information in the extension part of such nested type extensions, and use the dynamic part of the tag to point at it. (That way, the @lquotes@;dynamic@rquotes@; part of the tag could be static, at the cost of indirect access.)]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If the tagged type is descended from any interface types, it also will need to include @lquotes@;subtags@rquotes@; (one for each interface) that describe the mapping of the primitive operations of the interface to the primitives of the type. These subtags could directly reference the primitive operations (for faster performance), or simply provide the tag @lquotes@;slot@rquotes@; numbers for the primitive operations (for easier derivation). In either case, the subtags would be used for calls that dispatch through a class-wide type of the interface.]} Other implementation models are possible. The rules ensure that @lquotes@;dangling dispatching@rquotes@; is impossible; that is, when a dispatching call is made, there is always a body to execute. This is different from some other object-oriented languages, such as Smalltalk, where it is possible to get a run-time error from a missing method. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Dispatching calls should be efficient, and should have a bounded worst-case execution time. This is important in a language intended for real-time applications. In the intended implementation model, a dispatching call involves calling indirect through the appropriate slot in the dispatch table. No complicated "method lookup" is involved@Chg{Version=[2],New=[ although a call which is dispatching on an interface may require a lookup of the appropriate interface subtag],Old=[]}. The programmer should have the choice at each call site of a dispatching operation whether to do a dispatching call or a statically determined call (i.e. whether the body executed should be determined at run time or at compile time). The same body should be executed for a call where the tag is statically determined to be T'Tag as for a dispatching call where the tag is found at run time to be T'Tag. This allows one to test a given tagged type with statically determined calls, with some confidence that run-time dispatching will produce the same behavior. All views of a type should share the same type descriptor and the same tag. The visibility rules determine what is legal at compile time; they have nothing to do with what bodies can be executed at run time. Thus, it is possible to dispatch to a subprogram whose declaration is not visible at the call site. In fact, this is one of the primary facts that gives object-oriented programming its power. The subprogram that ends up being dispatched to by a given call might even be designed long after the call site has been coded and compiled. Given that Ada has overloading, determining whether a given subprogram overrides another is based both on the names and the type profiles of the operations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} When a type extension is declared, if there is any place within its immediate scope where a certain subprogram of the parent @Chg{Version=[2],New=[or progenitor ],Old=[]}is visible, then a matching subprogram should override. If there is no such place, then a matching subprogram should be totally unrelated, and occupy a different slot in the type descriptor. This is important to preserve the privacy of private parts; when an operation declared in a private part is inherited, the inherited version can be overridden only in that private part, in the package body, and in any children of the package. If an implementation shares code for instances of generic bodies, it should be allowed to share type descriptors of tagged types declared in the generic body, so long as they are not extensions of types declared in the specification of the generic unit. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Defn{tagged type} A record type or private type that has the reserved word @key(tagged) in its declaration is called a @i(tagged) type.@Chg{Version=[2],New=[ In addition, an interface type is a tagged type, as is a task or protected type derived from an interface (see @RefSecNum{Interface Types}).],Old=[]} @Redundant[When deriving from a tagged type, @Chg{Version=[2],New=[as],Old=[additional components may be defined. As]} for any derived type, additional primitive subprograms may be defined, and inherited primitive subprograms may be overridden.] @Defn{type extension} @Defn2{Term=[extension], Sec=(of a type)} The derived type is called an @i(extension) of @Chg{Version=[2],New=[its],Old=[the]} ancestor @Chg{Version=[2],New=[types],Old=[type]}, or simply a @i(type extension).@Chg{Version=[2],New=[],Old=[ @Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is also a tagged type, and is either a @i(record extension) or a @i(private extension) of some other tagged type. A record extension is defined by a @nt<derived_type_definition> with a @nt<record_extension_part>. A private extension, which is a partial view of a record extension, can be declared in the visible part of a package (see @RefSecNum(Private Types and Private Extensions)) or in a generic formal part (see @RefSecNum(Formal Private and Derived Types)).]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is also a tagged type, and is a @i(record extension) or a @i(private extension) of some other tagged type, or a non-interface synchronized tagged type (see @RefSecNum{Interface Types}). A record extension is defined by a @nt<derived_type_definition> with a @nt<record_extension_part> (see @RefSecNum{Type Extensions})@Redundant[, which may include the definition of additional components]. A private extension, which is a partial view of a record extension or of a synchronized tagged type, can be declared in the visible part of a package (see @RefSecNum(Private Types and Private Extensions)) or in a generic formal part (see @RefSecNum(Formal Private and Derived Types)).]} @ToGlossary{Term=<Tagged type>, Text=<The objects of a tagged type have a run-time type tag, which indicates the specific type with which the object was originally created. An operand of a class-wide tagged type can be used in a dispatching call; the tag indicates which subprogram body to invoke. Nondispatching calls, in which the subprogram body to invoke is determined at compile time, are also allowed. Tagged types may be extended with additional components.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} If a tagged type is declared other than in a @nt{package_specification}, it is impossible to add new primitive subprograms for that type, although it can inherit primitive subprograms, and those can be overridden. If the user incorrectly thinks a certain subprogram is primitive when it is not, and tries to call it with a dispatching call, an error message will be given at the call site.@Chg{Version=[2],New=[ Similarly, by using an @nt{overriding_indicator} (see @RefSecNum{Subprogram Declarations}), the user can declare that a subprogram is intended to be overriding, and get an error message when they made a mistake. The use of @nt{overriding_indicator}s is highly recommended in new code that does not need to be compatible with Ada 95.],Old=[]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[Note that the accessibility rules imply that a tagged type declared in a library @nt{package_specification} cannot be extended in a nested subprogram or task body.]} @end{Ramification} @Defn{tag of an object} An object of a tagged type has an associated (run-time) @i(tag) that identifies the specific tagged type used to create the object originally. @Redundant[ The tag of an operand of a class-wide tagged type @i(T)'Class controls which subprogram body is to be executed when a primitive subprogram of type @i(T) is applied to the operand (see @RefSecNum(Dispatching Operations of Tagged Types)); @Defn{dispatching} using a tag to control which body to execute is called @i(dispatching).] @IndexSee{Term=[type tag],See=[tag]} @IndexSee{Term=[run-time type],See=[tag]} @IndexSeeAlso{Term=[type],See=[tag]} @IndexSeeAlso{Term=[class],See=[tag]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} The tag of a specific tagged type identifies the @nt<full_type_declaration> of the type@Chg{Version=[2],New=[, and for a type extension, is sufficient to uniquely identify the type among all descendants of the same ancestor],Old=[]}. If a declaration for a tagged type occurs within a @nt{generic_package_declaration}, then the corresponding type declarations in distinct instances of the generic package are associated with distinct tags. For a tagged type that is local to a generic package body@Chg{Version=[2], New=[ and with all of its ancestors (if any) also local to the generic body],Old=[]}, the language does not specify whether repeated instantiations of the generic body result in distinct tags.@PDefn{Unspecified} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[This eases generic code sharing.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[In most cases, a tag need only identify a particular tagged type declaration, and can therefore be a simple link-time-known address. However, for tag checks (see @RefSecNum{Dispatching Operations of Tagged Types}) it is essential that each descendant (that currently exists) of a given type have a unique tag. Hence, for types declared in shared generic bodies where an ancestor comes from outside the generic, or for types declared at a deeper level than an ancestor, the tag needs to be augmented with some kind of dynamic descriptor (which may be a static link, global display, instance descriptor pointer, or combination). This implies that type Tag may need to be two words, the second of which is normally null, but in these identified special cases needs to include a static link or equivalent. Within an object of one of these types with a two-word tag, the two parts of the tag would typically be separated, one part as the first word of the object, the second placed in the first extension part that corresponds to a type declared more nested than its parent or declared in a shared generic body when the parent is declared outside. Alternatively, by using an extra level of indirection, the type Tag could remain a single-word.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[For types that are not type extensions (even for ones declared in nested scopes), we do not require that], Old=[The language does not specify whether]} repeated elaborations of the same @nt<full_type_declaration> correspond to distinct tags. @Chg{Version=[2],New=[This was done so that Ada 2005 implementations of tagged types could maintain representation compatibility with Ada 95 implementations. Only type extensions that were not allowed in Ada 95 require additional information with the tag.], Old=[In most cases, we expect that all elaborations will correspond to the same tag, since the tag will frequently be the address (or index) of a statically allocated type descriptor. However, with shared generics, the type descriptor might have to be allocated on a per-instance basis, which in some implementation models implies per-elaboration of the instantiation.]} @end{implnote} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The wording @lquotes@;is sufficient to uniquely identify the type among all descendants of the same ancestor@rquotes@; only applies to types that currently exist. It is not necessary to distinguish between descendants that currently exist, and descendants of the same type that no longer exist. For instance, the address of the stack frame of the subprogram that created the tag is sufficient to meet the requirements of this rule, even though it is possible, after the subprogram returns, that a later call of the subprogram could have the same stack frame and thus have an identical tag.]} @end{Honest} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada],Child=[Tags]}@key[package] Ada.Tags @key[is] @Chg{Version=[2],New=[@key[pragma] Preelaborate(Tags); ],Old=[]}@key[type] @AdaTypeDefn{Tag} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Tag);],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Tag} : @key[constant] Tag;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} @key[function] @AdaSubDefn{Expanded_Name}(T : Tag) @key[return] String;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Expanded_Name}(T : Tag) @key[return] Wide_String; @key[function] @AdaSubDefn{Wide_Wide_Expanded_Name}(T : Tag) @key[return] Wide_Wide_String;],Old=[]} @key[function] @AdaSubDefn{External_Tag}(T : Tag) @key[return] String; @key[function] @AdaSubDefn{Internal_Tag}(External : String) @key[return] Tag; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Descendant_Tag}(External : String; Ancestor : Tag) @key[return] Tag; @key[function] @AdaSubDefn{Is_Descendant_At_Same_Level}(Descendant, Ancestor : Tag) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Parent_Tag} (T : Tag) @key[return] Tag;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[ @key[type] @AdaTypeDefn{Tag_Array} @key[is array] (Positive @key[range] <>) @key[of] Tag;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Interface_Ancestor_Tags} (T : Tag) @key[return] Tag_Array;]} @AdaExcDefn{Tag_Error} : @key[exception]; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Tags; @end{Example} @begin{Reason} Tag is a nonlimited, definite subtype, because it needs the equality operators, so that tag checking makes sense. Also, equality, assignment, and object declaration are all useful capabilities for this subtype. For an object X and a type T, @lquotes@;X'Tag = T'Tag@rquotes@; is not needed, because a membership test can be used. However, comparing the tags of two objects cannot be done via membership. This is one reason to allow equality for type Tag. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[No_Tag is the default initial value of type Tag.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[This is similar to the requirement that all access values be initialized to @key[null].]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} The function @Chg{Version=[2],New=[Wide_@!Wide_@!Expanded_@!Name], Old=[Expanded_@!Name]} returns the full expanded name of the first subtype of the specific type identified by the tag, in upper case, starting with a root library unit. The result is implementation defined if the type is declared within an unnamed @nt{block_statement}. @begin{Honest} This name, as well as each @nt{prefix} of it, does not denote a @nt{renaming_declaration}. @end{Honest} @ChgImplDef{Version=[2],Kind=[Revised],Text=[The result of @Chg{Version=[2], New=[Tags.Wide_@!Wide_@!Expanded_@!Name],Old=[Tags.Expanded_@!Name]} for types declared within an unnamed @nt{block_statement}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[The function Expanded_Name (respectively, Wide_Expanded_Name) returns the same sequence of graphic characters as that defined for Wide_Wide_Expanded_Name, if all the graphic characters are defined in Character (respectively, Wide_Character); otherwise, the sequence of characters is implementation defined, but no shorter than that returned by Wide_Wide_Expanded_Name for the same value of the argument.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[ The sequence of characters of the value returned by Tags.Expanded_Name (respectively, Tags.Wide_Expanded_Name) when some of the graphic characters of Tags.Wide_Wide_Expanded_Name are not defined in Character (respectively, Wide_Character).],Old=[]}]} The function External_Tag returns a string to be used in an external representation for the given tag. The call External_Tag(S'Tag) is equivalent to the @nt<attribute_reference> S'External_Tag (see @RefSecNum{Operational and Representation Attributes}). @begin{Reason} It might seem redundant to provide both the function External_Tag and the attribute External_Tag. The function is needed because the attribute can't be applied to values of type Tag. The attribute is needed so that it can be @Chg{Version=[2], New=[specified],Old=[specifiable]} via an @nt{attribute_definition_clause}. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=[The string returned by the functions Expanded_Name, Wide_Expanded_Name, Wide_Wide_Expanded_Name, and External_Tag has lower bound 1.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00279-01]} The function Internal_Tag returns @Chg{Version=[2],New=[a],Old=[the]} tag that corresponds to the given external tag, or raises Tag_Error if the given string is not the external tag for any specific type of the partition.@Chg{Version=[2],New=[ Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created (see @RefSecNum{Freezing Rules}).],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[The check for uncreated library-level types prevents a reference to the type before execution reaches the freezing point of the type. This is important so that T'Class'Input or an instance of Tags.Generic_Dispatching_Constructor do not try to create an object of a type that hasn't been frozen (which may not have yet elaborated its constraints). We don't require this behavior for non-library-level types as the tag can be created multiple times and possibly multiple copies can exist at the same time, making the check complex.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The function Descendant_Tag returns the (internal) tag for the type that corresponds to the given external tag and is both a descendant of the type identified by the Ancestor tag and has the same accessibility level as the identified ancestor. Tag_Error is raised if External is not the external tag for such a type. Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Descendant_Tag is used by T'Class'Input to identify the type identified by an external tag. Because there can be multiple elaborations of a given type declaration, Internal_Tag does not have enough information to choose a unique such type. Descendant_Tag does not return the tag for types declared at deeper accessibility levels than the ancestor because there could be ambiguity in the presence of recursion or multiple tasks. Descendant_Tag can be used in constructing a user-defined replacement for T'Class'Input.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The function Is_Descendant_At_Same_Level returns True if the Descendant tag identifies a type that is both a descendant of the type identified by Ancestor and at the same accessibility level. If not, it returns False.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Is_Descendant_At_Same_Level (or something similar to it) is used by T'Class'Output to determine whether the item being written is at the same accessibility level as T. It may be used to determine prior to using T'Class'Output whether Tag_Error will be raised, and also can be used in constructing a user-defined replacement for T'Class'Output.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The function Parent_Tag returns the tag of the parent type of the type whose tag is T. If the type does not have a parent type (that is, it was not declared by a derived_type_declaration), then No_Tag is returned.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The parent type is always the parent of the full type; a private extension appears to define a parent type, but it does not (only the various forms of derivation do that). As this is a run-time operation, ignoring privateness is OK.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[The function Interface_Ancestor_Tags returns an array containing the tag of each interface ancestor type of the type whose tag is T, other than T itself. The lower bound of the returned array is 1, and the order of the returned tags is unspecified. Each tag appears in the result exactly once.@Redundant[ If the type whose tag is T has no interface ancestors, a null array is returned.]]}@PDefn{Unspecified} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The result of Interface_Ancestor_Tags includes the tag of the parent type, if the parent is an interface.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Indirect interface ancestors are included in the result of Interface_Ancestor_Tags. That's because where an interface appears in the derivation tree has no effect on the semantics of the type; the only interesting property is whether the type has an interface as an ancestor.]} @end{Ramification} For @PrefixType{every subtype S of a tagged type @i(T) (specific or class-wide)}, the following attributes are defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<Class>, Text=[S'Class denotes a subtype of the class-wide type (called @i(T)'Class in this International Standard) for the class rooted at @i(T) (or if S already denotes a class-wide subtype, then S'Class is the same as S). @Noprefix@Defn2{Term=[unconstrained], Sec=(subtype)} @Defn2{Term=[constrained], Sec=(subtype)} S'Class is unconstrained. However, if S is constrained, then the values of S'Class are only those that when converted to the type @i(T) belong to S.]} @begin{Ramification} This attribute is defined for both specific and class-wide subtypes. The definition is such that S'Class'Class is the same as S'Class. Note that if S is constrained, S'Class is only partially constrained, since there might be additional discriminants added in descendants of @i(T) which are not constrained. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} The Class attribute is not defined for untagged subtypes (except for incomplete types and private types whose full view is tagged @em see @Chg{Version=[2],New=[@RefSecNum{The Class Attribute of Untagged Incomplete Types}], Old=[@RefSecNum{Incomplete Type Declarations}]} and @RefSecNum{Private Operations}) so as to preclude implicit conversion in the absence of run-time type information. If it were defined for untagged subtypes, it would correspond to the concept of universal types provided for the predefined numeric classes. @end{Reason} @Attribute{Prefix=<S>, AttrName=<Tag>, Text=[S'Tag denotes the tag of the type @i(T) (or if @i(T) is class-wide, the tag of the root type of the corresponding class). The value of this attribute is of type Tag.]} @begin{Reason} S'Class'Tag equals S'Tag, to avoid generic contract model problems when S'Class is the actual type associated with a generic formal derived type.@end{reason} @end(description) @EndPrefixType{} Given @PrefixType{a @nt<prefix> X that is of a class-wide tagged type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @Attribute{Prefix=<X>, AttrName=<Tag>, Text=[X'Tag denotes the tag of X. The value of this attribute is of type Tag.]} @begin(Reason) X'Tag is not defined if X is of a specific type. This is primarily to avoid confusion that might result about whether the Tag attribute should reflect the tag of the type of X, or the tag of X. No such confusion is possible if X is of a class-wide type. @end(Reason) @end(description) @EndPrefixType{} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00441-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following language-defined generic function exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Tags],Child=[Generic_@!Dispatching_@!Constructor]}@key{generic} @key{type} T (<>) @key{is abstract tagged limited private}; @key{type} Parameters (<>) @key{is limited private}; @key{with function} Constructor (Params : @key{not null access} Parameters) @key{return} T @key{is abstract}; @key{function} Ada.Tags.Generic_Dispatching_Constructor (The_Tag : Tag; Params : @key{not null access} Parameters) @key{return} T'Class; @key{pragma} Preelaborate(Generic_Dispatching_Constructor); @key{pragma} Convention(Intrinsic, Generic_Dispatching_Constructor);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Tags.Generic_Dispatching_Constructor provides a mechanism to create an object of an appropriate type from just a tag value. The function Constructor is expected to create the object given a reference to an object of type Parameters.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This specification is designed to make it easy to create dispatching constructors for streams; in particular, this can be used to construct overridings for T'Class'Input.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that any tagged type will match T (see @RefSecNum{Formal Private and Derived Types}).]} @end{Discussion} @end{StaticSem} @begin{RunTime} @Leading@keepnext@;The tag associated with an object of a tagged type is determined as follows: @begin(Itemize) @PDefn2{Term=[tag of an object], Sec=(stand-alone object, component, or @nt<aggregate>)} The tag of a stand-alone object, a component, or an @nt<aggregate> of a specific tagged type @i(T) identifies @i(T). @begin{Discussion} The tag of a formal parameter of type @i(T) is not necessarily the tag of @i(T), if, for example, the actual was a type conversion. @end{Discussion} @PDefn2{Term=[tag of an object], Sec=(object created by an @nt<allocator>)} The tag of an object created by an allocator for an access type with a specific designated tagged type @i(T), identifies @i(T). @begin{Discussion} The tag of an object designated by a value of such an access type might not be @i(T), if, for example, the access value is the result of a type conversion.@end{discussion} @PDefn2{Term=[tag of an object], Sec=(class-wide object)} The tag of an object of a class-wide tagged type is that of its initialization expression. @begin{Ramification} The tag of an object (even a class-wide one) cannot be changed after it is initialized, since a @lquotes@;class-wide@rquotes@; @nt{assignment_statement} raises Constraint_Error if the tags don't match, and a @lquotes@;specific@rquotes@; @nt{assignment_statement} does not affect the tag. @end{Ramification} @PDefn2{Term=[tag of an object], Sec=(returned by a function)} The tag of the result returned by a function whose result type is a specific tagged type @i(T) identifies @i(T). @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For a limited tagged type, the return object is @lquotes@;built in place@rquotes in the ultimate result object with the appropriate tag.], Old=[This requires a run-time check for limited tagged types, since they are returned "by-reference."]} For a nonlimited type, a new anonymous object with the appropriate tag is created as part of the function return@Chg{Version=[2],New=[],Old=[, and then assigned the value of the return expression]}. See @RefSec{Return Statements}. @end{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @PDefn2{Term=[tag of an object], Sec=(returned by a function)} The tag of the result returned by a function with a class-wide result type is that of the return @Chg{Version=[2],New=[object],Old=[expression]}. @end(Itemize) @PDefn2{Term=[tag of an object], Sec=(preserved by type conversion and parameter passing)} The tag is preserved by type conversion and by parameter passing. The tag of a value is the tag of the associated object (see @RefSecNum{Formal Parameter Modes}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00344-01],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[Tag_Error is raised by a call of Descendant_Tag, Expanded_Name, External_Tag, Interface_Ancestor_Tag, Is_Descendant_At_Same_Level, or Parent_Tag if any tag passed is No_Tag.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[An instance of Tags.Generic_Dispatching_Constructor raises Tag_Error if The_Tag does not represent a concrete descendant of T or if the innermost master (see @RefSecNum{Completion and Finalization}) of this descendant is not also a master of the instance. Otherwise, it dispatches to the primitive function denoted by the formal Constructor for the type identified by The_Tag, passing Params, and returns the result. Any exception raised by the function is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The tag check checks both that The_Tag is in T'Class, and that it is not abstract. These checks are similar to the ones required by streams for T'Class'Input (see @RefSecNum{Stream-Oriented Attributes}). In addition, there is a check that the tag identifies a type declared on the current dynamic call chain, and not a more nested type or a type declared by another task. This check is not necessary for streams, because the stream attributes are declared at the same dynamic level as the type used.]} @end{Ramification} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If an internal tag provided to an instance of Tags.Generic_Dispatching_Constructor or to any subprogram declared in package Tags identifies either a type that is not library-level and whose tag has not been created (see @RefSecNum{Freezing Rules}), or a type that does not exist in the partition at the time of the call, then execution is erroneous.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[One reason that a type might not exist in the partition is that the tag refers to a type whose declaration was elaborated as part of an execution of a @nt{subprogram_body} which has been left (see @RefSecNum{Completion and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We exclude tags of library-level types from the current execution of the partition, because misuse of such tags should always be detected. T'Tag freezes the type (and thus creates the tag), and Internal_Tag and Descendant_Tag cannot return the tag of a library-level type that has not been created. All ancestors of a tagged type must be frozen no later than the (full) declaration of a type that uses them, so Parent_Tag and Interface_Ancestor_Tags cannot return a tag that has not been created. Finally, library-level types never cease to exist while the partition is executing. Thus, if the tag comes from a library-level type, there cannot be erroneous execution (the use of Descendant_Tag rather than Internal_Tag can help ensure that the tag is of a library-level type). This is also similar to the rules for T'Class'Input (see @RefSecNum{Stream-Oriented Attributes}).]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Ada 95 allowed Tag_Error in this case, or expected the functions to work. This worked because most implementations used tags constructed at link-time, and each elaboration of the same @nt{type_declaration} produced the same tag. However, Ada 2005 requires at least part of the tags to be dynamically constructed for a type derived from a type at a shallower level. For dynamically constructed tags, detecting the error can be expensive and unreliable. To see this, consider a program containing two tasks. Task A creates a nested tagged type, passes the tag to task B (which saves it), and then terminates. The nested tag (if dynamic) probably will need to refer in some way to the stack frame for task A. If task B later tries to use the tag created by task A, the tag's reference to the stack frame of A probably is a dangling pointer. Avoiding this would require some sort of protected tag manager, which would be a bottleneck in a program's performance. Moreover, we'd still have a race condition; if task A terminated after the tag check, but before the tag was used, we'd still have a problem. That means that all of these operations would have to be serialized. That could be a significant performance drain, whether or not nested tagged types are every used. Therefore, we allow execution to become erroneous as we do for other dangling pointers. If the implementation can detect the error, we recommend that Tag_Error be raised.]} @end{Discussion} @end{Erron} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00279-01]} The implementation of @Chg{Version=[2],New=[Internal_Tag and Descendant_Tag], Old=[the functions in Ada.Tags]} may raise Tag_Error if no specific type corresponding to the @Chg{Version=[2],New=[string External],Old=[tag]} passed as a parameter exists in the partition at the time the function is called@Chg{Version=[2],New=[, or if there is no such type whose innermost master is a master of the point of the function call],Old=[]}. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Locking would be required to ensure that the mapping of strings to tags never returned tags of types which no longer exist, because types can cease to exist (because they belong to another task, as described above) during the execution of these operations. Moreover, even if these functions did use locking, that would not prevent the type from ceasing to exist at the instant that the function returned. Thus, we do not require the overhead of locking;],Old=[In most implementations, repeated elaborations of the same @nt{type_declaration} will all produce the same tag. In such an implementation, Tag_Error will be raised in cases where the internal or external tag was passed from a different partition. However, some implementations might create a new tag value at run time for each elaboration of a @nt{type_declaration}. In that case, Tag_Error could also be raised if the created type no longer exists because the subprogram containing it has returned, for example. We don't require the latter behavior;]} hence the word @lquotes@;may@rquotes@; in this rule. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Internal_Tag should return the tag of a type whose innermost master is the master of the point of the function call.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2], New=[Tags.Internal_Tag should return the tag of a type whose innermost master is the master of the point of the function call.],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[It's not helpful if Internal_Tag returns the tag of some type in another task when one is available in the task that made the call. We don't require this behavior (because it requires the same implementation techniques we decided not to insist on previously), but encourage it.]} @end{Reason} @end{ImplAdvice} @begin{Notes} A type declared with the reserved word @key[tagged] should normally be declared in a @nt{package_specification}, so that new primitive subprograms can be declared for it. Once an object has been created, its tag never changes. Class-wide types are defined to have unknown discriminants (see @RefSecNum(Discriminants)). This means that objects of a class-wide type have to be explicitly initialized (whether created by an @nt<object_declaration> or an @nt<allocator>), and that @nt<aggregate>s have to be explicitly qualified with a specific type when their expected type is class-wide. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[If S denotes an untagged private type whose full type is tagged, then S'Class is also allowed before the full type definition, but only in the private part of the package in which the type is declared (see @RefSecNum(Private Operations)). Similarly, the Class attribute is defined for incomplete types whose full type is tagged, but only within the library unit in which the incomplete type is declared (see @RefSecNum(Incomplete Type Declarations)).]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The capability provided by Tags.Generic_Dispatching_Constructor is sometimes known as a @i<factory>.@Defn{factory}@Defn{class factory}]} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of tagged record types:) @begin(Example) @key(type) Point @key(is tagged) @key(record) X, Y : Real := 0.0; @key(end record); @key(type) Expression @key(is tagged null record); --@RI[ Components will be added by each extension] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Tagged types are a new concept. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Added wording specifying that Internal_Tag must raise Tag_Error if the tag of a library-level type has not yet been created. Ada 95 gave an Implementation Permission to do this; we require it to avoid erroneous execution when streaming in an object of a library-level type that has not yet been elaborated. This is technically inconsistent; a program that used Internal_Tag outside of streaming and used a compiler that didn't take advantage of the Implementation Permission would not have raised Tag_Error, and may have returned a useful tag. (If the tag was used in streaming, the program would have been erroneous.) Since such a program would not have been portable to a compiler that did take advantage of the Implementation Permission, this is not a significant inconsistency.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=<We now define the lower bound of the string returned from [[Wide_]Wide_]Expanded_Name and External_Name. This makes working with the returned string easier, and is consistent with many other string-returning functions in Ada. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from one of these functions, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.>} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02],ARef=[AI95-00344-01],ARef=[AI95-00400-01],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Constant No_Tag, and functions Parent_Tag, Interface_Ancestor_Tags, Descendant_Tag, Is_Descendant_At_Same_Level, Wide_Expanded_Name, and Wide_Wide_Expanded_Name are newly added to Ada.Tags. If Ada.Tags is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Ada.Tags is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Ada.Tags is now defined to be preelaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Generic function Tags.Generic_Dispatching_Constructor is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[We talk about return objects rather than return expressions, as functions can return using an @nt{extended_return_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added wording to define that tags for all descendants of a tagged type must be distinct. This is needed to ensure that more nested type extensions will work properly. The wording does not require implementation changes for types that were allowed in Ada 95.]} @end{DiffWord95} @LabeledSubClause{Type Extensions} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Redundant[@Defn{type extension} @Defn2{Term=[extension], Sec=(of a type)} @Defn{record extension} @Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is a tagged type, and is @Chg{Version=[2],New=[],Old=[either ]}a @i(record extension) or a @i(private extension) of some other tagged type@Chg{Version=[2],New=[, or a non-interface synchronized tagged type.],Old=[]}.] @end{Intro} @begin{MetaRules} We want to make sure that we can extend a generic formal tagged type, without knowing its discriminants. We don't want to allow components in an extension aggregate to depend on discriminants inherited from the parent value, since such dependence requires staticness in aggregates, at least for variants. @end{MetaRules} @begin{Syntax} @Syn{lhs=<record_extension_part>,rhs="@key(with) @Syn2{record_definition}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01],ARef=[AI95-00345-01],ARef=[AI95-00419-01]} The parent type of a record extension shall not be a class-wide type@Chg{Version=[2],New=[ nor shall it be a synchronized tagged type (see @RefSecNum{Interface Types})],Old=[]}. If the parent type@Chg{Version=[2],New=[ or any progenitor],Old=[]} is nonlimited, then each of the components of the @nt{record_extension_part} shall be nonlimited.@Chg{Version=[2],New=[],Old=[ @PDefn2{Term=[accessibility rule],Sec=(record extension)} The accessibility level (see @RefSecNum(Operations of Access Types)) of a record extension shall not be statically deeper than that of its parent type.]} @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit. @begin{Reason} If the parent is a limited formal type, then the actual might be nonlimited. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Ada 95 required the record extensions to be the same level as the parent type. Now we use accessibility checks on class-wide @nt{allocator}s and return statements to prevent objects from living longer than their type.], Old=[A similar accessibility rule is not needed for private extensions, because in a package, the rule will apply to the @nt{full_type_declaration}, and for a generic formal private extension, the actual is all that matters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Synchronized tagged types cannot be extended. We have this limitation so that all of the data of a task or protected type is defined within the type. Data defined outside of the type wouldn't be subject to the mutual exclusion properties of a protected type, and couldn't be used by a task, and thus doesn't seem to be worth the potential impact on implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Within the body of a generic unit, or the body of any of its descendant library units, a tagged type],Old=[A type extension]} shall not be declared @Chg{Version=[2],New=[as a descendant of a formal type declared within the formal part of the generic unit], Old=[in a generic body if the parent type is declared outside that body]}. @begin{Reason} This paragraph ensures that a dispatching call will never attempt to execute an inaccessible subprogram body. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The convoluted wording (@ldquote@;formal type declared within the formal part@rdquote@;) is necessary to include tagged types that are formal parameters of formal packages of the generic unit, as well as formal tagged and tagged formal derived types of the generic unit.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @ChgNote{This rule is only about generic bodies (and always was only about generic bodies. So we drop the extra text.} @Chg{Version=[2],New=[This rule],Old=[The part about generic bodies]} is necessary in order to preserve the contract model. @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[If an ancestor],Old=[Since a generic unit can be instantiated at a deeper accessibility level than the generic unit, it is necessary to prevent type extensions whose parent is declared outside the generic unit. The same is true if the parent]} is a formal of the generic unit @Chg{Version=[2],New=[, we have a problem],Old=[. If the parent is declared in the @nt{generic_declaration} (but is not a formal), we don't run afoul of the accessibility rules, because we know that the instance declaration and body will be at the same accessibility level. However, we still have a problem in that case,]} because it might have an unknown number of abstract subprograms, as in the following example: @begin{Example} @ChgRef{Version=[2],Kind=[Revised]} @key[package] P @key[is] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; @key[function] F @key[return] T; --@RI{ Inherited versions will @Chg{Version=[2],New=[require overriding],Old=[be abstract]}.} @key[end] P; @key[generic] @key[type] TT @key[is] @key[tagged] @key[private]; @key[package] Gp @key[is] @key[type] NT @key[is] @key[abstract new] TT @key[with] @key[null] @key[record]; @key[procedure] Q(X : @key[in] NT) @key[is abstract]; @key[end] Gp; @ChgRef{Version=[2],Kind=[Revised]} @key[package] @key[body] Gp @key[is] @key[type] NT2 @key[is] @key[new] NT @key[with] @key[null] @key[record]; --@RI{ Illegal!} @key[procedure] Q(X : @key[in] NT2) @key[is] @key[begin] @key[null]; @key[end] Q; --@RI{ Is this legal or not? Can't decide because} --@RI{ we don't know whether TT had any functions that @Chg{Version=[2],New=[require],Old=[go abstract]}} --@RI{ @Chg{Version=[2],New=[overriding ],Old=[]}on extension.} @key[end] Gp; @key[package] I @key[is] @key[new] Gp(TT => P.T); @end{Example} @ChgRef{Version=[2],Kind=[Revised]} I.NT is an abstract type with two abstract subprograms: F (inherited as abstract) and Q (explicitly declared as abstract). But the generic body doesn't know about F, so we don't know that it needs to be overridden to make a nonabstract extension of NT.@Chg{Version=[2],New=[],Old=[ Furthermore, a formal tagged limited private type can be extended with limited components, but the actual might not be limited, which would allow assignment of limited types, which is bad. ]}Hence, we have to disallow this case@Chg{Version=[2],New=[],Old=[ as well]}. @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Similarly, since the actual type for a formal tagged limited private type can be a nonlimited type, we would have a problem if a type extension of a limited private formal type could be declared in a generic body. Such an extension could have a task component, for example, and an object of that type could be passed to a dispatching operation of a nonlimited ancestor type. That operation could try to copy the object with the task component. That would be bad. So we disallow this as well.]} If TT were declared as abstract, then we could have the same problem with abstract procedures. We considered disallowing all tagged types in a generic body, for simplicity. We decided not to go that far, in order to avoid unnecessary restrictions. @PDefn2{Term=[accessibility rule],Sec=(not part of generic contract)} We also considered trying make the accessibility level part of the contract; i.e. invent some way of saying (in the @nt{generic_declaration}) @lquotes@;all instances of this generic unit will have the same accessibility level as the @nt{generic_declaration}.@rquotes@; Unfortunately, that doesn't solve the part of the problem having to do with abstract types. @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Children of generic units obviate the need for extension in the body somewhat.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344]} @ChgAdded{Version=[2],Text=[This rule applies to types with ancestors (directly or indirectly) of formal interface types (see @RefSecNum{Formal Interface Types}), formal tagged private types (see @RefSecNum{Formal Private and Derived Types}), and formal derived private types whose ancestor type is tagged (see @RefSecNum{Formal Private and Derived Types}).]} @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[@defn{null extension} A record extension is a @i{null extension} if its declaration has no @nt{known_discriminant_part} and its @nt{record_extension_part} includes no @nt{component_declaration}s.]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(record_extension_part)} The elaboration of a @nt{record_extension_part} consists of the elaboration of the @nt{record_definition}. @end{RunTime} @begin{Notes} The term @lquotes@;type extension@rquotes@; refers to a type as a whole. The term @lquotes@;extension part@rquotes@; refers to the piece of text that defines the additional components (if any) the type extension has relative to its specified ancestor type. @begin(Discussion) We considered other terminology, such as @lquotes@;extended type.@rquotes@; However, the terms @lquotes@;private extended type@rquotes@; and @lquotes@;record extended type@rquotes@; did not convey the proper meaning. Hence, we have chosen to uniformly use the term @lquotes@;extension@rquotes@; as the type resulting from extending a type, with @lquotes@;private extension@rquotes@; being one produced by privately extending the type, and @lquotes@;record extension@rquotes@; being one produced by extending the type with an additional record-like set of components. Note also that the term @lquotes@;type extension@rquotes@; refers to the result of extending a type in the language Oberon as well (though there the term @lquotes@;extended type@rquotes@; is also used, interchangeably, perhaps because Oberon doesn't have the concept of a @lquotes@;private extension@rquotes@;). @end(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[],Old=[The accessibility rules imply that a tagged type declared in a library @nt{package_specification} can be extended only at library level or as a generic formal. ]}When @Chg{Version=[2],New=[an],Old=[the]} extension is declared immediately within a @Chg{Version=[2],New=[body],Old=[@nt{package_body}]}, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added. A @nt<name> that denotes a component (including a discriminant) of the parent type is not allowed within the @nt{record_extension_part}. Similarly, a @nt<name> that denotes a component defined within the @nt{record_extension_part} is not allowed within the @nt{record_extension_part}. It is permissible to use a @nt<name> that denotes a discriminant of the record extension, providing there is a new @nt{known_discriminant_part} in the enclosing type declaration. (The full rule is given in @RefSecNum(Record Types).) @begin(Reason) The restriction against depending on discriminants of the parent is to simplify the definition of extension aggregates. The restriction against using parent components in other ways is methodological; it presumably simplifies implementation as well. @end(Reason) Each visible component of a record extension has to have a unique name, whether the component is (visibly) inherited from the parent type or declared in the @nt<record_extension_part> (see @RefSecNum{Visibility}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of record extensions (of types defined above in @RefSecNum(Tagged Types and Type Extensions)):} @begin(Example) @key(type) Painted_Point @key(is new) Point @key(with) @key(record) Paint : Color := White; @key(end record); --@RI[ Components X and Y are inherited] Origin : @key(constant) Painted_Point := (X | Y => 0.0, Paint => Black); @key(type) Literal @key(is new) Expression @key(with) @key(record) --@RI[ a leaf in an Expression tree] Value : Real; @key(end record); @key(type) Expr_Ptr @key(is access all) Expression'Class; --@RI[ see @RefSecNum(Access Types)] @key(type) Binary_Operation @key(is new) Expression @key(with) @key(record) --@RI[ an internal node in an Expression tree] Left, Right : Expr_Ptr; @key(end record); @key(type) Addition @key(is new) Binary_Operation @key(with null record); @key(type) Subtraction @key(is new) Binary_Operation @key(with null record); --@RI[ No additional components needed for these extensions] Tree : Expr_Ptr := --@RI[ A tree representation of @lquotes@;5.0 + (13.0@en@;7.0)@rquotes@;] @key(new) Addition'( Left => @key(new) Literal'(Value => 5.0), Right => @key(new) Subtraction'( Left => @key(new) Literal'(Value => 13.0), Right => @key(new) Literal'(Value => 7.0))); @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Type extension is a new concept. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Type extensions now can be declared in more nested scopes than their parent types. Additional accessibility checks on @nt{allocator}s and return statements prevent objects from outliving their type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent extending synchronized tagged types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[Defined null extension for use elsewhere.]} @end{DiffWord95} @LabeledSubClause{Dispatching Operations of Tagged Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00335-01]} @RootDefn{dispatching operation} @Defn2{Term=[dispatching call], Sec=(on a dispatching operation)} @Defn2{Term=[nondispatching call], Sec=(on a dispatching operation)} @Defn{statically determined tag} @Defn{dynamically determined tag} @Defn{polymorphism} @Defn{run-time polymorphism} @Defn2{Term=[controlling tag], Sec=(for a call on a dispatching operation)} The primitive subprograms of a tagged type@Chg{Version=[2],New=[, the subprograms declared by @nt{formal_@!abstract_@!subprogram_@!declaration}s, and the stream attributes of a specific tagged type that are available (see @RefSecNum{Stream-Oriented Attributes}) at the end of the declaration list where the type is declared],Old=[]} are called @i(dispatching operations). @Redundant[A dispatching operation can be called using a statically determined @i{controlling} tag, in which case the body to be executed is determined at compile time. Alternatively, the controlling tag can be dynamically determined, in which case the call @i{dispatches} to a body that is determined at run time;] such a call is termed a @i{dispatching call}. @Redundant[As explained below, the properties of the operands and the context of a particular call on a dispatching operation determine how the controlling tag is determined, and hence whether or not the call is a dispatching call. Run-time polymorphism is achieved when a dispatching operation is called by a dispatching call.] @IndexSee{Term=[object-oriented programming (OOP)],See=[dispatching operations of tagged types]} @IndexSee{Term=[OOP (object-oriented programming)],See=[dispatching operations of tagged types]} @IndexSee{Term=[message],See=[dispatching call]} @IndexSee{Term=[method],See=[dispatching subprogram]} @IndexSee{Term=[virtual function],See=[dispatching subprogram]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00335-01]} @ChgAdded{Version=[2],Text=[For the stream attributes of a type declared immediately within a @nt{package_specification} that has a partial view, the declaration list to consider is the visible part of the package. Stream attributes that are not available in the same declaration list are not dispatching as there is no guarantee that descendants of the type have available attributes (there is such a guarantee for visibly available attributes). If we allowed dispatching for any available attribute, then for attributes defined in the private part we could end up executing a non-existent body.]} @end{Reason} @end{Intro} @begin{MetaRules} The controlling tag determination rules are analogous to the overload resolution rules, except they deal with run-time type identification (tags) rather than compile-time type resolution. As with overload resolution, controlling tag determination may depend on operands or result context. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00416-01]} @Defn{call on a dispatching operation} @Defn{dispatching operation} A @i{call on a dispatching operation} is a call whose @nt<name> or @nt<prefix> denotes the declaration of@Chg{Version=[2],New=[], Old=[ a primitive subprogram of a tagged type, that is,]} a dispatching operation. @Defn{controlling operand} A @i{controlling operand} in a call on a dispatching operation of a tagged type @i(T) is one whose corresponding formal parameter is of type @i(T) or is of an anonymous access type with designated type @i(T); @Defn{controlling formal parameter} the corresponding formal parameter is called a @i(controlling formal parameter). If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. @Defn{controlling result} If the call is to a (primitive) function with result type @i(T), then the call has a @i(controlling result) @em the context of the call can control the dispatching.@Chg{Version=[2], New=[ Similarly, if the call is to a function with access result type designating @i(T), then the call has a @i(controlling access result), and the context can similarly control dispatching.],Old=[]} @begin{Ramification} This definition implies that a call through the dereference of an access-to-subprogram value is never considered a call on a dispatching operation. Note also that if the @nt{prefix} denotes a @nt{renaming_declaration}, the place where the renaming occurs determines whether it is primitive; the thing being renamed is irrelevant. @end{Ramification} @Leading@;A @nt<name> or expression of a tagged type is either @i(statically) tagged, @i(dynamically) tagged, or @i(tag indeterminate), according to whether, when used as a controlling operand, the tag that controls dispatching is determined statically by the operand's (specific) type, dynamically by its tag at run time, or from context. A @nt<qualified_expression> or parenthesized expression is statically, dynamically, or indeterminately tagged according to its operand. For other kinds of @nt<name>s and expressions, this is determined as follows: @begin(Itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{statically tagged} The @nt<name> or expression is @i(statically tagged) if it is of a specific tagged type and, if it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]}, it has at least one statically tagged controlling operand; @begin{Discussion} It is illegal to have both statically tagged and dynamically tagged controlling operands in the same call -- see below. @end{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{dynamically tagged} The @nt<name> or expression is @i(dynamically tagged) if it is of a class-wide type, or it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]} and at least one dynamically tagged controlling operand; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{tag indeterminate} The @nt<name> or expression is @i(tag indeterminate) if it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]}, all of whose controlling operands (if any) are tag indeterminate. @end(itemize) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @Redundant[A @nt<type_conversion> is statically or dynamically tagged according to whether the type determined by the @nt<subtype_mark> is specific or class-wide, respectively.] @Chg{New=[For an object that is designated by an expression whose expected type is an anonymous access-to-specific tagged type, the object is dynamically tagged if the expression, ignoring enclosing parentheses, is of the form X'Access, where X is of a class-wide type, or is of the form @key(new) T'(...), where T denotes a class-wide subtype. Otherwise, the object], Old=[For a controlling operand that is designated by an actual parameter, the controlling operand]} is statically or dynamically tagged according to whether the designated type @Chg{New=[of the type of the expression], Old=[of the actual parameter]} is specific or class-wide, respectively. @begin{Ramification} A @nt<type_conversion> is never tag indeterminate, even if its operand is. A designated object is never tag indeterminate. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[1],Text=[Allocators and access attributes of class-wide types can be used as the controlling parameters of dispatching calls.]} @end{Ramification} @end{StaticSem} @begin{Legality} A call on a dispatching operation shall not have both dynamically tagged and statically tagged controlling operands. @begin{Reason} This restriction is intended to minimize confusion between whether the dynamically tagged operands are implicitly converted to, or tag checked against the specific type of the statically tagged operand(s). @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} If the expected type for an expression or @nt<name> is some specific tagged type, then the expression or @nt<name> shall not be dynamically tagged unless it is a controlling operand in a call on a dispatching operation. Similarly, if the expected type for an expression is an anonymous access-to-specific tagged type, then the @Chg{New=[object designated by the expression shall not be dynamically tagged unless it is],Old=[expression shall not be of an access-to-class-wide type unless it designates]} a controlling operand in a call on a dispatching operation. @begin(Reason) This prevents implicit "truncation" of a dynamically-tagged value to the specific type of the target object/formal. An explicit conversion is required to request this truncation. @end(Reason) @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01]}@ChgNote{Add info about prefix calls} This rule applies to all expressions or @nt<name>s with a specific expected type, not just those that are actual parameters to a dispatching call. This rule does not apply to a membership test whose @nt<expression> is class-wide, since any type that covers the tested type is explicitly allowed. See @RefSecNum(Relational Operators and Membership Tests).@Chg{Version=[2], New=[ This rule also doesn't apply to a @nt{selected_component} whose @nt{selector_name} is a subprogram, since the rules explicitly say that the prefix may be class-wide (see @RefSecNum{Selected Components}).],Old=[]} @end(Ramification) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00430-01]} In the declaration of a dispatching operation of a tagged type, everywhere a subtype of the tagged type appears as a subtype of the profile (see @RefSecNum(Subprogram Declarations)), it shall statically match the first subtype of the tagged type. @PDefn2{Term=[statically matching],Sec=(required)} If the dispatching operation overrides an inherited subprogram, it shall be subtype conformant with the inherited subprogram. @Defn2{Term=[subtype conformance],Sec=(required)} @Chg{New=[The convention of an inherited @Chg{Version=[2],New=[], Old=[or overriding ]}dispatching operation is the convention of the corresponding primitive operation of the parent @Chg{Version=[2],New=[or progenitor ],Old=[]}type. @Chg{Version=[2],New=[The default convention of a dispatching operation that overrides an inherited primitive operation is the convention of the inherited operation; if the operation overrides multiple inherited operations, then they shall all have the same convention. ],Old=[]}An explicitly declared],Old=[A]} dispatching operation shall not be of convention Intrinsic.@Chg{New=[],Old=[ If a dispatching operation overrides the predefined equals operator, then it shall be of convention Ada @Redundant[(either explicitly or by default @em see @RefSecNum{Conformance Rules})].]} @begin{Reason} These rules ensure that constraint checks can be performed by the caller in a dispatching call, and parameter passing conventions match up properly. A special rule on aggregates prevents values of a tagged type from being created that are outside of its first subtype. @end{reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} The @nt<default_expression> for a controlling formal parameter of a dispatching operation shall be tag indeter@!minate.@Chg{Version=[2], New=[],Old=[ A controlling formal parameter that is an access parameter shall not have a @nt<default_expression>.]} @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[This rule],Old=[The first part]} ensures that the @nt{default_expression} always produces the "correct" tag when called with or without dispatching, or when inherited by a descendant. If it were statically tagged, the default would be useless for a dispatching call; if it were dynamically tagged, the default would be useless for a nondispatching call. @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00416-01]} @ChgDeleted{Version=[2],Text=[The second part is consistent with the first part, since designated objects are never tag-indeterminate.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00404-01]} @ChgAdded{Version=[2],Text=[If a dispatching operation is defined by a @nt{subprogram_renaming_declaration} or the instantiation of a generic subprogram, any access parameter of the renamed subprogram or the generic subprogram that corresponds to a controlling access parameter of the dispatching operation, shall have a subtype that excludes null.]} A given subprogram shall not be a dispatching operation of two or more distinct tagged types. @begin{Reason} This restriction minimizes confusion since multiple dispatching is not provided. The normal solution is to replace all but one of the tagged types with their class-wide types. @end{reason} @begin{ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0098],ARef=[AI95-00183-01]} @ChgAdded{Version=[1],Text=[This restriction applies even if the partial view (see @RefSecNum{Private Types and Private Extensions}) of one or both of the types is untagged. This follows from the definition of dispatching operation: the operation is a dispatching operation anywhere the full views of the (tagged) types are visible.]} @end{ramification} The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen (see @RefSecNum{Freezing Rules}). @Redundant[For example, new dispatching operations cannot be added after objects or values of the type exist, nor after deriving a record extension from it, nor after a body.] @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @begin{Discussion} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]} @end{Discussion}} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]}@ChgNote{Tags now have two parts, logically} This rule is needed because (1) we don't want people dispatching to things that haven't been declared yet, and (2) we want to allow @Chg{Version=[2],New=[the static part of ],Old=[]}tagged type descriptors to be static (allocated statically, and initialized to link-time-known symbols). Suppose T2 inherits primitive P from T1, and then overrides P. Suppose P is called @i{before} the declaration of the overriding P. What should it dispatch to? If the answer is the new P, we've violated the first principle above. If the answer is the old P, we've violated the second principle. (A call to the new one necessarily raises Program_Error, but that's beside the point.) Note that a call upon a dispatching operation of type @i(T) will freeze @i(T). We considered applying this rule to all derived types, for uniformity. However, that would be upward incompatible, so we rejected the idea. As in Ada 83, for an untagged type, the above call upon P will call the old P (which is arguably confusing). @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]}@ChgNote{We have tagged incomplete types now, and they don't freeze} Because of this rule, the type descriptor can be created (presumably containing linker symbols pointing at the not-yet-compiled bodies) at the first freezing point of the type. It also prevents, for a @Chg{Version=[2],New=[(non-incomplete) ],Old=[]}tagged type declared in a @nt{package_specification}, overriding in the body or by a child subprogram. @end{ImplNote} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]}@ChgNote{Interfaces cause this too} A consequence is that for a @Chg{Version=[2],New=[tagged type declaration], Old=[@ntf{derived_type_declaration}]} in a @nt{declarative_part}, only the @Chg{Version=[2],New=[last (overriding)],Old=[first]} primitive subprogram can be declared by a @nt{subprogram_body}.@Chg{Version=[2],New=[ (Other overridings must be provided by @nt{subprogram_declaration}s.)],Old=[]} @end{Ramification} @end{Legality} @begin{RunTime} @Leading@PDefn2{Term=[execution], Sec=(call on a dispatching operation)} @Defn{controlling tag value} For the execution of a call on a dispatching operation of a type @i(T), the @i(controlling tag value) determines which subprogram body is executed. The controlling tag value is defined as follows: @begin(itemize) @PDefn{statically determined tag} If one or more controlling operands are statically tagged, then the controlling tag value is @i(statically determined) to be the tag of @i(T). If one or more controlling operands are dynamically tagged, then the controlling tag value is not statically determined, but is rather determined by the tags of the controlling operands. @IndexCheck{Tag_Check} If there is more than one dynamically tagged controlling operand, a check is made that they all have the same tag. @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If this check fails, Constraint_Error is raised unless the call is a @nt<function_call> whose @nt<name> denotes the declaration of an equality operator (predefined or user defined) that returns Boolean, in which case the result of the call is defined to indicate inequality, and no @nt<subprogram_body> is executed. This check is performed prior to evaluating any tag-indeterminate controlling operands. @begin(Reason) Tag mismatch is considered an error (except for "=" and "/=") since the corresponding primitive subprograms in each specific type expect all controlling operands to be of the same type. For tag mismatch with an equality operator, rather than raising an exception, "=" returns False and "/=" returns True. No equality operator is actually invoked, since there is no common tag value to control the dispatch. Equality is a special case to be consistent with the existing Ada 83 principle that equality comparisons, even between objects with different constraints, never raise Constraint_Error. @end(Reason) @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00196-01]} If all of the controlling operands @Chg{Version=[2],New=[(if any) ],Old=[]}are tag-indeterminate, then: @begin(inneritemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00239-01],ARef=[AI95-00416-01]} If the call has a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]} and is itself@Chg{Version=[2],New=[, or designates,],Old=[]} a (possibly parenthesized or qualified) controlling operand of an enclosing call on a dispatching operation of @Chg{Version=[2],New=[a descendant of ],Old=[]}type @i(T), then its controlling tag value is determined by the controlling tag value of this enclosing call; @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00239-01]} @ChgAdded{Version=[2],Text=[For code that a user can write explicitly, the only contexts that can control dispatching of a function with a controlling result of type T are those that involve controlling operands of the same type T: if the two types differ there is an illegality and the dynamic semantics are irrelevant.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In the case of an inherited subprogram however, if a default expression is a function call, it may be of type T while the parameter is of a type derived from T. To cover this case, we talk about "a descendant of T" above. This is safe, because if the type of the parameter is descended from the type of the function result, it is guaranteed to inherit or override the function, and this ensures that there will be an appropriate body to dispatch to. Note that abstract functions are not an issue here because the call to the function is a dispatching call, so it is guaranteed to always land on a concrete body.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00196-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the call has a controlling result or controlling access result and (possibly parenthesized, qualified, or dereferenced) is the expression of an @nt{assignment_statement} whose target is of a class-wide type, then its controlling tag value is determined by the target;]} @PDefn{statically determined tag} Otherwise, the controlling tag value is statically determined to be the tag of type @i(T). @begin{Ramification} This includes the cases of a tag-indeterminate procedure call, and a tag-indeterminate @nt{function_call} that is used to initialize a class-wide formal parameter or class-wide object. @end{Ramification} @end(inneritemize) @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{Dummy add to allow conditional "leading"} For the execution of a call on a dispatching operation, the @Chg{Version=[2],New=[action performed is determined by the properties of the corresponding dispatching operation],Old=[body executed is the one for the corresponding primitive subprogram]} of the specific type identified by the controlling tag value. @Chg{Version=[2],New=[If the corresponding operation is],Old=[The body for an]} explicitly declared @Chg{Version=[2],New=[for this type, @Redundant[even if the declaration occurs in a private part], then the action comprises an invocation of the], Old=[dispatching operation is the corresponding]} explicit body for the @Chg{Version=[2],New=[operation. If the corresponding operation is implicitly declared for this type:],Old=[subprogram. The body for an implicitly declared dispatching operation that is overridden is the body for the overriding subprogram, @Redundant[even if the overriding occurs in a private part.] The body for an inherited dispatching operation that is not overridden is the body of the corresponding subprogram of the parent or ancestor type.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[if the operation is implemented by an entry or protected subprogram (see @RefSecNum{Task Units and Task Objects} and @RefSecNum{Protected Units and Protected Objects}), then the action comprises a call on this entry or protected subprogram, with the target object being given by the first actual parameter of the call, and the actual parameters of the entry or protected subprogram being given by the remaining actual parameters of the call, if any;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[otherwise, the action is the same as the action for the corresponding operation of the parent type.]} @end{Itemize} @begin{Honest} In the unusual case in which a dispatching subprogram is explicitly declared (overridden) by a body (with no preceding @nt{subprogram_declaration}), the body for that dispatching subprogram is that body; that is, the @lquotes@;corresponding explicit body@rquotes@; in the above rule is the body itself. @end{Honest} @begin{Reason} @Leading@;The wording of the above rule is intended to ensure that the same body is executed for a given tag, whether that tag is determined statically or dynamically. For a type declared in a package, it doesn't matter whether a given subprogram is overridden in the visible part or the private part, and it doesn't matter whether the call is inside or outside the package. For example: @begin{Example} @key[package] P1 @key[is] @key[type] T1 @key[is] @key[tagged] @key[null] @key[record]; @key[procedure] Op_A(Arg : @key[in] T1); @key[procedure] Op_B(Arg : @key[in] T1); @key[end] P1; @key[with] P1; @key[use] P1; @key[package] P2 @key[is] @key[type] T2 @key[is] @key[new] T1 @key[with] @key[null] @key[record]; @key[procedure] Op_A(Param : @key[in] T2); @key[private] @key[procedure] Op_B(Param : @key[in] T2); @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00009 & AI-00114} @key[with] P1; @key[with] P2; @key[procedure] Main @key[is] X : @Chg{New=[P2.],Old=[]}T2; Y : @Chg{New=[P1.],Old=[]}T1'Class := X; @key[begin] P2.Op_A(Param => X); --@RI{ Nondispatching call@Chg{New=[ to a dispatching operation],Old=[]}.} P1.Op_A(Arg => Y); --@RI{ Dispatching call.} P2.Op_B(Arg => X); --@RI{ Nondispatching call@Chg{New=[ to a dispatching operation],Old=[]}.} P1.Op_B(Arg => Y); --@RI{ Dispatching call.} @key[end] Main; @end{Example} The two calls to Op_A both execute the body of Op_A that has to occur in the body of package P2. Similarly, the two calls to Op_B both execute the body of Op_B that has to occur in the body of package P2, even though Op_B is overridden in the private part of P2. Note, however, that the formal parameter names are different for P2.Op_A versus P2.Op_B. The overriding declaration for P2.Op_B is not visible in Main, so the name in the call actually denotes the implicit declaration of Op_B inherited from T1. If a call occurs in the program text before an overriding, which can happen only if the call is part of a default expression, the overriding will still take effect for that call. @end{Reason} @begin{ImplNote} Even when a tag is not @i(statically determined), a compiler might still be able to figure it out and thereby avoid the overhead of run-time dispatching.@end{implnote} @end{RunTime} @begin{Notes} The body to be executed for a call on a dispatching operation is determined by the tag; it does not matter whether that tag is determined statically or dynamically, and it does not matter whether the subprogram's declaration is visible at the place of the call. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} This subclause covers calls on @Chg{Version=[2],New=[dispatching], Old=[primitive]} subprograms of a tagged type. Rules for tagged type membership tests are described in @RefSecNum(Relational Operators and Membership Tests). Controlling tag determination for an @nt{assignment_statement} is described in @RefSecNum(Assignment Statements). A dispatching call can dispatch to a body whose declaration is not visible at the place of the call. A call through an access-to-subprogram value is never a dispatching call, even if the access value designates a dispatching operation. Similarly a call whose @nt<prefix> denotes a @nt<subprogram_renaming_declaration> cannot be a dispatching call unless the renaming itself is the declaration of a primitive subprogram. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concept of dispatching operations is new. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00404-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} If a dispatching operation is defined by a @nt{subprogram_renaming_declaration}, and it has a controlling access parameter, Ada 2005 requires the subtype of the parameter to exclude null. The same applies to instantiations. This is required so that all calls to the subprogram operate the same way (controlling access parameters have to exclude null so that dispatching calls will work). Since Ada 95 didn't have the notion of access subtypes that exclude null, and all access parameters excluded null, it had no such rules. These rules will require the addition of an explicit @key{not null} on nondispatching operations that are later renamed to be dispatching, or on a generic that is used to define a dispatching operation.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Functions that have an access result type can be dispatching in the same way as a function that returns a tagged object directly.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:>@ChgNote{This is documented as an extension in the two sections referenced below.} Allocators and access attributes of objects of class-wide types can be used as the controlling parameter in a dispatching calls. This was an oversight in the definition of Ada 95. (See @RefSecNum{Operations of Access Types} and @RefSecNum{Allocators}).]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0011],ARef=[AI95-00117-01],ARef=[AI95-00430-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the conventions of dispatching operations. This is extended in Ada 2005 to cover operations inherited from progenitors, and to ensure that the conventions of all inherited operations are the same.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00196-01]} @ChgAdded{Version=[2],Text=[Clarified the wording to ensure that functions with no controlling operands are tag-indeterminate, and to describe that the controlling tag can come from the target of an @nt{assignment_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00239-01]} @ChgAdded{Version=[2],Text=[Fixed the wording to cover default expressions inherited by derived subprograms. A literal reading of the old wording would have implied that operations would be called with objects of the wrong type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[An abstract formal subprogram is a dispatching operation, even though it is not a primitive operation. See @RefSec{Formal Subprograms}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Dispatching calls include operations implemented by entries and protected operations, so we have to update the wording to reflect that.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00335-01]} @ChgAdded{Version=[2],Text=[A stream attribute of a tagged type is usually a dispatching operation, even though it is not a primitive operation. If they weren't dispatching, T'Class'Input and T'Class'Output wouldn't work.]} @end{Diffword95} @LabeledSubClause{Abstract Types and Subprograms} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @redundant[@Defn{abstract type} @IndexSeeAlso{Term=[abstract data type (ADT)],See=(abstract type)} @IndexSeeAlso{Term=[ADT (abstract data type)],See=(abstract type)} @IndexSee{Term=[concrete type],See=(nonabstract type)} An @i(abstract type) is a tagged type intended for use as @Chg{Version=[2],New=[an ancestor of other types],Old=[a parent type for type extensions]}, but which is not allowed to have objects of its own. @Defn{abstract subprogram} @IndexSee{Term=[concrete subprogram],See=(nonabstract subprogram)} An @i(abstract subprogram) is a subprogram that has no body, but is intended to be overridden at some point when inherited. Because objects of an abstract type cannot be created, a dispatching call to an abstract subprogram always dispatches to some overriding body.] @ChgToGlossary{Version=[2],Kind=[Added],Term=<Abstract type>, Text=<@ChgAdded{Version=[2],Text=[An abstract type is a tagged type intended for use as an ancestor of other types, but which is not allowed to have objects of its own.]}>} @end{Intro} @begin{MetaRules} An abstract subprogram has no body, so the rules in this clause are designed to ensure (at compile time) that the body will never be invoked. We do so primarily by disallowing the creation of values of the abstract type. Therefore, since type conversion and parameter passing don't change the tag, we know we will never get a class-wide value with a tag identifying an abstract type. This means that we only have to disallow nondispatching calls on abstract subprograms (dispatching calls will never reach them). @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00218-03],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<abstract_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] @Syn2{subprogram_specification} @key{is} @key{abstract};>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @Chg{Version=[2],New=[@Defn{abstract type} @Defn2{Term=[type], Sec=(abstract)}Interface types (see @RefSecNum{Interface Types}) are abstract types. In addition, a tagged type that has the reserved word @key{abstract} in its declaration is an abstract type. The class-wide type (see @RefSecNum{Derivation Classes}) rooted at an abstract type is not itself an abstract type.],Old=[]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Chg{Version=[2],New=[Only a tagged type shall have],Old=[@Defn{abstract type} @Defn2{Term=[type], Sec=(abstract)} An @i{abstract type} is a specific type that has]} the reserved word @key{abstract} in its declaration.@Chg{Version=[2],New=[],Old=[Only a tagged type is allowed to be declared abstract.]} @begin{Ramification}@ChgNote{These AARM notes really belong on the Static Semantics paragraph, but I won't move them, as it's not worth the time.} Untagged types are never abstract, even though they can have primitive abstract subprograms. Such subprograms cannot be called, unless they also happen to be dispatching operations of some tagged type, and then only via a dispatching call. Class-wide types are never abstract. If T is abstract, then it is illegal to declare a stand-alone object of type T, but it is OK to declare a stand-alone object of type T'Class; the latter will get a tag from its initial value, and this tag will necessarily be different from T'Tag. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00348-01]} @Defn{abstract subprogram} @Defn2{Term=[subprogram], Sec=(abstract)} A subprogram declared by an @nt{abstract_@!subprogram_@!declaration} @Chg{Version=[2],New=[or a @nt{formal_@!abstract_@!subprogram_@!declaration} (see @RefSecNum{Formal Subprograms})], Old=[(see @RefSecNum{Subprogram Declarations})]} is an @i{abstract subprogram}. If it is a primitive subprogram of a tagged type, then the tagged type shall be abstract. @begin{Ramification} @Leading@keepnext@;Note that for a private type, this applies to both views. The following is illegal: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[abstract] @key[tagged] @key[private]; @key[function] Foo (X : T) @key[return] Boolean @key[is] @key[abstract]; --@RI{ Illegal!} @key[private] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; --@RI{ Illegal!} X : T; Y : Boolean := Foo (T'Class (X)); @key[end] P; @end{Example} The full view of T is not abstract, but has an abstract operation Foo, which is illegal. The two lines marked "--@i{ Illegal!}" are illegal when taken together. @end{Ramification} @begin{Reason} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} We considered disallowing untagged types from having abstract primitive subprograms. However, we rejected that plan, because it introduced some silly anomalies, and because such subprograms are harmless@Chg{Version=[2], New=[],Old=[ (if not terribly useful)]}. For example: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00010} @key[package] P @key[is] @key[type] Field_Size @key[is] @key[range] 0..100; @key[type] T @key[is] @key[abstract tagged] @key[null] @key[record]; @key[procedure] Print(X : @key[in] T; F : @key[in] Field_Size := 0) @key[is] @Chg{New=[@key[abstract]],Old=[abstract]}; . . . @key[package] Q @key[is] @key[type] My_Field_Size @key[is] @key[new] Field_Size; --@RI{ implicit declaration of Print(X : T; F : My_Field_Size := 0) @Chg{New=[@key[is abstract]],Old=[is abstract]};} @key[end] Q; @end{Example} It seemed silly to make the derivative of My_Field_Size illegal, just because there was an implicitly declared abstract subprogram that was not primitive on some tagged type. Other rules could be formulated to solve this problem, but the current ones seem like the simplest. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[In Ada 2005, abstract primitive subprograms of an untagged type may be used to @lquotes@;undefine@rquotes@; an operation.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Note that the second sentence does not apply to abstract formal subprograms, as they are never primitive operations of a type.]} @end{Ramification} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00334-01],ARef=[AI95-00391-01]} @Chg{Version=[2],New=[If a type has an implicitly declared primitive subprogram that is inherited or is the predefined equality operator, and the corresponding primitive subprogram of],Old=[For a derived type, if]} the parent or ancestor type @Chg{Version=[2],New=[is abstract or is a function with a controlling access result, or if a type other than a null extension inherits a], Old=[has an abstract primitive subprogram, or a primitive]} function with a controlling result, then: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00334-01]} If the @Chg{Version=[2],New=[],Old=[derived ]}type is abstract or untagged, the @Chg{Version=[2],New=[implicitly declared],Old=[inherited]} subprogram is @i{abstract}. @begin{Ramification} Note that it is possible to override a concrete subprogram with an abstract one. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01]} Otherwise, the subprogram shall be overridden with a nonabstract subprogram@Chg{Version=[2],New=[ or, in the case of a private extension inheriting a function with a controlling result, have a full type that is a null extension],Old=[]}@Redundant[; for a type declared in the visible part of a package, the overriding may be either in the visible or the private part]. @Chg{Version=[2],New=[Such a subprogram is said to @i{require overriding}.@Defn{require overriding} ],Old=[]}However, if the type is a generic formal type, the subprogram need not be overridden for the formal type itself; @Redundant[a nonabstract version will necessarily be provided by the actual type.] @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00228-01],ARef=[AI95-00391-01]} A function that returns the parent type @Chg{Version=[2],New=[requires overriding],Old=[becomes abstract]}@ChgNote{Can't leave this ancient and broken terminology around here!!} for @Chg{Version=[2],New=[a],Old=[an abstract]} type extension @Chg{Version=[2],New=[(or becomes abstract for an abstract type)], Old=[(if not overridden)]} because conversion from a parent type to a type extension is not defined, and function return semantics is defined in terms of conversion@Chg{Version=[2],New=[ (other than for a null extension; see below)],Old=[]}. (Note that parameters of mode @key{in out} or @key{out} do not have this problem, because the tag of the actual is not changed.) @Leading@keepnext@;Note that the overriding required above can be in the private part, which allows the following: @begin{Example} @key[package] Pack1 @key[is] @key[type] Ancestor @key[is] @key[abstract] ...; @key[procedure] Do_Something(X : @key[in] Ancestor) @key[is] @key[abstract]; @key[end] Pack1; @key[with] Pack1; @key[use] Pack1; @key[package] Pack2 @key[is] @key[type] T1 @key[is] @key[new] Ancestor @key[with] @key[record] ...; --@RI{ A concrete type.} @key[procedure] Do_Something(X : @key[in] T1); --@RI{ Have to override.} @key[end] Pack2; @key[with] Pack1; @key[use] Pack1; @key[with] Pack2; @key[use] Pack2; @key[package] Pack3 @key[is] @key[type] T2 @key[is] @key[new] Ancestor @key[with] @key[private]; --@RI{ A concrete type.} @key[private] @key[type] T2 @key[is] @key[new] T1 @key[with] --@RI{ Parent different from ancestor.} @key[record] ... @key[end] @key[record]; --@RI{ Here, we inherit Pack2.Do_Something.} @key[end] Pack3; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00011} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00228-01]} T2 inherits an abstract Do_Something, but @Chg{New=[T2],Old=[T]} is not abstract, so Do_Something has to be overridden. However, it is OK to override it in the private part. In this case, we override it by inheriting a concrete version from a different type. Nondispatching calls to Pack3.Do_Something are allowed both inside and outside package Pack3@Chg{Version=[2],New=[, as the client @lquotes@;knows@rquotes@; that the subprogram was necessarily overridden somewhere],Old=[]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[For a null extension, the result of a function with a controlling result is defined in terms of an @nt{extension_aggregate} with a @key{null record} extension part (see @RefSecNum{Derived Types and Classes}). This means that these restrictions on functions with a controlling result do not have to apply to null extensions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[However, functions with controlling access results still require overriding. Changing the tag in place might clobber a preexisting object, and allocating new memory would possibly change the pool of the object, leading to storage leaks. Moreover, copying the object isn't possible for limited types. We don't need to restrict functions that have an access return type of an untagged type, as derived types with primitive subprograms have to have the same representation as their parent type.]} @end{Reason} @end{Itemize} A call on an abstract subprogram shall be a dispatching call; @Redundant[nondispatching calls to an abstract subprogram are not allowed.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} If an abstract subprogram is not a dispatching operation of some tagged type, then it cannot be called at all.@Chg{Version=[2],New=[ In Ada 2005, such subprograms are not even considered by name resolution (see @RefSecNum{Subprogram Calls}).],Old=[]} @end{Ramification} The type of an @nt{aggregate}, or of an object created by an @nt{object_declaration} or an @nt{allocator}, or a generic formal object of mode @key[in], shall not be abstract. The type of the target of an assignment operation (see @RefSecNum{Assignment Statements}) shall not be abstract. The type of a component shall not be abstract. If the result type of a function is abstract, then the function shall be abstract. @begin{Reason} This ensures that values of an abstract type cannot be created, which ensures that a dispatching call to an abstract subprogram will not try to execute the nonexistent body. Generic formal objects of mode @key[in] are like constants; therefore they should be forbidden for abstract types. Generic formal objects of mode @key[in out] are like renamings; therefore, abstract types are OK for them, though probably not terribly useful. @end{Reason} If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract. @begin{Discussion} By contrast, we allow the actual type to be nonabstract even if the formal type is declared abstract. Hence, the most general formal tagged type possible is "@key(type) T(<>) @key(is abstract tagged limited private);". For an abstract private extension declared in the visible part of a package, it is only possible for the full type to be nonabstract if the private extension has no abstract dispatching operations. @end{Discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00294-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the sentence about primitive subprograms above, there is some ambiguity as to what is meant by @lquotes@;corresponding@rquotes@; in the case where an inherited operation is overridden. This is best explained by an example, where the implicit declarations are shown as comments:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P1 @key{is} @key{type} T1 @key{is abstract tagged null record}; @key{procedure} P (X : T1); -- @RI[(1)] @key{end} P1;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P2 @key{is} @key{type} T2 @key{is abstract new} P1.T1 @key{with null record}; -- @RI[@key{procedure} P (X : T2); -- (2)] @key{procedure} P (X : T2) @key{is abstract}; -- (3) end P2;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} D @key{is abstract new} P1.T1 @key{with private}; -- @RI[@key{procedure} P (X : D); -- (4)] @key{procedure} G (X : D);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} I @key{is new} G (P2.T2); -- @RI[Illegal.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[Type T2 inherits a non-abstract procedure P (2) from the primitive procedure P (1) of T1. P (2) is overridden by the explicitly declared abstract procedure P (3). Type D inherits a non-abstract procedure P (4) from P (1). In instantiation I, the operation corresponding to P (4) is the one which is not overridden, that is, P (3): the overridden operation P (2) does not @lquotes@;reemerge@rquotes@;. Therefore, the instantiation is illegal.],Old=[]} @end{Honest} For an abstract type declared in a visible part, an abstract primitive subprogram shall not be declared in the private part, unless it is overriding an abstract subprogram implicitly declared in the visible part. For a tagged type declared in a visible part, a primitive function with a controlling result shall not be declared in the private part, unless it is overriding a function implicitly declared in the visible part. @begin{Reason} @Leading@;The @lquotes@;visible part@rquotes@; could be that of a package or a generic package. This rule is needed because a non-abstract type extension declared outside the package would not know about any abstract primitive subprograms or primitive functions with controlling results declared in the private part, and wouldn't know that they need to be overridden with non-abstract subprograms. The rule applies to a tagged record type or record extension declared in a visible part, just as to a tagged private type or private extension. The rule applies to explicitly and implicitly declared abstract subprograms: @begin{Example} @key[package] Pack @key[is] @key[type] T @key[is] @key[abstract] @key[new] T1 @key[with] @key[private]; @key[private] @key[type] T @key[is] @key[abstract] @key[new] T2 @key[with] @key[record] ... @key[end] @key[record]; ... @key[end] Pack; @end{Example} The above example would be illegal if T1 has a non-abstract primitive procedure P, but T2 overrides P with an abstract one; the private part should override P with a non-abstract version. On the other hand, if the P were abstract for both T1 and T2, the example would be legal as is. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} A generic actual subprogram shall not be an abstract subprogram @Chg{Version=[2],New=[unless the generic formal subprogram is declared by a @nt{formal_abstract_subprogram_declaration}],Old=[]}. The @nt{prefix} of an @nt{attribute_reference} for the Access, Unchecked_Access, or Address attributes shall not denote an abstract subprogram. @begin{Ramification} An @nt{abstract_subprogram_declaration} is not syntactically a @nt{subprogram_declaration}. Nonetheless, an abstract subprogram is a subprogram, and an @nt{abstract_subprogram_declaration} is a declaration of a subprogram. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} The part about generic actual subprograms includes those given by default.@Chg{Version=[2],New=[ Of course, an abstract formal subprogram's actual subprogram can be abstract.],Old=[]} @end{Ramification} @end{Legality} @begin{Runtime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[elaboration], Sec=(abstract_subprogram_declaration)} The elaboration of an @nt{abstract_subprogram_declaration} has no effect.]} @end{Runtime} @begin{Notes} Abstractness is not inherited; to declare an abstract type, the reserved word @key[abstract] has to be used in the declaration of the type extension. @begin{Ramification} A derived type can be abstract even if its parent is not. Similarly, an inherited concrete subprogram can be overridden with an abstract subprogram. @end{Ramification} A class-wide type is never abstract. Even if a class is rooted at an abstract type, the class-wide type for the class is not abstract, and an object of the class-wide type can be created; the tag of such an object will identify some nonabstract type in the class. @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of an abstract type representing a set of natural numbers:) @begin{Example} @key(package) Sets @key(is) @key(subtype) Element_Type @key(is) Natural; @key(type) Set @key(is abstract tagged null record); @key(function) Empty @key(return) Set @key(is abstract); @key(function) Union(Left, Right : Set) @key(return) Set @key(is abstract); @key(function) Intersection(Left, Right : Set) @key(return) Set @key(is abstract); @key(function) Unit_Set(Element : Element_Type) @key(return) Set @key(is abstract); @key(procedure) Take(Element : @key(out) Element_Type; From : @key(in out) Set) @key(is abstract); @key(end) Sets; @end{Example} @end{Examples} @begin{Notes} @i(Notes on the example:) Given the above abstract type, one could then derive various (nonabstract) extensions of the type, representing alternative implementations of a set. One might use a bit vector, but impose an upper bound on the largest element representable, while another might use a hash table, trading off space for flexibility. @begin{Discussion} One way to export a type from a package with some components visible and some components private is as follows: @begin{Example} @key[package] P @key[is] @key[type] Public_Part @key[is] @key[abstract] @key[tagged] @key[record] ... @key[end] @key[record]; @key[type] T @key[is] @key[new] Public_Part @key[with] @key[private]; ... @key[private] @key[type] T @key[is] @key[new] Public_Part @key[with] @key[record] ... @key[end] @key[record]; @key[end] P; @end{Example} The fact that Public_Part is abstract tells clients they have to create objects of type T instead of Public_Part. Note that the public part has to come first; it would be illegal to declare a private type Private_Part, and then a record extension T of it, unless T were in the private part after the full declaration of Private_Part, but then clients of the package would not have visibility to T. @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} It is not necessary to override functions with a controlling result for a null extension. This makes it easier to derive a tagged type to complete a private type.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect the addition of interface types (see @RefSecNum{Interface Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect the addition of abstract formal subprograms (see @RefSecNum{Formal Subprograms}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00334-01]} @ChgAdded{Version=[2],Text=[The wording of shall-be-overridden was clarified so that it clearly applies to abstract predefined equality.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Moved the syntax and elaboration rule for @nt{abstract_subprogram_declaration} here, so the syntax and most of the semantics are together (which is consistent with null procedures).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[We define the term @i<require overriding> to make other wording easier to understand.]} @end{Diffword95} @LabeledAddedSubClause{Version=[2],Name=[Interface Types]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Redundant[An interface type is an abstract tagged type that provides a restricted form of multiple inheritance. A tagged type, task type, or protected type may have one or more interface types as ancestors.]]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Interface type>, Text=<@ChgAdded{Version=[2],Text=[An interface type is a form of abstract tagged type which has no components or concrete operations except possibly null procedures. Interface types are used for composing other interfaces and tagged types and thereby provide multiple inheritance. Only an interface type can be used as a progenitor of another type.]}>} @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The rules are designed so that an interface can be used as either a parent type or a progenitor type without changing the meaning. That's important so that the order that interfaces are specified in a @nt{derived_type_definition} is not significant. In particular, we want:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Con1 @key{is new} Int1 @key{and} Int2 @key{with null record}; @key{type} Con2 @key{is new} Int2 @key{and} Int1 @key{with null record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[to mean exactly the same thing.]} @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<interface_type_definition>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@key{limited} | @key{task} | @key{protected} | @key{synchronized}] @key{interface} [@key{and} @Syn2{interface_list}]>,Old=<>}"} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00419-01]} @Syn{lhs=<@Chg{Version=[2],New=<interface_list>,Old=<>}>, rhs="@Chg{Version=[2],New=<@SynI{interface_}@Syn2{subtype_mark} {@key{and} @SynI{interface_}@Syn2{subtype_mark}}>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[An interface type (also called an @i{interface}) is@RootDefn{interface}@PDefn2{Term=[interface],Sec=[type]} a specific abstract tagged type that is defined by an @nt{interface_type_definition}.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface with the reserved word @key{limited}, @key{task}, @key{protected}, or @key{synchronized} in its definition is termed, respectively, a @i{limited interface}, a @i{task interface}, a @i{protected interface}, or a @i{synchronized interface}. In addition,@PDefn2{Term=[interface],Sec=[synchronized]} @PDefn2{Term=[interface],Sec=[protected]} @PDefn2{Term=[interface],Sec=[task]} @PDefn2{Term=[interface],Sec=[limited]} @PDefn2{Term=[interface],Sec=[nonlimited]} @Defn{synchronized interface} @Defn{protected interface} @Defn{task interface} @Defn{limited interface} @Defn{nonlimited interface} all task and protected interfaces are synchronized interfaces, and all synchronized interfaces are limited interfaces.]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Synchronized>, Text=<@ChgAdded{Version=[2],Text=[A synchronized entity is one that will work safely with multiple tasks at one time. A synchronized interface can be an ancestor of a task or a protected type. Such a task or protected type is called a synchronized tagged type.]}>} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[@Defn{synchronized tagged type} @PDefn2{Term=[type],Sec=[synchronized tagged]} @PDefn2{Term=[tagged type],Sec=[synchronized]} @PDefn2{Term=[tagged type],Sec=[task]} @PDefn2{Term=[tagged type],Sec=[protected]} @Defn{task tagged type} @Defn{protected tagged type} @Redundant[A task or protected type derived from an interface is a tagged type.] Such a tagged type is called a @i<synchronized> tagged type, as are synchronized interfaces and private extensions whose declaration includes the reserved word @b{synchronized}.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The full definition of tagged types given in @RefSecNum{Tagged Types and Type Extensions} includes task and protected types derived from interfaces.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The class-wide type associated with a tagged task type (including a task interface type) is a task type, because @lquotes@;task@rquotes is one of the language-defined classes of types (see @RefSecNum{Types and Subtypes}. However, the class-wide type associated with an interface is @i<not> an interface type, as @lquotes@;interface@rquotes is @i<not> one of the language-defined classes (as it is not closed under derivation). In this sense, @lquotes@;interface@rquotes is similar to @lquotes@;abstract@rquotes. The class-wide type associated with an interface is a concrete (nonabstract) indefinite tagged composite type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@lquotes@;Private extension@rquotes@; includes generic formal private extensions, as explained in @RefSecNum{Formal Private and Derived Types}.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A task interface is an @Redundant[abstract] task type. A protected interface is an @Redundant[abstract] protected type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;abstract@rquotes follows from the definition of an interface type.]} @end{TheProof} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that task operations (like abort and the Terminated attribute) can be applied to a task interface type and the associated class-wide type. While there are no protected type operations, we apply the same rule to protected interfaces for consistency.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[@Redundant[An interface type has no components.]],Old=[]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This follows from the syntax and the fact that discriminants are not allowed for interface types.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{progenitor subtype}@Defn{progenitor type} An @Syni(interface_)@nt{subtype_mark} in an @nt{interface_list} names a @i(progenitor subtype); its type is the @i(progenitor type). An interface type inherits user-defined primitive subprograms from each progenitor type in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}).]} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Progenitor>, Text=<@ChgAdded{Version=[2],Text=[A progenitor of a derived type is one of the types given in the definition of the derived type other than the first. A progenitor is always an interface type. Interfaces, tasks, and protected types may also have progenitors.]}>} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[All user-defined primitive subprograms of an interface type shall be abstract subprograms or null procedures.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The type of a subtype named in an @nt{interface_list} shall be an interface type.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A type derived from a nonlimited interface shall be nonlimited.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a task interface shall include the reserved word @key{task} in its definition; any other type derived from a task interface shall be a private extension or a task type declared by a task declaration (see @RefSecNum{Task Units and Task Objects}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a protected interface shall include the reserved word @key{protected} in its definition; any other type derived from a protected interface shall be a private extension or a protected type declared by a protected declaration (see @RefSecNum{Protected Units and Protected Objects}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a synchronized interface shall include one of the reserved words @key{task}, @key{protected}, or @key{synchronized} in its definition; any other type derived from a synchronized interface shall be a private extension, a task type declared by a task declaration, or a protected type declared by a protected declaration.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require that an interface descendant of a task, protected, or synchronized interface repeat the explicit kind of interface it will be, rather than simply inheriting it, so that a reader is always aware of whether the interface provides synchronization and whether it may be implemented only by a task or protected type. The only place where inheritance of the kind of interface might be useful would be in a generic if you didn't know the kind of the actual interface. However, the value of that is low because you cannot implement an interface properly if you don't know whether it is a task, protected, or synchronized interface. Hence, we require the kind of the actual interface to match the kind of the formal interface (see @RefSecNum{Formal Interface Types}).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[No type shall be derived from both a task interface and a protected interface.]} @begin{Reason} @ChgAdded{Version=[2],Text=[This prevents a single private extension from inheriting from both a task and a protected interface. For a private type, there can be no legal completion. For a generic formal derived type, there can be no possible matching type (so no instantiation could be legal). This rule provides early detection of the errors.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.@PDefn{generic contract issue}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This paragraph is intended to apply to all of the @LegalityTitle@; in this clause. We cannot allow interface types which do not obey these rules, anywhere. Luckily, deriving from a formal type (which might be an interface) is not allowed for any tagged types in a generic body. So checking in the private part of a generic covers all of the cases.]} @end{Ramification} @end{Legality} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The elaboration of an @nt{interface_type_definition} has no effect.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{interface_list} is made up of @nt{subtype_mark}s, which do not need to be elaborated, so the @nt{interface_list} does not either. This is consistent with the handling of @nt{discriminant_part}s.]} @end{Discussion} @end{Runtime} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00411-01]} @ChgAdded{Version=[2],Text=[Nonlimited interface types have predefined nonabstract equality operators. These may be overridden with user-defined abstract equality operators. Such operators will then require an explicit overriding for any nonabstract descendant of the interface.]} @end{Notes} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example of a limited interface and a synchronized interface extending it:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Queue @key{is limited interface}; @key{procedure} Append(Q : @key{in out} Queue; Person : @key{in} Person_Name) @key{is abstract}; @key{procedure} Remove_First(Q : @key{in out} Queue; Person : @key{out} Person_Name) @key{is abstract}; @key{function} Cur_Count(Q : @key{in} Queue) @key{return} Natural @key{is abstract}; @key{function} Max_Count(Q : @key{in} Queue) @key{return} Natural @key{is abstract}; -- @RI[See @RefSecNum{Incomplete Type Declarations} for Person_Name.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Queue_Error : @key{exception}; --@RI[ Append raises Queue_Error if Count(Q) = Max_Count(Q)] --@RI[ Remove_First raises Queue_Error if Count(Q) = 0]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Synchronized_Queue @key{is synchronized interface and} Queue; --@RI[ see @RefSecNum{Example of Tasking and Synchronization}] @key{procedure} Append_Wait(Q : @key{in out} Synchronized_Queue; Person : @key{in} Person_Name) @key{is abstract}; @key{procedure} Remove_First_Wait(Q : @key{in out} Synchronized_Queue; Person : @key{out} Person_Name) @key{is abstract};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} Transfer(From : @key{in out} Queue'Class; To : @key{in out} Queue'Class; Number : @key{in} Natural := 1) @key{is} Person : Person_Name; @key{begin} @key{for} I @key{in} 1..Number @key{loop} Remove_First(From, Person); Append(To, Person); @key{end loop}; @key{end} Transfer;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This defines a Queue interface defining a queue of people. (A similar design could be created to define any kind of queue simply by replacing Person_Name by an appropriate type.) The Queue interface has four dispatching operations, Append, Remove_First, Cur_Count, and Max_Count. The body of a class-wide operation, Transfer is also shown. Every non-abstract extension of Queue must provide implementations for at least its four dispatching operations, as they are abstract. Any object of a type derived from Queue may be passed to Transfer as either the From or the To operand. The two operands need not be of the same type in any given call.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Synchronized_Queue interface inherits the four dispatching operations from Queue and adds two additional dispatching operations, which wait if necessary rather than raising the Queue_Error exception. This synchronized interface may only be implemented by a task or protected type, and as such ensures safe concurrent access.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example use of the interface:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Fast_Food_Queue @key{is new} Queue @key{with record} ...; @key{procedure} Append(Q : @key{in out} Fast_Food_Queue; Person : @key{in} Person_Name); @key{procedure} Remove_First(Q : @key{in out} Fast_Food_Queue; Person : @key{in} Person_Name); @key{function} Cur_Count(Q : @key{in} Fast_Food_Queue) @key{return} Natural; @key{function} Max_Count(Q : @key{in} Fast_Food_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Cashier, Counter : Fast_Food_Queue;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[... -- @RI[Add George (see @RefSecNum{Incomplete Type Declarations}) to the cashier's queue:] Append (Cashier, George); -- @RI[After payment, move George to the sandwich counter queue:] Transfer (Cashier, Counter); ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An interface such as Queue can be used directly as the parent of a new type (as shown here), or can be used as a progenitor when a type is derived. In either case, the primitive operations of the interface are inherited. For Queue, the implementation of the four inherited routines must be provided. Inside the call of Transfer, calls will dispatch to the implementations of Append and Remove_First for type Fast_Food_Queue.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example of a task interface:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Serial_Device @key{is task interface}; --@RI[ see @RefSecNum{Task Units and Task Objects}] @key{procedure} Read (Dev : @key{in} Serial_Device; C : @key{out} Character) @key{is abstract}; @key{procedure} Write(Dev : @key{in} Serial_Device; C : @key{in} Character) @key{is abstract};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Serial_Device interface has two dispatching operations which are intended to be implemented by task entries (see 9.1).]} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Interface types are new. They provide multiple inheritance of interfaces, similar to the facility provided in Java and other recent language designs.]} @end{Extend95} @LabeledClause{Access Types} @begin{Intro} @Defn{access type} @Defn{access value} @Defn{designate} A value of an access type (an @i(access value)) provides indirect access to the object or subprogram it @i(designates). Depending on its type, an access value can designate either subprograms, objects created by allocators (see @RefSecNum(Allocators)), or more generally @i(aliased) objects of an appropriate type. @IndexSee{Term=[pointer],See=(access value)} @IndexSee{Term=[pointer type],See=(access type)} @begin(Discussion) A @nt<name> @i(denotes) an entity; an access value @i(designates) an entity. The @lquotes@;dereference@rquotes@; of an access value X, written @lquotes@;X.@key[all]@rquotes@;, is a @nt<name> that denotes the entity designated by X. @end(Discussion) @end{Intro} @begin{MetaRules} Access values should always be well defined (barring uses of certain unchecked features of Section 13). In particular, uninitialized access variables should be prevented by compile-time rules. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<access_type_definition>,rhs=" @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{access_to_object_definition} | @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{access_to_subprogram_definition}"} @Syn{lhs=<access_to_object_definition>,rhs=" @key{access} [@Syn2{general_access_modifier}] @Syn2{subtype_indication}"} @Syn{lhs=<general_access_modifier>,rhs="@key{all} | @key{constant}"} @Syn{lhs=<access_to_subprogram_definition>,rhs=" @key{access} [@key{protected}] @key{procedure} @Syn2{parameter_profile} | @key{access} [@key{protected}] @key{function} @Syn2{parameter_and_result_profile}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[null_exclusion],Old=[]}>, rhs="@Chg{Version=[2],New=[@key{not} @key{null}],Old=[]}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00404-01]} @Syn{lhs=<access_definition>,rhs="@Chg{Version=[2],New=< [@Syn2{null_exclusion}] @key{access} [@key{constant}] @Syn2{subtype_mark} | [@Syn2{null_exclusion}] @key{access} [@key{protected}] @key{procedure} @Syn2{parameter_profile} | [@Syn2{null_exclusion}] @key{access} [@key{protected}] @key{function} @Syn2{parameter_and_result_profile}>, Old=[@key{access} @Syn2{subtype_mark}]}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0012],ARef=[AI95-00062-01]} @Defn{access-to-object type} @Defn{access-to-subprogram type} @Defn{pool-specific access type} @Defn{general access type} There are two kinds of access types, @i{access-to-object} types, whose values designate objects, and @i(access-to-subprogram) types, whose values designate subprograms. @Defn{storage pool} Associated with an access-to-object type is a @i(storage pool); several access types may share the same storage pool. @Chg{New=[All descendants of an access type share the same storage pool.],Old=[]} @Defn{pool element} A storage pool is an area of storage used to hold dynamically allocated objects (called @i(pool elements)) created by allocators@Redundant[; storage pools are described further in @RefSec(Storage Management)]. @Defn{pool-specific access type} @Defn{general access type} Access-to-object types are further subdivided into @i(pool-specific) access types, whose values can designate only the elements of their associated storage pool, and @i(general) access types, whose values can designate the elements of any storage pool, as well as aliased objects created by declarations rather than allocators, and aliased subcomponents of other objects. @begin(ImplNote) The value of an access type will typically be a machine address. However, a value of a pool-specific access type can be represented as an offset (or index) relative to its storage pool, since it can point only to the elements of that pool. @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00225-01],ARef=[AI95-00363-01]} @Defn{aliased} A view of an object is defined to be @i(aliased) if it is defined by an @nt<object_@!declaration> or @nt<component_@!definition> with the reserved word @key(aliased), or by a renaming of an aliased view. In addition, the dereference of an access-to-object value denotes an aliased view, as does a view conversion (see @RefSecNum{Type Conversions}) of an aliased view. @Chg{Version=[2],New=[The],Old=[Finally, the]} current instance of a limited@Chg{Version=[2],New=[ tagged],Old=[]} type, @Chg{Version=[2],New=[a protected type, a task type, or a type that has the reserved word @key{limited} in its full definition is also defined to be aliased. Finally,],Old=[and]} a formal parameter or generic formal object of a tagged type @Chg{Version=[2],New=[is],Old=[are]} defined to be aliased. @Redundant[Aliased views are the ones that can be designated by an access value.] @Chg{Version=[2],New=[],Old=[@Defn2{Term=[constrained], Sec=(object)} @Defn2{Term=[unconstrained], Sec=(object)} @Defn{constrained by its initial value} If the view defined by an @nt{object_@!declaration} is aliased, and the type of the object has discriminants, then the object is constrained; if its nominal subtype is unconstrained, then the object is constrained by its initial value. @Redundant[Similarly, if the object created by an @nt<allocator> has discriminants, the object is constrained, either by the designated subtype, or by its initial value.]]} @ToGlossary{Term=<Aliased>, Text=<An aliased view of an object is one that can be designated by an access value. Objects allocated by allocators are aliased. Objects can also be explicitly declared as aliased with the reserved word @key(aliased). The Access attribute can be used to create an access value designating an aliased object.>} @begin(Ramification) The current instance of a nonlimited type is not aliased. The object created by an allocator is aliased, but not its subcomponents, except of course for those that themselves have @key(aliased) in their @nt<component_definition>. The renaming of an aliased object is aliased. Slices are never aliased. See @RefSecNum{Slices} for more discussion. @end(Ramification) @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00225-01]} The current instance of a limited type is defined to be aliased so that an access discriminant of a component can be initialized with T'Access inside the definition of T.@Chg{Version=[2],New=[ Note that we don't want this to apply to a type that could become nonlimited later within its immediate scope, so we require the full definition to be limited.],Old=[]} A formal parameter of a tagged type is defined to be aliased so that a (tagged) parameter X may be passed to an access parameter P by using P => X'Access. Access parameters are most important for tagged types because of dispatching-on-access-parameters (see @RefSecNum(Dispatching Operations of Tagged Types)). By restricting this to formal parameters, we minimize problems associated with allowing components that are not declared aliased to be pointed-to from within the same record. @Leading@;A view conversion of an aliased view is aliased so that the type of an access parameter can be changed without first converting to a named access type. For example: @begin{Example} @key(type) T1 @key(is tagged) ...; @key(procedure) P(X : @key(access) T1); @key(type) T2 @key(is new) T1 @key(with) ...; @key(procedure) P(X : @key(access) T2) @key(is) @key(begin) P(T1(X.@key(all))'Access); --@RI[ hand off to T1's P] . . . --@RI[ now do extra T2-specific processing] @key(end) P; @end{Example} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[The rule about objects with discriminants is necessary because values of a constrained access subtype can designate an object whose nominal subtype is unconstrained; without this rule, a check on every use of such values would be required to ensure that the discriminants of the object had not changed. With this rule (among others), we ensure that if there might exist aliased views of a discriminated object, then the object is necessarily constrained. Note that this rule is necessary only for untagged types, since a discriminant of a tagged type can't have a default, so all tagged discriminated objects are always constrained anyway.]} @ChgNote{This rule was a disaster, so it thankfully has been repealed. We instead make general access constrained subtypes illegal if the type allows unconstrained instances, see Discriminant Constraints.} @ChgRef{Version=[2],Kind=[Revised]}@ChgNote{Eilers reported double word} We considered making more kinds of objects aliased by default. In particular, any object of a by-reference type will pretty much have to be allocated at an addressable location, so it can be passed by reference without using bit-field pointers. Therefore, one might wish to allow the Access and @Chg{Version=[2],New=[],Old=[and ]}Unchecked_Access attributes for such objects. However, private parts are transparent to the definition of @lquotes@;by-reference type@rquotes@;, so if we made all objects of a by-reference type aliased, we would be violating the privacy of private parts. Instead, we would have to define a concept of @lquotes@;visibly by-reference@rquotes@; and base the rule on that. This seemed to complicate the rules more than it was worth, especially since there is no way to declare an untagged limited private type to be by-reference, since the full type might by nonlimited. @end(Reason) @begin{Discussion} Note that we do not use the term @lquotes@;aliased@rquotes@; to refer to formal parameters that are referenced through multiple access paths (see @RefSecNum{Formal Parameter Modes}). @end{Discussion} An @nt{access_to_object_definition} defines an access-to-object type and its first subtype; @Defn2{Term=[designated subtype], Sec=(of a named access type)} @Defn2{Term=[designated type], Sec=(of a named access type)} the @nt<subtype_@!indication> defines the @i(designated subtype) of the access type. If a @nt<general_@!access_@!modifier> appears, then the access type is a general access type. @Defn{access-to-constant type} If the modifier is the reserved word @key(constant), then the type is an @i(access-to-constant type)@Redundant[; a designated object cannot be updated through a value of such a type]. @Defn{access-to-variable type} If the modifier is the reserved word @key(all), then the type is an @i(access-to-variable type)@Redundant[; a designated object can be both read and updated through a value of such a type]. If no @nt<general_@!access_@!modifier> appears in the @nt<access_to_@!object_@!definition>, the access type is a pool-specific access-to-variable type. @begin{Honest} The type of the designated subtype is called the @i{designated type}. @end{Honest} @begin(Reason) The modifier @key(all) was picked to suggest that values of a general access type could point into @lquotes@;all@rquotes@; storage pools, as well as to objects declared aliased, and that @lquotes@;all@rquotes@; access (both read and update) to the designated object was provided. We couldn't think of any use for pool-specific access-to-constant types, so any access type defined with the modifier @key(constant) is considered a general access type, and can point into any storage pool or at other (appropriate) aliased objects. @end(Reason) @begin(ImplNote) The predefined generic Unchecked_Deallocation can be instantiated for any named access-to-variable type. There is no (language-defined) support for deallocating objects designated by a value of an access-to-constant type. Because of this, an allocator for an access-to-constant type can allocate out of a storage pool with no support for deallocation. Frequently, the allocation can be done at link-time, if the size and initial value are known then. @end(ImplNote) @begin(Discussion) For the purpose of generic formal type matching, the relevant subclasses of access types are access-to-subprogram types, access-to-constant types, and (named) access-to-variable types, with its subclass (named) general access-to-variable types. Pool-specific access-to-variable types are not a separately matchable subclass of types, since they don't have any @lquotes@;extra@rquotes@; operations relative to all (named) access-to-variable types. @end(Discussion) @Defn{access-to-subprogram type} An @nt{access_to_subprogram_definition} defines an access-to-subprogram type and its first subtype; @Defn2{Term=[designated profile], Sec=(of an access-to-subprogram type)} the @nt<parameter_profile> or @nt<parameter_and_result_profile> defines the @i(designated profile) of the access type. @Defn2{Term=[calling convention], Sec=(associated with a designated profile)} There is a @i(calling convention) associated with the designated profile@Redundant[; only subprograms with this calling convention can be designated by values of the access type.] By default, the calling convention is @lquotes@i(protected)@rquotes@; if the reserved word @key(protected) appears, and @lquotes@;Ada@rquotes@; otherwise. @Redundant[See @RefSecNum{Interface to Other Languages} for how to override this default.] @begin(Ramification) The calling convention @i(protected) is in italics to emphasize that it cannot be specified explicitly by the user. This is a consequence of it being a reserved word. @end(Ramification) @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} For @Chg{Version=[2],New=[a named],Old=[an]} access-to-subprogram type, the representation of an access value might include implementation-defined information needed to support up-level references @em for example, a static link. The accessibility rules (see @RefSecNum(Operations of Access Types)) ensure that in a "global-display-based" implementation model (as opposed to a static-link-based model), @Chg{Version=[2],New=[a named],Old=[an]} access-to-(unprotected)-subprogram value need consist only of the address of the subprogram. The global display is guaranteed to be properly set up any time the designated subprogram is called. Even in a static-link-based model, the only time a static link is definitely required is for an access-to-subprogram type declared in a scope nested at least two levels deep within subprogram or task bodies, since values of such a type might designate subprograms nested a smaller number of levels. For the normal case of @Chg{Version=[2],New=[a named],Old=[an]} access-to-subprogram type declared at the outermost (library) level, a code address by itself should be sufficient to represent the access value in many implementations. For access-to-protected-subprogram, the access values will necessarily include both an address (or other identification) of the code of the subprogram, as well as the address of the associated protected object. This could be thought of as a static link, but it will be needed even for global-display-based implementation models. It corresponds to the value of the @lquotes@;implicit parameter@rquotes@; that is passed into every call of a protected operation, to identify the current instance of the protected type on which they are to operate. Any Elaboration_Check is performed when a call is made through an access value, rather than when the access value is first "created" via a 'Access. For implementation models that normally put that check at the call-site, an access value will have to point to a separate entry point that does the check. Alternatively, the access value could point to a "subprogram descriptor" that consisted of two words (or perhaps more), the first being the address of the code, the second being the elaboration bit. Or perhaps more efficiently, just the address of the code, but using the trick that the descriptor is initialized to point to a Raise-Program-Error routine initially, and then set to point to the "real" code when the body is elaborated. For implementations that share code between generic instantiations, the extra level of indirection suggested above to support Elaboration_Checks could also be used to provide a pointer to the per-instance data area normally required when calling shared code. The trick would be to put a pointer to the per-instance data area into the subprogram descriptor, and then make sure that the address of the subprogram descriptor is loaded into a "known" register whenever an indirect call is performed. Once inside the shared code, the address of the per-instance data area can be retrieved out of the subprogram descriptor, by indexing off the "known" register. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00344-01]} @ChgNote{This is not remotely true with nested extensions and with interfaces. I don't much feel like trying to explain this properly.} @ChgDeleted{Version=[2],Text=[Essentially the same implementation issues arise for calls on dispatching operations of tagged types, except that the static link is always known "statically."]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} Note that access parameters of an anonymous access-to-subprogram type are @Chg{Version=[2],New=[],Old=[not ]}permitted. @Chg{Version=[2],New=[Such],Old=[If there were such]} parameters@Chg{Version=[2], New=[ represent],Old=[,]} full @lquotes@;downward@rquotes@; closures@Chg{Version=[2],New=[],Old=[would be required]}, meaning that in an implementation that uses a per-task (global) display, the display @Chg{Version=[2],New=[will],Old=[would]} have to be passed as a hidden parameter, and reconstructed at the point of call.@Chg{Version=[2],New=[], Old=[ This was felt to be an undue implementation burden, given that an equivalent (actually, more general) capability is available via formal subprogram parameters to a generic.]} @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @Defn{anonymous access type} @Defn2{Term=[designated subtype], Sec=(of an anonymous access type)} @Defn2{Term=[designated type], Sec=(of an anonymous access type)} An @nt{access_definition} defines an anonymous general @Chg{Version=[2],New=[access type or an anonymous access-to-subprogram type. For a general access type,], Old=[access-to-variable type;]} the @nt<subtype_mark> denotes its @i(designated subtype)@Chg{Version=[2],New=[; if the @nt{general_@!access_@!modifier} @key{constant} appears, the type is an access-to-constant type; otherwise it is an access-to-variable type. For an access-to-subprogram type, the @nt{parameter_@!profile} or @nt{parameter_@!and_@!result_@!profile} denotes its @i{designated profile}.@Defn2{Term=[designated profile], Sec=(of an anonymous access type)}], Old=[. @Redundant[An @nt<access_definition> is used in the specification of an access discriminant (see @RefSecNum(Discriminants)) or an access parameter (see @RefSecNum(Subprogram Declarations)).]]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @Defn2{Term=[null value], Sec=(of an access type)} For each @Chg{Version=[2],New=[],Old=[(named) ]}access type, there is @Chg{Version=[2],New=[],Old=[a literal @key(null) which has ]}a null access value designating no entity at all@Chg{Version=[2],New=[, which can be obtained by (implicitly) converting the literal @key{null} to the access type],Old=[]}. @Redundant[The null value of @Chg{Version=[2],New=[an],Old=[a named]} access type is the default initial value of the type.] @Chg{Version=[2],New=[Non-null],Old=[Other]} values of an access@Chg{Version=[2],New=[-to-object],Old=[]} type are obtained by evaluating @Chg{Version=[2],New=[],Old=[an @nt<attribute_reference> for the Access or Unchecked_Access attribute of an aliased view of an object or non-intrinsic subprogram, or, in the case of a named access-to-object type,]} an @nt<allocator>@Redundant[, which returns an access value designating a newly created object (see @RefSecNum(Operations of Access Types))]@Chg{Version=[2],New=[, or in the case of a general access-to-object type, evaluating an @nt{attribute_reference} for the Access or Unchecked_Access attribute of an aliased view of an object. Non-null values of an access-to-subprogram type are obtained by evaluating an @nt{attribute_reference} for the Access attribute of a non-intrinsic subprogram.],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[A value of an anonymous access type (that is, the value of an access parameter or access discriminant) cannot be null.]} @end{ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[Access parameters allow dispatching on the tag of the object designated by the actual parameter (which gets converted to the anonymous access type as part of the call). In order for dispatching to work properly, there had better be such an object. Hence, the type conversion will raise Constraint_Error if the value of the actual parameter is null.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[excludes null],Sec=[subtype]} A @nt{null_exclusion} in a construct specifies that the null value does not belong to the access subtype defined by the construct, that is, the access subtype @i{excludes null}. In addition, the anonymous access subtype defined by the @nt{access_definition} for a controlling access parameter (see @RefSecNum{Dispatching Operations of Tagged Types}) excludes null. Finally, for a @nt{subtype_indication} without a @nt{null_exclusion}, the subtype denoted by the @nt{subtype_indication} excludes null if and only if the subtype denoted by the @nt{subtype_mark} in the @nt{subtype_indication} excludes null.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[An @nt{access_definition} used in a controlling parameter excludes null because it is necessary to read the tag to dispatch, and null has no tag. We would have preferred to require @key{not null} to be specified for such parameters, but that would have been too incompatible with Ada 95 code to require.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Note that we considered imposing a similar implicit null exclusion for controlling access results, but chose not to do that, because there is no Ada 95 compatibility issue, and there is no automatic null check inherent in the use of a controlling access result. If a null check is necessary, it is because there is a dereference of the result, or because the value is passed to a parameter whose subtype excludes null. If there is no dereference of the result, a null return value is perfectly acceptable, and can be a useful indication of a particular status of the call.]} @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0013],ARef=[AI95-00012-01]} @PDefn2{Term=[constrained],Sec=(subtype)} @PDefn2{Term=[unconstrained],Sec=(subtype)} @Redundant[All subtypes of an access-to-subprogram type are constrained.] The first subtype of a type defined by an @Chg{New=[@nt<access_definition>],Old=[@nt<access_type_definition>]} or an @nt<access_to_object_definition> is unconstrained if the designated subtype is an unconstrained array or discriminated @Chg{New=[subtype],Old=[type]}; otherwise it is constrained. @begin(TheProof) The @LegalityTitle on @nt<range_constraint>s (see @RefSecNum(Scalar Types)) do not permit the @nt<subtype_mark> of the @nt<subtype_indication> to denote an access-to-scalar type, only a scalar type. The @LegalityTitle on @nt<index_constraint>s (see @RefSecNum(Index Constraints and Discrete Ranges)) and @nt<discriminant_constraint>s (see @RefSecNum(Discriminant Constraints)) both permit access-to-composite types in a @nt<subtype_indication> with such _@nt<constraint>s. Note that an access-to-access-to-composite is never permitted in a @nt<subtype_indication> with a @nt<constraint>. @end(TheProof) @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} Only @nt<composite_constraint>s are permitted for an access type, and only on access-to-composite types. A constraint on an access-to-scalar or access-to-access type might be violated due to assignments via other access paths that were not so constrained. By contrast, if the designated subtype is an array or discriminated type@Chg{Version=[2],New=[ without defaults],Old=[]}, the constraint could not be violated by unconstrained assignments, since array objects are always constrained, and @Chg{Version=[2],New=[],Old=[aliased]} discriminated objects are also constrained @Chg{Version=[2],New=[when the type does not have defaults for its discriminants. Constraints are not allowed on general access-to-unconstrained discriminated types if the type has defaults for its discriminants; constraints on pool-specific access types are usually allowed because allocated objects are usually constrained by their initial value.], Old=[(by fiat, see @StaticSemTitle).]} @end(Reason) @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If a @nt{subtype_@!indication}, @nt{discriminant_@!specification}, @nt{parameter_@!specification}, @nt{parameter_@!and_@!result_@!profile}, @nt{object_@!renaming_@!declaration}, or @nt{formal_@!object_@!declaration} has a @nt{null_@!exclusion}, the @nt{subtype_@!mark} in that construct shall denote an access subtype that does not exclude null.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[This means @lquotes@;directly allowed in@rquotes; we are not talking about a @nt{null_exclusion} that occurs in an @nt{access_definition} in one of these constructs (for an @nt{access_definition}, the @nt{subtype_mark} in such an @nt{access_definition} is not restricted).]} @end(Honest) @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[This is similar to doubly constraining a composite subtype, which we also don't allow.]} @end(Reason) @end{Legality} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @PDefn2{Term=[compatibility], Sec=(composite_constraint with an access subtype)} A @nt<composite_constraint> is @i(compatible) with an unconstrained access subtype if it is compatible with the designated subtype.@Chg{Version=[2],New=[ A @nt{null_exclusion} is compatible with any access subtype that does not exclude null.],Old=[]} @PDefn2{Term=[satisfies], Sec=(for an access value)} An access value @i(satisfies) a @nt<composite_constraint> of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint.@Chg{Version=[2],New=[ An access value satisfies an exclusion of the null value if it does not equal the null value of its type.],Old=[]} @PDefn2{Term=[elaboration], Sec=(access_type_definition)} The elaboration of an @nt{access_type_definition} creates the access type and its first subtype. For an access-to-object type, this elaboration includes the elaboration of the @nt{subtype_indication}, which creates the designated subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00254-01]} @PDefn2{Term=[elaboration], Sec=(access_definition)} The elaboration of an @nt{access_definition} creates an anonymous@Chg{Version=[2],New=[],Old=[ general]} access@Chg{Version=[2], New=[],Old=[-to-variable]} type@Chg{Version=[2],New=[], Old=[ @Redundant[(this happens as part of the initialization of an access parameter or access discriminant)]]}. @end{RunTime} @begin{Notes} Access values are called @lquotes@;pointers@rquotes@; or @lquotes@;references@rquotes@; in some other languages. Each access-to-object type has an associated storage pool; several access types can share the same pool. An object can be created in the storage pool of an access type by an @nt{allocator} (see @RefSecNum{Allocators}) for the access type. A storage pool (roughly) corresponds to what some other languages call a @lquotes@;heap.@rquotes@; See @RefSecNum{Storage Management} for a discussion of pools. Only @nt<index_constraint>s and @nt<discriminant_constraint>s can be applied to access types (see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Discriminant Constraints}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of access-to-object types:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[type] Peripheral_Ref @key<is @Chg{Version=[2],New=[not null ],Old=[]}access> Peripheral; --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] @key[type] Binop_Ptr @key[is access all] Binary_Operation'Class; --@RI[ general access-to-class-wide, see @RefSecNum{Type Extensions}] @end{Example} @begin{Wide} @leading@keepnext@i{Example of an access subtype:} @end{Wide} @begin{Example} @key[subtype] Drum_Ref @key[is] Peripheral_Ref(Drum); --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] @end{Example} @begin{Wide} @leading@keepnext@i{Example of an access-to-subprogram type:} @end{Wide} @begin{Example} @key[type] Message_Procedure @key[is] @key[access] @key[procedure] (M : @key[in] String := "Error!"); @key[procedure] Default_Message_Procedure(M : @key[in] String); Give_Message : Message_Procedure := Default_Message_Procedure'Access; ... @key[procedure] Other_Procedure(M : @key[in] String); ... Give_Message := Other_Procedure'Access; ... Give_Message("File not found."); --@RI{ call with parameter (.@key[all] is optional)} Give_Message.@key[all]; --@RI{ call with no parameters} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for @nt{access_type_definition} is changed to support general access types (including access-to-constants) and access-to-subprograms. The syntax rules for @nt{general_access_modifier} and @nt{access_definition} are new. @end{Extend83} @begin{DiffWord83} We use the term "storage pool" to talk about the data area from which allocation takes place. The term "collection" is no longer used. ("Collection" and "storage pool" are not the same thing because multiple unrelated access types can share the same storage pool; see @RefSecNum(Storage Management) for more discussion.) @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Access discriminants and non-controlling access parameters no longer exclude null. A program which passed @key{null} to such an access discriminant or access parameter and expected it to raise Constraint_Error may fail @ChgNote{but not if the parameter is dereferenced in the subprogram or record }when compiled with Ada 2005. One hopes that there no such programs outside of the ACATS. (Of course, a program which actually wants to pass @key{null} will work, which is far more likely.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[Most unconstrained aliased objects with defaulted discriminants are no longer constrained by their initial values. This means that a program that raised Constraint_Error from an attempt to change the discriminants will no longer do so. The change only affects programs that depended on the raising of Constraint_Error in this case, so the inconsistency is unlikely to occur outside of the ACATS. This change may however cause compilers to implement these objects differently, possibly taking additional memory or time. This is unlikely to be worse than the differences caused by any major compiler upgrade.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00225-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] The rule defining when a current instance of a limited type is considered to be aliased has been tightened to apply only to types that cannot become nonlimited. A program that attempts to take 'Access of the current instance of a limited type that can become nonlimited will be illegal in Ada 2005. While original Ada 95 allowed the current instance of any limited type to be treated as aliased, this was inconsistently implemented in compilers, and was likely to not work as expected for types that are ultimately nonlimited.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @Chg{Version=[2],New=[@Defn{extensions to Ada 95}The @nt{null_exclusion} is new. It can be used in both anonymous and named access type definitions. It is most useful to declare that parameters cannot be @key{null}, thus eliminating the need for checks on use.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00404-01]} @Chg{Version=[2],New=[The kinds of anonymous access types allowed were increased by adding anonymous access-to-constant and anonymous access-to-subprogram types. Anonymous access-to-subprogram types used as parameters allow passing of subprograms at any level.],Old=[]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0012],ARef=[AI95-00062-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Added accidentally-omitted wording that says that a derived access type shares its storage pool with its parent type. This was clearly intended, both because of a note in @RefSecNum{Derived Types and Classes}, and because anything else would have been incompatible with Ada 83.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0013],ARef=[AI95-00012-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Fixed typographical errors in the description of when access types are constrained.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[The wording was fixed to allow @nt{allocator}s and the literal @key{null} for anonymous access types. The former was clearly intended by Ada 95; see the @ImplAdviceTitle in @RefSecNum{Storage Management}.], Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[The rules about aliased objects being constrained by their initial values now apply only to allocated objects, and thus have been moved to @RefSec{Allocators}.],Old=[]} @end{DiffWord95} @LabeledSubClause{Incomplete Type Declarations} @begin{Intro} There are no particular limitations on the designated type of an access type. In particular, the type of a component of the designated type can be another access type, or even the same access type. This permits mutually dependent and recursive access types. An @nt<incomplete_type_declaration> can be used to introduce a type to be used as a designated type, while deferring its full definition to a subsequent @nt<full_type_declaration>. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Syn{lhs=<incomplete_type_declaration>, rhs="@key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}]@Chg{Version=[2],New=< [@key{is tagged}]>,Old=<>};"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incomplete type}@Defn{incomplete view} An @nt{incomplete_type_declaration} declares an @i{incomplete view} of a type and its first subtype; the first subtype is unconstrained if a @nt<discriminant_part> appears. If the @nt{incomplete_@!type_@!declaration} includes the reserved word @key{tagged}, it declares a @i{tagged incomplete view}.@Defn2{Term=[incomplete view],Sec=[tagged]}@Defn{tagged incomplete view} An incomplete view of a type is a limited view of the type (see @RefSecNum{Limited Types}).]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Given an access type @i{A} whose designated type @i{T} is an incomplete view, a dereference of a value of type @i{A} also has this incomplete view except when:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[it occurs within the immediate scope of the completion of @i{T}, or],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it occurs within the scope of a @nt{nonlimited_with_clause} that mentions a library package in whose visible part the completion of @i{T} is declared.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[In these cases, the dereference has the full view of @i{T}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[We need the @lquotes@;in whose visible part@rquotes@; rule so that the second rule doesn't trigger in the body of a package with a @key{with} of a child unit:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{package} P @Key{is} @Key{private} @Key{type} T; @Key{type} PtrT @Key{is access} T; @Key{end} P;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{private package} P.C @Key{is} Ptr : PtrT; @Key{end} P.C;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{with} P.C; @Key{package body} P @Key{is} -- @RI{Ptr.all'Size is not legal here, but it is in the scope of a} -- @nt{nonlimited_with_clause} @RI{for P.} @Key{type} T @Key{is} ... -- @RI{Ptr.all'Size is legal here.} @Key{end} P;],Old=[]} @end{Example} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[Similarly, if a @nt{subtype_mark} denotes a @nt{subtype_declaration} defining a subtype of an incomplete view @i<T>, the @nt{subtype_mark} denotes an incomplete view except under the same two circumstances given above, in which case it denotes the full view of @i<T>.]} @end{StaticSem} @begin{Legality} @PDefn2{Term=[requires a completion], Sec=(@nt<incomplete_type_declaration>)} An @nt{incomplete_type_declaration} requires a completion, which shall be a @nt{full_@!type_@!declaration}. @Redundant[If the @nt{incomplete_@!type_@!declaration} occurs immediately within either the visible part of a @nt{package_@!specification} or a @nt<declarative_@!part>, then the @nt{full_@!type_@!declaration} shall occur later and immediately within this visible part or @nt<declarative_@!part>. If the @nt{incomplete_@!type_@!declaration} occurs immediately within the private part of a given @nt<package_@!specification>, then the @nt{full_@!type_@!declaration} shall occur later and immediately within either the private part itself, or the @nt{declarative_@!part} of the corresponding @nt{package_@!body}.] @begin{TheProof} This is implied by the next AARM-only rule, plus the rules in @RefSec{Completions of Declarations} which require a completion to appear later and immediately within the same declarative region. @end{TheProof} @begin{Honest} If the @nt{incomplete_type_declaration} occurs immediately within the visible part of a @nt{package_specification}, then the @nt{full_type_declaration} shall occur immediately within this visible part. @end{Honest} @begin(Honest) If the implementation supports it, an @nt{incomplete_type_declaration} can be completed by a @nt{pragma} Import. @end(Honest) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[If an @nt{incomplete_@!type_@!declaration} includes the reserved word @key{tagged}, then a @nt{full_@!type_@!declaration} that completes it shall declare a tagged type. ],Old=[]}If an @nt{incomplete_@!type_@!declaration} has a @nt{known_@!discriminant_@!part}, then a @nt{full_@!type_@!declaration} that completes it shall have a fully conforming (explicit) @nt{known_@!discriminant_@!part} (see @RefSecNum(Conformance Rules)). @Defn2{Term=[full conformance],Sec=(required)} @Redundant[If an @nt{incomplete_@!type_@!declaration} has no @nt<discriminant_part> (or an @nt<unknown_@!discriminant_@!part>), then a corresponding @nt{full_@!type_@!declaration} is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.] @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[A],Old=[The only allowed uses of a]} @nt{name} that denotes an @Chg{Version=[2],New=[incomplete view of a type may be used], Old=[@nt{incomplete_type_declaration} are]} as follows: @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[No need to say "prior to the end of the @nt{full_type_declaration}" since the name would not denote the @nt{incomplete_type_declaration} after the end of the @nt{full_type_declaration}. Also, with child library units, it would not be well defined whether they come before or after the @nt<full_type_declaration> for deferred incomplete types.]} @end(Discussion) @begin(itemize) as the @nt{subtype_mark} in the @nt{subtype_indication} of an @nt{access_to_@!object_@!definition}; @Redundant[the only form of @nt{constraint} allowed in this @nt{subtype_indication} is a @nt{discriminant_constraint};] @begin(ImplNote) We now allow @nt<discriminant_constraint>s even if the full type is deferred to the package body. However, there is no particular implementation burden because we have dropped the concept of the dependent compatibility check. In other words, we have effectively repealed AI83-00007. @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01],ARef=[AI95-00412-01]}@ChgNote{The old rule is moved} as the @nt{subtype_mark} @Chg{Version=[2],New=[in the @nt{subtype_indication} of a @nt{subtype_declaration}; the @nt{subtype_@!indication} shall not have a @nt{null_@!exclusion} or a @nt{constraint};],Old=[defining the subtype of a parameter or result of an @nt{access_to_@!subprogram_@!definition};]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00326-01]}@ChgNote{Really moved} @ChgDeleted{Version=[2],Text=[This allows, for example, a record to have a component designating a subprogram that takes that same record type as a parameter.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} as the @nt<subtype_mark> in an @nt<access_definition>@Chg{Version=[2],New=[.],Old=[;]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[If such a @nt{name} denotes a tagged incomplete view, it may also be used:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[as the @nt{subtype_mark} defining the subtype of a parameter in a @nt{formal_part};],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} as the @nt{prefix} of an @nt{attribute_reference} whose @nt{attribute_@!designator} is Class; such an @nt{attribute_@!reference} is @Chg{Version=[2],New=[],Old=[similarly ]}restricted to the uses allowed here; @Chg{Version=[2],New=[it denotes a tagged incomplete view], Old=[when used in this way, the corresponding @nt{full_type_@!declaration} shall declare a tagged type, and the @nt<attribute_@!reference> shall occur in the same library unit as the @nt<incomplete_@!type_@!declaration>]}. @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[This is to prevent children from imposing requirements on their ancestor library units for deferred incomplete types.]} @end{reason} @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If such a @nt{name} occurs within the declaration list containing the completion of the incomplete view, it may also be used:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]}@ChgNote{Really moved} @ChgAdded{Version=[2],Text=[as the @nt{subtype_mark} defining the subtype of a parameter or result of an @nt{access_to_@!subprogram_@!definition}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This allows, for example, a record to have a component designating a subprogram that takes that same record type as a parameter.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[If any of the above uses occurs as part of the declaration of a primitive subprogram of the incomplete view, and the declaration occurs immediately within the private part of a package, then the completion of the incomplete view shall also occur immediately within the private part; it shall not be deferred to the package body.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This fixes a hole in Ada 95 where a dispatching operation with an access parameter could be declared in a private part and a dispatching call on it could occur in a child even though there is no visibility on the full type, requiring access to the controlling tag without access to the representation of the type.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[No other uses of a @nt{name} that denotes an incomplete view of a type are allowed.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[A @nt{prefix} that denotes an object], Old=[A dereference (whether implicit or explicit @em see @RefSecNum(Names))]} shall not be of an incomplete @Chg{Version=[2],New=[view],Old=[type]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We used to disallow all dereferences of an incomplete type. Now we only disallow such dereferences when used as a @nt{prefix}. Dereferences used in other contexts do not pose a problem since normal type matching will preclude their use except when the full type is @lquotes@;nearby@rquotes@; as context (for example, as the expected type).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This also disallows @nt{prefix}es that are directly of an incomplete view. For instance, a parameter @i{P} can be declared of a tagged incomplete type, but we don't want to allow @i{P}'Size, @i{P}'Alignment, or the like, as representation values aren't known for an incomplete view.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We say @lquotes@;denotes an object@rquotes so that prefixes that directly name an incomplete view are not covered; the previous rules cover such cases, and we certainly don't want to ban Incomp'Class.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[@Defn{incomplete type} An @nt{incomplete_type_declaration} declares an incomplete type and its first subtype; the first subtype is unconstrained if a @nt<known_discriminant_part> appears.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If an @nt<unknown_discriminant_part> or no @nt{discriminant_part} appears, then the constrainedness of the first subtype doesn't matter for any other rules or semantics, so we don't bother defining it. The case with a @nt<known_discriminant_part> is the only case in which a constraint could later be given in a @nt{subtype_indication} naming the incomplete type.]} @end{Reason} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(incomplete_type_declaration)} The elaboration of an @nt{incomplete_type_declaration} has no effect. @begin(Reason) An incomplete type has no real existence, so it doesn't need to be "created" in the usual sense we do for other types. It is roughly equivalent to a "forward;" declaration in Pascal. Private types are different, because they have a different set of characteristics from their full type. @end(Reason) @end{RunTime} @begin{Notes} @PDefn{completion legality} Within a @nt<declarative_part>, an @nt<incomplete_type_declaration> and a corresponding @nt<full_type_declaration> cannot be separated by an intervening body. This is because a type has to be completely defined before it is frozen, and a body freezes all types declared prior to it in the same @nt<declarative_part> (see @RefSecNum{Freezing Rules}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a recursive type:) @begin(Example) @key(type) Cell; --@RI[ incomplete type declaration] @key(type) Link @key(is) @key(access) Cell; @key(type) Cell @key(is) @key(record) Value : Integer; Succ : Link; Pred : Link; @key(end) @key(record); Head : Link := @key(new) Cell'(0, @key(null), @key(null)); Next : Link := Head.Succ; @end(Example) @i(Examples of mutually dependent access types:) @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Person(<>); --@RI[ incomplete type declaration] @key(type) Car@Chg{Version=[2],New=[ @key{is tagged};],Old=[; ]} --@RI[ incomplete type declaration] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Person_Name @key(is) @key(access) Person; @key(type) Car_Name @key(is) @key(access) @key(all) Car@Chg{Version=[2],New=['Class],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Car @key(is)@Chg{Version=[2],New=[ @key(tagged)],Old=[]} @key(record) Number : Integer; Owner : Person_Name; @key(end) @key(record); @key(type) Person(Sex : Gender) @key(is) @key(record) Name : String(1 .. 20); Birth : Date; Age : Integer @key(range) 0 .. 130; Vehicle : Car_Name; @key(case) Sex @key(is) @key(when) M => Wife : Person_Name(Sex => F); @key(when) F => Husband : Person_Name(Sex => M); @key(end) @key(case); @key(end) @key(record); My_Car, Your_Car, Next_Car : Car_Name := @key[new] Car; --@RI[ see @RefSecNum{Allocators}] George : Person_Name := @key[new] Person(M); ... George.Vehicle := Your_Car; @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{full_type_declaration} that completes an @nt{incomplete_type_declaration} may have a @nt{known_discriminant_part} even if the @nt{incomplete_type_declaration} does not. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00013} A @nt<discriminant_constraint> may be applied to an incomplete type, even if @Chg{New=[],Old=[it ]}its completion is deferred to the package body, because there is no @lquotes@;dependent compatibility check@rquotes@; required any more. Of course, the constraint can be specified only if a @nt<known_discriminant_part> was given in the @nt<incomplete_type_declaration>. As mentioned in the previous paragraph, that is no longer required even when the full type has discriminants. @end{Extend83} @begin{DiffWord83} @Leading@;Dereferences producing incomplete types were not explicitly disallowed in RM83, though AI83-00039 indicated that it was not strictly necessary since troublesome cases would result in Constraint_Error at run time, since the access value would necessarily be null. However, this introduces an undesirable implementation burden, as illustrated by Example 4 of AI83-00039: @begin{example} @key[package] Pack @key[is] @key[type] Pri @key[is] @key[private]; @key[private] @key[type] Sep; @key[type] Pri @key[is] @key[access] Sep; X : Pri; @key[end] Pack; @key[package] @key[body] Pack @key[is] --@RI{ Could be separately compiled!} @key[type] Sep @key[is] ...; X := @key[new] Sep; @key[end] Pack; @key[pragma] Elaborate(Pack); @key[private] @key[package] Pack.Child @key[is] I : Integer := X.@key{all}'Size; --@RI{ Legal, by AI-00039.} @key[end] Pack.Child; @end{example} Generating code for the above example could be a serious implementation burden, since it would require all aliased objects to store size dope, and for that dope to be in the same format for all kinds of types (or some other equivalently inefficient implementation). On the contrary, most implementations allocate dope differently (or not at all) for different designated subtypes. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} It is now illegal to use an incomplete view (type) as the parameter or result of an access-to-subprogram type unless the incomplete view is completed in the same declaration list as the use. This was allowed in Ada 95 for incomplete types where the completion was deferred to the body. By disallowing this rare use of incomplete views, we can allow the use of incomplete views in many more places, which is especially valuable for limited views.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[It is now illegal to use an incomplete view (type) in a primitive subprogram of the type unless the incomplete view is completed in the package specification. This was allowed in Ada 95 for incomplete types where the completion was deferred to the body (the use would have to be in an access parameter). This incompatibility was caused by the fix for the hole noted in @LegalityTitle above.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Tagged incomplete types are new. They are allowed in parameter declarations as well as the usual places, as tagged types are always by-reference types (and thus there can be no code generation issue).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[A @nt{subtype_declaration} can be used to give a new name to an incomplete view of a type. This is valuable to give shorter names to entities imported with a @nt{limited_with_clause}.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[The description of incomplete types as @i{incomplete views} is new. Ada 95 defined these as separate types, but neglected to give any rules for matching them with other types. Luckily, implementers did the right thing anyway. This change also makes it easier to describe the meaning of a limited view.]} @end{DiffWord95} @LabeledSubClause{Operations of Access Types} @begin{Intro} @Redundant[The attribute Access is used to create access values designating aliased objects and non-intrinsic subprograms. The @lquotes@;accessibility@rquotes@; rules prevent dangling references (in the absence of uses of certain unchecked features @em see Section 13).] @end{Intro} @begin{MetaRules} It should be possible for an access value to designate an object declared by an object declaration, or a subcomponent thereof. In implementation terms, this means pointing at stack-allocated and statically allocated data structures. However, dangling references should be prevented, primarily via compile-time rules, so long as features like Unchecked_Access and Unchecked_Deallocation are not used. In order to create such access values, we require that the access type be a general access type, that the designated object be aliased, and that the accessibility rules be obeyed. @end{MetaRules} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235-01]} @PDefn2{Term=[expected type], Sec=(access attribute_reference)} For an @nt<attribute_reference> with @nt<attribute_designator> Access (or Unchecked_Access @em see @RefSecNum(Unchecked Access Value Creation)), the expected type shall be a single access type@Chg{Version=[2],New=[ @i<A> such that:],Old=[@Redundant[; the @nt<prefix> of such an @nt<attribute_reference> is never interpreted as an @nt<implicit_dereference>]. @PDefn2{Term=[expected profile], Sec=(Access @nt<attribute_reference> @nt<prefix>)} If the expected type is an access-to-subprogram type, then the expected profile of the @nt<prefix> is the designated profile of the access type.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@i{A} is an access-to-object type with designated type @i{D} and the type of the @nt{prefix} is @i{D}'Class or is covered by @i{D}, or],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@i{A} is an access-to-subprogram type whose designated profile is type conformant with that of the prefix.],Old=[]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@Redundant[The @nt{prefix} of such an @nt{attribute_reference} is never interpreted as an @nt{implicit_dereference} or a parameterless @nt{function_call} (see @RefSecNum{Attributes}).] @PDefn2{Term=[expected profile], Sec=(Access @nt<attribute_reference> @nt<prefix>)} @PDefn2{Term=[expected type], Sec=(Access @nt<attribute_reference> @nt<prefix>)} The designated type or profile of the expected type of the @nt{attribute_reference} is the expected type or profile for the @nt{prefix}.],Old=[]} @begin(Discussion) Saying that the expected type shall be a "single access type" is our "new" way of saying that the type has to be determinable from context using only the fact that it is an access type. See @RefSecNum{Literals} and @RefSecNum{The Context of Overload Resolution}. Specifying the expected profile only implies type conformance. The more stringent subtype conformance is required by a Legality Rule. This is the only Resolution Rule that applies to the @nt<name> in a @nt{prefix} of an @nt{attribute_reference}. In all other cases, the @nt{name} has to be resolved without using context. See @RefSecNum{Attributes}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Saying @lquotes@;single access type@rquotes@; is a bit of a fudge. Both the context and the @nt{prefix} may provide both multiple types; @lquotes@;single@rquotes@; only means that a single, specific interpretation must remain after resolution. We say @lquotes@;single@rquotes@; here to trigger the @LegalityTitle of @RefSecNum{The Context of Overload Resolution}. The resolution of an access attribute is similar to that of an @nt{assignment_statement}. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Int_Ptr @key{is access all} Integer; @key{type} Char_Ptr @key{is access all} Character; @key{type} Float_Ptr @key{is access all} Float;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{function} Zap (Val : Int_Ptr) @key{return} Float; -- @RI[(1)] @key{function} Zap (Val : Float_Ptr) @key{return} Float; -- @RI[(2)] @key{function} Zop @key{return} Int_Ptr; -- @RI[(3)] @key{function} Zop @key{return} Char_Ptr; -- @RI[(4)]],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[Result : Float := Zap (Zop.@key{all}'Access); -- @RI[Resolves to Zap (1) and Zop (3).]],Old=[]} @end{Example} @end(Discussion) @end{Resolution} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @Defn{accessibility level} @Defn2{Term=[level],Sec=(accessibility)} @Defn2{Term=[deeper],Sec=(accessibility level)} @Defn2{Term=[depth],Sec=(accessibility level)} @Defn2{Term=[dangling references],Sec=(prevention via accessibility rules)} @Defn{lifetime} @Redundant[The accessibility rules, which prevent dangling references, are written in terms of @i{accessibility levels}, which reflect the run-time nesting of @i{masters}. As explained in @RefSecNum{Completion and Finalization}, a master is the execution of a @Chg{Version=[2],New=[certain construct, such as],Old=[,@nt{task_body}, a @nt{block_statement},]} a @nt{subprogram_body}@Chg{Version=[2],New=[],Old=[, an @nt{entry_body}, or an @nt{accept_statement}]}. An accessibility level is @i{deeper than} another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules.] @Defn{statically deeper} @Defn2{Term=[deeper],Sec=(statically)} @Redundant[A given accessibility level is said to be @i{statically deeper} than another if the given level is known at compile time (as defined below) to be deeper than the other for all possible executions. In most cases, accessibility is enforced at compile time by @LegalityTitle. Run-time accessibility checks are also used, since the @LegalityTitle do not cover certain cases involving access parameters and generic packages.] @Leading@keepnext@;Each master, and each entity and view created by it, has an accessibility level: @begin{Itemize} The accessibility level of a given master is deeper than that of each dynamically enclosing master, and deeper than that of each master upon which the task executing the given master directly depends (see @RefSecNum{Task Dependence - Termination of Tasks}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} An entity or view @Chg{Version=[2],New=[defined],Old=[created]} by a declaration@Chg{Version=[2],New=[ and created as part of its elaboration],Old=[]} has the same accessibility level as the innermost @Chg{Version=[2],New=[],Old=[enclosing ]}master @Chg{Version=[2],New=[of the declaration ],Old=[]}except in the cases of renaming and derived access types described below. A parameter of a master has the same accessibility level as the master. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[This rule defines the @lquotes@;normal@rquotes accessibility of entities. In the absence of special rules below, we intend for this rule to apply.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[This rule defines the accessibility of all named access types, as well as the accessibility level of all anonymous access types other than those for access parameters and access discriminants. Special rules exist for the accessibility level of such anonymous types. Components, stand-alone objects, and function results whose (anonymous) type is defined by an @nt{access_definition} have accessibility levels corresponding to named access types defined at the same point.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Because accessibility level is determined by where the @nt{access_definition} is elaborated, for a type extension, the anonymous access types of components (other than access discriminants) inherited from the parent have the same accessibility as they did in the parent; those in the extension part have the accessibility determined by the scope where the type extension is declared. Similarly, the types of the non-discriminant access components of a derived untagged type have the same accessibility as they did in the parent.]} @end{Ramification} The accessibility level of a view of an object or subprogram defined by a @nt{renaming_declaration} is the same as that of the renamed view. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} The accessibility level of a view conversion@Chg{Version=[2],New=[, @nt{qualified_expression}, or parenthesized expression,],Old=[]} is the same as that of the operand. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[The],Old=[For a function whose result type is a return-by-reference type, the accessibility level of the result object is the same as that of the master that elaborated the function body. For any other function, the]} accessibility level of @Chg{Version=[2],New=[an @nt{aggregate} or ],Old=[]}the result @Chg{Version=[2],New=[of a function call @Redundant[(or equivalent use of an operator)] that is used (in its entirety) to directly initialize part of an ],Old=[]}object is that of the @Chg{Version=[2],New=[object being initialized. In other contexts, the accessibility level of an @nt{aggregate} or the result of a function call is that of the innermost master that evaluates the @nt{aggregate} or],Old=[execution of the called]} function@Chg{Version=[2],New=[ call],Old=[]}. @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The first sentence is talking about a static use of the entire return object - a slice that happens to be the entire return object doesn't count. On the other hand, this is intended to allow parentheses and @nt{qualified_expression}s.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the function is used as a @nt{prefix}, the second sentence applies. Similarly, an @nt{assignment_statement} is not an initialization of an object, so the second sentence applies.]} @ChgAdded{Version=[2],Text=[The @lquotes@;innermost master which evaluated the function call@rquotes@; does not include the function call itself (which might be a master).]} @ChgAdded{Version=[2],Text=[We really mean the innermost master here, which could be a very short lifetime. Consider a function call used as a parameter of a procedure call. In this case the innermost master which evaluated the function call is the procedure call.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Within a return statement, the accessibility level of the return object is that of the execution of the return statement. If the return statement completes normally by returning from the function, then prior to leaving the function, the accessibility level of the return object changes to be a level determined by the point of call, as does the level of any coextensions (see below) of the return object.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[We define the accessibility level of the return object during the return statement to be that of the return statement itself so that the object may be designated by objects local to the return statement, but not by objects outside the return statement. In addition, the intent is that the return object gets finalized if the return statement ends without actually returning (for example, due to propagating an exception, or a goto). For a normal return, of course, no finalization is done before returning.]} @end{Reason} The accessibility level of a derived access type is the same as that of its ultimate ancestor. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type defined by an @nt{access_definition} of an @nt{object_renaming_declaration} is the same as that of the renamed view.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgNote{Use ChgAdded below to get conditional Leading} @ChgAdded{Version=[2],Type=[Leading],Text=[]}The accessibility level of the anonymous access type of an access discriminant @Chg{Version=[2],New=[in the @nt{subtype_indication} or @nt{qualified_expression} of an @nt{allocator}, or in the @nt{expression} or @nt{return_@!subtype_@!indication} of a return statement is determined as follows:],Old=[is the same as that of the containing object or associated constrained subtype.]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If the value of the access discriminant is determined by a @nt{discriminant_association} in a @nt{subtype_indication}, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This deals with the following cases, when they occur in the context of an @nt{allocator} or return statement:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{extension_aggregate} where the @nt{ancestor_part} is a @nt{subtype_mark} denoting a constrained subtype;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An uninitialized @nt{allocator} where the @nt{subtype_indication} defines a constrained subtype;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A discriminant of an object with a constrained nominal subtype, including constrained components, the result of calling a function with a constrained result subtype, the dereference of an access-to-constrained subtype, etc.]} @end{InnerItemize} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If the value of the access discriminant is determined by a @nt{record_component_association} in an @nt{aggregate}, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this bullet, the @nt{aggregate} has to occur in the context of an @nt{allocator} or return statement, while the @nt{subtype_indication} of the previous bullet can occur anywhere (it doesn't have to be directly given in the @nt{allocator} or return statement).]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[In other cases, where the value of the access discriminant is determined by an object with an unconstrained nominal subtype, the accessibility level of the object.]} @end{InnerItemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[In other words, if you know the value of the discriminant for an @nt{allocator} or return statement from a discriminant constraint or an @nt{aggregate} component association, then that determines the accessibility level; if you don't know it, then it is based on the object itself.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access discriminant in any other context is that of the enclosing object.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00254-01]} The accessibility level of the anonymous access type of an access parameter@Chg{Version=[2],New=[ specifying an access-to-object type],Old=[]} is the same as that of the view designated by the actual.@Chg{Version=[2],New=[],Old=[ If the actual is an @nt{allocator}, this is the accessibility level of the execution of the called subprogram.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access parameter specifying an access-to-subprogram type is deeper than that of any master; all such anonymous access types have this same level.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{downward closure} @Defn2{Term=[closure],Sec=(downward)} These represent @lquotes@;downward closures@rquotes@; and thus require passing of static links or global display information (along with generic sharing information if the implementation does sharing) along with the address of the subprogram. We must prevent conversions of these to types with @lquotes@;normal@rquotes@; accessibility, as those typically don't include the extra information needed to make a call.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @ChgNote{Use ChgAdded below to get conditional Leading} @ChgAdded{Version=[2],Type=[Leading],Text=[]} The accessibility level of an object created by an @nt{allocator} is the same as that of the access type@Chg{Version=[2],New=[, except for an @nt{allocator} of an anonymous access type that defines the value of an access parameter or an access discriminant. For an @nt{allocator} defining the value of an access parameter, the accessibility level is that of the innermost master of the call. For one defining an access discriminant, the accessibility level is determined as follows:],Old=[.]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[for an @nt{allocator} used to define the constraint in a @nt{subtype_declaration}, the level of the @nt{subtype_declaration};]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[for an @nt{allocator} used to define the constraint in a @nt{component_definition}, the level of the enclosing type;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[for an @nt{allocator} used to define the discriminant of an object, the level of the object.]} @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=[coextension],Sec=(of an object)} In this last case, the allocated object is said to be a @i{coextension} of the object whose discriminant designates it, as well as of any object of which the discriminated object is itself a coextension or subcomponent. All coextensions of an object are finalized when the object is finalized (see @RefSecNum{Completion and Finalization}).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The rules of access discriminants are such that when the space for an object with a coextension is reclaimed, the space for the coextensions can be reclaimed. Hence, there is implementation advice (see 13.11) that an object and its coextensions all be allocated from the same storage pool (or stack frame, in the case of a declared object).]} @end{Ramification} The accessibility level of a view of an object or subprogram denoted by a dereference of an access value is the same as that of the access type. The accessibility level of a component, protected subprogram, or entry of (a view of) a composite object is the same as that of (the view of) the composite object. @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[In the above rules, the operand of a view conversion, parenthesized expression or @nt{qualified_expression} is considered to be used in a context if the view conversion, parenthesized expression or @nt{qualified_expression} itself is used in that context.]} @begin{Wide} @Leading@Defn{statically deeper} @Defn2{Term=[deeper],Sec=(statically)} One accessibility level is defined to be @i{statically deeper} than another in the following cases: @end{Wide} @begin{Itemize} For a master that is statically nested within another master, the accessibility level of the inner master is statically deeper than that of the outer master. @begin{Honest} Strictly speaking, this should talk about the @i{constructs} (such as @ntf{subprogram_bodies}) being statically nested within one another; the masters are really the @i{executions} of those constructs. @end{Honest} @begin{Honest} If a given accessibility level is statically deeper than another, then each level defined to be the same as the given level is statically deeper than each level defined to be the same as the other level. @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access parameter specifying an access-to-subprogram type is statically deeper than that of any master; all such anonymous access types have this same level.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule means that it is illegal to convert an access parameter specifying an access to subprogram to a named access to subprogram type, but it is allowed to pass such an access parameter to another access parameter (the implicit conversion's accessibility will succeed).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} The statically deeper relationship does not apply to the accessibility level of the anonymous type of an access parameter@Chg{Version=[2], New=[ specifying an access-to-object type],Old=[]}; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. For determining whether one level is statically deeper than another when within a generic package body, the generic package is presumed to be instantiated at the same level as where it was declared; run-time checks are needed in the case of more deeply nested instantiations. For determining whether one level is statically deeper than another when within the declarative region of a @nt{type_declaration}, the current instance of the type is presumed to be an object created at a deeper level than that of the type. @begin{Ramification} In other words, the rules are checked at compile time of the @nt{type_declaration}, in an assume-the-worst manner. @end{Ramification} @end{Itemize} @Defn{library level} @Defn2{Term=[level],Sec=(library)} The accessibility level of all library units is called the @i{library level}; a library-level declaration or entity is one whose accessibility level is the library level. @begin{Ramification} @nt{Library_unit_declaration}s are library level. Nested declarations are library level if they are nested only within packages (possibly more than one), and not within subprograms, tasks, etc. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised]} @Leading@;The definition of the accessibility level of the anonymous type of an access parameter@Chg{Version=[2],New=[ specifying an access-to-object type],Old=[]} cheats a bit, since it refers to the view designated by the actual, but access values designate objects, not views of objects. What we really mean is the view that @lquotes@;would be@rquotes@; denoted by an expression @lquotes@;X.@key[all]@rquotes@;, where X is the actual, even though such an expression is a figment of our imagination. The definition is intended to be equivalent to the following more verbose version: The accessibility level of the anonymous type of an access parameter is as follows: @begin{Itemize} if the actual is an expression of a named access type @em the accessibility level of that type; if the actual is an @nt{allocator} @em the accessibility level of the execution of the called subprogram; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} if the actual is a reference to the Access attribute @em the accessibility level of the view denoted by the @Chg{New=[@nt{prefix}],Old=[prefix]}; if the actual is a reference to the Unchecked_Access attribute @em library accessibility level; if the actual is an access parameter @em the accessibility level of its type. @end{Itemize} Note that the @nt{allocator} case is explicitly mentioned in the RM95, because otherwise the definition would be circular: the level of the anonymous type is that of the view designated by the actual, which is that of the access type. @end{Honest} @begin{Discussion} A deeper accessibility level implies a shorter maximum lifetime. Hence, when a rule requires X to have a level that is @lquotes@;not deeper than@rquotes@; Y's level, this requires that X has a lifetime at least as long as Y. (We say @lquotes@;maximum lifetime@rquotes@; here, because the accessibility level really represents an upper bound on the lifetime; an object created by an @nt{allocator} can have its lifetime prematurely ended by an instance of Unchecked_Deallocation.) Package elaborations are not masters, and are therefore invisible to the accessibility rules: an object declared immediately within a package has the same accessibility level as an object declared immediately within the declarative region containing the package. This is true even in the body of a package; it jibes with the fact that objects declared in a @nt{package_body} live as long as objects declared outside the package, even though the body objects are not visible outside the package. Note that the level of the @i{view} denoted by X.@key[all] can be different from the level of the @i{object} denoted by X.@key[all]. The former is determined by the type of X; the latter is determined either by the type of the @nt{allocator}, or by the master in which the object was declared. The former is used in several @LegalityTitle and run-time checks; the latter is used to define when X.@key[all] gets finalized. The level of a view reflects what we can conservatively @lquotes@;know@rquotes@; about the object of that view; for example, due to @nt{type_conversion}s, an access value might designate an object that was allocated by an @nt{allocator} for a different access type. Similarly, the level of the view denoted by X.@key[all].Comp can be different from the level of the object denoted by X.@key[all].Comp. If Y is statically deeper than X, this implies that Y will be (dynamically) deeper than X in all possible executions. @Leading@;Most accessibility checking is done at compile time; the rules are stated in terms of @lquotes@;statically deeper than@rquotes@;. The exceptions are: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised]} Checks involving access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}. The fact that @lquotes@;statically deeper than@rquotes@; is not defined for the anonymous access type of an access parameter implies that any rule saying @lquotes@;shall not be statically deeper than@rquotes@; does not apply to such a type, nor to anything defined to have @lquotes@;the same@rquotes@; level as such a type. Checks involving entities and views within generic packages. This is because an instantiation can be at a level that is more deeply nested than the generic package itself. In implementations that use a macro-expansion model of generics, these violations can be detected at macro-expansion time. For implementations that share generics, run-time code is needed to detect the error. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} Checks during function return@Chg{Version=[2],New=[ and @nt{allocator}s, for nested type extensions and access discriminants],Old=[]}. @end{Itemize} Note that run-time checks are not required for access discriminants, because their accessibility is determined statically by the accessibility level of the enclosing object. @ChgRef{Version=[2],Kind=[Revised]} @Chg{Version=[2],New=[],Old=[This ]}The accessibility level of the result object of a function reflects the time when that object will be finalized; we don't allow pointers to the object to survive beyond that time. We sometimes use the terms @lquotes@;accessible@rquotes@; and @lquotes@;inaccessible@rquotes@; to mean that something has an accessibility level that is not deeper, or deeper, respectively, than something else. @end{Discussion} @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} If an accessibility @LegalityName is satisfied, then the corresponding run-time check (if any) cannot fail (and a reasonable implementation will not generate any checking code) unless @Chg{Version=[2],New=[one of the cases requiring run-time checks mentioned previously is],Old=[access parameters or shared generic bodies are]} involved. Accessibility levels are defined in terms of the relations @lquotes@;the same as@rquotes@; and @lquotes@;deeper than@rquotes@;. To make the discussion more concrete, we can assign actual numbers to each level. Here, we assume that library-level accessibility is level 0, and each level defined as @lquotes@;deeper than@rquotes@; is one level deeper. Thus, a subprogram directly called from the environment task (such as the main subprogram) would be at level 1, and so on. @ChgRef{Version=[2],Kind=[Revised]} Accessibility is not enforced at compile time for access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}. The @lquotes@;obvious@rquotes@; implementation of the run-time checks would be inefficient, and would involve distributed overhead; therefore, an efficient method is given below. The @lquotes@;obvious@rquotes@; implementation would be to pass the level of the caller at each subprogram call, task creation, etc. This level would be incremented by 1 for each dynamically nested master. An Accessibility_Check would be implemented as a simple comparison @em checking that X is not deeper than Y would involve checking that X <= Y. A more efficient method is based on passing @i{static} nesting levels (within constructs that correspond at run time to masters @em packages don't count). Whenever an access parameter is passed, an implicit extra parameter is passed with it. The extra parameter represents (in an indirect way) the accessibility level of the anonymous access type, and, therefore, the level of the view denoted by a dereference of the access parameter. This is analogous to the implicit @lquotes@;Constrained@rquotes@; bit associated with certain formal parameters of an unconstrained but definite composite subtype. In this method, we avoid distributed overhead: it is not necessary to pass any extra information to subprograms that have no access parameters. For anything other than an access parameter and its anonymous type, the static nesting level is known at compile time, and is defined analogously to the RM95 definition of accessibility level (e.g. derived access types get their nesting level from their parent). Checking @lquotes@;not deeper than@rquotes@; is a "<=" test on the levels. @ChgRef{Version=[2],Kind=[Revised]} @Leading@keepnext@;For each access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, the static depth passed depends on the actual, as follows: @begin{Itemize} If the actual is an expression of a named access type, pass the static nesting level of that type. If the actual is an @nt{allocator}, pass the static nesting level of the caller, plus one. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} If the actual is a reference to the Access attribute, pass the level of the view denoted by the @Chg{New=[@nt{prefix}],Old=[prefix]}. If the actual is a reference to the Unchecked_Access attribute, pass 0 (the library accessibility level). @ChgRef{Version=[2],Kind=[Revised]} If the actual is an access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, usually just pass along the level passed in. However, if the static nesting level of the formal (access) parameter is greater than the static nesting level of the actual (access) parameter, the level to be passed is the minimum of the static nesting level of the access parameter and the actual level passed in. @end{Itemize} @ChgRef{Version=[2],Kind=[Revised]} For the Accessibility_Check associated with a @nt{type_conversion} of an access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]} of a given subprogram to a named access type, if the target type is statically nested within the subprogram, do nothing; the check can't fail in this case. Otherwise, check that the value passed in is <= the static nesting depth of the target type. The other Accessibility_Checks are handled in a similar manner. This method, using statically known values most of the time, is efficient, and, more importantly, avoids distributed overhead. @end(ImplNote) @begin{Discussion} @Leading@keepnext@;Examples of accessibility: @begin{Example} @key[package] @key[body] Lib_Unit @key[is] @key[type] T @key[is] @key[tagged] ...; @key[type] A0 @key[is] @key[access] @key[all] T; Global: A0 := ...; @key[procedure] P(X: T) @key[is] Y: @key[aliased] T; @key[type] A1 @key[is] @key[access] @key[all] T; Ptr0: A0 := Global; --@RI{ OK.} Ptr1: A1 := X'Access; --@RI{ OK.} @key[begin] Ptr1 := Y'Access; --@RI{ OK;} Ptr0 := A0(Ptr1); --@RI{ Illegal type conversion!} Ptr0 := X'Access; --@RI{ Illegal reference to Access attribute!} Ptr0 := Y'Access; --@RI{ Illegal reference to Access attribute!} Global := Ptr0; --@RI{ OK.} @key[end] P; @key[end] Lib_Unit; @end{Example} The above illegal statements are illegal because the accessibility level of X and Y are statically deeper than the accessibility level of A0. In every possible execution of any program including this library unit, if P is called, the accessibility level of X will be (dynamically) deeper than that of A0. Note that the accessibility levels of X and Y are the same. @ChgRef{Version=[2],Kind=[Revised]} @Leading@keepnext@;Here's an example involving access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}: @begin{Example} @key[procedure] Main @key[is] @key[type] Level_1_Type @key[is] @key[access] @key[all] Integer; @key[procedure] P(X: @key[access] Integer) @key[is] @key[type] Nested_Type @key[is] @key[access] @key[all] Integer; @key[begin] ... Nested_Type(X) ... --@RI{ (1)} ... Level_1_Type(X) ... --@RI{ (2)} @key[end] P; @key[procedure] Q(X: @key[access] Integer) @key[is] @key[procedure] Nested(X: @key[access] Integer) @key[is] @key[begin] P(X); @key[end] Nested; @key[begin] Nested(X); @key[end] Q; @key[procedure] R @key[is] Level_2: @key[aliased] Integer; @key[begin] Q(Level_2'Access); --@RI{ (3)} @key[end] R; Level_1: @key[aliased] Integer; @key[begin] Q(Level_1'Access); --@RI{ (4)} R; @key[end] Main; @end{Example} The run-time Accessibility_Check at (1) can never fail, and no code should be generated to check it. The check at (2) will fail when called from (3), but not when called from (4). @Leading@;Within a @nt{type_declaration}, the rules are checked in an assume-the-worst manner. For example: @begin{Example} @key[package] P @key[is] @key[type] Int_Ptr @key[is] @key[access] @key[all] Integer; @key[type] Rec(D: @key[access] Integer) @key[is] @key[limited] @key[private]; @key[private] @key[type] Rec_Ptr @key[is] @key[access] @key[all] Rec; @key[function] F(X: Rec_Ptr) @key[return] Boolean; @key[function] G(X: @key[access] Rec) @key[return] Boolean; @key[type] Rec(D: @key[access] Integer) @key[is] @key[record] C1: Int_Ptr := Int_Ptr(D); --@RI{ Illegal!} C2: Rec_Ptr := Rec'Access; --@RI{ Illegal!} C3: Boolean := F(Rec'Access); --@RI{ Illegal!} C4: Boolean := G(Rec'Access); @key[end] @key[record]; @key[end] P; @end{Example} C1, C2, and C3 are all illegal, because one might declare an object of type Rec at a more deeply nested place than the declaration of the type. C4 is legal, but the accessibility level of the object will be passed to function G, and constraint checks within G will prevent it from doing any evil deeds. Note that we cannot defer the checks on C1, C2, and C3 until compile-time of the object creation, because that would cause violation of the privacy of private parts. Furthermore, the problems might occur within a task or protected body, which the compiler can't see while compiling an object creation. @end{Discussion} @begin{Wide} @Leading@;The following attribute is defined for @PrefixType{a @nt{prefix} X that denotes an aliased view of an object}: @end{Wide} @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<X>, AttrName=<Access>, Ref=[8652/0010], ARef=[AI95-00127-01], Text=<X'Access yields an access value that designates the object denoted by X. The type of X'Access is an access-to-object type, as determined by the expected type. The expected type shall be a general access type.>} @IndexSeeAlso{Term=[Unchecked_Access attribute],See=(Access attribute)} @EndPrefixType{} X shall denote an aliased view of an object@Redundant[, including possibly the current instance (see @RefSecNum{The Context of Overload Resolution}) of a limited type within its definition, or a formal parameter or generic formal object of a tagged type]. The view denoted by the @nt<prefix> X shall satisfy the following additional requirements, presuming the expected type for X'Access is the general access type @i(A)@Chg{New=[ with designated type @i(D)],Old=[]}: @begin(itemize) If @i(A) is an access-to-variable type, then the view shall be a variable; @Redundant[on the other hand, if @i(A) is an access-to-constant type, the view may be either a constant or a variable.] @begin{Discussion} The current instance of a limited type is considered a variable. @end{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} The view shall not be a subcomponent that depends on discriminants of a variable whose nominal subtype is unconstrained, unless this subtype is indefinite, or the variable is @Chg{Version=[2],New=[constrained by its initial value], Old=[aliased]}. @begin(Discussion) @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} This restriction is intended to be similar to the restriction on renaming discriminant-dependent subcomponents. @end{Discussion} @begin{Reason} This prevents references to subcomponents that might disappear or move or change constraints after creating the reference. @end{Reason} @begin{ImplNote} @Leading@;There was some thought to making this restriction more stringent, roughly: "X shall not denote a subcomponent of a variable with discriminant-dependent subcomponents, if the nominal subtype of the variable is an unconstrained definite subtype." This was because in some implementations, it is not just the discriminant-dependent subcomponents that might move as the result of an assignment that changed the discriminants of the enclosing object. However, it was decided not to make this change because a reasonable implementation strategy was identified to avoid such problems, as follows: @begin(Itemize) Place non-discriminant-dependent components with any aliased parts at offsets preceding any discriminant-dependent components in a discriminated record type with defaulted discriminants. Preallocate the maximum space for unconstrained discriminated variables with aliased subcomponents, rather than allocating the initial size and moving them to a larger (heap-resident) place if they grow as the result of an assignment. @end(Itemize) Note that for objects of a by-reference type, it is not an error for a programmer to take advantage of the fact that such objects are passed by reference. Therefore, the above approach is also necessary for discriminated record types with components of a by-reference type. To make the above strategy work, it is important that a component of a derived type is defined to be discriminant-dependent if it is inherited and the parent subtype constraint is defined in terms of a discriminant of the derived type (see @RefSecNum(Discriminants)). @end{ImplNote} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If X is a subcomponent that depends on discriminants, and the subcomponent is a dereference of a general access type whose designated type is unconstrained and whose discriminants have defaults, the attribute is illegal. Such a general access type can designate an unconstrained (stack) object. Since such a type might not designate an object constrained by its initial value, the 'Access is illegal @em the rule says @lquotes@;is@rquotes constrained by its initial value, not @lquotes@;might be@rquotes constrained by its initial value. No other interpretation makes sense, as we can't have legality depending on something (which object is designated) that is not known at compile-time, and we surely can't allow this for unconstrained objects. The wording of the rule should be much clearer on this point, but this was discovered after the completion of Amendment 1 when it was too late to fix it.]} @end{Honest} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} If @Chg{New=[@i(A) is a named access type and @i(D) is a tagged type], Old=[the designated type of @i(A) is tagged]}, then the type of the view shall be covered by @Chg{New=[@i(D)],Old=[the designated type]}; @Chg{New=[if @i(A) is anonymous and @i(D) is tagged, then the type of the view shall be either @i(D)'Class or a type covered by @Chg{Version=[2],New=[@i<D>],Old=[D]};],Old=[]} if @Chg{New=[@i(D) is untagged],Old=[@i(A)'s designated type is not tagged]}, then the type of the view shall be @Chg{New=[@i(D)],Old=[the same]}, and @Chg{Version=[2],New=[either:],Old=[@Chg{New=[],Old=[either ]}@i(A)'s designated subtype shall @Chg{New=[either ],Old=[]} statically match the nominal subtype of the view@Chg{New=[ or be], Old=[, or the designated subtype shall be]} discriminated and unconstrained; @PDefn2{Term=[statically matching],Sec=(required)}]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[the designated subtype of @i{A} shall statically match the nominal subtype of the view; or@PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@i{D} shall be discriminated in its full view and unconstrained in any partial view, and the designated subtype of @i{A} shall be unconstrained.]} @end{InnerItemize} @begin{ImplNote} This ensures that the dope for an aliased array object can always be stored contiguous with it, but need not be if its nominal subtype is constrained. @end{implnote} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @Chg{New=[An access attribute can be used as the controlling operand in a dispatching call; see @RefSecNum{Dispatching Operations of Tagged Types}.], Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[This does not require that types have a partial view in order to allow an access attribute of an unconstrained discriminated object, only that any partial view that does exist is unconstrained.],Old=[]} @end{Ramification} The accessibility level of the view shall not be statically deeper than that of the access type @i{A}. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. @PDefn2{Term=[accessibility rule],Sec=(Access attribute)} @PDefn{generic contract issue} @begin(Ramification) In an instance body, a run-time check applies. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If @i(A) is an anonymous@Chg{Version=[2],New=[ access-to-object type of an access parameter],Old=[access type]}, then the view can never have a deeper accessibility level than @i(A)@Chg{Version=[2],New=[. The same is true for an anonymous access-to-object type of an access discriminant],Old=[]}, except when X'Access is used to initialize an access discriminant of an object created by an @nt<allocator>. The latter case is illegal if the accessibility level of X is statically deeper than that of the access type of the @nt<allocator>; a run-time check is needed in the case where the initial value comes from an access parameter.@Chg{Version=[2],New=[ Other anonymous access-to-object types have "normal" accessibility checks.],Old=[]} @end(Ramification) @end(itemize) @NoPrefix@IndexCheck{Accessibility_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} A check is made that the accessibility level of X is not deeper than that of the access type @i(A). If this check fails, Program_Error is raised. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised]} The check is needed for access parameters @Chg{Version=[2],New=[ of an access-to-object type],Old=[]} and in instance bodies. @end{Ramification} @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised]} This check requires that some indication of lifetime is passed as an implicit parameter along with access parameters@Chg{Version=[2], New=[ of an access-to-object type],Old=[]}. No such requirement applies to @Chg{Version=[2],New=[other anonymous access types],Old=[access discriminants]}, since the checks associated with them are all compile-time checks. @end(ImplNote) @NoPrefix@PDefn2{Term=[implicit subtype conversion],Sec=(Access attribute)} If the nominal subtype of X does not statically match the designated subtype of @i(A), a view conversion of X to the designated subtype is evaluated (which might raise Constraint_Error @em see @RefSecNum(Type Conversions)) and the value of X'Access designates that view. @end(description) The following attribute is defined for @PrefixType{a @nt{prefix} P that denotes a subprogram}: @begin(description) @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[F], Leading=[F], Prefix=<P>, AttrName=<Access>,ARef=[AI95-00229-01], ARef=[AI95-00254-01], Text=<P'Access yields an access value that designates the subprogram denoted by P. The type of P'Access is an access-to-subprogram type (@i(S)), as determined by the expected type.>} @EndPrefixType{} @PDefn2{Term=[accessibility rule],Sec=(Access attribute)} The accessibility level of P shall not be statically deeper than that of @i{S}. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. The profile of P shall be subtype-conformant with the designated profile of @i(S), and shall not be Intrinsic. @Defn2{Term=[subtype conformance],Sec=(required)} If the subprogram denoted by P is declared within a generic @Chg{Version=[2],New=[unit, and the expression P'Access occurs within the body of that generic unit or within the body of a generic unit declared within the declarative region of the generic unit, then the ultimate ancestor of @i{S} shall be either a non-formal type declared within the generic unit or an anonymous access type of an access parameter.], Old=[body, @i{S} shall be declared within the generic body.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00229-01]} The part about generic bodies is worded in terms of the denoted subprogram, not the denoted view; this implies that renaming is invisible to this part of the rule.@Chg{Version=[2],New=[ @lquotes@;Declared within the declarative region of the generic@rquotes@; is referring to child and nested generic units.],Old=[]}This rule is partly to prevent contract model problems with respect to the accessibility rules, and partly to ease shared-generic-body implementations, in which a subprogram declared in an instance needs to have a different calling convention from other subprograms with the same profile. Overload resolution ensures only that the profile is type-conformant. This rule specifies that subtype conformance is required (which also requires matching calling conventions). P cannot denote an entry because access-to-subprogram types never have the @i(entry) calling convention. P cannot denote an enumeration literal or an attribute function because these have intrinsic calling conventions. @end(Discussion) @end(description) @end{StaticSem} @begin{Notes} The Unchecked_Access attribute yields the same result as the Access attribute for objects, but has fewer restrictions (see @RefSecNum{Unchecked Access Value Creation}). There are other predefined operations that yield access values: an @nt<allocator> can be used to create an object, and return an access value that designates it (see @RefSecNum(Allocators)); evaluating the literal @key(null) yields a null access value that designates no entity at all (see @RefSecNum(Literals)). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @PDefn2{Term=[predefined operations],Sec=(of an access type)} The predefined operations of an access type also include the assignment operation, qualification, and membership tests. Explicit conversion is allowed between general access types with matching designated subtypes; explicit conversion is allowed between access-to-subprogram types with subtype conformant profiles (see @RefSecNum{Type Conversions}). @PDefn{subtype conformance} Named access types have predefined equality operators; anonymous access types do not@Chg{Version=[2],New=[, but they can use the predefined equality operators for @i<universal_access> ],Old=[]}(see @RefSecNum{Relational Operators and Membership Tests}). @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[Anonymous access types can use the universal access equality operators declared in Standard, while named access types cannot for compatibility reasons. ],Old=[]}By not having equality operators for anonymous access types, we eliminate the need to specify exactly where the predefined operators for anonymous access types would be defined, as well as the need for an implementer to insert an implicit declaration for "=", etc. at the appropriate place in their symbol table. Note that @Chg{Version=[2],New=[":=", ],Old=[]}'Access@Chg{Version=[2],New=[,],Old=[]} and ".@key[all]" are defined@Chg{Version=[2],New=[],Old=[, and ":=" is defined though useless since all instances are constant. The literal @key(null) is also defined for the purposes of overload resolution, but is disallowed by a @LegalityTitle of this subclause]}. @end(Reason) The object or subprogram designated by an access value can be named with a dereference, either an @nt<explicit_@!dereference> or an @nt<implicit_dereference>. See @RefSecNum{Names}. A call through the dereference of an access-to-subprogram value is never a dispatching call. @begin{TheProof} See @RefSecNum{Dispatching Operations of Tagged Types}. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} @Defn{downward closure} @Defn2{Term=[closure],Sec=(downward)} @Chg{Version=[2],New=[The],Old=[The accessibility rules imply that it is not possible to use the]} Access attribute@Chg{Version=[2],New=[ for subprograms and parameters of an anonymous access-to-subprogram type may together be used],Old=[]} to implement @lquotes@;downward closures@rquotes@; @em that is, to pass a more-nested subprogram as a parameter to a less-nested subprogram, as might be @Chg{Version=[2], New=[appropriate],Old=[desired for example]} for an iterator abstraction@Chg{Version=[2],New=[ or numerical integration. Downward],Old=[. Instead, downward]} closures can @Chg{Version=[2],New=[also ],Old=[]}be implemented using generic formal subprograms (see @RefSecNum{Formal Subprograms}). Note that Unchecked_Access is not allowed for subprograms. Note that using an access-to-class-wide tagged type with a dispatching operation is a potentially more structured alternative to using an access-to-subprogram type. An implementation may consider two access-to-subprogram values to be unequal, even though they designate the same subprogram. This might be because one points directly to the subprogram, while the other points to a special prologue that performs an Elaboration_Check and then jumps to the subprogram. See @RefSecNum(Relational Operators and Membership Tests). @begin{Ramification} If equality of access-to-subprogram values is important to the logic of a program, a reference to the Access attribute of a subprogram should be evaluated only once and stored in a global constant for subsequent use and equality comparison.@end{ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of use of the Access attribute:} @begin{Example} Martha : Person_Name := @key[new] Person(F); --@RI[ see @RefSecNum{Incomplete Type Declarations}] Cars : @key[array] (1..2) @key[of] @key[aliased] Car; ... Martha.Vehicle := Cars(1)'Access; George.Vehicle := Cars(2)'Access; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We no longer make things like 'Last and ".component" (basic) operations of an access type that need to be "declared" somewhere. Instead, implicit dereference in a @nt{prefix} takes care of them all. This means that there should never be a case when X.@key{all}'Last is legal while X'Last is not. See AI83-00154. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[@Leading@;@Defn{incompatibilities with Ada 95} Aliased variables are not necessarily constrained in Ada 2005 (see @RefSecNum{Array Types}). Therefore, a subcomponent of an aliased variable may disappear or change shape, and taking 'Access of such a subcomponent thus is illegal, while the same operation would have been legal in Ada 95. Note that most allocated objects are still constrained by their initial value (see @RefSecNum{Allocators}), and thus legality of 'Access didn't change for them. For example:],Old=[]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} T1 (D1 : Boolean := False) @key{is} @key{record} @key{case} D1 @key{is} @key{when} False => C1 : @key{aliased} Integer; @key{when} True => @key{null}; @key{end} @key{case}; @key{end} @key{record}; @key{type} Acc_Int @key{is access all} Integer;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[A_T : @key{aliased} T1; Ptr : Acc_Int := A_T.C1'Access; -- @RI[Illegal in Ada 2005, legal in Ada 95] A_T := (D1 => True); -- @RI[Raised Constraint_Error in Ada 95, but does not] -- @RI[in Ada 2005, so Ptr would become invalid when this] -- @RI[is assigned (thus Ptr is illegal).]],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[If a discriminated full type has a partial view (private type) that is constrained, we do not allow 'Access on objects to create a value of an object of an access-to-unconstrained type. Ada 95 allowed this attribute and various access subtypes, requiring that the heap object be constrained and thus making details of the implementation of the private type visible to the client of the private type. See @RefSecNum{Allocators} for more on this topic.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00229-01],ARef=[AI95-00254-01]} @Chg{Version=[2],New=[@b[Amendment Correction:] Taking 'Access of a subprogram declared in a generic unit in the body of that generic is no longer allowed. Such references can easily be used to create dangling pointers, as @LegalityTitle are not rechecked in instance bodies. At the same time, the rules were loosened a bit where that is harmless, and also to allow any routine to be passed to an access parameter of an access-to-subprogram type. The now illegal uses of 'Access can almost always be moved to the private part of the generic unit, where they are still legal (and rechecked upon instantiation for possibly dangling pointers).],Old=[]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @Chg{Version=[2],New=[@b<Corrigendum:> @Defn{extensions to Ada 95} Access attributes of objects of class-wide types can be used as the controlling parameter in a dispatching calls (see @RefSecNum{Dispatching Operations of Tagged Types}). This was an oversight in Ada 95.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] The type of the prefix can now be used in resolving Access attributes. This allows more uses of the Access attribute to resolve. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Int_Ptr @key{is access all} Integer; @key{type} Float_Ptr @key{is access all} Float;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{function} Zap (Val : Int_Ptr) @key{return} Float; @key{function} Zap (Val : Float_Ptr) @key{return} Float;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Value : @key{aliased} Integer := 10;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Result1 : Float := Zap (Value'access); -- @RI[Ambiguous in Ada 95; resolves in Ada 2005.] Result2 : Float := Zap (Int_Ptr'(Value'access)); -- @RI[Resolves in Ada 95 and Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This change is upward compatible; any expression that does not resolve by the new rules would have failed a Legality Rule.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00162-01]} @Chg{Version=[2],New=[Adjusted the wording to reflect the fact that expressions and function calls are masters.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00254-01],ARef=[AI95-00318-02],ARef=[AI95-00385-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[Defined the accessibility of the various new kinds and uses of anonymous access types.],Old=[]} @end{DiffWord95} @LabeledClause{Declarative Parts} @begin{Intro} @Redundant[A @nt<declarative_part> contains @nt<declarative_item>s (possibly none).] @end{Intro} @begin{Syntax} @Syn{lhs=<declarative_part>,rhs="{@Syn2{declarative_item}}"} @Syn{lhs=<declarative_item>,rhs=" @Syn2{basic_declarative_item} | @Syn2{body}"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<basic_declarative_item>,rhs=" @Syn2{basic_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]} | @Syn2{use_clause}"} @Syn{lhs=<body>,rhs="@Syn2{proper_body} | @Syn2{body_stub}"} @Syn{lhs=<proper_body>,rhs=" @Syn2{subprogram_body} | @Syn2{package_body} | @Syn2{task_body} | @Syn2{protected_body}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[The list of @nt{declarative_item}s of a @nt{declarative_part} is called the @i{declaration list} of the @nt{declarative_part}.@PDefn2{Term=[declaration list],Sec=[declarative_part]}]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(declarative_part)} The elaboration of a @nt{declarative_part} consists of the elaboration of the @nt{declarative_item}s, if any, in the order in which they are given in the @nt{declarative_part}. @Defn{elaborated} An elaborable construct is in the @i(elaborated) state after the normal completion of its elaboration. Prior to that, it is @i(not yet elaborated). @begin{Ramification} The elaborated state is only important for bodies; certain uses of a body raise an exception if the body is not yet elaborated. Note that "prior" implies before the start of elaboration, as well as during elaboration. The use of the term "normal completion" implies that if the elaboration propagates an exception or is aborted, the declaration is not elaborated. RM83 missed the aborted case. @end{Ramification} @IndexCheck{Elaboration_Check} For a construct that attempts to use a body, a check (Elaboration_Check) is performed, as follows: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014],ARef=[AI95-00064-01]} For a call to a (non-protected) subprogram that has an explicit body, a check is made that the @Chg{New=[body],Old=[@nt{subprogram_body}]} is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order. @begin{Discussion} AI83-00180 specifies that there is no elaboration check for a subprogram defined by a @nt{pragma} Interface (or equivalently, @nt{pragma} Import). AI83-00430 specifies that there is no elaboration check for an enumeration literal. AI83-00406 specifies that the evaluation of parameters and the elaboration check occur in an arbitrary order. AI83-00406 applies to generic instantiation as well (see below). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[1],Text=[A subprogram can be completed by a renaming-as-body, and we need to make an elaboration check on such a body, so we use @lquotes@;body@rquotes@; rather than @nt{subprogram_body} above.]} @end{Discussion} For a call to a protected operation of a protected type (that has a body @em no check is performed if a @nt{pragma} Import applies to the protected type), a check is made that the @nt<protected_body> is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order. @begin{Discussion} A protected type has only one elaboration @lquotes@;bit,@rquotes@; rather than one for each operation, because one call may result in evaluating the barriers of other entries, and because there are no elaborable declarations between the bodies of the operations. In fact, the elaboration of a @nt<protected_body> does not elaborate the enclosed bodies, since they are not considered independently elaborable. Note that there is no elaboration check when calling a task entry. Task entry calls are permitted even before the associated @nt<task_body> has been seen. Such calls are simply queued until the task is activated and reaches a corresponding @nt<accept_statement>. We considered a similar rule for protected entries @em simply queuing all calls until the @nt<protected_body> was seen, but felt it was not worth the possible implementation overhead, particularly given that there might be multiple instances of the protected type. @end{Discussion} For the activation of a task, a check is made by the activator that the @nt{task_body} is already elaborated. If two or more tasks are being activated together (see @RefSecNum{Task Execution - Task Activation}), as the result of the elaboration of a @nt{declarative_part} or the initialization for the object created by an allocator, this check is done for all of them before activating any of them. @begin{Reason} As specified by AI83-00149, the check is done by the activator, rather than by the task itself. If it were done by the task itself, it would be turned into a Tasking_Error in the activator, and the other tasks would still be activated. @end{Reason} For the instantiation of a generic unit that has a body, a check is made that this body is already elaborated. This check and the evaluation of any @nt{explicit_generic_actual_parameter}s of the instantiation are done in an arbitrary order. @end{Itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if any of these checks fails. @end{RunTime} @begin{Extend83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @Defn{extensions to Ada 83} The syntax for @nt{declarative_part} is modified to remove the ordering restrictions of Ada 83; that is, the distinction between @nt{basic_declarative_item}s and @ntf{later_declarative_item}s within @nt{declarative_part}s is removed. This means that things like @nt{use_clause}s and @Chg{Version=[2],New=[@nt{object_declaration}s],Old=[@ntf{variable_declaration}s]} can be freely intermixed with things like bodies. The syntax rule for @nt{proper_body} now allows a @nt{protected_body}, and the rules for elaboration checks now cover calls on protected operations. @end{Extend83} @begin{DiffWord83} The syntax rule for @ntf{later_declarative_item} is removed; the syntax rule for @nt{declarative_item} is new. RM83 defines @lquotes@;elaborated@rquotes@; and @lquotes@;not yet elaborated@rquotes@; for @nt{declarative_item}s here, and for other things in @RefSec{Declarations}. That's no longer necessary, since these terms are fully defined in @RefSecNum{Declarations}. In RM83, all uses of @nt{declarative_part} are optional (except for the one in @nt{block_statement} with a @key(declare)) which is sort of strange, since a @nt{declarative_part} can be empty, according to the syntax. That is, @nt{declarative_part}s are sort of @lquotes@;doubly optional@rquotes@;. In Ada 95, these @nt{declarative_part}s are always required (but can still be empty). To simplify description, we go further and say (see @RefSec(Block Statements)) that a @nt<block_statement> without an explicit @nt<declarative_part> is equivalent to one with an empty one. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the elaboration check applies to all kinds of subprogram bodies.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[Defined @lquotes@;declaration list@rquotes to avoid confusion for various rules. Other kinds of declaration list are defined elsewhere.]} @end{DiffWord95} @LabeledSubClause{Completions of Declarations} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014],ARef=[AI95-00064-01]} Declarations sometimes come in two parts. @Defn{requires a completion} A declaration that requires a second part is said to @i(require completion). @Defn2{Term=[completion], Sec=(compile-time concept)} The second part is called the @i(completion) of the declaration (and of the entity declared), and is either another declaration, a body, or a @nt<pragma>. @Chg{New=[A @defn<body>@i<body> is a @nt<body>, an @nt<entry_body>, or a renaming-as-body (see @RefSecNum<Subprogram Renaming Declarations>).],Old=[]} @begin{Discussion} @Leading@keepnext@;Throughout the RM95, there are rules about completions that define the following: @begin{Itemize} Which declarations require a corresponding completion. Which constructs can only serve as the completion of a declaration. Where the completion of a declaration is allowed to be. What kinds of completions are allowed to correspond to each kind of declaration that allows one. @end{Itemize} Don't confuse this compile-time concept with the run-time concept of completion defined in @RefSecNum{Completion and Finalization}. Note that the declaration of a private type (if limited) can be completed with the declaration of a task type, which is then completed with a body. Thus, a declaration can actually come in @i{three} parts. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[In Ada 2005 the limited view of the package contains an incomplete view of the private type, so we can have @i{four} parts now.],Old=[]} @end{Discussion} @end{Intro} @begin{Resolution} @Leading@keepnext@;A construct that can be a completion is interpreted as the completion of a prior declaration only if: @begin(itemize) The declaration and the completion occur immediately within the same declarative region; The defining name or @nt{defining_program_unit_name} in the completion is the same as in the declaration, or in the case of a @nt{pragma}, the @nt{pragma} applies to the declaration; If the declaration is overloadable, then the completion either has a type-conformant profile, or is a @nt{pragma}. @Defn2{Term=[type conformance],Sec=(required)} @end(itemize) @end{Resolution} @begin{Legality} An implicit declaration shall not have a completion. @RootDefn{requires a completion} For any explicit declaration that is specified to @i(require completion), there shall be a corresponding explicit completion. @begin(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[The implicit declarations occurring in a limited view do have a completion (the explicit declaration occurring in the full view) but that's a special case, since the implicit declarations are actually built from the explicit ones. So they do not @i{require} a completion, they have one by @i{fiat}.],Old=[]} @end{Honest} @begin(Discussion) The implicit declarations of predefined operators are not allowed to have a completion. Enumeration literals, although they are subprograms, are not allowed to have a corresponding @nt{subprogram_body}. That's because the completion rules are described in terms of constructs (@nt{subprogram_declaration}s) and not entities (subprograms). When a completion is required, it has to be explicit; the implicit null @nt{package_body} that Section 7 talks about cannot serve as the completion of a @nt{package_declaration} if a completion is required. @end(Discussion) At most one completion is allowed for a given declaration. Additional requirements on completions appear where each kind of completion is defined. @begin{Ramification} A subunit is not a completion; the stub is. If the completion of a declaration is also a declaration, then @i{that} declaration might have a completion, too. For example, a limited private type can be completed with a task type, which can then be completed with a task body. This is not a violation of the @lquotes@;at most one completion@rquotes@; rule. @end{Ramification} @Defn{completely defined} A type is @i(completely defined) at a place that is after its full type definition (if it has one) and after all of its subcomponent types are completely defined. A type shall be completely defined before it is frozen (see @RefSecNum{Freezing Rules} and @RefSecNum{Private Types and Private Extensions}). @begin(Reason) @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} Index types are always completely defined @em no need to mention them. There is no way for a completely defined type to depend on the value of a (still) deferred constant. @end(Reason) @end{Legality} @begin{Notes} Completions are in principle allowed for any kind of explicit declaration. However, for some kinds of declaration, the only allowed completion is a @nt{pragma} Import, and implementations are not required to support @nt{pragma} Import for every kind of entity. @begin(Discussion) In fact, we expect that implementations will @i{not} support pragma Import of things like types @em it's hard to even define the semantics of what it would mean. Therefore, in practice, @i{not} every explicit declaration can have a completion. In any case, if an implementation chooses to support pragma Import for, say, types, it can place whatever restrictions on the feature it wants to. For example, it might want the @nt{pragma} to be a freezing point for the type. @end(Discussion) There are rules that prevent premature uses of declarations that have a corresponding completion. The Elaboration_Checks of @RefSecNum{Declarative Parts} prevent such uses at run time for subprograms, protected operations, tasks, and generic units. The rules of @RefSec{Freezing Rules} prevent, at compile time, premature uses of other entities such as private types and deferred constants. @end{Notes} @begin{DiffWord83} This subclause is new. It is intended to cover all kinds of completions of declarations, be they a body for a spec, a full type for an incomplete or private type, a full constant declaration for a deferred constant declaration, or a @nt{pragma} Import for any kind of entity. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added a definition of @i{body}, which is different than @nt{body} or @key{body}.]} @end{DiffWord95} ��������������������������������������������������������������org.adaic.arm_form/source_2005/04a.mss��������������������������������������������������������������0000755�0001752�0001001�00000515440�12273462240�016542� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(04, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:24 $} @LabeledSection{Names and Expressions} @Comment{$Source: e:\\cvsroot/ARM/Source/04a.mss,v $} @Comment{$Revision: 1.83 $} @begin{Intro} @Redundant[The rules applicable to the different forms of @nt<name> and expression, and to their evaluation, are given in this section.] @end{Intro} @LabeledClause{Names} @begin{Intro} @redundant[@nt<Name>s can denote declared entities, whether declared explicitly or implicitly (see @RefSecNum(Declarations)). @nt<Name>s can also denote objects or subprograms designated by access values; the results of @nt<type_conversion>s or @nt<function_call>s; subcomponents and slices of objects and values; protected subprograms, single entries, entry families, and entries in families of entries. Finally, @nt<name>s can denote attributes of any of the foregoing.] @end{Intro} @begin{Syntax} @Syn{tabs=[P22], lhs=<name>,rhs=" @Syn2{direct_name}@\| @Syn2{explicit_dereference} | @Syn2{indexed_component}@\| @Syn2{slice} | @Syn2{selected_component}@\| @Syn2{attribute_reference} | @Syn2{type_conversion}@\| @Syn2{function_call} | @Syn2{character_literal}"} @Syn{lhs=<direct_name>, rhs="@Syn2{identifier} | @Syn2{operator_symbol}"} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @nt<character_literal> is no longer a @nt<direct_name>. @nt<character_literal>s are usable even when the corresponding @Chg{Version=[2],New=[enumeration type declaration],Old=[@ntf<enumeration_type_declaration>]} is not visible. See @RefSecNum(Literals). @end{Discussion} @Syn{lhs=<prefix>,rhs="@Syn2{name} | @Syn2{implicit_dereference}"} @Syn{lhs=<explicit_dereference>,rhs="@Syn2{name}.@key{all}"} @Syn{lhs=<implicit_dereference>,rhs="@Syn2{name}"} @end{Syntax} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised]} @Redundant[Certain forms of @nt<name> (@nt<indexed_component>s, @nt<selected_component>s, @nt<slice>s, and @Chg{Version=[2],New=[@nt<attribute_reference>s],Old=[@ntf<attribute>s]}) include a @nt<prefix> that is either itself a @nt<name> that denotes some related entity, or an @nt<implicit_dereference> of an access value that designates some related entity.] @end{Intro} @begin{Resolution} @Defn{dereference} @PDefn2{Term=[expected type], Sec=(dereference @nt{name})} The @nt{name} in a @i(dereference) (either an @nt<implicit_dereference> or an @nt<explicit_dereference>) is expected to be of any access type. @end{Resolution} @begin{StaticSem} @PDefn2{Term=[nominal subtype], Sec=(associated with a dereference)} If the type of the @nt{name} in a dereference is some access-to-object type @i(T), then the dereference denotes a view of an object, the @i(nominal subtype) of the view being the designated subtype of @i(T). @begin{Ramification} If the value of the @nt<name> is the result of an access type conversion, the dereference denotes a view created as part of the conversion. The nominal subtype of the view is not necessarily the same as that used to create the designated object. See @RefSecNum{Type Conversions}. @end{Ramification} @begin{Honest} @PDefn2{Term=[nominal subtype], Sec=(of a @nt<name>)} We sometimes refer to the nominal subtype of a particular kind of @nt<name> rather than the nominal subtype of the view denoted by the @nt<name> (presuming the @nt<name> denotes a view of an object). These two uses of nominal subtype are intended to mean the same thing. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If an @nt{allocator} for the access-to-object type @i(T) is one that creates objects that are constrained by their initial value (see @RefSecNum{Allocators}), the subtype of the dereference is constrained even if the designated subtype of @i(T) is not. We don't want the effect of the dereference to depend on the designated object. This matters because general access-to-unconstrained can designate both allocated objects (which are constrained at birth) and aliased stack objects (which aren't necessarily constrained). This is a wording bug that was discovered after the completion of Amendment 1 when it was too late to fix it; we expect that it will be corrected by an early Ada 2005 AI.]} @end{Honest} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[Since we don't depend on whether the designated object is constrained, it is not necessary to include a constrained bit in every object that could be designated by a general access type.]} @end{ImplNote} @PDefn2{Term=[profile], Sec=(associated with a dereference)} If the type of the @nt<name> in a dereference is some access-to-subprogram type @i(S), then the dereference denotes a view of a subprogram, the @i(profile) of the view being the designated profile of @i(S). @begin{Ramification} This means that the formal parameter names and default expressions to be used in a call whose @nt<name> or @nt<prefix> is a dereference are those of the designated profile, which need not be the same as those of the subprogram designated by the access value, since 'Access requires only subtype conformance, not full conformance. @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @PDefn2{Term=[evaluation], Sec=(name)} The evaluation of a @nt<name> determines the entity denoted by the @Chg{Version=[2],New=[@nt<name>],Old=[name]}. This evaluation has no other effect for a @nt<name> that is a @nt<direct_name> or a @nt<character_literal>. @PDefn2{Term=[evaluation], Sec=(name that has a prefix)} @Redundant[The evaluation of a @nt<name> that has a @nt<prefix> includes the evaluation of the @nt<prefix>.] @PDefn2{Term=[evaluation], Sec=(prefix)} The evaluation of a @nt{prefix} consists of the evaluation of the @nt{name} or the @nt{implicit_dereference}. The @nt{prefix} denotes the entity denoted by the @nt{name} or the @nt{implicit_dereference}. @PDefn2{Term=[evaluation], Sec=(dereference)} The evaluation of a dereference consists of the evaluation of the @nt{name} and the determination of the object or subprogram that is designated by the value of the @nt{name}. @IndexCheck{Access_Check} A check is made that the value of the @nt{name} is not the null access value. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. The dereference denotes the object or subprogram designated by the value of the @nt{name}. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of direct names:) @begin(Example) @tabclear()@tabset(P9, P47) Pi @\@RI(-- the direct name of a number) @\(see @RefSecNum(Number Declarations)) Limit @\@RI(-- the direct name of a constant) @\(see @RefSecNum(Object Declarations)) Count @\@RI(-- the direct name of a scalar variable) @\(see @RefSecNum(Object Declarations)) Board @\@RI(-- the direct name of an array variable) @\(see @RefSecNum(Index Constraints and Discrete Ranges)) Matrix @\@RI(-- the direct name of a type) @\(see @RefSecNum(Array Types)) Random @\@RI(-- the direct name of a function) @\(see @RefSecNum(Subprogram Declarations)) Error @\@RI(-- the direct name of an exception) @\(see @RefSecNum(Exception Declarations)) @end(Example) @begin{Wide} @leading@keepnext@i{Examples of dereferences:} @end{Wide} @begin{Example}@tabclear()@tabset(P19) Next_Car.@key[all]@\--@RI[ explicit dereference denoting the object designated by] @\--@RI[ the access variable Next_Car (see @RefSecNum{Incomplete Type Declarations})] Next_Car.Owner @\--@RI[ selected component with implicit dereference;] @\--@RI[ same as Next_Car.@key[all].Owner] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Type conversions and function calls are now considered names that denote the result of the operation. In the case of a type conversion used as an actual parameter or that is of a tagged type, the type conversion is considered a variable if the operand is a variable. This simplifies the description of "parameters of the form of a type conversion" as well as better supporting an important OOP paradigm that requires the combination of a conversion from a class-wide type to some specific type followed immediately by component selection. Function calls are considered names so that a type conversion of a function call and the function call itself are treated equivalently in the grammar. A function call is considered the name of a constant, and can be used anywhere such a name is permitted. See @RefSecNum(Return Statements). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} Type conversions of a tagged type are permitted anywhere their operand is permitted. That is, if the operand is a variable, then the type conversion can appear on the left-hand side of an @nt{assignment_statement}. If the operand is an object, then the type conversion can appear in an object renaming or as a @Chg{New=[@nt{prefix}],Old=[prefix]}. See @RefSecNum(Type Conversions). @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Everything of the general syntactic form @nt{name}(...) is now syntactically a @nt{name}. In any realistic parser, this would be a necessity since distinguishing among the various @nt{name}(...) constructs inevitably requires name resolution. In cases where the construct yields a value rather than an object, the name denotes @Chg{Version=[2],New=[a],Old=[the]} value rather than an object. Names already denote values in Ada 83 with named numbers, components of the result of a function call, etc. This is partly just a wording change, and partly an extension of functionality (see Extensions heading above). The syntax rule for @nt{direct_name} is new. It is used in places where direct visibility is required. It's kind of like Ada 83's @ntf{simple_name}, but @ntf{simple_name} applied to both direct visibility and visibility by selection, and furthermore, it didn't work right for @nt{operator_symbol}s. The syntax rule for @ntf{simple_name} is removed, since its use is covered by a combination of @nt{direct_name} and @nt{selector_name}. The syntactic categories @nt{direct_name} and @nt{selector_name} are similar; it's mainly the visibility rules that distinguish the two. The introduction of @nt{direct_name} requires the insertion of one new explicit textual rule: to forbid @nt<statement_identifier>s from being @nt<operator_symbol>s. This is the only case where the explicit rule is needed, because this is the only case where the declaration of the entity is implicit. For example, there is no need to syntactically forbid (say) @lquotes@;X: "Rem";@rquotes@;, because it is impossible to declare a type whose name is an @nt{operator_symbol} in the first place. The syntax rules for @nt{explicit_dereference} and @nt{implicit_dereference} are new; this makes other rules simpler, since dereferencing an access value has substantially different semantics from @nt{selected_component}s. We also use @nt{name} instead of @nt{prefix} in the @nt{explicit_dereference} rule since that seems clearer. Note that these rules rely on the fact that function calls are now names, so we don't need to use prefix to allow functions calls in front of .@key{all}. @begin{Discussion} Actually, it would be reasonable to allow any @nt{primary} in front of .@key{all}, since only the value is needed, but that would be a bit radical. @end{Discussion} We no longer use the term @i(appropriate for a type) since we now describe the semantics of a prefix in terms of implicit dereference. @end{DiffWord83} @LabeledSubClause{Indexed Components} @begin{Intro} @Redundant[An @nt<indexed_component> denotes either a component of an array or an entry in a family of entries. @IndexSee{Term=[array indexing],See=(indexed_component)}] @end{Intro} @begin{Syntax} @Syn{lhs=<indexed_component>,rhs="@Syn2{prefix}(@Syn2{expression} {, @Syn2{expression}})"} @end{Syntax} @begin{Resolution} The @nt{prefix} of an @nt{indexed_component} with a given number of @nt<expression>s shall resolve to denote an array (after any implicit dereference) with the corresponding number of index positions, or shall resolve to denote an entry family of a task or protected object (in which case there shall be only one @nt<expression>). @PDefn2{Term=[expected type], Sec=(indexed_component expression)} The expected type for each @nt{expression} is the corresponding index type. @end{Resolution} @begin{StaticSem} When the @nt<prefix> denotes an array, the @nt<indexed_component> denotes the component of the array with the specified index value(s). @PDefn2{Term=[nominal subtype], Sec=(associated with an @nt<indexed_component>)} The nominal subtype of the @nt<indexed_component> is the component subtype of the array type. @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In the case of an array whose components are aliased, and of an unconstrained discriminated subtype, the components are constrained even though their nominal subtype is unconstrained. (This is because all aliased discriminated objects are constrained. See @RefSecNum(Operations of Access Types).) In all other cases, an array component is constrained if and only if its nominal subtype is constrained.]} @end{Ramification} When the @nt<prefix> denotes an entry family, the @nt<indexed_component> denotes the individual entry of the entry family with the specified index value. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(indexed_component)} For the evaluation of an @nt<indexed_component>, the @nt{prefix} and the @nt{expression}s are evaluated in an arbitrary order. The value of each @nt<expression> is converted to the corresponding index type. @PDefn2{Term=[implicit subtype conversion],Sec=(array index)} @IndexCheck{Index_Check} A check is made that each index value belongs to the corresponding index range of the array or entry family denoted by the @nt<prefix>. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of indexed components:) @begin{Example} @tabclear()@tabset(P64) My_Schedule(Sat) --@RI[ a component of a one-dimensional array @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Page(10) --@RI[ a component of a one-dimensional array @\(see @RefSecNum{Array Types})] Board(M, J + 1) --@RI[ a component of a two-dimensional array @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Page(10)(20) --@RI[ a component of a component @\(see @RefSecNum{Array Types})] Request(Medium) --@RI[ an entry in a family of entries @\(see @RefSecNum{Task Units and Task Objects})] Next_Frame(L)(M, N) --@RI[ a component of a function call @\(see @RefSecNum{Subprogram Declarations})] @end{Example} @end{Examples} @begin{Notes} @i(Notes on the examples:) Distinct notations are used for components of multidimensional arrays (such as Board) and arrays of arrays (such as Page). The components of an array of arrays are arrays and can therefore be indexed. Thus Page(10)(20) denotes the 20th component of Page(10). In the last example Next_Frame(L) is a function call returning an access value that designates a two-dimensional array. @end{Notes} @LabeledSubClause{Slices} @begin{Intro} @redundant[@Defn{array slice} A @nt<slice> denotes a one-dimensional array formed by a sequence of consecutive components of a one-dimensional array. A @nt<slice> of a variable is a variable; a @nt<slice> of a constant is a constant;] a @nt<slice> of a value is a value. @end{Intro} @begin{Syntax} @Syn{lhs=<slice>,rhs="@Syn2{prefix}(@Syn2{discrete_range})"} @end{Syntax} @begin{Resolution} The @nt{prefix} of a @nt{slice} shall resolve to denote a one-dimensional array (after any implicit dereference). @PDefn2{Term=[expected type], Sec=(slice discrete_range)} The expected type for the @nt{discrete_range} of a @nt<slice> is the index type of the array type. @end{Resolution} @begin{StaticSem} A @nt<slice> denotes a one-dimensional array formed by the sequence of consecutive components of the array denoted by the @nt<prefix>, corresponding to the range of values of the index given by the @nt<discrete_range>. The type of the @nt<slice> is that of the @nt<prefix>. Its bounds are those defined by the @nt{discrete_range}. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(slice)} For the evaluation of a @nt{slice}, the @nt{prefix} and the @nt{discrete_range} are evaluated in an arbitrary order. @IndexCheck{Index_Check} @Defn{null slice} If the @nt{slice} is not a @i(null slice) (a @nt<slice> where the @nt<discrete_range> is a null range), then a check is made that the bounds of the @nt{discrete_range} belong to the index range of the array denoted by the @nt{prefix}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{RunTime} @begin{Notes} A @nt<slice> is not permitted as the @nt<prefix> of an Access @nt<attribute_reference>, even if the components or the array as a whole are aliased. See @RefSecNum(Operations of Access Types). @begin{TheProof} Slices are not aliased, by @RefSec{Access Types}. @end{TheProof} @begin(Reason) This is to ease implementation of general-access-to-array. If slices were aliased, implementations would need to store array dope with the access values, which is not always desirable given access-to-incomplete types completed in a package body. @end(Reason) For a one-dimensional array A, the @nt<slice> A(N .. N) denotes an array that has only one component; its type is the type of A. On the other hand, A(N) denotes a component of the array A and has the corresponding component type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of slices:) @begin{Example} @tabclear()@tabset(P58) Stars(1 .. 15) --@RI[ a slice of 15 characters @\(see @RefSecNum{String Types})] Page(10 .. 10 + Size) --@RI[ a slice of 1 + Size components @\(see @RefSecNum{Array Types})] Page(L)(A .. B) --@RI[ a slice of the array Page(L) @\(see @RefSecNum{Array Types})] Stars(1 .. 0) --@RI[ a null slice @\(see @RefSecNum{String Types})] My_Schedule(Weekday) --@RI[ bounds given by subtype @\(see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Enumeration Types})] Stars(5 .. 15)(K) --@RI[ same as Stars(K) @\(see @RefSecNum{String Types})] --@RI[ provided that K is in 5 .. 15] @end{Example} @end{Examples} @LabeledSubClause{Selected Components} @begin{Intro} @redundant[@nt{Selected_component}s are used to denote components (including discriminants), entries, entry families, and protected subprograms; they are also used as expanded names as described below. @IndexSee{Term=[dot selection],See=(selected_component)}] @end{Intro} @begin{Syntax} @Syn{lhs=<selected_component>,rhs="@Syn2{prefix} . @Syn2{selector_name}"} @Syn{lhs=<selector_name>,rhs="@Syn2{identifier} | @Syn2{character_literal} | @Syn2{operator_symbol}"} @end{Syntax} @begin{Resolution} @Defn{expanded name} A @nt<selected_component> is called an @i(expanded name) if, according to the visibility rules, at least one possible interpretation of its @nt<prefix> denotes a package or an enclosing named construct (directly, not through a @nt<subprogram_renaming_declaration> or @nt<generic_renaming_declaration>). @begin{Discussion} See AI83-00187. @end{Discussion} @Leading@;A @nt{selected_component} that is not an expanded name shall resolve to denote one of the following: @begin(Ramification) If the @nt<prefix> of a @nt<selected_component> denotes an enclosing named construct, then the @nt<selected_component> is interpreted only as an expanded name, even if the named construct is a function that could be called without parameters. @end(Ramification) @begin{Itemize} A component @Redundant[(including a discriminant)]: @NoPrefix@;The @nt{prefix} shall resolve to denote an object or value of some non-array composite type (after any implicit dereference). The @nt{selector_name} shall resolve to denote a @nt{discriminant_specification} of the type, or, unless the type is a protected type, a @nt<component_declaration> of the type. The @nt{selected_component} denotes the corresponding component of the object or value. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00015} The components of a protected object cannot be named except by an expanded name, even from within the corresponding protected body. The protected body may not reference @Chg{New=[],Old=[the ]}the private components of some arbitrary object of the protected type; the protected body may reference components of the current instance only (by an expanded name or a @nt<direct_name>). @end{Reason} @begin{Ramification} Only the discriminants and components visible at the place of the @nt<selected_component> can be selected, since a @nt<selector_name> can only denote declarations that are visible (see @RefSecNum{Visibility}). @end{Ramification} A single entry, an entry family, or a protected subprogram: @NoPrefix@;The @nt{prefix} shall resolve to denote an object or value of some task or protected type (after any implicit dereference). The @nt{selector_name} shall resolve to denote an @nt{entry_declaration} or @nt{subprogram_declaration} occurring (implicitly or explicitly) within the visible part of that type. The @nt{selected_component} denotes the corresponding entry, entry family, or protected subprogram. @begin{Reason} This explicitly says @lquotes@;visible part@rquotes@; because even though the body has visibility on the private part, it cannot call the private operations of some arbitrary object of the task or protected type, only those of the current instance (and expanded name notation has to be used for that). @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[A view of a subprogram whose first formal parameter is of a tagged type or is an access parameter whose designated type is tagged:]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The @nt<prefix> (after any implicit dereference) shall resolve to denote an object or value of a specific tagged type @i<T> or class-wide type @i<T>'Class. The @nt<selector_name> shall resolve to denote a view of a subprogram declared immediately within the declarative region in which an ancestor of the type @i<T> is declared. The first formal parameter of the subprogram shall be of type @i<T>, or a class-wide type that covers @i<T>, or an access parameter designating one of these types. The designator of the subprogram shall not be the same as that of a component of the tagged type visible at the point of the @nt<selected_component>. The @nt<selected_component> denotes a view of this subprogram that omits the first formal parameter. This view is called a @i{prefixed view} of the subprogram, and the @nt{prefix} of the @nt<selected_component> (after any implicit dereference) is called the @i<prefix> of the prefixed view. @Defn{prefixed view}@Defn2{Term=[prefix],Sec=[of a prefixed view]}]} @end{Itemize} @Leading@;An expanded name shall resolve to denote a declaration that occurs immediately within a named declarative region, as follows: @begin(itemize) The @nt<prefix> shall resolve to denote either a package @Redundant[(including the current instance of a generic package, or a rename of a package)], or an enclosing named construct. The @nt{selector_name} shall resolve to denote a declaration that occurs immediately within the declarative region of the package or enclosing construct @Redundant[(the declaration shall be visible at the place of the expanded name @em see @RefSecNum(Visibility))]. The expanded name denotes that declaration. @begin{Ramification} Hence, a library unit or subunit can use an expanded name to refer to the declarations within the private part of its parent unit, as well as to other children that have been mentioned in @nt<with_clause>s. @end{Ramification} If the @nt<prefix> does not denote a package, then it shall be a @nt<direct_name> or an expanded name, and it shall resolve to denote a program unit (other than a package), the current instance of a type, a @nt{block_statement}, a @nt{loop_statement}, or an @nt{accept_@!statement} (in the case of an @nt<accept_@!statement> or @nt<entry_@!body>, no family index is allowed); the expanded name shall occur within the declarative region of this construct. Further, if this construct is a callable construct and the @nt<prefix> denotes more than one such enclosing callable construct, then the expanded name is ambiguous, independently of the @nt<selector_name>. @end(itemize) @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[For a subprogram whose first parameter is an access parameter, the prefix of any prefixed view shall denote an aliased view of an object.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[For a subprogram whose first parameter is of mode @b<in out> or @b<out>, or of an anonymous access-to-variable type, the prefix of any prefixed view shall denote a variable.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We want calls through a prefixed view and through a normal view to have the same legality. Thus, the implicit 'Access in this new notation needs the same legality check that an explicit 'Access would have. Similarly, we need to prohibit the object from being constant if the first parameter of the subprogram is @key{in out}, because that is (obviously) prohibited for passing a normal parameter.]} @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(selected_component)} The evaluation of a @nt{selected_component} includes the evaluation of the @nt{prefix}. @IndexCheck{Discriminant_Check} For a @nt{selected_component} that denotes a component of a @nt{variant}, a check is made that the values of the discriminants are such that the value or object denoted by the @nt<prefix> has this component. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if this check fails. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of selected components:) @begin{Example} @tabclear()@tabset(P60) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} Tomorrow.Month --@RI[ a record component @\(see @RefSecNum{Record Types})] Next_Car.Owner --@RI[ a record component @\(see @RefSecNum{Incomplete Type Declarations})] Next_Car.Owner.Age --@RI[ a record component @\(see @RefSecNum{Incomplete Type Declarations})] --@RI[ the previous two lines involve implicit dereferences] Writer.Unit --@RI[ a record component (a discriminant) @\(see @RefSecNum{Variant Parts and Discrete Choices})] Min_Cell(H).Value --@RI[ a record component of the result @\(see @RefSecNum{Subprogram Declarations})] --@RI[ of the function call Min_Cell(H)] @Chg{Version=[2],New=< Cashier.Append --@RI[ a prefixed view of a procedure @\(see @RefSecNum{Interface Types})] >,Old=<>} Control.Seize --@RI[ an entry of a protected object @\(see @RefSecNum{Protected Units and Protected Objects})] Pool(K).Write --@RI[ an entry of the task Pool(K) @\(see @RefSecNum{Protected Units and Protected Objects})] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of expanded names:) @end{Wide} @begin{Example} @tabclear()@tabset(P67) Key_Manager."<" --@RI[ an operator of the visible part of a package @\(see @RefSecNum{Private Operations})] Dot_Product.Sum --@RI[ a variable declared in a function body @\(see @RefSecNum{Subprogram Declarations})] Buffer.Pool --@RI[ a variable declared in a protected unit @\(see @RefSecNum{Example of Tasking and Synchronization})] Buffer.Read --@RI[ an entry of a protected unit @\(see @RefSecNum{Example of Tasking and Synchronization})] Swap.Temp --@RI[ a variable declared in a block statement @\(see @RefSecNum{Block Statements})] Standard.Boolean --@RI[ the name of a predefined type @\(see @RefSecNum{The Package Standard})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now allow an expanded name to use a prefix that denotes a rename of a package, even if the selector is for an entity local to the body or private part of the package, so long as the entity is visible at the place of the reference. This eliminates a preexisting anomaly where references in a package body may refer to declarations of its visible part but not those of its private part or body when the prefix is a rename of the package. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{selector_name} is new. It is used in places where visibility, but not necessarily direct visibility, is required. See @RefSec{Names} for more information. The description of dereferencing an access type has been moved to @RefSec{Names}; @nt<name>.@key(all) is no longer considered a @nt<selected_component>. The rules have been restated to be consistent with our new terminology, to accommodate class-wide types, etc. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00252-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}The prefixed view notation for tagged objects is new. This provides a similar notation to that used in other popular languages, and also reduces the need for @nt{use_clause}s. This is sometimes known as @lquotes@;distinguished receiver notation@rquotes@;. @Defn{distinguished receiver notation}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Given the following definitions for a tagged type T:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} Do_Something (Obj : @key{in out} T; Count : @key{in} Natural); @key{procedure} Do_Something_Else (Obj : @key{access} T; Flag : @key{in} Boolean); My_Object : @key{aliased} T;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following calls are equivalent:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Do_Something (My_Object, Count => 10); My_Object.Do_Something (Count => 10);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[as are the following calls:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Do_Something_Else (My_Object'Access, Flag => True); My_Object.Do_Something_Else (Flag => True);]} @end{Example} @end{Extend95} @RMNewPage@ChgNote{Only needed for Ada 2005 version} @LabeledSubClause{Attributes} @begin{Intro} @Defn{attribute} @Redundant[An @i(attribute) is a characteristic of an entity that can be queried via an @nt{attribute_@!reference} or a @nt<range_@!attribute_@!reference>.] @end{Intro} @begin{Syntax} @Syn{lhs=<attribute_reference>, rhs="@Syn2{prefix}@SingleQuote@Syn2{attribute_designator}"} @Syn{lhs=<attribute_designator>,rhs=" @Syn2{identifier}[(@SynI{static_}@Syn2{expression})] | Access | Delta | Digits"} @Syn{lhs=<range_attribute_reference>, rhs="@Syn2{prefix}@SingleQuote@Syn2{range_attribute_designator}"} @Syn{lhs=<range_attribute_designator>, rhs="Range[(@SynI{static_}@Syn2{expression})]"} @end{Syntax} @begin{Resolution} In an @nt<attribute_reference>, if the @nt<attribute_designator> is for an attribute defined for (at least some) objects of an access type, then the @nt<prefix> is never interpreted as an @nt<implicit_dereference>; otherwise (and for all @nt<range_attribute_reference>s), if the type of the @nt<name> within the @nt<prefix> is of an access type, the @nt<prefix> is interpreted as an @nt<implicit_dereference>. Similarly, if the @nt{attribute_designator} is for an attribute defined for (at least some) functions, then the @nt<prefix> is never interpreted as a parameterless @nt{function_call}; otherwise (and for all @nt<range_attribute_reference>s), if the @nt<prefix> consists of a @nt<name> that denotes a function, it is interpreted as a parameterless @nt<function_call>. @begin{Discussion} The first part of this rule is essentially a "preference" against implicit dereference, so that it is possible to ask for, say, 'Size of an access object, without automatically getting the size of the object designated by the access object. This rule applies to 'Access, 'Unchecked_Access, 'Size, and 'Address, and any other attributes that are defined for at least some access objects. The second part of this rule implies that, for a parameterless function F, F'Address is the address of F, whereas F'Size is the size of the anonymous constant returned by F. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} We normally talk in terms of expected type or profile for name resolution rules, but we don't do this for attributes because certain attributes are legal independent of the type or the profile of the @Chg{New=[@nt{prefix}],Old=[prefix]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Other than the rules given above, the @ResolutionName@;s for the @nt{prefix} of each attribute are defined as @ResolutionTitle for that attribute. If no such rules are defined, then no context at all should be used when resolving the @nt{prefix}. In particular, any knowledge about the kind of entities required must not be used for resolution unless that is required by @ResolutionTitle. This matters in obscure cases; for instance, given the following declarations:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] Get_It @key[return] Integer @key[is] ... -- @RI[(1)] @key[function] Get_It @key[return] Some_Record_Type @key[is] ... -- @RI[(2)]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following @nt{attribute_reference} cannot be resolved and is illegal:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[if] Get_It'Valid @key[then]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[even though the Valid attribute is only defined for objects of scalar types, and thus cannot be applied to the result of function (2). That information cannot be used to resolve the @nt{prefix}. The same would be true if (2) was been a procedure; even though the procedure does not denote an object, the @nt{attribute_reference} is still illegal.]} @end{Discussion} @PDefn2{Term=[expected type], Sec=(attribute_designator expression)} @PDefn2{Term=[expected type], Sec=(range_attribute_designator expression)} The @nt{expression}, if any, in an @nt{attribute_designator} or @nt{range_attribute_designator} is expected to be of any integer type. @end{Resolution} @begin{Legality} The @nt{expression}, if any, in an @nt{attribute_designator} or @nt{range_attribute_designator} shall be static. @end{Legality} @begin{StaticSem} An @nt{attribute_reference} denotes a value, an object, a subprogram, or some other kind of program entity. @begin{Ramification} The attributes defined by the language are summarized in @RefSecNum{Language-Defined Attributes}. Implementations can define additional attributes. @end{Ramification} @Redundant[A @nt{range_attribute_reference} X'Range(N) is equivalent to the @nt<range> X'First(N) .. X'Last(N), except that the @nt{prefix} is only evaluated once. Similarly, X'Range is equivalent to X'First .. X'Last, except that the @nt{prefix} is only evaluated once.] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(attribute_reference)} @PDefn2{Term=[evaluation], Sec=(range_attribute_reference)} The evaluation of an @nt{attribute_reference} (or @nt{range_attribute_reference}) consists of the evaluation of the @nt{prefix}. @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0015],ARef=[AI95-00093-01]} An implementation may provide implementation-defined attributes; the @nt{identifier} for an implementation-defined attribute shall differ from those of the language-defined attributes@Chg{New=[ unless supplied for compatibility with a previous edition of this International Standard],Old=[]}. @ImplDef{Implementation-defined attributes.} @begin{Ramification} They cannot be reserved words because reserved words are not legal identifiers. The semantics of implementation-defined attributes, and any associated rules, are, of course, implementation defined. For example, the implementation defines whether a given implementation-defined attribute can be used in a static expression. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0015],ARef=[AI95-00093-01]} @Chg{New=[Implementations are allowed to support the Small attribute for floating types, as this was defined in Ada 83, even though the name would conflict with a language-defined attribute.],Old=[]} @end{Ramification} @end{ImplPerm} @begin{Notes} Attributes are defined throughout this International Standard, and are summarized in @RefSecNum{Language-Defined Attributes}. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235]} In general, the @nt<name> in a @nt<prefix> of an @nt<attribute_reference> (or a @nt<range_attribute_reference>) has to be resolved without using any context. However, in the case of the Access attribute, the expected type for the @Chg{Version=[2],New=[@nt{attribute_reference}], Old=[@Chg{New=[@nt{prefix}],Old=[prefix]}]} has to be a single access type, and@Chg{Version=[2],New=[],Old=[ if it is an access-to-subprogram type (see @RefSecNum(Operations of Access Types)) then]} the resolution of the @nt<name> can use the fact that the@Chg{Version=[2],New=[ type of the object or the],Old=[]} profile of the callable entity denoted by the @nt<prefix> has to @Chg{Version=[2],New=[match the designated type or ],Old=[]}be type conformant with the designated profile of the access type. @Defn2{Term=[type conformance],Sec=(required)} @begin(TheProof) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235]} In the general case, there is no @lquotes@;expected type@rquotes@; for the @nt<prefix> of an @nt<attribute_reference>. In the special case of 'Access, there is an @Chg{Version=[2],New=[@lquotes@;expected type@rquotes@; or ], Old=[]}@lquotes@;expected profile@rquotes@; for the @nt<prefix>. @end(TheProof) @begin(Reason) 'Access is a special case, because without it, it would be very difficult to take 'Access of an overloaded subprogram. @end(Reason) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of attributes:) @begin{Example} @tabclear()@tabset(P64) Color'First --@RI[ minimum value of the enumeration type Color @\(see @RefSecNum{Enumeration Types})] Rainbow'Base'First --@RI[ same as Color'First @\(see @RefSecNum{Enumeration Types})] Real'Digits --@RI[ precision of the type Real @\(see @RefSecNum{Floating Point Types})] Board'Last(2) --@RI[ upper bound of the second dimension of Board @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Board'Range(1) --@RI[ index range of the first dimension of Board @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Pool(K)'Terminated --@RI[ True if task Pool(K) is terminated @\(see @RefSecNum{Task Units and Task Objects})] Date'Size --@RI[ number of bits for records of type Date @\(see @RefSecNum{Record Types})] Message'Address --@RI[ address of the record variable Message @\(see @RefSecNum{Discriminant Constraints})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now uniformly treat X'Range as X'First..X'Last, allowing its use with scalar subtypes. We allow any integer type in the @SynI{static_}@nt{expression} of an attribute designator, not just a value of @i(universal_integer). The preference rules ensure upward compatibility. @end{Extend83} @begin{DiffWord83} We use the syntactic category @nt{attribute_reference} rather than simply "attribute" to avoid confusing the name of something with the thing itself. The syntax rule for @nt{attribute_reference} now uses @nt{identifier} instead of @ntf{simple_name}, because attribute @nt{identifier}s are not required to follow the normal visibility rules. We now separate @nt{attribute_reference} from @nt{range_attribute_reference}, and enumerate the reserved words that are legal attribute or range attribute designators. We do this because @nt{identifier} no longer includes reserved words. The Ada 95 name resolution rules are a bit more explicit than in Ada 83. The Ada 83 rule said that the "meaning of the prefix of an attribute must be determinable independently of the attribute designator and independently of the fact that it is the prefix of an attribute." That isn't quite right since the meaning even in Ada 83 embodies whether or not the prefix is interpreted as a parameterless function call, and in Ada 95, it also embodies whether or not the prefix is interpreted as an implicit_dereference. So the attribute designator does make a difference @em just not much. Note however that if the attribute designator is Access, it makes a big difference in the interpretation of the prefix (see @RefSecNum(Operations of Access Types)). @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0015],ARef=[AI95-00093-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was changed to allow implementations to continue to implement the Ada 83 Small attribute. This was always intended to be allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Text=[The note about resolving prefixes of attributes was updated to reflect that the prefix of an Access attribute now has an expected type (see @RefSecNum{Operations of Access Types}).]} @end{DiffWord95} @LabeledClause{Literals} @begin{Intro} @Redundant[@Defn{literal} A @i(literal) represents a value literally, that is, by means of notation suited to its kind.] A literal is either a @nt<numeric_literal>, a @nt<character_literal>, the literal @key(null), or a @nt<string_literal>. @IndexSeeAlso{Term=[constant],See=(literal)} @begin(Discussion) An enumeration literal that is an @nt<identifier> rather than a @nt<character_literal> is not considered a @i(literal) in the above sense, because it involves no special notation @lquotes@;suited to its kind.@rquotes@; It might more properly be called an @ntf<enumeration_identifier>, except for historical reasons. @end(Discussion) @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[expected type],Sec=(null literal)} The expected type for a literal @key(null) shall be a single access type.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This new wording ("expected type ... shall be a single ... type") replaces the old "shall be determinable" stuff. It reflects an attempt to simplify and unify the description of the rules for resolving aggregates, literals, type conversions, etc. See @RefSec{The Context of Overload Resolution} for the details.]} @end{Discussion} @PDefn2{Term=[expected type],Sec=(character_literal)} @PDefn2{Term=[expected profile],Sec=(character_literal)} For a @nt<name> that consists of a @nt<character_literal>, either its expected type shall be a single character type, in which case it is interpreted as a parameterless @nt<function_call> that yields the corresponding value of the character type, or its expected profile shall correspond to a parameterless function with a character result type, in which case it is interpreted as the name of the corresponding parameterless function declared as part of the character type's definition (see @RefSecNum(Enumeration Types)). In either case, the @nt{character_literal} denotes the @nt{enumeration_literal_specification}. @begin{Discussion} See @RefSecNum(Selected Components) for the resolution rules for a @nt<selector_name> that is a @nt<character_literal>. @end{Discussion} @PDefn2{Term=[expected type],Sec=(string_literal)} The expected type for a @nt{primary} that is a @nt<string_literal> shall be a single string type. @end{Resolution} @begin{Legality} A @nt{character_literal} that is a @nt<name> shall correspond to a @nt<defining_character_literal> of the expected type, or of the result type of the expected profile. For each character of a @nt{string_literal} with a given expected string type, there shall be a corresponding @nt<defining_character_literal> of the component type of the expected string type. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[A literal @s<null>@ChgNote{We use @S since this isn't a non-terminal, and since it is deleted we don't want to fix it.} shall not be of an anonymous access type@Redundant[, since such types do not have a null value (see @RefSecNum{Access Types})].]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This is a legality rule rather than an overloading rule, to simplify implementations.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} An integer literal is of type @i{universal_integer}. A real literal is of type @i{universal_real}.@Chg{Version=[2],New=[ The literal @key<null> is of type @i<universal_access>.],Old=[]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(numeric literal)} @PDefn2{Term=[evaluation], Sec=(null literal)} @Defn{null access value} @IndexSee{Term=[null pointer],See=(null access value)} The evaluation of a numeric literal, or the literal @key(null), yields the represented value. @PDefn2{Term=[evaluation], Sec=(string_literal)} The evaluation of a @nt{string_literal} that is a @nt<primary> yields an array value containing the value of each character of the sequence of characters of the @nt<string_literal>, as defined in @RefSecNum{String Literals}. The bounds of this array value are determined according to the rules for @nt<positional_array_aggregate>s (see @RefSecNum{Array Aggregates}), except that for a null string literal, the upper bound is the predecessor of the lower bound. @IndexCheck{Range_Check} For the evaluation of a @nt<string_literal> of type @i(T), a check is made that the value of each character of the @nt<string_literal> belongs to the component subtype of @i(T). For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if either of these checks fails. @begin{Ramification} The checks on the characters need not involve more than two checks altogether, since one need only check the characters of the string with the lowest and highest position numbers against the range of the component subtype. @end{Ramification} @end{RunTime} @begin{Notes} Enumeration literals that are @nt<identifier>s rather than @nt<character_literal>s follow the normal rules for @nt<identifier>s when used in a @nt<name> (see @RefSecNum{Names} and @RefSecNum{Selected Components}). @nt<Character_literal>s used as @nt<selector_name>s follow the normal rules for expanded names (see @RefSecNum{Selected Components}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of literals:) @begin{Example} @tabclear()@tabset(P16) 3.14159_26536 @\--@RI[ a real literal] 1_345 @\--@RI[ an integer literal] 'A' @\--@RI[ a character literal] "Some Text" @\--@RI[ a string literal ] @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Because @nt<character_literal>s are now treated like other literals, in that they are resolved using context rather than depending on direct visibility, additional qualification might be necessary when passing a @nt<character_literal> to an overloaded subprogram. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} @nt<Character_literal>s are now treated analogously to @key(null) and @nt<string_literal>s, in that they are resolved using context, rather than their content; the declaration of the corresponding @nt<defining_character_literal> need not be directly visible. @end{Extend83} @begin{DiffWord83} Name Resolution rules for enumeration literals that are not @nt<character_literal>s are not included anymore, since they are neither syntactically nor semantically "literals" but are rather names of parameterless functions. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}@key{Null} now has type @i<universal_access>, which is similar to other literals. @key{Null} can be used with anonymous access types.]} @end{Extend95} @LabeledClause{Aggregates} @begin{Intro} @Redundant[@Defn{aggregate} An @i(aggregate) combines component values into a composite value of an array type, record type, or record extension.] @IndexSeeAlso{Term={literal},See=(aggregate)} @end{Intro} @begin{Syntax} @Syn{lhs=<aggregate>,rhs="@Syn2{record_aggregate} | @Syn2{extension_aggregate} | @Syn2{array_aggregate}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type],Sec=(aggregate)} The expected type for an @nt{aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}array type, record type, or record extension. @begin{Discussion} See @RefSec{The Context of Overload Resolution} for the meaning of @lquotes@;shall be a single ... type.@rquotes@; @end{Discussion} @end{Resolution} @begin{Legality} An @nt{aggregate} shall not be of a class-wide type. @begin{Ramification} When the expected type in some context is class-wide, an aggregate has to be explicitly qualified by the specific type of value to be created, so that the expected type for the aggregate itself is specific. @end{Ramification} @begin{Discussion} We used to disallow @nt<aggregate>s of a type with unknown discriminants. However, that was unnecessarily restrictive in the case of an extension aggregate, and irrelevant to a record aggregate (since a type that is legal for a record aggregate could not possibly have unknown discriminants) and to an array aggregate (the only specific types that can have unknown discriminants are private types, private extensions, and types derived from them). @end{Discussion} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(aggregate)} For the evaluation of an @nt<aggregate>, an anonymous object is created and values for the components or ancestor part are obtained (as described in the subsequent subclause for each kind of the @nt<aggregate>) and assigned into the corresponding components or ancestor part of the anonymous object. @Defn2{Term=[assignment operation], Sec=(during evaluation of an @nt{aggregate})} Obtaining the values and the assignments occur in an arbitrary order. The value of the @nt{aggregate} is the value of this object. @begin{Discussion} The ancestor part is the set of components inherited from the ancestor type. The syntactic category @nt<ancestor_part> is the @nt<expression> or @nt<subtype_mark> that specifies how the ancestor part of the anonymous object should be initialized. @end{Discussion} @begin{Ramification} The assignment operations do the necessary value adjustment, as described in @RefSecNum{User-Defined Assignment and Finalization}. Note that the value as a whole is not adjusted @em just the subcomponents (and ancestor part, if any). @RefSecNum{User-Defined Assignment and Finalization} also describes when this anonymous object is finalized. If the @nt<ancestor_part> is a @nt<subtype_mark> the Initialize procedure for the ancestor type is applied to the ancestor part after default-initializing it, unless the procedure is abstract, as described in @RefSecNum{User-Defined Assignment and Finalization}. The Adjust procedure for the ancestor type is not called in this case, since there is no assignment to the ancestor part as a whole. @end{Ramification} @IndexCheck{Discriminant_Check} If an @nt{aggregate} is of a tagged type, a check is made that its value belongs to the first subtype of the type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{Ramification} This check ensures that no values of a tagged type are ever outside the first subtype, as required for inherited dispatching operations to work properly (see @RefSecNum(Derived Types and Classes)). This check will always succeed if the first subtype is unconstrained. This check is not extended to untagged types to preserve upward compatibility. @end{Ramification} @end{RunTime} @begin{Extend83} @Defn{extensions to Ada 83} We now allow @nt{extension_aggregate}s. @end{Extend83} @begin{DiffWord83} We have adopted new wording for expressing the rule that the type of an aggregate shall be determinable from the outside, though using the fact that it is nonlimited record (extension) or array. An @nt{aggregate} now creates an anonymous object. This is necessary so that controlled types will work (see @RefSecNum{User-Defined Assignment and Finalization}). @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} In Ada 95, a limited type is not considered when resolving an @nt{aggregate}. Since Ada 2005 now allows limited @nt{aggregate}s, we can have incompatibilities. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Lim @key{is} @key{limited} @key{record} Comp: Integer; @key{end} @key{record};],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Not_Lim @key{is} @key{record} Comp: Integer; @key{end} @key{record};],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{procedure} P(X: Lim); @key{procedure} P(X: Not_Lim);],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[P((Comp => 123)); -- @RI[Illegal in Ada 2005, legal in Ada 95]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The call to P is ambiguous in Ada 2005, while it would not be ambiguous in Ada 95 as the @nt{aggregate} could not have a limited type. Qualifying the @nt{aggregate} will eliminate any ambiguity. This construction would be rather confusing to a maintenance programmer, so it should be avoided, and thus we expect it to be rare.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}@nt{Aggregate}s can be of a limited type.]} @end{Extend95} @LabeledSubClause{Record Aggregates} @begin{Intro} @Redundant[In a @nt<record_aggregate>, a value is specified for each component of the record or record extension value, using either a named or a positional association.] @end{Intro} @begin{Syntax} @Syn{lhs=<record_aggregate>,rhs="(@Syn2{record_component_association_list})"} @Syn{lhs=<record_component_association_list>,rhs=" @Syn2{record_component_association} {, @Syn2{record_component_association}} | @key<null record>"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<record_component_association>,rhs=" [@Syn2{component_choice_list} =>] @Syn2{expression}@Chg{Version=[2],New=[ | @Syn2{component_choice_list} => <>],Old=[]}"} @Syn{lhs=<component_choice_list>,rhs=" @SynI{component_}@Syn2{selector_name} {| @SynI{component_}@Syn2{selector_name}} | @key{others}"} @begin(SyntaxText) @Defn{named component association} A @nt<record_@!component_@!association> is a @i(named component association) if it has a @nt<component_choice_list>; @Defn{positional component association} otherwise, it is a @i(positional component association). Any positional component associations shall precede any named component associations. If there is a named association with a @nt<component_choice_list> of @key(others), it shall come last. @begin{Discussion} These rules were implied by the BNF in an early version of the RM9X, but it made the grammar harder to read, and was inconsistent with how we handle discriminant constraints. Note that for array aggregates we still express some of the rules in the grammar, but array aggregates are significantly different because an array aggregate is either all positional (with a possible @key(others) at the end), or all named. @end{Discussion} In the @nt<record_@!component_@!association_@!list> for a @nt<record_@!aggregate>, if there is only one association, it shall be a named association. @begin{Reason} Otherwise the construct would be interpreted as a parenthesized expression. This is considered a syntax rule, since it is relevant to overload resolution. We choose not to express it with BNF so we can share the definition of @nt<record_component_association_list> in both @nt<record_aggregate> and @nt<extension_aggregate>. @end{Reason} @begin{Ramification} The @nt<record_component_association_list> of an @nt<extension_aggregate> does not have such a restriction. @end{Ramification} @end(SyntaxText) @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type],Sec=(record_aggregate)} The expected type for a @nt{record_aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}record type or record extension. @begin{Ramification} This rule is used to resolve whether an @nt{aggregate} is an @nt{array_aggregate} or a @nt{record_aggregate}. The presence of a @key(with) is used to resolve between a @nt{record_aggregate} and an @nt{extension_aggregate}. @end{Ramification} @Defn2{Term=[needed component], Sec=(@nt<record_aggregate> @nt<record_component_association_list>)} For the @nt<record_@!component_@!association_@!list> of a @nt<record_@!aggregate>, all components of the composite value defined by the aggregate are @i(needed)@Redundant[; for the association list of an @nt<extension_aggregate>, only those components not determined by the ancestor expression or subtype are needed (see @RefSecNum{Extension Aggregates}).] Each @nt{selector_@!name} in a @nt{record_@!component_@!association} shall denote a needed component @Redundant[(including possibly a discriminant)]. @begin{Ramification} For the association list of a @nt{record_aggregate}, @lquotes@;needed components@rquotes@; includes every component of the composite value, but does not include those in unchosen @nt{variant}s (see AI83-309). If there are @nt<variant>s, then the value specified for the discriminant that governs them determines which @nt<variant> is chosen, and hence which components are needed. If an extension defines a new @nt{known_discriminant_part}, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the @nt<record_@!component_@!association_@!list> are well defined, and that discriminants that govern @nt{variant_part}s can be given by static expressions. @end{Ramification} @Leading@Keepnext@PDefn2{Term=[expected type], Sec=(record_component_association expression)} The expected type for the @nt<expression> of a @nt<record_@!component_@!association> is the type of the @i(associated) component(s); @Defn2{Term=[associated components], Sec=(of a @nt<record_component_association>)} the associated component(s) are as follows: @begin(itemize) For a positional association, the component @Redundant[(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components; @begin{Ramification} This means that for an association list of an @nt<extension_aggregate>, only noninherited components are counted to determine the position. @end{Ramification} For a named association with one or more @i(component_)@nt<selector_name>s, the named component(s); For a named association with the reserved word @key(others), all needed components that are not associated with some previous association. @end(itemize) @end{Resolution} @begin{Legality} If the type of a @nt{record_aggregate} is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions). If there are no components needed in a given @nt<record_@!component_@!association_@!list>, then the reserved words @key(null record) shall appear rather than a list of @nt<record_@!component_@!association>s. @begin{Ramification} For example, "(@key(null record))" is a @nt<record_aggregate> for a null record type. Similarly, "(T'(A) @key(with null record))" is an @nt<extension_aggregate> for a type defined as a null record extension of T. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Each @nt<record_component_association>@Chg{Version=[2],New=[ other than an @key{others} choice with a <>],Old=[]} shall have at least one associated component, and each needed component shall be associated with exactly one @nt<record_@!component_@!association>. If a @nt<record_@!component_@!association> @Chg{Version=[2],New=[with an @nt{expression} ],Old=[]}has two or more associated components, all of them shall be of the same type. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} These rules apply to an association with an @key(others) choice@Chg{Version=[2],New=[ with an expression. An @key(others) choice with a <> can match zero components or several components with different types.],Old=[]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Without these rules, there would be no way to know what was the expected type for the @nt<expression> of the association. @Chg{Version=[2],New=[Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow @key{others} => <> to match no components as this is similar to array aggregates. That means that (@key{others} => <>) always represents a default-initialized record or array value.],Old=[]} @end{Reason} @begin{Discussion} AI83-00244 also requires that the @nt{expression} shall be legal for each associated component. This is because even though two components have the same type, they might have different subtypes. Therefore, the legality of the @nt<expression>, particularly if it is an array aggregate, might differ depending on the associated component's subtype. However, we have relaxed the rules on array aggregates slightly for Ada 95, so the staticness of an applicable index constraint has no effect on the legality of the array aggregate to which it applies. See @RefSecNum{Array Aggregates}. This was the only case (that we know of) where a subtype provided by context affected the legality of an @nt{expression}. @end{Discussion} @begin{Ramification} The rule that requires at least one associated component for each @nt<record_component_association> implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an @nt<extension_aggregate>. The second part of the first sentence ensures that no needed components are left out, nor specified twice. @end{Ramification} If the components of a @nt{variant_part} are needed, then the value of a discriminant that governs the @nt{variant_part} shall be given by a static expression. @begin{Ramification} This expression might either be given within the aggregate itself, or in a constraint on the parent subtype in a @nt<derived_type_definition> for some ancestor of the type of the aggregate. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[A @nt<record_component_association> for a discriminant without a @nt<default_expression> shall have an @nt<expression> rather than <>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A discriminant must always have a defined value, but <> means uninitialized for a discrete type unless the component has a default value.]} @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(record_aggregate)} The evaluation of a @nt<record_aggregate> consists of the evaluation of the @nt<record_@!component_@!association_@!list>. @PDefn2{Term=[evaluation], Sec=(record_component_association_list)} For the evaluation of a @nt{record_@!component_@!association_@!list}, any per-object constraints (see @RefSecNum(Record Types)) for components specified in the association list are elaborated and any @nt<expression>s are evaluated and converted to the subtype of the associated component. @PDefn2{Term=[implicit subtype conversion],Sec=(expressions in aggregate)} Any constraint elaborations and @nt{expression} evaluations (and conversions) occur in an arbitrary order, except that the @nt<expression> for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the @nt{expression} for the component with the per-object constraint. @begin{Ramification} The conversion in the first rule might raise Constraint_Error. @end{Ramification} @begin{Discussion} This check in the first rule presumably happened as part of the dependent compatibility check in Ada 83. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[For a @nt<record_component_association> with an @nt<expression>, the @nt<expression> defines the value for the associated component(s). For a @nt<record_component_association> with <>, if the @nt<component_declaration> has a @nt<default_expression>, that @nt<default_expression> defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see @RefSecNum{Object Declarations}).]} The @nt<expression> of a @nt{record_component_association} is evaluated (and converted) once for each associated component. @end{RunTime} @begin{Notes} For a @nt<record_aggregate> with positional associations, expressions specifying discriminant values appear first since the @nt<known_discriminant_part> is given first in the declaration of the type; they have to be in the same order as in the @nt<known_discriminant_part>. @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a record aggregate with positional associations:) @begin{Example} (4, July, 1776) --@RI[ see @RefSecNum{Record Types} ] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of record aggregates with named associations:) @end{Wide} @begin{Example} (Day => 4, Month => July, Year => 1776) (Month => July, Day => 4, Year => 1776) (Disk, Closed, Track => 5, Cylinder => 12) --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] (Unit => Disk, Status => Closed, Cylinder => 9, Track => 1) @end{Example} @begin{Wide} @leading@keepnext@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @i(@Chg{Version=[2],New=[Examples],Old=[Example]} of component @Chg{Version=[2],New=[associations],Old=[association]} with several choices:) @end{Wide} @begin{Example} @tabclear()@tabset(P50) (Value => 0, Succ|Pred => @key(new) Cell'(0, @key(null), @key(null))) @\--@RI[ see @RefSecNum{Incomplete Type Declarations}] --@RI[ The allocator is evaluated twice: Succ and Pred designate different cells] @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[(Value => 0, Succ|Pred => <>) @\--@RI[ see @RefSecNum{Incomplete Type Declarations}]],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ --@RI[ Succ and Pred will be set to @key{null}]],Old=[]} @end{Example} @begin{Wide} @leading@keepnext@i{Examples of record aggregates for tagged types (see @RefSecNum(Tagged Types and Type Extensions) and @RefSecNum{Type Extensions}):} @end{Wide} @begin{Example} Expression'(@key{null record}) Literal'(Value => 0.0) Painted_Point'(0.0, Pi/2.0, Paint => Red) @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Null record aggregates may now be specified, via "(@key(null record))". However, this syntax is more useful for null record extensions in extension aggregates. @end{Extend83} @begin{DiffWord83} Various AIs have been incorporated (AI83-00189, AI83-00244, and AI83-00309). In particular, Ada 83 did not explicitly disallow extra values in a record aggregate. Now we do. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}<> can be used in place of an @nt{expression} in a @nt{record_aggregate}, default initializing the component.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{record_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @end{DiffWord95} @RmNewPage @LabeledSubClause{Extension Aggregates} @begin{Intro} @Redundant[An @nt<extension_aggregate> specifies a value for a type that is a record extension by specifying a value or subtype for an ancestor of the type, followed by associations for any components not determined by the @nt<ancestor_part>.] @end{Intro} @begin{MetaRules} The model underlying this syntax is that a record extension can also be viewed as a regular record type with an ancestor "prefix." The @nt<record_@!component_@!association_@!list> corresponds to exactly what would be needed if there were no ancestor/prefix type. The @nt{ancestor_part} determines the value of the ancestor/prefix. @end{MetaRules} @begin{Syntax} @Syn{lhs=<extension_aggregate>,rhs=" (@Syn2{ancestor_part} @key(with) @Syn2{record_component_association_list})"} @Syn{lhs=<ancestor_part>, rhs="@Syn2{expression} | @Syn2{subtype_mark}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(extension_aggregate)} The expected type for an @nt{extension_aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}type that is a record extension. @PDefn2{Term=[expected type], Sec=(extension_aggregate ancestor expression)} If the @nt<ancestor_part> is an @nt<expression>, it is expected to be of any @Chg{Version=[2],New=[],Old=[nonlimited ]}tagged type. @begin{Reason} We could have made the expected type @i(T')Class where @i(T) is the ultimate ancestor of the type of the aggregate, or we could have made it even more specific than that. However, if the overload resolution rules get too complicated, the implementation gets more difficult and it becomes harder to produce good error messages. @end{Reason} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00306-01]} If the @nt<ancestor_part> is a @nt<subtype_mark>, it shall denote a specific tagged subtype. @Chg{Version=[2],New=[If the @nt{ancestor_part} is an @nt{expression}, it shall not be dynamically tagged. ],Old=[]} The type of the @nt{extension_aggregate} shall be derived from the type of the @nt<ancestor_part>, through one or more record extensions (and no private extensions). @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00306-01]} @ChgAdded{Version=[2],Text=[The expression cannot be dynamically tagged to prevent implicit "truncation" of a dynamically-tagged value to the specific ancestor type. This is similar to the rules in @RefSecNum{Dispatching Operations of Tagged Types}.]} @end{Reason} @end{Legality} @begin{StaticSem} @Defn2{Term=[needed component], Sec=(@nt<extension_aggregate> @nt<record_component_association_list>)} For the @nt{record_@!component_@!association_@!list} of an @nt{extension_@!aggregate}, the only components @i(needed) are those of the composite value defined by the aggregate that are not inherited from the type of the @nt<ancestor_@!part>, plus any inherited discriminants if the @nt<ancestor_@!part> is a @nt<subtype_@!mark> that denotes an unconstrained subtype. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(extension_aggregate)} For the evaluation of an @nt{extension_aggregate}, the @nt{record_@!component_@!association_@!list} is evaluated. If the @nt<ancestor_part> is an @nt<expression>, it is also evaluated; if the @nt<ancestor_part> is a @nt<subtype_mark>, the components of the value of the aggregate not given by the @nt<record_@!component_@!association_@!list> are initialized by default as for an object of the ancestor type. Any implicit initializations or evaluations are performed in an arbitrary order, except that the @nt<expression> for a discriminant is evaluated prior to any other evaluation or initialization that depends on it. @IndexCheck{Discriminant_Check} If the type of the @nt<ancestor_part> has discriminants that are not inherited by the type of the @nt{extension_aggregate}, then, unless the @nt<ancestor_part> is a @nt<subtype_mark> that denotes an unconstrained subtype, a check is made that each discriminant of the ancestor has the value specified for a corresponding discriminant, either in the @nt{record_@!component_@!association_@!list}, or in the @nt<derived_type_definition> for some ancestor of the type of the @nt{extension_aggregate}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{Ramification} Corresponding and specified discriminants are defined in @RefSecNum{Discriminants}. The rules requiring static compatibility between new discriminants of a derived type and the parent discriminant(s) they constrain ensure that at most one check is required per discriminant of the ancestor expression. @end{Ramification} @end{RunTime} @begin{Notes} If all components of the value of the @nt<extension_aggregate> are determined by the @nt<ancestor_part>, then the @nt<record_@!component_@!association_@!list> is required to be simply @key(null record). If the @nt<ancestor_part> is a @nt<subtype_mark>, then its type can be abstract. If its type is controlled, then as the last step of evaluating the aggregate, the Initialize procedure of the ancestor type is called, unless the Initialize procedure is abstract (see @RefSecNum{User-Defined Assignment and Finalization}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of extension aggregates (for types defined in @RefSecNum{Type Extensions}):} @begin(example) Painted_Point'(Point @key{with} Red) (Point'(P) @key{with} Paint => Black) (Expression @key{with} Left => 1.2, Right => 3.4) Addition'(Binop @key{with null record}) --@RI[ presuming Binop is of type Binary_Operation] @end(example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The extension aggregate syntax is new. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00306-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Eliminated implicit @lquotes@;truncation@rquotes of a dynamically tagged value when it is used as an ancestor @nt{expression}. If an @nt{aggregate} includes such an @nt{expression}, it is illegal in Ada 2005. Such @nt{aggregate}s are thought to be rare; the problem can be fixed with a type conversion to the appropriate specific type if it occurs.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{extension_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @end{DiffWord95} @LabeledSubClause{Array Aggregates} @begin{Intro} @Redundant[In an @nt<array_aggregate>, a value is specified for each component of an array, either positionally or by its index.] For a @nt{positional_array_aggregate}, the components are given in increasing-index order, with a final @key[others], if any, representing any remaining components. For a @nt{named_array_aggregate}, the components are identified by the values covered by the @nt{discrete_choice}s. @end{Intro} @begin{MetaRules} @ChgRef{Version=[1],Kind=[Revised]} The rules in this subclause are based on terms and rules for @nt{discrete_choice_list}s defined in @RefSec{Variant Parts and Discrete Choices}. @Chg{New=[For example, the requirements that @key(others) come last and stand alone are found there.],Old=[]}@Comment{This question is asked periodically, so we answer it explicitly.} @end{MetaRules} @begin{Syntax} @Syn{lhs=<array_aggregate>,rhs=" @Syn2{positional_array_aggregate} | @Syn2{named_array_aggregate}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<positional_array_aggregate>,rhs=" (@Syn2{expression}, @Syn2{expression} {, @Syn2{expression}}) | (@Syn2{expression} {, @Syn2{expression}}, @key(others) => @Syn2{expression})@Chg{Version=[2],New=[ | (@Syn2{expression} {, @Syn2{expression}}, @key(others) => <>)],Old=[]}"} @Syn{lhs=<named_array_aggregate>,rhs=" (@Syn2{array_component_association} {, @Syn2{array_component_association}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<array_component_association>,rhs=" @Syn2{discrete_choice_list} => @Syn2{expression}@Chg{Version=[2],New=[ | @Syn2{discrete_choice_list} => <>],Old=[]}"} @end{Syntax} @begin{Intro} @Defn{n-dimensional @nt<array_aggregate>} An @i(n-dimensional) @nt<array_aggregate> is one that is written as n levels of nested @nt{array_aggregate}s (or at the bottom level, equivalent @nt{string_literal}s). @Defn2{Term=[subaggregate], Sec=(of an @nt{array_aggregate})} For the multidimensional case (n >= 2) the @nt<array_aggregate>s (or equivalent @nt<string_literal>s) at the n@en@;1 lower levels are called @i(subaggregate)s of the enclosing n-dimensional @nt<array_aggregate>. @Defn{array component expression} The @nt<expression>s of the bottom level subaggregates (or of the @nt<array_aggregate> itself if one-dimensional) are called the @i(array component expressions) of the enclosing n-dimensional @nt<array_aggregate>. @begin(Ramification) Subaggregates do not have a type. They correspond to part of an array. For example, with a matrix, a subaggregate would correspond to a single row of the matrix. The definition of "n-dimensional" @nt<array_aggregate> applies to subaggregates as well as @nt<aggregate>s that have a type. @end(Ramification) @begin(Honest) @Defn{others choice} An @i(@key(others) choice) is the reserved word @key(others) as it appears in a @nt{positional_array_aggregate} or as the @nt{discrete_choice} of the @nt{discrete_choice_list} in an @nt{array_component_association}. @end(Honest) @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(array_aggregate)} The expected type for an @nt{array_aggregate} (that is not a subaggregate) shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}array type. @PDefn2{Term=[expected type], Sec=(array_aggregate component expression)} The component type of this array type is the expected type for each array component expression of the @nt<array_aggregate>. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} We already require a single array or record type or record extension for an @nt{aggregate}. The above rule requiring a single @Chg{Version=[2],New=[], Old=[nonlimited ]}array type (and similar ones for record and extension aggregates) resolves which kind of aggregate you have. @end{Ramification} @PDefn2{Term=[expected type], Sec=(array_aggregate discrete_choice)} The expected type for each @nt{discrete_choice} in any @nt{discrete_choice_list} of a @nt{named_array_aggregate} is the type of the @i(corresponding index); @Defn2{Term=[corresponding index], Sec=(for an @nt{array_aggregate})} the corresponding index for an @nt<array_aggregate> that is not a subaggregate is the first index of its type; for an (n@en@;m)-dimensional subaggregate within an @nt<array_aggregate> of an n-dimensional type, the corresponding index is the index in position m+1. @end{Resolution} @begin{Legality} An @nt<array_aggregate> of an n-dimensional array type shall be written as an n-dimensional @nt<array_aggregate>. @begin(Ramification) In an m-dimensional @nt<array_aggregate> @Redundant[(including a subaggregate)], where m >= 2, each of the @nt<expression>s has to be an (m@en@;1)-dimensional subaggregate. @end(Ramification) @Leading@;An @key(others) choice is allowed for an @nt<array_aggregate> only if an @i(applicable index constraint) applies to the @nt{array_aggregate}. @Defn{applicable index constraint} @Redundant[An applicable index constraint is a constraint provided by certain contexts where an @nt{array_aggregate} is permitted that can be used to determine the bounds of the array value specified by the aggregate.] Each of the following contexts (and none other) defines an applicable index constraint: @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} For an @nt{explicit_actual_parameter}, an @nt{explicit_generic_actual_parameter}, the @nt{expression} of a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}, the initialization expression in an @nt{object_@!declaration}, or a @nt{default_@!expression} @Redundant[(for a parameter or a component)], when the nominal subtype of the corresponding formal parameter, generic formal parameter, function @Chg{Version=[2],New=[return object],Old=[result]}, object, or component is a constrained array subtype, the applicable index constraint is the constraint of the subtype; For the @nt{expression} of an @nt{assignment_statement} where the @nt{name} denotes an array variable, the applicable index constraint is the constraint of the array variable; @begin{Reason} This case is broken out because the constraint comes from the actual subtype of the variable (which is always constrained) rather than its nominal subtype (which might be unconstrained). @end{Reason} For the operand of a @nt{qualified_expression} whose @nt{subtype_mark} denotes a constrained array subtype, the applicable index constraint is the constraint of the subtype; For a component @nt{expression} in an @nt{aggregate}, if the component's nominal subtype is a constrained array subtype, the applicable index constraint is the constraint of the subtype; @begin{Discussion} Here, the @nt{array_aggregate} with @key[others] is being used within a larger aggregate. @end{Discussion} For a parenthesized @nt{expression}, the applicable index constraint is that, if any, defined for the @nt{expression}. @begin{Discussion} RM83 omitted this case, presumably as an oversight. We want to minimize situations where an @nt{expression} becomes illegal if parenthesized. @end{Discussion} @end(itemize) The applicable index constraint @i(applies) to an @nt{array_aggregate} that appears in such a context, as well as to any subaggregates thereof. In the case of an @nt<explicit_actual_parameter> (or @nt<default_expression>) for a call on a generic formal subprogram, no applicable index constraint is defined. @begin(Reason) This avoids generic contract model problems, because only mode conformance is required when matching actual subprograms with generic formal subprograms. @end(Reason) The @nt{discrete_choice_list} of an @nt{array_component_association} is allowed to have a @nt{discrete_choice} that is a nonstatic @nt<expression> or that is a @nt{discrete_range} that defines a nonstatic or null range, only if it is the single @nt{discrete_choice} of its @nt{discrete_choice_list}, and there is only one @nt{array_component_association} in the @nt<array_aggregate>. @begin{Discussion} We now allow a nonstatic @key(others) choice even if there are other array component expressions as well. @end{Discussion} In a @nt<named_array_aggregate> with more than one @nt<discrete_choice>, no two @nt<discrete_choice>s are allowed to cover the same value (see @RefSecNum{Variant Parts and Discrete Choices}); if there is no @key[others] choice, the @nt<discrete_choice>s taken together shall exactly cover a contiguous sequence of values of the corresponding index type. @begin{Ramification} This implies that each component must be specified exactly once. See AI83-309. @end{Ramification} A bottom level subaggregate of a multidimensional @nt<array_aggregate> of a given array type is allowed to be a @nt<string_literal> only if the component type of the array type is a character type; each character of such a @nt{string_literal} shall correspond to a @nt<defining_character_literal> of the component type. @end{Legality} @begin{StaticSem} A subaggregate that is a @nt<string_literal> is equivalent to one that is a @nt<positional_array_aggregate> of the same length, with each @nt<expression> being the @nt<character_literal> for the corresponding character of the @nt<string_literal>. @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(array_aggregate)} The evaluation of an @nt{array_aggregate} of a given array type proceeds in two steps: @begin(enumerate) Any @nt{discrete_choice}s of this aggregate and of its subaggregates are evaluated in an arbitrary order, and converted to the corresponding index type; @PDefn2{Term=[implicit subtype conversion],Sec=(choices of aggregate)} The array component expressions of the aggregate are evaluated in an arbitrary order and their values are converted to the component subtype of the array type; an array component expression is evaluated once for each associated component. @PDefn2{Term=[implicit subtype conversion],Sec=(expressions of aggregate)} @end(enumerate) @begin(Ramification) Subaggregates are not separately evaluated. The conversion of the value of the component expressions to the component subtype might raise Constraint_Error. @end(Ramification) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Each @nt<expression> in an @nt<array_component_association> defines the value for the associated component(s). For an @nt<array_component_association> with <>, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see @RefSecNum{Object Declarations}).]} @Leading@Defn2{Term=[bounds], Sec=(of the index range of an @nt{array_aggregate})} The bounds of the index range of an @nt{array_aggregate} @Redundant[(including a subaggregate)] are determined as follows: @begin(itemize) For an @nt{array_aggregate} with an @key(others) choice, the bounds are those of the corresponding index range from the applicable index constraint; For a @nt{positional_array_aggregate} @Redundant[(or equivalent @nt<string_literal>)] without an @key(others) choice, the lower bound is that of the corresponding index range in the applicable index constraint, if defined, or that of the corresponding index subtype, if not; in either case, the upper bound is determined from the lower bound and the number of @nt<expression>s @Redundant[(or the length of the @nt<string_literal>)]; For a @nt{named_array_aggregate} without an @key(others) choice, the bounds are determined by the smallest and largest index values covered by any @nt{discrete_choice_list}. @begin{Reason} We don't need to say that each index value has to be covered exactly once, since that is a ramification of the general rule on @nt{aggregate}s that each component's value has to be specified exactly once. @end{Reason} @end(itemize) @IndexCheck{Range_Check} For an @nt<array_aggregate>, a check is made that the index range defined by its bounds is compatible with the corresponding index subtype. @begin{Discussion} In RM83, this was phrased more explicitly, but once we define "compatibility" between a range and a subtype, it seems to make sense to take advantage of that definition. @end{Discussion} @begin(Ramification) The definition of compatibility handles the special case of a null range, which is always compatible with a subtype. See AI83-00313. @end(Ramification) @IndexCheck{Index_Check} For an @nt{array_aggregate} with an @key(others) choice, a check is made that no @nt<expression> is specified for an index value outside the bounds determined by the applicable index constraint. @begin{Discussion} RM83 omitted this case, apparently through an oversight. AI83-00309 defines this as a dynamic check, even though other Ada 83 rules ensured that this check could be performed statically. We now allow an @key(others) choice to be dynamic, even if it is not the only choice, so this check now needs to be dynamic, in some cases. Also, within a generic unit, this would be a nonstatic check in some cases. @end{Discussion} @IndexCheck{Index_Check} For a multidimensional @nt{array_aggregate}, a check is made that all subaggregates that correspond to the same index have the same bounds. @begin{Ramification} No array bounds @lquotes@;sliding@rquotes@; is performed on subaggregates. @end{Ramification} @begin{Reason} If sliding were performed, it would not be obvious which subaggregate would determine the bounds of the corresponding index. @end{Reason} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if any of the above checks fail. @end{RunTime} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised]} In an @nt<array_aggregate>, positional notation may only be used with two or more @nt<expression>s; a single @nt<expression> in parentheses is interpreted as a @Chg{Version=[2],New=[parenthesized expression],Old=[@ntf{parenthesized_expression}]}. A @nt<named_array_aggregate>, such as (1 => X), may be used to specify an array with a single component. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of array aggregates with positional associations:) @begin{Example} (7, 9, 5, 1, 3, 2, 4, 8, 6, 0) Table'(5, 8, 4, 1, @key(others) => 0) --@RI[ see @RefSecNum{Array Types} ] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of array aggregates with named associations:) @end{Wide} @begin{Example} (1 .. 5 => (1 .. 8 => 0.0)) --@RI[ two-dimensional] (1 .. N => @key(new) Cell) --@RI[ N new cells, in particular for N = 0] Table'(2 | 4 | 10 => 1, @key(others) => 0) Schedule'(Mon .. Fri => True, @key(others) => False) --@RI[ see @RefSecNum{Array Types}] Schedule'(Wed | Sun => False, @key(others) => True) Vector'(1 => 2.5) --@RI[ single-component vector] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of two-dimensional array aggregates:) @end{Wide} @begin{Example} --@RI[ Three aggregates for the same value of subtype Matrix(1..2,1..3) (see @RefSecNum{Array Types}):] ((1.1, 1.2, 1.3), (2.1, 2.2, 2.3)) (1 => (1.1, 1.2, 1.3), 2 => (2.1, 2.2, 2.3)) (1 => (1 => 1.1, 2 => 1.2, 3 => 1.3), 2 => (1 => 2.1, 2 => 2.2, 3 => 2.3)) @end{Example} @begin{Wide} @leading@keepnext@i(Examples of aggregates as initial values:) @end{Wide} @begin{Example} A : Table := (7, 9, 5, 1, 3, 2, 4, 8, 6, 0); --@RI[ A(1)=7, A(10)=0] B : Table := (2 | 4 | 10 => 1, @key(others) => 0); --@RI[ B(1)=0, B(10)=1] C : @key(constant) Matrix := (1 .. 5 => (1 .. 8 => 0.0)); --@RI[ C'Last(1)=5, C'Last(2)=8] D : Bit_Vector(M .. N) := (M .. N => True); --@RI[ see @RefSecNum{Array Types}] E : Bit_Vector(M .. N) := (@key(others) => True); F : String(1 .. 1) := (1 => 'F'); --@RI[ a one component aggregate: same as "F"] @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T],Text=[@i{Example of an array aggregate with defaulted others choice and with an applicable index constraint provided by an enclosing record aggregate:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Buffer'(Size => 50, Pos => 1, Value => String'('x', @key(others) => <>)) --@RI[ see @RefSecNum{Discriminants}]]} @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @ChgAdded{Version=[1],Type=[Leading],Text=[@Defn{incompatibilities with Ada 83} In Ada 95, no applicable index constraint is defined for a parameter in a call to a generic formal subprogram; thus, some aggregates that are legal in Ada 83 are illegal in Ada 95. For example:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @Chg{New=[@key[subtype] S3 @key[is] String (1 .. 3); ... @key[generic] @key[with function] F (The_S3 : @key[in] S3) @key[return] Integer; @key[package] Gp @key[is] I : constant Integer := F ((1 => '!', others => '?')); -- @RI{The aggregate is legal in Ada 83, illegal in Ada 95.} @key[end] Gp;],Old=[]} @end{Example} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @Chg{New=[This change eliminates generic contract model problems.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} We now allow "named with others" aggregates in all contexts where there is an applicable index constraint, effectively eliminating what was RM83-4.3.2(6). Sliding never occurs on an aggregate with others, because its bounds come from the applicable index constraint, and therefore already match the bounds of the target. The legality of an @key(others) choice is no longer affected by the staticness of the applicable index constraint. This substantially simplifies several rules, while being slightly more flexible for the user. It obviates the rulings of AI83-00244 and AI83-00310, while taking advantage of the dynamic nature of the "extra values" check required by AI83-00309. Named array aggregates are permitted even if the index type is descended from a formal scalar type. See @RefSecNum(Static Expressions and Static Subtypes) and AI83-00190. @end{Extend83} @begin{DiffWord83} We now separate named and positional array aggregate syntax, since, unlike other aggregates, named and positional associations cannot be mixed in array aggregates (except that an @key(others) choice is allowed in a positional array aggregate). We have also reorganized the presentation to handle multidimensional and one-dimensional aggregates more uniformly, and to incorporate the rulings of AI83-00019, AI83-00309, etc. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}<> can be used in place of an @nt{expression} in an @nt{array_aggregate}, default-initializing the component.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{array_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Fixed @nt{aggregate}s to use the subtype of the return object of a function, rather than the result subtype, because they can be different for an @nt{extended_return_statement}, and we want to use the subtype that's explicitly in the code at the point of the @nt{expression}.]} @end{DiffWord95} @LabeledClause{Expressions} @begin{Intro} @Defn{expression} An @i(expression) is a formula that defines the computation or retrieval of a value. In this International Standard, the term @lquotes@;expression@rquotes@; refers to a construct of the syntactic category @nt<expression> or of any of the other five syntactic categories defined below. @Defn{and operator}@Defn2{Term=[operator],Sec=(and)} @Defn{or operator}@Defn2{Term=[operator],Sec=(or)} @Defn{xor operator}@Defn2{Term=[operator],Sec=(xor)} @Defn{and then (short-circuit control form)} @Defn{or else (short-circuit control form)} @Defn{= operator}@Defn2{Term=[operator],Sec=(=)} @Defn{equal operator}@Defn2{Term=[operator],Sec=(equal)} @Defn{/= operator}@Defn2{Term=[operator],Sec=(/=)} @Defn{not equal operator}@Defn2{Term=[operator],Sec=(not equal)} @Defn{< operator}@Defn2{Term=[operator],Sec=(<)} @Defn{less than operator}@Defn2{Term=[operator],Sec=(less than)} @Defn{<= operator}@Defn2{Term=[operator],Sec=(<=)} @Defn{less than or equal operator}@Defn2{Term=[operator],Sec=(less than or equal)} @Defn{> operator}@Defn2{Term=[operator],Sec=(>)} @Defn{greater than operator}@Defn2{Term=[operator],Sec=(greater than)} @Defn{>= operator}@Defn2{Term=[operator],Sec=(>=)} @Defn{greater than or equal operator}@Defn2{Term=[operator],Sec=(greater than or equal)} @Defn{in (membership test)} @Defn{not in (membership test)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} @Defn{& operator}@Defn2{Term=[operator],Sec=(&)} @Defn{ampersand operator}@Defn2{Term=[operator],Sec=(ampersand)} @Defn{concatenation operator}@Defn2{Term=[operator],Sec=(concatenation)} @IndexSee{Term=[catenation operator],See=(concatenation operator)} @Defn{* operator}@Defn2{Term=[operator],Sec=(*)} @Defn{multiply operator}@Defn2{Term=[operator],Sec=(multiply)} @Defn{times operator}@Defn2{Term=[operator],Sec=(times)} @Defn{/ operator}@Defn2{Term=[operator],Sec=(/)} @Defn{divide operator}@Defn2{Term=[operator],Sec=(divide)} @Defn{mod operator}@Defn2{Term=[operator],Sec=(mod)} @Defn{rem operator}@Defn2{Term=[operator],Sec=(rem)} @Defn{** operator}@Defn2{Term=[operator],Sec=(**)} @Defn{exponentiation operator}@Defn2{Term=[operator],Sec=(exponentiation)} @Defn{abs operator}@Defn2{Term=[operator],Sec=(abs)} @Defn{absolute value} @Defn{not operator}@Defn2{Term=[operator],Sec=(not)} @end{Intro} @begin{Syntax} @Syn{tabs=[P23], lhs=<expression>,rhs=" @Syn2{relation} {@key{and} @Syn2{relation}} @\| @Syn2{relation} {@key{and} @key{then} @Syn2{relation}} | @Syn2{relation} {@key{or} @Syn2{relation}} @\| @Syn2{relation} {@key{or} @key{else} @Syn2{relation}} | @Syn2{relation} {@key{xor} @Syn2{relation}}"} @Syn{lhs=<relation>,rhs=" @Syn2{simple_expression} [@Syn2{relational_operator} @Syn2{simple_expression}] | @Syn2{simple_expression} [@key{not}] @key{in} @Syn2{range} | @Syn2{simple_expression} [@key{not}] @key{in} @Syn2{subtype_mark}"} @Syn{lhs=<simple_expression>,rhs="[@Syn2{unary_adding_operator}] @Syn2{term} {@Syn2{binary_adding_operator} @Syn2{term}}"} @Syn{lhs=<term>,rhs="@Syn2{factor} {@Syn2{multiplying_operator} @Syn2{factor}}"} @Syn{lhs=<factor>,rhs="@Syn2{primary} [** @Syn2{primary}] | @key{abs} @Syn2{primary} | @key{not} @Syn2{primary}"} @Syn{lhs=<primary>,rhs=" @Syn2{numeric_literal} | @key{null} | @Syn2{string_literal} | @Syn2{aggregate} | @Syn2{name} | @Syn2{qualified_expression} | @Syn2{allocator} | (@Syn2{expression})"} @end{Syntax} @begin{Resolution} A @nt<name> used as a @nt<primary> shall resolve to denote an object or a value. @begin{Discussion} This replaces RM83-4.4(3). We don't need to mention named numbers explicitly, because the name of a named number denotes a value. We don't need to mention attributes explicitly, because attributes now denote (rather than yield) values in general. Also, the new wording allows attributes that denote objects, which should always have been allowed (in case the implementation chose to have such a thing). @end{Discussion} @begin{Reason} It might seem odd that this is an overload resolution rule, but it is relevant during overload resolution. For example, it helps ensure that a @nt<primary> that consists of only the identifier of a parameterless function is interpreted as a @nt<function_call> rather than directly as a @nt<direct_name>. @end{Reason} @end{Resolution} @begin{StaticSem} Each expression has a type; it specifies the computation or retrieval of a value of that type. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(primary that is a name)} The value of a @nt<primary> that is a @nt{name} denoting an object is the value of the object. @end{RunTime} @begin{ImplPerm} @IndexCheck{Overflow_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} For the evaluation of a @nt<primary> that is a @nt<name> denoting an object of an unconstrained numeric subtype, if the value of the object is outside the base range of its type, the implementation may either raise Constraint_Error or return the value of the object. @begin{Ramification} This means that if extra-range intermediates are used to hold the value of an object of an unconstrained numeric subtype, a Constraint_Error can be raised on a read of the object, rather than only on an assignment to it. Similarly, it means that computing the value of an object of such a subtype can be deferred until the first read of the object (presuming no side-effects other than failing an Overflow_Check are possible). This permission is over and above that provided by clause @RefSecNum(Exceptions and Optimization), since this allows the Constraint_Error to move to a different handler. @end{Ramification} @begin{Reason} This permission is intended to allow extra-range registers to be used efficiently to hold parameters and local variables, even if they might need to be transferred into smaller registers for performing certain predefined operations. @end{Reason} @begin{Discussion} There is no need to mention other kinds of @nt<primary>s, since any Constraint_Error to be raised can be @lquotes@;charged@rquotes@; to the evaluation of the particular kind of @nt<primary>. @end{Discussion} @end{ImplPerm} @begin{Examples} @Leading@keepnext@i(Examples of primaries:) @begin{Example} @Trailing@;4.0 --@RI[ real literal] Pi --@RI[ named number] (1 .. 10 => 0) --@RI[ array aggregate] Sum --@RI[ variable] Integer'Last --@RI[ attribute] Sine(X) --@RI[ function call] Color'(Blue) --@RI[ qualified expression] Real(M*N) --@RI[ conversion] (Line_Count + 10) --@RI[ parenthesized expression ] @end{Example} @leading@keepnext@i(Examples of expressions:) @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Volume --@RI[ primary] @key(not) Destroyed --@RI[ factor] 2*Line_Count --@RI[ term] -4.0 --@RI[ simple expression] -4.0 + A --@RI[ simple expression] B**2 - 4.0*A*C --@RI[ simple expression]@Chg{Version=[2],New=[ R*Sin(@unicode<952>)*Cos(@unicode<966>) --@RI[ simple expression]],Old=[]} Password(1 .. 3) = "Bwv" --@RI[ relation] Count @key(in) Small_Int --@RI[ relation] Count @key(not) @key(in) Small_Int --@RI[ relation] Index = 0 @key(or) Item_Hit --@RI[ expression] (Cold @key(and) Sunny) @key(or) Warm --@RI[ expression (parentheses are required)] A**(B**C) --@RI[ expression (parentheses are required)] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, @key{out} parameters and their nondiscriminant subcomponents are not allowed as @ntf{primaries}. These restrictions are eliminated in Ada 95. In various contexts throughout the language where Ada 83 syntax rules had @nt<simple_expression>, the corresponding Ada 95 syntax rule has @nt<expression> instead. This reflects the inclusion of modular integer types, which makes the logical operators "@key[and]", "@key[or]", and "@key[xor]" more useful in expressions of an integer type. Requiring parentheses to use these operators in such contexts seemed unnecessary and potentially confusing. Note that the bounds of a @nt<range> still have to be specified by @nt<simple_expression>s, since otherwise @nt<expression>s involving membership tests might be ambiguous. Essentially, the operation ".." is of higher precedence than the logical operators, and hence uses of logical operators still have to be parenthesized when used in a bound of a range. @end{Extend83} @LabeledClause{Operators and Expression Evaluation} @begin{Intro} @Redundant[@Defn{precedence of operators} @Defn{operator precedence} The language defines the following six categories of operators (given in order of increasing precedence). The corresponding @nt<operator_symbol>s, and only those, can be used as @nt<designator>s in declarations of functions for user-defined operators. See @RefSec(Overloading of Operators).] @end{Intro} @begin{Syntax} @Syn{tabs=[P36], lhs=<logical_operator>, rhs="@\ @key{and} | @key{or} | @key{xor}"} @Syn{tabs=[P36], lhs=<relational_operator>,rhs="@\ = | /= | < | <= | > | >="} @Syn{tabs=[P36], lhs=<binary_adding_operator>,rhs="@\ + | @en | &"} @Syn{tabs=[P36], lhs=<unary_adding_operator>,rhs="@\ + | @en"} @Syn{tabs=[P36], lhs=<multiplying_operator>,rhs="@\ * | / | @key{mod} | @key{rem}"} @Syn{tabs=[P36], lhs=<highest_precedence_operator>,rhs="@\ ** | @key{abs} | @key{not}"} @begin(Discussion) Some of the above syntactic categories are not used in other syntax rules. They are just used for classification. The others are used for both classification and parsing. @end(Discussion) @end{Syntax} @begin{StaticSem} For a sequence of operators of the same precedence level, the operators are associated with their operands in textual order from left to right. Parentheses can be used to impose specific associations. @begin{Discussion} The left-associativity is not directly inherent in the grammar of @RefSecNum{Expressions}, though in @RefSecNum{Method of Description and Syntax Notation} the definition of the metasymbols @b({}) implies left associativity. So this could be seen as redundant, depending on how literally one interprets the definition of the @b({}) metasymbols. See the Implementation Permissions below regarding flexibility in reassociating operators of the same precedence. @end{Discussion} @Defn{predefined operator}@Defn2{Term=[operator],Sec=(predefined)} For each form of type definition, certain of the above operators are @i(predefined); that is, they are implicitly declared immediately after the type definition. @Defn{binary operator}@Defn2{Term=[operator],Sec=(binary)} @Defn{unary operator}@Defn2{Term=[operator],Sec=(unary)} For each such implicit operator declaration, the parameters are called Left and Right for @i(binary) operators; the single parameter is called Right for @i(unary) operators. @redundant[An expression of the form X op Y, where op is a binary operator, is equivalent to a @nt<function_call> of the form "op"(X, Y). An expression of the form op Y, where op is a unary operator, is equivalent to a @nt<function_call> of the form "op"(Y). The predefined operators and their effects are described in subclauses @RefSecNum(Logical Operators and Short-Circuit Control Forms) through @RefSecNum(Highest Precedence Operators).] @end{StaticSem} @begin{RunTime} @redundant[@Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The predefined operations on integer types either yield the mathematically correct result or raise the exception Constraint_Error. For implementations that support the Numerics Annex, the predefined operations on real types yield results whose accuracy is defined in @RefSecNum(Numerics), or raise the exception Constraint_Error. ] @begin{Honest} Predefined operations on real types can @lquotes@;silently@rquotes@; give wrong results when the Machine_Overflows attribute is false, and the computation overflows. @end{Honest} @end{RunTime} @begin{ImplReq} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of a predefined operator that delivers a result of an integer or fixed point type may raise Constraint_Error only if the result is outside the base range of the result type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of a predefined operator that delivers a result of a floating point type may raise Constraint_Error only if the result is outside the safe range of the result type. @begin{Honest} An exception is made for exponentiation by a negative exponent in @RefSecNum{Highest Precedence Operators}. @end{Honest} @end{ImplReq} @begin{ImplPerm} For a sequence of predefined operators of the same precedence level (and in the absence of parentheses imposing a specific association), an implementation may impose any association of the operators with operands so long as the result produced is an allowed result for the left-to-right association, but ignoring the potential for failure of language-defined checks in either the left-to-right or chosen order of association. @begin{Discussion} Note that the permission to reassociate the operands in any way subject to producing a result allowed for the left-to-right association is not much help for most floating point operators, since reassociation may introduce significantly different round-off errors, delivering a result that is outside the model interval for the left-to-right association. Similar problems arise for division with integer or fixed point operands. Note that this permission does not apply to user-defined operators. @end{Discussion} @end{ImplPerm} @begin{Notes} The two operands of an expression of the form X op Y, where op is a binary operator, are evaluated in an arbitrary order, as for any @nt<function_call> (see @RefSecNum(Subprogram Calls)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of precedence:) @begin{Example} @key(not) Sunny @key(or) Warm --@RI[ same as (not Sunny) or Warm] X > 4.0 @key(and) Y > 0.0 --@RI[ same as (X > 4.0) and (Y > 0.0)] -4.0*A**2 --@RI[ same as @en@;(4.0 * (A**2))] @key(abs)(1 + A) + B --@RI[ same as (abs (1 + A)) + B] Y**(-3) --@RI[ parentheses are necessary] A / B * C --@RI[ same as (A/B)*C] A + (B + C) --@RI[ evaluate B + C before adding it to A ] @end{Example} @end{Examples} @begin{DiffWord83} We don't give a detailed definition of precedence, since it is all implicit in the syntax rules anyway. The permission to reassociate is moved here from RM83-11.6(5), so it is closer to the rules defining operator association. @end{DiffWord83} @LabeledSubClause{Logical Operators and Short-circuit Control Forms} @begin{Resolution} @Defn{short-circuit control form} @Defn{and then (short-circuit control form)} @Defn{or else (short-circuit control form)} An @nt<expression> consisting of two @nt<relation>s connected by @key(and then) or @key(or else) (a @i(short-circuit control form)) shall resolve to be of some boolean type; @PDefn2{Term=[expected type],Sec=(short-circuit control form relation)} the expected type for both @nt<relation>s is that same boolean type. @begin(Reason) This rule is written this way so that overload resolution treats the two operands symmetrically; the resolution of overloading present in either one can benefit from the resolution of the other. Furthermore, the type expected by context can help. @end(Reason) @end{Resolution} @begin{StaticSem} @Leading@Defn{logical operator}@Defn2{Term=[operator],Sec=(logical)} @Defn{and operator}@Defn2{Term=[operator],Sec=(and)} @Defn{or operator}@Defn2{Term=[operator],Sec=(or)} @Defn{xor operator}@Defn2{Term=[operator],Sec=(xor)} The following logical operators are predefined for every boolean type @i(T), for every modular type @i(T), and for every one-dimensional array type @i(T) whose component type is a boolean type: @IndexSee{Term=[bit string],See=(logical operators on boolean arrays)} @begin{example} @tabclear() @key[function] "@key(and)"(Left, Right : @RI(T)) @key[return] @RI(T) @key[function] "@key(or)" (Left, Right : @RI(T)) @key[return] @RI(T) @key[function] "@key(xor)"(Left, Right : @RI(T)) @key[return] @RI(T) @end{example} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00145-01]} @ChgDeleted{Version=[2],Text=[For predefined operators, the parameter and result subtypes shown as @i(T) are actually the unconstrained subtype of the type.]} @ChgNote{Sorry, Bob, but there is no "honesty" issue here. And "unconstrained" is wrong.} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[For these operators, we are talking about the type without any (interesting) subtype, and not some subtype with a constraint or exclusion. Since it's possible that there is no name for the @lquotes@;uninteresting@rquotes subtype, we denote the type with an italicized @i(T). This applies to the italicized @i(T) in many other predefined operators and attributes as well.@Defn2{Term=[T],Sec=[italicized]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[In many cases, there is a subtype with the correct properties available. The italicized @i(T) means:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i(T)'Base, for scalars;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the first subtype of @i(T), for tagged types;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a subtype of the type @i(T) without any constraint or null exclusion, in other cases.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that @lquotes@;without a constraint@rquotes is not the same as unconstrained. For instance, a record type with no discriminant part is considered constrained; no subtype of it has a constraint, but the subtype is still constrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, the last case often is the same as the first subtype of @i(T), but that isn't the case for constrained array types (where the correct subtype is unconstrained) and for access types with a @nt{null_exclusion} (where the correct subtype does not exclude null).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This italicized @i(T) is used for defining operators and attributes of the language. The meaning is intended to be as described here.]} @end{Ramification} For boolean types, the predefined logical operators @key{and}, @key{or}, and @key{xor} perform the conventional operations of conjunction, inclusive disjunction, and exclusive disjunction, respectively. For modular types, the predefined logical operators are defined on a bit-by-bit basis, using the binary representation of the value of the operands to yield a binary representation for the result, where zero represents False and one represents True. If this result is outside the base range of the type, a final subtraction by the modulus is performed to bring the result into the base range of the type. The logical operators on arrays are performed on a component-by-component basis on matching components (as for equality @em see @RefSecNum{Relational Operators and Membership Tests}), using the predefined logical operator for the component type. The bounds of the resulting array are those of the left operand. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(short-circuit control form)} The short-circuit control forms @key{and then} and @key{or else} deliver the same result as the corresponding predefined @key{and} and @key{or} operators for boolean types, except that the left operand is always evaluated first, and the right operand is not evaluated if the value of the left operand determines the result. @IndexCheck{Length_Check} For the logical operators on arrays, a check is made that for each component of the left operand there is a matching component of the right operand, and vice versa. @IndexCheck{Range_Check} Also, a check is made that each component of the result belongs to the component subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if either of the above checks fails. @begin{Discussion} The check against the component subtype is per AI83-00535. @end{Discussion} @end{RunTime} @begin{Notes} @Leading@;The conventional meaning of the logical operators is given by the following truth table: @begin(Display) @TabClear() @TabSet(P4, P20, P36, P52, P68) @\@ @ A@\@ @ B@\(A @key(and) B)@\(A @key(or) B)@\(A @key(xor) B)@* @\True @\True @\True @\True @\False @\True @\False @\False @\True @\True @\False @\True @\False @\True @\True @\False @\False @\False @\False @\False @end(Display) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of logical operators:) @begin{Example} Sunny @key(or) Warm Filter(1 .. 10) @key(and) Filter(15 .. 24) --@RI[ see @RefSecNum{Index Constraints and Discrete Ranges} ] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of short-circuit control forms:) @end{Wide} @begin{Example} Next_Car.Owner /= @key(null) @key(and) @key(then) Next_Car.Owner.Age > 25 --@RI[ see @RefSecNum{Incomplete Type Declarations}] N = 0 @key(or) @key(else) A(N) = Hit_Value @end{Example} @end{Examples} @LabeledSubClause{Relational Operators and Membership Tests} @begin{Intro} @redundant[@Defn{relational operator}@Defn2{Term=[operator],Sec=(relational)} @IndexSee{Term=[comparison operator],See=(relational operator)} @Defn{equality operator}@Defn2{Term=[operator],Sec=(equality)} The @i(equality operators) = (equals) and /= (not equals) are predefined for nonlimited types. @Defn{ordering operator}@Defn2{Term=[operator],Sec=(ordering)} The other @nt<relational_operator>s are the @i(ordering operators) < (less than), <= (less than or equal), > (greater than), and >= (greater than or equal). @Defn{= operator}@Defn2{Term=[operator],Sec=(=)} @Defn{equal operator}@Defn2{Term=[operator],Sec=(equal)} @Defn{/= operator}@Defn2{Term=[operator],Sec=(/=)} @Defn{not equal operator}@Defn2{Term=[operator],Sec=(not equal)} @Defn{< operator}@Defn2{Term=[operator],Sec=(<)} @Defn{less than operator}@Defn2{Term=[operator],Sec=(less than)} @Defn{<= operator}@Defn2{Term=[operator],Sec=(<=)} @Defn{less than or equal operator}@Defn2{Term=[operator],Sec=(less than or equal)} @Defn{> operator}@Defn2{Term=[operator],Sec=(>)} @Defn{greater than operator}@Defn2{Term=[operator],Sec=(greater than)} @Defn{>= operator}@Defn2{Term=[operator],Sec=(>=)} @Defn{greater than or equal operator}@Defn2{Term=[operator],Sec=(greater than or equal)} @Defn{discrete array type} The ordering operators are predefined for scalar types, and for @i(discrete array types), that is, one-dimensional array types whose components are of a discrete type. @begin{Ramification} The equality operators are not defined for @i{every} nonlimited type @em see below for the exact rule. @end{Ramification} @Defn{membership test} @Defn{in (membership test)} @Defn{not in (membership test)} A @i(membership test), using @key(in) or @key(not in), determines whether or not a value belongs to a given subtype or range, or has a tag that identifies a type that is covered by a given type. Membership tests are allowed for all types.] @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @PDefn2{Term=[expected type], Sec=(membership test simple_expression)} @Defn2{Term=[tested type], Sec=(of a membership test)} The @i(tested type) of a membership test is the type of the @nt<range> or the type determined by the @nt<subtype_mark>. If the tested type is tagged, then the @nt<simple_expression> shall resolve to be of a type that @Chg{Version=[2],New=[is convertible (see @RefSecNum{Type Conversions}) to],Old=[covers or is covered by]} the tested type; if untagged, the expected type for the @nt<simple_expression> is the tested type. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The part of the rule for untagged types is stated in a way that ensures that operands like @Chg{Version=[2],New=[a string literal],Old=[@key(null)]} are still legal as operands of a membership test. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The significance of @lquotes@;@Chg{Version=[2],New=[is convertible to], Old=[covers or is covered by]}@rquotes@; is that we allow the @nt<simple_expression> to be of any class-wide type that @Chg{Version=[2], New=[could be converted to],Old=[covers]} the tested type, not just the one rooted at the tested type.@Chg{Version=[2],New=[ This includes any class-wide type that covers the tested type, along with class-wide interfaces in some cases.],Old=[]} @end{Reason} @end{Resolution} @begin{Legality} For a membership test, if the @nt<simple_expression> is of a tagged class-wide type, then the tested type shall be (visibly) tagged. @begin{Ramification} Untagged types covered by the tagged class-wide type are not permitted. Such types can exist if they are descendants of a private type whose full type is tagged. This rule is intended to avoid confusion since such derivatives don't have their @lquotes@;own@rquotes@; tag, and hence are indistinguishable from one another at run time once converted to a covering class-wide type. @end{Ramification} @end{Legality} @begin{StaticSem} The result type of a membership test is the predefined type Boolean. @Leading@;The equality operators are predefined for every specific type @i(T) that is not limited, and not an anonymous access type, with the following specifications: @begin(example) @key(function) "=" (Left, Right : @RI(T)) @key(return) Boolean @key(function) "/="(Left, Right : @RI(T)) @key(return) Boolean @end(example) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following additional equality operators for the @i<universal_access> type are declared in package Standard for use with anonymous access types:]} @begin(example) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> "=" (Left, Right : @i<universal_access>) @key<return> Boolean @key<function> "/="(Left, Right : @i<universal_access>) @key<return> Boolean]} @end(example) @Leading@;The ordering operators are predefined for every specific scalar type @i(T), and for every discrete array type @i(T), with the following specifications: @begin(example) @key(function) "<" (Left, Right : @RI(T)) @key(return) Boolean @key(function) "<="(Left, Right : @RI(T)) @key(return) Boolean @key(function) ">" (Left, Right : @RI(T)) @key(return) Boolean @key(function) ">="(Left, Right : @RI(T)) @key(return) Boolean @end(example) @end{StaticSem} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[At least one of the operands of an equality operator for @i<universal_access> shall be of a specific anonymous access type. Unless the predefined equality operator is identified using an expanded name with @nt{prefix} denoting the package Standard, neither operand shall be of an access-to-object type whose designated type is @i<D> or @i<D>'Class, where @i<D> has a user-defined primitive equality operator such that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[its result type is Boolean;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is declared immediately within the same declaration list as @i<D>; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[at least one of its operands is an access parameter with designated type @i<D>.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The first sentence prevents compatibility problems by ensuring that these operators are not used for named access types. Also, universal access types do not count for the purposes of this rule. Otherwise, equality expressions like (X = @key{null}) would be ambiguous for normal access types.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rest of the rule makes it possible to call (including a dispatching call) user-defined "=" operators for anonymous access-to-object types (they'd be hidden otherwise), and to write user-defined "=" operations for anonymous access types (by making it possible to see the universal operator using the Standard prefix).]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't need a similar rule for anonymous access-to-subprogram types because they can't be primitive for any type. Note that any non-primitive user-defined equality operators still are hidden by the universal operators; they'll have to be called with a package prefix, but they are likely to be very uncommon.]} @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[At least one of the operands of the equality operators for @i<universal_access> shall be of type @i<universal_access>, or both shall be of access-to-object types, or both shall be of access-to-subprogram types. Further:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[When both are of access-to-object types, the designated types shall be the same or one shall cover the other, and if the designated types are elementary or array types, then the designated subtypes shall statically match;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[When both are of access-to-subprogram types, the designated profiles shall be subtype conformant.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't want to allow completely arbitrary comparisons, as we don't want to insist that all access types are represented in ways that are convertible to one another. For instance, a compiler could use completely separate address spaces or incompatible representations. Instead, we allow compares if there exists an access parameter to which both operands could be converted. Since the user could write such an subprogram, and any reasonable meaning for "=" would allow using it in such a subprogram, this doesn't impose any further restrictions on Ada implementations.]} @end{Reason} @end{Legality} @begin{RunTime} For discrete types, the predefined relational operators are defined in terms of corresponding mathematical operations on the position numbers of the values of the operands. For real types, the predefined relational operators are defined in terms of the corresponding mathematical operations on the values of the operands, subject to the accuracy of the type. @begin{Ramification} For floating point types, the results of comparing @i(nearly) equal values depends on the accuracy of the implementation (see @RefSec{Model of Floating Point Arithmetic} for implementations that support the Numerics Annex). @end{Ramification} @begin{ImplNote} On a machine with signed zeros, if the generated code generates both plus zero and minus zero, plus and minus zero must be equal by the predefined equality operators. @end{ImplNote} Two access-to-object values are equal if they designate the same object, or if both are equal to the null value of the access type. Two access-to-subprogram values are equal if they are the result of the same evaluation of an Access @nt<attribute_reference>, or if both are equal to the null value of the access type. Two access-to-subprogram values are unequal if they designate different subprograms. @PDefn{unspecified} @Redundant[It is unspecified whether two access values that designate the same subprogram but are the result of distinct evaluations of Access @nt<attribute_reference>s are equal or unequal.] @begin{Reason} This allows each Access @nt<attribute_reference> for a subprogram to designate a distinct @lquotes@;wrapper@rquotes@; subprogram if necessary to support an indirect call. @end{Reason} @Defn2{Term=[equality operator],Sec=(special inheritance rule for tagged types)} For a type extension, predefined equality is defined in terms of the primitive @Redundant[(possibly user-defined)] equals operator of the parent type and of any tagged components of the extension part, and predefined equality for any other components not inherited from the parent type. @begin{Ramification} Two values of a type extension are not equal if there is a @nt<variant_part> in the extension part and the two values have different @nt<variant>s present. This is a ramification of the requirement that a discriminant governing such a @nt<variant_part> has to be a @lquotes@;new@rquotes@; discriminant, and so has to be equal in the two values for the values to be equal. Note that @nt<variant_part>s in the parent part need not match if the primitive equals operator for the parent type considers them equal. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00349-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The full type extension's operation is used for a private extension. This follows as only full types have parent types; the type specified in a private extension is an ancestor, but not necessarily the parent type. For instance, in:]} @begin(Example) @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{with} Pak1; @key{package} Pak2 @key{is} @key{type} Typ3 @key{is} @key{new} Pak1.Typ1 @key{with} @key{private}; @key{private} @key{type} Typ3 @key{is} @key{new} Pak1.Typ2 @key{with} @key{null} @key{record}; @key{end} Pak2;],Old=[]} @end(Example) @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[the parent type is Pak1.Typ2, not Pak1.Typ1, and the equality operator of Pak1.Typ2 is used to create predefined equality for Typ3.],Old=[]} @end{Ramification} For a private type, if its full type is tagged, predefined equality is defined in terms of the primitive equals operator of the full type; if the full type is untagged, predefined equality for the private type is that of its full type. @Leading@Defn{matching components} For other composite types, the predefined equality operators @Redundant[(and certain other predefined operations on composite types @em see @RefSecNum(Logical Operators and Short-circuit Control Forms) and @RefSecNum(Type Conversions))] are defined in terms of the corresponding operation on @i(matching components), defined as follows: @begin(itemize) For two composite objects or values of the same non-array type, matching components are those that correspond to the same @nt<component_declaration> or @nt<discriminant_specification>; For two one-dimensional arrays of the same type, matching components are those (if any) whose index values match in the following sense: the lower bounds of the index ranges are defined to match, and the successors of matching indices are defined to match; For two multidimensional arrays of the same type, matching components are those whose index values match in successive index positions. @end(itemize) The analogous definitions apply if the types of the two objects or values are convertible, rather than being the same. @begin{Discussion} Ada 83 seems to omit this part of the definition, though it is used in array type conversions. See @RefSecNum{Type Conversions}. @end{Discussion} @Leading@;Given the above definition of matching components, the result of the predefined equals operator for composite types (other than for those composite types covered earlier) is defined as follows: @begin(Itemize) If there are no components, the result is defined to be True; If there are unmatched components, the result is defined to be False; Otherwise, the result is defined in terms of the primitive equals operator for any matching tagged components, and the predefined equals for any matching untagged components. @begin{Reason} This asymmetry between tagged and untagged components is necessary to preserve upward compatibility and corresponds with the corresponding situation with generics, where the predefined operations @lquotes@;reemerge@rquotes@; in a generic for untagged types, but do not for tagged types. Also, only tagged types support user-defined assignment (see @RefSecNum{User-Defined Assignment and Finalization}), so only tagged types can fully handle levels of indirection in the implementation of the type. For untagged types, one reason for a user-defined equals operator might be to allow values with different bounds or discriminants to compare equal in certain cases. When such values are matching components, the bounds or discriminants will necessarily match anyway if the discriminants of the enclosing values match. @end{Reason} @end(Itemize) @begin{Ramification} Two null arrays of the same type are always equal; two null records of the same type are always equal. Note that if a composite object has a component of a floating point type, and the floating point type has both a plus and minus zero, which are considered equal by the predefined equality, then a block compare cannot be used for the predefined composite equality. Of course, with user-defined equals operators for tagged components, a block compare breaks down anyway, so this is not the only special case that requires component-by-component comparisons. On a one's complement machine, a similar situation might occur for integer types, since one's complement machines typically have both a plus and minus (integer) zero. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For a component with an anonymous access type, @lquotes@;predefined equality@rquotes@; is that defined for the @i<universal_access> type (anonymous access types have no equality operators of their own).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For a component with a tagged type @i{T}, @lquotes@;the primitive equals operator@rquotes@; is the one with two parameters of @i(T) which returns Boolean. We're not talking about some random other primitive function named "=".]} @end{Honest} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0016],ARef=[AI95-00123-01]} @ChgAdded{Version=[1],Text=[For any composite type, the order in which "=" is called for components is unspecified. Furthermore, if the result can be determined before calling "=" on some components, it is unspecified whether "=" is called on those components.@PDefn{Unspecified}]} The predefined "/=" operator gives the complementary result to the predefined "=" operator. @begin{Ramification} Furthermore, if the user defines an "=" operator that returns Boolean, then a "/=" operator is implicitly declared in terms of the user-defined "=" operator so as to give the complementary result. See @RefSecNum(Overloading of Operators). @end{Ramification} @Defn{lexicographic order} For a discrete array type, the predefined ordering operators correspond to @i(lexicographic order) using the predefined order relation of the component type: A null array is lexicographically less than any array having at least one component. In the case of nonnull arrays, the left operand is lexicographically less than the right operand if the first component of the left operand is less than that of the right; otherwise the left operand is lexicographically less than the right operand only if their first components are equal and the tail of the left operand is lexicographically less than that of the right (the @i(tail) consists of the remaining components beyond the first and can be null). @PDefn2{Term=[evaluation], Sec=(membership test)} For the evaluation of a membership test, the @nt<simple_expression> and the @nt<range> (if any) are evaluated in an arbitrary order. @Leading@;A membership test using @key(in) yields the result True if: @begin(itemize) The tested type is scalar, and the value of the @nt<simple_expression> belongs to the given @nt<range>, or the range of the named subtype; or @begin{Ramification} The scalar membership test only does a range check. It does not perform any other check, such as whether a value falls in a @lquotes@;hole@rquotes@; of a @lquotes@;holey@rquotes@; enumeration type. The Pos attribute function can be used for that purpose. Even though Standard.Float is an unconstrained subtype, the test @lquotes@;X in Float@rquotes@; will still return False (presuming the evaluation of X does not raise Constraint_Error) when X is outside Float'Range. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{To get conditional Leading} The tested type is not scalar, and the value of the @nt<simple_expression> satisfies any constraints of the named subtype, and@Chg{Version=[2],New=[:],Old=[, if the type of the @nt{simple_expression} is class-wide, the value has a tag that identifies a type covered by the tested type.]} @begin{Inneritemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[if the type of the @nt{simple_expression} is class-wide, the value has a tag that identifies a type covered by the tested type;]} @begin{Ramification} Note that the tag is not checked if the @nt{simple_expression} is of a specific type. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[if the tested type is an access type and the named subtype excludes null, the value of the @nt{simple_expression} is not null.]} @end{Inneritemize} @end(itemize) Otherwise the test yields the result False. A membership test using @key(not in) gives the complementary result to the corresponding membership test using @key(in). @end{RunTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0016],ARef=[AI95-00123-01]} @ChgAdded{Version=[1],Text=[For all nonlimited types declared in language-defined packages, the "=" and "/=" operators of the type shall behave as if they were the predefined equality operators for the purposes of the equality of composite types and generic formal types.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[If any language-defined types are implemented with a user-defined "=" operator, then either the full type must be tagged, or the compiler must use @lquotes@;magic@rquotes@; to implement equality for this type. A normal user-defined "=" operator for an untagged type does @i{not} meet this requirement.]} @end{Ramification} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgDeleted{Version=[2],Text=[No exception is ever raised by a membership test, by a predefined ordering operator, or by a predefined equality operator for an elementary type, but an exception can be raised by the evaluation of the operands. A predefined equality operator for a composite type can only raise an exception if the type has a tagged part whose primitive equals operator propagates an exception.]} If a composite type has components that depend on discriminants, two values of this type have matching components if and only if their discriminants are equal. Two nonnull arrays have matching components if and only if the length of each dimension is the same for both. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving relational operators and membership tests:) @begin{Example} X /= Y "" < "A" @key(and) "A" < "Aa" --@RI[ True] "Aa" < "B" @key(and) "A" < "A " --@RI[ True] My_Car = @key(null) --@RI[ true if My_Car has been set to null (see @RefSecNum{Incomplete Type Declarations})] My_Car = Your_Car --@RI[ true if we both share the same car] My_Car.@key[all] = Your_Car.@key[all] --@RI[ true if the two cars are identical] N @key(not) @key(in) 1 .. 10 --@RI[ range membership test] Today @key(in) Mon .. Fri --@RI[ range membership test] Today @key(in) Weekday --@RI[ subtype membership test (see @RefSecNum{Enumeration Types})] Archive @key(in) Disk_Unit --@RI[ subtype membership test (see @RefSecNum{Variant Parts and Discrete Choices})] Tree.@key(all) @key(in) Addition'Class --@RI[ class membership test (see @RefSecNum{Type Extensions})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Membership tests can be used to test the tag of a class-wide value. Predefined equality for a composite type is defined in terms of the primitive equals operator for tagged components or the parent part. @end{Extend83} @begin{DiffWord83} The term @lquotes@;membership test@rquotes@; refers to the @nt<relation> "X in S" rather to simply the reserved word @key(in) or @key(not in). We use the term @lquotes@;equality operator@rquotes@; to refer to both the = (equals) and /= (not equals) operators. Ada 83 referred to = as @i(the) equality operator, and /= as the inequality operator. The new wording is more consistent with the ISO 10646 name for "=" (equals sign) and provides a category similar to @lquotes@;ordering operator@rquotes@; to refer to both = and /=. We have changed the term @lquotes@;catenate@rquotes@; to @lquotes@;concatenate@rquotes@;. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00420-01]} @Chg{Version=[2],New=[@Defn{extensions to Ada 95}The @i{universal_access} equality operators are new. They provide equality operations (most importantly, testing against @key{null}) for anonymous access types.],Old=[]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0016],ARef=[AI95-00123-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Wording was added to clarify that the order of calls (and whether the calls are made at all) on "=" for components is unspecified. Also clarified that "=" must compose properly for language-defined types.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[Memberships were adjusted to allow interfaces which don't cover the tested type, in order to be consistent with type conversions.],Old=[]} @end{DiffWord95} @LabeledSubClause{Binary Adding Operators} @begin{StaticSem} @Leading@Defn{binary adding operator}@Defn2{Term=[operator],Sec=(binary adding)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} The binary adding operators + (addition) and @en (subtraction) are predefined for every specific numeric type @i(T) with their conventional meaning. They have the following specifications: @begin(example) @key(function) "+"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "-"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@Defn{& operator}@Defn2{Term=[operator],Sec=(&)} @Defn{ampersand operator}@Defn2{Term=[operator],Sec=(ampersand)} @Defn{concatenation operator}@Defn2{Term=[operator],Sec=(concatenation)} @IndexSee{Term=[catenation operator],See=(concatenation operator)} The concatenation operators & are predefined for every nonlimited, one-dimensional array type @i(T) with component type @i(C). They have the following specifications: @begin(example) @key(function) "&"(Left : @RI(T); Right : @RI(T)) @key(return) @RI(T) @key(function) "&"(Left : @RI(T); Right : @RI(C)) @key(return) @RI(T) @key(function) "&"(Left : @RI(C); Right : @RI(T)) @key(return) @RI(T) @key(function) "&"(Left : @RI(C); Right : @RI(C)) @key(return) @RI(T) @end(example) @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(concatenation)} For the evaluation of a concatenation with result type @i(T), if both operands are of type @i(T), the result of the concatenation is a one-dimensional array whose length is the sum of the lengths of its operands, and whose components comprise the components of the left operand followed by the components of the right operand. If the left operand is a null array, the result of the concatenation is the right operand. Otherwise, the lower bound of the result is determined as follows: @begin(Itemize) If the ultimate ancestor of the array type was defined by a @nt<constrained_array_definition>, then the lower bound of the result is that of the index subtype; @begin(Reason) This rule avoids Constraint_Error when using concatenation on an array type whose first subtype is constrained. @end(Reason) If the ultimate ancestor of the array type was defined by an @nt<unconstrained_array_definition>, then the lower bound of the result is that of the left operand. @end(Itemize) @Redundant[The upper bound is determined by the lower bound and the length.] @IndexCheck{Index_Check} A check is made that the upper bound of the result of the concatenation belongs to the range of the index subtype, unless the result is a null array. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. If either operand is of the component type @i(C), the result of the concatenation is given by the above rules, using in place of such an operand an array having this operand as its only component (converted to the component subtype) and having the lower bound of the index subtype of the array type as its lower bound. @PDefn2{Term=[implicit subtype conversion],Sec=(operand of concatenation)} @begin{Ramification} The conversion might raise Constraint_Error. The conversion provides @lquotes@;sliding@rquotes@; for the component in the case of an array-of-arrays, consistent with the normal Ada 95 rules that allow sliding during parameter passing. @end{Ramification} @Defn2{Term=[assignment operation], Sec=(during evaluation of concatenation)} The result of a concatenation is defined in terms of an assignment to an anonymous object, as for any function call (see @RefSecNum{Return Statements}). @begin{Ramification} This implies that value adjustment is performed as appropriate @em see @RefSecNum{User-Defined Assignment and Finalization}. We don't bother saying this for other predefined operators, even though they are all function calls, because this is the only one where it matters. It is the only one that can return a value having controlled parts. @end{Ramification} @end{RunTime} @begin{Notes} As for all predefined operators on modular types, the binary adding operators + and @en on modular types include a final reduction modulo the modulus if the result is outside the base range of the type. @begin{ImplNote} A full "modulus" operation need not be performed after addition or subtraction of modular types. For binary moduli, a simple mask is sufficient. For nonbinary moduli, a check after addition to see if the value is greater than the high bound of the base range can be followed by a conditional subtraction of the modulus. Conversely, a check after subtraction to see if a "borrow" was performed can be followed by a conditional addition of the modulus. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving binary adding operators:) @begin{Example} Z + 0.1 --@RI[ Z has to be of a real type ] "A" & "BCD" --@RI[ concatenation of two string literals] 'A' & "BCD" --@RI[ concatenation of a character literal and a string literal] 'A' & 'A' --@RI[ concatenation of two character literals ] @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The lower bound of the result of concatenation, for a type whose first subtype is constrained, is now that of the index subtype. This is inconsistent with Ada 83, but generally only for Ada 83 programs that raise Constraint_Error. For example, the concatenation operator in @begin(Example) X : @key(array)(1..10) @key(of) Integer; @key(begin) X := X(6..10) & X(1..5); @end(Example) would raise Constraint_Error in Ada 83 (because the bounds of the result of the concatenation would be 6..15, which is outside of 1..10), but would succeed and swap the halves of X (as expected) in Ada 95. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Concatenation is now useful for array types whose first subtype is constrained. When the result type of a concatenation is such an array type, Constraint_Error is avoided by effectively first sliding the left operand (if nonnull) so that its lower bound is that of the index subtype. @end{Extend83} @LabeledSubClause{Unary Adding Operators} @begin{StaticSem} @Leading@Defn{unary adding operator}@Defn2{Term=[operator],Sec=(unary adding)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} The unary adding operators + (identity) and @en (negation) are predefined for every specific numeric type @i(T) with their conventional meaning. They have the following specifications: @begin(example) @key(function) "+"(Right : @RI(T)) @key(return) @RI(T) @key(function) "-"(Right : @RI(T)) @key(return) @RI(T) @end(example) @end{StaticSem} @begin{Notes} For modular integer types, the unary adding operator @en, when given a nonzero operand, returns the result of subtracting the value of the operand from the modulus; for a zero operand, the result is zero. @end{Notes} @LabeledSubClause{Multiplying Operators} @begin{StaticSem} @Leading@Defn{multiplying operator}@Defn2{Term=[operator],Sec=(multiplying)} @Defn{* operator}@Defn2{Term=[operator],Sec=(*)} @Defn{multiply operator}@Defn2{Term=[operator],Sec=(multiply)} @Defn{times operator}@Defn2{Term=[operator],Sec=(times)} @Defn{/ operator}@Defn2{Term=[operator],Sec=(/)} @Defn{divide operator}@Defn2{Term=[operator],Sec=(divide)} @Defn{mod operator}@Defn2{Term=[operator],Sec=(mod)} @Defn{rem operator}@Defn2{Term=[operator],Sec=(rem)} The multiplying operators * (multiplication), / (division), @key(mod) (modulus), and @key(rem) (remainder) are predefined for every specific integer type @i(T): @begin(example) @key(function) "*" (Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "/" (Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "@key(mod)"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "@key(rem)"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) Signed integer multiplication has its conventional meaning. @Leading@keepnext@;Signed integer division and remainder are defined by the relation: @begin(example) A = (A/B)*B + (A @key(rem) B) @end(example) @Leading@;where (A @key(rem) B) has the sign of A and an absolute value less than the absolute value of B. Signed integer division satisfies the identity: @begin(example) (-A)/B = -(A/B) = A/(-B) @end(example) @begin{Wide} @Leading@;The signed integer modulus operator is defined such that the result of A @key(mod) B has the sign of B and an absolute value less than the absolute value of B; in addition, for some signed integer value N, this result satisfies the relation: @begin(example) A = B*N + (A @key(mod) B) @end(example) The multiplying operators on modular types are defined in terms of the corresponding signed integer operators@Redundant[, followed by a reduction modulo the modulus if the result is outside the base range of the type] @Redundant[(which is only possible for the "*" operator)]. @begin{Ramification} The above identity satisfied by signed integer division is not satisfied by modular division because of the difference in effect of negation. @end{Ramification} @end{Wide} @Leading@;Multiplication and division operators are predefined for every specific floating point type @i(T): @begin(example) @key(function) "*"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "/"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@;The following multiplication and division operators, with an operand of the predefined type Integer, are predefined for every specific fixed point type @i(T): @begin(example) @key(function) "*"(Left : @RI(T); Right : Integer) @key(return) @RI(T) @key(function) "*"(Left : Integer; Right : @RI(T)) @key(return) @RI(T) @key(function) "/"(Left : @RI(T); Right : Integer) @key(return) @RI(T) @end(example) @Leading@Redundant[All of the above multiplying operators are usable with an operand of an appropriate universal numeric type.] The following additional multiplying operators for @i(root_real) are predefined@Redundant[, and are usable when both operands are of an appropriate universal or root numeric type, and the result is allowed to be of type @i(root_real), as in a @nt<number_declaration>]: @begin{Ramification} These operators are analogous to the multiplying operators involving fixed or floating point types where @i(root_real) substitutes for the fixed or floating point type, and @i(root_integer) substitutes for Integer. Only values of the corresponding universal numeric types are implicitly convertible to these root numeric types, so these operators are really restricted to use with operands of a universal type, or the specified root numeric types. @end{Ramification} @begin(example) @key(function) "*"(Left, Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "/"(Left, Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "*"(Left : @RI(root_real); Right : @RI(root_integer)) @key(return) @RI(root_real) @key(function) "*"(Left : @RI(root_integer); Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "/"(Left : @RI(root_real); Right : @RI(root_integer)) @key(return) @RI(root_real) @end(example) @Leading@;Multiplication and division between any two fixed point types are provided by the following two predefined operators: @begin{Ramification} @i(Universal_fixed) is the universal type for the class of fixed point types, meaning that these operators take operands of any fixed point types (not necessarily the same) and return a result that is implicitly (or explicitly) convertible to any fixed point type. @end{Ramification} @begin(example) @key(function) "*"(Left, Right : @RI(universal_fixed)) @key(return) @RI(universal_fixed) @key(function) "/"(Left, Right : @RI(universal_fixed)) @key(return) @RI(universal_fixed) @end(example) @end{StaticSem} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The above two fixed-fixed multiplying operators shall not be used in a context where the expected type for the result is itself @i(universal_fixed) @Redundant[@em the context has to identify some other numeric type to which the result is to be converted, either explicitly or implicitly]. Unless the predefined universal operator is identified using an expanded name with @nt{prefix} denoting the package Standard, an explicit conversion is required on the result when using the above fixed-fixed multiplication operator if either operand is of a type having a user-defined primitive multiplication operator such that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is declared immediately within the same declaration list as the type; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[both of its formal parameters are of a fixed-point type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[A corresponding requirement applies to the universal fixed-fixed division operator.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @i(small) of @i(universal_fixed) is infinitesimal; no loss of precision is permitted. However, fixed-fixed division is impractical to implement when an exact result is required, and multiplication will sometimes result in unanticipated overflows in such circumstances, so we require an explicit conversion to be inserted in expressions like A * B * C if A, B, and C are each of some fixed point type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[On the other hand, X := A * B; is permitted by this rule, even if X, A, and B are all of different fixed point types, since the expected type for the result of the multiplication is the type of X, which is necessarily not @i(universal_fixed).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[We have made these into Name Resolution rules to ensure that user-defined primitive fixed-fixed operators are not made unusable due to the presence of these universal fixed-fixed operators. But we do allow these operators to be used if prefixed by package Standard, so that they can be used in the definitions of user-defined operators.]} @end(Discussion) @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00364-01]} @ChgDeleted{Version=[2],Text=[The above two fixed-fixed multiplying operators shall not be used in a context where the expected type for the result is itself @i(universal_fixed) @em @Redundant[the context has to identify some other numeric type to which the result is to be converted, either explicitly or implicitly].]} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The @i(small) of @i(universal_fixed) is infinitesimal; no loss of precision is permitted. However, fixed-fixed division is impractical to implement when an exact result is required, and multiplication will sometimes result in unanticipated overflows in such circumstances, so we require an explicit conversion to be inserted in expressions like A * B * C if A, B, and C are each of some fixed point type.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[On the other hand, X := A * B; is permitted by this rule, even if X, A, and B are all of different fixed point types, since the expected type for the result of the multiplication is the type of X, which is necessarily not @i(universal_fixed).]} @end(Discussion) @end{Legality} @begin{RunTime} The multiplication and division operators for real types have their conventional meaning. @redundant[For floating point types, the accuracy of the result is determined by the precision of the result type. For decimal fixed point types, the result is truncated toward zero if the mathematical result is between two multiples of the @i(small) of the specific result type (possibly determined by context); for ordinary fixed point types, if the mathematical result is between two multiples of the @i(small), it is unspecified which of the two is the result. @PDefn{unspecified}] @IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised by integer division, @key(rem), and @key(mod) if the right operand is zero. @Redundant[Similarly, for a real type @i(T) with @i(T')Machine_Overflows True, division by zero raises Constraint_Error.] @end{RunTime} @begin{Notes} @Leading@;For positive A and B, A/B is the quotient and A @key(rem) B is the remainder when A is divided by B. The following relations are satisfied by the rem operator: @begin{Example} A @key(rem) (-B) = A @key(rem) B (-A) @key(rem) B = -(A @key(rem) B) @end{Example} @Leading@keepnext@;For any signed integer K, the following identity holds: @begin{Example} A @key(mod) B = (A + K*B) @key(mod) B @end{Example} @begin{Bundle} @NoPrefix@Leading@;The relations between signed integer division, remainder, and modulus are illustrated by the following table: @begin{Example} A B A/B A @key(rem) B A @key(mod) B A B A/B A @key(rem) B A @key(mod) B 10 5 2 0 0 -10 5 -2 0 0 11 5 2 1 1 -11 5 -2 -1 4 12 5 2 2 2 -12 5 -2 -2 3 13 5 2 3 3 -13 5 -2 -3 2 14 5 2 4 4 -14 5 -2 -4 1 A B A/B A @key(rem) B A @key(mod) B A B A/B A @key(rem) B A @key(mod) B@* 10 -5 -2 0 0 -10 -5 2 0 0 11 -5 -2 1 -4 -11 -5 2 -1 -1 12 -5 -2 2 -3 -12 -5 2 -2 -2 13 -5 -2 3 -2 -13 -5 2 -3 -3 14 -5 -2 4 -1 -14 -5 2 -4 -4 @end{Example} @end{Bundle} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving multiplying operators:) @begin{Example} I : Integer := 1; J : Integer := 2; K : Integer := 3; X : Real := 1.0; --@RI[ see @RefSecNum{Floating Point Types}] Y : Real := 2.0; F : Fraction := 0.25; --@RI[ see @RefSecNum{Fixed Point Types}] G : Fraction := 0.5; @end{Example} @begin{Example} @tabclear()@tabset(P19, P31) @RI(Expression) @\@RI(Value) @\@RI(Result Type)@* @R{I*J} @\@R{2} @\@RI(same as I and J, that is, Integer) @R{K/J} @\@R{1} @\@RI(same as K and J, that is, Integer) @R{K @key(mod) J} @\@R{1} @\@RI(same as K and J, that is, Integer)@* @R{X/Y} @\@R{0.5} @\@RI(same as X and Y, that is, Real) @R{F/2} @\@R{0.125} @\@RI(same as F, that is, Fraction)@* @R{3*F} @\@R{0.75} @\@RI(same as F, that is, Fraction) @R{0.75*G} @\@R{0.375} @\@RI(universal_fixed, implicitly convertible) @\ @\@RI(to any fixed point type) @R{Fraction(F*G)} @\@R{0.125} @\@RI(Fraction, as stated by the conversion) @R{Real(J)*Y} @\@R{4.0} @\@RI(Real, the type of both operands after) @\ @\@RI(conversion of J) @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @Chg{Version=[2],New=[@Defn{incompatibilities with Ada 83}The universal fixed-fixed multiplying operators are now directly available (see below). Any attempt to use user-defined fixed-fixed multiplying operators will be ambiguous with the universal ones. The only way to use the user-defined operators is to fully qualify them in a prefix call. This problem was not documented during the design of Ada 95, and has been mitigated by Ada 2005.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Explicit conversion of the result of multiplying or dividing two fixed point numbers is no longer required, provided the context uniquely determines some specific fixed point result type. This is to improve support for decimal fixed point, where requiring explicit conversion on every fixed-fixed multiply or divide was felt to be inappropriate. The type @i(universal_fixed) is covered by @i(universal_real), so real literals and fixed point operands may be multiplied or divided directly, without any explicit conversions required. @end{Extend83} @begin{DiffWord83} We have used the normal syntax for function definition rather than a tabular format. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00364-01]} @Chg{Version=[2],New=[@Defn{incompatibilities with Ada 95}We have changed the resolution rules for the universal fixed-fixed multiplying operators to remove the incompatibility with Ada 83 discussed above. The solution is to hide the universal operators in some circumstances. As a result, some legal Ada 95 programs will require the insertion of an explicit conversion around a fixed-fixed multiply operator. This change is likely to catch as many bugs as it causes, since it is unlikely that the user wanted to use predefined operators when they had defined user-defined versions.],Old=[]} @end{Incompatible95} @LabeledSubClause{Highest Precedence Operators} @begin{StaticSem} @Leading@Defn{highest precedence operator}@Defn2{Term=[operator],Sec=(highest precedence)} @Defn{abs operator}@Defn2{Term=[operator],Sec=(abs)} @Defn{absolute value} The highest precedence unary operator @key(abs) (absolute value) is predefined for every specific numeric type @i(T), with the following specification: @begin(example) @key(function) "@key(abs)"(Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@Defn{not operator}@Defn2{Term=[operator],Sec=(not)} @IndexSeeAlso{Term=[logical operator],See=(not operator)} The highest precedence unary operator @key(not) (logical negation) is predefined for every boolean type @i(T), every modular type @i(T), and for every one-dimensional array type @i(T) whose components are of a boolean type, with the following specification: @begin(example) @key(function) "@key(not)"(Right : @RI(T)) @key(return) @RI(T) @end(example) The result of the operator @key(not) for a modular type is defined as the difference between the high bound of the base range of the type and the value of the operand. @Redundant[For a binary modulus, this corresponds to a bit-wise complement of the binary representation of the value of the operand.] The operator @key(not) that applies to a one-dimensional array of boolean components yields a one-dimensional boolean array with the same bounds; each component of the result is obtained by logical negation of the corresponding component of the operand (that is, the component that has the same index value). @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} A check is made that each component of the result belongs to the component subtype; the exception Constraint_Error is raised if this check fails. @begin{Discussion} The check against the component subtype is per AI83-00535. @end{Discussion} @Leading@Defn{exponentiation operator}@Defn2{Term=[operator],Sec=(exponentiation)} @Defn{** operator}@Defn2{Term=[operator],Sec=(**)} The highest precedence @i(exponentiation) operator ** is predefined for every specific integer type @i(T) with the following specification: @begin(example) @key(function) "**"(Left : @RI(T); Right : Natural) @key(return) @RI(T) @end(example) @Leading@;Exponentiation is also predefined for every specific floating point type as well as @i{root_real}, with the following specification (where @i(T) is @i{root_real} or the floating point type): @begin(example) @key(function) "**"(Left : @RI(T); Right : Integer'Base) @key(return) @RI(T) @end(example) @Defn{exponent} The right operand of an exponentiation is the @i(exponent). The expression X**N with the value of the exponent N positive is equivalent to the expression X*X*...X (with N@en@;1 multiplications) except that the multiplications are associated in an arbitrary order. With N equal to zero, the result is one. With the value of N negative @Redundant[(only defined for a floating point operand)], the result is the reciprocal of the result using the absolute value of N as the exponent. @begin{Ramification} The language does not specify the order of association of the multiplications inherent in an exponentiation. For a floating point type, the accuracy of the result might depend on the particular association order chosen. @end{Ramification} @end{StaticSem} @begin{ImplPerm} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of exponentiation for the case of a negative exponent is allowed to raise Constraint_Error if the intermediate result of the repeated multiplications is outside the safe range of the type, even though the final result (after taking the reciprocal) would not be. (The best machine approximation to the final result in this case would generally be 0.0.) @end{ImplPerm} @begin{Notes} @IndexCheck{Range_Check} As implied by the specification given above for exponentiation of an integer type, a check is made that the exponent is not negative. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{Notes} @begin{Inconsistent83} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0100],ARef=[AI95-00018-01]} @ChgAdded{Version=[1],Text=[@Defn{inconsistencies with Ada 83} The definition of "**" allows arbitrary association of the multiplications which make up the result. Ada 83 required left-to-right associations (confirmed by AI83-00137). Thus it is possible that "**" would provide a slightly different (and more potentially accurate) answer in Ada 95 than in the same Ada 83 program.]} @end{Inconsistent83} @begin{DiffWord83} We now show the specification for "**" for integer types with a parameter subtype of Natural rather than Integer for the exponent. This reflects the fact that Constraint_Error is raised if a negative value is provided for the exponent. @end{DiffWord83} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/04b.mss��������������������������������������������������������������0000755�0001752�0001001�00000323627�12273462240�016547� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(04, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:24 $} @Comment{$Source: e:\\cvsroot/ARM/Source/04b.mss,v $} @Comment{$Revision: 1.33 $} @LabeledClause{Type Conversions} @begin{Intro} @Redundant[Explicit type conversions, both value conversions and view conversions, are allowed between closely related types as defined below. This clause also defines rules for value and view conversions to a particular subtype of a type, both explicit ones and those implicit in other constructs. @IndexSee{Term=[subtype conversion],See=(type conversion)} @Defn{type conversion} @Defn{conversion} @IndexSee{Term=[cast],See=(type conversion)}] @IndexSeeAlso{Term=[subtype conversion],See=(implicit subtype conversion)} @IndexSee{Term=[type conversion, implicit],See=(implicit subtype conversion)} @end{Intro} @begin{Syntax} @Syn{lhs=<type_conversion>,rhs=" @Syn2{subtype_mark}(@Syn2{expression}) | @Syn2{subtype_mark}(@Syn2{name})"} @end{Syntax} @begin{Intro} @Defn2{Term=[target subtype], Sec=(of a @nt<type_conversion>)} The @i(target subtype) of a @nt<type_conversion> is the subtype denoted by the @nt{subtype_mark}. @Defn2{Term=[operand], Sec=(of a @nt<type_conversion>)} The @i(operand) of a @nt<type_conversion> is the @nt{expression} or @nt{name} within the parentheses; @Defn2{Term=[operand type], Sec=(of a @nt<type_conversion>)} its type is the @i(operand type). @Defn{convertible} One type is @i(convertible) to a second type if a @nt<type_conversion> with the first type as operand type and the second type as target type is legal according to the rules of this clause. Two types are convertible if each is convertible to the other. @begin{Ramification} Note that @lquotes@;convertible@rquotes@; is defined in terms of legality of the conversion. Whether the conversion would raise an exception at run time is irrelevant to this definition. @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00330-01]} @Defn{view conversion} @Defn2{Term=[conversion],Sec=(view)} A @nt{type_conversion} whose operand is the @nt<name> of an object is called a @i(view conversion) if @Chg{New=[both ],Old=[]}its target type @Chg{New=[and operand type are],Old=[is]} tagged, or if it appears@Chg{Version=[2],New=[ in a call],Old=[]} as an actual parameter of mode @key[out] or @key[in out]; @Defn{value conversion} @Defn2{Term=[conversion],Sec=(value)} other @nt<type_conversion>s are called @i(value conversions). @IndexSee{Term=[super],See=(view conversion)} @begin{Ramification} A view conversion to a tagged type can appear in any context that requires an object @nt<name>, including in an object renaming, the @nt<prefix> of a @nt<selected_component>, and if the operand is a variable, on the left side of an @nt<assignment_statement>. View conversions to other types only occur as actual parameters. Allowing view conversions of untagged types in all contexts seemed to incur an undue implementation burden. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00330-01]} @ChgAdded{Version=[2],Text=[A type conversion appearing as an @key{in out} parameter in a generic instantiation is not a view conversion; the second part of the rule only applies to subprogram calls, not instantiations.]} @end{Ramification} @end{Intro} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(type_conversion operand)} The operand of a @nt<type_conversion> is expected to be of any type. @begin{Discussion} This replaces the "must be determinable" wording of Ada 83. This is equivalent to (but hopefully more intuitive than) saying that the operand of a @nt<type_conversion> is a @lquotes@;complete context.@rquotes@; @end{Discussion} The operand of a view conversion is interpreted only as a @nt<name>; the operand of a value conversion is interpreted as an @nt<expression>. @begin{Reason} This formally resolves the syntactic ambiguity between the two forms of @nt<type_conversion>, not that it really matters. @end{Reason} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[In a view conversion for an untagged type, the target type shall be convertible (back) to the operand type.], Old=[@Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} If the target type is a numeric type, then the operand type shall be a numeric type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=<Untagged view conversions appear only as [@key{in}] @key{out} parameters. Hence, the reverse conversion must be legal as well. The forward conversion must be legal even for an @key{out} parameter, because (for example) actual parameters of an access type are always copied in anyway.>} @end{Reason} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 9 through 20 were reorganized and moved below.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The entire @LegalityTitle section has been reorganized to eliminate an unintentional incompatibility with Ada 83. In rare cases, a type conversion between two types related by derivation is not allowed by Ada 95, while it is allowed in Ada 83. The reorganization fixes this. Much of the wording of the legality section is unchanged, but it is reordered and reformatted. Because of the limitations of our tools, we had to delete and replace nearly the entire section. The text of Ada 95 paragraphs 8 through 12, 14, 15, 17, 19, 20, and 24 are unchanged (just moved); these are now 24.1 through 24.5, 24.12, 24.13, 24.17, 24.19, 24.20, and 8.]} @end{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} If the target type is an array type, then the operand type shall be an array type. Further:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The types shall have the same dimensionality;]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[Corresponding index types shall be convertible;@Chg{New=[],Old=[ and]} @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The component subtypes shall statically match@Chg{New=[; and],Old=[.]} @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@Chg{New=[In a view conversion, the target type and the operand type shall both or neither have aliased components.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[Without this rule, it is possible to violate the constrained status of aliased array components. Consider:],Old=[]}]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[@key[package] P @key[is] @key[type] T @key[is private]; A : @key[constant] T; @key[type] A1 @key[is array] (1 .. 10) @key[of aliased] T; @key[type] A2 @key[is array] (1 .. 10) @key[of] T; @key[private] @key[type] T (D : Integer := 0) @key[is null record]; A : @key[constant] T := (D => 1); @key[end] P;],Old=[]}]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[@key[with] P; @key[procedure] Exam @key[is] X : P.A1; @key[procedure] S (Y : @key[in out] P.A2) @key[is] @key[begin] Y (1) := P.A; @key[end]; @key[begin] S (P.A2 (X)); -- This call will change the discriminant of X (1), -- so we cannot allow the conversion. @key[end];],Old=[]}]} @end{Example} @end{Reason} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is a general access type, then the operand type shall be an access-to-object type. Further:]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The @LegalityTitle and @RunTimeTitle are worded so that a @nt{type_conversion} T(X) (where T is an access type) is (almost) equivalent to the @nt{attribute_reference} X.@key[all]'Access, where the result is of type T. The @nt{type_conversion} accepts a null value, whereas the @nt{attribute_reference} would raise Constraint_Error.]} @end{Discussion} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target type is an access-to-variable type, then the operand type shall be an access-to-variable type;]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If the target type is an access-to-constant type, then the operand type can be access-to-constant or access-to-variable.]} @end{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target designated type is tagged, then the operand designated type shall be convertible to the target designated type; @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target designated type is not tagged, then the designated types shall be the same, and either the designated subtypes shall statically match or the target designated subtype shall be discriminated and unconstrained; and @PDefn2{Term=[statically matching],Sec=(required)}]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[These rules are designed to ensure that aliased array objects only @i(need) "dope" if their nominal subtype is unconstrained, but they can always @i(have) dope if required by the run-time model (since no sliding is permitted as part of access type conversion). By contrast, aliased discriminated objects will always @i(need) their discriminants stored with them, even if nominally constrained. (Here, we are assuming an implementation that represents an access value as a single pointer.)]} @end{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The access parameter case is handled by a run-time check. Run-time checks are also done in instance bodies.]} @end{Ramification} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is an access-to-subprogram type, then the operand type shall be an access-to-subprogram type. Further:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The designated profiles shall be subtype-conformant.@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. If the operand type is declared within a generic body, the target type shall be declared within the generic body.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The reason it is illegal to convert from an access-to-subprogram type declared in a generic body to one declared outside that body is that in an implementation that shares generic bodies, procedures declared inside the generic need to have a different calling convention @em they need an extra parameter pointing to the data declared in the current instance. For procedures declared in the spec, that's OK, because the compiler can know about them at compile time of the instantiation.]} @end{Reason} @end(itemize) @Comment{We start the new text here, so we can modify the handful of rules that are not reformatted. (Except the first rule is at the top.)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Leading@Defn2{Term=[type conversion],sec=[composite (non-array)]} @Defn2{Term=[conversion],sec=[composite (non-array)]} @Chg{Version=[2],New=[If there is a type that is an ancestor of both the target type and the operand type, or both types are class-wide types, then at least one of the following rules shall apply:],Old=[@Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)} If the target type is not included in any of the above four cases, there shall be a type that is an ancestor of both the target type and the operand type. Further, if the target type is tagged, then either:]} @begin(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)}The target type shall be untagged; or]} The operand type shall be covered by or descended from the target type; or @begin{Ramification} This is a conversion toward the root, which is always safe. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The operand type shall be a class-wide type that covers the target type@Chg{Version=[2],New=[; or],Old=[.]} @begin{Ramification} This is a conversion of a class-wide type toward the leaves, which requires a tag check. See @RunTimeTitle. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} These two rules imply that a conversion from @Chg{Version=[2],New=[an ancestor],Old=[a parent]} type to a type extension is not permitted, as this would require specifying the values for additional components, in general, and changing the tag. An @nt<extension_aggregate> has to be used instead, constructing a new value, rather than converting an existing value. However, a conversion from the class-wide type rooted at @Chg{Version=[2],New=[an ancestor],Old=[the parent]} type is permitted; such a conversion just verifies that the operand's tag is a descendant of the target. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The operand and target types shall both be class-wide types and the specific type associated with at least one of them shall be an interface type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow converting any class-wide type T'Class to or from a class-wide interface type even if the specific type T does not have an appropriate interface ancestor, because some extension of T might have the needed ancestor. This is similar to a conversion of a class-wide type toward the leaves of the tree, and we need to be consistent. Of course, there is a run-time check that the actual object has the needed interface.]} @end{Ramification} @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[If there is no type that is the ancestor of both the target type and the operand type, and they are not both class-wide types, one of the following rules shall apply:], Old=[In a view conversion for an untagged type, the target type shall be convertible (back) to the operand type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<Untagged view conversions appear only as [in] out parameters. Hence, the reverse conversion must be legal as well. The forward conversion must be legal even if an out parameter, because actual parameters of an access type are always copied in anyway.>} @end{Reason} @begin(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} If the target type is a numeric type, then the operand type shall be a numeric type.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} If the target type is an array type, then the operand type shall be an array type. Further:]} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The types shall have the same dimensionality;],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[Corresponding index types shall be convertible; @PDefn2{Term=[convertible],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The component subtypes shall statically match; @PDefn2{Term=[statically matching],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00392-01]} @Chg{Version=[2],New=[If the component types are anonymous access types, then the accessibility level of the operand type shall not be statically deeper than that of the target type; @PDefn2{Term=[accessibility rule],Sec=(type conversion, array components)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For unrelated array types, the component types could have different accessibility, and we had better not allow a conversion of a local type into a global type, in case the local type points at local objects. We don't need a check for other types of components; such components necessarily are for related types, and either have the same accessibility or (for access discriminants) cannot be changed so the discriminant check will prevent problems.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[Neither the target type nor the operand type shall be limited;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We cannot allow conversions between unrelated limited types, as they may have different representations, and (since the types are limited), a copy cannot be made to reconcile the representations.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If the target type of a view conversion has aliased components, then so shall the operand type; and]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[We cannot allow a view conversion from an object with unaliased components to an object with aliased components, because that would effectively allow pointers to unaliased components. This rule was missing from Ada 95.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00246-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The operand type of a view conversion shall not have a tagged, private, or volatile subcomponent.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[We cannot allow view conversions between unrelated might-be-by-reference types, as they may have different representations, and a copy cannot be made to reconcile the representations.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules only apply to unrelated array conversions; different (weaker) rules apply to conversions between related types.]} @end{Ramification} @end(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[If the target type is @i<universal_access>, then the operand type shall be an access type.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such a conversion cannot be written explicitly, of course, but it can be implicit (see below).]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)}If the target type is a general access-to-object type, then the operand type shall be @i<universal_@!access> or an access-to-object type. Further, if the operand type is not @i<universal_@!access>:]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @LegalityTitle and @RunTimeTitle are worded so that a @nt{type_conversion} T(X) (where T is an access type) is (almost) equivalent to the @nt{attribute_reference} X.@key[all]'Access, where the result is of type T. The only difference is that the @nt{type_conversion} accepts a null value, whereas the @nt{attribute_reference} would raise Constraint_Error.]} @end{Discussion} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[If the target type is an access-to-variable type, then the operand type shall be an access-to-variable type;],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target type is an access-to-constant type, then the operand type can be access-to-constant or access-to-variable.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If the target designated type is tagged, then the operand designated type shall be convertible to the target designated type; @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the target designated type is not tagged, then the designated types shall be the same, and either:]} @begin(innerinneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[the designated subtypes shall statically match; or@PDefn2{Term=[statically matching],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01],ARef=[AI95-00384-01]} @Chg{Version=[2],New=[the designated type shall be discriminated in its full view and unconstrained in any partial view, and one of the designated subtypes shall be unconstrained;],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[This does not require that types have a partial view in order to allow the conversion, simply that any partial view that does exist is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00384-01]} @ChgAdded{Version=[2],Text=[This allows conversions both ways (either subtype can be unconstrained); while Ada 95 only allowed the conversion if the target subtype is unconstrained. We generally want type conversions to be symmetric; which type is the target shouldn't matter for legality.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If the visible partial view is constrained, we do not allow conversion between unconstrained and constrained subtypes. This means that whether the full type had discriminants is not visible to clients of the partial view.]} @end{Reason} @end(innerinneritemize) @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are designed to ensure that aliased array objects only @i(need) "dope" if their nominal subtype is unconstrained, but they can always @i(have) dope if required by the run-time model (since no sliding is permitted as part of access type conversion). By contrast, aliased discriminated objects will always @i(need) their discriminants stored with them, even if nominally constrained. (Here, we are assuming an implementation that represents an access value as a single pointer.)]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The access parameter case is handled by a run-time check. Run-time checks are also done in instance bodies.]} @end{Ramification} @end(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)}If the target type is a pool-specific access-to-object type, then the operand type shall be @i<universal_access>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This allows @b<null> to be converted to pool-specific types. Without it, @b<null> could be converted to general access types but not pool-specific ones, which would be too inconsistent. Remember that these rules only apply to unrelated types, so we don't have to talk about conversions to derived or other related types.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is an access-to-subprogram type, then the operand type shall be @i<universal_@!access> or an access-to-subprogram type. Further, if the operand type is not @i<universal_@!access>:]} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The designated profiles shall be subtype-conformant. @Defn2{Term=[subtype conformance],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. If the operand type is declared within a generic body, the target type shall be declared within the generic body.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The reason it is illegal to convert from an access-to-subprogram type declared in a generic body to one declared outside that body is that in an implementation that shares generic bodies, procedures declared inside the generic need to have a different calling convention @em they need an extra parameter pointing to the data declared in the current instance. For procedures declared in the spec, that's OK, because the compiler can know about them at compile time of the instantiation.]} @end{Reason} @end(inneritemize) @end(itemize) @end{Legality} @begin{StaticSem} A @nt{type_conversion} that is a value conversion denotes the value that is the result of converting the value of the operand to the target subtype. A @nt{type_conversion} that is a view conversion denotes a view of the object denoted by the operand. This view is a variable of the target type if the operand denotes a variable; otherwise it is a constant of the target type. @PDefn2{Term=[nominal subtype], Sec=(associated with a @nt<type_conversion>)} The nominal subtype of a @nt<type_conversion> is its target subtype. @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(value conversion)} @Defn2{Term=[corresponding value], Sec=(of the target type of a conversion)} @Defn{conversion} For the evaluation of a @nt<type_conversion> that is a value conversion, the operand is evaluated, and then the value of the operand is @i(converted) to a @i(corresponding) value of the target type, if any. @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If there is no value of the target type that corresponds to the operand value, Constraint_Error is raised@Redundant[; this can only happen on conversion to a modular type, and only when the operand value is outside the base range of the modular type.] Additional rules follow: @begin(itemize) @Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} Numeric Type Conversion @begin(inneritemize) If the target and the operand types are both integer types, then the result is the value of the target type that corresponds to the same mathematical integer as the operand. If the target type is a decimal fixed point type, then the result is truncated (toward 0) if the value of the operand is not a multiple of the @i{small} of the target type. @Defn{accuracy} If the target type is some other real type, then the result is within the accuracy of the target type (see @RefSec{Numeric Performance Requirements}, for implementations that support the Numerics Annex). @begin(Discussion) An integer type might have more bits of precision than a real type, so on conversion (of a large integer), some precision might be lost. @end(Discussion) If the target type is an integer type and the operand type is real, the result is rounded to the nearest integer (away from zero if exactly halfway between two integers). @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00267-01]} This was implementation defined in Ada 83. There seems no reason to preserve the nonportability in Ada 95. Round-away-from-zero is the conventional definition of rounding, and standard Fortran and COBOL both specify rounding away from zero, so for interoperability, it seems important to pick this. This is also the most easily @lquotes@;undone@rquotes@; by hand. Round-to-nearest-even is an alternative, but that is quite complicated if not supported by the hardware. In any case, this operation is not @Chg{Version=[2],New=[usually],Old=[expected to be]} part of an inner loop, so predictability and portability are judged most important. @Chg{Version=[2],New=[A],Old=[We anticipate that a]} floating point attribute function Unbiased_Rounding @Chg{Version=[2], New=[is],Old=[will be]} provided@Chg{Version=[2], New=[ (see @RefSecNum{Attributes of Floating Point Types})],Old=[]} for those applications that require round-to-nearest-even@Chg{Version=[2], New=[, and a floating point attribute function Machine_Rounding (also see @RefSecNum{Attributes of Floating Point Types}) is provided for those applications that require the highest possible performance], Old=[]}. @lquotes@;Deterministic@rquotes@; rounding is required for static conversions to integer as well. See @RefSecNum{Static Expressions and Static Subtypes}. @end{Discussion} @end(inneritemize) @Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)} Enumeration Type Conversion @begin(inneritemize) The result is the value of the target type with the same position number as that of the operand value. @end(inneritemize) @Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} Array Type Conversion @begin(inneritemize) @IndexCheck{Length_Check} If the target subtype is a constrained array subtype, then a check is made that the length of each dimension of the value of the operand equals the length of the corresponding dimension of the target subtype. The bounds of the result are those of the target subtype. @IndexCheck{Range_Check} If the target subtype is an unconstrained array subtype, then the bounds of the result are obtained by converting each bound of the value of the operand to the corresponding index type of the target type. @PDefn2{Term=[implicit subtype conversion],Sec=(array bounds)} For each nonnull index range, a check is made that the bounds of the range belong to the corresponding index subtype. @begin(Discussion) Only nonnull index ranges are checked, per AI83-00313. @end(Discussion) In either array case, the value of each component of the result is that of the matching component of the operand value (see @RefSecNum{Relational Operators and Membership Tests}). @begin{Ramification} This applies whether or not the component is initialized. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00392-01]} @ChgAdded{Version=[2],Text=[If the component types of the array types are anonymous access types, then a check is made that the accessibility level of the operand type is not deeper than that of the target type. @IndexCheck{Accessibility_Check}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check is needed for operands that are access parameters and in instance bodies. Other cases are handled by the legality rule given previously.]} @end{Reason} @end(inneritemize) @Defn2{Term=[type conversion],sec=[composite (non-array)]} @Defn2{Term=[conversion],sec=[composite (non-array)]} Composite (Non-Array) Type Conversion @begin(inneritemize) The value of each nondiscriminant component of the result is that of the matching component of the operand value. @begin{Ramification} This applies whether or not the component is initialized. @end{Ramification} @Redundant[The tag of the result is that of the operand.] @IndexCheck{Tag_Check} If the operand type is class-wide, a check is made that the tag of the operand identifies a (specific) type that is covered by or descended from the target type. @begin{Ramification} This check is certain to succeed if the operand type is itself covered by or descended from the target type. @end{Ramification} @begin{TheProof} The fact that a @nt{type_conversion} preserves the tag is stated officially in @RefSec{Tagged Types and Type Extensions} @end{TheProof} For each discriminant of the target type that corresponds to a discriminant of the operand type, its value is that of the corresponding discriminant of the operand value; @IndexCheck{Discriminant_Check} if it corresponds to more than one discriminant of the operand type, a check is made that all these discriminants are equal in the operand value. For each discriminant of the target type that corresponds to a discriminant that is specified by the @nt<derived_type_definition> for some ancestor of the operand type (or if class-wide, some ancestor of the specific type identified by the tag of the operand), its value in the result is that specified by the @nt<derived_type_definition>. @begin{Ramification} It is a ramification of the rules for the discriminants of derived types that each discriminant of the result is covered either by this paragraph or the previous one. See @RefSecNum(Discriminants). @end{Ramification} @IndexCheck{Discriminant_Check} For each discriminant of the operand type that corresponds to a discriminant that is specified by the @nt<derived_type_definition> for some ancestor of the target type, a check is made that in the operand value it equals the value specified for it. @IndexCheck{Range_Check} For each discriminant of the result, a check is made that its value belongs to its subtype. @end(inneritemize) @Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} Access Type Conversion @begin(inneritemize) For an access-to-object type, a check is made that the accessibility level of the operand type is not deeper than that of the target type. @IndexCheck{Accessibility_Check} @begin{Ramification} This check is needed for operands that are access parameters and in instance bodies. Note that this check can never fail for the implicit conversion to the anonymous type of an access parameter that is done when calling a subprogram with an access parameter. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} If the @Chg{Version=[2],New=[],Old=[target type is an anonymous access type, a check is made that the value of the operand is not null; if the target is not an anonymous access type, then the result is null if the ]}operand value is null@Chg{Version=[2],New=[, the result of the conversion is the null value of the target type.],Old=[. @IndexCheck{Access_Check}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised]} A conversion to an anonymous access type happens implicitly as part of initializing @Chg{Version=[2],New=[or assigning to an anonymous access object], Old=[an access discriminant or access parameter]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[As explained in @RefSec{Access Types}, it is important that a value of an anonymous access type can never be null.]} @end{Reason} If the operand value is not null, then the result designates the same object (or subprogram) as is designated by the operand value, but viewed as being of the target designated subtype (or profile); any checks associated with evaluating a conversion to the target designated subtype are performed. @begin{Ramification} The checks are certain to succeed if the target and operand designated subtypes statically match. @end{Ramification} @end(inneritemize) @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @IndexCheck{Range_Check} @IndexCheck{Discriminant_Check} @IndexCheck{Index_Check} @Chg{Version=[2],New=[@IndexCheck{Access_Check}],Old=[]} After conversion of the value to the target type, if the target subtype is constrained, a check is performed that the value satisfies this constraint. @Chg{Version=[2],New=[If the target subtype excludes null, then a check is made that the value is not null.],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} The @Chg{Version=[2],New=[first],Old=[above]} check @Chg{Version=[2],New=[above ],Old=[]}is a Range_Check for scalar subtypes, a Discriminant_Check or Index_Check for access subtypes, and a Discriminant_Check for discriminated subtypes. The Length_Check for an array conversion is performed as part of the conversion to the target type. @Chg{Version=[2],New=[The check for exclusion of null is an Access_Check.],Old=[]} @end{Ramification} @PDefn2{Term=[evaluation], Sec=(view conversion)} For the evaluation of a view conversion, the operand @nt<name> is evaluated, and a new view of the object denoted by the operand is created, whose type is the target type; @IndexCheck{Length_Check} @IndexCheck{Tag_Check} @IndexCheck{Discriminant_Check} if the target type is composite, checks are performed as above for a value conversion. @Leading@;The properties of this new view are as follows: @begin(itemize) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} If the target type is composite, the bounds or discriminants (if any) of the view are as defined above for a value conversion; each nondiscriminant component of the view denotes the matching component of the operand object; the subtype of the view is constrained if either the target subtype or the operand object is constrained, @Chg{New=[or if the target subtype is indefinite,],Old=[]} or if the operand type is a descendant of the target type@Chg{New=[],Old=[,]} and has discriminants that were not inherited from the target type; If the target type is tagged, then an assignment to the view assigns to the corresponding part of the object denoted by the operand; otherwise, an assignment to the view assigns to the object, after converting the assigned value to the subtype of the object (which might raise Constraint_Error); @PDefn2{Term=[implicit subtype conversion],Sec=(assignment to view conversion)} Reading the value of the view yields the result of converting the value of the operand object to the target subtype (which might raise Constraint_Error), except if the object is of an access type and the view conversion is passed as an @key(out) parameter; in this latter case, the value of the operand object is used to initialize the formal parameter without checking against any constraint of the target subtype (see @RefSecNum(Parameter Associations)). @PDefn2{Term=[implicit subtype conversion],Sec=(reading a view conversion)} @begin(Reason) This ensures that even an @key(out) parameter of an access type is initialized reasonably. @end(Reason) @end(itemize) @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If an Accessibility_Check fails, Program_Error is raised. Any other check associated with a conversion raises Constraint_Error if it fails. Conversion to a type is the same as conversion to an unconstrained subtype of the type. @begin{Reason} This definition is needed because the semantics of various constructs involves converting to a type, whereas an explicit @nt{type_conversion} actually converts to a subtype. For example, the evaluation of a @nt{range} is defined to convert the values of the expressions to the type of the range. @end{Reason} @begin{Ramification} A conversion to a scalar type, or, equivalently, to an unconstrained scalar subtype, can raise Constraint_Error if the value is outside the base range of the type. @end{Ramification} @end{RunTime} @begin{Notes} @RootDefn{implicit subtype conversion} In addition to explicit @nt<type_conversion>s, type conversions are performed implicitly in situations where the expected type and the actual type of a construct differ, as is permitted by the type resolution rules (see @RefSecNum(The Context of Overload Resolution)). For example, an integer literal is of the type @i(universal_integer), and is implicitly converted when assigned to a target of some specific integer type. Similarly, an actual parameter of a specific tagged type is implicitly converted when the corresponding formal parameter is of a class-wide type. @NoPrefix@;@RootDefn{implicit subtype conversion} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Even when the expected and actual types are the same, implicit subtype conversions are performed to adjust the array bounds (if any) of an operand to match the desired target subtype, or to raise Constraint_Error if the (possibly adjusted) value does not satisfy the constraints of the target subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} A ramification of the overload resolution rules is that the operand of an (explicit) @nt<type_conversion> cannot be @Chg{Version=[2],New=[],Old=[the literal @key(null), ]}an @nt<allocator>, an @nt<aggregate>, a @nt<string_literal>, a @nt<character_literal>, or an @nt<attribute_reference> for an Access or Unchecked_Access attribute. Similarly, such an @nt{expression} enclosed by parentheses is not allowed. A @nt<qualified_expression> (see @RefSecNum(Qualified Expressions)) can be used instead of such a @nt<type_conversion>. The constraint of the target subtype has no effect for a @nt<type_conversion> of an elementary type passed as an @key(out) parameter. Hence, it is recommended that the first subtype be specified as the target to minimize confusion (a similar recommendation applies to renaming and generic formal @key(in out) objects). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of numeric type conversion:) @begin{Example} Real(2*J) @RI[-- value is converted to floating point] Integer(1.6) @RI[-- value is 2] Integer(-0.4) @RI[-- value is 0] @end{Example} @begin{Wide} @leading@keepnext@i(Example of conversion between derived types:) @end{Wide} @begin{Example} @key(type) A_Form @key(is) @key(new) B_Form; X : A_Form; Y : B_Form; X := A_Form(Y); Y := B_Form(X); @RI[-- the reverse conversion ] @end{Example} @begin{Wide} @leading@keepnext@i(Examples of conversions between array types:) @end{Wide} @begin{Example} @key(type) Sequence @key(is) @key(array) (Integer @key(range) <>) @key(of) Integer; @key(subtype) Dozen @key(is) Sequence(1 .. 12); Ledger : @key(array)(1 .. 100) @key(of) Integer; Sequence(Ledger) @RI[-- bounds are those of Ledger] Sequence(Ledger(31 .. 42)) @RI[-- bounds are 31 and 42] Dozen(Ledger(31 .. 42)) @RI[-- bounds are those of Dozen ] @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} A @nt<character_literal> is not allowed as the operand of a @nt<type_conversion>, since there are now two character types in package Standard. The component subtypes have to statically match in an array conversion, rather than being checked for matching constraints at run time. Because sliding of array bounds is now provided for operations where it was not in Ada 83, programs that used to raise Constraint_Error might now continue executing and produce a reasonable result. This is likely to fix more bugs than it creates. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} A @nt<type_conversion> is considered the name of an object in certain circumstances (such a @nt<type_conversion> is called a view conversion). In particular, as in Ada 83, a @nt<type_conversion> can appear as an @key(in out) or @key(out) actual parameter. In addition, if the target type is tagged and the operand is the @nt<name> of an object, then so is the @nt<type_conversion>, and it can be used as the @nt<prefix> to a @nt<selected_component>, in an @nt<object_renaming_declaration>, etc. We no longer require type-mark conformance between a parameter of the form of a type conversion, and the corresponding formal parameter. This had caused some problems for inherited subprograms (since there isn't really a type-mark for converted formals), as well as for renamings, formal subprograms, etc. See AI83-00245, AI83-00318, AI83-00547. We now specify @lquotes@;deterministic@rquotes@; rounding from real to integer types when the value of the operand is exactly between two integers (rounding is away from zero in this case). @lquotes@;Sliding@rquotes@; of array bounds (which is part of conversion to an array subtype) is performed in more cases in Ada 95 than in Ada 83. Sliding is not performed on the operand of a membership test, nor on the operand of a @nt{qualified_expression}. It wouldn't make sense on a membership test, and we wish to retain a connection between subtype membership and subtype qualification. In general, a subtype membership test returns True if and only if a corresponding subtype qualification succeeds without raising an exception. Other operations that take arrays perform sliding. @end{Extend83} @begin{DiffWord83} We no longer explicitly list the kinds of things that are not allowed as the operand of a @nt<type_conversion>, except in a NOTE. The rules in this clause subsume the rules for "parameters of the form of a type conversion," and have been generalized to cover the use of a type conversion as a @nt<name>. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Conversions between unrelated array types that are limited or (for view conversions) might be by-reference types are now illegal. The representations of two such arrays may differ, making the conversions impossible. We make the check here, because legality should not be based on representation properties. Such conversions are likely to be rare, anyway. There is a potential that this change would make a working program illegal (if the types have the same representation).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If a discriminated full type has a partial view (private type) that is constrained, we do not allow conversion between access-to-unconstrained and access-to-constrained subtypes designating the type. Ada 95 allowed this conversion and the declaration of various access subtypes, requiring that the designated object be constrained and thus making details of the implementation of the private type visible to the client of the private type. See @RefSecNum{Allocators} for more on this topic.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Conversion rules for @i<universal_access> were defined. These allow the use of anonymous access values in equality tests (see @RefSecNum{Relational Operators and Membership Tests}), and also allow the use of @b<null> in type conversions and other contexts that do not provide a single expected type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00384-01]} @ChgAdded{Version=[2],Text=[A type conversion from an access-to-discriminated and unconstrained object to an access-to-discriminated and constrained one is allowed. Ada 95 only allowed the reverse conversion, which was weird and asymmetric. Of course, a constraint check will be performed for this conversion.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Wording was added to ensure that view conversions are constrained, and that a tagged view conversion has a tagged object. Both rules are needed to avoid having a way to change the discriminants of a constrained object.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Wording was added to ensure that the aliased status of array components cannot change in a view conversion. This rule was needed to avoid having a way to change the discriminants of an aliased object. This rule was repealed later, as Ada 2005 allows changing the discriminants of an aliased object.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Wording was added to check subtypes that exclude null (see @RefSecNum{Access Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The organization of the legality rules was changed, both to make it clearer, and to eliminate an unintentional incompatibility with Ada 83. The old organization prevented type conversions between some types that were related by derivation (which Ada 83 always allowed).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00330-01]} @ChgAdded{Version=[2],Text=[Clarified that an untagged type conversion appearing as a generic actual parameter for a generic @key{in out} formal parameter is not a view conversion (and thus is illegal). This confirms the ACATS tests, so all implementations already follow this intepretation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[Rules added by the Corrigendum to eliminate problems with discriminants of aliased components changing were removed, as we now generally allow discriminants of aliased components to be changed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00392-01]} @ChgAdded{Version=[2],Text=[Accessibility checks on conversions involving types with anonymous access components were added. These components have the level of the type, and conversions can be between types at different levels, which could cause dangling access values in the absence of such checks.]} @end{DiffWord95} @LabeledClause{Qualified Expressions} @begin{Intro} @Redundant[A @nt<qualified_expression> is used to state explicitly the type, and to verify the subtype, of an operand that is either an @nt<expression> or an @nt<aggregate>. @IndexSeeAlso{Term=[type conversion],See=(qualified_expression)}] @end{Intro} @begin{Syntax} @Syn{lhs=<qualified_expression>,rhs=" @Syn2{subtype_mark}@SingleQuote@;(@Syn2{expression}) | @Syn2{subtype_mark}@SingleQuote@Syn2{aggregate}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[operand], Sec=(of a @nt{qualified_expression})} The @i(operand) (the @nt{expression} or @nt{aggregate}) shall resolve to be of the type determined by the @nt{subtype_@!mark}, or a universal type that covers it. @end{Resolution} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(qualified_expression)} @IndexCheck{Range_Check} @IndexCheck{Discriminant_Check} @IndexCheck{Index_Check} The evaluation of a @nt{qualified_expression} evaluates the operand (and if of a universal type, converts it to the type determined by the @nt{subtype_mark}) and checks that its value belongs to the subtype denoted by the @nt{subtype_mark}. @PDefn2{Term=[implicit subtype conversion],Sec=(qualified_expression)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if this check fails. @begin{Ramification} This is one of the few contexts in Ada 95 where implicit subtype conversion is not performed prior to a constraint check, and hence no @lquotes@;sliding@rquotes@; of array bounds is provided. @end{Ramification} @begin{Reason} Implicit subtype conversion is not provided because a @nt<qualified_expression> with a constrained target subtype is essentially an assertion about the subtype of the operand, rather than a request for conversion. An explicit @nt<type_conversion> can be used rather than a @nt<qualified_expression> if subtype conversion is desired. @end{Reason} @end{RunTime} @begin{Notes} When a given context does not uniquely identify an expected type, a @nt<qualified_expression> can be used to do so. In particular, if an overloaded @nt<name> or @nt<aggregate> is passed to an overloaded subprogram, it might be necessary to qualify the operand to resolve its type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of disambiguating expressions using qualification:) @begin{Example} @key(type) Mask @key(is) (Fix, Dec, Exp, Signif); @key(type) Code @key(is) (Fix, Cla, Dec, Tnz, Sub); Print (Mask'(Dec)); @RI[-- Dec is of type Mask] Print (Code'(Dec)); @RI[-- Dec is of type Code ] @key(for) J @key(in) Code'(Fix) .. Code'(Dec) @key(loop) ... @RI[-- qualification needed for either Fix or Dec] @key(for) J @key(in) Code @key(range) Fix .. Dec @key(loop) ... @RI[-- qualification unnecessary] @key(for) J @key(in) Code'(Fix) .. Dec @key(loop) ... @RI[-- qualification unnecessary for Dec] Dozen'(1 | 3 | 5 | 7 => 2, @key(others) => 0) @RI[-- see @RefSecNum{Type Conversions} ] @end{Example} @end{Examples} @LabeledClause{Allocators} @begin{Intro} @Redundant[The evaluation of an @nt<allocator> creates an object and yields an access value that designates the object. @IndexSee{Term=[new],See=(allocator)} @IndexSee{Term=[malloc],See=(allocator)} @IndexSeeAlso{Term=[heap management],See=(allocator)}] @end{Intro} @begin{Syntax} @Syn{lhs=<allocator>,rhs=" @key{new} @Syn2{subtype_indication} | @key{new} @Syn2{qualified_expression}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @PDefn2{Term=[expected type],Sec=(allocator)} The expected type for an @nt<allocator> shall be a single access-to-object type @Chg{New=[with],Old=[whose]} designated type @Chg{New=[@i<D> such that either @i<D>],Old=[]} covers the type determined by the @nt<subtype_mark> of the @nt<subtype_@!indication> or @nt<qualified_@!expression>@Chg{New=[, or the expected type is anonymous and the determined type is @i<D>'Class],Old=[]}. @begin{Discussion} See @RefSec(The Context of Overload Resolution) for the meaning of @lquotes@;shall be a single ... type whose ...@rquotes@; @end{Discussion} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @Chg{New=[An @nt{allocator} is allowed as a controlling parameter of a dispatching call (see @RefSecNum{Dispatching Operations of Tagged Types}).],Old=[]} @end{Ramification} @end{Resolution} @begin{Legality} @Defn{initialized allocator} An @i(initialized) allocator is an @nt{allocator} with a @nt{qualified_expression}. @Defn{uninitialized allocator} An @i(uninitialized) allocator is one with a @nt{subtype_indication}. In the @nt<subtype_indication> of an uninitialized allocator, a @nt<constraint> is permitted only if the @nt<subtype_mark> denotes an @Redundant[unconstrained] composite subtype; if there is no @nt<constraint>, then the @nt<subtype_mark> shall denote a definite subtype. @IndexSee{Term=[constructor],See=[initialized allocator]} @begin{Ramification} For example, ... @key[new] S'Class ... (with no initialization expression) is illegal, but ... @key[new] S'Class'(X) ... is legal, and takes its tag and constraints from the initial value X. (Note that the former case cannot have a constraint.) @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} If the type of the @nt<allocator> is an access-to-constant type, the @nt<allocator> shall be an initialized allocator. @Chg{Version=[2],New=[],Old=[If the designated type is limited, the @nt<allocator> shall be an uninitialized allocator.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[For an access-to-constant type whose designated type is limited, @nt{allocator}s are illegal. The Access attribute is legal for such a type, however.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[If the designated type of the type of the @nt{allocator} is class-wide, the accessibility level of the type determined by the @nt{subtype_indication} or @nt{qualified_expression} shall not be statically deeper than that of the type of the @nt{allocator}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the allocated object from outliving its type.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the designated subtype of the type of the @nt{allocator} has one or more unconstrained access discriminants, then the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{subtype_indication} or @nt{qualified_expression} of the @nt{allocator}, shall not be statically deeper than that of the type of the @nt{allocator} (see @RefSecNum{Operations of Access Types}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the allocated object from outliving its discriminants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[An @nt{allocator} shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. This rule does not apply in the body of a generic unit or within a body declared within the declarative region of a generic unit, if the type of the allocator is a descendant of a formal access type declared within the formal part of the generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{allocator} for an access type that has Storage_Size specified to be zero is required to raise Storage_Error anyway. It's better to detect the error at compile-time, as the @nt{allocator} might be executed infrequently. This also simplifies the rules for Pure units, where we do not want to allow any allocators for library-level access types, as they would represent state.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The last sentence covers the case of children of generics, and formal access types of formal packages of the generic unit.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} If the designated type of the type of the @nt<allocator> is elementary, then the subtype of the created object is the designated subtype. If the designated type is composite, then the @Chg{Version=[2],New=[subtype of the ],Old=[]}created object is @Chg{Version=[2],New=[the designated subtype when the designated subtype is constrained or there is a partial view of the designated type that is constrained; otherwise, the created],Old=[always constrained; if the designated subtype is constrained, then it provides the constraint of the created object; otherwise, the]} object is constrained by its initial value @Redundant[(even if the designated subtype is unconstrained with defaults)]. @PDefn{constrained by its initial value} @begin{Discussion} See AI83-00331. @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} All objects created by an @Chg{Version=[2],New=[@nt{allocator}],Old=[allocator]} are aliased, and @Chg{Version=[2],New=[most],Old=[all]} aliased composite objects need to be constrained so that access subtypes work reasonably. @Chg{Version=[2],New=[Problematic access subtypes are prohibited for types with a constrained partial view.],Old=[]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If there is a constrained partial view of the type, this allows the objects to be unconstrained. This eliminates privacy breaking (we don't want the objects to act differently simply because they're allocated). Such a created object is effectively constrained by its initial value if the access type is an access-to-constant type, or the designated type is limited (in all views), but we don't need to state that here. It is implicit in other rules. Note, however, that a value of an access-to-constant type can designate a variable object via 'Access or conversion, and the variable object might be assigned by some other access path, and that assignment might alter the discriminants.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @PDefn2{Term=[evaluation], Sec=(allocator)} For the evaluation of an @Chg{Version=[2],New=[initialized allocator], Old=[@nt<allocator>]}, the @Chg{Version=[2],New=[],Old=[elaboration of the @nt<subtype_indication> or the ]}evaluation of the @nt<qualified_expression> is performed first. @PDefn2{Term=[evaluation], Sec=(initialized allocator)} @Defn2{Term=[assignment operation], Sec=(during evaluation of an initialized allocator)} @Chg{Version=[2],New=[An],Old=[For the evaluation of an initialized allocator, an]} object of the designated type is created and the value of the @nt<qualified_expression> is converted to the designated subtype and assigned to the object. @PDefn2{Term=[implicit subtype conversion],Sec=(initialization expression of allocator)} @begin{Ramification} The conversion might raise Constraint_Error. @end{Ramification} @PDefn2{Term=[evaluation], Sec=(uninitialized allocator)} @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} For the evaluation of an uninitialized allocator@Chg{Version=[2],New=[, the elaboration of the @nt{subtype_indication} is performed first. Then],Old=[]}: @begin(itemize) @Defn2{Term=[assignment operation], Sec=(during evaluation of an uninitialized allocator)} If the designated type is elementary, an object of the designated subtype is created and any implicit initial value is assigned; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @Chg{Version=[2],New=[],Old=[@Defn2{Term=[assignment operation], Sec=(during evaluation of an uninitialized allocator)}]} If the designated type is composite, an object of the designated type is created with tag, if any, determined by the @nt<subtype_mark> of the @nt<subtype_indication>@Chg{Version=[2],New=[. This object is then initialized by default (see @RefSecNum{Object Declarations}) using],Old=[; any per-object constraints on subcomponents are elaborated @Chg{New=[(see @RefSecNum{Record Types}) ],Old=[]}and any implicit initial values for the subcomponents of the object are obtained as determined by]} the @nt<subtype_indication> @Chg{Version=[2],New=[to determine its nominal subtype], Old=[and assigned to the corresponding subcomponents]}. @IndexCheck{Index_Check} @IndexCheck{Discriminant_Check} A check is made that the value of the object belongs to the designated subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order. @begin{Discussion} AI83-00150. @end{Discussion} @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[For any @nt{allocator}, if the designated type of the type of the @nt{allocator} is class-wide, then a check is made that the accessibility level of the type determined by the @nt{subtype_indication}, or by the tag of the value of the @nt{qualified_expression}, is not deeper than that of the type of the @nt{allocator}. If the designated subtype of the @nt{allocator} has one or more unconstrained access discriminants, then a check is made that the accessibility level of the anonymous access type of each access discriminant is not deeper than that of the type of the @nt{allocator}. Program_Error is raised if either such check fails.@IndexCheck{Accessibility_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The accessibility check on class-wide types prevents the allocated object from outliving its type. We need the run-time check in instance bodies, or when the type of the @nt{qualified_expression} is class-wide (other cases are statically detected).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The accessibility check on access discriminants prevents the allocated object from outliving its discriminants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @Chg{Version=[2],New=[If the object to be created by an @nt<allocator> has a controlled or protected part, and the finalization of the collection of the type of the @nt{allocator} (see @RefSecNum{Completion and Finalization}) has started, Program_Error is raised.@IndexCheck{Allocation_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the object has a controlled or protected part, its finalization is likely to be non-trivial. If the allocation was allowed, we could not know whether the finalization would actually be performed. That would be dangerous to otherwise safe abstractions, so we mandate a check here. On the other hand, if the finalization of the object will be trivial, we do not require (but allow) the check, as no real harm could come from late allocation.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check can only fail if an @nt{allocator} is evaluated in code reached from a Finalize routine for a type declared in the same master. That's highly unlikely; Finalize routines are much more likely to be deallocating objects than allocating them.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @Chg{Version=[2],New=[If the object to be created by an @nt<allocator> contains any tasks, and the master of the type of the @nt<allocator> is completed, and all of the dependent tasks of the master are terminated (see @RefSecNum{Task Dependence - Termination of Tasks}), then Program_Error is raised.@IndexCheck{Allocation_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A task created after waiting for tasks has finished could depend on freed data structures, and certainly would never be awaited.]} @end{Reason} @Redundant[If the created object contains any tasks, they are activated (see @RefSecNum(Task Execution - Task Activation)).] Finally, an access value that designates the created object is returned. @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error if the finalization of the collection of the type (see @RefSecNum{Completion and Finalization}) of the @nt<allocator> has started. If the error is detected, Program_Error is raised. Otherwise, the allocation proceeds normally.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check is required in some cases; see above.]} @end{Discussion} @end{Bounded} @begin{Notes} Allocators cannot create objects of an abstract type. See @RefSecNum{Abstract Types and Subprograms}. If any part of the created object is controlled, the initialization includes calls on corresponding Initialize or Adjust procedures. See @RefSecNum{User-Defined Assignment and Finalization}. As explained in @RefSec{Storage Management}, the storage for an object allocated by an @nt{allocator} comes from a storage pool (possibly user defined). @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} The exception Storage_Error is raised by an @nt<allocator> if there is not enough storage. Instances of Unchecked_Deallocation may be used to explicitly reclaim storage. Implementations are permitted, but not required, to provide garbage collection (see @RefSecNum{Pragma Controlled}). @begin{Ramification} Note that in an @nt<allocator>, the exception Constraint_Error can be raised by the evaluation of the @nt<qualified_expression>, by the elaboration of the @nt<subtype_indication>, or by the initialization. @end{Ramification} @begin{Discussion} By default, the implementation provides the storage pool. The user may exercise more control over storage management by associating a user-defined pool with an access type. @end{Discussion} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of allocators:} @begin{Example} @key(new) Cell'(0, @key(null), @key(null)) @RI[-- initialized explicitly, see @RefSecNum{Incomplete Type Declarations}] @key(new) Cell'(Value => 0, Succ => @key(null), Pred => @key(null)) @RI[-- initialized explicitly] @key(new) Cell @RI[-- not initialized] @key(new) Matrix(1 .. 10, 1 .. 20) @RI[-- the bounds only are given] @key(new) Matrix'(1 .. 10 => (1 .. 20 => 0.0)) @RI[-- initialized explicitly] @key(new) Buffer(100) @RI[-- the discriminant only is given] @key(new) Buffer'(Size => 80, Pos => 0, Value => (1 .. 80 => 'A')) @RI[-- initialized explicitly] Expr_Ptr'(@key(new) Literal) @RI[-- allocator for access-to-class-wide type, see @RefSecNum{Type Extensions}] Expr_Ptr'(@key(new) Literal'(Expression @key[with] 3.5)) @RI[-- initialized explicitly] @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00019} @Defn{incompatibilities with Ada 83} The @nt<subtype_indication> of an uninitialized allocator may not have an explicit @nt<constraint> if the designated type is an access type. In Ada 83, this was permitted even though the @nt<constraint> had no @Chg{New=[e],Old=[a]}ffect on the subtype of the created object. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Allocators creating objects of type @i(T) are now overloaded on access types designating @i(T')Class and all class-wide types that cover @i(T). Implicit array subtype conversion (sliding) is now performed as part of an initialized allocator. @end{Extend83} @begin{DiffWord83} We have used a new organization, inspired by the ACID document, that makes it clearer what is the subtype of the created object, and what subtype conversions take place. Discussion of storage management issues, such as garbage collection and the raising of Storage_Error, has been moved to @RefSec{Storage Management}. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95}If the designated type has a constrained partial view, the allocated object can be unconstrained. This might cause the object to take up a different amount of memory, and might cause the operations to work where they previously would have raised Constraint_Error. It's unlikely that the latter would actually matter in a real program (Constraint_Error usually indicates a bug that would be fixed, not left in a program.) The former might cause Storage_Error to be raised at a different time than in an Ada 95 program.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95}An @nt{allocator} for an access type that has Storage_Size specified to be zero is now illegal. Ada 95 allowed the @nt{allocator}, but it had to raise Storage_Error if executed. The primary impact of this change should be to detect bugs.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b<Corrigendum:> An @nt{allocator} can be a controlling parameter of a dispatching call. This was an oversight in Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Initialized @nt{allocator}s are allowed when the designated type is limited.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the elaboration of per-object constraints for an uninitialized allocator.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Program_Error is now raised if the @nt{allocator} occurs after the finalization of the collection or the waiting for tasks. This is not listed as an incompatibility as the Ada 95 behavior was unspecified, and Ada 95 implementations tend to generate programs that crash in this case.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to class-wide @nt{allocator}s. These checks could not fail in Ada 95 (as all of the designated types had to be declared at the same level, so the access type would necessarily have been at the same level or more nested than the type of allocated object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Revised the description of evaluation of uninitialized allocators to use @lquotes@;initialized by default@rquotes so that the ordering requirements are the same for all kinds of objects that are default-initialized.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to access discriminants of @nt{allocator}s. These checks could not fail in Ada 95 as the discriminants always have the accessibility of the object.]} @end{DiffWord95} @LabeledClause{Static Expressions and Static Subtypes} @begin{Intro} Certain expressions of a scalar or string type are defined to be static. Similarly, certain discrete ranges are defined to be static, and certain scalar and string subtypes are defined to be static subtypes. @Redundant[@Defn{static} @i(Static) means determinable at compile time, using the declared properties or values of the program entities.] @IndexSeeAlso{Term=[constant],See=(static)} @begin{Discussion} As opposed to more elaborate data flow analysis, etc. @end{Discussion} @end{Intro} @begin{MetaRules} For an expression to be static, it has to be calculable at compile time. Only scalar and string expressions are static. To be static, an expression cannot have any nonscalar, nonstring subexpressions (though it can have nonscalar constituent @nt<name>s). A static scalar expression cannot have any nonscalar subexpressions. There is one exception @em a membership test for a string subtype can be static, and the result is scalar, even though a subexpression is nonscalar. The rules for evaluating static expressions are designed to maximize portability of static calculations. @end{MetaRules} @begin{Intro} @Leading@Defn2{Term=[static], Sec=(expression)} A static expression is @Redundant[a scalar or string expression that is] one of the following: @begin{Itemize} a @nt{numeric_literal}; @begin{Ramification} A @nt<numeric_literal> is always a static expression, even if its expected type is not that of a static subtype. However, if its value is explicitly converted to, or qualified by, a nonstatic subtype, the resulting expression is nonstatic. @end{Ramification} a @nt{string_literal} of a static string subtype; @begin(Ramification) That is, the constrained subtype defined by the index range of the string is static. Note that elementary values don't generally have subtypes, while composite values do (since the bounds or discriminants are inherent in the value). @end(Ramification) a @nt{name} that denotes the declaration of a named number or a static constant; @begin{Ramification} Note that enumeration literals are covered by the @nt{function_call} case. @end{Ramification} a @nt{function_call} whose @SynI{function_}@nt{name} or @SynI{function_}@nt{prefix} statically denotes a static function, and whose actual parameters, if any (whether given explicitly or by default), are all static expressions; @begin{Ramification} This includes uses of operators that are equivalent to @nt{function_call}s. @end{Ramification} an @nt{attribute_reference} that denotes a scalar value, and whose @nt{prefix} denotes a static scalar subtype; @begin{Ramification} Note that this does not include the case of an attribute that is a function; a reference to such an attribute is not even an expression. See above for function @i{calls}. An implementation may define the staticness and other properties of implementation-defined attributes. @end{Ramification} an @nt{attribute_reference} whose @nt{prefix} statically denotes a statically constrained array object or array subtype, and whose @nt<attribute_designator> is First, Last, or Length, with an optional dimension; a @nt{type_conversion} whose @nt{subtype_mark} denotes a static scalar subtype, and whose operand is a static expression; a @nt{qualified_expression} whose @nt{subtype_mark} denotes a static @Redundant[(scalar or string)] subtype, and whose operand is a static expression; @begin{Ramification} This rules out the @nt{subtype_mark}'@nt{aggregate} case. @end{Ramification} @begin{Reason} Adding qualification to an expression shouldn't make it nonstatic, even for strings. @end{Reason} a membership test whose @nt{simple_expression} is a static expression, and whose @nt{range} is a static range or whose @nt{subtype_mark} denotes a static @Redundant[(scalar or string)] subtype; @begin{Reason} Clearly, we should allow membership tests in exactly the same cases where we allow @nt{qualified_expression}s. @end{Reason} a short-circuit control form both of whose @nt{relation}s are static expressions; a static expression enclosed in parentheses. @end{Itemize} @begin(Discussion) @Defn2{Term=[static], Sec=(value)} Informally, we talk about a @i(static value). When we do, we mean a value specified by a static expression. @end(Discussion) @begin{Ramification} The language requires a static expression in a @nt<number_declaration>, a numeric type definition, a @nt<discrete_choice> (sometimes), certain representation items, an @nt<attribute_designator>, and when specifying the value of a discriminant governing a @nt{variant_part} in a @nt<record_aggregate> or @nt<extension_aggregate>. @end{Ramification} @Leading@Defn2{Term=[statically], Sec=(denote)} A @nt{name} @i(statically denotes) an entity if it denotes the entity and: @begin(itemize) It is a @nt<direct_name>, expanded name, or @nt{character_literal}, and it denotes a declaration other than a @nt<renaming_declaration>; or It is an @nt{attribute_reference} whose @nt{prefix} statically denotes some entity; or It denotes a @nt<renaming_declaration> with a @nt<name> that statically denotes the renamed entity. @end(itemize) @begin{Ramification} @nt{Selected_component}s that are not expanded names and @nt{indexed_component}s do not statically denote things. @end{Ramification} @Leading@Defn2{Term=[static], Sec=(function)} A @i{static function} is one of the following: @begin{Ramification} These are the functions whose calls can be static expressions. @end{Ramification} @begin{Itemize} a predefined operator whose parameter and result types are all scalar types none of which are descendants of formal scalar types; a predefined concatenation operator whose result type is a string type; an enumeration literal; a language-defined attribute that is a function, if the @nt{prefix} denotes a static scalar subtype, and if the parameter and result types are scalar. @end{Itemize} In any case, a generic formal subprogram is not a static function. @Defn2{Term=[static], Sec=(constant)} A @i(static constant) is a constant view declared by a full constant declaration or an @nt<object_@!renaming_@!declaration> with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression whose value has a length not exceeding the maximum length of a @nt{string_@!literal} in the implementation. @begin{Ramification} A deferred constant is not static; the view introduced by the corresponding full constant declaration can be static. @end{Ramification} @begin{Reason} The reason for restricting the length of static string constants is so that compilers don't have to store giant strings in their symbol tables. Since most string constants will be initialized from @nt{string_literal}s, the length limit seems pretty natural. The reason for avoiding nonstring types is also to save symbol table space. We're trying to keep it cheap and simple (from the implementer's viewpoint), while still allowing, for example, the link name of a pragma Import to contain a concatenation. The length we're talking about is the maximum number of characters in the value represented by a @nt{string_literal}, not the number of characters in the source representation; the quotes don't count. @end{Reason} @Defn2{Term=[static], Sec=(range)} A @i(static range) is a @nt{range} whose bounds are static expressions, @Redundant[or a @nt<range_@!attribute_@!reference> that is equivalent to such a @nt<range>.] @Defn2{Term=[static], Sec=(discrete_range)} A @i(static @nt<discrete_@!range>) is one that is a static range or is a @nt<subtype_@!indication> that defines a static scalar subtype. The base range of a scalar type is a static range, unless the type is a descendant of a formal scalar type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00263-01]} @Defn2{Term=[static], Sec=(subtype)} A @i(static subtype) is either a @i(static scalar subtype) or a @i(static string subtype). @Defn2{Term=[static], Sec=(scalar subtype)} A static scalar subtype is an unconstrained scalar subtype whose type is not a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, or a constrained scalar subtype formed by imposing a compatible static constraint on a static scalar subtype. @Defn2{Term=[static], Sec=(string subtype)} A static string subtype is an unconstrained string subtype whose index subtype and component subtype are static@Chg{Version=[2],New=[],Old=[ (and whose type is not a descendant of a formal array type)]}, or a constrained string subtype formed by imposing a compatible static constraint on a static string subtype. In any case, the subtype of a generic formal object of mode @key[in out], and the result subtype of a generic formal function, are not static. @begin{Ramification} String subtypes are the only composite subtypes that can be static. @end{Ramification} @begin{Reason} @Leading@;The part about generic formal objects of mode @key[in out] is necessary because the subtype of the formal is not required to have anything to do with the subtype of the actual. For example: @begin{Example} @key[subtype] Int10 @key[is] Integer @key[range] 1..10; @key[generic] F : @key[in] @key[out] Int10; @key[procedure] G; @key[procedure] G @key[is] @key[begin] @key[case] F @key[is] @key[when] 1..10 => @key[null]; --@RI{ Illegal!} @key[end] @key[case]; @key[end] G; X : Integer @key[range] 1..20; @key[procedure] I @key[is] @key[new] G(F => X); --@RI{ OK.} @end{Example} The @nt{case_statement} is illegal, because the subtype of F is not static, so the choices have to cover all values of Integer, not just those in the range 1..10. A similar issue arises for generic formal functions, now that function calls are object names. @end{Reason} @Leading@Defn2{Term=[static], Sec=(constraint)} The different kinds of @i(static constraint) are defined as follows: @begin(itemize) A null constraint is always static; @Defn2{Term=[static], Sec=(range constraint)} @Defn2{Term=[static], Sec=(digits constraint)} @Defn2{Term=[static], Sec=(delta constraint)} A scalar constraint is static if it has no @nt<range_constraint>, or one with a static range; @Defn2{Term=[static], Sec=(index constraint)} An index constraint is static if each @nt<discrete_range> is static, and each index subtype of the corresponding array type is static; @Defn2{Term=[static], Sec=(discriminant constraint)} A discriminant constraint is static if each @nt<expression> of the constraint is static, and the subtype of each discriminant is static. @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00311-01]} @Chg{Version=[2],New=[In any case, the constraint of the first subtype of a scalar formal type is neither static nor null.],Old=[]} @Defn2{Term=[statically], Sec=(constrained)} A subtype is @i(statically constrained) if it is constrained, and its constraint is static. An object is @i(statically constrained) if its nominal subtype is statically constrained, or if it is a static string constant. @end{Intro} @begin{Legality} @Leading@;A static expression is evaluated at compile time except when it is part of the right operand of a static short-circuit control form whose value is determined by its left operand. This evaluation is performed exactly, without performing Overflow_Checks. For a static expression that is evaluated: @begin{Itemize} The expression is illegal if its evaluation fails a language-defined check other than Overflow_@!Check. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} If the expression is not part of a larger static expression@Chg{Version=[2],New=[ and the expression is expected to be of a single specific type],Old=[]}, then its value shall be within the base range of its expected type. Otherwise, the value may be arbitrarily large or small. @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[If the expression is expected to be of a universal type, or of @lquotes@;any integer type@rquotes, there are no limits on the value of the expression.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} If the expression is of type @i<universal_real> and its expected type is a decimal fixed point type, then its value shall be a multiple of the @i<small> of the decimal type.@Chg{Version=[2],New=[ This restriction does not apply if the expected type is a descendant of a formal scalar type (or a corresponding actual type in an instance).],Old=[]} @begin{Ramification} This means that a @nt{numeric_literal} for a decimal type cannot have @lquotes@;extra@rquotes@; significant digits. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[The small is not known for a generic formal type, so we have to exclude formal types from this check.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} @Chg{Version=[2],New=[@PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), the above restrictions also apply in the private part of an instance of a generic unit.],Old=[The last two restrictions above do not apply if the expected type is a descendant of a formal scalar type (or a corresponding actual type in an instance).]} @begin{Discussion} Values outside the base range are not permitted when crossing from the @lquotes@;static@rquotes@; domain to the @lquotes@;dynamic@rquotes@; domain. This rule is designed to enhance portability of programs containing static expressions. Note that this rule applies to the exact value, not the value after any rounding or truncation. (See below for the rounding and truncation requirements.) @Leading@;Short-circuit control forms are a special case: @begin{Example} N: @key[constant] := 0.0; X: @key[constant] Boolean := (N = 0.0) @key[or] @key[else] (1.0/N > 0.5); --@RI{ Static.} @end{Example} The declaration of X is legal, since the divide-by-zero part of the expression is not evaluated. X is a static constant equal to True. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00269-01]} @ChgDeleted{Version=[2],Text=[There is no requirement to recheck these rules in an instance; the base range check will generally be performed at run time anyway.]} @end{Ramification} @end{Legality} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00268-01],ARef=[AI95-00269-01]} For a real static expression that is not part of a larger static expression, and whose expected type is not a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, the implementation shall round or truncate the value (according to the Machine_Rounds attribute of the expected type) to the nearest machine number of the expected type; if the value is exactly half-way between two machine numbers, @Chg{Version=[2],New=[the],Old=[any]} rounding @Chg{Version=[2],New=[],Old=[shall be ]}performed @Chg{Version=[2],New=[is implementation-defined],Old=[away from zero]}. If the expected type is a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, @Chg{Version=[2],New=[or if the static expression appears in the body of an instance of a generic unit and the corresponding expression is nonstatic in the corresponding generic body, then],Old=[]} no special rounding or truncating is required @em normal accuracy rules apply (see @RefSecNum(Numerics)). @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[Rounding of real static expressions which are exactly half-way between two machine numbers.],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00268-01]} Discarding extended precision enhances portability by ensuring that the value of a static constant of a real type is always a machine number of the type. @Chg{Version=[2],New=[],Old=[Deterministic rounding of exact halves also enhances portability.]} When the expected type is a descendant of a formal floating point type, extended precision (beyond that of the machine numbers) can be retained when evaluating a static expression, to ease code sharing for generic instantiations. For similar reasons, normal (nondeterministic) rounding or truncating rules apply for descendants of a formal fixed point type. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[There is no requirement for exact evaluation or special rounding in an instance body (unless the expression is static in the generic body). This eliminates a potential contract issue where the exact value of a static expression depends on the actual parameters (which could then affect the legality of other code).]} @end{Reason} @begin{ImplNote} Note that the implementation of static expressions has to keep track of plus and minus zero for a type whose Signed_Zeros attribute is True. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00100-01]} Note that the only @Chg{Version=[2],New=[machine numbers],Old=[values]} of a fixed point type are the multiples of the small, so a static conversion to a fixed-point type, or division by an integer, must do truncation to a multiple of small. It is not correct for the implementation to do all static calculations in infinite precision. @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[For a real static expression that is not part of a larger static expression, and whose expected type is not a descendant of a formal type, the rounding should be the same as the default rounding for the target system.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For a real static expression with a non-formal type that is not part of a larger static expression should be rounded the same as the target system.]}]} @end{ImplAdvice} @begin{Notes} An expression can be static even if it occurs in a context where staticness is not required. @begin{Ramification} @Leading@keepnext@;For example: @begin{Example} X : Float := Float'(1.0E+400) + 1.0 - Float'(1.0E+400); @end{Example} The expression is static, which means that the value of X must be exactly 1.0, independent of the accuracy or range of the run-time floating point implementation. The following kinds of expressions are never static: @nt{explicit_dereference}, @nt{indexed_component}, @nt{slice}, @key{null}, @nt{aggregate}, @nt{allocator}. @end{Ramification} A static (or run-time) @nt<type_conversion> from a real type to an integer type performs rounding. If the operand value is exactly half-way between two integers, the rounding is performed away from zero. @begin{Reason} We specify this for portability. The reason for not choosing round-to-nearest-even, for example, is that this method is easier to undo. @end{Reason} @begin{Ramification} The attribute Truncation (see @RefSecNum{Attributes of Floating Point Types}) can be used to perform a (static) truncation prior to conversion, to prevent rounding. @end{Ramification} @begin{ImplNote} The value of the literal 0E999999999999999999999999999999999999999999999 is zero. The implementation must take care to evaluate such literals properly. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of static expressions:) @begin{Example} 1 + 1 @RI[-- 2] @key(abs)(-10)*3 @RI[-- 30] Kilo : @key(constant) := 1000; Mega : @key(constant) := Kilo*Kilo; @RI[-- 1_000_000] Long : @key(constant) := Float'Digits*2; Half_Pi : @key(constant) := Pi/2; @RI[-- see @RefSecNum(Number Declarations)] Deg_To_Rad : @key(constant) := Half_Pi/90; Rad_To_Deg : @key(constant) := 1.0/Deg_To_Rad; @RI[-- equivalent to 1.0/((3.14159_26536/2)/90)] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The rules for static expressions and static subtypes are generalized to allow more kinds of compile-time-known expressions to be used where compile-time-known values are required, as follows: @begin(itemize) Membership tests and short-circuit control forms may appear in a static expression. The bounds and length of statically constrained array objects or subtypes are static. The Range attribute of a statically constrained array subtype or object gives a static range. A @nt{type_conversion} is static if the @nt{subtype_mark} denotes a static scalar subtype and the operand is a static expression. All numeric literals are now static, even if the expected type is a formal scalar type. This is useful in @nt{case_statement}s and @nt{variant_part}s, which both now allow a value of a formal scalar type to control the selection, to ease conversion of a package into a generic package. Similarly, named array aggregates are also permitted for array types with an index type that is a formal scalar type. @end(itemize) The rules for the evaluation of static expressions are revised to require exact evaluation at compile time, and force a machine number result when crossing from the static realm to the dynamic realm, to enhance portability and predictability. Exact evaluation is not required for descendants of a formal scalar type, to simplify generic code sharing and to avoid generic contract model problems. @Leading@;Static expressions are legal even if an intermediate in the expression goes outside the base range of the type. Therefore, the following will succeed in Ada 95, whereas it might raise an exception in Ada 83: @begin{Example} @key[type] Short_Int @key[is] @key[range] -32_768 .. 32_767; I : Short_Int := -32_768; @end{Example} This might raise an exception in Ada 83 because "32_768" is out of range, even though "@en@;32_768" is not. In Ada 95, this will always succeed. Certain expressions involving string operations (in particular concatenation and membership tests) are considered static in Ada 95. The reason for this change is to simplify the rule requiring compile-time-known string expressions as the link name in an interfacing pragma, and to simplify the preelaborability rules. @end{Extend83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} An Ada 83 program that uses an out-of-range static value is illegal in Ada 95, unless the expression is part of a larger static expression, or the expression is not evaluated due to being on the right-hand side of a short-circuit control form. @end{Incompatible83} @begin{DiffWord83} This clause (and @RefSec{Multiplying Operators}) subsumes the RM83 section on Universal Expressions. The existence of static string expressions necessitated changing the definition of static subtype to include string subtypes. Most occurrences of "static subtype" have been changed to "static scalar subtype", in order to preserve the effect of the Ada 83 rules. This has the added benefit of clarifying the difference between "static subtype" and "statically constrained subtype", which has been a source of confusion. In cases where we allow static string subtypes, we explicitly use phrases like "static string subtype" or "static (scalar or string) subtype", in order to clarify the meaning for those who have gotten used to the Ada 83 terminology. @Leading@;In Ada 83, an expression was considered nonstatic if it raised an exception. Thus, for example: @begin{Example} Bad: @key[constant] := 1/0; --@RI{ Illegal!} @end{Example} was illegal because 1/0 was not static. In Ada 95, the above example is still illegal, but for a different reason: 1/0 is static, but there's a separate rule forbidding the exception raising. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Rounding of static real expressions is implementation-defined in Ada 2005, while it was specified as away from zero in (original) Ada 95. This could make subtle differences in programs. However, the original Ada 95 rule required rounding that (probably) differed from the target processor, thus creating anomalies where the value of a static expression was required to be different than the same expression evaluated at run-time.]} @end{Inconsistent95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00263-01],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[The Ada 95 wording that defined static subtypes unintentionally failed to exclude formal derived types that happen to be scalar (these aren't formal scalar types); and had a parenthetical remark excluding formal string types - but that was neither necessary nor parenthetical (it didn't follow from other wording). This issue also applies to the rounding rules for real static expressions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[Ada 95 didn't clearly define the bounds of a value of a static expression for universal types and for "any integer/float/fixed type". We also make it clear that we do not intend exact evaluation of static expressions in an instance body if the expressions aren't static in the generic body.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00311-01]} @ChgAdded{Version=[2],Text=[We clarify that the first subtype of a scalar formal type has a nonstatic, non-null constraint.]} @end{DiffWord95} @LabeledSubClause{Statically Matching Constraints and Subtypes} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00311-01]} @Defn2{Term=[statically matching], Sec=(for constraints)} A constraint @i(statically matches) another constraint if@Chg{Version=[2],New=[:],Old=[ both are null constraints, both are static and have equal corresponding bounds or discriminant values, or both are nonstatic and result from the same elaboration of a @nt<constraint> of a @nt<subtype_@!indication> or the same evaluation of a @nt<range> of a @nt<discrete_@!subtype_@!definition>.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are null constraints;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are static and have equal corresponding bounds or discriminant values;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are nonstatic and result from the same elaboration of a @nt<constraint> of a @nt<subtype_@!indication> or the same evaluation of a @nt<range> of a @nt<discrete_@!subtype_@!definition>; or],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00311-01]} @Chg{Version=[2],New=[both are nonstatic and come from the same @nt{formal_type_declaration}.],Old=[]} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @Defn2{Term=[statically matching], Sec=(for subtypes)} A subtype @i(statically matches) another subtype of the same type if they have statically matching constraints@Chg{Version=[2],New=[, and, for access subtypes, either both or neither exclude null],Old=[]}. Two anonymous access@Chg{Version=[2],New=[-to-object],Old=[]} subtypes statically match if their designated subtypes statically match@Chg{Version=[2],New=[, and either both or neither exclude null, and either both or neither are access-to-constant. Two anonymous access-to-subprogram subtypes statically match if their designated profiles are subtype conformant, and either both or neither exclude null],Old=[]}. @begin{Ramification} Statically matching constraints and subtypes are the basis for subtype conformance of profiles (see @RefSecNum(Conformance Rules)). @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Even though anonymous access types always represent different types, they can statically match. That's important so that they can be used widely. For instance, if this wasn't true, access parameters and access discriminants could never conform, so they couldn't be used in separate specifications.]} @end{Reason} @Defn2{Term=[statically matching], Sec=(for ranges)} Two ranges of the same type @i{statically match} if both result from the same evaluation of a @nt{range}, or if both are static and have equal corresponding bounds. @begin{Ramification} The notion of static matching of ranges is used in @RefSec{Formal Array Types}; the index ranges of formal and actual constrained array subtypes have to statically match. @end{Ramification} @Defn2{Term=[statically compatible], Sec=(for a constraint and a scalar subtype)} A constraint is @i(statically compatible) with a scalar subtype if it statically matches the constraint of the subtype, or if both are static and the constraint is compatible with the subtype. @Defn2{Term=[statically compatible], Sec=(for a constraint and an access or composite subtype)} A constraint is @i(statically compatible) with an access or composite subtype if it statically matches the constraint of the subtype, or if the subtype is unconstrained. @Defn2{Term=[statically compatible], Sec=(for two subtypes)} One subtype is @i(statically compatible) with a second subtype if the constraint of the first is statically compatible with the second subtype. @begin{Discussion} Static compatibility is required when constraining a parent subtype with a discriminant from a new @nt<discriminant_part>. See @RefSecNum{Discriminants}. Static compatibility is also used in matching generic formal derived types. Note that statically compatible with a subtype does not imply compatible with a type. It is OK since the terms are used in different contexts. @end{Discussion} @end{StaticSem} @begin{DiffWord83} This subclause is new to Ada 95. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @Chg{Version=[2],New=[Added static matching rules for null exclusions and anonymous access-to-subprogram types; both of these are new in Ada 2005.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00311-01]} @Chg{Version=[2],New=[We clarify that the constraint of the first subtype of a scalar formal type statically matches itself.],Old=[]} @end{DiffWord95} ���������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/05.mss���������������������������������������������������������������0000755�0001752�0001001�00000133627�12273462240�016405� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(05, Root="ada.mss") @Comment{$Date: 2006/10/17 05:29:45 $} @LabeledSection{Statements} @Comment{$Source: e:\\cvsroot/ARM/Source/05.mss,v $} @Comment{$Revision: 1.31 $} @begin{Intro} @Redundant[A @nt{statement} defines an action to be performed upon its execution.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Redundant[This section describes the general rules applicable to all @nt{statement}s. Some @nt{statement}s are discussed in later sections: @nt{Procedure_@!call_@!statement}s and @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} are described in @RefSec{Subprograms}. @nt{Entry_@!call_@!statement}s, @nt{requeue_@!statement}s, @nt{delay_@!statement}s, @nt{accept_@!statement}s, @nt{select_@!statement}s, and @nt{abort_@!statement}s are described in @RefSec{Tasks and Synchronization}. @nt{Raise_@!statement}s are described in @RefSec{Exceptions}, and @nt{code_@!statement}s in @RefSecNum{Representation Issues}. The remaining forms of @nt{statement}s are presented in this section.] @end{Intro} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The description of @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} has been moved to @RefSec{Return Statements}, so that it is closer to the description of subprograms. @end{DiffWord83} @LabeledClause{Simple and Compound Statements - Sequences of Statements} @begin{Intro} @Redundant[A @nt<statement> is either simple or compound. A @nt<simple_statement> encloses no other @nt<statement>. A @nt<compound_statement> can enclose @nt<simple_statement>s and other @nt<compound_statement>s.] @end{Intro} @begin{Syntax} @Syn{lhs=<sequence_of_statements>,rhs="@Syn2{statement} {@Syn2{statement}}"} @Syn{lhs=<statement>,rhs=" {@Syn2{label}} @Syn2{simple_statement} | {@Syn2{label}} @Syn2{compound_statement}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{tabs=[P31], lhs=<simple_statement>,rhs="@Syn2{null_statement} | @Syn2{assignment_statement}@\| @Syn2{exit_statement} | @Syn2{goto_statement}@\| @Syn2{procedure_call_statement} | @Chg{Version=[2],New=[@Syn2{simple_return_statement}],Old=[@Syn2{return_statement}]}@\| @Syn2{entry_call_statement} | @Syn2{requeue_statement}@\| @Syn2{delay_statement} | @Syn2{abort_statement}@\| @Syn2{raise_statement} | @Syn2{code_statement}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{tabs=[P31], lhs=<compound_statement>,rhs=" @Syn2{if_statement}@\| @Syn2{case_statement} | @Syn2{loop_statement}@\| @Syn2{block_statement}@Chg{Version=[2],New=[ | @Syn2{extended_return_statement}],Old=[]} | @Syn2{accept_statement}@\| @Syn2{select_statement}"} @Syn{lhs=<null_statement>,rhs="@key{null};"} @Syn{lhs=<label>,rhs="<<@SynI{label_}@Syn2{statement_identifier}>>"} @Syn{lhs=<statement_identifier>,rhs="@Syn2{direct_name}"} @begin(SyntaxText) The @nt<direct_name> of a @nt<statement_identifier> shall be an @nt<identifier> (not an @nt<operator_symbol>). @end(SyntaxText) @end{Syntax} @begin{Resolution} The @nt<direct_name> of a @nt<statement_identifier> shall resolve to denote its corresponding implicit declaration (see below). @end{Resolution} @begin{Legality} Distinct @nt{identifier}s shall be used for all @nt<statement_identifier>s that appear in the same body, including inner @nt{block_statement}s but excluding inner program units. @end{Legality} @begin{StaticSem} For each @nt<statement_identifier>, there is an implicit declaration (with the specified @nt<identifier>) at the end of the @nt{declarative_part} of the innermost @nt{block_statement} or body that encloses the @nt{statement_identifier}. The implicit declarations occur in the same order as the @nt<statement_identifier>s occur in the source text. If a usage name denotes such an implicit declaration, the entity it denotes is the @nt<label>, @nt<loop_statement>, or @nt<block_statement> with the given @nt<statement_identifier>. @begin{Reason} We talk in terms of individual @nt<statement_identifier>s here rather than in terms of the corresponding statements, since a given @nt{statement} may have multiple @nt<statement_identifier>s. A @nt{block_statement} that has no explicit @nt{declarative_part} has an implicit empty @nt{declarative_part}, so this rule can safely refer to the @nt{declarative_part} of a @nt<block_statement>. The scope of a declaration starts at the place of the declaration itself (see @RefSecNum{Scope of Declarations}). In the case of a label, loop, or block name, it follows from this rule that the scope of the implicit declaration starts before the first explicit occurrence of the corresponding name, since this occurrence is either in a statement label, a @nt{loop_statement}, a @nt{block_statement}, or a @nt{goto_statement}. An implicit declaration in a @nt{block_statement} may hide a declaration given in an outer program unit or @nt{block_statement} (according to the usual rules of hiding explained in @RefSecNum{Visibility}). The syntax rule for @nt{label} uses @nt{statement_identifier} which is a @nt<direct_name> (not a @nt{defining_identifier}), because labels are implicitly declared. The same applies to loop and block names. In other words, the @nt{label} itself is not the defining occurrence; the implicit declaration is. @Leading@;We cannot consider the @nt{label} to be a defining occurrence. An example that can tell the difference is this: @begin{example} @key[declare] --@RI{ Label Foo is implicitly declared here.} @key[begin] @key[for] Foo @key[in] ... @key[loop] ... <<Foo>> --@RI{ Illegal.} ... @key[end] @key[loop]; @key[end]; @end{example} The label in this example is hidden from itself by the loop parameter with the same name; the example is illegal. We considered creating a new syntactic category name, separate from @nt{direct_name} and @nt{selector_name}, for use in the case of statement labels. However, that would confuse the rules in Section 8, so we didn't do it. @end{Reason} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(null_statement)} The execution of a @nt{null_statement} has no effect. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{transfer of control} A @i{transfer of control} is the run-time action of an @nt{exit_statement}, @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}, @nt{goto_statement}, or @nt{requeue_statement}, selection of a @nt{terminate_alternative}, raising of an exception, or an abort, which causes the next action performed to be one other than what would normally be expected from the other rules of the language. @Redundant[As explained in @RefSecNum{Completion and Finalization}, a transfer of control can cause the execution of constructs to be completed and then left, which may trigger finalization.] @PDefn2{Term=[execution], Sec=(sequence_of_statements)} The execution of a @nt{sequence_of_statements} consists of the execution of the individual @nt{statement}s in succession until the @ntf{sequence_} is completed. @begin{Ramification} It could be completed by reaching the end of it, or by a transfer of control. @end{Ramification} @end{RunTime} @begin{Notes} A @nt<statement_identifier> that appears immediately within the declarative region of a named @nt<loop_statement> or an @nt<accept_statement> is nevertheless implicitly declared immediately within the declarative region of the innermost enclosing body or @nt<block_statement>; in other words, the expanded name for a named statement is not affected by whether the statement occurs inside or outside a named loop or an @nt<accept_statement> @em only nesting within @nt<block_statement>s is relevant to the form of its expanded name. @begin{Discussion} @Leading@keepnext@;Each comment in the following example gives the expanded name associated with an entity declared in the task body: @begin{Example} @key(task body) Compute @key(is) Sum : Integer := 0; --@RI[ Compute.Sum] @key(begin) Outer: --@RI[ Compute.Outer] @key(for) I @key(in) 1..10 @key(loop) --@RI[ Compute.Outer.I] Blk: --@RI[ Compute.Blk] @key(declare) Sum : Integer := 0; --@RI[ Compute.Blk.Sum] @key(begin) @key(accept) Ent(I : out Integer; J : in Integer) @key(do) --@RI[ Compute.Ent.I, Compute.Ent.J] Compute.Ent.I := Compute.Outer.I; Inner: --@RI[ Compute.Blk.Inner] @key(for) J @key(in) 1..10 @key(loop) --@RI[ Compute.Blk.Inner.J] Sum := Sum + Compute.Blk.Inner.J * Compute.Ent.J; @key(end loop) Inner; @key(end) Ent; Compute.Sum := Compute.Sum + Compute.Blk.Sum; @key(end) Blk; @key(end loop) Outer; Record_Result(Sum); @key(end) Compute; @end{Example} @end{Discussion} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of labeled statements:} @begin{Example} <<Here>> <<Ici>> <<Aqui>> <<Hier>> @key[null]; <<After>> X := 1; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{requeue_statement} is new. @end{Extend83} @begin{DiffWord83} We define the syntactic category @nt<statement_identifier> to simplify the description. It is used for labels, loop names, and block names. We define the entity associated with the implicit declarations of statement names. Completion includes completion caused by a transfer of control, although RM83-5.1(6) did not take this view. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{extended_return_statement} is new (@nt{simple_return_statement} is merely renamed).]} @end{Extend95} @LabeledClause{Assignment Statements} @begin{Intro} @Redundant[An @nt{assignment_statement} replaces the current value of a variable with the result of evaluating an @nt<expression>.] @end{Intro} @begin{Syntax} @Syn{lhs=<assignment_statement>,rhs=" @SynI{variable_}@Syn2{name} := @Syn2{expression};"} @end{Syntax} @begin{Intro} The execution of an @nt<assignment_statement> includes the evaluation of the @nt<expression> and the @i(assignment) of the value of the @nt<expression> into the @i(target). @RootDefn{assignment operation} @IndexSee{Term=[assign], See=(assignment operation)} @Redundant[An assignment operation (as opposed to an @nt<assignment_@!statement>) is performed in other contexts as well, including object initialization and by-copy parameter passing.] @Defn2{Term=[target], Sec=(of an assignment operation)} @Defn2{Term=[target], Sec=(of an @nt{assignment_statement})} The @i{target} of an assignment operation is the view of the object to which a value is being assigned; the target of an @nt{assignment_@!statement} is the variable denoted by the @SynI{variable_}@nt{name}. @begin{Discussion} Don't confuse this notion of the @lquotes@;target@rquotes@; of an assignment with the notion of the @lquotes@;target object@rquotes@; of an entry call or requeue. Don't confuse the term @lquotes@;assignment operation@rquotes@; with the @nt{assignment_statement}. The assignment operation is just one part of the execution of an @nt{assignment_statement}. The assignment operation is also a part of the execution of various other constructs; see @RefSec{Completion and Finalization} for a complete list. Note that when we say, @lquotes@;such-and-such is assigned to so-and-so@rquotes@;, we mean that the assignment operation is being applied, and that so-and-so is the target of the assignment operation. @end{Discussion} @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(assignment_statement variable_name)} The @i(variable_)@nt<name> of an @nt<assignment_statement> is expected to be of any @Chg{Version=[2],New=[],Old=[nonlimited ]}type. @PDefn2{Term=[expected type], Sec=(assignment_statement expression)} The expected type for the @nt<expression> is the type of the target. @begin{ImplNote} @Leading@keepnext@;An @nt<assignment_statement> as a whole is a "complete context," so if the @i{variable_}@nt<name> of an @nt<assignment_statement> is overloaded, the @nt<expression> can be used to help disambiguate it. For example: @begin{Example} @key[type] P1 @key[is access] R1; @key[type] P2 @key[is access] R2; @key[function] F return P1; @key[function] F return P2; X : R1; @key[begin] F.all := X; --@RI[ Right hand side helps resolve left hand side] @end{Example} @end{ImplNote} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} The target @Redundant[denoted by the @i(variable_)@nt<name>] shall be a variable@Chg{Version=[2],New=[ of a nonlimited type],Old=[]}. If the target is of a tagged class-wide type @i(T)'Class, then the @nt<expression> shall either be dynamically tagged, or of type @i(T) and tag-indeterminate (see @RefSecNum{Dispatching Operations of Tagged Types}). @begin{Reason} This is consistent with the general rule that a single dispatching operation shall not have both dynamically tagged and statically tagged operands. Note that for an object initialization (as opposed to the @nt{assignment_statement}), a statically tagged initialization expression is permitted, since there is no chance for confusion (or Tag_Check failure). Also, in an object initialization, tag-indeterminate expressions of any type covered by @i(T)'Class would be allowed, but with an @nt{assignment_statement}, that might not work if the tag of the target was for a type that didn't have one of the dispatching operations in the tag-indeterminate expression. @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(assignment_statement)} For the execution of an @nt{assignment_statement}, the @i(variable_)@nt<name> and the @nt<expression> are first evaluated in an arbitrary order. @begin{Ramification} Other rules of the language may require that the bounds of the variable be determined prior to evaluating the @nt<expression>, but that does not necessarily require evaluation of the @i(variable_)@nt<name>, as pointed out by the ACID. @end{Ramification} @Leading@keepnext@;When the type of the target is class-wide: @begin(itemize) @PDefn2{Term=[controlling tag value], Sec=(for the @nt{expression} in an @nt{assignment_statement})} If the @nt<expression> is tag-indeterminate (see @RefSecNum{Dispatching Operations of Tagged Types}), then the controlling tag value for the @nt<expression> is the tag of the target; @begin{Ramification} See @RefSec(Dispatching Operations of Tagged Types). @end{Ramification} @IndexCheck{Tag_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Otherwise @Redundant[(the @nt<expression> is dynamically tagged)], a check is made that the tag of the value of the @nt<expression> is the same as that of the target; if this check fails, Constraint_Error is raised. @end(itemize) The value of the @nt<expression> is converted to the subtype of the target. @Redundant[The conversion might raise an exception (see @RefSecNum{Type Conversions}).] @PDefn2{Term=[implicit subtype conversion],Sec=(assignment_statement)} @begin{Ramification} @RefSec(Type Conversions) defines what actions and checks are associated with subtype conversion. For non-array subtypes, it is just a constraint check presuming the types match. For array subtypes, it checks the lengths and slides if the target is constrained. @lquotes@;Sliding@rquotes@; means the array doesn't have to have the same bounds, so long as it is the same length. @end{Ramification} In cases involving controlled types, the target is finalized, and an anonymous object might be used as an intermediate in the assignment, as described in @RefSec{Completion and Finalization}. @Defn{assignment operation} @Defn2{Term=[assignment operation], Sec=(during execution of an @nt{assignment_statement})} In any case, the converted value of the @nt<expression> is then @i(assigned) to the target, which consists of the following two steps: @begin{Honest} @RefSecNum{Completion and Finalization} actually says that finalization happens always, but unless controlled types are involved, this finalization during an @nt{assignment_statement} does nothing. @end{Honest} @begin(itemize) The value of the target becomes the converted value. If any part of the target is controlled, its value is adjusted as explained in clause @RefSecNum{User-Defined Assignment and Finalization}. @PDefn2{Term=[adjustment], Sec=(as part of assignment)} @begin{Ramification} If any parts of the object are controlled, abort is deferred during the assignment operation itself, but not during the rest of the execution of an @nt<assignment_statement>. @end{Ramification} @end(itemize) @end{RunTime} @begin{Notes} The tag of an object never changes; in particular, an @nt{assignment_statement} does not change the tag of the target. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[The values of the discriminants of an object designated by an access value cannot be changed (not even by assigning a complete value to the object itself) since such objects are always constrained; however, subcomponents of such objects may be unconstrained.]} @begin{Ramification} The implicit subtype conversion described above for @nt{assignment_statement}s is performed only for the value of the right-hand side expression as a whole; it is not performed for subcomponents of the value. The determination of the type of the variable of an @nt{assignment_statement} may require consideration of the expression if the variable name can be interpreted as the name of a variable designated by the access value returned by a function call, and similarly, as a component or slice of such a variable (see @RefSec{The Context of Overload Resolution}). @end{Ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of assignment statements:} @begin{Example} Value := Max_Value - 1; Shade := Blue; Next_Frame(F)(M, N) := 2.5; --@RI{ see @RefSecNum{Indexed Components}} U := Dot_Product(V, W); --@RI{ see @RefSecNum{Subprogram Bodies}} Writer := (Status => Open, Unit => Printer, Line_Count => 60); --@RI{ see @RefSecNum{Variant Parts and Discrete Choices}} Next_Car.@key[all] := (72074, @key[null]); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @end{Example} @begin{Wide} @Leading@keepnext@i{Examples involving scalar subtype conversions:} @end{Wide} @begin{Example} I, J : Integer @key[range] 1 .. 10 := 5; K : Integer @key[range] 1 .. 20 := 15; ... I := J; --@RI{ identical ranges} K := J; --@RI{ compatible ranges} J := K; --@RI{ will raise Constraint_Error if K > 10} @end{Example} @begin{Wide} @leading@keepnext@i{Examples involving array subtype conversions:} @end{Wide} @begin{Example} A : String(1 .. 31); B : String(3 .. 33); ... A := B; --@RI{ same number of components} A(1 .. 9) := "tar sauce"; A(4 .. 12) := A(1 .. 9); --@RI{ A(1 .. 12) = "tartar sauce"} @end{Example} @end{Examples} @begin{Notes} @i{Notes on the examples:} @nt{Assignment_statement}s are allowed even in the case of overlapping slices of the same array, because the @SynI{variable_}@nt{name} and @nt{expression} are both evaluated before copying the value into the variable. In the above example, an implementation yielding A(1 .. 12) = "tartartartar" would be incorrect. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} We now allow user-defined finalization and value adjustment actions as part of @nt{assignment_statement}s (see @RefSec{User-Defined Assignment and Finalization}). @end{Extend83} @begin{DiffWord83} The special case of array assignment is subsumed by the concept of a subtype conversion, which is applied for all kinds of types, not just arrays. For arrays it provides @lquotes@;sliding@rquotes@;. For numeric types it provides conversion of a value of a universal type to the specific type of the target. For other types, it generally has no run-time effect, other than a constraint check. We now cover in a general way in @RefSecNum{Operations of Discriminated Types} the erroneous execution possible due to changing the value of a discriminant when the variable in an @nt<assignment_statement> is a subcomponent that depends on discriminants. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @Chg{Version=[2],New=[@Defn{incompatibilities with Ada 95} The change of the limited check from a resolution rule to a legality rule is not quite upward compatible. For example],Old=[]}. @begin{Example} @Chg{Version=[2],New=[@key{type} AccNonLim @key{is} @key{access} NonLim; @key{function} Foo (Arg : in Integer) @key{return} AccNonLim; @key{type} AccLim @key{is} @key{access} Lim; @key{function} Foo (Arg : in Integer) @key{return} AccLim; Foo(2).@key{all} := Foo(1).@key{all};],Old=[]}. @end{Example} @ChgAdded{Version=[2],Text=[where NonLim is a nonlimited type and Lim is a limited type. The assignment is legal in Ada 95 (only the first Foo would be considered), and is ambiguous in Ada 2005. We made the change because we want limited types to be as similar to nonlimited types as possible. Limited expressions are now allowed in all other contexts (with a similar incompatibility), and it would be odd if assignments had different resolution rules (which would eliminate ambiguities in some cases). Moreover, examples like this one are rare, as they depend on assigning into overloaded function calls.]} @end{Incompatible95} @LabeledClause{If Statements} @begin{Intro} @Redundant[An @nt{if_statement} selects for execution at most one of the enclosed @ntf{sequences_of_statements}, depending on the (truth) value of one or more corresponding @nt{condition}s.] @end{Intro} @begin{Syntax} @Syn{lhs=<if_statement>,rhs=" @key{if} @Syn2{condition} @key{then} @Syn2{sequence_of_statements} {@key{elsif} @Syn2{condition} @key{then} @Syn2{sequence_of_statements}} [@key{else} @Syn2{sequence_of_statements}] @key{end} @key{if};"} @Syn{lhs=<condition>,rhs="@SynI{boolean_}@Syn2{expression}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(condition)} A @nt{condition} is expected to be of any boolean type. @end{Resolution} @begin{RunTime} @PDefn2{Term=[execution], Sec=(if_statement)} For the execution of an @nt{if_statement}, the @nt{condition} specified after @key{if}, and any @nt{condition}s specified after @key{elsif}, are evaluated in succession (treating a final @key{else} as @key{elsif} True @key{then}), until one evaluates to True or all @nt{condition}s are evaluated and yield False. If a @nt{condition} evaluates to True, then the corresponding @nt{sequence_of_statements} is executed; otherwise none of them is executed. @begin{Ramification} The part about all evaluating to False can't happen if there is an @key{else}, since that is herein considered equivalent to @key{elsif} True @key{then}. @end{Ramification} @end{RunTime} @begin{Examples} @Leading@keepnext@i{Examples of if statements:} @begin{Example} @key[if] Month = December @key[and] Day = 31 @key[then] Month := January; Day := 1; Year := Year + 1; @key[end] @key[if]; @key[if] Line_Too_Short @key[then] @key[raise] Layout_Error; @key[elsif] Line_Full @key[then] New_Line; Put(Item); @key[else] Put(Item); @key[end] @key[if]; @key[if] My_Car.Owner.Vehicle /= My_Car @key[then] --@RI{ see @RefSecNum{Incomplete Type Declarations}} Report ("Incorrect data"); @key[end] @key[if]; @end{Example} @end{Examples} @LabeledClause{Case Statements} @begin{Intro} @Redundant[A @nt{case_statement} selects for execution one of a number of alternative @ntf{sequences_of_statements}; the chosen alternative is defined by the value of an expression.] @end{Intro} @begin{Syntax} @Syn{lhs=<case_statement>,rhs=" @key{case} @Syn2{expression} @key{is} @Syn2{case_statement_alternative} {@Syn2{case_statement_alternative}} @key{end} @key{case};"} @Syn{lhs=<case_statement_alternative>,rhs=" @key{when} @Syn2{discrete_choice_list} => @Syn2{sequence_of_statements}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(case expression)} The @nt{expression} is expected to be of any discrete type. @PDefn2{Term=[expected type], Sec=(case_statement_alternative discrete_choice)} The expected type for each @nt{discrete_choice} is the type of the @nt{expression}. @end{Resolution} @begin{Legality} The @nt{expression}s and @nt{discrete_range}s given as @nt{discrete_choice}s of a @nt{case_statement} shall be static. @Redundant[A @nt{discrete_choice} @key(others), if present, shall appear alone and in the last @nt{discrete_choice_list}.] The possible values of the @nt{expression} shall be covered as follows: @begin{itemize} If the @nt{expression} is a @nt{name} @Redundant[(including a @nt<type_conversion> or a @nt<function_call>)] having a static and constrained nominal subtype, or is a @nt{qualified_expression} whose @nt{subtype_mark} denotes a static and constrained scalar subtype, then each non-@key{others} @nt{discrete_choice} shall cover only values in that subtype, and each value of that subtype shall be covered by some @nt{discrete_choice} @Redundant[(either explicitly or by @key(others))]. @begin{Ramification} Although not official @nt<name>s of objects, a value conversion still has a defined nominal subtype, namely its target subtype. See @RefSecNum{Type Conversions}. @end{Ramification} If the type of the @nt{expression} is @i(root_integer), @i(universal_integer), or a descendant of a formal scalar type, then the @nt{case_statement} shall have an @key{others} @nt{discrete_choice}. @begin{Reason} This is because the base range is implementation defined for @i(root_integer) and @i(universal_integer), and not known statically in the case of a formal scalar type. @end{Reason} Otherwise, each value of the base range of the type of the @nt{expression} shall be covered @Redundant[(either explicitly or by @key(others))]. @end{itemize} Two distinct @nt{discrete_choice}s of a @nt{case_statement} shall not cover the same value. @begin{Ramification} The goal of these coverage rules is that any possible value of the @nt{expression} of a @nt{case_statement} should be covered by exactly one @nt{discrete_choice} of the @nt{case_statement}, and that this should be checked at compile time. The goal is achieved in most cases, but there are two minor loopholes: @begin{Itemize} If the expression reads an object with an invalid representation (e.g. an uninitialized object), then the value can be outside the covered range. This can happen for static constrained subtypes, as well as nonstatic or unconstrained subtypes. It cannot, however, happen if the @nt{case_statement} has the @nt{discrete_choice} @key{others}, because @key{others} covers all values, even those outside the subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} If the compiler chooses to represent the value of an expression of an unconstrained subtype in a way that includes values outside the bounds of the subtype, then those values can be outside the covered range. For example, if X: Integer := Integer'Last;, and the case @nt{expression} is X+1, then the implementation might choose to produce the correct value, which is outside the bounds of Integer. (It might raise Constraint_Error instead.) This case can only happen for non-generic subtypes that are either unconstrained or non@Chg{Version=[2],New=[],Old=[-]}@ChgNote{Make spelling consistent}static (or both). It can only happen if there is no @key{others} @nt{discrete_choice}. @end{Itemize} In the uninitialized variable case, the value might be anything; hence, any alternative can be chosen, or Constraint_Error can be raised. (We intend to prevent, however, jumping to random memory locations and the like.) In the out-of-range case, the behavior is more sensible: if there is an @key{others}, then the implementation may choose to raise Constraint_Error on the evaluation of the @nt{expression} (as usual), or it may choose to correctly evaluate the @nt{expression} and therefore choose the @key{others} alternative. Otherwise (no @key{others}), Constraint_Error is raised either way @em on the @nt{expression} evaluation, or for the @nt{case_statement} itself. For an enumeration type with a discontiguous set of internal codes (see @RefSecNum{Enumeration Representation Clauses}), the only way to get values in between the proper values is via an object with an invalid representation; there is no @lquotes@;out-of-range@rquotes@; situation that can produce them. @end{Ramification} @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(case_statement)} For the execution of a @nt{case_statement} the @nt{expression} is first evaluated. If the value of the @nt{expression} is covered by the @nt{discrete_@!choice_@!list} of some @nt{case_@!statement_@!alternative}, then the @nt{sequence_of_@!statements} of the @ntf{_alternative} is executed. @IndexCheck{Overflow_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Otherwise (the value is not covered by any @nt{discrete_choice_list}, perhaps due to being outside the base range), Constraint_Error is raised. @begin{Ramification} In this case, the value is outside the base range of its type, or is an invalid representation. @end{Ramification} @end{RunTime} @begin{Notes} The execution of a @nt{case_statement} chooses one and only one alternative. Qualification of the expression of a @nt{case_statement} by a static subtype can often be used to limit the number of choices that need be given explicitly. @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of case statements:} @begin{Example} @tabclear()@tabset(P22) @key[case] Sensor @key[is] @key[when] Elevation@\=> Record_Elevation(Sensor_Value); @key[when] Azimuth@\=> Record_Azimuth (Sensor_Value); @key[when] Distance@\=> Record_Distance (Sensor_Value); @key[when] @key[others]@\=> @key[null]; @key[end] @key[case]; @tabclear()@tabset(P22) @key[case] Today @key[is] @key[when] Mon@\=> Compute_Initial_Balance; @key[when] Fri@\=> Compute_Closing_Balance; @key[when] Tue .. Thu@\=> Generate_Report(Today); @key[when] Sat .. Sun@\=> @key[null]; @key[end] @key[case]; @tabclear()@tabset(P16) @key[case] Bin_Number(Count) @key[is] @key[when] 1@\=> Update_Bin(1); @key[when] 2@\=> Update_Bin(2); @key[when] 3 | 4@\=> Empty_Bin(1); Empty_Bin(2); @key[when] @key[others]@\=> @key[raise] Error; @key[end] @key[case]; @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00020} @Chg{New=[@Defn{incompatibilities with Ada 83} In Ada 95, @nt{function_call}s and @nt{type_conversion}s are @nt{name}s, whereas in Ada 83, they were @nt{expression}s. Therefore, if the @nt{expression} of a @nt{case_statement} is a @nt{function_call} or @nt{type_conversion}, and the result subtype is static, it is illegal to specify a choice outside the bounds of the subtype. For this case in Ada 83 choices only are required to be in the base range of the type.],Old=[]} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00020} @Chg{New=[In addition, the rule about which choices must be covered is unchanged in Ada 95. Therefore, for a @nt{case_statement} whose @nt{expression} is a @nt{function_call} or @nt{type_conversion}, Ada 83 required covering all choices in the base range, while Ada 95 only requires covering choices in the bounds of the subtype. If the @nt{case_statement} does not include an @key{others} @nt{discrete_choice}, then a legal Ada 83 @nt{case_statement} will be illegal in Ada 95 if the bounds of the subtype are different than the bounds of the base type.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, the @nt{expression} in a @nt{case_statement} is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an @key{others} @nt{discrete_choice} is required instead. In Ada 95, a function call is the name of an object; this was not true in Ada 83 (see @RefSec{Names}). This change makes the following @nt{case_statement} legal: @begin{Example} @key[subtype] S @key[is] Integer @key[range] 1..2; @key[function] F @key[return] S; @key[case] F @key[is] @key[when] 1 => ...; @key[when] 2 => ...; --@RI{ No @key{others} needed.} @key[end] @key[case]; @end{Example} Note that the result subtype given in a function @nt{renaming_declaration} is ignored; for a @nt{case_statement} whose expression calls a such a function, the full coverage rules are checked using the result subtype of the original function. Note that predefined operators such as "+" have an unconstrained result subtype (see @RefSecNum{Logical Operators and Short-circuit Control Forms}). Note that generic formal functions do not have static result subtypes. Note that the result subtype of an inherited subprogram need not correspond to any namable subtype; there is still a perfectly good result subtype, though. @end{Extend83} @begin{DiffWord83} Ada 83 forgot to say what happens for @lquotes@;legally@rquotes@; out-of-bounds values. We take advantage of rules and terms (e.g. @i(cover a value)) defined for @nt{discrete_choice}s and @nt{discrete_choice_list}s in @RefSec{Variant Parts and Discrete Choices}. In the @ResolutionName for the case expression, we no longer need RM83-5.4(3)'s @lquotes@;which must be determinable independently of the context in which the expression occurs, but using the fact that the expression must be of a discrete type,@rquotes@; because the @nt{expression} is now a complete context. See @RefSec{The Context of Overload Resolution}. Since @nt<type_conversion>s are now defined as @nt<name>s, their coverage rule is now covered under the general rule for @nt<name>s, rather than being separated out along with @nt<qualified_expression>s. @end{DiffWord83} @LabeledClause{Loop Statements} @begin{Intro} @Redundant[A @nt{loop_statement} includes a @nt{sequence_of_statements} that is to be executed repeatedly, zero or more times.] @end{Intro} @begin{Syntax} @Syn{lhs=<loop_statement>,rhs=" [@SynI{loop_}@Syn2{statement_identifier}:] [@Syn2{iteration_scheme}] @key{loop} @Syn2{sequence_of_statements} @key{end} @key{loop} [@SynI{loop_}@Syn2{identifier}];"} @Syn{lhs=<iteration_scheme>,rhs="@key{while} @Syn2{condition} | @key{for} @Syn2{loop_parameter_specification}"} @Syn{lhs=<loop_parameter_specification>,rhs=" @Syn2{defining_identifier} @key{in} [@key{reverse}] @Syn2{discrete_subtype_definition}"} @begin(SyntaxText) If a @nt{loop_statement} has a @SynI{loop_}@nt{statement_identifier}, then the @nt<identifier> shall be repeated after the @key{end loop}; otherwise, there shall not be an @nt<identifier> after the @key{end loop}. @end(SyntaxText) @end{Syntax} @begin{StaticSem} @Defn{loop parameter} A @nt{loop_parameter_specification} declares a @i{loop parameter}, which is an object whose subtype is that defined by the @nt{discrete_subtype_definition}. @IndexSeeAlso{Term=[parameter],See=[loop parameter]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(loop_statement)} For the execution of a @nt{loop_statement}, the @nt{sequence_of_statements} is executed repeatedly, zero or more times, until the @nt{loop_statement} is complete. The @nt{loop_statement} is complete when a transfer of control occurs that transfers control out of the loop, or, in the case of an @nt{iteration_scheme}, as specified below. @PDefn2{Term=[execution], Sec=(loop_statement with a while iteration_scheme)} For the execution of a @nt{loop_statement} with a @key{while} @nt{iteration_scheme}, the condition is evaluated before each execution of the @nt{sequence_of_@!statements}; if the value of the @nt{condition} is True, the @nt{sequence_of_@!statements} is executed; if False, the execution of the @nt{loop_@!statement} is complete. @PDefn2{Term=[execution], Sec=(loop_statement with a for iteration_scheme)} @PDefn2{Term=[elaboration], Sec=(loop_parameter_specification)} For the execution of a @nt{loop_statement} with a @key{for} @nt{iteration_scheme}, the @nt{loop_@!parameter_@!specification} is first elaborated. This elaboration creates the loop parameter and elaborates the @nt{discrete_@!subtype_@!definition}. If the @nt{discrete_@!subtype_@!definition} defines a subtype with a null range, the execution of the @nt{loop_statement} is complete. Otherwise, the @nt{sequence_of_@!statements} is executed once for each value of the discrete subtype defined by the @nt{discrete_@!subtype_@!definition} (or until the loop is left as a consequence of a transfer of control). @Defn2{Term=[assignment operation], Sec=(during execution of a @key{for} loop)} Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter. These values are assigned in increasing order unless the reserved word @key{reverse} is present, in which case the values are assigned in decreasing order. @begin{Ramification} The order of creating the loop parameter and evaluating the @nt{discrete_subtype_definition} doesn't matter, since the creation of the loop parameter has no side effects (other than possibly raising Storage_Error, but anything can do that). @end{Ramification} @end{RunTime} @begin{Notes} A loop parameter is a constant; it cannot be updated within the @nt{sequence_of_statements} of the loop (see @RefSecNum{Objects and Named Numbers}). An @nt{object_declaration} should not be given for a loop parameter, since the loop parameter is automatically declared by the @nt{loop_parameter_specification}. The scope of a loop parameter extends from the @nt{loop_parameter_specification} to the end of the @nt{loop_statement}, and the visibility rules are such that a loop parameter is only visible within the @nt{sequence_of_statements} of the loop. @begin{ImplNote} An implementation could give a warning if a variable is hidden by a @nt{loop_parameter_specification}. @end{ImplNote} The @nt<discrete_subtype_definition> of a for loop is elaborated just once. Use of the reserved word @key[reverse] does not alter the discrete subtype defined, so that the following @nt{iteration_scheme}s are not equivalent; the first has a null range. @begin{Example} @key[for] J @key[in] @key[reverse] 1 .. 0 @key[for] J @key[in] 0 .. 1 @end{Example} @begin{Ramification} If a @nt{loop_parameter_specification} has a static discrete range, the subtype of the loop parameter is static. @end{Ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of a loop statement without an iteration scheme:} @begin{Example} @key[loop] Get(Current_Character); @key[exit] @key[when] Current_Character = '*'; @key[end] @key[loop]; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a loop statement with a @key[while] iteration scheme:} @end{Wide} @begin{Example} @key[while] Bid(N).Price < Cut_Off.Price @key[loop] Record_Bid(Bid(N).Price); N := N + 1; @key[end] @key[loop]; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a loop statement with a @key[for] iteration scheme:} @end{Wide} @begin{Example} @key[for] J @key[in] Buffer'Range @key[loop] --@RI{ works even with a null range} @key[if] Buffer(J) /= Space @key[then] Put(Buffer(J)); @key[end] @key[if]; @key[end] @key[loop]; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a loop statement with a name:} @end{Wide} @begin{Example} Summation: @key[while] Next /= Head @key[loop] --@RI{ see @RefSecNum{Incomplete Type Declarations}} Sum := Sum + Next.Value; Next := Next.Succ; @key[end] @key[loop] Summation; @end{Example} @end{Examples} @begin{DiffWord83} The constant-ness of loop parameters is specified in @RefSec{Objects and Named Numbers}. @end{DiffWord83} @RMNewPage @LabeledClause{Block Statements} @begin{Intro} @Redundant[A @nt{block_statement} encloses a @nt{handled_sequence_of_statements} optionally preceded by a @nt{declarative_part}.] @end{Intro} @begin{Syntax} @Syn{lhs=<block_statement>,rhs=" [@SynI{block_}@Syn2{statement_identifier}:] [@key{declare} @Syn2{declarative_part}] @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{block_}@Syn2{identifier}];"} @begin(SyntaxText) If a @nt{block_statement} has a @SynI{block_}@nt{statement_identifier}, then the @nt<identifier> shall be repeated after the @key{end}; otherwise, there shall not be an @nt<identifier> after the @key{end}. @end(SyntaxText) @end{Syntax} @begin{StaticSem} A @nt{block_statement} that has no explicit @nt{declarative_part} has an implicit empty @nt{declarative_part}. @begin{Ramification} Thus, other rules can always refer to the @nt{declarative_part} of a @nt<block_statement>. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(block_statement)} The execution of a @nt{block_statement} consists of the elaboration of its @nt{declarative_part} followed by the execution of its @nt{handled_sequence_of_statements}. @end{RunTime} @begin{Examples} @Leading@keepnext@i{Example of a block statement with a local variable:} @begin{Example} Swap: @key[declare] Temp : Integer; @key[begin] Temp := V; V := U; U := Temp; @key[end] Swap; @end{Example} @begin{Ramification} If task objects are declared within a @nt{block_statement} whose execution is completed, the @nt{block_statement} is not left until all its dependent tasks are terminated (see @RefSecNum{User-Defined Assignment and Finalization}). This rule applies to completion caused by a transfer of control. Within a @nt{block_statement}, the block name can be used in expanded names denoting local entities such as Swap.Temp in the above example (see @RefSecNum{Selected Components}). @end{Ramification} @end{Examples} @begin{DiffWord83} The syntax rule for @nt{block_statement} now uses the syntactic category @nt{handled_sequence_of_statements}. @end{DiffWord83} @LabeledClause{Exit Statements} @begin{Intro} @Redundant[An @nt{exit_statement} is used to complete the execution of an enclosing @nt{loop_statement}; the completion is conditional if the @nt{exit_statement} includes a @nt{condition}.] @end{Intro} @begin{Syntax} @Syn{lhs=<exit_statement>,rhs=" @key{exit} [@SynI{loop_}@Syn2{name}] [@key{when} @Syn2{condition}];"} @end{Syntax} @begin{Resolution} The @i(loop_)@nt{name}, if any, in an @nt{exit_statement} shall resolve to denote a @nt{loop_statement}. @end{Resolution} @begin{Legality} @Defn2{Term=[apply], Sec=(to a @nt{loop_statement} by an @nt{exit_statement})} Each @nt{exit_@!statement} @i{applies to} a @nt{loop_@!statement}; this is the @nt{loop_@!statement} being exited. An @nt{exit_@!statement} with a @nt{name} is only allowed within the @nt{loop_@!statement} denoted by the @nt{name}, and applies to that @nt{loop_@!statement}. An @nt{exit_@!statement} without a @nt{name} is only allowed within a @nt{loop_@!statement}, and applies to the innermost enclosing one. An @nt{exit_@!statement} that applies to a given @nt{loop_@!statement} shall not appear within a body or @nt{accept_@!statement}, if this construct is itself enclosed by the given @nt{loop_statement}. @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(exit_statement)} For the execution of an @nt{exit_statement}, the @nt{condition}, if present, is first evaluated. If the value of the @nt{condition} is True, or if there is no @nt{condition}, a transfer of control is done to complete the @nt{loop_@!statement}. If the value of the @nt{condition} is False, no transfer of control takes place. @end{RunTime} @begin{Notes} Several nested loops can be exited by an @nt{exit_statement} that names the outer loop. @end{Notes} @begin{Examples} @i{Examples of loops with exit statements:} @begin{Example} @key[for] N @key[in] 1 .. Max_Num_Items @key[loop] Get_New_Item(New_Item); Merge_Item(New_Item, Storage_File); @key[exit] @key[when] New_Item = Terminal_Item; @key[end] @key[loop]; Main_Cycle: @key[loop] --@RI{ initial statements} @key[exit] Main_Cycle @key[when] Found; --@RI{ final statements} @key[end] @key[loop] Main_Cycle; @end{Example} @end{Examples} @LabeledClause{Goto Statements} @begin{Intro} @Redundant[A @nt{goto_statement} specifies an explicit transfer of control from this @nt{statement} to a target statement with a given label.] @end{Intro} @begin{Syntax} @Syn{lhs=<goto_statement>,rhs="@key{goto} @SynI{label_}@Syn2{name};"} @end{Syntax} @begin{Resolution} @Defn2{Term=[target statement], Sec=(of a @nt{goto_statement})} The @i(label_)@nt{name} shall resolve to denote a @nt<label>; the @nt{statement} with that @nt{label} is the @i(target statement). @end{Resolution} @begin{Legality} The innermost @nt{sequence_of_statements} that encloses the target statement shall also enclose the @nt{goto_statement}. Furthermore, if a @nt{goto_statement} is enclosed by an @nt{accept_statement} or a body, then the target statement shall not be outside this enclosing construct. @begin{Ramification} The @nt{goto_statement} can be a @nt{statement} of an inner @ntf{sequence_}. It follows from the second rule that if the target @nt{statement} is enclosed by such a construct, then the @nt{goto_statement} cannot be outside. @end{Ramification} @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(goto_statement)} The execution of a @nt{goto_statement} transfers control to the target statement, completing the execution of any @nt<compound_statement> that encloses the @nt<goto_statement> but does not enclose the target. @end{RunTime} @begin{Notes} The above rules allow transfer of control to a @nt{statement} of an enclosing @nt{sequence_of_statements} but not the reverse. Similarly, they prohibit transfers of control such as between alternatives of a @nt{case_statement}, @nt{if_statement}, or @nt{select_statement}; between @nt{exception_handler}s; or from an @nt{exception_handler} of a @nt{handled_sequence_of_statements} back to its @nt{sequence_of_statements}. @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of a loop containing a goto statement:} @begin{Example} <<Sort>> @key[for] I @key[in] 1 .. N-1 @key[loop] @key[if] A(I) > A(I+1) @key[then] Exchange(A(I), A(I+1)); @key[goto] Sort; @key[end] @key[if]; @key[end] @key[loop]; @end{Example} @end{Examples}���������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/06.mss���������������������������������������������������������������0000755�0001752�0001001�00000350275�12273462240�016406� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(06, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:24 $} @LabeledSection{Subprograms} @Comment{$Source: e:\\cvsroot/ARM/Source/06.mss,v $} @Comment{$Revision: 1.77 $} @begin{Intro} @Defn{subprogram} @Defn{procedure} @Defn{function} A subprogram is a program unit or intrinsic operation whose execution is invoked by a subprogram call. There are two forms of subprogram: procedures and functions. A procedure call is a @nt{statement}; a function call is an expression and returns a value. The definition of a subprogram can be given in two parts: a subprogram declaration defining its interface, and a @nt{subprogram_body} defining its execution. @Redundant[Operators and enumeration literals are functions.] @begin{Honest} A function call is an expression, but more specifically it is a @nt<name>. @end{Honest} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Subprogram>, Text=<@ChgAdded{Version=[2],Text=[A subprogram is a section of a program that can be executed in various contexts. It is invoked by a subprogram call that may qualify the effect of the subprogram through the passing of parameters. There are two forms of subprograms: functions, which return values, and procedures, which do not.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Function>, Text=<@ChgAdded{Version=[2],Text=[A function is a form of subprogram that returns a result and can be called as part of an expression.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Procedure>, Text=<@ChgAdded{Version=[2],Text=[A procedure is a form of subprogram that does not return a result and can only be called by a @nt{statement}.]}>} @Defn{callable entity} A @i(callable entity) is a subprogram or entry (see Section 9). @Defn{call} A callable entity is invoked by a @i{call}; that is, a subprogram call or entry call. @Defn{callable construct} A @i(callable construct) is a construct that defines the action of a call upon a callable entity: a @nt{subprogram_body}, @nt{entry_body}, or @nt{accept_statement}. @begin{Ramification} Note that @lquotes@;callable entity@rquotes@; includes predefined operators, enumeration literals, and abstract subprograms. @lquotes@;Call@rquotes@; includes calls of these things. They do not have callable constructs, since they don't have completions. @end{Ramification} @end{Intro} @LabeledClause{Subprogram Declarations} @begin{Intro} @Redundant[A @nt{subprogram_declaration} declares a procedure or function.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @Syn{lhs=<subprogram_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=<>}@Syn2{subprogram_specification};"} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00348-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<abstract_subprogram_declaration>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Syn2{subprogram_specification} @key{is} @key{abstract};>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Syn{lhs=<subprogram_specification>,rhs="@Chg{Version=[2],New=[ @Syn2{procedure_specification} | @Syn2{function_specification}],Old=[ @key{procedure} @Syn2{defining_program_unit_name} @Syn2{parameter_profile} | @key{function} @Syn2{defining_designator} @Syn2{parameter_and_result_profile}]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<procedure_specification>,Old=<>}>, rhs="@Chg{Version=[2],New=<@key{procedure} @Syn2{defining_program_unit_name} @Syn2{parameter_profile}>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<function_specification>,Old=<>}>, rhs="@Chg{Version=[2],New=<@key{function} @Syn2{defining_designator} @Syn2{parameter_and_result_profile}>,Old=<>}"} @Syn{lhs=<designator>,rhs="[@Syn2{parent_unit_name} . ]@Syn2{identifier} | @Syn2{operator_symbol}"} @Syn{lhs=<defining_designator>, rhs="@Syn2{defining_program_unit_name} | @Syn2{defining_operator_symbol}"} @Syn{lhs=<defining_program_unit_name>,rhs="[@Syn2{parent_unit_name} . ]@Syn2{defining_identifier}"} @begin{SyntaxText} @Redundant[The optional @nt{parent_unit_name} is only allowed for library units (see @RefSecNum{Compilation Units - Library Units}).] @end{SyntaxText} @Syn{lhs=<operator_symbol>,rhs="@Syn2{string_literal}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00395-01]} The sequence of characters in an @nt{operator_symbol} shall @Chg{Version=[2], New=[form a reserved word, a delimiter, or compound delimiter that corresponds],Old=[correspond]} to an operator belonging to one of the six @Chg{Version=[2],New=[categories], Old=[classes]} of operators defined in clause @RefSecNum{Operators and Expression Evaluation}@Chg{Version=[2], New=[],Old=[(spaces are not allowed and the case of letters is not significant)]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The @lquote@;sequence of characters@rquotes of the string literal of the operator is a technical term (see @RefSecNum{String Literals}), and does not include the surrounding quote characters. As defined in @RefSecNum{Lexical Elements, Separators, and Delimiters}, lexical elements are @lquotes@;formed@rquotes from a sequence of characters. Spaces are not allowed, and upper and lower case is not significant. See @RefSecNum{Lexical Elements, Separators, and Delimiters} and @RefSecNum{Reserved Words} for rules related to the use of @ntf{other_format} characters in delimiters and reserved words.]} @end{Reason} @end{SyntaxText} @Syn{lhs=<defining_operator_symbol>,rhs="@Syn2{operator_symbol}"} @Syn{lhs=<parameter_profile>,rhs="[@Syn2{formal_part}]"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @Syn{lhs=<parameter_and_result_profile>,rhs="@Chg{Version=[2],New=[ ],Old=[]}[@Syn2{formal_part}] @key{return}@Chg{Version=[2],New=< [@Syn2{null_exclusion}]>,Old=<>} @Syn2{subtype_mark}@Chg{Version=[2],New=< | [@Syn2{formal_part}] @key{return} @Syn2{access_definition}>,Old=<>}"} @Syn{lhs=<formal_part>,rhs=" (@Syn2{parameter_specification} {; @Syn2{parameter_specification}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<parameter_specification>,rhs=" @Syn2{defining_identifier_list} : @Syn2{mode} @Chg{Version=[2],New=<[@Syn2{null_exclusion}]>,Old=<>} @Syn2{subtype_mark} [:= @Syn2{default_expression}] | @Syn2{defining_identifier_list} : @Syn2{access_definition} [:= @Syn2{default_expression}]"} @Syn{lhs=<mode>,rhs="[@key{in}] | @key{in} @key{out} | @key{out}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[formal parameter], Sec=(of a subprogram)} A @i(formal parameter) is an object @Redundant[directly visible within a @nt{subprogram_body}] that represents the actual parameter passed to the subprogram in a call; it is declared by a @nt{parameter_specification}. @PDefn2{Term=[expected type], Sec=(parameter @nt{default_expression})} For a formal parameter, the expected type for its @nt<default_expression>, if any, is that of the formal parameter. @IndexSee{Term=[parameter],See=[formal parameter]} @end{Resolution} @begin{Legality} @Defn{parameter mode} The @i(parameter mode) of a formal parameter conveys the direction of information transfer with the actual parameter: @key(in), @key(in out), or @key(out). Mode @key(in) is the default, and is the mode of a parameter defined by an @nt{access_definition}. The formal parameters of a function, if any, shall have the mode @key(in). @begin{Ramification} Access parameters are permitted. This restriction to @b(in) parameters is primarily a methodological restriction, though it also simplifies implementation for some compiler technologies. @end{Ramification} A @nt{default_expression} is only allowed in a @nt{parameter_specification} for a formal parameter of mode @key(in). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @PDefn2{Term=[requires a completion], Sec=(@nt{subprogram_declaration})} @PDefn2{Term=[requires a completion], Sec=(@nt{generic_subprogram_declaration})} A @nt{subprogram_declaration} or a @nt{generic_subprogram_declaration} requires a completion: @Redundant[a body, a @nt<renaming_declaration> (see @RefSecNum(Renaming Declarations)), or a @Chg{Version=[2],New=[@nt{pragma}], Old=[@key(pragma)]} Import (see @RefSecNum{Interfacing Pragmas})]. @Redundant[A completion is not allowed for an @nt<abstract_subprogram_declaration>@Chg{Version=[2],New=[ (see @RefSecNum{Abstract Types and Subprograms}) or a @nt{null_procedure_declaration} (see @RefSecNum{Null Procedures})],Old=[]}.] @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} Abstract subprograms @Chg{Version=[2],New=[and null procedures ],Old=[]}are not declared by @nt{subprogram_declaration}s, and so do not require completion. Protected subprograms are declared by @nt{subprogram_declaration}s, and so require completion. Note that an abstract subprogram is a subprogram, and a protected subprogram is a subprogram, but a generic subprogram is not a subprogram. @end(Ramification) A @nt{name} that denotes a formal parameter is not allowed within the @nt{formal_part} in which it is declared, nor within the @nt{formal_part} of a corresponding body or @nt{accept_statement}. @begin{Ramification} By contrast, @nt<generic_formal_parameter_declaration>s are visible to subsequent declarations in the same @nt<generic_formal_part>. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{profile} The @i(profile) of (a view of) a callable entity is either a @nt{parameter_profile} or @nt{parameter_and_result_profile}@Redundant[; it embodies information about the interface to that entity @em for example, the profile includes information about parameters passed to the callable entity. All callable entities have a profile @em enumeration literals, other subprograms, and entries. An access-to-subprogram type has a designated profile.] Associated with a profile is a calling convention. A @nt<subprogram_declaration> declares a procedure or a function, as indicated by the initial reserved word, with name and profile as given by its specification. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @PDefn2{Term=[nominal subtype], Sec=(of a formal parameter)} The nominal subtype of a formal parameter is the subtype @Chg{Version=[2],New=[determined],Old=[denoted]} by @Chg{Version=[2],New=[the optional @nt{null_exclusion} and ], Old=[]}the @nt{subtype_mark}, or defined by the @nt{access_definition}, in the @nt{parameter_specification}.@Chg{Version=[2],New=[ The nominal subtype of a function result is the subtype determined by the optional @nt{null_exclusion} and the @nt{subtype_mark}, or defined by the @nt{access_definition}, in the @nt{parameter_and_result_profile}. @PDefn2{Term=[nominal subtype], Sec=(of a function result)}], Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00318-02]} @Defn{access parameter} An @i(access parameter) is a formal @key[in] parameter specified by an @nt{access_definition}. @Defn{access result type} @Chg{Version=[2],New=[An @i(access result type) is a function result type specified by an @nt{access_definition}.],Old=[]} An access parameter @Chg{Version=[2],New=[or result type ],Old=[]}is of an anonymous @Chg{Version=[2],New=[access],Old=[general access-to-variable]} type (see @RefSecNum{Access Types}). @Redundant[Access parameters @Chg{Version=[2],New=[of an access-to-object type],Old=[]} allow dispatching calls to be controlled by access values.@Chg{Version=[2],New=[ Access parameters of an access-to-subprogram type permit calls to subprograms passed as parameters irrespective of their accessibility level.],Old=[]}] @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Access result types have normal accessibility and thus don't have any special properties worth noting here.]} @end{Discussion} @leading@keepnext@Defn2{Term=[subtypes], Sec=(of a profile)} The @i(subtypes of a profile) are: @begin{Itemize} For any non-access parameters, the nominal subtype of the parameter. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} For any access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, the designated subtype of the parameter type. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[For any access parameters of an access-to-subprogram type, the subtypes of the profile of the parameter type.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For any non-access result, the nominal subtype of the function result.],Old=[For any result, the result subtype.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For any access result type of an access-to-object type, the designated subtype of the result type.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For any access result type of an access-to-subprogram type, the subtypes of the profile of the result type.],Old=[]} @end{Itemize} @Redundant[@Defn2{Term=[types], Sec=(of a profile)} The @i{types of a profile} are the types of those subtypes.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Redundant[A subprogram declared by an @nt<abstract_subprogram_declaration> is abstract; a subprogram declared by a @nt<subprogram_declaration> is not. See @RefSec{Abstract Types and Subprograms}.@Chg{Version=[2],New=[ Similarly, a procedure defined by a @nt{null_procedure_declaration} is a null procedure; a procedure declared by a @nt{subprogram_declaration} is not. See @RefSec{Null Procedures}.],Old=[]}] @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Redundant[An @nt{overriding_indicator} is used to indicate whether overriding is intended. See @RefSec{Overriding Indicators}.]]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @PDefn2{Term=[elaboration], Sec=(subprogram_declaration)}@Chg{Version=[2],New=[],Old=[ @PDefn2{Term=[elaboration], Sec=(abstract_subprogram_declaration)}]} The elaboration of a @nt{subprogram_declaration}@Chg{Version=[2],New=[],Old=[ or an @nt{abstract_subprogram_declaration}]} has no effect. @end{RunTime} @begin{Notes} A @nt{parameter_specification} with several identifiers is equivalent to a sequence of single @nt{parameter_specification}s, as explained in @RefSecNum{Objects and Named Numbers}. Abstract subprograms do not have bodies, and cannot be used in a nondispatching call (see @RefSec{Abstract Types and Subprograms}). The evaluation of @nt<default_expression>s is caused by certain calls, as described in @RefSecNum{Parameter Associations}. They are not evaluated during the elaboration of the subprogram declaration. Subprograms can be called recursively and can be called concurrently from multiple tasks. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of subprogram declarations:} @begin{Example} @key[procedure] Traverse_Tree; @key[procedure] Increment(X : @key[in] @key[out] Integer); @key[procedure] Right_Indent(Margin : @key[out] Line_Size); --@RI{ see @RefSecNum{Integer Types}} @key[procedure] Switch(From, To : @key[in] @key[out] Link); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[function] Random @key[return] Probability; --@RI{ see @RefSecNum{Floating Point Types}} @key[function] Min_Cell(X : Link) @key[return] Cell; --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[function] Next_Frame(K : Positive) @key[return] Frame; --@RI{ see @RefSecNum{Access Types}} @key[function] Dot_Product(Left, Right : Vector) @key[return] Real; --@RI{ see @RefSecNum{Array Types}} @key[function] "*"(Left, Right : Matrix) @key[return] Matrix; --@RI{ see @RefSecNum{Array Types}} @end{Example} @begin{wide} @leading@keepnext@i{Examples of @key[in] parameters with default expressions:} @end{wide} @begin{Example} @key[procedure] Print_Header(Pages : @key[in] Natural; Header : @key[in] Line := (1 .. Line'Last => ' '); --@RI{ see @RefSecNum{Array Types}} Center : @key[in] Boolean := True); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for @nt{abstract_subprogram_declaration} is added. The syntax for @nt{parameter_specification} is revised to allow for access parameters (see @RefSecNum{Access Types}) Program units that are library units may have a @nt{parent_unit_name} to indicate the parent of a child (see Section 10). @end{Extend83} @begin{DiffWord83} We have incorporated the rules from RM83-6.5, @lquotes@;Function Subprograms@rquotes@; here and in @RefSec{Subprogram Bodies} We have incorporated the definitions of RM83-6.6, @lquotes@;Parameter and Result Type Profile - Overloading of Subprograms@rquotes@; here. The syntax rule for @nt{defining_operator_symbol} is new. It is used for the defining occurrence of an @nt{operator_symbol}, analogously to @nt{defining_identifier}. Usage occurrences use the @nt{direct_name} or @nt{selector_name} syntactic categories. The syntax rules for @nt{defining_designator} and @nt{defining_program_unit_name} are new. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Subprograms now allow @nt{overriding_indicator}s for better error checking of overriding.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[An optional @nt{null_exclusion} can be used in a formal parameter declaration. Similarly, an optional @nt{null_exclusion} can be used in a function result.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The return type of a function can be an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[A description of the purpose of anonymous access-to-subprogram parameters and the definition of the profile of subprograms containing them was added.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Split the production for @nt{subprogram_specification} in order to make the declaration of null procedures (see @RefSecNum{Null Procedures}) easier.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Moved the @SyntaxTitle and @RuntimeTitle for @nt{abstract_subprogram_declaration} to @RefSecNum{Abstract Types and Subprograms}, so that the syntax and semantics are together. This also keeps abstract and null subprograms similar.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Revised to allow @ntf{other_format} characters in @nt{operator_symbol}s in the same way as the underlying constructs.]} @end{DiffWord95} @LabeledClause{Formal Parameter Modes} @begin{Intro} @Redundant[A @nt{parameter_specification} declares a formal parameter of mode @key[in], @key[in out], or @key[out].] @end{Intro} @begin{StaticSem} @Defn{pass by copy} @Defn{by copy parameter passing} @Defn{copy parameter passing} @Defn{pass by reference} @Defn{by reference parameter passing} @Defn{reference parameter passing} A parameter is passed either @i{by copy} or @i{by reference}. @Redundant[When a parameter is passed by copy, the formal parameter denotes a separate object from the actual parameter, and any information transfer between the two occurs only before and after executing the subprogram. When a parameter is passed by reference, the formal parameter denotes (a view of) the object denoted by the actual parameter; reads and updates of the formal parameter directly reference the actual parameter object.] @Defn{by-copy type} A type is a @i(by-copy type) if it is an elementary type, or if it is a descendant of a private type whose full type is a by-copy type. A parameter of a by-copy type is passed by copy. @leading@keepnext@Defn{by-reference type} A type is a @i(by-reference type) if it is a descendant of one of the following: @begin(itemize) a tagged type; a task or protected type; a nonprivate type with the reserved word @b(limited) in its declaration; @begin{Ramification} A limited private type is by-reference only if it falls under one of the other categories. @end{Ramification} a composite type with a subcomponent of a by-reference type; a private type whose full type is a by-reference type. @end(itemize) A parameter of a by-reference type is passed by reference. @Defn2{Term=[associated object], Sec=(of a value of a by-reference type)} Each value of a by-reference type has an associated object. For a parenthesized expression, @nt{qualified_expression}, or @nt{type_conversion}, this object is the one associated with the operand. @begin{Ramification} By-reference parameter passing makes sense only if there is an object to reference; hence, we define such an object for each case. Since tagged types are by-reference types, this implies that every value of a tagged type has an associated object. This simplifies things, because we can define the tag to be a property of the object, and not of the value of the object, which makes it clearer that object tags never change. We considered simplifying things even more by making every value (and therefore every expression) have an associated object. After all, there is little semantic difference between a constant object and a value. However, this would cause problems for untagged types. In particular, we would have to do a constraint check on every read of a type conversion (or a renaming thereof) in certain cases. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} We do not want this definition to depend on the view of the type; privateness is essentially ignored for this definition. Otherwise, things would be confusing (does the rule apply at the call site, at the site of the declaration of the subprogram, at the site of the @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}?), and requiring different calls to use different mechanisms would be an implementation burden. @RefSec{Shared Variable Control} says that a composite type with an atomic or volatile subcomponent is a by-reference type, among other things. @Defn2{Term=[associated object], Sec=(of a value of a limited type)} Every value of a limited by-reference type is the value of one and only one limited object. The @i{associated object} of a value of a limited by-reference type is the object whose value it represents. @Defn2{Term=[same value], Sec=(for a limited type)} Two values of a limited by-reference type are the @i{same} if and only if they represent the value of the same object. We say @lquotes@;by-reference@rquotes@; above because these statements are not always true for limited private types whose underlying type is nonlimited (unfortunately). @end{Ramification} @PDefn{unspecified} For parameters of other types, it is unspecified whether the parameter is passed by copy or by reference. @begin{Discussion} There is no need to incorporate the discussion of AI83-00178, which requires pass-by-copy for certain kinds of actual parameters, while allowing pass-by-reference for others. This is because we explicitly indicate that a function creates an anonymous constant object for its result, unless the type is a return-by-reference type (see @RefSecNum{Return Statements}). We also provide a special dispensation for instances of Unchecked_Conversion to return by reference, even if the result type is not a return-by-reference type (see @RefSecNum{Unchecked Type Conversions}). @end{Discussion} @end{StaticSem} @begin{Bounded} @Defn{distinct access paths} @Defn2{Term=[access paths],Sec=(distinct)} @IndexSee{Term=[aliasing],See=(distinct access paths)} @PDefn2{Term=(bounded error),Sec=(cause)} If one @nt<name> denotes a part of a formal parameter, and a second @nt<name> denotes a part of a distinct formal parameter or an object that is not part of a formal parameter, then the two @nt<name>s are considered @i(distinct access paths). If an object is of a type for which the parameter passing mechanism is not specified, then it is a bounded error to assign to the object via one access path, and then read the value of the object via a distinct access path, unless the first access path denotes a part of a formal parameter that no longer exists at the point of the second access @Redundant[(due to leaving the corresponding callable construct).] @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible consequences are that Program_Error is raised, or the newly assigned value is read, or some old value of the object is read. @begin{Discussion} For example, if we call @lquotes@;P(X => Global_Variable, Y => Global_Variable)@rquotes@;, then within P, the names @lquotes@;X@rquotes@;, @lquotes@;Y@rquotes@;, and @lquotes@;Global_Variable@rquotes@; are all distinct access paths. If Global_Variable's type is neither pass-by-copy nor pass-by-reference, then it is a bounded error to assign to Global_Variable and then read X or Y, since the language does not specify whether the old or the new value would be read. On the other hand, if Global_Variable's type is pass-by-copy, then the old value would always be read, and there is no error. Similarly, if Global_Variable's type is defined by the language to be pass-by-reference, then the new value would always be read, and again there is no error. @end{Discussion} @begin{Reason} We are saying @i(assign) here, not @i(update), because updating any subcomponent is considered to update the enclosing object. The @lquotes@;still exists@rquotes@; part is so that a read after the subprogram returns is OK. If the parameter is of a by-copy type, then there is no issue here @em the formal is not a view of the actual. If the parameter is of a by-reference type, then the programmer may depend on updates through one access path being visible through some other access path, just as if the parameter were of an access type. @end{Reason} @begin{ImplNote} The implementation can keep a copy in a register of a parameter whose parameter-passing mechanism is not specified. If a different access path is used to update the object (creating a bounded error situation), then the implementation can still use the value of the register, even though the in-memory version of the object has been changed. However, to keep the error properly bounded, if the implementation chooses to read the in-memory version, it has to be consistent -- it cannot then assume that something it has proven about the register is true of the memory location. For example, suppose the formal parameter is L, the value of L(6) is now in a register, and L(6) is used in an @nt{indexed_component} as in @lquotes@;A(L(6)) := 99;@rquotes@;, where A has bounds 1..3. If the implementation can prove that the value for L(6) in the register is in the range 1..3, then it need not perform the constraint check if it uses the register value. However, if the memory value of L(6) has been changed to 4, and the implementation uses that memory value, then it had better not alter memory outside of A. Note that the rule allows the implementation to pass a parameter by reference and then keep just part of it in a register, or, equivalently, to pass part of the parameter by reference and another part by copy. @end{ImplNote} @begin{Reason} @leading@;We do not want to go so far as to say that the mere presence of aliasing is wrong. We wish to be able to write the following sorts of things in standard Ada: @begin{Example} @key[procedure] Move ( Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@RI{ Copies elements from Source to Target (safely if they overlap)} @end{Example} This is from the standard string handling package. It would be embarrassing if this couldn't be written in Ada! The @lquotes@;then@rquotes@; before @lquotes@;read@rquotes@; in the rule implies that the implementation can move a read to an earlier place in the code, but not to a later place after a potentially aliased assignment. Thus, if the subprogram reads one of its parameters into a local variable, and then updates another potentially aliased one, the local copy is safe @em it is known to have the old value. For example, the above-mentioned Move subprogram can be implemented by copying Source into a local variable before assigning into Target. @leading@;For an @nt{assignment_statement} assigning one array parameter to another, the implementation has to check which direction to copy at run time, in general, in case the actual parameters are overlapping slices. For example: @begin{Example} @key[procedure] Copy(X : @key[in out] String; Y: String) @key[is] @key[begin] X := Y; @key[end] Copy; @end{Example} It would be wrong for the compiler to assume that X and Y do not overlap (unless, of course, it can prove otherwise). @end{Reason} @end{Bounded} @begin{Notes} A formal parameter of mode @key(in) is a constant view (see @RefSecNum{Objects and Named Numbers}); it cannot be updated within the @nt{subprogram_body}. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The value of an @key(out) parameter may be read. An @key(out) parameter is treated like a declared variable without an explicit initial expression. @end{Extend83} @begin{DiffWord83} Discussion of copy-in for parts of out parameters is now covered in @RefSec{Parameter Associations}. The concept of a by-reference type is new to Ada 95. We now cover in a general way in @RefSecNum{Operations of Discriminated Types} the rule regarding erroneous execution when a discriminant is changed and one of the parameters depends on the discriminant. @end{DiffWord83} @LabeledClause{Subprogram Bodies} @begin{Intro} @Redundant[A @nt{subprogram_body} specifies the execution of a subprogram.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @Syn{lhs=<subprogram_body>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}]>,Old=<>} @Syn2{subprogram_specification} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@Syn2{designator}];"} @begin{SyntaxText} If a @nt{designator} appears at the end of a @nt{subprogram_body}, it shall repeat the @nt{defining_designator} of the @nt{subprogram_specification}. @end{SyntaxText} @end{Syntax} @begin{Legality} @Redundant[In contrast to other bodies,] a @nt{subprogram_body} need not be the completion of a previous declaration@Redundant[, in which case the body declares the subprogram]. If the body is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of a @nt{subprogram_body} that completes a declaration shall conform fully to that of the declaration. @Defn2{Term=[full conformance],Sec=(required)} @end{Legality} @begin{StaticSem} A @nt{subprogram_body} is considered a declaration. It can either complete a previous declaration, or itself be the initial declaration of the subprogram. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(non-generic subprogram_body)} The elaboration of a non-generic @nt{subprogram_body} has no other effect than to establish that the subprogram can from then on be called without failing the Elaboration_Check. @begin{Ramification} See @RefSecNum{Generic Bodies} for elaboration of a generic body. Note that protected @ntf{subprogram_bodies} never get elaborated; the elaboration of the containing @nt{protected_body} allows them to be called without failing the Elaboration_Check. @end{Ramification} @PDefn2{Term=[execution], Sec=(subprogram_body)} @Redundant[The execution of a @nt{subprogram_body} is invoked by a subprogram call.] For this execution the @nt{declarative_part} is elaborated, and the @nt{handled_sequence_of_statements} is then executed. @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of procedure body:} @begin{Example} @key[procedure] Push(E : @key[in] Element_Type; S : @key[in] @key[out] Stack) @key[is] @key[begin] @key[if] S.Index = S.Size @key[then] @key[raise] Stack_Overflow; @key[else] S.Index := S.Index + 1; S.Space(S.Index) := E; @key[end] @key[if]; @key[end] Push; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a function body:} @end{Wide} @begin{Example} @key[function] Dot_Product(Left, Right : Vector) @key[return] Real @key[is] Sum : Real := 0.0; @key[begin] Check(Left'First = Right'First @key[and] Left'Last = Right'Last); @key[for] J @key[in] Left'Range @key[loop] Sum := Sum + Left(J)*Right(J); @key[end] @key[loop]; @key[return] Sum; @key[end] Dot_Product; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} A @nt{renaming_declaration} may be used instead of a @nt{subprogram_body}. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{subprogram_body} now uses the syntactic category @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{subprogram_body} is now required; that doesn't make any real difference, because a @nt{declarative_part} can be empty. We have incorporated some rules from RM83-6.5 here. RM83 forgot to restrict the definition of elaboration of a @nt{subprogram_body} to non-generics. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @Chg{Version=[2],New=[@nt{Overriding_indicator} is added to @nt{subprogram_body}.],Old=[]} @end{DiffWord95} @LabeledSubClause{Conformance Rules} @begin{Intro} @Defn{conformance} @SeeAlso{Primary=[conformance],Other=(type conformance)} @SeeAlso{Primary=[conformance],Other=(mode conformance)} @SeeAlso{Primary=[conformance],Other=(subtype conformance)} @SeeAlso{Primary=[conformance],Other=(full conformance)} @Redundant[When subprogram profiles are given in more than one place, they are required to conform in one of four ways: type conformance, mode conformance, subtype conformance, or full conformance.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0011],ARef=[AI95-00117-01]} @leading@Defn{convention} @Defn{calling convention} @Redundant[As explained in @RefSec{Interfacing Pragmas}, a @i{convention} can be specified for an entity.] @Chg{New=[Unless this International Standard states otherwise, the default convention of an entity is Ada.],Old=[]} @Redundant[For a callable entity or access-to-subprogram type, the convention is called the @i{calling convention}.] The following conventions are defined by the language: @begin{Itemize} @Defn{Ada calling convention} @Defn2{Term=[calling convention], Sec=(Ada)} The default calling convention for any subprogram not listed below is @i{Ada}. @Redundant[A @nt{pragma} Convention, Import, or Export may be used to override the default calling convention (see @RefSecNum{Interfacing Pragmas})]. @begin{Ramification} See also the rule about renamings-as-body in @RefSecNum{Subprogram Renaming Declarations}. @end{Ramification} @leading@Defn{Intrinsic calling convention} @Defn2{Term=[calling convention], Sec=(Intrinsic)} The @i{Intrinsic} calling convention represents subprograms that are @lquotes@;built in@rquotes@; to the compiler. The default calling convention is Intrinsic for the following: @begin{InnerItemize} an enumeration literal; a "/=" operator declared implicitly due to the declaration of "=" (see @RefSecNum{Overloading of Operators}); any other implicitly declared subprogram unless it is a dispatching operation of a tagged type; an inherited subprogram of a generic formal tagged type with unknown discriminants; @begin{Reason} @Comment{8652/0011 suggests that the reason for this rule be documented in the AARM.} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Consider:],Old=[]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] P @key[is] @key[type] Root @key[is tagged null record]; @key[procedure] Proc(X: Root); @key[end] P;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[generic] @key[type] Formal(<>) @key[is new] Root @key[with private]; @key[package] G @key[is] ... @key[end] G;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@key[package body] G @key[is] ... X: Formal := ...; ... Proc(X); -- @RI[This is a dispatching call in Instance, because] -- @RI[the actual type for Formal is class-wide.] ... -- @RI[Proc'Access would be illegal here, because it is of] -- @RI[convention Intrinsic, by the above rule.] @key[end] G;]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@key[type] Actual @key[is new] Root @key[with] ...; @key[procedure] Proc(X: Actual); @key[package] Instance @key[is new] G(Formal => Actual'Class); -- @RI[It is legal to pass in a class-wide actual, because Formal] -- @RI[has unknown discriminants.]]} @end{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Within Instance, all calls to Proc will be dispatching calls, so Proc doesn't really exist in machine code, so we wish to avoid taking 'Access of it. This rule applies to those cases where the actual type might be class-wide, and makes these Intrinsic, thus forbidding 'Access.],Old=[]} @end{Reason} an attribute that is a subprogram; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01]} a subprogram declared immediately within a @nt{protected_body}@Chg{Version=[2],New=[;],Old=[.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[any prefixed view of a subprogram (see @RefSecNum{Selected Components}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The profile of a prefixed view is different than the @lquotes@;real@rquotes profile of the subprogram (it doesn't have the first parameter), so we don't want to be able to take 'Access of it, as that would require generating a wrapper of some sort.]} @end{Reason} @end{InnerItemize} @NoPrefix@Redundant[The Access attribute is not allowed for Intrinsic subprograms.] @begin{Ramification} The Intrinsic calling convention really represents any number of calling conventions at the machine code level; the compiler might have a different instruction sequence for each intrinsic. That's why the Access attribute is disallowed. We do not wish to require the implementation to generate an out of line body for an intrinsic. Whenever we wish to disallow the Access attribute in order to ease implementation, we make the subprogram Intrinsic. Several language-defined subprograms have @lquotes@;@key[pragma] Convention(Intrinsic, ...);@rquotes@;. An implementation might actually implement this as @lquotes@;@key[pragma] Import(Intrinsic, ...);@rquotes@;, if there is really no body, and the implementation of the subprogram is built into the code generator. Subprograms declared in @ntf{protected_bodies} will generally have a special calling convention so as to pass along the identification of the current instance of the protected type. The convention is not @i(protected) since such local subprograms need not contain any @lquotes@;locking@rquotes@; logic since they are not callable via @lquotes@;external@rquotes@; calls; this rule prevents an access value designating such a subprogram from being passed outside the protected unit. The @lquotes@;implicitly declared subprogram@rquotes@; above refers to predefined operators (other than the "=" of a tagged type) and the inherited subprograms of untagged types. @end{Ramification} @Defn{protected calling convention} @Defn2{Term=[calling convention], Sec=(protected)} The default calling convention is @i{protected} for a protected subprogram, and for an access-to-subprogram type with the reserved word @key(protected) in its definition. @Defn{entry calling convention} @Defn2{Term=[calling convention], Sec=(entry)} The default calling convention is @i{entry} for an entry. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[The calling convention for an anonymous access-to-subprogram parameter or anonymous access-to-subprogram result is @i<protected> if the reserved word @key{protected} appears in its definition and otherwise is the convention of the subprogram that contains the parameter.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The calling convention for other anonymous access-to-subprogram types is Ada.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0011],ARef=[AI95-00117-01]} @Chg{Version=[1],New=[@Redundant[If not specified above as Intrinsic, the calling convention for any inherited or overriding dispatching operation of a tagged type is that of the corresponding subprogram of the parent type.] The default calling convention for a new dispatching operation of a tagged type is the convention of the type.], Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The first rule is officially stated in @RefSecNum(Dispatching Operations of Tagged Types). The second is intended to make interfacing to foreign OOP languages easier, by making the default be that the type and operations all have the same convention.]} @end{Reason} @end{Itemize} Of these four conventions, only Ada and Intrinsic are allowed as a @SynI{convention_}@nt{identifier} in a @nt{pragma} Convention, Import, or Export. @begin{Discussion} The names of the @i{protected} and @i{entry} calling conventions cannot be used in the interfacing pragmas. Note that @key[protected] and @key[entry] are reserved words. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00409-01]} @Defn{type conformance} @Defn2{Term=[profile],Sec=(type conformant)} Two profiles are @i{type conformant} if they have the same number of parameters, and both have a result if either does, and corresponding parameter and result types are the same, or, for access parameters@Chg{Version=[2],New=[ or access results],Old=[]}, corresponding designated types are the same@Chg{Version=[2],New=[, or corresponding designated profiles are type conformant],Old=[]}. @IndexSee{Term=[type profile],See=(profile, type conformant)} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00409-01]} For @Chg{Version=[2],New=[anonymous access-to-object],Old=[access]} parameters, the designated types have to be the same for type conformance, not the access types, since in general each access parameter has its own anonymous access type, created when the subprogram is called. Of course, corresponding parameters have to be either both access parameters or both not access parameters. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[Similarly, for anonymous access-to-subprogram parameters, the designated profiles of the types, not the types themselves, have to be conformant.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00409-01]} @Defn{mode conformance} @Defn2{Term=[profile],Sec=(mode conformant)} Two profiles are @i{mode conformant} if they are type-conformant, and corresponding parameters have identical modes, and, for access parameters@Chg{Version=[2],New=[ or access result types],Old=[]}, the designated subtypes statically match@Chg{Version=[2],New=[, or the designated profiles are subtype conformant.],Old=[]} @PDefn2{Term=[statically matching],Sec=(required)} @Defn{subtype conformance} @Defn2{Term=[profile],Sec=(subtype conformant)} Two profiles are @i{subtype conformant} if they are mode-conformant, corresponding subtypes of the profile statically match, and the associated calling conventions are the same. The profile of a generic formal subprogram is not subtype-conformant with any other profile. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Ramification} @PDefn{generic contract issue} @end{Ramification} @Defn2{Term=[full conformance], Sec=(for profiles)} @Defn2{Term=[profile],Sec=(fully conformant)} Two profiles are @i{fully conformant} if they are subtype-conformant, and corresponding parameters have the same names and have @nt<default_expression>s that are fully conformant with one another. @begin{Ramification} Full conformance requires subtype conformance, which requires the same calling conventions. However, the calling convention of the declaration and body of a subprogram or entry are always the same by definition. @end{Ramification} @leading@Defn2{Term=[full conformance], Sec=(for expressions)} Two expressions are @i(fully conformant) if, @Redundant[after replacing each use of an operator with the equivalent @nt{function_call}:] @begin{Itemize} each constituent construct of one corresponds to an instance of the same syntactic category in the other, except that an expanded name may correspond to a @nt{direct_name} (or @nt{character_literal}) or to a different expanded name in the other; and each @nt{direct_name}, @nt{character_literal}, and @nt{selector_name} that is not part of the @nt{prefix} of an expanded name in one denotes the same declaration as the corresponding @nt{direct_name}, @nt{character_literal}, or @nt{selector_name} in the other; and @begin{Ramification} Note that it doesn't say @lquotes@;respectively@rquotes@; because a @nt{direct_name} can correspond to a @nt{selector_name}, and vice-versa, by the previous bullet. This rule allows the @nt{prefix} of an expanded name to be removed, or replaced with a different @nt{prefix} that denotes a renaming of the same entity. However, it does not allow a @nt{direct_name} or @nt{selector_name} to be replaced with one denoting a distinct renaming (except for @nt{direct_name}s and @nt{selector_name}s in @nt{prefix}es of expanded names). Note that calls using operator notation are equivalent to calls using prefix notation. @leading@keepnext@;Given the following declarations: @begin{Example} @key[package] A @key[is] @key[function] F(X : Integer := 1) @key[return] Boolean; @key[end] A; @key[with] A; @key[package] B @key[is] @key[package] A_View @key[renames] A; @key[function] F_View(X : Integer := 9999) @key[return] Boolean @key[renames] F; @key[end] B; @key[with] A, B; @key[use] A, B; @key[procedure] Main @key[is] ... @end{Example} Within Main, the expressions @lquotes@;F@rquotes@;, @lquotes@;A.F@rquotes@;, @lquotes@;B.A_View.F@rquotes@;, and @lquotes@;A_View.F@rquotes@; are all fully conformant with one another. However, @lquotes@;F@rquotes@; and @lquotes@;F_View@rquotes@; are not fully conformant. If they were, it would be bad news, since the two denoted views have different @nt{default_expression}s. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0018],ARef=[AI95-00175-01]} @Chg{New=[each @nt{attribute_designator} in one must be the same as the corresponding @nt{attribute_designator} in the other; and],Old=[]} each @nt{primary} that is a literal in one has the same value as the corresponding literal in the other. @begin{Ramification} The literals may be written differently. @end{Ramification} @end{Itemize} @begin{Ramification} Note that the above definition makes full conformance a transitive relation. @end{Ramification} @Defn2{Term=[full conformance], Sec=(for @nt{known_discriminant_part}s)} Two @nt{known_discriminant_part}s are @i(fully conformant) if they have the same number of discriminants, and discriminants in the same positions have the same names, statically matching subtypes, and @nt{default_expression}s that are fully conformant with one another. @PDefn2{Term=[statically matching],Sec=(required)} @Defn2{Term=[full conformance], Sec=(for @nt{discrete_subtype_definition}s)} Two @nt<discrete_subtype_definition>s are @i(fully conformant) if they are both @nt<subtype_indication>s or are both @nt<range>s, the @nt<subtype_mark>s (if any) denote the same subtype, and the corresponding @nt<simple_expression>s of the @nt<range>s (if any) fully conform. @begin{Ramification} In the @nt{subtype_indication} case, any ranges have to @i{be} corresponding; that is, two @nt{subtype_indication}s cannot conform unless both or neither has a @nt{range}. @end{Ramification} @begin{Discussion} This definition is used in @RefSec(Entries and Accept Statements) for the conformance required between the @nt<discrete_subtype_definition>s of an @nt<entry_declaration> for a family of entries and the corresponding @nt<entry_index_specification> of the @nt<entry_body>. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[@Defn{prefixed view profile} The @i<prefixed view profile> of a subprogram is the profile obtained by omitting the first parameter of that subprogram. There is no prefixed view profile for a parameterless subprogram. For the purposes of defining subtype and mode conformance, the convention of a prefixed view profile is considered to match that of either an entry or a protected operation.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This definition is used to define how primitive subprograms of interfaces match operations in task and protected type definitions (see @RefSecNum{Task Units and Task Objects} and @RefSecNum{Protected Units and Protected Objects}).]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The weird rule about conventions is pretty much required for synchronized interfaces to make any sense. There will be wrappers all over the place for interfaces anyway. Of course, this doesn't imply that entries have the same convention as protected operations.]} @end{Reason} @end{StaticSem} @begin{ImplPerm} An implementation may declare an operator declared in a language-defined library unit to be intrinsic. @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} The rules for full conformance are relaxed @em they are now based on the structure of constructs, rather than the sequence of lexical elements. This implies, for example, that "(X, Y: T)" conforms fully with "(X: T; Y: T)", and "(X: T)" conforms fully with "(X: @key[in] T)". @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the default convention is Ada. Also clarified that the convention of a primitive operation of a tagged type is the same as that of the type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0018],ARef=[AI95-00175-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to ensure that two attributes conform only if they have the same @nt{attribute_designator}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00252-01],ARef=[AI95-00254-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[Defined the calling convention for anonymous access-to-subprogram types and for prefixed views of subprograms (see @RefSecNum{Selected Components}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Defined the conformance of access result types (see @RefSecNum{Subprogram Declarations}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[Defined the prefixed view profile of subprograms for later use.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[Defined the conformance of anonymous access-to-subprogram parameters.]} @end{DiffWord95} @LabeledSubClause{Inline Expansion of Subprograms} @begin{Intro} @Redundant[Subprograms may be expanded in line at the call site.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @leading@keepnext@PDefn2{Term=[program unit pragma], Sec=(Inline)} @PDefn2{Term=[pragma, program unit], Sec=(Inline)} The form of a @nt{pragma} Inline, which is a program unit pragma (see @RefSecNum{Pragmas and Program Units}), is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Inline)(@Syn2{name} {, @Syn2{name}});' @end{Syntax} @begin{Legality} The @nt{pragma} shall apply to one or more callable entities or generic subprograms. @end{Legality} @begin{StaticSem} If a @nt{pragma} Inline applies to a callable entity, this indicates that inline expansion is desired for all calls to that entity. If a @nt{pragma} Inline applies to a generic subprogram, this indicates that inline expansion is desired for all calls to all instances of that generic subprogram. @begin{Ramification} @leading@;Note that inline expansion is desired no matter what name is used in the call. This allows one to request inlining for only one of several overloaded subprograms as follows: @begin{Example} @key[package] IO @key[is] @key[procedure] Put(X : @key[in] Integer); @key[procedure] Put(X : @key[in] String); @key[procedure] Put(X : @key[in] Character); @key[private] @key[procedure] Character_Put(X : @key[in] Character) @key[renames] Put; @key[pragma] Inline(Character_Put); @key[end] IO; @key[with] IO; @key[use] IO; @key[procedure] Main @key[is] I : Integer; C : Character; @key[begin] ... Put(C); --@RI{ Inline expansion is desired.} Put(I); --@RI{ Inline expansion is NOT desired.} @key[end] Main; @end{Example} @end{Ramification} @begin{Ramification} The meaning of a subprogram can be changed by a @nt{pragma} Inline only in the presence of failing checks (see @RefSecNum{Exceptions and Optimization}). @end{Ramification} @end{StaticSem} @begin{ImplPerm} For each call, an implementation is free to follow or to ignore the recommendation expressed by the @nt{pragma}. @begin{Ramification} Note, in particular, that the recommendation cannot always be followed for a recursive call, and is often infeasible for entries. Note also that the implementation can inline calls even when no such desire was expressed by a pragma, so long as the semantics of the program remains unchanged. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00309-01]} @Chg{Version=[2],New=[An implementation may allow a @nt{pragma} Inline that has an argument which is a @nt{direct_name} denoting a @nt{subprogram_body} of the same @nt{declarative_part}.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is allowed for Ada 83 compatibility. This is only a permission as this usage is considered obsolescent.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We only need to allow this in @nt{declarative_part}s, because a body is only allowed in another body, and these all have @nt{declarative_part}s.]} @end{Discussion} @end{ImplPerm} @begin{Notes} The @nt{name} in a @nt{pragma} Inline can denote more than one entity in the case of overloading. Such a @nt{pragma} applies to all of the denoted entities. @end{Notes} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00309-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 83} A pragma Inline cannot refer to a @nt{subprogram_body} outside of that body. The pragma can be given inside of the subprogram body. Ada 2005 adds an @ImplPermName to allow this usage for compatibility (and Ada 95 implementations also can use this permission), but implementations do not have to allow such @nt{pragma}s.]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} A @nt{pragma} Inline is allowed inside a @nt{subprogram_body} if there is no corresponding @nt{subprogram_declaration}. This is for uniformity with other program unit pragmas. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00309-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Implementations are allowed to let @nt{Pragma} Inline apply to a @nt{subprogram_body}.]} @end{Extend95} @RMNewPage@Comment{For printed RM Ada 2005 only} @LabeledClause{Subprogram Calls} @begin{Intro} @Defn{subprogram call} A @i{subprogram call} is either a @nt{procedure_call_statement} or a @nt{function_call}; @Redundant[it invokes the execution of the @nt{subprogram_body}. The call specifies the association of the actual parameters, if any, with formal parameters of the subprogram.] @end{Intro} @begin{Syntax} @Syn{lhs=<procedure_call_statement>,rhs=" @SynI{procedure_}@Syn2{name}; | @SynI{procedure_}@Syn2{prefix} @Syn2{actual_parameter_part};"} @Syn{lhs=<function_call>,rhs=" @SynI{function_}@Syn2{name} | @SynI{function_}@Syn2{prefix} @Syn2{actual_parameter_part}"} @Syn{lhs=<actual_parameter_part>,rhs=" (@Syn2{parameter_association} {, @Syn2{parameter_association}})"} @Syn{lhs=<parameter_association>,rhs=" [@SynI{formal_parameter_}@Syn2{selector_name} =>] @Syn2{explicit_actual_parameter}"} @Syn{lhs=<explicit_actual_parameter>,rhs="@Syn2{expression} | @SynI{variable_}@Syn2{name}"} @begin{SyntaxText} @Defn{named association} @Defn{positional association} A @nt{parameter_association} is @i{named} or @i{positional} according to whether or not the @SynI{formal_@!parameter_}@!@nt{selector_@!name} is specified. Any positional associations shall precede any named associations. Named associations are not allowed if the @nt{prefix} in a subprogram call is an @nt{attribute_@!reference}. @begin{Ramification} This means that the formal parameter names used in describing predefined attributes are to aid presentation of their semantics, but are not intended for use in actual calls. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} The @nt{name} or @nt{prefix} given in a @nt{procedure_call_statement} shall resolve to denote a callable entity that is a procedure, or an entry renamed as (viewed as) a procedure. The @nt{name} or @nt{prefix} given in a @nt{function_call} shall resolve to denote a callable entity that is a function.@Chg{Version=[2],New=[ The @nt{name} or @nt{prefix} shall not resolve to denote an abstract subprogram unless it is also a dispatching subprogram.],Old=[]} @Redundant[When there is an @nt<actual_@!parameter_@!part>, the @nt<prefix> can be an @nt<implicit_@!dereference> of an access-to-subprogram value.] @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[This rule is talking about dispatching operations (which is a static concept) and not about dispatching calls (which is a dynamic concept).]} @end{Discussion} @begin{Ramification} The function can be an operator, enumeration literal, attribute that is a function, etc. @end{Ramification} A subprogram call shall contain at most one association for each formal parameter. Each formal parameter without an association shall have a @nt{default_expression} (in the profile of the view denoted by the @nt<name> or @nt<prefix>). This rule is an overloading rule (see @RefSecNum{The Context of Overload Resolution}). @end{Resolution} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(subprogram call)} For the execution of a subprogram call, the @nt{name} or @nt{prefix} of the call is evaluated, and each @nt{parameter_@!association} is evaluated (see @RefSecNum{Parameter Associations}). If a @nt{default_@!expression} is used, an implicit @nt{parameter_@!association} is assumed for this rule. These evaluations are done in an arbitrary order. The @nt{subprogram_@!body} is then executed@Chg{Version=[2],New=[, or a call on an entry or protected subprogram is performed (see @RefSecNum{Dispatching Operations of Tagged Types})],Old=[]}. Finally, if the subprogram completes normally, then after it is left, any necessary assigning back of formal to actual parameters occurs (see @RefSecNum{Parameter Associations}). @begin{Discussion} The implicit association for a default is only for this run-time rule. At compile time, the visibility rules are applied to the default at the place where it occurs, not at the place of a call. @end{Discussion} @begin{Honest} If the subprogram is inherited, see @RefSec{Derived Types and Classes}. If the subprogram is protected, see @RefSec{Protected Subprograms and Protected Actions}. If the subprogram is really a renaming of an entry, see @RefSec{Entry Calls}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If the subprogram is implemented by an entry or protected subprogram, it will be treated as a dispatching call to the corresponding entry (see @RefSec{Entry Calls}) or protected subprogram (see @RefSec{Protected Subprograms and Protected Actions}).]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} Normally, the @nt{subprogram_body} that is executed by the above rule is the one for the subprogram being called. For an enumeration literal, implicitly declared (but noninherited) subprogram, @Chg{Version=[2],New=[null procedure, ],Old=[]}or an attribute that is a subprogram, an implicit body is assumed. For a dispatching call, @RefSec{Dispatching Operations of Tagged Types} defines which @nt{subprogram_body} is executed. @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[If the @nt{name} or @nt{prefix} of a subprogram call denotes a prefixed view (see @RefSecNum{Selected Components}), the subprogram call is equivalent to a call on the underlying subprogram, with the first actual parameter being provided by the @nt{prefix} of the prefixed view (or the Access attribute of this @nt{prefix} if the first formal parameter is an access parameter), and the remaining actual parameters given by the @nt{actual_parameter_part}, if any.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised at the point of a @nt{function_call} if the function completes normally without executing a @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]}. @begin{Discussion} We are committing to raising the exception at the point of call, for uniformity @em see AI83-00152. This happens after the function is left, of course. Note that there is no name for suppressing this check, since the check imposes no time overhead and minimal space overhead (since it can usually be statically eliminated as dead code). @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} A @nt{function_call} denotes a constant, as defined in @RefSecNum{Return Statements}; the nominal subtype of the constant is given by the @Chg{Version=[2],New=[nominal],Old=[result]} subtype of the function@Chg{Version=[2],New=[ result],Old=[]}. @PDefn2{Term=[nominal subtype], Sec=(of the result of a @nt<function_call>)} @PDefn2{Term=[constant], Sec=(result of a @nt<function_call>)} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of procedure calls:} @begin{Example} Traverse_Tree; --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(128, Title, True); --@RI{ see @RefSecNum{Subprogram Declarations}} Switch(From => X, To => Next); --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(128, Header => Title, Center => True); --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(Header => Title, Center => True, Pages => 128); --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @begin{Wide} @leading@keepnext@i{Examples of function calls:} @end{Wide} @begin{Example} Dot_Product(U, V) --@RI{ see @RefSecNum{Subprogram Declarations} and @RefSecNum{Subprogram Bodies}} Clock --@RI{ see @RefSecNum{Delay Statements, Duration, and Time}} F.@key[all] --@RI{ presuming F is of an access-to-subprogram type @em see @RefSecNum{Access Types}} @end{Example} @begin{Wide} @leading@keepnext@i{Examples of procedures with default expressions:} @end{Wide} @begin{Example} @key[procedure] Activate(Process : @key[in] Process_Name; After : @key[in] Process_Name := No_Process; Wait : @key[in] Duration := 0.0; Prior : @key[in] Boolean := False); @key[procedure] Pair(Left, Right : @key[in] Person_Name := @key[new] Person); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @end{Example} @begin{Wide} @leading@keepnext@i{Examples of their calls:} @end{Wide} @begin{Example} Activate(X); Activate(X, After => Y); Activate(X, Wait => 60.0, Prior => True); Activate(X, Y, 10.0, False); Pair; Pair(Left => @key[new] Person, Right => @key[new] Person); @end{Example} @end{Examples} @begin{Notes} If a @nt{default_expression} is used for two or more parameters in a multiple @nt{parameter_@!specification}, the @nt{default_@!expression} is evaluated once for each omitted parameter. Hence in the above examples, the two calls of Pair are equivalent. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of overloaded subprograms:} @begin{Example} @key[procedure] Put(X : @key[in] Integer); @key[procedure] Put(X : @key[in] String); @key[procedure] Set(Tint : @key[in] Color); @key[procedure] Set(Signal : @key[in] Light); @end{Example} @begin{Wide} @leading@keepnext@i{Examples of their calls:} @end{Wide} @begin{Example} Put(28); Put("no possible ambiguity here"); Set(Tint => Red); Set(Signal => Red); Set(Color'(Red)); --@RI{ Set(Red) would be ambiguous since Red may} --@RI{ denote a value either of type Color or of type Light} @end{Example} @end{Examples} @begin{DiffWord83} We have gotten rid of parameters @lquotes@;of the form of a type conversion@rquotes@; (see RM83-6.4.1(3)). The new view semantics of @nt{type_conversion}s allows us to use normal @nt{type_conversion}s instead. We have moved wording about run-time semantics of parameter associations to @RefSecNum{Parameter Associations}. We have moved wording about raising Program_Error for a function that falls off the end to here from RM83-6.5. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Nondispatching abstract operations are no longer considered when resolving a subprogram call. That makes it possible to use @key{abstract} to @lquotes@;undefine@rquotes@; a predefined operation for an untagged type. That's especially helpful when defining custom arithmetic packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Changed the definition of the nominal subtype of a @nt{function_call} to use the nominal subtype wording of @RefSecNum{Subprogram Declarations}, to take into account @nt{null_exclusion}s and access result types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that the meaning of a call on a subprogram @lquotes@;implemented by@rquotes an entry or protected operation is defined by @RefSecNum{Dispatching Operations of Tagged Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[Defined the meaning of a call on a prefixed view of a subprogram (see @RefSecNum{Selected Components}).]} @end{DiffWord95} @LabeledSubClause{Parameter Associations} @begin{Intro} @Redundant[@Defn{parameter passing} A parameter association defines the association between an actual parameter and a formal parameter.] @end{Intro} @begin{MetaRules} The parameter passing rules for @b(out) parameters are designed to ensure that the parts of a type that have implicit initial values (see @RefSecNum{Object Declarations}) don't become @lquotes@;de-initialized@rquotes@; by being passed as an @b(out) parameter. @end{MetaRules} @begin{Resolution} The @SynI{formal_parameter_}@nt{selector_name} of a @nt{parameter_@!association} shall resolve to denote a @nt{parameter_@!specification} of the view being called. @Defn2{Term=[actual parameter], Sec=(for a formal parameter)} The @i(actual parameter) is either the @nt<explicit_actual_parameter> given in a @nt<parameter_association> for a given formal parameter, or the corresponding @nt<default_expression> if no @nt<parameter_association> is given for the formal parameter. @Defn2{Term=[expected type], Sec=(actual parameter)} The expected type for an actual parameter is the type of the corresponding formal parameter. @begin{Honest} The corresponding @nt<default_expression> is the one of the corresponding formal parameter in the profile of the view denoted by the @nt<name> or @nt<prefix> of the call. @end{Honest} If the mode is @key(in), the actual is interpreted as an @nt{expression}; otherwise, the actual is interpreted only as a @nt{name}, if possible. @begin{Ramification} This formally resolves the ambiguity present in the syntax rule for @nt<explicit_actual_parameter>. Note that we don't actually require that the actual be a @nt<name> if the mode is not @key(in); we do that below. @end{Ramification} @end{Resolution} @begin{Legality} If the mode is @key(in out) or @key(out), the actual shall be a @nt<name> that denotes a variable. @begin{Discussion} We no longer need @lquotes@;or a @nt{type_conversion} whose argument is the @nt{name} of a variable,@rquotes@; because a @nt{type_conversion} is now a @nt{name}, and a @nt{type_conversion} of a variable is a variable. @end{Discussion} @begin{Reason} @leading@;The requirement that the actual be a (variable) @nt<name> is not an overload resolution rule, since we don't want the difference between @nt<expression> and @nt{name} to be used to resolve overloading. For example: @begin{Example} procedure Print(X : @key[in] Integer; Y : @key[in] Boolean := True); procedure Print(Z : @key[in out] Integer); . . . Print(3); --@RI{ Ambiguous!} @end{Example} The above call to Print is ambiguous even though the call is not compatible with the second Print which requires an actual that is a (variable) @nt<name> (@lquotes@;3@rquotes@; is an @nt<expression>, not a @nt<name>). This requirement is a legality rule, so overload resolution fails before it is considered, meaning that the call is ambiguous. @end{Reason} The type of the actual parameter associated with an access parameter shall be convertible (see @RefSecNum{Type Conversions}) to its anonymous access type. @PDefn2{Term=[convertible],Sec=(required)} @end{Legality} @begin{RunTime} @leading@keepnext@PDefn2{Term=[evaluation], Sec=(parameter_association)} For the evaluation of a @nt{parameter_association}: @begin{Itemize} The actual parameter is first evaluated. For an access parameter, the @nt{access_definition} is elaborated, which creates the anonymous access type. For a parameter @Redundant[(of any mode)] that is passed by reference (see @RefSecNum{Formal Parameter Modes}), a view conversion of the actual parameter to the nominal subtype of the formal parameter is evaluated, and the formal parameter denotes that conversion. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} @begin{Discussion} We are always allowing sliding, even for [@key(in)[ @key(out) by-reference parameters. @end{Discussion} @Defn2{Term=[assignment operation], Sec=(during evaluation of a @nt{parameter_association})} For an @key(in) or @key(in out) parameter that is passed by copy (see @RefSecNum{Formal Parameter Modes}), the formal parameter object is created, and the value of the actual parameter is converted to the nominal subtype of the formal parameter and assigned to the formal. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} @begin{Ramification} The conversion mentioned here is a value conversion. @end{Ramification} @leading@keepnext@;For an @key(out) parameter that is passed by copy, the formal parameter object is created, and: @begin(itemize) For an access type, the formal parameter is initialized from the value of the actual, without a constraint check; @begin{Reason} This preserves the @MetaRulesName that an object of an access type is always initialized with a @lquotes@;reasonable@rquotes@; value. @end{Reason} For a composite type with discriminants or that has implicit initial values for any subcomponents (see @RefSecNum{Object Declarations}), the behavior is as for an @key[in out] parameter passed by copy. @begin{Reason} This ensures that no part of an object of such a type can become @lquotes@;de-initialized@rquotes@; by being part of an @b(out) parameter. @end{Reason} @begin{Ramification} This includes an array type whose component type is an access type, and a record type with a component that has a @nt{default_expression}, among other things. @end{Ramification} For any other type, the formal parameter is uninitialized. If composite, a view conversion of the actual parameter to the nominal subtype of the formal is evaluated @Redundant[(which might raise Constraint_Error)], and the actual subtype of the formal is that of the view conversion. If elementary, the actual subtype of the formal is given by its nominal subtype. @begin{Ramification} This case covers scalar types, and composite types whose subcomponent's subtypes do not have any implicit initial values. The view conversion for composite types ensures that if the lengths don't match between an actual and a formal array parameter, the Constraint_Error is raised before the call, rather than after. @end{Ramification} @end(itemize) @end{Itemize} @PDefn2{Term=[constrained],Sec=(object)} @PDefn2{Term=[unconstrained],Sec=(object)} A formal parameter of mode @key[in out] or @key[out] with discriminants is constrained if either its nominal subtype or the actual parameter is constrained. @Defn{parameter copy back} @Defn{copy back of parameters} @Defn{parameter assigning back} @Defn{assigning back of parameters} @Defn2{Term=[assignment operation], Sec=(during parameter copy back)} After normal completion and leaving of a subprogram, for each @key(in out) or @key(out) parameter that is passed by copy, the value of the formal parameter is converted to the subtype of the variable given as the actual parameter and assigned to it. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} These conversions and assignments occur in an arbitrary order. @begin{Ramification} The conversions mentioned above during parameter passing might raise Constraint_Error @em (see @RefSecNum{Type Conversions}). @end{Ramification} @begin{Ramification} If any conversion or assignment as part of parameter passing propagates an exception, the exception is raised at the place of the subprogram call; that is, it cannot be handled inside the @nt{subprogram_body}. @end{Ramification} @begin{TheProof} Since these checks happen before or after executing the @nt{subprogram_body}, the execution of the @nt{subprogram_body} does not dynamically enclose them, so it can't handle the exceptions. @end{TheProof} @begin{Discussion} The variable we're talking about is the one denoted by the @i{variable_}@nt{name} given as the @nt{explicit_actual_parameter}. If this @i{variable_}@nt{name} is a @nt{type_conversion}, then the rules in @RefSecNum{Type Conversions} for assigning to a view conversion apply. That is, if X is of subtype S1, and the actual is S2(X), the above-mentioned conversion will convert to S2, and the one mentioned in @RefSecNum{Type Conversions} will convert to S1. @end{Discussion} @end{RunTime} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 95, a program can rely on the fact that passing an object as an @key[out] parameter does not @lquotes@;de-initialize@rquotes@; any parts of the object whose subtypes have implicit initial values. (This generalizes the RM83 rule that required copy-in for parts that were discriminants or of an access type.) @end{Extend83} @begin{DiffWord83} We have eliminated the subclause on Default Parameters, as it is subsumed by earlier clauses and subclauses. @end{DiffWord83} @LabeledClause{Return Statements} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} A @Chg{Version=[2],New=[@nt{simple_@!return_@!statement} or @nt{extended_@!return_@!statement} (collectively called a @i<return statement>) @Defn{return statement}],Old=[@nt{return_statement}]} is used to complete the execution of the innermost enclosing @nt{subprogram_@!body}, @nt{entry_@!body}, or @nt{accept_@!statement}. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{lhs=<@Chg{Version=[2],New=[simple_return_statement],Old=[return_statement]}>,rhs="@key{return} [@Syn2{expression}];"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[extended_return_statement],Old=[]}>, rhs="@Chg{Version=[2],New=< @key{return} @Syn2{defining_identifier} : [@Key{aliased}] @Syn2{return_subtype_indication} [:= @Syn2{expression}] [@Key{do} @Syn2{handled_sequence_of_statements} @key{end} @key{return}];>,Old=[]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[return_subtype_indication],Old=[]}>, rhs="@Chg{Version=[2],New=<@Syn2{subtype_indication} | @Syn2{access_definition}>,Old=[]}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@Defn2{Term=[result subtype], Sec=(of a function)} The @i<result subtype> of a function is the subtype denoted by the @nt<subtype_mark>, or defined by the @nt<access_definition>, after the reserved word @key<return> in the profile of the function.@PDefn2{Term=[expected type], Sec=(@nt{expression} of @nt<simple_@!return_@!statement>)}],Old=[@Defn{return expression} The @nt{expression}, if any, of a @nt{return_statement} is called the @i{return expression}. @Defn2{Term=[result subtype], Sec=(of a function)} The @i(result subtype) of a function is the subtype denoted by the @nt{subtype_mark} after the reserved word @key(return) in the profile of the function.@PDefn2{Term=[expected type], Sec=(return expression)}]} The expected type for @Chg{Version=[2],New=[the @nt{expression}, if any, of a @nt{simple_@!return_@!statement}],Old=[a return expression]} is the result type of the corresponding function.@Chg{Version=[2],New=[ @PDefn2{Term=[expected type], Sec=(@nt{expression} of @nt{extended_return_statement})} The expected type for the @nt{expression} of an @nt{extended_return_statement} is that of the @nt{return_@!subtype_@!indication}.],Old=[]} @begin{Honest} The same applies to generic functions. @end{Honest} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@Defn2{Term=[apply], Sec=(to a callable construct by a return statement)}], Old=[@Defn2{Term=[apply], Sec=(to a callable construct by a @nt{return_statement})}]} A @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} shall be within a callable construct, and it @i{applies to} the innermost @Chg{Version=[2],New=[callable construct or @nt{extended_return_statement} that contains it],Old=[one]}. A @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} shall not be within a body that is within the construct to which the @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} applies. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} A function body shall contain at least one @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} that applies to the function body, unless the function contains @nt{code_statement}s. A @Chg{Version=[2],New=[@nt{simple_@!return_@!statement}],Old=[@nt{return_@!statement}]} shall include @Chg{Version=[2],New=[an @nt{expression}],Old=[a return expression]} if and only if it applies to a function body.@Chg{Version=[2],New=[ An @nt<extended_return_statement> shall apply to a function body.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The requirement that a function body has to have at least one @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} is a @lquotes@;helpful@rquotes@; restriction. There @Chg{Version=[2],New=[has],Old=[was]} been some interest in lifting this restriction, or allowing a raise statement to substitute for the @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]}. However, there was enough interest in leaving it as is that we decided not to change it. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[A return statement can apply to an @nt{extended_return_statement}, so a @nt{simple_@!return_@!statement} without an @nt{expression} can be given in one. However, neither @nt{simple_@!return_@!statement} with an @nt{expression} nor an @nt{extended_return_statement} can be given inside an @nt{extended_return_statement}, as they must apply (directly) to a function body.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an @nt{extended_@!return_@!statement} that applies to a function body:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is defined by a @nt{subtype_mark}, the @nt{return_@!subtype_@!indication} shall be a @nt{subtype_indication}. The type of the @nt{subtype_indication} shall be the result type of the function. If the result subtype of the function is constrained, then the subtype defined by the @nt{subtype_indication} shall also be constrained and shall statically match this result subtype. @PDefn2{Term=[statically matching],Sec=(required)} If the result subtype of the function is unconstrained, then the subtype defined by the @nt{subtype_indication} shall be a definite subtype, or there shall be an @nt{expression}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is defined by an @nt{access_definition}, the @nt{return_@!subtype_@!indication} shall be an @nt{access_definition}. The subtype defined by the @nt{access_definition} shall statically match the result subtype of the function. The accessibility level of this anonymous access subtype is that of the result subtype.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[For any return statement that applies to a function body:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is limited, then the @nt{expression} of the return statement (if any) shall be an @nt{aggregate}, a function call (or equivalent use of an operator), or a @nt{qualified_expression} or parenthesized expression whose operand is one of these.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, if limited, the @nt{expression} must produce a @lquotes@;new@rquotes@; object, rather than being the name of a preexisting object (which would imply copying).]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is class-wide, the accessibility level of the type of the @nt{expression} of the return statement shall not be statically deeper than that of the master that elaborated the function body. If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{expression} of the @nt{simple_@!return_@!statement} or the @nt{return_@!subtype_@!indication}, shall not be statically deeper than that of the master that elaborated the function body.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We know that if the result type is class wide, then there must be an @nt{expression} of the return statement. Similarly, if the result subtype is unconstrained, then either the @nt{return_@!subtype_@!indication} (if any) is constrained, or there must be an @nt{expression}.]} @end{Discussion} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[return object], Sec=(extended_return_statement)} Within an @nt{extended_return_statement}, the @i{return object} is declared with the given @nt{defining_identifier}, with the nominal subtype defined by the @nt{return_@!subtype_@!indication}.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[execution], Sec=(extended_return_statement)} For the execution of an @nt{extended_return_statement}, the @nt{subtype_indication} or @nt{access_definition} is elaborated. This creates the nominal subtype of the return object. If there is an @nt{expression}, it is evaluated and converted to the nominal subtype (which might raise Constraint_Error @em see @RefSecNum{Type Conversions}@PDefn2{Term=[implicit subtype conversion],Sec=(function return)}); the return object is created and the converted value is assigned to the return object. Otherwise, the return object is created and initialized by default as for a stand-alone object of its nominal subtype (see @RefSecNum{Object Declarations}). If the nominal subtype is indefinite, the return object is constrained by its initial value.@PDefn2{Term=[creation],Sec=[of a return object]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the result type is controlled or has a controlled part, appropriate calls on Initialize or Adjust are performed prior to executing the @nt{handled_sequence_of_statements}, except when the initial expression is an @nt{aggregate} (which requires build-in-place with no call on Adjust).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the return statement is left without resulting in a return (for example, due to an exception propagated from the @nt{expression} or the @nt{handled_sequence_of_statements}, or a goto out of the @nt{handled_sequence_of_statements}), the return object is finalized prior to leaving the return statement.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@PDefn2{Term=[execution], Sec=(simple_@!return_@!statement)}], Old=[@PDefn2{Term=[execution], Sec=(return_statement)}]} For the execution of a @Chg{Version=[2],New=[@nt{simple_@!return_@!statement}], Old=[@nt{return_statement}]}, the @nt{expression} (if any) is first evaluated@Chg{Version=[2],New=[,],Old=[ and]} converted to the result subtype@Chg{Version=[2], New=[, and then is assigned to the anonymous @i{return object}. @PDefn2{Term=[return object], Sec=(simple_@!return_@!statement)}],Old=[.]} @PDefn2{Term=[implicit subtype conversion],Sec=(function return)} @begin{Ramification} The conversion might raise Constraint_Error @em (see @RefSecNum{Type Conversions}). @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[@Redundant[If the return object has any parts that are tasks, the activation of those tasks does not occur until after the function returns (see @RefSecNum{Task Execution - Task Activation}).]], Old=[If the result type is class-wide, then the tag of the result is the tag of the value of the @nt<expression>.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is specified by the rules in @RefSecNum{Task Execution - Task Activation}.]} @end{TheProof} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Only the caller can know when task activations should take place, as it depends on the context of the call. If the function is being used to initialize the component of some larger object, then that entire object must be initialized before any task activations. Even after the outer object is fully initialized, task activations are still postponed until the @key{begin} at the end of the declarative part if the function is being used to initialize part of a declared object.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Type=[Leading],Keepnext=[T],Text=[]}@ChgNote{A dummy ChgDeleted to get conditional "Leading".}If the result type @Chg{Version=[2],New=[of a function ],Old=[]}is a specific tagged type@Chg{Version=[2],New=[, the tag of the return object is that of the result type. If the result type is class-wide, the tag of the return object is that of the value of the expression. A check is made that the accessibility level of the type identified by the tag of the result is not deeper than that of the master that elaborated the function body. If this check fails, Program_Error is raised.@Defn2{Term=[Program_Error], Sec=(raised by failure of run-time check)} @IndexCheck{Accessibility_Check}],Old=[:]} @begin{Ramification} @ChgNote{Moved from after paragraph 10} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The first sentence is true even if the tag of the @nt{expression} is different, which could happen if the @nt{expression} were a view conversion or a dereference of an access value. Note that for a limited type, because of the restriction to @nt{aggregate}s and function calls (and no conversions), the tag will already match]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The first rule ensures that a function whose result type is a specific tagged type always returns an object whose tag is that of the result type. This is important for dispatching on controlling result, and allows the caller to allocate the appropriate amount of space to hold the value being returned (assuming there are no discriminants).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check prevents the returned object from outliving its type. Note that this check cannot fail for a specific tagged type, as the tag represents the function's type, which necessarily must be declared outside of the function.]} @end{Reason} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 9 through 20 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[@IndexCheck{Tag_Check} If it is limited, then a check is made that the tag of the value of the return expression identifies the result type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[If it is nonlimited, then the tag of the result is that of the result type.]} @begin{Ramification} @ChgNote{These two notes were revised and moved up} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[This is true even if the tag of the return expression is different.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[These rules ensure that a function whose result type is a specific tagged type always returns an object whose tag is that of the result type. This is important for dispatching on controlling result, and, if nonlimited, allows the caller to allocate the appropriate amount of space to hold the value being returned (assuming there are no discriminants).]} @end{Reason} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Type=[Leading],Keepnext=[T], Text=[@Defn{return-by-reference type} A type is a @i(return-by-reference) type if it is a descendant of one of the following:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a tagged limited type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a task or protected type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a nonprivate type with the reserved word @b(limited) in its declaration;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a composite type with a subcomponent of a return-by-reference type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a private type whose full type is a return-by-reference type.]} @end(itemize) @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[ The above rules are such that there are no "Ada 83" types other than those containing tasks that are return-by-reference. This helps to minimize upward incompatibilities relating to return-by-reference.]} @end{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@IndexCheck{Accessibility_Check} If the result type is a return-by-reference type, then a check is made that the return expression is one of the following:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a @nt{name} that denotes an object view whose accessibility level is not deeper than that of the master that elaborated the function body; or]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00316-01]} @ChgNote{This really wasn't in the previous version, but we don't want it in a version without deletions shown...} @ChgDeleted{Version=[2],Text=[This rule was unnecessarily confusing, and the parenthetical remark "(or a value with an associated object, see 6.2)" was added @em and then the entire concept was deleted.]} @end{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a parenthesized expression or @nt{qualified_expression} whose operand is one of these kinds of expressions.]} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if this check fails.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Compare the definition of return-by-reference with that of by-reference.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The return-by-reference types are all limited types except those that are limited only because of a limited private type with a nonlimited untagged full type.]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@PDefn{generic contract issue} This check can often be performed at compile time. It is defined to be a run-time check to avoid generic contract model problems. In a future version of the standard, we anticipate that function return of a local variable will be illegal for all limited types, eliminating the need for the run-time check except for dereferences of an access parameter.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @Chg{Version=[2], New=[If the result subtype of a function has one or more unconstrained access discriminants, a check is made that the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{expression} or the @nt{return_@!subtype_@!indication} of the function, is not deeper than that of the master that elaborated the function body. If this check fails, Program_Error is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @IndexCheck{Accessibility_Check}], Old=[For a function with a return-by-reference result type the result is returned by reference; that is, the function call denotes a constant view of the object associated with the value of the return expression. @Defn2{Term=[assignment operation], Sec=(during execution of a @nt{return_statement})} For any other function, the result is returned by copy; that is, the converted value is assigned into an anonymous constant created at the point of the @nt{return_statement}, and the function call denotes that object.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The assignment operation does the necessary value adjustment, as described in @RefSec{User-Defined Assignment and Finalization}. @RefSecNum{Completion and Finalization} describes when the anonymous constant is finalized.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check prevents the returned object (for a nonlimited type) from outliving the object designated by one of its discriminants. The check is made on the values of the discriminants, which may come from the @nt{return_@!subtype_@!indication} (if constrained), or the @nt{expression}, but it is never necessary to check both.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For the execution of an @nt{extended_@!return_@!statement}, the @nt{handled_@!sequence_@!of_@!statements} is executed. Within this @nt{handled_@!sequence_@!of_@!statements}, the execution of a @nt{simple_@!return_@!statement} that applies to the @nt{extended_@!return_@!statement} causes a transfer of control that completes the @nt{extended_@!return_@!statement}. Upon completion of a return statement that applies to a callable construct],Old=[Finally]}, a transfer of control is performed which completes the execution of the callable construct@Chg{Version=[2],New=[], Old=[ to which the @nt{return_@!statement} applies]}, and returns to the caller. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[In the case of a function, the @nt{function_call} denotes a constant view of the return object.]} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the result subtype of a function is unconstrained, and a call on the function is used to provide the initial value of an object with a constrained nominal subtype, Constraint_Error may be raised at the point of the call (after abandoning the execution of the function body) if, while elaborating the @nt{return_@!subtype_@!indication} or evaluating the @nt{expression} of a return statement that applies to the function body, it is determined that the value of the result will violate the constraint of the subtype of this object.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Without such a permission, it would be very difficult to implement @lquotes@;build-in-place@rquotes semantics. Such an exception is not handleable within the function, because in the return-by-copy case, the constraint check to verify that the result satisfies the constraints of the object being initialized happens after the function returns, and we want the semantics to change as little as possible when switching between return-by-copy and build-in-place. This implies further that upon detecting such a situation, the implementation may need to simulate a goto to a point outside any local exception handlers prior to raising the exception.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This permission is allowed during the evaluation of the @nt{expression} of an @nt{extended_return_statement}, because the @nt{return_@!subtype_@!indication} may be unconstrained and the @nt{expression} then would provide the constraints.]} @end{Ramification} @end{ImplPerm} @begin{Examples} @leading@keepnext@i{Examples of return statements:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @key[return]; --@RI{ in a procedure body, }@nt{entry_body}@RI{,}@Chg{Version=[2],New=[ -- @nt{accept_statement}@RI{, or }@nt{extended_return_statement}],Old=[@RI{ or }@nt{accept_statement}]} @key[return] Key_Value(Last_Index); --@RI{ in a function body} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @Chg{Version=[2],New=<@key[return] Node : Cell @key{do} --@RI{ in a function body, see @RefSecNum{Incomplete Type Declarations} for Cell} Node.Value := Result; Node.Succ := Next_Node; @key{end} @key{return};>,Old=<>} @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{incompatibilities with Ada 83} In Ada 95, if the result type of a function has a part that is a task, then an attempt to return a local variable will raise Program_Error. @Chg{Version=[2],New=[This is illegal in Ada 2005, see below. ], Old=[]}In Ada 83, if a function returns a local variable containing a task, execution is erroneous according to AI83-00867. However, there are other situations where functions that return tasks (or that return a variant record only one of whose variants includes a task) are correct in Ada 83 but will raise Program_Error according to the new rules. The rule change was made because there will be more types (protected types, limited controlled types) in Ada 95 for which it will be meaningless to return a local variable, and making all of these erroneous is unacceptable. The current rule was felt to be the simplest that kept upward incompatibilities to situations involving returning tasks, which are quite rare. @end{Incompatible83} @begin{DiffWord83} This clause has been moved here from chapter 5, since it has mainly to do with subprograms. A function now creates an anonymous object. This is necessary so that controlled types will work. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} We have clarified that a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} applies to a callable construct, not to a callable entity. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} There is no need to mention generics in the rules about where a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} can appear and what it applies to; the phrase @lquotes@;body of a subprogram or generic subprogram@rquotes@; is syntactic, and refers exactly to @lquotes@;@nt{subprogram_body}@rquotes@;. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The entire business about return-by-reference types has been dropped. Instead, the @nt{expression} of a return statement of a limited type can only be an @nt{aggregate} or @nt{function_call} (see @RefSecNum{Limited Types}). This means that returning a global object or @nt{type_conversion}, legal in Ada 95, is now illegal. Such functions can be converted to use anonymous access return types by adding @key{access} in the function definition and return statement, adding .@key{all} in uses, and adding @key{aliased} in the object declarations. This has the advantage of making the reference return semantics much clearer to the casual reader.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We changed these rules so that functions, combined with the new rules for limited types (@RefSecnum{Limited Types}), can be used as build-in-place constructors for limited types. This reduces the differences between limited and nonlimited types, which will make limited types useful in more circumstances.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{extended_return_statement} is new. This provides a name for the object being returned, which reduces the copying needed to return complex objects (including no copying at all for limited objects). It also allows component-by-component construction of the return object.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The wording was updated to support anonymous access return subtypes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The term @lquotes@;return expression@rquotes@; was dropped because reviewers found it confusing when applied to the default @nt{expression} of an @nt{extended_return_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to class-wide return statements. These checks could not fail in Ada 95 (as all of the types had to be declared at the same level, so the tagged type would necessarily have been at the same level as the type of the object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to return statements for types with access discriminants. Since such types have to be limited in Ada 95, the @nt{expression} of a return statement would have been illegal in order for this check to fail.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added an @ImplPermName allowing early raising of Constraint_Error if the result cannot fit in the ultimate object. This gives implementations more flexibility to do built-in-place returns, and is essential for limited types (which cannot be built in a temporary).]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Pragma No_Return]} @ChgNote{Putting @nt{pragma} in the syntax font is used for Assert and Pure, at least.} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[A @nt{pragma} No_Return indicates that a procedure cannot return normally@Redundant[; it may propagate an exception or loop forever].]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@nt{Pragma} No_Deposit will have to wait for Ada 2017. :-)]} @end{Discussion} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[The form of a @nt{pragma} No_Return, which is a representation pragma (see @RefSecNum{Operational and Representation Items}), is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag<No_Return>(@SynI{procedure_}@Syn2{local_name}{, @SynI{procedure_}@Syn2{local_name}});''} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[@Defn{non-returning}Each @SynI{procedure_}@nt{local_name} shall denote one or more procedures or generic procedures; the denoted entities are @i<non-returning>. The @SynI{procedure_}@nt{local_name} shall not denote a null procedure nor an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A null procedure cannot have the appropriate non-returning semantics, as it does not raise an exception or loop forever.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The procedure can be abstract. The denoted declaration can be a @nt{renaming_declaration} if it obeys the usual rules for representation pragmas: the renaming has to occur immediately within the same declarative region as the renamed subprogram. If a non-returning procedure is renamed (anywhere) calls through the new name still have the non-returning semantics.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[A return statement shall not apply to a non-returning procedure or generic procedure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[A procedure shall be non-returning if it overrides a dispatching non-returning procedure. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that dispatching calls to non-returning procedures will, in fact, not return.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[If a renaming-as-body completes a non-returning procedure declaration, then the renamed procedure shall be non-returning.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that no extra code is needed to implement the renames (that is, no wrapper is needed) as the body has the same property.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[If a generic procedure is non-returning, then so are its instances. If a procedure declared within a generic unit is non-returning, then so are the corresponding copies of that procedure in instances.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[If the body of a non-returning procedure completes normally, Program_Error is raised at the point of the call. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{RunTime} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that there is no name for suppressing this check, since the check represents a bug, imposes no time overhead, and minimal space overhead (since it can usually be statically eliminated as dead code).]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a non-returning procedure tries to return, we raise Program_Error. This is stated as happening at the call site, because we do not wish to allow the procedure to handle the exception (and then, perhaps, try to return again!). However, the expected run-time model is that the compiler will generate @key{raise} Program_Error at the end of the procedure body (but not handleable by the procedure itself), as opposed to doing it at the call site. (This is just like the typical run-time model for functions that fall off the end without returning a value). The reason is indirect calls: in P.@key{all}(...);, the compiler cannot know whether P designates a non-returning procedure or a normal one. Putting the @key{raise} Program_Error in the procedure's generated code solves this problem neatly.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Similarly, if one passes a non-returning procedure to a generic formal parameter, the compiler cannot know this at call sites (in shared code implementations); the raise-in-body solution deals with this neatly.]} @end{ImplNote} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(procedure) Fail(Msg : String); --@RI[ raises Fatal_Error exception] @key(pragma) No_Return(Fail); --@RI[ Inform compiler and reader that procedure never returns normally]]} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} No_Return is new.]} @end{Extend95} @LabeledClause{Overloading of Operators} @begin{Intro} @Defn{operator} @Defn{user-defined operator} @Defn2{Term=[operator], Sec=(user-defined)} An @i{operator} is a function whose @nt{designator} is an @nt<operator_symbol>. @Redundant[Operators, like other functions, may be overloaded.] @end{Intro} @begin{Resolution} Each use of a unary or binary operator is equivalent to a @nt{function_call} with @SynI{function_}@nt{prefix} being the corresponding @nt{operator_symbol}, and with (respectively) one or two positional actual parameters being the operand(s) of the operator (in order). @begin{Honest} We also use the term operator (in Section 4 and in @RefSecNum{Subprogram Declarations}) to refer to one of the syntactic categories defined in @RefSec{Operators and Expression Evaluation} whose names end with @lquotes@;_operator:@rquotes@; @nt<logical_@!operator>, @nt<relational_@!operator>, @nt<binary_@!adding_@!operator>, @nt<unary_@!adding_@!operator>, @nt<multiplying_@!operator>, and @nt<highest_@!precedence_@!operator>. @end{Honest} @end{Resolution} @begin{Legality} The @nt{subprogram_specification} of a unary or binary operator shall have one or two parameters, respectively. A generic function instantiation whose @nt{designator} is an @nt{operator_symbol} is only allowed if the specification of the generic function has the corresponding number of parameters. @nt{Default_expression}s are not allowed for the parameters of an operator (whether the operator is declared with an explicit @nt{subprogram_specification} or by a @nt{generic_instantiation}). An explicit declaration of "/=" shall not have a result type of the predefined type Boolean. @end{Legality} @begin{StaticSem} A declaration of "=" whose result type is Boolean implicitly declares a declaration of "/=" that gives the complementary result. @end{StaticSem} @begin{Notes} The operators "+" and "@en@;" are both unary and binary operators, and hence may be overloaded with both one- and two-parameter functions. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of user-defined operators:} @begin{Example} @key[function] "+" (Left, Right : Matrix) @key[return] Matrix; @key[function] "+" (Left, Right : Vector) @key[return] Vector; @Comment{Blank line} --@RI{ assuming that A, B, and C are of the type Vector} --@RI{ the following two statements are equivalent:} @Comment{Blank line} A := B + C; A := "+"(B, C); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Explicit declarations of "=" are now permitted for any combination of parameter and result types. Explicit declarations of "/=" are now permitted, so long as the result type is not Boolean. @end{Extend83} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledAddedClause{Version=[2],Name=[Null Procedures]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A @nt<null_procedure_declaration> provides a shorthand to declare a procedure with an empty body.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<null_procedure_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] @Syn2{procedure_specification} @key{is} @key{null};>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A @nt<null_procedure_declaration> declares a @i<null procedure>.@Defn{null procedure}@Defn2{Term=[procedure],Sec=[null]} A completion is not allowed for a @nt<null_procedure_declaration>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no null functions because the return value has to be constructed somehow; a function that always raises Program_Error doesn't seem very useful or worth the complication.]} @end{Reason} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[The execution of a null procedure is invoked by a subprogram call. For the execution of a subprogram call on a null procedure, the execution of the @nt<subprogram_body> has no effect.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, a null procedure is equivalent to the body]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{begin} @key{null}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[with the exception that a null procedure can be used in place of a procedure specification.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[elaboration], Sec=(null_procedure_declaration)} The elaboration of a @nt{null_procedure_declaration} has no effect.]} @end{RunTime} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(procedure) Simplify(Expr : @key(in out) Expression) @key(is null); --@RI[ see @RefSecNum{Tagged Types and Type Extensions}] --@RI[ By default, Simplify does nothing, but it may be overridden in extensions of Expression]]} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Null procedures are new.]} @end{Extend95} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/07.mss���������������������������������������������������������������0000755�0001752�0001001�00000446525�12273462240�016413� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(07, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:24 $} @LabeledSection{Packages} @Comment{$Source: e:\\cvsroot/ARM/Source/07.mss,v $} @Comment{$Revision: 1.83 $} @begin{Intro} @redundant[@ToGlossaryAlso{Term=<Package>, Text=<Packages are program units that allow the specification of groups of logically related entities. Typically, a package contains the declaration of a type (often a private type or private extension) along with the declarations of primitive subprograms of the type, which can be called from outside the package, while their inner workings remain hidden from outside users.>} @IndexSee{Term=[information hiding],See=(package)} @IndexSee{Term=[encapsulation],See=(package)} @IndexSee{Term=[module],See=(package)} @IndexSeeAlso{Term=[class],See=(package)}] @end{Intro} @LabeledClause{Package Specifications and Declarations} @begin{Intro} @redundant[A package is generally provided in two parts: a @nt{package_specification} and a @nt{package_body}. Every package has a @nt{package_specification}, but not all packages have a @nt{package_body}.] @end{Intro} @begin{Syntax} @Syn{lhs=<package_declaration>,rhs="@Syn2{package_specification};"} @Syn{lhs=<package_specification>,rhs=" @key{package} @Syn2{defining_program_unit_name} @key{is} {@Syn2{basic_declarative_item}} [@key{private} {@Syn2{basic_declarative_item}}] @key{end} [[@Syn2{parent_unit_name}.]@Syn2{identifier}]"} @begin{SyntaxText} If an @nt{identifier} or @nt{parent_unit_name}.@nt{identifier} appears at the end of a @nt{package_specification}, then this sequence of lexical elements shall repeat the @nt{defining_program_unit_name}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @PDefn2{Term=[requires a completion], Sec=(@nt{package_declaration})} @PDefn2{Term=[requires a completion], Sec=(@nt{generic_package_declaration})} A @nt{package_declaration} or @nt{generic_package_declaration} requires a completion @Redundant[(a body)] if it contains any @Chg{Version=[2],New=[@nt{basic_declarative_item}], Old=[@nt<declarative_item>]} that requires a completion, but whose completion is not in its @nt{package_specification}. @begin(Honest) If an implementation supports it, a @nt{pragma} Import may substitute for the body of a package or generic package. @end(Honest) @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00420-01],ARef=[AI95-00434-01]} @PDefn2{Term=[visible part], Sec=<of a package (other than a generic formal package)>} The first list of @Chg{Version=[2],New=[@nt{basic_declarative_item}s], Old=[@nt{declarative_item}s]} of a @nt{package_specification} of a package other than a generic formal package is called the @i{visible part} of the package. @Redundant[@PDefn2{Term=[private part], Sec=(of a package)} The optional list of @Chg{Version=[2],New=[@nt{basic_declarative_item}s], Old=[@nt{declarative_item}s]} after the reserved word @key{private} (of any @nt{package_specification}) is called the @i{private part} of the package. If the reserved word @key{private} does not appear, the package has an implicit empty private part.]@Chg{Version=[2],New=[ Each list of @nt{basic_declarative_item}s of a @nt{package_specification} forms a @i{declaration list} of the package.@PDefn2{Term=[declaration list],Sec=(package_specification)}],Old=[]} @begin{Ramification} This definition of visible part does not apply to generic formal packages @em @RefSecNum{Formal Packages} defines the visible part of a generic formal package. The implicit empty private part is important because certain implicit declarations occur there if the package is a child package, and it defines types in its visible part that are derived from, or contain as components, private types declared within the parent package. These implicit declarations are visible in children of the child package. See @RefSecNum(Compilation Units - Library Units). @end{Ramification} @redundant[An entity declared in the private part of a package is visible only within the declarative region of the package itself (including any child units @em see @RefSecNum{Compilation Units - Library Units}). In contrast, expanded names denoting entities declared in the visible part can be used even outside the package; furthermore, direct visibility of such entities can be achieved by means of @nt{use_clause}s (see @RefSecNum{Selected Components} and @RefSecNum{Use Clauses}).] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(package_declaration)} The elaboration of a @nt{package_declaration} consists of the elaboration of its @nt{basic_declarative_item}s in the given order. @end{RunTime} @begin{Notes} The visible part of a package contains all the information that another program unit is able to know about the package. If a declaration occurs immediately within the specification of a package, and the declaration has a corresponding completion that is a body, then that body has to occur immediately within the body of the package. @begin{TheProof} This follows from the fact that the declaration and completion are required to occur immediately within the same declarative region, and the fact that @ntf{bodies} are disallowed (by the @SyntaxName@;s) in @nt{package_specification}s. This does not apply to instances of generic units, whose bodies can occur in @nt{package_specification}s. @end{TheProof} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package declaration:} @begin{Example} @key[package] Rational_Numbers @key[is] @key[type] Rational @key[is] @key[record] Numerator : Integer; Denominator : Positive; @key[end] @key[record]; @key[function] "="(X,Y : Rational) @key[return] Boolean; @key[function] "/" (X,Y : Integer) @key[return] Rational; --@RI{ to construct a rational number} @key[function] "+" (X,Y : Rational) @key[return] Rational; @key[function] "-" (X,Y : Rational) @key[return] Rational; @key[function] "*" (X,Y : Rational) @key[return] Rational; @key[function] "/" (X,Y : Rational) @key[return] Rational; @key[end] Rational_Numbers; @end{Example} There are also many examples of package declarations in the predefined language environment (see @RefSecNum{Predefined Language Environment}). @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 83, a library package is allowed to have a body even if it doesn't need one. In Ada 95, a library package body is either required or forbidden @em never optional. The workaround is to add @key[pragma] Elaborate_Body, or something else requiring a body, to each library package that has a body that isn't otherwise required. @end{Incompatible83} @begin{DiffWord83} We have moved the syntax into this clause and the next clause from RM83-7.1, @lquotes@;Package Structure@rquotes@;, which we have removed. RM83 was unclear on the rules about when a package requires a body. For example, RM83-7.1(4) and RM83-7.1(8) clearly forgot about the case of an incomplete type declared in a @nt{package_declaration} but completed in the body. In addition, RM83 forgot to make this rule apply to a generic package. We have corrected these rules. Finally, since we now allow a @nt{pragma} Import for any explicit declaration, the completion rules need to take this into account as well. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[Defined @lquotes@;declaration list@rquotes to avoid ambiguity in other rules as to whether packages are included.]} @end{DiffWord95} @LabeledClause{Package Bodies} @begin{Intro} @redundant[In contrast to the entities declared in the visible part of a package, the entities declared in the @nt{package_body} are visible only within the @nt{package_body} itself. As a consequence, a package with a @nt{package_body} can be used for the construction of a group of related subprograms in which the logical operations available to clients are clearly isolated from the internal entities.] @end{Intro} @begin{Syntax} @Syn{lhs=<package_body>,rhs=" @key{package} @key{body} @Syn2{defining_program_unit_name} @key{is} @Syn2{declarative_part} [@key{begin} @Syn2{handled_sequence_of_statements}] @key{end} [[@Syn2{parent_unit_name}.]@Syn2{identifier}];"} @begin{SyntaxText} If an @nt{identifier} or @nt{parent_unit_name}.@nt{identifier} appears at the end of a @nt{package_body}, then this sequence of lexical elements shall repeat the @nt{defining_program_unit_name}. @end{SyntaxText} @end{Syntax} @begin{Legality} A @nt{package_body} shall be the completion of a previous @nt{package_@!declaration} or @nt{generic_@!package_@!declaration}. A library @nt{package_@!declaration} or library @nt{generic_@!package_@!declaration} shall not have a body unless it requires a body@Redundant[; @key<pragma> Elaborate_Body can be used to require a @nt<library_@!unit_@!declaration> to have a body (see @RefSecNum{Elaboration Control}) if it would not otherwise require one]. @begin{Ramification} The first part of the rule forbids a @nt{package_body} from standing alone @em it has to belong to some previous @nt{package_declaration} or @nt{generic_package_declaration}. A nonlibrary @nt{package_declaration} or nonlibrary @nt<generic_package_declaration> that does not require a completion may have a corresponding body anyway. @end{Ramification} @end{Legality} @begin{StaticSem} In any @nt{package_body} without @nt{statement}s there is an implicit @nt{null_@!statement}. For any @nt{package_@!declaration} without an explicit completion, there is an implicit @nt{package_@!body} containing a single @nt{null_statement}. For a noninstance, nonlibrary package, this body occurs at the end of the @nt{declarative_@!part} of the innermost enclosing program unit or @nt{block_@!statement}; if there are several such packages, the order of the implicit @ntf{package_@!bodies} is unspecified. @PDefn{unspecified} @Redundant[(For an instance, the implicit @nt{package_@!body} occurs at the place of the instantiation (see @RefSecNum{Generic Instantiation}). For a library package, the place is partially determined by the elaboration dependences (see Section 10).)] @begin{Discussion} Thus, for example, we can refer to something happening just after the @key{begin} of a @nt{package_body}, and we can refer to the @nt{handled_sequence_of_statements} of a @nt{package_body}, without worrying about all the optional pieces. The place of the implicit body makes a difference for tasks activated by the package. See also RM83-9.3(5). The implicit body would be illegal if explicit in the case of a library package that does not require (and therefore does not allow) a body. This is a bit strange, but not harmful. @end{Discussion} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(nongeneric package_body)} For the elaboration of a nongeneric @nt{package_body}, its @nt{declarative_@!part} is first elaborated, and its @nt{handled_@!sequence_of_@!statements} is then executed. @end{RunTime} @begin{Notes} A variable declared in the body of a package is only visible within this body and, consequently, its value can only be changed within the @nt{package_body}. In the absence of local tasks, the value of such a variable remains unchanged between calls issued from outside the package to subprograms declared in the visible part. The properties of such a variable are similar to those of a @lquotes@;static@rquotes@; variable of C. The elaboration of the body of a subprogram explicitly declared in the visible part of a package is caused by the elaboration of the body of the package. Hence a call of such a subprogram by an outside program unit raises the exception Program_Error if the call takes place before the elaboration of the @nt{package_body} (see @RefSecNum{Declarative Parts}). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package body (see @RefSecNum{Package Specifications and Declarations}):} @begin{Example} @key[package] @key[body] Rational_Numbers @key[is] @key[procedure] Same_Denominator (X,Y : @key[in] @key[out] Rational) @key[is] @key[begin] --@RI{ reduces X and Y to the same denominator:} ... @key[end] Same_Denominator; @key[function] "="(X,Y : Rational) @key[return] Boolean @key[is] U : Rational := X; V : Rational := Y; @key[begin] Same_Denominator (U,V); @key[return] U.Numerator = V.Numerator; @key[end] "="; @key[function] "/" (X,Y : Integer) @key[return] Rational @key[is] @key[begin] @key[if] Y > 0 @key[then] @key[return] (Numerator => X, Denominator => Y); @key[else] @key[return] (Numerator => -X, Denominator => -Y); @key[end] @key[if]; @key[end] "/"; @key[function] "+" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "+"; @key[function] "-" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "-"; @key[function] "*" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "*"; @key[function] "/" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "/"; @key[end] Rational_Numbers; @end{Example} @end{Examples} @begin{DiffWord83} The syntax rule for @nt{package_body} now uses the syntactic category @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{package_body} is now required; that doesn't make any real difference, since a @nt{declarative_part} can be empty. RM83 seems to have forgotten to say that a @nt{package_body} can't stand alone, without a previous declaration. We state that rule here. RM83 forgot to restrict the definition of elaboration of @ntf{package_bodies} to nongeneric ones. We have corrected that omission. The rule about implicit bodies (from RM83-9.3(5)) is moved here, since it is more generally applicable. @end{DiffWord83} @LabeledClause{Private Types and Private Extensions} @begin{Intro} @redundant[The declaration (in the visible part of a package) of a type as a private type or private extension serves to separate the characteristics that can be used directly by outside program units (that is, the logical properties) from other characteristics whose direct use is confined to the package (the details of the definition of the type itself). See @RefSecNum(Type Extensions) for an overview of type extensions. @Defn{private types and private extensions} @IndexSee{Term=[information hiding],See=(private types and private extensions)} @IndexSee{Term=[opaque type],See=(private types and private extensions)} @IndexSee{Term=[abstract data type (ADT)],See=(private types and private extensions)} @IndexSee{Term=[ADT (abstract data type)],See=(private types and private extensions)}] @end{Intro} @begin{MetaRules} A private (untagged) type can be thought of as a record type with the type of its single (hidden) component being the full view. A private tagged type can be thought of as a private extension of an anonymous parent with no components. The only dispatching operation of the parent is equality (although the Size attribute, and, if nonlimited, assignment are allowed, and those will presumably be implemented in terms of dispatching). @end{MetaRules} @begin{Syntax} @Syn{lhs=<private_type_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}] @key{is} [[@key{abstract}] @key{tagged}] [@key{limited}] @key{private};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Syn{lhs=<private_extension_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}] @key{is} [@key{abstract}] @Chg{Version=[2],New=<[@key{limited} | @key{synchronized}]>,Old=[]} @key{new} @SynI(ancestor_)@Syn2{subtype_indication}@Chg{Version=[2],New=< [@key{and} @Syn2[interface_list]]>,Old=<>} @key{with private};"} @end{Syntax} @begin{Legality} @ChgNote{We don't mark this as a change, since it only involves the AARM} @Defn2{Term=[partial view], Sec=(of a type)} @PDefn2{Term=[requires a completion], Sec=(declaration of a partial view)} A @nt<private_type_declaration> or @nt<private_extension_declaration> declares a @i{partial view} of the type; such a declaration is allowed only as a @nt{declarative_item} of the visible part of a package, and it requires a completion, which shall be a @nt{full_type_declaration} that occurs as a @nt{declarative_item} of the private part of the package. @Chg{Version=[2],New=[],Old=[@Defn2{Term=[full view], Sec=(of a type)}]} @Redundant[@ChgNote{This really should be a change, but that's too hard.} The view of the type declared by the @nt<full_type_declaration> is called the @i(full view).] A generic formal private type or a generic formal private extension is also a partial view. @begin(Honest) A private type can also be completed by a @nt{pragma} Import, if supported by an implementation. @end(Honest) @begin{Reason} We originally used the term @lquotes@;private view,@rquotes@; but this was easily confused with the view provided @i(from) the private part, namely the full view. @end{Reason} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Full view is now defined in @RefSec{Type Declarations}, as all types now have them.]} @end{TheProof} @Redundant[A type shall be completely defined before it is frozen (see @RefSecNum{Completions of Declarations} and @RefSecNum{Freezing Rules}). Thus, neither the declaration of a variable of a partial view of a type, nor the creation by an @nt{allocator} of an object of the partial view are allowed before the full declaration of the type. Similarly, before the full declaration, the name of the partial view cannot be used in a @nt{generic_instantiation} or in a representation item.] @begin{TheProof} This rule is stated officially in @RefSec{Completions of Declarations}. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Redundant[A private type is limited if its declaration includes the reserved word @key[limited]; a private extension is limited if its ancestor type is @Chg{Version=[2], New=[a limited type that is not an interface type, or if the reserved word @key{limited} or @key{synchronized} appears in its definition],Old=[limited]}.] If the partial view is nonlimited, then the full view shall be nonlimited. If a tagged partial view is limited, then the full view shall be limited. @Redundant[On the other hand, if an untagged partial view is limited, the full view may be limited or nonlimited.] If the partial view is tagged, then the full view shall be tagged. @Redundant[On the other hand, if the partial view is untagged, then the full view may be tagged or untagged.] In the case where the partial view is untagged and the full view is tagged, no derivatives of the partial view are allowed within the immediate scope of the partial view; @Redundant[derivatives of the full view are allowed.] @begin{Ramification} Note that deriving from a partial view within its immediate scope can only occur in a package that is a child of the one where the partial view is declared. The rule implies that in the visible part of a public child package, it is impossible to derive from an untagged private type declared in the visible part of the parent package in the case where the full view of the parent type turns out to be tagged. We considered a model in which the derived type was implicitly redeclared at the earliest place within its immediate scope where characteristics needed to be added. However, we rejected that model, because (1) it would imply that (for an untagged type) subprograms explicitly declared after the derived type could be inherited, and (2) to make this model work for composite types as well, several implicit redeclarations would be needed, since new characteristics can become visible one by one; that seemed like too much mechanism. @end{Ramification} @begin{Discussion} The rule for tagged partial views is redundant for partial views that are private extensions, since all extensions of a given ancestor tagged type are tagged, and limited if the ancestor is limited. We phrase this rule partially redundantly to keep its structure parallel with the other rules. @end{Discussion} @begin{Honest} This rule is checked in a generic unit, rather than using the @lquotes@;assume the best@rquotes@; or @lquotes@;assume the worst@rquotes@; method. @end{Honest} @begin{Reason} @leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}Tagged limited private types have certain capabilities that are incompatible with having assignment for the full view of the type. In particular, tagged limited private types can be extended with @Chg{Version=[2],New=[],Old=[access discriminants and ]}components of a limited type, which works only because assignment is not allowed. Consider the following example: @begin{Example} @key[package] P1 @key[is] @key[type] T1 @key[is] @key[tagged] @key[limited] @key[private]; @key[procedure] Foo(X : @key[in] T1'Class); @key[private] @key[type] T1 @key[is] @key[tagged] @key[null] @key[record]; --@RI{ Illegal!} --@RI{ This should say @lquotes@;@key[tagged limited null record]@rquotes@;.} @key[end] P1; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] @key[body] P1 @key[is] @key[type] A @key[is] @key[access] T1'Class; Global : A; @key[procedure] Foo(X : @key[in] T1'Class) @key[is] @key[begin] Global := @key[new] T1'Class'(X); --@RI{ This would be illegal if the full view of} --@RI{ T1 were limited, like it's supposed to be.} @key[end] @Chg{New=[Foo],Old=[A]}; @key[end] P1; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}@key[with] P1; @key[package] P2 @key[is] @key[type] T2(D : @key[access] Integer)@Chg{Version=[2],New=[],Old=[ --@RI{ Trouble!}]} @key[is] @key[new] P1.T1 @key[with] @key[record] My_Task : Some_Task_Type; --@RI{ @Chg{Version=[2],New=[Trouble],Old=[More trouble]}!} @key[end] @key[record]; @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[with] P1; @key[with] P2; @key[procedure] Main @key[is] Local : @key[aliased] Integer; Y : P2.T2(@Chg{New=[D],Old=[A]} => Local'Access); @key[begin] P1.Foo(Y); @key[end] Main; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If the above example were legal, we would have succeeded in @Chg{Version=[2],New=[],Old=[making an access value that points to Main.Local after Main has been left, and we would also have succeeded in ]}doing an assignment of a task object, @Chg{Version=[2],New=[],Old=[both of ]}which @Chg{Version=[2],New=[is], Old=[are]} supposed to be @Chg{Version=[2],New=[a no-no],Old=[no-no's]}. @ChgNote{A runtime check prevents the first from being a problem in Ada 2005.} This rule is not needed for private extensions, because they inherit their limitedness from their ancestor, and there is a separate rule forbidding limited components of the corresponding record extension if the parent is nonlimited. @end{Reason} @begin{Ramification} @leading@;A type derived from an untagged private type is untagged, even if the full view of the parent is tagged, and even at places that can see the parent: @begin{Example} @key[package] P @key[is] @key[type] Parent @key[is] @key[private]; @key[private] @key[type] Parent @key[is] @key[tagged] @key[record] X: Integer; @key[end] @key[record]; @key[end] P; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @Chg{New=[@key[with] P; ],Old=[]}@key[package] Q @key[is] @key[type] T @key[is] @key[new] @Chg{New=[P.],Old=[]}Parent; @key[end] Q; @key[with] Q; @key[use] Q; @key[package] @key[body] P @key[is] ... T'Class ... --@RI{ Illegal!} Object: T; ... Object.X ... --@RI{ Illegal!} ... Parent(Object).X ... --@RI{ OK.} @key[end] P; @end{Example} The declaration of T declares an untagged view. This view is always untagged, so T'Class is illegal, it would be illegal to extend T, and so forth. The component name X is never visible for this view, although the component is still there @em one can get one's hands on it via a @nt{type_conversion}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00396-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If a full type has a partial view that is tagged, then:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the partial view shall be a synchronized tagged type (see @RefSecNum{Interface Types}) if and only if the full type is a synchronized tagged type;]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Since we do not allow record extensions of synchronized tagged types, this property has to be visible in the partial view to avoid privacy breaking. Generic formals do not need a similar rule as any extensions are rechecked for legality in the specification, and extensions of tagged formals are always illegal in a generic body.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the partial view shall be a descendant of an interface type (see 3.9.4) if and only if the full type is a descendant of the interface type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[Consider the following example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P @key{is} @key{package} Pkg @key{is} @key{type} Ifc @key{is interface}; @key{procedure} Foo (X : Ifc) @key{is abstract}; @key{end} Pkg;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Parent_1 @key{is tagged null record};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} T1 @key{is new} Parent_1 @key{with private}; @key{private} @key{type} Parent_2 @key{is new} Parent_1 @key{and} Pkg.Ifc @key{with null record}; @key{procedure} Foo (X : Parent_2); -- @RI[Foo #1]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} T1 @key{is new} Parent_2 @key{with null record}; -- @RI[Illegal.] @key{end} P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} P; @key{package} P_Client @key{is} @key{type} T2 @key{is new} P.T1 @key{and} P.Pkg.Ifc @key{with null record}; @key{procedure} Foo (X : T2); -- @RI[Foo #2] X : T2; @key{end} P_Client;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} P_Client; @key{package body} P @key{is} ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Bar (X : T1'Class) @key{is} @key{begin} Pkg.Foo (X); -- @RI[should call Foo #1 or an override thereof] @key{end};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{begin} Pkg.Foo (Pkg.Ifc'Class (P_Client.X)); -- @RI[should call Foo #2] Bar (T1'Class (P_Client.X)); @key{end} P;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This example is illegal because the completion of T1 is descended from an interface that the partial view is not descended from. If it were legal, T2 would implement Ifc twice, once in the visible part of P, and once in the visible part of P_Client. We would need to decide how Foo #1 and Foo #2 relate to each other. There are two options: either Foo #2 overrides Foo #1, or it doesn't.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Foo #2 overrides Foo #1, we have a problem because the client redefines a behavior that it doesn't know about, and we try to avoid this at all costs, as it would lead to a breakdown of whatever abstraction was implemented. If the abstraction didn't expose that it implements Ifc, there must be a reason, and it should be able to depend on the fact that no overriding takes place in clients. Also, during maintenance, things may change and the full view might implement a different set of interfaces. Furthermore, the situation is even worse if the full type implements another interface Ifc2 that happens to have a conforming Foo (otherwise unrelated, except for its name and profile).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Foo #2 doesn't override Foo #1, there is some similarity with the case of normal tagged private types, where a client can declare an operation that happens to conform to some private operation, and that's OK, it gets a different slot in the type descriptor. The problem here is that T2 would implement Ifc in two different ways, and through conversions to Ifc'Class we could end up with visibility on both of these two different implementations. This is the @lquotes@;diamond inheritance@rquotes problem of C++ all over again, and we would need some kind of a preference rule to pick one implementation. We don't want to go there (if we did, we might as well provide full-fledged multiple inheritance).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that there wouldn't be any difficulty to implement the first option, so the restriction is essentially methodological. The second option might be harder to implement, depending on the language rules that we would choose.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule also prevents completing a private type with an interface. A interface, like all types, is a descendant of itself, and thus this rule is triggered. One reason this is necessary is that a client of a private extension should be able to inherit limitedness without having to look in the private part to see if the type is an interface (remember that limitedness of interfaces is never inherited, while it is inherited from other types).]} @end{Ramification} @end{Itemize} @Defn2{Term=[ancestor subtype], Sec=(of a @nt<private_extension_declaration>)} The @i(ancestor subtype) of a @nt<private_extension_declaration> is the subtype defined by the @i(ancestor_)@!@nt<subtype_@!indication>; the ancestor type shall be a specific tagged type. The full view of a private extension shall be derived (directly or indirectly) from the ancestor type. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), the requirement that the ancestor be specific applies also in the private part of an instance of a generic unit. @begin{Reason} This rule allows the full view to be defined through several intermediate derivations, possibly from a series of types produced by @nt{generic_instantiation}s. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[If the reserved word @key{limited} appears in a @nt{private_extension_declaration}, the ancestor type shall be a limited type. If the reserved word @key{synchronized} appears in a @nt{private_extension_declaration}, the ancestor type shall be a limited interface.]} If the declaration of a partial view includes a @nt{known_discriminant_part}, then the @nt{full_type_declaration} shall have a fully conforming @Redundant[(explicit)] @nt{known_discriminant_part} @Redundant[(see @RefSec(Conformance Rules))]. @Defn2{Term=[full conformance],Sec=(required)} @Redundant[The ancestor subtype may be unconstrained; the parent subtype of the full view is required to be constrained (see @RefSecNum{Discriminants}).] @begin{Discussion} If the ancestor subtype has discriminants, then it is usually best to make it unconstrained. @end{Discussion} @begin{Ramification} If the partial view has a @nt<known_discriminant_part>, then the full view has to be a composite, non-array type, since only such types may have known discriminants. Also, the full view cannot inherit the discriminants in this case; the @nt{known_discriminant_part} has to be explicit. @leading@keepnext@;That is, the following is illegal: @begin{Example} @key[package] P @key[is] @key[type] T(D : Integer) @key[is] @key[private]; @key[private] @key[type] T @key[is] @key[new] Some_Other_Type; --@RI{ Illegal!} @key[end] P; @end{Example} even if Some_Other_Type has an integer discriminant called D. It is a ramification of this and other rules that in order for a tagged type to privately inherit unconstrained discriminants, the private type declaration has to have an @nt{unknown_discriminant_part}. @end{Ramification} If a private extension inherits known discriminants from the ancestor subtype, then the full view shall also inherit its discriminants from the ancestor subtype, and the parent subtype of the full view shall be constrained if and only if the ancestor subtype is constrained. @begin{Reason} The first part ensures that the full view has the same discriminants as the partial view. The second part ensures that if the partial view is unconstrained, then the full view is also unconstrained; otherwise, a client might constrain the partial view in a way that conflicts with the constraint on the full view. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[If the @nt{full_type_declaration} for a private extension is defined by a @nt{derived_type_definition}, then the reserved word @key{limited} shall appear in the @nt{full_type_declaration} if and only if it also appears in the @nt{private_extension_declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The word @key{limited} is optional (unless the ancestor is an interface), but it should be used consistently. Otherwise things would be too confusing for the reader. Of course, we only require that if the full type is defined by a @nt{derived_type_definition}, as we want to allow task and protected types to complete extensions of synchronized interfaces.]} @end{Reason} @Redundant[If a partial view has unknown discriminants, then the @nt{full_type_declaration} may define a definite or an indefinite subtype, with or without discriminants.] If a partial view has neither known nor unknown discriminants, then the @nt{full_type_declaration} shall define a definite subtype. If the ancestor subtype of a private extension has constrained discriminants, then the parent subtype of the full view shall impose a statically matching constraint on those discriminants. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Ramification} If the parent type of the full view is not the ancestor type, but is rather some descendant thereof, the constraint on the discriminants of the parent type might come from the declaration of some intermediate type in the derivation chain between the ancestor type and the parent type. @end{Ramification} @begin{Reason} @leading@keepnext@;This prevents the following: @begin{Example} @key[package] P @key[is] @key[type] T2 @key[is] @key[new] T1(Discrim => 3) @key[with] @key[private]; @key[private] @key[type] T2 @key[is] @key[new] T1(Discrim => 999) --@RI{ Illegal!} @key[with] @key[record] ...; @key[end] P; @end{Example} The constraints in this example do not statically match. @leading@;If the constraint on the parent subtype of the full view depends on discriminants of the full view, then the ancestor subtype has to be unconstrained: @begin{Example} @key[type] One_Discrim(A: Integer) @key[is] @key[tagged] ...; ... @key[package] P @key[is] @key[type] Two_Discrims(B: Boolean; C: Integer) @key[is] @key[new] One_Discrim @key[with] @key[private]; @key[private] @key[type] Two_Discrims(B: Boolean; C: Integer) @key[is] @key[new] One_Discrim(A => C) @key[with] @key[record] ... @key[end] @key[record]; @key[end] P; @end{Example} The above example would be illegal if the private extension said @lquotes@;is new One_Discrim(A => C);@rquotes@;, because then the constraints would not statically match. (Constraints that depend on discriminants are not static.) @end{Reason} @end{Legality} @begin{StaticSem} @PDefn{private type} A @nt{private_type_declaration} declares a private type and its first subtype. @PDefn{private extension} Similarly, a @nt{private_@!extension_@!declaration} declares a private extension and its first subtype. @begin{Discussion} @Defn{package-private type} A @i(package-private type) is one declared by a @nt<private_type_declaration>; that is, a private type other than a generic formal private type. @Defn{package-private extension} Similarly, a @i(package-private extension) is one declared by a @nt<private_extension_declaration>. These terms are not used in the RM95 version of this document. @end{Discussion} A declaration of a partial view and the corresponding @nt{full_type_declaration} define two views of a single type. The declaration of a partial view together with the visible part define the operations that are available to outside program units; the declaration of the full view together with the private part define other operations whose direct use is possible only within the declarative region of the package itself. @Defn{characteristics} Moreover, within the scope of the declaration of the full view, the @i{characteristics} of the type are determined by the full view; in particular, within its scope, the full view determines the classes that include the type, which components, entries, and protected subprograms are visible, what attributes and other predefined operations are allowed, and whether the first subtype is static. See @RefSecNum{Private Operations}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401]} A private extension inherits components (including discriminants unless there is a new @nt<discriminant_part> specified) and user-defined primitive subprograms from its ancestor type@Chg{Version=[2],New=[ and its progenitor types (if any)],Old=[]}, in the same way that a record extension inherits components and user-defined primitive subprograms from its parent type@Chg{Version=[2],New=[ and its progenitor types],Old=[]} (see @RefSecNum{Derived Types and Classes}). @begin{Honest} If an operation of the parent type is abstract, then the abstractness of the inherited operation is different for nonabstract record extensions than for nonabstract private extensions (see @RefSecNum{Abstract Types and Subprograms}). @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(private_type_declaration)} The elaboration of a @nt{private_type_declaration} creates a partial view of a type. @PDefn2{Term=[elaboration], Sec=(private_extension_declaration)} The elaboration of a @nt{private_extension_declaration} elaborates the @i(ancestor_)@nt<subtype_indication>, and creates a partial view of a type. @end{RunTime} @begin{Notes} The partial view of a type as declared by a @nt<private_type_declaration> is defined to be a composite view (in @RefSecNum{Types and Subtypes}). The full view of the type might or might not be composite. A private extension is also composite, as is its full view. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} Declaring a private type with an @nt{unknown_discriminant_part} is a way of preventing clients from creating uninitialized objects of the type; they are then forced to initialize each object by calling some operation declared in the visible part of the package. @Chg{Version=[2],New=[],Old=[If such a type is also limited, then no objects of the type can be declared outside the scope of the @nt{full_type_declaration}, restricting all object creation to the package defining the type. This allows complete control over all storage allocation for the type. Objects of such a type can still be passed as parameters, however.]} @begin{Discussion} @Defn{generic contract/private type contract analogy} Packages with private types are analogous to generic packages with formal private types, as follows: The declaration of a package-private type is like the declaration of a formal private type. The visible part of the package is like the generic formal part; these both specify a contract (that is, a set of operations and other things available for the private type). The private part of the package is like an instantiation of the generic; they both give a @nt{full_type_declaration} that specifies implementation details of the private type. The clients of the package are like the body of the generic; usage of the private type in these places is restricted to the operations defined by the contract. In other words, being inside the package is like being outside the generic, and being outside the package is like being inside the generic; a generic is like an @lquotes@;inside-out@rquotes@; package. This analogy also works for private extensions in the same inside-out way. Many of the legality rules are defined with this analogy in mind. See, for example, the rules relating to operations of [formal] derived types. The completion rules for a private type are intentionally quite similar to the matching rules for a generic formal private type. This analogy breaks down in one respect: a generic actual subtype is a subtype, whereas the full view for a private type is always a new type. (We considered allowing the completion of a @nt{private_type_declaration} to be a @nt{subtype_declaration}, but the semantics just won't work.) This difference is behind the fact that a generic actual type can be class-wide, whereas the completion of a private type always declares a specific type. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401]} The ancestor type specified in a @nt<private_extension_declaration> and the parent type specified in the corresponding declaration of a record extension given in the private part need not be the same@Chg{Version=[2],New=[. If the ancestor type is not an interface type,],Old=[ @em]} the parent type of the full view can be any descendant of the ancestor type. In this case, for a primitive subprogram that is inherited from the ancestor type and not overridden, the formal parameter names and default expressions (if any) come from the corresponding primitive subprogram of the specified ancestor type, while the body comes from the corresponding primitive subprogram of the parent type of the full view. See @RefSecNum{Dispatching Operations of Tagged Types}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00401]} @ChgAdded{Version=[2],Text=[If the ancestor type specified in a @nt{private_extension_declaration} is an interface type, the parent type can be any type so long as the full view is a descendant of the ancestor type. The progenitor types specified in a @nt{private_extension_declaration} and the progenitor types specified in the corresponding declaration of a record extension given in the private part need not be the same @em the only requirement is that the private extension and the record extension be descended from the same set of interfaces.]} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of private type declarations:} @begin{Example} @key[type] Key @key[is] @key[private]; @key[type] File_Name @key[is] @key[limited] @key[private]; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a private extension declaration:} @end{Wide} @begin{Example} @key[type] List @key[is] @key[new] Ada.Finalization.Controlled @key[with] @key[private]; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{private_type_declaration} is augmented to allow the reserved word @key{tagged}. In Ada 83, a private type without discriminants cannot be completed with a type with discriminants. Ada 95 allows the full view to have discriminants, so long as they have defaults (that is, so long as the first subtype is definite). This change is made for uniformity with generics, and because the rule as stated is simpler and easier to remember than the Ada 83 rule. In the original version of Ada 83, the same restriction applied to generic formal private types. However, the restriction was removed by the ARG for generics. In order to maintain the @lquotes@;generic contract/private type contract analogy@rquotes@; discussed above, we have to apply the same rule to package-private types. Note that a private untagged type without discriminants can be completed with a tagged type with discriminants only if the full view is constrained, because discriminants of tagged types cannot have defaults. @end{Extend83} @begin{DiffWord83} RM83-7.4.1(4), @lquotes@;Within the specification of the package that declares a private type and before the end of the corresponding full type declaration, a restriction applies....@rquotes@;, is subsumed (and corrected) by the rule that a type shall be completely defined before it is frozen, and the rule that the parent type of a derived type declaration shall be completely defined, unless the derived type is a private extension. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00396-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Added @nt{interface_list} to private extensions to support interfaces and multiple inheritance (see @RefSecNum{Interface Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A private extension may specify that it is a limited type. This is required for interface ancestors (from which limitedness is not inherited), but it is generally useful as documentation of limitedness.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[A private extension may specify that it is a synchronized type. This is required in order so that a regular limited interface can be used as the ancestor of a synchronized type (we do not allow hiding of synchronization).]} @end{Extend95} @LabeledSubClause{Private Operations} @begin{Intro} @Redundant[For a type declared in the visible part of a package or generic package, certain operations on the type do not become visible until later in the package @em either in the private part or the body. @Defn{private operations} Such @i{private operations} are available only inside the declarative region of the package or generic package.] @end{Intro} @begin{StaticSem} The predefined operators that exist for a given type are determined by the classes to which the type belongs. For example, an integer type has a predefined "+" operator. In most cases, the predefined operators of a type are declared immediately after the definition of the type; the exceptions are explained below. Inherited subprograms are also implicitly declared immediately after the definition of the type, except as stated below. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} For a composite type, the characteristics (see @RefSecNum{Private Types and Private Extensions}) of the type are determined in part by the characteristics of its component types. At the place where the composite type is declared, the only characteristics of component types used are those characteristics visible at that place. If later @Chg{New=[immediately within the declarative region in which the composite type is declared], Old=[within the immediate scope of the composite type]} additional characteristics become visible for a component type, then any corresponding characteristics become visible for the composite type. Any additional predefined operators are implicitly declared at that place. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} The corresponding rule applies to a type defined by a @nt{derived_type_definition}, if there is a place @Chg{New=[immediately within the declarative region in which the type is declared], Old=[within its immediate scope]} where additional characteristics of its parent type become visible. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} @Defn{become nonlimited} @Defn2{Term=[nonlimited type],Sec=(becoming nonlimited)} @Defn2{Term=[limited type],Sec=(becoming nonlimited)} @Redundant[For example, an array type whose component type is limited private becomes nonlimited if the full view of the component type is nonlimited and visible at some later place @Chg{New=[immediately within the declarative region in which the array type is declared.], Old=[within the immediate scope of the array type.]} In such a case, the predefined "=" operator is implicitly declared at that place, and assignment is allowed after that place.] @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} Inherited primitive subprograms follow a different rule. For a @nt{derived_type_definition}, each inherited primitive subprogram is implicitly declared at the earliest place, if any, @Chg{New=[immediately within the declarative region in which], Old=[within the immediate scope of]} the @nt{type_declaration}@Chg{New=[ occurs],Old=[]}, but after the @nt{type_declaration}, where the corresponding declaration from the parent is visible. If there is no such place, then the inherited subprogram is not declared at all. @Redundant[An inherited subprogram that is not declared at all cannot be named in a call and cannot be overridden, but for a tagged type, it is possible to dispatch to it.] For a @nt{private_extension_declaration}, each inherited subprogram is declared immediately after the @nt{private_extension_declaration} if the corresponding declaration from the ancestor is visible at that place. Otherwise, the inherited subprogram is not declared for the private extension, @Redundant[though it might be for the full type]. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} There is no need for the @lquotes@;earliest place @Chg{New=[immediately within the declarative region], Old=[within the immediate scope]}@rquotes@; business here, because a @nt{private_extension_declaration} will be completed with a @nt{full_type_declaration}, so we can hang the necessary private implicit declarations on the @nt{full_type_declaration}. @end{Reason} @begin{Discussion} The above rules matter only when the component type (or parent type) is declared in the visible part of a package, and the composite type (or derived type) is declared within the declarative region of that package (possibly in a nested package or a child package). @leading@keepnext@;Consider: @begin{Example} @key[package] Parent @key[is] @key[type] Root @key[is] @key[tagged] @key[null] @key[record]; @key[procedure] Op1(X : Root); @key[type] My_Int @key[is] @key[range] 1..10; @key[private] @key[procedure] Op2(X : Root); @key[type] Another_Int @key[is] @key[new] My_Int; @key[procedure] Int_Op(X : My_Int); @key[end] Parent; @key[with] Parent; @key[use] Parent; @key[package] Unrelated @key[is] @key[type] T2 @key[is] @key[new] Root @key[with] @key[null] @key[record]; @key[procedure] Op2(X : T2); @key[end] Unrelated; @key[package] Parent.Child @key[is] @key[type] T3 @key[is] @key[new] Root @key[with] @key[null] @key[record]; --@RI{ Op1(T3) implicitly declared here.} @key[package] Nested @key[is] @key[type] T4 @key[is] @key[new] Root @key[with] @key[null] @key[record]; @key[private] ... @key[end] Nested; @key[private] --@RI{ Op2(T3) implicitly declared here.} ... @key[end] Parent.Child; @key[with] Unrelated; @key[use] Unrelated; @key[package] @key[body] Parent.Child @key[is] @key[package] @key[body] Nested @key[is] --@RI{ Op2(T4) implicitly declared here.} @key[end] Nested; @key[type] T5 @key[is] @key[new] T2 @key[with] @key[null] @key[record]; @key[end] Parent.Child; @end{Example} Another_Int does not inherit Int_Op, because Int_Op does not @lquotes@;exist@rquotes@; at the place where Another_Int is declared. @ChgRef{Version=[1],Kind=[Revised]} Type T2 inherits Op1 and Op2 from Root. However, the inherited Op2 is never declared, because Parent.Op2 is never visible @Chg{New=[immediately within the declarative region], Old=[within the immediate scope]} of T2. T2 explicitly declares its own Op2, but this is unrelated to the inherited one @em it does not override the inherited one, and occupies a different slot in the type descriptor. T3 inherits both Op1 and Op2. Op1 is implicitly declared immediately after the type declaration, whereas Op2 is declared at the beginning of the private part. Note that if Child were a private child of Parent, then Op1 and Op2 would both be implicitly declared immediately after the type declaration. @ChgRef{Version=[1],Kind=[Revised]} T4 is similar to T3, except that the earliest place @Chg{New=[immediately within the declarative region containing T4], Old=[within T4's immediate scope]} where Root's Op2 is visible is in the body of Nested. If T3 or T4 were to declare a type-conformant Op2, this would override the one inherited from Root. This is different from the situation with T2. T5 inherits Op1 and two Op2's from T2. Op1 is implicitly declared immediately after the declaration of T5, as is the Op2 that came from Unrelated.Op2. However, the Op2 that originally came from Parent.Op2 is never implicitly declared for T5, since T2's version of that Op2 is never visible (anywhere @em it never got declared either). For all of these rules, implicit private parts and bodies are assumed as needed. @leading@keepnext@;It is possible for characteristics of a type to be revealed in more than one place: @begin{Example} @key[package] P @key[is] @key[type] Comp1 @key[is] @key[private]; @key[private] @key[type] Comp1 @key[is] @key[new] Boolean; @key[end] P; @key[package] P.Q @key[is] @key[package] R @key[is] @key[type] Comp2 @key[is] @key[limited] @key[private]; @key[type] A @key[is] @key[array](Integer @key[range] <>) @key[of] Comp2; @key[private] @key[type] Comp2 @key[is] @key[new] Comp1; --@RI{ A becomes nonlimited here.} --@RI{ "="(A, A) return Boolean is implicitly declared here.} ... @key[end] R; @key[private] --@RI{ Now we find out what Comp1 really is, which reveals} --@RI{ more information about Comp2, but we're not within} --@RI{ the immediate scope of Comp2, so we don't do anything} --@RI{ about it yet.} @key[end] P.Q; @key[package] @key[body] P.Q @key[is] @key[package] @key[body] R @key[is] --@RI{ Things like "@key[xor]"(A,A) return A are implicitly} --@RI{ declared here.} @key[end] R; @key[end] P.Q; @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0019],ARef=[AI95-00033-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[We say @i<immediately> within the declarative region in order that types do not gain operations within a nested scope. Consider:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@Key[package] Outer @key[is] @key[package] Inner @key[is] @key[type] Inner_Type @key[is] @key[private]; @key[private] @key[type] Inner_Type @key[is] @key[new] Boolean; @key[end] Inner; @key[type] Outer_Type @key[is] @key[array](Natural @key[range] <>) @key[of] Inner.Inner_Type; @key[end] Outer;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] @key[body] Outer @key[is] @key[package] @key[body] Inner @key[is] -- At this point, we can see that Inner_Type is a Boolean type. -- But we don't want Outer_Type to gain an "and" operator here. @key[end] Inner; @key[end] Outer;],Old=[]} @end{Example} @end{Discussion} @leading@Redundant[The Class attribute is defined for tagged subtypes in @RefSecNum{Tagged Types and Type Extensions}. In addition,] for @PrefixType{every subtype S of an untagged private type whose full view is tagged}, the following attribute is defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<Class>, Text=<Denotes the class-wide subtype corresponding to the full view of S. This attribute is allowed only from the beginning of the private part in which the full view is declared, until the declaration of the full view. @Redundant[After the full view, the Class attribute of the full view can be used.]>} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} Because a partial view and a full view are two different views of one and the same type, outside of the defining package the characteristics of the type are those defined by the visible part. Within these outside program units the type is just a private type or private extension, and any language rule that applies only to another class of types does not apply. The fact that the full declaration might implement a private type with a type of a particular class (for example, as an array type) is relevant only within the declarative region of the package itself including any child units. @NoPrefix@;The consequences of this actual implementation are, however, valid everywhere. For example: any default initialization of components takes place; the attribute Size provides the size of the full view; finalization is still done for controlled components of the full view; task dependence rules still apply to components that are task objects. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Partial views provide @Chg{Version=[2],New=[initialization], Old=[assignment (unless the view is limited)]}, membership tests, selected components for the selection of discriminants and inherited components, qualification, and explicit conversion.@Chg{Version=[2],New=[ Nonlimited partial views also allow use of @nt{assignment_statement}s.],Old=[]} For a subtype S of a partial view, S'Size is defined (see @RefSecNum{Operational and Representation Attributes}). For an object A of a partial view, the attributes A'Size and A'Address are defined (see @RefSecNum{Operational and Representation Attributes}). The Position, First_Bit, and Last_Bit attributes are also defined for discriminants and inherited components. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a type with private operations:} @begin{Example} @key[package] Key_Manager @key[is] @key[type] Key @key[is] @key[private]; Null_Key : @key[constant] Key; --@RI{ a deferred constant declaration (see @RefSecNum{Deferred Constants})} @key[procedure] Get_Key(K : @key[out] Key); @key[function] "<" (X, Y : Key) @key[return] Boolean; @key[private] @key[type] Key @key[is] @key[new] Natural; Null_Key : @key[constant] Key := Key'First; @key[end] Key_Manager; @key[package] @key[body] Key_Manager @key[is] Last_Key : Key := Null_Key; @key[procedure] Get_Key(K : @key[out] Key) @key[is] @key[begin] Last_Key := Last_Key + 1; K := Last_Key; @key[end] Get_Key; @key[function] "<" (X, Y : Key) @key[return] Boolean @key[is] @key[begin] @key[return] Natural(X) < Natural(Y); @key[end] "<"; @key[end] Key_Manager; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the example:} Outside of the package Key_Manager, the operations available for objects of type Key include assignment, the comparison for equality or inequality, the procedure Get_Key and the operator "<"; they do not include other relational operators such as ">=", or arithmetic operators. @NoPrefix@;The explicitly declared operator "<" hides the predefined operator "<" implicitly declared by the @nt{full_type_declaration}. Within the body of the function, an explicit conversion of X and Y to the subtype Natural is necessary to invoke the "<" operator of the parent type. Alternatively, the result of the function could be written as not (X >= Y), since the operator ">=" is not redefined. @NoPrefix@;The value of the variable Last_Key, declared in the package body, remains unchanged between calls of the procedure Get_Key. (See also the NOTES of @RefSecNum{Package Bodies}.) @end{Notes} @begin{DiffWord83} The phrase in RM83-7.4.2(7), @lquotes@;...after the full type declaration@rquotes@;, doesn't work in the presence of child units, so we define that rule in terms of visibility. The definition of the Constrained attribute for private types has been moved to @lquotes@;Obsolescent Features.@rquotes@; (The Constrained attribute of an object has not been moved there.) @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0018],ARef=[AI95-00033-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Clarified when additional operations are declared.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @Chg{Version=[2],New=[Revised the note on operations of partial views to reflect that limited types do have an assignment operation, but not @nt{assignment_statement}s.],Old=[]} @end{DiffWord95} @LabeledClause{Deferred Constants} @begin{Intro} @redundant[Deferred constant declarations may be used to declare constants in the visible part of a package, but with the value of the constant given in the private part. They may also be used to declare constants imported from other languages (see @RefSecNum{Interface to Other Languages}).] @end{Intro} @begin{Legality} @Redundant[@Defn{deferred constant declaration} A @i(deferred constant declaration) is an @nt<object_declaration> with the reserved word @key(constant) but no initialization expression.] @Defn{deferred constant} The constant declared by a deferred constant declaration is called a @i{deferred constant}. @PDefn2{Term=[requires a completion], Sec=(deferred constant declaration)} A deferred constant declaration requires a completion, which shall be a full constant declaration (called the @i{full declaration} of the deferred constant), or a @nt{pragma} Import (see @RefSecNum(Interface to Other Languages)). @Defn{full declaration} @begin{TheProof} The first sentence is redundant, as it is stated officially in @RefSecNum(Object Declarations). @end{TheProof} @leading@;A deferred constant declaration that is completed by a full constant declaration shall occur immediately within the visible part of a @nt<package_specification>. For this case, the following additional rules apply to the corresponding full declaration: @begin(itemize) The full declaration shall occur immediately within the private part of the same package; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The deferred and full constants shall have the same type@Chg{Version=[2], New=[, or shall have statically matching anonymous access subtypes],Old=[]}; @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} This implies that both the deferred declaration and the full declaration have to have a @nt<subtype_indication>@Chg{Version=[2],New=[ or @nt{access_definition}],Old=[]} rather than an @nt<array_type_definition>, because each @nt{array_type_definition} would define a new type. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} If the @Chg{Version=[2],New=[deferred constant declaration includes a],Old=[subtype defined by the]} @nt<subtype_indication> @Chg{Version=[2], New=[that defines a],Old=[in the deferred declaration is]} constrained@Chg{Version=[2],New=[ subtype],Old=[]}, then the subtype defined by the @nt<subtype_indication> in the full declaration shall match it statically.@Redundant[ On the other hand, if the subtype of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint. The constant itself will be constrained, like all constants;] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} If the deferred constant declaration includes the reserved word @key(aliased), then the full declaration shall also@Chg{Version=[2],New=[;],Old=[.]} @begin{Ramification} On the other hand, the full constant can be aliased even if the deferred constant is not. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If the subtype of the deferred constant declaration excludes null, the subtype of the full declaration shall also exclude null.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[On the other hand, the full constant can exclude null even if the deferred constant does not. But that can only happen for a @nt{subtype_indication}, as anonymous access types are required to statically match (which includes any @nt{null_exclusion}).]} @end{Ramification} @end(itemize) @Redundant[A deferred constant declaration that is completed by a @nt{pragma} Import need not appear in the visible part of a @nt{package_specification}, and has no full constant declaration.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} The completion of a deferred constant declaration shall occur before the constant is frozen (see @Chg{Version=[2],New=[@RefSecNum{Freezing Rules}], Old=[@RefSecNum{Deferred Constants}]}). @end{Legality} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(deferred constant declaration)} The elaboration of a deferred constant declaration elaborates the @nt<subtype_indication> or (only allowed in the case of an imported constant) the @nt<array_type_definition>. @end{RunTime} @begin{Notes} The full constant declaration for a deferred constant that is of a given private type or private extension is not allowed before the corresponding @nt{full_type_declaration}. This is a consequence of the freezing rules for types (see @RefSecNum{Freezing Rules}). @begin{Ramification} Multiple or single declarations are allowed for the deferred and the full declarations, provided that the equivalent single declarations would be allowed. Deferred constant declarations are useful for declaring constants of private views, and types with components of private views. They are also useful for declaring access-to-constant objects that designate variables declared in the private part of a package. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of deferred constant declarations:} @begin{Example} Null_Key : @key[constant] Key; --@RI[ see @RefSecNum{Private Operations}] CPU_Identifier : @key[constant] String(1..8); @key[pragma] Import(Assembler, CPU_Identifier, Link_Name => "CPU_ID"); --@RI[ see @RefSecNum{Interfacing Pragmas}] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, a deferred constant is required to be of a private type declared in the same visible part. This restriction is removed for Ada 95; deferred constants can be of any type. In Ada 83, a deferred constant declaration was not permitted to include a constraint, nor the reserved word @key(aliased). In Ada 83, the rules required conformance of type marks; here we require static matching of subtypes if the deferred constant is constrained. A deferred constant declaration can be completed with a @nt{pragma} Import. Such a deferred constant declaration need not be within a @nt{package_specification}. The rules for too-early uses of deferred constants are modified in Ada 95 to allow more cases, and catch all errors at compile time. This change is necessary in order to allow deferred constants of a tagged type without violating the principle that for a dispatching call, there is always an implementation to dispatch to. It has the beneficial side-effect of catching some Ada-83-erroneous programs at compile time. The new rule fits in well with the new freezing-point rules. Furthermore, we are trying to convert undefined-value problems into bounded errors, and we were having trouble for the case of deferred constants. Furthermore, uninitialized deferred constants cause trouble for the shared variable / tasking rules, since they are really variable, even though they purport to be constant. In Ada 95, they cannot be touched until they become constant. Note that we do not consider this change to be an upward incompatibility, because it merely changes an erroneous execution in Ada 83 into a compile-time error. The Ada 83 semantics are unclear in the case where the full view turns out to be an access type. It is a goal of the language design to prevent uninitialized access objects. One wonders if the implementation is required to initialize the deferred constant to null, and then initialize it (again!) to its real value. In Ada 95, the problem goes away. @end{Extend83} @begin{DiffWord83} Since deferred constants can now be of a nonprivate type, we have made this a stand-alone clause, rather than a subclause of @RefSec{Private Types and Private Extensions}. Deferred constant declarations used to have their own syntax, but now they are simply a special case of @nt<object_declaration>s. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Deferred constants were enhanced to allow the use of anonymous access types in them.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added matching rules for subtypes that exclude null.]} @end{DiffWord95} @LabeledClause{Limited Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @redundant[A limited type is (a view of) a type for which @Chg{Version=[2],New=[copying (such as for an @nt{assignment_statement})], Old=[the assignment operation]} is not allowed. A nonlimited type is a (view of a) type for which @Chg{Version=[2],New=[copying], Old=[the assignment operation]} is allowed.] @begin{Discussion} The concept of the @i(value) of a limited type is difficult to define, since the abstract value of a limited type often extends beyond its physical representation. In some sense, values of a limited type cannot be divorced from their object. The value @i(is) the object. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} In Ada 83, in the two places where limited types were defined by the language, namely tasks and files, an implicit level of indirection was implied by the semantics to avoid the separation of the value from an associated object. In Ada 95, most limited types are passed by reference, and even return-ed by reference.@Chg{Version=[2],New=[ In Ada 2005, most limited types are built-in-place upon return, rather than returned by reference. Thus the object @lquotes@;identity@rquotes is part of the logical value of most limited types.],Old=[]} @end{Discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00419-01]} For a limited partial view whose full view is nonlimited, @Chg{Version=[2],New=[copying],Old=[assignment]} is possible on parameter passing and function return. To prevent any copying whatsoever, one should make both the partial @i{and} full views limited. @end{Honest} @Comment{The below was moved from a ChgToGlossaryAlso.} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Limited type>, Text=<A limited type is @Chg{Version=[2],New=[],Old=[(a view of) ]}a type for which @Chg{Version=[2],New=[copying (such as in an @nt{assignment_statement})], Old=[the assignment operation]} is not allowed. A nonlimited type is a @Chg{Version=[2],New=[],Old=[(view of a) ]}type for which @Chg{Version=[2],New=[copying], Old=[the assignment operation]} is allowed.>} @end{Intro} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} If a tagged record type has any limited components, then the reserved word @key[limited] shall appear in its @nt<record_type_definition>.@Chg{Version=[2],New=[ @Redundant[If the reserved word @key[limited] appears in the definition of a @nt{derived_type_definition}, its parent type and any progenitor interfaces shall be limited.]],Old=[]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[The rule about the parent type being required to be limited can be found in @RefSecNum{Derived Types and Classes}. Rules about progenitor interfaces can be found in @RefSecNum{Interface Types}, specifically, a nonlimited interface can appear only on a nonlimited type. We repeat these rules here to gather these scattered rules in one obvious place.]} @end{TheProof} @begin{Reason} @leading@;This prevents tagged limited types from becoming nonlimited. Otherwise, the following could happen: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[limited] @key[private]; @key[type] R @key[is] @key[tagged] @key[record] --@RI{ Illegal!} --@RI{ This should say @lquotes@;@key[limited record]@rquotes@;.} X : T; @key[end] @key[record]; @key[private] @key[type] T @key[is] @key[new] Integer; --@RI{ R becomes nonlimited here.} @key[end] P; @ChgRef{Version=[2],Kind=[Revised]} @key[package] Q @key[is] @key[type] R2@Chg{Version=[2],New=[],Old=[(Access_Discrim : @key[access] ...)]} @key[is] @key[new] R @key[with] @key[record] Y : Some_Task_Type; @key[end] @key[record]; @key[end] Q; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If the above were legal, then assignment would be defined for R'Class in the body of P, which is bad news, given @Chg{Version=[2],New=[],Old=[the access discriminant and ]}the task. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the following contexts, an @nt{expression} of a limited type is not permitted unless it is an @nt{aggregate}, a @nt{function_call}, or a parenthesized @nt{expression} or @nt{qualified_expression} whose operand is permitted by this rule:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the initialization @nt{expression} of an @nt{object_declaration} (see @RefSecNum{Object Declarations})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{default_expression} of a @nt{component_declaration} (see @RefSecNum{Record Types})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} of a @nt{record_component_association} (see @RefSecNum{Record Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} for an @nt{ancestor_part} of an @nt{extension_aggregate} (see @RefSecNum{Extension Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[an @nt{expression} of a @nt{positional_array_aggregate} or the @nt{expression} of an @nt{array_component_association} (see @RefSecNum{Array Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{qualified_expression} of an initialized allocator (see @RefSecNum{Allocators})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} of a return statement (see @RefSecNum{Return Statements})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{default_expression} or actual parameter for a formal object of mode @b{in} (see @RefSecNum{Formal Objects})],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[All of these contexts normally require copying; by restricting the uses as above, we can require the new object to be built-in-place.]} @end{Discussion} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @leading@keepnext@Defn{limited type} A type is @i{limited} if it is @Chg{Version=[2],New=[],Old=[a descendant of ]}one of the following: @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00411-01],ARef=[AI95-00419-01]} a type with the reserved word @key(limited)@Chg{Version=[2],New=[, @key(synchronized), @key(task), or @key(protected) ],Old=[]} in its definition; @begin{Ramification} Note that there is always a @lquotes@;definition,@rquotes@; conceptually, even if there is no syntactic category called @lquotes@;..._definition@rquotes@;. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[This includes interfaces of the above kinds, derived types with the reserved word @key{limited}, as well as task and protected types.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00419-01]} @ChgDeleted{Version=[2],Text=[a task or protected type;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} a composite type with a limited component@Chg{Version=[2],New=[;],Old=[.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[a derived type whose parent is limited and is not an interface.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Limitedness is not inherited from interfaces; it must be explicitly specified when the parent is an interface.]} @end{Ramification} @end(itemize) @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A derived type can become nonlimited if @key{limited} does not appear and the derivation takes place in the visible part of a child package, and the parent type is nonlimited as viewed from the private part or body of the child package.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[We considered a rule where limitedness was always inherited from the parent for derived types, but in the case of a type whose parent is an interface, this meant that the first interface is treated differently than other interfaces. It also would have forced users to declare dummy nonlimited interfaces just to get the limitedness right. We also considered a syntax like @key{not limited} to specify nonlimitedness when the parent was limited, but that was unsavory. The rule given is more uniform and simpler to understand.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[The rules for interfaces are asymmetrical, but the language is not: if the parent interface is limited, the presence of the word @key{limited} determines the limitedness, and nonlimited progenitors are illegal by the rules in @RefSecNum{Interface Types}. If the parent interface is nonlimited, the word @key{limited} is illegal by the rules in @RefSecNum{Derived Types and Classes}. The net effect is that the order of the interfaces doesn't matter.]} @end{Reason} @Defn{nonlimited type} Otherwise, the type is nonlimited. @Redundant[There are no predefined equality operators for a limited type.] @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[ For an @nt{aggregate} of a limited type used to initialize an object as allowed above, the implementation shall not create a separate anonymous object for the @nt{aggregate}. For a @nt{function_call} of a type with a part that is of a task, protected, or explicitly limited record type that is used to initialize an object as allowed above, the implementation shall not create a separate return object (see 6.5) for the @nt{function_call}. The @nt{aggregate} or @nt{function_call} shall be constructed directly in the new object.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[For a @nt{function_call}, we only require @i{build-in-place}@PDefn{build-in-place} for a limited type that would have been a return-by-reference type in Ada 95. We do this because we want to minimize disruption to Ada 95 implementations and users.]} @end{Discussion} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[While it is allowed to write initializations of limited objects, such initializations never copy a limited object. The source of such an assignment operation must be an @nt<aggregate> or @nt<function_call>, and such @nt<aggregate>s and @nt<function_call>s must be built directly in the target object.], Old=[@leading@keepnext@;The following are consequences of the rules for limited types:]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This isn't quite true if the type can become nonlimited (see below); @nt{function_call}s only are required to be build-in-place for @lquotes@;really@rquotes@; limited types.]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 10 through 15 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[An initialization expression is not allowed in an @nt{object_declaration} if the type of the object is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A default expression is not allowed in a @nt{component_declaration} if the type of the record component is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[An initialized allocator is not allowed if the designated type is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A generic formal parameter of mode @key[in] must not be of a limited type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[@nt{Aggregate}s are not available for a limited composite type. Concatenation is not available for a limited array type.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[The rules do not exclude a @nt{default_expression} for a formal parameter of a limited type; they do not exclude a deferred constant of a limited type if the full declaration of the constant is of a nonlimited type.]} @Defn{become nonlimited} @Defn2{Term=[nonlimited type],Sec=(becoming nonlimited)} @Defn2{Term=[limited type],Sec=(becoming nonlimited)} As illustrated in @RefSecNum{Private Operations}, an untagged limited type can become nonlimited under certain circumstances. @begin{Ramification} Limited private types do not become nonlimited; instead, their full view can be nonlimited, which has a similar effect. It is important to remember that a single nonprivate type can be both limited and nonlimited in different parts of its scope. In other words, @lquotes@;limited@rquotes@; is a property that depends on where you are in the scope of the type. We don't call this a @lquotes@;view property@rquotes@; because there is no particular declaration to declare the nonlimited view. Tagged types never become nonlimited. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package with a limited type:} @begin{Example} @key[package] IO_Package @key[is] @key[type] File_Name @key[is] @key[limited] @key[private]; @key[procedure] Open (F : @key[in] @key[out] File_Name); @key[procedure] Close(F : @key[in] @key[out] File_Name); @key[procedure] Read (F : @key[in] File_Name; Item : @key[out] Integer); @key[procedure] Write(F : @key[in] File_Name; Item : @key[in] Integer); @key[private] @key[type] File_Name @key[is] @key[limited] @key[record] Internal_Name : Integer := 0; @key[end] @key[record]; @key[end] IO_Package; @key[package] @key[body] IO_Package @key[is] Limit : @key[constant] := 200; @key[type] File_Descriptor @key[is] @key[record] ... @key[end] @key[record]; Directory : @key[array] (1 .. Limit) @key[of] File_Descriptor; ... @key[procedure] Open (F : @key[in] @key[out] File_Name) @key[is] ... @key[end]; @key[procedure] Close(F : @key[in] @key[out] File_Name) @key[is] ... @key[end]; @key[procedure] Read (F : @key[in] File_Name; Item : @key[out] Integer) @key[is] ... @key[end]; @key[procedure] Write(F : @key[in] File_Name; Item : @key[in] Integer) @key[is] ... @key[end]; @key[begin] ... @key[end] IO_Package; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the example:} In the example above, an outside subprogram making use of IO_Package may obtain a file name by calling Open and later use it in calls to Read and Write. Thus, outside the package, a file name obtained from Open acts as a kind of password; its internal properties (such as containing a numeric value) are not known and no other operations (such as addition or comparison of internal names) can be performed on a file name. Most importantly, clients of the package cannot make copies of objects of type File_Name. @NoPrefix@;This example is characteristic of any case where complete control over the operations of a type is desired. Such packages serve a dual purpose. They prevent a user from making use of the internal structure of the type. They also implement the notion of an encapsulated data type where the only operations on the type are those given in the package specification. @NoPrefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The fact that the full view of File_Name is explicitly declared @key[limited] means that parameter passing @Chg{Version=[2],New=[], Old=[and function return ]}will always be by reference@Chg{Version=[2],New=[ and function results will always be built directly in the result object],Old=[]} (see @RefSecNum{Formal Parameter Modes} and @RefSecNum{Return Statements}). @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The restrictions in RM83-7.4.4(4), which disallowed @key[out] parameters of limited types in certain cases, are removed. @end{Extend83} @begin{DiffWord83} Since limitedness and privateness are orthogonal in Ada 95 (and to some extent in Ada 83), this is now its own clause rather than being a subclause of @RefSec{Private Types and Private Extensions}. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Limited types now have an assignment operation, but its use is restricted such that all uses are build-in-place. This is accomplished by restricting uses to @nt{aggregate}s and @nt{function_call}s. @nt{Aggregate}s were not allowed to have a limited type in Ada 95, which causes a compatibility issue discussed in @RefSec{Aggregates}. Compatibility issues with return statements for limited @nt{function_call}s are discussed in @RefSec{Return Statements}.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00411-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Rewrote the definition of limited to ensure that interfaces are covered, but that limitedness is not inherited from interfaces. Derived types that explicitly include @key{limited} are now also covered.]} @end{DiffWord95} @LabeledClause{User-Defined Assignment and Finalization} @begin{Intro} @redundant[@Defn{user-defined assignment} @Defn2{Term=[assignment], Sec=(user-defined)} Three kinds of actions are fundamental to the manipulation of objects: initialization, finalization, and assignment. Every object is initialized, either explicitly or by default, after being created (for example, by an @nt{object_declaration} or @nt{allocator}). Every object is finalized before being destroyed (for example, by leaving a @nt{subprogram_body} containing an @nt{object_declaration}, or by a call to an instance of Unchecked_Deallocation). An assignment operation is used as part of @nt{assignment_statement}s, explicit initialization, parameter passing, and other operations. @IndexSee{Term=[constructor],See=[initialization]} @IndexSee{Term=[constructor],See=[Initialize]} @IndexSee{Term=[destructor],See=[finalization]} Default definitions for these three fundamental operations are provided by the language, but @Defn{controlled type} a @i{controlled} type gives the user additional control over parts of these operations. @Defn{Initialize}@Defn{Finalize}@Defn{Adjust} In particular, the user can define, for a controlled type, an Initialize procedure which is invoked immediately after the normal default initialization of a controlled object, a Finalize procedure which is invoked immediately before finalization of any of the components of a controlled object, and an Adjust procedure which is invoked as the last step of an assignment to a (nonlimited) controlled object.] @ToGlossary{Term=<Controlled type>, Text=<A controlled type supports user-defined assignment and finalization. Objects are always finalized before being destroyed.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01],ARef=[AI95-00287-01]} Here's the basic idea of initialization, value adjustment, and finalization, whether or not user defined: When an object is created, if it is explicitly assigned an initial value, @Chg{Version=[2],New=[the object is either built-in-place from an @nt{aggregate} or function call (in which case neither Adjust nor Initialize is applied), or ],Old=[]} the assignment copies and adjusts the initial value. Otherwise, Initialize is applied to it (except in the case of an @nt{aggregate} as a whole). An @nt{assignment_statement} finalizes the target before copying in and adjusting the new value. Whenever an object goes away, it is finalized. Calls on Initialize and Adjust happen bottom-up; that is, components first, followed by the containing object. Calls on Finalize @Chg{Version=[2],New=[happen],Old=[happens]} top-down; that is, first the containing object, and then its components. These ordering rules ensure that any components will be in a well-defined state when Initialize, Adjust, or Finalize is applied to the containing object. @end{Ramification} @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{Example}@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @key[package] Ada.Finalization @key[is]@ChildUnit{Parent=[Ada],Child=[Finalization]} @key[pragma] Preelaborate(Finalization);@Chg{New=[ @key[pragma] Remote_Types(Finalization);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Controlled} @key[is abstract tagged private];@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Controlled);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @key(procedure) @AdaSubDefn{Initialize} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Adjust} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Finalize} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Limited_Controlled} @key[is abstract tagged limited private];@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Limited_Controlled);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @key(procedure) @AdaSubDefn{Initialize} (Object : @key(in out) Limited_Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Finalize} (Object : @key(in out) Limited_Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(private) ... -- @RI{not specified by the language} @key[end] Ada.Finalization; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Defn{controlled type} A controlled type is a descendant of Controlled or Limited_Controlled. @Chg{Version=[2],New=[],Old=[The (default) implementations of Initialize, Adjust, and Finalize have no effect. ]}The predefined "=" operator of type Controlled always returns True, @Redundant[since this operator is incorporated into the implementation of the predefined equality operator of types derived from Controlled, as explained in @RefSecNum(Relational Operators and Membership Tests).] The type Limited_Controlled is like Controlled, except that it is limited and it lacks the primitive subprogram Adjust. @begin{Discussion} We say @lquotes@;nonlimited controlled type@rquotes@ (rather than just @lquotes@;controlled type@rquotes@;; when we want to talk about descendants of Controlled only. @end{Discussion} @begin{Reason} We considered making Adjust and Finalize abstract. However, a reasonable coding convention is e.g. for Finalize to always call the parent's Finalize after doing whatever work is needed for the extension part. (Unlike CLOS, we have no way to do that automatically in Ada 95.) For this to work, Finalize cannot be abstract. In a generic unit, for a generic formal abstract derived type whose ancestor is Controlled or Limited_Controlled, calling the ancestor's Finalize would be illegal if it were abstract, even though the actual type might have a concrete version. Types Controlled and Limited_Controlled are abstract, even though they have no abstract primitive subprograms. It is not clear that they need to be abstract, but there seems to be no harm in it, and it might make an implementation's life easier to know that there are no objects of these types @em in case the implementation wishes to make them @lquotes@;magic@rquotes@; in some way. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[For Ada 2005, we considered making these types interfaces. That would have the advantage of allowing them to be added to existing trees. But that was rejected both because it would cause massive disruption to existing implementations, and because it would be very incompatible due to the "no hidden interfaces" rule. The latter rule would prevent a tagged private type from being completed with a derivation from Controlled or Limited_Controlled @em a very common idiom.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A type is said to @i{need finalization} if:@Defn{needs finalization}@Defn2{Term=[type],Sec=[needs finalization]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is a controlled type, a task type or a protected type; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it has a component that needs finalization; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is a limited type that has an access discriminant whose designated type needs finalization; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is one of a number of language-defined types that are explicitly defined to need finalization.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The fact that a type needs finalization does not require it to be implemented with a controlled type. It just has to be recognized by the No_Nested_Finalization restriction.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This property is defined for the type, not for a particular view. That's necessary as restrictions look in private parts to enforce their restrictions; the point is to eliminate all controlled parts, not just ones that are visible.]} @end{Ramification} @end{Itemize} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @Chg{Version=[2],New=[],Old=[@PDefn2{Term=[elaboration], Sec=(object_declaration)}]}During the elaboration @Chg{Version=[2],New=[or evaluation of a construct that causes an object to be initialized by default],Old=[of an @nt{object_declaration}]}, for every controlled subcomponent of the object that is not assigned an initial value (as defined in @RefSecNum{Object Declarations}), Initialize is called on that subcomponent. Similarly, if the object @Chg{Version=[2],New=[that is initialized by default ],Old=[]}as a whole is controlled@Chg{Version=[2],New=[],Old=[ and is not assigned an initial value]}, Initialize is called on the object.@Chg{Version=[2], New=[],Old=[ The same applies to the evaluation of an @nt{allocator}, as explained in @RefSecNum{Allocators}.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} For an @nt{extension_aggregate} whose @nt{ancestor_part} is a @nt{subtype_mark}@Chg{Version=[2],New=[ denoting a], Old=[, @Chg{New=[for each controlled subcomponent of the ancestor part, either Initialize is called, or its initial value is assigned, as appropriate], Old=[Initialize is called on all controlled subcomponents of the ancestor part]}; if the type of the ancestor part is itself]} controlled@Chg{Version=[2],New=[ subtype],Old=[]}, the Initialize procedure of the ancestor type is called, unless that Initialize procedure is abstract. @begin{Discussion} @leading@keepnext@;Example: @begin{Example} @key[type] T1 @key[is] @key[new] Controlled @key[with] @key[record] ... --@RI{ some components might have defaults} @key[end] @key[record]; @key[type] T2 @key[is] @key[new] Controlled @key[with] @key[record] X : T1; --@RI{ no default} Y : T1 := ...; --@RI{ default} @key[end] @key[record]; A : T2; B : T2 := ...; @end{Example} As part of the elaboration of A's declaration, A.Y is assigned a value; therefore Initialize is not applied to A.Y. Instead, Adjust is applied to A.Y as part of the assignment operation. Initialize is applied to A.X and to A, since those objects are not assigned an initial value. The assignment to A.Y is not considered an assignment to A. For the elaboration of B's declaration, Initialize is not called at all. Instead the assignment adjusts B's value; that is, it applies Adjust to B.X, B.Y, and B. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00373-01]} @ChgAdded{Version=[1],Text=[The @nt{ancestor_part} of an @nt{extension_aggregate}@Chg{Version=[2],New=[, <> in aggregates, and the return object of an @nt{extended_return_statement} are],Old=[ is]} handled similarly.]} @end{Discussion} Initialize and other initialization operations are done in an arbitrary order, except as follows. Initialize is applied to an object after initialization of its subcomponents, if any @Redundant[(including both implicit initialization and Initialize calls)]. If an object has a component with an access discriminant constrained by a per-object expression, Initialize is applied to this component after any components that do not have such discriminants. For an object with several components with such a discriminant, Initialize is applied to them in order of their @nt{component_declaration}s. For an @nt<allocator>, any task activations follow all calls on Initialize. @begin{Reason} The fact that Initialize is done for subcomponents first allows Initialize for a composite object to refer to its subcomponents knowing they have been properly initialized. The fact that Initialize is done for components with access discriminants after other components allows the Initialize operation for a component with a self-referential access discriminant to assume that other components of the enclosing object have already been properly initialized. For multiple such components, it allows some predictability. @end{Reason} @leading@keepnext@Defn{assignment operation} When a target object with any controlled parts is assigned a value, @Redundant[either when created or in a subsequent @nt{assignment_statement},] the @i{assignment operation} proceeds as follows: @begin(itemize) The value of the target becomes the assigned value. @Defn{adjusting the value of an object} @Defn{adjustment} The value of the target is @i{adjusted.} @end(itemize) @begin{Ramification} If any parts of the object are controlled, abort is deferred during the assignment operation. @end{Ramification} @Defn{adjusting the value of an object} @Defn{adjustment} To adjust the value of a @Redundant[(nonlimited)] composite object, the values of the components of the object are first adjusted in an arbitrary order, and then, if the object is controlled, Adjust is called. Adjusting the value of an elementary object has no effect@Redundant[, nor does adjusting the value of a composite object with no controlled parts.] @begin{Ramification} Adjustment is never performed for values of a by-reference limited type, since these types do not support copying. @end{Ramification} @begin{Reason} The verbiage in the Initialize rule about access discriminants constrained by per-object expressions is not necessary here, since such types are limited, and therefore are never adjusted. @end{Reason} @PDefn2{Term=[execution], Sec=(assignment_statement)} For an @nt{assignment_statement}, @Redundant[ after the @nt{name} and @nt{expression} have been evaluated, and any conversion (including constraint checking) has been done,] an anonymous object is created, and the value is assigned into it; @Redundant[that is, the assignment operation is applied]. @Redundant[(Assignment includes value adjustment.)] The target of the @nt{assignment_statement} is then finalized. The value of the anonymous object is then assigned into the target of the @nt{assignment_statement}. Finally, the anonymous object is finalized. @Redundant[As explained below, the implementation may eliminate the intermediate anonymous object, so this description subsumes the one given in @RefSec{Assignment Statements}.] @begin{Reason} @leading@;An alternative design for user-defined assignment might involve an Assign operation instead of Adjust: @begin{Example} @key[procedure] Assign(Target : @key[in] @key[out] Controlled; Source : @key[in] @key[out] Controlled); @end{Example} @leading@keepnext@;Or perhaps even a syntax like this: @begin{Example} @key[procedure] ":="(Target : @key[in] @key[out] Controlled; Source : @key[in] @key[out] Controlled); @end{Example} @leading@;Assign (or ":=") would have the responsibility of doing the copy, as well as whatever else is necessary. This would have the advantage that the Assign operation knows about both the target and the source at the same time @em it would be possible to do things like reuse storage belonging to the target, for example, which Adjust cannot do. However, this sort of design would not work in the case of unconstrained discriminated variables, because there is no way to change the discriminants individually. For example: @begin{Example} @key[type] Mutable(D : Integer := 0) @key[is] @key[record] X : Array_Of_Controlled_Things(1..D); @key[case] D @key[is] @key[when] 17 => Y : Controlled_Thing; @key[when] @key[others] => @key[null]; @key[end] D; @key[end] @key[record]; @end{Example} An assignment to an unconstrained variable of type Mutable can cause some of the components of X, and the component Y, to appear and/or disappear. There is no way to write the Assign operation to handle this sort of case. Forbidding such cases is not an option @em it would cause generic contract model violations. @end{Reason} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0022],ARef=[AI95-00083-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00318-02]} @ChgAdded{Version=[1],Text=[For an @nt{aggregate} of a controlled type whose value is assigned, other than by an @nt{assignment_statement}@Chg{Version=[2],New=[],Old=[ or a @nt{return_statement}]}, the implementation shall not create a separate anonymous object for the @nt{aggregate}. The aggregate value shall be constructed directly in the target of the assignment operation and Adjust is not called on the target object.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00318-02]} @ChgAdded{Version=[1],Type=[Leading],Text=[@Chg{Version=[2], New=[@PDefn{build-in-place}],Old=[]}This@Chg{Version=[2], New=[ @i<build-in-place> requirement],Old=[]} is necessary to prevent elaboration problems with deferred constants of controlled types. Consider:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] P @key[is] @key[type] Dyn_String @key[is private]; Null_String : @key[constant] Dyn_String; ... @key[private] @key[type] Dyn_String @key[is new] Ada.Finalization.Controlled @key[with] ... @key[procedure] Finalize(X : @key[in out] Dyn_String); @key[procedure] Adjust(X : @key[in out] Dyn_String); @comment{Blank Line} Null_String : @key[constant] Dyn_String := (Ada.Finalization.Controlled @key[with] ...); ... @key[end] P;],Old=[]} @end{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[When Null_String is elaborated, the bodies of Finalize and Adjust clearly have not been elaborated. Without this rule, this declaration would necessarily raise Program_Error (unless the permissions given below are used by the implementation).],Old=[]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{aggregate} used in the return expression of a @nt{simple_@!return_@!statement} has to be built-in-place in the anonymous return object, as this is similar to an object declaration. (This is a change from Ada 95, but it is not an inconsistency as it only serves to restrict implementation choices.) But this only covers the @nt{aggregate}; a separate anonymous return object can still be used unless it too is required to be built-in-place (see @RefSecNum{Limited Types}).]} @end{Ramification} @end{ImplReq} @begin{ImplPerm} An implementation is allowed to relax the above rules @Redundant[(for nonlimited controlled types)] in the following ways: @begin{TheProof} The phrase @lquotes@;for nonlimited controlled types@rquotes@; follows from the fact that all of the following permissions apply to cases involving assignment. It is important because the programmer can count on a stricter semantics for limited controlled types. @end{TheProof} @begin{Itemize} For an @nt{assignment_statement} that assigns to an object the value of that same object, the implementation need not do anything. @begin{Ramification} In other words, even if an object is controlled and a combination of Finalize and Adjust on the object might have a net side effect, they need not be performed. @end{Ramification} For an @nt{assignment_statement} for a noncontrolled type, the implementation may finalize and assign each component of the variable separately (rather than finalizing the entire variable and assigning the entire new value) unless a discriminant of the variable is changed by the assignment. @begin{Reason} For example, in a slice assignment, an anonymous object is not necessary if the slice is copied component-by-component in the right direction, since array types are not controlled (although their components may be). Note that the direction, and even the fact that it's a slice assignment, can in general be determined only at run time. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00147-01]} For an @nt{aggregate} or function call whose value is assigned into a target object, the implementation need not create a separate anonymous object if it can safely create the value of the @nt{aggregate} or function call directly in the target object. Similarly, for an @nt{assignment_@!statement}, the implementation need not create an anonymous object if the value being assigned is the result of evaluating a @nt{name} denoting an object (the source object) whose storage cannot overlap with the target. If the source object might overlap with the target object, then the implementation can avoid the need for an intermediary anonymous object by exercising one of the above permissions and perform the assignment one component at a time (for an overlapping array assignment), or not at all (for an assignment where the target and the source of the assignment are the same object).@Chg{Version=[2],New=[],Old=[ Even if an anonymous object is created, the implementation may move its value to the target object as part of the assignment without re-adjusting so long as the anonymous object has no aliased subcomponents.]} @begin{Ramification} In the @nt{aggregate} case, only one value adjustment is necessary, and there is no anonymous object to be finalized. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00147-01]} @Chg{Version=[2],New=[Similarly, in the function call case, the anonymous object can be eliminated. Note, however, that Adjust must be called],Old=[In the @nt{assignment_statement} case as well, no finalization of the anonymous object is needed. On the other hand, if the target has aliased subcomponents, then an adjustment takes place]} directly on the target object as the last step of the assignment, since some of the subcomponents may be self-referential or otherwise position-dependent.@Chg{Version=[2],New=[ This Adjust can be eliminated only by using one of the following permissions.],Old=[]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00147-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Furthermore, an implementation is permitted to omit implicit Initialize, Adjust, and Finalize calls and associated assignment operations on an object of a nonlimited controlled type provided that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[any omitted Initialize call is not a call on a user-defined Initialize procedure, and]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This does not apply to any calls to a user-defined Initialize routine that happen to occur in an Adjust or Finalize routine. It is intended that it is never necessary to look inside of an Adjust or Finalize routine to determine if the call can be omitted.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't want to eliminate objects for which the Initialize might have side effects (such as locking a resource).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[any usage of the value of the object after the implicit Initialize or Adjust call and before any subsequent Finalize call on the object does not change the external effect of the program, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[after the omission of such calls and operations, any execution of the program that executes an Initialize or Adjust call on an object or initializes an object by an @nt{aggregate} will also later execute a Finalize call on the object and will always do so prior to assigning a new value to the object, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the assignment operations associated with omitted Adjust calls are also omitted.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This permission applies to Adjust and Finalize calls even if the implicit calls have additional external effects.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The goal of the above permissions is to allow typical dead assignment and dead variable removal algorithms to work for nonlimited controlled types. We require that @lquotes@;pairs@rquotes@; of Initialize/Adjust/Finalize operations are removed. (These aren't always pairs, which is why we talk about @lquotes@;any execution of the program@rquotes@;.)]} @end{Reason} @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} Controlled types and user-defined finalization are new to Ada 95. (Ada 83 had finalization semantics only for masters of tasks.) @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Types Controlled and Limited_Controlled now have Preelaborable_Initialization, so that objects of types derived from these types can be used in preelaborated packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Ada.Finalization is a remote types package.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to clarify that the default initialization (whatever it is) of an ancestor part is used.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0022],ARef=[AI95-00083-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Adjust is never called on an aggregate used for the initialization of an object or subaggregate, or passed as a parameter.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00147-01]} @ChgAdded{Version=[2],Text=[Additional optimizations are allowed for nonlimited controlled types. These allow traditional dead variable elimination to be applied to such types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Corrected the build-in-place requirement for controlled @nt{aggregate}s to be consistent with the requirements for limited types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[The operations of types Controlled and Limited_Controlled are now declared as null procedures (see @RefSecNum{Null Procedures}) to make the semantics clear (and to provide a good example of what null procedures can be used for).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[Types that need finalization are defined; this is used by the No_Nested_Finalization restriction (see @RefSec{Tasking Restrictions}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Generalized the description of objects that have Initialize called for them to say that it is done for all objects that are initialized by default. This is needed so that all of the new cases are covered.]} @end{DiffWord95} @LabeledSubClause{Completion and Finalization} @begin{Intro} @redundant[This subclause defines @i{completion} and @i{leaving} of the execution of constructs and entities. A @i{master} is the execution of a construct that includes finalization of local objects after it is complete (and after waiting for any local tasks @em see @RefSecNum(Task Dependence - Termination of Tasks)), but before leaving. Other constructs and entities are left immediately upon completion. @IndexSee{Term=[cleanup],See=(finalization)} @IndexSee{Term=[destructor],See=(finalization)}] @end{Intro} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{completion and leaving (completed and left)} @Defn2{Term=[completion], Sec=(run-time concept)} The execution of a construct or entity is @i{complete} when the end of that execution has been reached, or when a transfer of control (see @RefSecNum{Simple and Compound Statements - Sequences of Statements}) causes it to be abandoned. @Defn{normal completion} @Defn2{Term=[completion], Sec=(normal)} @Defn{abnormal completion} @Defn2{Term=[completion], Sec=(abnormal)} Completion due to reaching the end of execution, or due to the transfer of control of an @Chg{Version=[2], New=[@nt{exit_statement}, return statement, @nt{goto_statement}], Old=[@ntf{exit_}, @ntf{return_}, @ntf{goto_}]}, or @nt{requeue_statement} or of the selection of a @nt{terminate_alternative} is @i{normal completion}. Completion is @i{abnormal} otherwise @Redundant[@em when control is transferred out of a construct due to abort or the raising of an exception]. @begin{Discussion} Don't confuse the run-time concept of completion with the compile-time concept of completion defined in @RefSecNum{Completions of Declarations}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @Defn{leaving} @Defn{left} After execution of a construct or entity is complete, it is @i{left}, meaning that execution continues with the next action, as defined for the execution that is taking place. @Defn{master} Leaving an execution happens immediately after its completion, except in the case of a @i{master}: the execution of a @Chg{Version=[2],New=[body other than a @nt{package_body}; the execution of a @nt{statement}; or the evaluation of an @nt{expression}, @nt{function_call}, or @nt{range} that is not part of an enclosing @nt{expression}, @nt{function_call}, @nt{range}, or @nt{simple_@!statement} other than a @nt{simple_@!return_@!statement}], Old=[@nt{task_body}, a @nt{block_@!statement}, a @nt{subprogram_body}, an @nt{entry_body}, or an @nt{accept_@!statement}]}. A master is finalized after it is complete, and before it is left. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[@nt{Expression}s and @nt{statement}s are masters so that objects created by subprogram calls (in @nt{aggregate}s, @nt{allocator}s for anonymous access-to-object types, and so on) are finalized and have their tasks awaited before the @nt{expression}s or @nt{statement}s are left. Note that @nt{expression}s like the @nt{condition} of an @nt{if_statement} are masters, because they are not enclosed by a @nt{simple_statement}. Similarly, a @nt{function_call} which is renamed is a master, as it is not in a @nt{simple_@!statement}.], Old=[Note that although an @nt{accept_statement} has no @nt{declarative_part}, it can call functions and evaluate @nt{aggregate}s, possibly causing anonymous controlled objects to be created, and we don't want those objects to escape outside the rendezvous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[We have to include @nt{function_call}s in the contexts that do not cause masters to occur so that @nt{expression}s contained in a @nt{function_call} (that is not part of an @nt{expression} or @nt{simple_statement}) do not individually become masters. We certainly do not want the parameter @nt{expression}s of a @nt{function_call} to be separate masters, as they would then be finalized before the function is called.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The fact that a @nt{function_call} is a master does not change the accessibility of the return object denoted by the @nt{function_call}; that depends on the use of the @nt{function_call}. The @nt{function_call} is the master of any short-lived entities (such as @nt{aggregate}s used as parameters of types with task or controlled parts).]} @end{Ramification} @Defn2{Term=[finalization], Sec=(of a master)} For the @i{finalization} of a master, dependent tasks are first awaited, as explained in @RefSecNum{Task Dependence - Termination of Tasks}. Then each object whose accessibility level is the same as that of the master is finalized if the object was successfully initialized and still exists. @Redundant[These actions are performed whether the master is left by reaching the last statement or via a transfer of control.] When a transfer of control causes completion of an execution, each included master is finalized in order, from innermost outward. @begin{Ramification} As explained in @RefSecNum{Operations of Access Types}, the set of objects with the same accessibility level as that of the master includes objects declared immediately within the master, objects declared in nested packages, objects created by @nt{allocator}s (if the ultimate ancestor access type is declared in one of those places) and subcomponents of all of these things. If an object was already finalized by Unchecked_Deallocation, then it is not finalized again when the master is left. Note that any object whose accessibility level is deeper than that of the master would no longer exist; those objects would have been finalized by some inner master. Thus, after leaving a master, the only objects yet to be finalized are those whose accessibility level is less deep than that of the master. @end{Ramification} @begin{Honest} Subcomponents of objects due to be finalized are not finalized by the finalization of the master; they are finalized by the finalization of the containing object. @end{Honest} @begin{Reason} We need to finalize subcomponents of objects even if the containing object is not going to get finalized because it was not fully initialized. But if the containing object is finalized, we don't want to require repeated finalization of the subcomponents, as might normally be implied by the recursion in finalization of a master and the recursion in finalization of an object. @end{Reason} @begin{Honest} Formally, completion and leaving refer to executions of constructs or entities. However, the standard sometimes (informally) refers to the constructs or entities whose executions are being completed. Thus, for example, @lquotes@;the subprogram call or task is complete@rquotes@; really means @lquotes@;@i{the execution of} the subprogram call or task is complete.@rquotes@; @end{Honest} @leading@keepnext@RootDefn2{Term=[finalization], Sec=(of an object)} For the @i{finalization} of an object: @begin{Itemize} If the object is of an elementary type, finalization has no effect; If the object is of a controlled type, the Finalize procedure is called; If the object is of a protected type, the actions defined in @RefSecNum{Protected Units and Protected Objects} are performed; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} If the object is of a composite type, then after performing the above actions, if any, every component of the object is finalized in an arbitrary order, except as follows: if the object has a component with an access discriminant constrained by a per-object expression, this component is finalized before any components that do not have such discriminants; for an object with several components with such a discriminant, they are finalized in the reverse of the order of their @nt<component_declaration>s@Chg{Version=[2],New=[;],Old=[.]} @begin{Reason} This allows the finalization of a component with an access discriminant to refer to other components of the enclosing object prior to their being finalized. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the object has coextensions (see @RefSecNum{Operations of Access Types}), each coextension is finalized after the object whose access discriminant designates it.]} @end{Itemize} @PDefn2{Term=[execution], Sec=(instance of Unchecked_Deallocation)} Immediately before an instance of Unchecked_Deallocation reclaims the storage of an object, the object is finalized. @Redundant[If an instance of Unchecked_Deallocation is never applied to an object created by an @nt{allocator}, the object will still exist when the corresponding master completes, and it will be finalized then.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00280-01]} The order in which the finalization of a master performs finalization of objects is as follows: Objects created by declarations in the master are finalized in the reverse order of their creation. For objects that were created by @nt{allocator}s for an access type whose ultimate ancestor is declared in the master, this rule is applied as though each such object that still exists had been created in an arbitrary order at the first freezing point (see @RefSecNum{Freezing Rules}) of the ultimate ancestor type@Chg{Version=[2],New=[; the finalization of these objects is called the @i<finalization of the collection>@Defn{finalization of the collection}@Defn2{Term=[collection], Sec=[finalization of]}],Old=[]}.@Chg{Version=[2], New=[ After the finalization of a master is complete, the objects finalized as part of its finalization cease to @i<exist>, as do any types and subtypes defined and created within the master.@PDefn2{Term=[exist],Sec=[cease to]} @PDefn2{Term=[cease to exist],Sec=[object]} @Defn2{Term=[cease to exist],Sec=[type]}],Old=[]} @begin{Reason} Note that we talk about the type of the @nt{allocator} here. There may be access values of a (general) access type pointing at objects created by @nt{allocator}s for some other type; these are not finalized at this point. The freezing point of the ultimate ancestor access type is chosen because before that point, pool elements cannot be created, and after that point, access values designating (parts of) the pool elements can be created. This is also the point after which the pool object cannot have been declared. We don't want to finalize the pool elements until after anything finalizing objects that contain access values designating them. Nor do we want to finalize pool elements after finalizing the pool object itself. @end{Reason} @begin{Ramification} Finalization of allocated objects is done according to the (ultimate ancestor) @nt{allocator} type, not according to the storage pool in which they are allocated. Pool finalization might reclaim storage (see @RefSec{Storage Management}), but has nothing (directly) to do with finalization of the pool elements. Note that finalization is done only for objects that still exist; if an instance of Unchecked_Deallocation has already gotten rid of a given pool element, that pool element will not be finalized when the master is left. Note that a deferred constant declaration does not create the constant; the full constant declaration creates it. Therefore, the order of finalization depends on where the full constant declaration occurs, not the deferred constant declaration. An imported object is not created by its declaration. It is neither initialized nor finalized. @end{Ramification} @begin{ImplNote} An implementation has to ensure that the storage for an object is not reclaimed when references to the object are still possible (unless, of course, the user explicitly requests reclamation via an instance of Unchecked_Deallocation). This implies, in general, that objects cannot be deallocated one by one as they are finalized; a subsequent finalization might reference an object that has been finalized, and that object had better be in its (well-defined) finalized state. @end{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @PDefn2{Term=[execution], Sec=(assignment_statement)} The target of an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment statement]} is finalized before copying in the new value, as explained in @RefSecNum{User-Defined Assignment and Finalization}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @Chg{Version=[2],New=[The master of an object is the master enclosing its creation whose accessibility level (see @RefSecNum{Operations of Access Types}) is equal to that of the object.], Old=[@Chg{New=[If the @i{object_}@nt{name} in an @nt{object_renaming_declaration}, or the actual parameter for a generic formal @key[in out] parameter in a @nt{generic_instantiation}, denotes any part of an anonymous object created by a function call, the anonymous object is not finalized until after it is no longer accessible via any name. Otherwise, an], Old=[The]} anonymous object@Chg{New=[],Old=[s]} created by @Chg{New=[a ],Old=[]}function @Chg{New=[call or],Old=[calls and]} by @Chg{New=[an ],Old=[]}@nt{aggregate}@Chg{New=[ is],Old=[s are]} finalized no later than the end of the innermost enclosing @nt{declarative_item} or @nt{statement}; if that is a @nt{compound_statement}, @Chg{New=[the object is],Old=[they are]} finalized before starting the execution of any @nt{statement} within the @nt{compound_statement}.]} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00162-01]}@ChgNote{Should be ChgDeleted} @ChgDeleted{Version=[2],Text=[@leading@;This is not to be construed as permission to call Finalize asynchronously with respect to normal user code. For example,]} @begin{Example} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[@key[declare] X : Some_Controlled_Type := F(G(...)); --@RI{ The anonymous objects created for F and G are finalized} --@RI{ no later than this point.} Y : ... @key[begin] ... @key[end];]} @end{Example} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[ The anonymous object for G should not be finalized at some random point in the middle of the body of F, because F might manipulate the same data structures as the Finalize operation, resulting in erroneous access to shared variables.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @Chg{Version=[2],New=[This effectively imports all of the special rules for the accessibility level of renames, @nt{allocator}s, and so on, and applies them to determine where objects created in them are finalized. For instance, the master of a rename of a subprogram is that of the renamed subprogram.], Old=[It might be quite inconvenient for the implementation to defer finalization of the anonymous object for G until after copying the value of F into X, especially if the size of the result is not known at the call site.]} @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00162-01]} @Chg{Version=[2],New=[In the case of an @nt{expression} that is a master, finalization of any (anonymous) objects occurs as the final part of evaluation of the @nt{expression}.], Old=[@Chg{New=[If a transfer of control or raising of an exception occurs prior to performing a finalization of an anonymous object, the anonymous object is finalized as part of the finalizations due to be performed for the object's innermost enclosing master.],Old=[]}]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0023],ARef=[AI95-00169-01]} @leading@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for a call on Finalize or Adjust @Chg{New=[that occurs as part of object finalization or assignment ], Old=[]}to propagate an exception. The possible consequences depend on what action invoked the Finalize or Adjust operation: @begin{Ramification} It is not a bounded error for Initialize to propagate an exception. If Initialize propagates an exception, then no further calls on Initialize are performed, and those components that have already been initialized (either explicitly or by default) are finalized in the usual way. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @Chg{New=[It also is not a bounded error for an explicit call to Finalize or Adjust to propagate an exception. We do not want implementations to have to treat explicit calls to these routines specially.],Old=[]} @end{Ramification} @begin{Itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of an @nt<assignment_statement>, Program_Error is raised at that point. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @Chg{New=[For an Adjust invoked as part of @Chg{Version=[2],New=[assignment operations other than those invoked as part of an @nt{assignment_statement}], Old=[the initialization of a controlled object]}, other adjustments due to be performed might or might not be performed, and then Program_Error is raised. During its propagation, finalization might or might not be applied to objects whose Adjust failed.],Old=[]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For an Adjust invoked as part of an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment @Chg{New=[statement],Old=[operation]}]}, any other adjustments due to be performed are performed, and then Program_Error is raised. @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[In the case of assignments that are part of initialization, there is no need to complete all adjustments if one propagates an exception, as the object will immediately be finalized. So long as a subcomponent is not going to be finalized, it need not be adjusted, even if it is initialized as part of an enclosing composite assignment operation for which some adjustments are performed. However, there is no harm in an implementation making additional Adjust calls (as long as any additional components that are adjusted are also finalized), so we allow the implementation flexibility here. On the other hand, for an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment statement]}, it is important that all adjustments be performed, even if one fails, because all controlled subcomponents are going to be finalized.@Chg{Version=[2],New=[ Other kinds of assignment are more like initialization than @nt{assignment_statement}s, so we include them as well in the permission.],Old=[]}]} @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgAdded{Version=[1],Text=[Even if an Adjust invoked as part of the initialization of a controlled object propagates an exception, objects whose initialization (including any Adjust or Initialize calls) successfully completed will be finalized. The permission above only applies to objects whose Adjust failed. Objects for which Adjust was never even invoked must not be finalized.]} @end{Ramification} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of a call on an instance of Unchecked_Deallocation, any other finalizations due to be performed are performed, and then Program_Error is raised. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0104],ARef=[AI95-00179-01]} @ChgAdded{Version=[1],Text=[The standard does not specify if storage is recovered in this case. If storage is not recovered (and the object continues to exist), Finalize may be called on the object again (when the @nt<allocator>'s master is finalized).]} @end{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @Chg{New=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of the finalization of the anonymous object created by a function call or @nt{aggregate}, any other finalizations due to be performed are performed, and then Program_Error is raised.],Old=[]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @Chg{New=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked due to reaching the end of the execution of a master, any other finalizations associated with the master are performed, and Program_Error is raised immediately after leaving the master.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked by the transfer of control of an @Chg{Version=[2], New=[@nt{exit_statement}, return statement, @nt{goto_statement}], Old=[@ntf{exit_}, @ntf{return_}, @ntf{goto_}]}, or @nt{requeue_@!statement}, Program_Error is raised no earlier than after the finalization of the master being finalized when the exception occurred, and no later than the point where normal execution would have continued. Any other finalizations due to be performed up to that point are performed before raising Program_Error. @begin{Ramification} For example, upon leaving a @nt{block_statement} due to a @nt{goto_statement}, the Program_Error would be raised at the point of the target statement denoted by the label, or else in some more dynamically nested place, but not so nested as to allow an @nt{exception_handler} that has visibility upon the finalized object to handle it. For example, @begin{Example} @key[procedure] Main @key[is] @key[begin] <<The_Label>> Outer_Block_Statement : @key[declare] X : Some_Controlled_Type; @key[begin] Inner_Block_Statement : @key[declare] Y : Some_Controlled_Type; Z : Some_Controlled_Type; @key[begin] @key[goto] The_Label; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 1.} @key[end]; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 2.} @key[end]; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 3.} @key[end] Main; @end{Example} The @nt{goto_statement} will first cause Finalize(Y) to be called. Suppose that Finalize(Y) propagates an exception. Program_Error will be raised after leaving Inner_Block_Statement, but before leaving Main. Thus, handler number 1 cannot handle this Program_Error; it will be handled either by handler number 2 or handler number 3. If it is handled by handler number 2, then Finalize(Z) will be done before executing the handler. If it is handled by handler number 3, then Finalize(Z) and Finalize(X) will both be done before executing the handler. @end{Ramification} For a Finalize invoked by a transfer of control that is due to raising an exception, any other finalizations due to be performed for the same master are performed; Program_Error is raised immediately after leaving the master. @begin{Ramification} If, in the above example, the @nt{goto_statement} were replaced by a @nt{raise_statement}, then the Program_Error would be handled by handler number 2, and Finalize(Z) would be done before executing the handler. @end{Ramification} @begin{Reason} We considered treating this case in the same way as the others, but that would render certain @nt{exception_handler}s useless. For example, suppose the only @nt{exception_handler} is one for @key{others} in the main subprogram. If some deeply nested call raises an exception, causing some Finalize operation to be called, which then raises an exception, then normal execution @lquotes@;would have continued@rquotes@; at the beginning of the @nt{exception_handler}. Raising Program_Error at that point would cause that handler's code to be skipped. One would need two nested @nt{exception_handler}s to be sure of catching such cases! On the other hand, the @nt{exception_handler} for a given master should not be allowed to handle exceptions raised during finalization of that master. @end{Reason} For a Finalize invoked by a transfer of control due to an abort or selection of a terminate alternative, the exception is ignored; any other finalizations due to be performed are performed. @begin{Ramification} This case includes an asynchronous transfer of control. @end{Ramification} @begin{Honest} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This violates the general principle that it is always possible for a bounded error to raise Program_Error (see @RefSec{Classification of Errors}). @end{Honest} @end{Itemize} @end{Bounded} @begin{Notes} The rules of Section 10 imply that immediately prior to partition termination, Finalize operations are applied to library-level controlled objects (including those created by @nt{allocator}s of library-level access types, except those already finalized). This occurs after waiting for library-level tasks to terminate. @begin{Discussion} We considered defining a pragma that would apply to a controlled type that would suppress Finalize operations for library-level objects of the type upon partition termination. This would be useful for types whose finalization actions consist of simply reclaiming global heap storage, when this is already provided automatically by the environment upon program termination. @end{Discussion} A constant is only constant between its initialization and finalization. Both initialization and finalization are allowed to change the value of a constant. Abort is deferred during certain operations related to controlled types, as explained in @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}. Those rules prevent an abort from causing a controlled object to be left in an ill-defined state. The Finalize procedure is called upon finalization of a controlled object, even if Finalize was called earlier, either explicitly or as part of an assignment; hence, if a controlled type is visibly controlled (implying that its Finalize primitive is directly callable), or is nonlimited (implying that assignment is allowed), its Finalize procedure should be designed to have no ill effect if it is applied a second time to the same object. @begin{Discussion} Or equivalently, a Finalize procedure should be @lquotes@;idempotent@rquotes@;; applying it twice to the same object should be equivalent to applying it once. @end{Discussion} @begin{Reason} A user-written Finalize procedure should be idempotent since it can be called explicitly by a client (at least if the type is "visibly" controlled). Also, Finalize is used implicitly as part of the @nt<assignment_statement> if the type is nonlimited, and an abort is permitted to disrupt an @nt<assignment_statement> between finalizing the left-hand side and assigning the new value to it (an abort is not permitted to disrupt an assignment operation between copying in the new value and adjusting it). @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Either Initialize or Adjust, but not both, is applied to (almost) every controlled object when it is created: Initialize is done when no initial value is assigned to the object, whereas Adjust is done as part of assigning the initial value. The one exception is the @Chg{Version=[2],New=[],Old=[anonymous ]}object @Chg{Version=[2],New=[initialized],Old=[created]} by an @nt{aggregate}@Chg{Version=[2],New=[ (both the anonymous object created for an aggregate, or an object initialized by an @nt{aggregate} that is built-in-place)],Old=[]}; Initialize is not applied to the @nt{aggregate} as a whole, nor is the value of the @nt<aggregate> @Chg{Version=[2], New=[or object ],Old=[]}adjusted. @leading@Defn2{Term=[assignment operation], Sec=(list of uses)} All of the following use the assignment operation, and thus perform value adjustment: @begin{Itemize} the @nt{assignment_statement} (see @RefSecNum{Assignment Statements}); explicit initialization of a stand-alone object (see @RefSecNum{Object Declarations}) or of a pool element (see @RefSecNum{Allocators}); default initialization of a component of a stand-alone object or pool element (in this case, the value of each component is assigned, and therefore adjusted, but the value of the object as a whole is not adjusted); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} function return, when the result @Chg{Version=[2],New=[is not built-in-place], Old=[type is not a return-by-reference type (see @RefSecNum{Return Statements});]} (adjustment of the result happens before finalization of the function@Chg{Version=[2],New=[],Old=[; values of return-by-reference types are not adjusted]}); predefined operators (although the only one that matters is concatenation; see @RefSecNum{Binary Adding Operators}); generic formal objects of mode @key{in} (see @RefSecNum{Formal Objects}); these are defined in terms of constant declarations; and @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @nt{aggregate}s (see @RefSecNum{Aggregates})@Chg{Version=[2],New=[, when the result is not built-in-place],Old=[]} (in this case, the value of each component, and the parent part, for an @nt{extension_aggregate}, is assigned, and therefore adjusted, but the value of the @nt{aggregate} as a whole is not adjusted; neither is Initialize called); @end{Itemize} @leading@;The following also use the assignment operation, but adjustment never does anything interesting in these cases: @begin{Itemize} By-copy parameter passing uses the assignment operation (see @RefSecNum{Parameter Associations}), but controlled objects are always passed by reference, so the assignment operation never does anything interesting in this case. If we were to allow by-copy parameter passing for controlled objects, we would need to make sure that the actual is finalized before doing the copy back for [@key{in}] @key{out} parameters. The finalization of the parameter itself needs to happen after the copy back (if any), similar to the finalization of an anonymous function return object or @nt{aggregate} object. @key{For} loops use the assignment operation (see @RefSecNum{Loop Statements}), but since the type of the loop parameter is never controlled, nothing interesting happens there, either. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Objects initialized by function results and @nt{aggregate}s that are built-in-place. In this case, the assignment operation is never executed, and no adjustment takes place. While built-in-place is always allowed, it is required for some types @em see @RefSecNum{Limited Types} and @RefSecNum{User-Defined Assignment and Finalization} @em and that's important since limited types have no Adjust to call.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[Because Controlled and Limited_Controlled are library-level tagged types, all controlled types will be library-level types, because of the accessibility rules (see @RefSecNum{Operations of Access Types} and @RefSecNum{Type Extensions}). This ensures that the Finalize operations may be applied without providing any @lquotes@;display@rquotes@; or @lquotes@;static-link.@rquotes@; This simplifies finalization as a result of garbage collection, abort, and asynchronous transfer of control.]} Finalization of the parts of a protected object are not done as protected actions. It is possible (in pathological cases) to create tasks during finalization that access these parts in parallel with the finalization itself. This is an erroneous use of shared variables. @end{Discussion} @begin{ImplNote} One implementation technique for finalization is to chain the controlled objects together on a per-task list. When leaving a master, the list can be walked up to a marked place. The links needed to implement the list can be declared (privately) in types Controlled and Limited_Controlled, so they will be inherited by all controlled types. Another implementation technique, which we refer to as the @lquotes@;PC-map@rquotes@; approach essentially implies inserting exception handlers at various places, and finalizing objects based on where the exception was raised. @Defn{PC-map approach to finalization} @Defn{program-counter-map approach to finalization} The PC-map approach is for the compiler/linker to create a map of code addresses; when an exception is raised, or abort occurs, the map can be consulted to see where the task was executing, and what finalization needs to be performed. This approach was given in the Ada 83 Rationale as a possible implementation strategy for exception handling @em the map is consulted to determine which exception handler applies. If the PC-map approach is used, the implementation must take care in the case of arrays. The generated code will generally contain a loop to initialize an array. If an exception is raised part way through the array, the components that have been initialized must be finalized, and the others must not be finalized. It is our intention that both of these implementation methods should be possible. @end{ImplNote} @end{Notes} @begin{DiffWord83} Finalization depends on the concepts of completion and leaving, and on the concept of a master. Therefore, we have moved the definitions of these concepts here, from where they used to be in Section 9. These concepts also needed to be generalized somewhat. Task waiting is closely related to user-defined finalization; the rules here refer to the task-waiting rules of Section 9. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the wording to say that anonymous objects aren't finalized until the object can't be used anymore.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0023],ARef=[AI95-00169-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to clarify what happens when Adjust or Finalize raises an exception; some cases had been omitted.]} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Stated that if Adjust raises an exception during initialization, nothing further is required. This is corrected in Ada 2005 to include all kinds of assignment other than @nt{assignment_statement}s.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Revised the definition of master to include @nt{expression}s and @nt{statement}s, in order to cleanly define what happens for tasks and controlled objects created as part of a subprogram call. Having done that, all of the special wording to cover those cases is eliminated (at least until the Ada comments start rolling in).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[We define @i{finalization of the collection} here, so as to be able to conveniently refer to it in other rules (especially in @RefSec{Allocators}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Clarified that a coextension is finalized at the same time as the outer object. (This was intended for Ada 95, but since the concept did not have a name, it was overlooked.)]} @end{DiffWord95} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/08.mss���������������������������������������������������������������0000755�0001752�0001001�00000431337�12273462240�016407� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(08, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:28 $} @LabeledSection{Visibility Rules} @Comment{$Source: e:\\cvsroot/ARM/Source/08.mss,v $} @Comment{$Revision: 1.73 $} @begin{Intro} @redundant[The rules defining the scope of declarations and the rules defining which @nt{identifier}s, @nt{character_literal}s, and @nt{operator_symbol}s are visible at (or from) various places in the text of the program are described in this section. The formulation of these rules uses the notion of a declarative region. As explained in Section 3, a declaration declares a view of an entity and associates a defining name with that view. The view comprises an identification of the viewed entity, and possibly additional properties. A usage name denotes a declaration. It also denotes the view declared by that declaration, and denotes the entity of that view. Thus, two different usage names might denote two different views of the same entity; in this case they denote the same entity.] @begin{Honest} In some cases, a usage name that denotes a declaration does not denote the view declared by that declaration, nor the entity of that view, but instead denotes a view of the current instance of the entity, and denotes the current instance of the entity. This sometimes happens when the usage name occurs inside the declarative region of the declaration. @end{Honest} @end{Intro} @begin{DiffWord83} We no longer define the term @lquotes@;basic operation;@rquotes@; thus we no longer have to worry about the visibility of them. Since they were essentially always visible in Ada 83, this change has no effect. The reason for this change is that the definition in Ada 83 was confusing, and not quite correct, and we found it difficult to fix. For example, one wonders why an @nt{if_statement} was not a basic operation of type Boolean. For another example, one wonders what it meant for a basic operation to be @lquotes@;inherent in@rquotes@; something. Finally, this fixes the problem addressed by AI83-00027/07. @end{DiffWord83} @LabeledClause{Declarative Region} @begin{StaticSem} @leading@Defn2{Term=[declarative region], Sec=(of a construct)} For each of the following constructs, there is a portion of the program text called its @i{declarative region}, @Redundant[within which nested declarations can occur]: @begin(itemize) any declaration, other than that of an enumeration type, that is not a completion @Redundant[of a previous declaration]; a @nt{block_statement}; a @nt{loop_statement}; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[an @nt{extended_return_statement};]} an @nt{accept_statement}; an @nt{exception_handler}. @end(itemize) @begin{Wide} @leading@;The declarative region includes the text of the construct together with additional text determined @Redundant[(recursively)], as follows: @end{Wide} @begin{Itemize} If a declaration is included, so is its completion, if any. If the declaration of a library unit @Redundant[(including Standard @em see @RefSecNum{Compilation Units - Library Units})] is included, so are the declarations of any child units @Redundant[(and their completions, by the previous rule)]. The child declarations occur after the declaration. If a @nt{body_stub} is included, so is the corresponding @nt{subunit}. If a @nt{type_declaration} is included, then so is a corresponding @nt{record_representation_clause}, if any. @begin{Reason} This is so that the @nt{component_declaration}s can be directly visible in the @nt{record_representation_clause}. @end{Reason} @end{Itemize} The declarative region of a declaration is also called the @i{declarative region} of any view or entity declared by the declaration. @begin{Reason} The constructs that have declarative regions are the constructs that can have declarations nested inside them. Nested declarations are declared in that declarative region. The one exception is for enumeration literals; although they are nested inside an enumeration type declaration, they behave as if they were declared at the same level as the type. @end{Reason} @begin{Honest} A declarative region does not include @nt{parent_unit_name}s. @end{Honest} @begin{Ramification} A declarative region does not include @nt{context_clause}s. @end{Ramification} @Defn{occur immediately within} @Defn{immediately within} @Defn2{Term=[within],Sec=(immediately)} @Defn{immediately enclosing} @Defn2{Term=[enclosing],Sec=(immediately)} A declaration occurs @i{immediately within} a declarative region if this region is the innermost declarative region that encloses the declaration (the @i{immediately enclosing} declarative region), not counting the declarative region (if any) associated with the declaration itself. @begin{Discussion} Don't confuse the declarative region of a declaration with the declarative region in which it immediately occurs. @end{Discussion} @redundant[@Defn{local to} A declaration is @i{local} to a declarative region if the declaration occurs immediately within the declarative region.] @redundant[An entity is @i{local} to a declarative region if the entity is declared by a declaration that is local to the declarative region.] @begin{Ramification} "Occurs immediately within" and "local to" are synonyms (when referring to declarations). Thus, @lquotes@;local to@rquotes@; applies to both declarations and entities, whereas @lquotes@;occurs immediately within@rquotes@; only applies to declarations. We use this term only informally; for cases where precision is required, we use the term "occurs immediately within", since it is less likely to cause confusion. @end{Ramification} @Defn{global to} A declaration is @i{global} to a declarative region if the declaration occurs immediately within another declarative region that encloses the declarative region. An entity is @i{global} to a declarative region if the entity is declared by a declaration that is global to the declarative region. @end{StaticSem} @begin{Notes} The children of a parent library unit are inside the parent's declarative region, even though they do not occur inside the parent's declaration or body. This implies that one can use (for example) "P.Q" to refer to a child of P whose defining name is Q, and that after "@key[use] P;" Q can refer (directly) to that child. As explained above and in @RefSec{Compilation Units - Library Units}, all library units are descendants of Standard, and so are contained in the declarative region of Standard. They are @i{not} inside the declaration or body of Standard, but they @i{are} inside its declarative region. For a declarative region that comes in multiple parts, the text of the declarative region does not contain any text that might appear between the parts. Thus, when a portion of a declarative region is said to extend from one place to another in the declarative region, the portion does not contain any text that might appear between the parts of the declarative region. @begin{Discussion} It is necessary for the things that have a declarative region to include anything that contains declarations (except for enumeration type declarations). This includes any declaration that has a profile (that is, @nt{subprogram_declaration}, @nt{subprogram_body}, @nt{entry_declaration}, @nt{subprogram_renaming_declaration}, @nt{formal_subprogram_declaration}, access-to-subprogram @nt{type_declaration}), anything that has a @nt{discriminant_part} (that is, various kinds of @nt{type_declaration}), anything that has a @nt{component_list} (that is, record @nt{type_declaration} and record extension @nt{type_declaration}), and finally the declarations of task and protected units and packages. @end{Discussion} @end{Notes} @begin{DiffWord83} @leading@;It was necessary to extend Ada 83's definition of declarative region to take the following Ada 95 features into account: @begin{Itemize} Child library units. Derived types/type extensions @em we need a declarative region for inherited components and also for new components. All the kinds of types that allow discriminants. Protected units. Entries that have bodies instead of accept statements. The @nt{choice_parameter_specification} of an @nt{exception_handler}. The formal parameters of access-to-subprogram types. Renamings-as-body. @end{Itemize} Discriminated and access-to-subprogram type declarations need a declarative region. Enumeration type declarations cannot have one, because you don't have to say "Color.Red" to refer to the literal Red of Color. For other type declarations, it doesn't really matter whether or not there is an associated declarative region, so for simplicity, we give one to all types except enumeration types. We now say that an @nt{accept_statement} has its own declarative region, rather than being part of the declarative region of the @nt{entry_declaration}, so that declarative regions are properly nested regions of text, so that it makes sense to talk about "inner declarative regions," and "...extends to the end of a declarative region." Inside an @nt{accept_statement}, the @nt{name} of one of the parameters denotes the @nt{parameter_specification} of the @nt{accept_statement}, not that of the @nt{entry_declaration}. If the @nt{accept_statement} is nested within a @nt{block_statement}, these @nt{parameter_specification}s can hide declarations of the @nt{block_statement}. The semantics of such cases was unclear in RM83. @begin{Honest} Unfortunately, we have the same problem for the entry name itself @em it should denote the @nt{accept_statement}, but @nt{accept_statement}s are not declarations. They should be, and they should hide the entry from all visibility within themselves. @end{Honest} Note that we can't generalize this to @ntf{entry_bodies}, or other bodies, because the @nt{declarative_part} of a body is not supposed to contain (explicit) homographs of things in the declaration. It works for @nt{accept_statement}s only because an @nt{accept_statement} does not have a @nt{declarative_part}. To avoid confusion, we use the term @lquotes@;local to@rquotes@; only informally in Ada 95. Even RM83 used the term incorrectly (see, for example, RM83-12.3(13)). In Ada 83, (root) library units were inside Standard; it was not clear whether the declaration or body of Standard was meant. In Ada 95, they are children of Standard, and so occur immediately within Standard's declarative region, but not within either the declaration or the body. (See RM83-8.6(2) and RM83-10.1.1(5).) @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@nt{Extended_return_statement} (see @RefSecNum{Return Statements}) is added to the list of constructs that have a declarative region.]} @end{DiffWord95} @LabeledClause{Scope of Declarations} @begin{Intro} @redundant[For each declaration, the language rules define a certain portion of the program text called the @i{scope} of the declaration. The scope of a declaration is also called the scope of any view or entity declared by the declaration. Within the scope of an entity, and only there, there are places where it is legal to refer to the declared entity. These places are defined by the rules of visibility and overloading.] @end{Intro} @begin{StaticSem} @Leading@Defn2{Term=[immediate scope], Sec=(of a declaration)} The @i{immediate scope} of a declaration is a portion of the declarative region immediately enclosing the declaration. The immediate scope starts at the beginning of the declaration, except in the case of an overloadable declaration, in which case the immediate scope starts just after the place where the profile of the callable entity is determined (which is at the end of the @ntf<_specification> for the callable entity, or at the end of the @nt<generic_instantiation> if an instance). The immediate scope extends to the end of the declarative region, with the following exceptions: @begin{Reason} The reason for making overloadable declarations with profiles special is to simplify compilation: until the compiler has determined the profile, it doesn't know which other declarations are homographs of this one, so it doesn't know which ones this one should hide. Without this rule, two passes over the @ntf<_specification> or @nt<generic_instantiation> would be required to resolve names that denote things with the same name as this one. @end{Reason} @begin{Itemize} The immediate scope of a @nt{library_item} includes only its semantic dependents. @begin{Reason} Section 10 defines only a partial ordering of @nt{library_item}s. Therefore, it is a good idea to restrict the immediate scope (and the scope, defined below) to semantic dependents. @leading@;Consider also examples like this: @begin{Example} @key[package] P @key[is] @key[end] P; @key[package] P.Q @key[is] I : Integer := 0; @key[end] P.Q; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00080 - syntax error} @key[with] P; @key[package] R @key[is] @key[package] X @key[renames] P; @Chg{New=[J : Integer := ],Old=[]}X.Q.I@Chg{New=[],Old=[ := 17]}; --@RI{ Illegal!} @key[end] R; @end{Example} The scope of P.Q does not contain R. Hence, neither P.Q nor X.Q are visible within R. However, the name R.X.Q would be visible in some other library unit where both R and P.Q are visible (assuming R were made legal by removing the offending declaration). @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[This rule applies to limited views as well as @lquotes@;normal@rquotes library items. In that case, the semantic dependents are the units that have a @nt{limited_with_clause} for the limited view.]} @end{Ramification} The immediate scope of a declaration in the private part of a library unit does not include the visible part of any public descendant of that library unit. @Pdefn2{Term=[descendant],Sec=(relationship with scope)} @begin{Ramification} In other words, a declaration in the private part can be visible within the visible part, private part and body of a private child unit. On the other hand, such a declaration can be visible within only the private part and body of a public child unit. @end{Ramification} @begin{Reason} The purpose of this rule is to prevent children from giving private information to clients. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} For a public child subprogram, this means that the parent's private part is not visible in the @Chg{Version=[2],New=[profile],Old=[@nt{formal_part}s]} of the declaration and of the body. This is true even for @ntf{subprogram_bodies} that are not completions. For a public child generic unit, it means that the parent's private part is not visible in the @nt{generic_formal_part}, as well as in the first list of @nt{basic_declarative_item}s (for a generic package), or the @Chg{Version=[2],New=[(syntactic) profile],Old=[@nt{formal_part}(s)]} (for a generic subprogram). @end{Ramification} @end{Itemize} @Defn{visible part} @Redundant[The @i(visible part) of (a view of) an entity is a portion of the text of its declaration containing declarations that are visible from outside.] @RootDefn{private part} The @i{private part} of (a view of) an entity that has a visible part contains all declarations within the declaration of (the view of) the entity, except those in the visible part; @Redundant[these are not visible from outside. Visible and private parts are defined only for these kinds of entities: callable entities, other program units, and composite types.] @begin{Itemize} @PDefn2{Term=[visible part], Sec=(of a view of a callable entity)} The visible part of a view of a callable entity is its profile. @PDefn2{Term=[visible part], Sec=(of a view of a composite type)} The visible part of a composite type other than a task or protected type consists of the declarations of all components declared @Redundant[(explicitly or implicitly)] within the @nt{type_declaration}. @PDefn2{Term=[visible part], Sec=(of a generic unit)} The visible part of a generic unit includes the @nt{generic_formal_part}. For a generic package, it also includes the first list of @nt{basic_declarative_item}s of the @nt{package_specification}. For a generic subprogram, it also includes the profile. @begin{Reason} Although there is no way to reference anything but the formals from outside a generic unit, they are still in the visible part in the sense that the corresponding declarations in an instance can be referenced (at least in some cases). In other words, these declarations have an effect on the outside world. The visible part of a generic unit needs to be defined this way in order to properly support the rule that makes a parent's private part invisible within a public child's visible part. @end{Reason} @begin{Ramification} The visible part of an instance of a generic unit is as defined for packages and subprograms; it is not defined in terms of the visible part of a generic unit. @end{Ramification} @Redundant[The visible part of a package, task unit, or protected unit consists of declarations in the program unit's declaration other than those following the reserved word @key{private}, if any; see @RefSecNum{Package Specifications and Declarations} and @RefSecNum{Formal Packages} for packages, @RefSecNum{Task Units and Task Objects} for task units, and @RefSecNum{Protected Units and Protected Objects} for protected units.] @end{Itemize} @Defn2{Term=[scope], Sec=(of a declaration)} The scope of a declaration always contains the immediate scope of the declaration. In addition, for a given declaration that occurs immediately within the visible part of an outer declaration, or is a public child of an outer declaration, the scope of the given declaration extends to the end of the scope of the outer declaration, except that the scope of a @nt{library_item} includes only its semantic dependents. @begin{Ramification} Note the recursion. If a declaration appears in the visible part of a library unit, its scope extends to the end of the scope of the library unit, but since that only includes dependents of the declaration of the library unit, the scope of the inner declaration also only includes those dependents. If X renames library package P, which has a child Q, a @nt{with_clause} mentioning P.Q is necessary to be able to refer to X.Q, even if P.Q is visible at the place where X is declared. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[scope], Sec=(of an attribute_@!definition_@!clause)} The scope of an @nt{attribute_definition_clause} is identical to the scope of a declaration that would occur at the point of the @nt{attribute_definition_clause}.]} @Defn2{Term=[immediate scope], Sec=[of (a view of) an entity]} The immediate scope of a declaration is also the immediate scope of the entity or view declared by the declaration. @Defn2{Term=[scope], Sec=[of (a view of) an entity]} Similarly, the scope of a declaration is also the scope of the entity or view declared by the declaration. @begin{Ramification} @leading@;The rule for immediate scope implies the following: @begin{Itemize} If the declaration is that of a library unit, then the immediate scope includes the declarative region of the declaration itself, but not other places, unless they are within the scope of a @nt{with_clause} that mentions the library unit. @NoPrefix@;It is necessary to attach the semantics of @nt{with_clause}s to [immediate] scopes (as opposed to visibility), in order for various rules to work properly. A library unit should hide a homographic implicit declaration that appears in its parent, but only within the scope of a @nt{with_clause} that mentions the library unit. Otherwise, we would violate the "legality determinable via semantic dependences" rule of @RefSec{Program Structure and Compilation Issues}. The declaration of a library unit should be allowed to be a homograph of an explicit declaration in its parent's body, so long as that body does not mention the library unit in a @nt{with_clause}. @NoPrefix@;This means that one cannot denote the declaration of the library unit, but one might still be able to denote the library unit via another view. @NoPrefix@;A @nt{with_clause} does not make the declaration of a library unit visible; the lack of a @nt{with_clause} prevents it from being visible. Even if a library unit is mentioned in a @nt{with_clause}, its declaration can still be hidden. The completion of the declaration of a library unit (assuming that's also a declaration) is not visible, neither directly nor by selection, outside that completion. The immediate scope of a declaration immediately within the body of a library unit does not include any child of that library unit. @NoPrefix@;This is needed to prevent children from looking inside their parent's body. The children are in the declarative region of the parent, and they might be after the parent's body. Therefore, the scope of a declaration that occurs immediately within the body might include some children. @end{Itemize} @end{Ramification} @end{StaticSem} @begin{Notes} There are notations for denoting visible declarations that are not directly visible. For example, @nt{parameter_@!specification}s are in the visible part of a @nt{subprogram_@!declaration} so that they can be used in named-notation calls appearing outside the called subprogram. For another example, declarations of the visible part of a package can be denoted by expanded names appearing outside the package, and can be made directly visible by a @nt{use_clause}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} There are some obscure @Chg{Version=[2],New=[cases ],Old=[]}involving generics @Chg{Version=[2],New=[],Old=[cases ]}in which there is no such notation. See Section 12. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The fact that the immediate scope of an overloadable declaration does not include its profile is new to Ada 95. It replaces RM83-8.3(16), which said that within a subprogram specification and within the formal part of an entry declaration or accept statement, all declarations with the same designator as the subprogram or entry were hidden from all visibility. The RM83-8.3(16) rule seemed to be overkill, and created both implementation difficulties and unnecessary semantic complexity. @end{Extend83} @begin{DiffWord83} We no longer need to talk about the scope of notations, @nt{identifier}s, @nt{character_literal}s, and @nt{operator_symbol}s. The notion of "visible part" has been extended in Ada 95. The syntax of task and protected units now allows private parts, thus requiring us to be able to talk about the visible part as well. It was necessary to extend the concept to subprograms and to generic units, in order for the visibility rules related to child library units to work properly. It was necessary to define the concept separately for generic formal packages, since their visible part is slightly different from that of a normal package. Extending the concept to composite types made the definition of scope slightly simpler. We define visible part for some things elsewhere, since it makes a big difference to the user for those things. For composite types and subprograms, however, the concept is used only in arcane visibility rules, so we localize it to this clause. In Ada 83, the semantics of @nt{with_clause}s was described in terms of visibility. It is now described in terms of [immediate] scope. @leading@;We have clarified that the following is illegal (where Q and R are library units): @begin{Example} @key[package] Q @key[is] I : Integer := 0; @key[end] Q; @key[package] R @key[is] @key[package] X @key[renames] Standard; X.Q.I := 17; --@RI{ Illegal!} @key[end] R; @end{Example} even though Q is declared in the declarative region of Standard, because R does not mention Q in a @nt{with_clause}. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[The scope of an @nt{attribute_definition_clause} is defined so that it can be used to define the visibility of such a clause, so @i<that> can be used by the stream attribute availability rules (see @RefSecNum{Stream-Oriented Attributes}).]} @end{DiffWord95} @LabeledClause{Visibility} @begin{Intro} @redundant[@Defn{visibility rules} The @i{visibility rules}, given below, determine which declarations are visible and directly visible at each place within a program. The visibility rules apply to both explicit and implicit declarations.] @end{Intro} @begin{StaticSem} @Defn2{Term=[visibility], Sec=(direct)} @Defn{directly visible} @Defn{directly visible} A declaration is defined to be @i{directly visible} at places where a @nt<name> consisting of only an @nt{identifier} or @nt{operator_symbol} is sufficient to denote the declaration; that is, no @nt<selected_component> notation or special context (such as preceding => in a named association) is necessary to denote the declaration. @Defn{visible} A declaration is defined to be @i{visible} wherever it is directly visible, as well as at other places where some @nt<name> (such as a @nt<selected_component>) can denote the declaration. The syntactic category @nt<direct_name> is used to indicate contexts where direct visibility is required. The syntactic category @nt<selector_name> is used to indicate contexts where visibility, but not direct visibility, is required. @Defn2{Term=[visibility], Sec=(immediate)} @Defn2{Term=[visibility], Sec=(use clause)} There are two kinds of direct visibility: @i{immediate visibility} and @i{use-visibility}. @Defn{immediately visible} A declaration is immediately visible at a place if it is directly visible because the place is within its immediate scope. @Defn{use-visible} A declaration is use-visible if it is directly visible because of a @nt{use_clause} (see @RefSecNum{Use Clauses}). Both conditions can apply. @Defn{hiding} A declaration can be @i{hidden}, either from direct visibility, or from all visibility, within certain parts of its scope. @Defn{hidden from all visibility} Where @i{hidden from all visibility}, it is not visible at all (neither using a @nt<direct_name> nor a @nt<selector_name>). @Defn{hidden from direct visibility} Where @i{hidden from direct visibility}, only direct visibility is lost; visibility using a @nt<selector_name> is still possible. @redundant[@Defn{overloaded} Two or more declarations are @i{overloaded} if they all have the same defining name and there is a place where they are all directly visible.] @begin{Ramification} Note that a @nt{name} can have more than one possible interpretation even if it denotes a non-overloadable entity. For example, if there are two functions F that return records, both containing a component called C, then the name F.C has two possible interpretations, even though component declarations are not overloadable. @end{Ramification} @Defn{overloadable} The declarations of callable entities @Redundant[(including enumeration literals)] are @i{overloadable}@Redundant[, meaning that overloading is allowed for them]. @begin{Ramification} A @nt{generic_declaration} is not overloadable within its own @nt{generic_formal_part}. This follows from the rules about when a @nt{name} denotes a current instance. See AI83-00286. This implies that within a @nt{generic_formal_part}, outer declarations with the same defining name are hidden from direct visibility. It also implies that if a generic formal parameter has the same defining name as the generic itself, the formal parameter hides the generic from direct visibility. @end{Ramification} @Defn{homograph} Two declarations are @i{homographs} if they have the same defining name, and, if both are overloadable, their profiles are type conformant. @PDefn{type conformance} @redundant[An inner declaration hides any outer homograph from direct visibility.] @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Overriding operation>, Text=[@ChgAdded{Version=[2],Text=[An overriding operation is one that replaces an inherited primitive operation. Operations may be marked explicitly as overriding or not overriding.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} @leading@Redundant[Two homographs are not generally allowed immediately within the same declarative region unless one @i{overrides} the other (see Legality Rules below).] @Defn{override} @Chg{New=[The only declarations that are @Defn{overridable}@i{overridable} are the implicit declarations for predefined operators and inherited primitive subprograms.],Old=[]} A declaration overrides another homograph that occurs immediately within the same declarative region in the following cases: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} @Chg{New=[A declaration that is not overridable overrides one that is overridable], Old=[An explicit declaration overrides an implicit declaration of a primitive subprogram]}, @Redundant[regardless of which declaration occurs first]; @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} And regardless of whether the @Chg{New=[non-overridable],Old=[explicit]} declaration is overloadable or not. @Chg{New=[For example, @nt{statement_identifier}s are covered by this rule.],Old=[]} The @lquotes@;regardless of which declaration occurs first@rquotes@; is there because the explicit declaration could be a primitive subprogram of a partial view, and then the full view might inherit a homograph. We are saying that the explicit one wins (within its scope), even though the implicit one comes later. If the overriding declaration is also a subprogram, then it is a primitive subprogram. As explained in @RefSec{Private Operations}, some inherited primitive subprograms are never declared. Such subprograms cannot be overridden, although they can be reached by dispatching calls in the case of a tagged type. @end{Ramification} The implicit declaration of an inherited operator overrides that of a predefined operator; @begin{Ramification} In a previous version of Ada 9X, we tried to avoid the notion of predefined operators, and say that they were inherited from some magical root type. However, this seemed like too much mechanism. Therefore, a type can have a predefined "+" as well as an inherited "+". The above rule says the inherited one wins. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The @lquotes@;regardless of which declaration occurs first@rquotes@; applies here as well, in the case where @Chg{Version=[2],New=[@nt{derived_type_definition}], Old=[@ntf{derived_type_declaration}]} in the visible part of a public library unit derives from a private type declared in the parent unit, and the full view of the parent type has additional predefined operators, as explained in @RefSec{Private Operations}. Those predefined operators can be overridden by inherited subprograms implicitly declared earlier. @end{Ramification} An implicit declaration of an inherited subprogram overrides a previous implicit declaration of an inherited subprogram. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If two or more homographs are implicitly declared at the same place:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If at least one is a subprogram that is neither a null procedure nor an abstract subprogram, and does not require overriding (see @RefSecNum{Abstract Types and Subprograms}), then they override those that are null procedures, abstract subprograms, or require overriding. If more than one such homograph remains that is not thus overridden, then they are all hidden from all visibility.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Otherwise (all are null procedures, abstract subprograms, or require overriding), then any null procedure overrides all abstract subprograms and all subprograms that require overriding; if more than one such homograph remains that is not thus overridden, then if they are all fully conformant with one another, one is chosen arbitrarily; if not, they are all hidden from all visibility. @Defn2{Term=[full conformance],Sec=(required)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case where the implementation arbitrarily chooses one overrider from among a group of inherited subprograms, users should not be able to determine which member was chosen, as the set of inherited subprograms which are chosen from must be fully conformant. This rule is needed in order to allow]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{package} Outer @Key{is} @Key{package} P1 @Key{is} @Key{type} Ifc1 @Key{is interface}; @Key{procedure} Null_Procedure (X : Ifc1) @Key{is null}; @Key{procedure} Abstract_Subp (X : Ifc1) @Key{is abstract}; @Key{end} P1;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[ @Key{package} P2 @Key{is} @Key{type} Ifc2 @Key{is interface}; @Key{procedure} Null_Procedure (X : Ifc2) @Key{is null}; @Key{procedure} Abstract_Subp (X : Ifc2) @Key{is abstract}; @Key{end} P2;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[ @Key{type} T @Key{is abstract new} P1.Ifc1 @Key{and} P2.Ifc2 @Key{with null record}; @Key{end} Outer;],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[without requiring that T explicitly override any of its inherited operations.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Full conformance is required here, as we cannot allow the parameter names to differ. If they did differ, the routine which was selected for overriding could be determined by using named parameter notation in a call.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the subprograms do not conform, we chose not to adopt the @lquotes@;use clause@rquotes rule which would make them all visible resulting in likely ambiguity. If we had used such a rule, any successful calls would be confusing; and the fact that there are no Beaujolais-like effect to worry about means we can consider other rules. The hidden-from-all-visibility homographs are still inherited by further derivations, which avoids order-of-declaration dependencies and other anomalies.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to be careful to not include arbitrary selection if the routines have real bodies. (This can happen in generics, see the example in the incompatibilities section below.) We don't want the ability to successfully call routines where the body executed depends on the compiler or a phase of the moon.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that if the type is concrete, abstract subprograms are inherited as subprograms that require overriding. We include functions that require overriding as well; these don't have real bodies, so they can use the more liberal rules.]} @end{Discussion} @end{InnerItemize} @Redundant[For an implicit declaration of a primitive subprogram in a generic unit, there is a copy of this declaration in an instance.] However, a whole new set of primitive subprograms is implicitly declared for each type declared within the visible part of the instance. These new declarations occur immediately after the type declaration, and override the copied ones. @Redundant[The copied ones can be called only from within the instance; the new ones can be called only from outside the instance, although for tagged types, the body of a new one can be executed by a call to an old one.] @begin{Discussion} In addition, this is also stated redundantly (again), and is repeated, in @RefSec{Generic Instantiation}. The rationale for the rule is explained there. @end{Discussion} @end{Itemize} @leading@Defn{visible} @RootDefn{hidden from all visibility} A declaration is visible within its scope, except where hidden from all visibility, as follows: @begin{Itemize} @PDefn2{Term=[hidden from all visibility], Sec=(for overridden declaration)} An overridden declaration is hidden from all visibility within the scope of the overriding declaration. @begin{Ramification} We have to talk about the scope of the overriding declaration, not its visibility, because it hides even when it is itself hidden. Note that the scope of an explicit @nt{subprogram_declaration} does not start until after its profile. @end{Ramification} @leading@PDefn2{Term=[hidden from all visibility], Sec=(within the declaration itself)} A declaration is hidden from all visibility until the end of the declaration, except: @begin(InnerItemize) For a record type or record extension, the declaration is hidden from all visibility only until the reserved word @b(record); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} For a @nt{package_declaration}, @Chg{Version=[2],New=[],Old=[task declaration, protected declaration, ]}@nt{generic_@!package_@!declaration}, or @nt{subprogram_@!body}, the declaration is hidden from all visibility only until the reserved word @key(is) of the declaration@Chg{Version=[2],New=[;],Old=[.]} @begin{Ramification} We're talking about the @key{is} of the construct itself, here, not some random @key{is} that might appear in a @nt{generic_formal_part}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[For a task declaration or protected declaration, the declaration is hidden from all visibility only until the reserved word @key(with) of the declaration if there is one, or the reserved word @key(is) of the declaration if there is no @key(with).]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If there is neither a @key(with) nor @key(is), then the exception does not apply and the name is hidden from all visibility until the end of the declaration. This oddity was inherited from Ada 95.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We need the @lquotes@key(with) or @key(is)@rquotes rule so that the visibility within an @nt{interface_list} does not vary by construct. That would make it harder to complete private extensions and would complicate implementations.]} @end{Reason} @end(InnerItemize) @PDefn2{Term=[hidden from all visibility], Sec=(for a declaration completed by a subsequent declaration)} If the completion of a declaration is a declaration, then within the scope of the completion, the first declaration is hidden from all visibility. Similarly, a @nt{discriminant_@!specification} or @nt{parameter_@!specification} is hidden within the scope of a corresponding @nt{discriminant_@!specification} or @nt{parameter_@!specification} of a corresponding completion, or of a corresponding @nt{accept_@!statement}. @begin{Ramification} This rule means, for example, that within the scope of a @nt{full_type_declaration} that completes a @nt{private_type_declaration}, the name of the type will denote the @nt{full_type_declaration}, and therefore the full view of the type. On the other hand, if the completion is not a declaration, then it doesn't hide anything, and you can't denote it. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @PDefn2{Term=[hidden from all visibility], Sec=(by lack of a @nt{with_clause})} The declaration of a library unit (including a @nt{library_unit_renaming_declaration}) is hidden from all visibility @Chg{Version=[2],New=[],Old=[except ]}at places @Chg{Version=[2],New=[outside],Old=[that are within]} its declarative region @Chg{Version=[2],New=[that are not],Old=[or]} within the scope of a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} that mentions it.@Chg{Version=[2],New=[ The limited view of a library package is hidden from all visibility at places that are not within the scope of a @nt{limited_with_clause} that mentions it; in addition, the limited view is hidden from all visibility within the declarative region of the package, as well as within the scope of any @nt{nonlimited_with_clause} that mentions the package. Where the declaration of the limited view of a package is visible, any name that denotes the package denotes the limited view, including those provided by a package renaming.],Old=[@Redundant[For each declaration or renaming of a generic unit as a child of some parent generic package, there is a corresponding declaration nested immediately within each instance of the parent.] Such a nested declaration is hidden from all visibility except at places that are within the scope of a @nt{with_clause} that mentions the child.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} This is the rule that prevents @nt{with_clause}s from being transitive; the [immediate] scope includes indirect semantic dependents. @Chg{Version=[2],New=[This rule also prevents the limited view of a package from being visible in the same place as the full view of the package, which prevents various ripple effects.],Old=[]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00412-01]}@ChgNote{Just moved from above} @ChgAdded{Version=[2],Text=[@Redundant[For each declaration or renaming of a generic unit as a child of some parent generic package, there is a corresponding declaration nested immediately within each instance of the parent.] Such a nested declaration is hidden from all visibility except at places that are within the scope of a @nt{with_clause} that mentions the child.]} @end{Itemize} @leading@Defn{directly visible} @Defn{immediately visible} @Defn2{Term=[visibility], Sec=(direct)} @Defn2{Term=[visibility], Sec=(immediate)} A declaration with a @nt{defining_identifier} or @nt{defining_operator_symbol} is immediately visible @Redundant[(and hence directly visible)] within its immediate scope @RootDefn{hidden from direct visibility} except where hidden from direct visibility, as follows: @begin{Itemize} @PDefn2{Term=[hidden from direct visibility], Sec=(by an inner homograph)} A declaration is hidden from direct visibility within the immediate scope of a homograph of the declaration, if the homograph occurs within an inner declarative region; @PDefn2{Term=[hidden from direct visibility], Sec=(where hidden from all visibility)} A declaration is also hidden from direct visibility where hidden from all visibility. @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00195-01],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[visible], Sec=(attribute_@!definition_@!clause)} An @nt{attribute_definition_clause} is @i{visible} everywhere within its scope.]} @end{StaticSem} @begin{Resolution} @PDefn2{Term=[possible interpretation], Sec=(for @nt{direct_name}s)} A @nt{direct_name} shall resolve to denote a directly visible declaration whose defining name is the same as the @nt{direct_name}. @PDefn2{Term=[possible interpretation], Sec=(for @nt{selector_name}s)} A @nt{selector_name} shall resolve to denote a visible declaration whose defining name is the same as the @nt{selector_name}. @begin{Discussion} "The same as" has the obvious meaning here, so for +, the possible interpretations are declarations whose defining name is "+" (an @nt{operator_symbol}). @end{Discussion} These rules on visibility and direct visibility do not apply in a @nt{context_clause}, a @nt{parent_unit_name}, or a @nt{pragma} that appears at the place of a @nt{compilation_unit}. For those contexts, see the rules in @RefSec{Environment-Level Visibility Rules}. @begin{Ramification} Direct visibility is irrelevant for @nt{character_literal}s. In terms of overload resolution @nt{character_literal}s are similar to other literals, like @key{null} @em see @RefSecNum{Literals}. For @nt{character_literal}s, there is no need to worry about hiding, since there is no way to declare homographs. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],Ref=[8652/0026],ARef=[AI95-00044-01],ARef=[AI95-00150-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00377-01]} @Chg{New=[A non-overridable],Old=[An explicit]} declaration is illegal if there is a homograph occurring immediately within the same declarative region that is visible at the place of the declaration, and is not hidden from all visibility by the @Chg{New=[non-overridable],Old=[explicit]} declaration. @Chg{New=[In addition, a type extension is illegal if somewhere within its immediate scope it has two visible components with the same name.],Old=[]} Similarly, the @nt<context_clause> for a @Chg{Version=[2], New=[compilation unit],Old=[@nt<subunit>]} is illegal if it mentions (in a @nt<with_clause>) some library unit, and there is a homograph of the library unit that is visible at the place of the @Chg{Version=[2], New=[compilation unit],Old=[corresponding stub]}, and the homograph and the mentioned library unit are both declared immediately within the same declarative region.@PDefn{generic contract issue} These rules also apply to dispatching operations declared in the visible part of an instance of a generic unit. However, they do not apply to other overloadable declarations in an instance@Redundant[; such declarations may have type conformant profiles in the instance, so long as the corresponding declarations in the generic were not type conformant]. @PDefn{type conformance} @begin{Discussion} @leading@;Normally, these rules just mean you can't explicitly declare two homographs immediately within the same declarative region. The wording is designed to handle the following special cases: @begin{Itemize} If the second declaration completes the first one, the second declaration is legal. @leading@;If the body of a library unit contains an explicit homograph of a child of that same library unit, this is illegal only if the body mentions the child in its @nt<context_clause>, or if some subunit mentions the child. Here's an example: @begin{Example} @key[package] P @key[is] @key[end] P; @key[package] P.Q @key[is] @key[end] P.Q; @key[package] @key[body] P @key[is] Q : Integer; --@RI{ OK; we cannot see package P.Q here.} @key[procedure] Sub @key[is] @key[separate]; @key[end] P; @key[with] P.Q; @key[separate](P) @key[procedure] Sub @key[is] --@RI{ Illegal.} @key[begin] @key[null]; @key[end] Sub; @end{Example} @NoPrefix@;If package body P said "@key[with] P.Q;", then it would be illegal to declare the homograph Q: Integer. But it does not, so the body of P is OK. However, the subunit would be able to see both P.Q's, and is therefore illegal. @NoPrefix@;A previous version of Ada 9X allowed the subunit, and said that references to P.Q would tend to be ambiguous. However, that was a bad idea, because it requires overload resolution to resolve references to directly visible non-overloadable homographs, which is something compilers have never before been required to do. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0026],Ref=[8652/0102],ARef=[AI95-00150-01],ARef=[AI95-00157-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[If a type extension contains a component with the same name as a component in an ancestor type, there must be no place where both components are visible. For instance:]} @begin{Example}@ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] A @key[is] @key[type] T @key[is tagged private]; @key[package] B @key[is] @key[type] NT @key[is new] T @key[with record] I: Integer; -- @RI{Illegal because T.I is visible in the body.} @key[end record]; -- @RI{T.I is not visible here.} @key[end] B; @key[private] @key[type] T @key[is tagged record] I: Integer; -- @RI{Illegal because T.I is visible in the body.} @key[end record]; @key[end] A;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @Chg{New=[@Chg{Version=[2],New=[],Old=[@key[package] A @key[is] ]}@key[package] @key[body] A @key[is] @key[package] @key[body] B @key[is] -- @RI{T.I becomes visible here.} @key[end] B; @key[end] A;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] A.C @key[is] @key[type] NT2 @key[is new] A.T @key[with record] I: Integer; -- @RI{Illegal because T.I is visible in the private part.} @key[end record]; -- @RI{T.I is not visible here.} @key[private] -- @RI{T.I is visible here.} @key[end] A.C;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[with] A; @key[package] D @key[is] @key[type] NT3 @key[is new] A.T @key[with record] I: Integer; -- @RI{Legal because T.I is never visible in this package.} @key[end record]; @key[end] D;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[with] D; @key[package] A.E @key[is] @key[type] NT4 @key[is new] D.NT3 @key[with null record]; X : NT4; I1 : Integer := X.I; -- @RI{D.NT3.I} I2 : Integer := D.NT3(X).I; -- @RI{D.NT3.I} I3 : Integer := A.T(X).I; -- @RI{A.T.I} @key[end] A.E;],Old=[]} @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0102],ARef=[AI95-00157-01]} @ChgAdded{Version=[1],NoPrefix=[T],Text=[D.NT3 can have a component I because the component I of the parent type is never visible. The parent component exists, of course, but is never declared for the type D.NT3. In the child package A.E, the component I of A.T is visible, but that does not change the fact that the A.T.I component was never declared for type D.NT3. Thus, A.E.NT4 does not (visibly) inherit the component I from A.T, while it does inherit the component I from D.NT3. Of course, both components exist, and can be accessed by a type conversion as shown above. This behavior stems from the fact that every characteristic of a type (including components) must be declared somewhere in the innermost declarative region containing the type @em if the characteristic is never visible in that declarative region, it is never declared. Therefore, such characteristics do not suddenly become available even if they are in fact visible in some other scope. See @RefSecNum{Private Operations} for more on the rules.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00377-01]} @ChgAdded{Version=[2],Text=[It is illegal to mention both an explicit child of an instance, and a child of the generic from which the instance was instantiated. This is easier to understand with an example:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{generic} @key{package} G1 @key{is} @key{end} G1;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{generic} @key{package} G1.G2 @key{is} @key{end} G1.G2;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{with} G1; @key{package} I1 @key{is new} G1;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key{package} I1.G2 @key{renames} ...]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{with} G1.G2; @key{with} I1.G2; -- @RI{Illegal} @key{package} Bad @key{is} ...],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The context clause for Bad is illegal as I1 has an implicit declaration of I1.G2 based on the generic child G1.G2, as well as the mention of the explicit child I1.G2. As in the previous cases, this is illegal only if the context clause makes both children visible; the explicit child can be mentioned as long as the generic child is not (and vice-versa).]} @end{Itemize} Note that we need to be careful which things we make "hidden from all visibility" versus which things we make simply illegal for names to denote. The distinction is subtle. The rules that disallow names denoting components within a type declaration (see @RefSecNum{Discriminants}) do not make the components invisible at those places, so that the above rule makes components with the same name illegal. The same is true for the rule that disallows names denoting formal parameters within a @nt{formal_part} (see @RefSecNum{Subprogram Declarations}). @end{Discussion} @begin{Discussion} The part about instances is from AI83-00012. The reason it says @lquotes@;overloadable declarations@rquotes@; is because we don't want it to apply to type extensions that appear in an instance; components are not overloadable. @end{Discussion} @end{Legality} @begin{Notes} Visibility for compilation units follows from the definition of the environment in @RefSecNum{The Compilation Process}, except that it is necessary to apply a @nt{with_clause} to obtain visibility to a @nt{library_unit_declaration} or @nt{library_unit_renaming_declaration}. In addition to the visibility rules given above, the meaning of the occurrence of a @nt{direct_name} or @nt{selector_name} at a given place in the text can depend on the overloading rules (see @RefSecNum{The Context of Overload Resolution}). Not all contexts where an @nt<identifier>, @nt<character_literal>, or @nt<operator_symbol> are allowed require visibility of a corresponding declaration. Contexts where visibility is not required are identified by using one of these three syntactic categories directly in a syntax rule, rather than using @nt<direct_name> or @nt<selector_name>. @begin{Ramification} @leading@;An @nt{identifier}, @nt{character_literal} or @nt{operator_symbol} that occurs in one of the following contexts is not required to denote a visible or directly visible declaration: @begin{enumerate} A defining name. The @nt{identifier}s or @nt{operator_symbol} that appear after the reserved word @key{end} in a @nt{proper_body}. Similarly for @lquotes@;@key{end loop}@rquotes@;, etc. An @nt{attribute_designator}. A @nt{pragma} @nt{identifier}. A @SynI{pragma_argument_}@nt{identifier}. An @nt{identifier} specific to a pragma used in a pragma argument. @end{enumerate} The visibility rules have nothing to do with the above cases; the meanings of such things are defined elsewhere. Reserved words are not @nt{identifier}s; the visibility rules don't apply to them either. Because of the way we have defined "declaration", it is possible for a usage name to denote a @nt{subprogram_body}, either within that body, or (for a non-library unit) after it (since the body hides the corresponding declaration, if any). Other bodies do not work that way. Completions of @nt{type_declaration}s and deferred constant declarations do work that way. @nt{Accept_statement}s are never denoted, although the @nt{parameter_specification}s in their profiles can be. @leading@;The scope of a subprogram does not start until after its profile. Thus, the following is legal: @begin{Example} X : @key[constant] Integer := 17; ... @key[package] P @key[is] @key[procedure] X(Y : @key[in] Integer := X); @key[end] P; @end{Example} The body of the subprogram will probably be illegal, however, since the constant X will be hidden by then. @leading@;The rule is different for generic subprograms, since they are not overloadable; the following is illegal: @begin{Example} X : @key[constant] Integer := 17; @key[package] P @key[is] @key[generic] Z : Integer := X; --@RI{ Illegal!} @key[procedure] X(Y : @key[in] Integer := X); --@RI{ Illegal!} @key[end] P; @end{Example} The constant X is hidden from direct visibility by the generic declaration. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Declarations with the same defining name as that of a subprogram or entry being defined are nevertheless visible within the subprogram specification or entry declaration. @end{Extend83} @begin{DiffWord83} The term @lquotes@;visible by selection@rquotes@; is no longer defined. We use the terms @lquotes@;directly visible@rquotes@; and @lquotes@;visible@rquotes@; (among other things). There are only two regions of text that are of interest, here: the region in which a declaration is visible, and the region in which it is directly visible. Visibility is defined only for declarations. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} Added rules to handle the inheritance and overriding of multiple homographs for a single type declaration, in order to support multiple inheritance from interfaces. The new rules are intended to be compatible with the existing rules so that programs that do not use interfaces do not change their legality. However, there is a very rare case where this is not true:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T1 @key{is private}; @key{type} T2 @key{is private}; @key{package} G @key{is} @key{type} T @key{is null record}; @key{procedure} P (X : T; Y : T1); @key{procedure} P (X : T; Z : T2); @key{end} G;]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} I @key{is new} G (Integer, Integer); -- @RI[Exports homographs of P.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} D @key{is new} I.T; -- @RI[Both Ps are inherited.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Obj : D;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[P (Obj, Z => 10); -- @RI[Legal in Ada 95, illegal in Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The call to P would resolve in Ada 95 by using the parameter name, while the procedures P would be hidden from all visibility in Ada 2005 and thus would not resolve. This case doesn't seem worth making the rules any more complex than they already are.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00377-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] A @nt{with_clause} is illegal if it would create a homograph of an implicitly declared generic child (see @RefSecNum{Compilation Units - Library Units}). An Ada 95 compiler could have allowed this, but which unit of the two units involved would be denoted wasn't specified, so any successful use isn't portable. Removing one of the two @nt{with_clause}s involved will fix the problem.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0025],ARef=[AI95-00044-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Clarified the overriding rules so that "/=" and @nt{statement_identifier}s are covered.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0026],ARef=[AI95-00150-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Clarified that is it never possible for two components with the same name to be visible; any such program is illegal.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[The visibility of an @nt{attribute_definition_clause} is defined so that it can be used by the stream attribute availability rules (see @RefSecNum{Stream-Oriented Attributes}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[The visibility of a limited view of a library package is defined (see @RefSecNum{Compilation Units - Library Units}).],Old=[]} @end{DiffWord95} @RMNewPage@Comment{For printed Ada 2005 only} @LabeledAddedSubClause{Version=[2],Name=[Overriding Indicators]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is used to declare that an operation is intended to override (or not override) an inherited operation.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<overriding_indicator>,Old=<>}>, rhs="@Chg{Version=[2],New=<[@key{not}] @key{overriding}>,Old=<>}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03],ARef=[AI95-00348-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If an @nt{abstract_@!subprogram_@!declaration}, @nt{null_@!procedure_@!declaration}, @nt{subprogram_body}, @nt{subprogram_@!body_stub}, @nt{subprogram_@!renaming_@!declaration}, @nt{generic_@!instantiation} of a subprogram, or @nt{subprogram_@!declaration} other than a protected subprogram has an @nt{overriding_@!indicator}, then:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the operation shall be a primitive operation for some type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the operation shall override a homograph at the place of the declaration or body;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the operation shall not override any homograph (at any place).]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply, these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @Key{overriding} and @Key{not overriding} rules differ slightly. For @Key{overriding}, we want the indicator to reflect the overriding state at the place of the declaration; otherwise the indicator would be @LQuotes@;lying@RQuotes@;. Whether a homograph is implicitly declared after the declaration (see 7.3.1 to see how this can happen) has no impact on this check. However, @Key{not overriding} is different; @LQuotes@;lying@RQuotes@; would happen if a homograph declared later actually is overriding. So, we require this check to take into account later overridings. That can be implemented either by looking ahead, or by rechecking when additional operations are declared.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @LQuotes@;no lying@RQuotes@; rules are needed to prevent a @nt{subprogram_declaration} and @nt{subprogram_body} from having contradictory @nt{overriding_indicator}s.]} @end{Discussion} @end{Legality} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[Rules for @nt{overriding_indicator}s of task and protected entries and of protected subprograms are found in @RefSecNum{Entries and Accept Statements} and @RefSecNum{Protected Units and Protected Objects}, respectively.]} @end{Notes} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The use of @nt{overriding_indicator}s allows the detection of errors at compile-time that otherwise might not be detected at all. For instance, we might declare a security queue derived from the Queue interface of 3.9.4 as:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Security_Queue @key{is new} Queue @key{with record} ...;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{procedure} Append(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{procedure} Remove_First(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{function} Cur_Count(Q : @key{in} Security_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{function} Max_Count(Q : @key{in} Security_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{not overriding} @key{procedure} Arrest(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The first four subprogram declarations guarantee that these subprograms will override the four subprograms inherited from the Queue interface. A misspelling in one of these subprograms will be detected by the implementation. Conversely, the declaration of Arrest guarantees that this is a new operation.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, the subprograms are abstract, so misspellings will get detected anyway. But for other subprograms (especially when deriving from concrete types), the error might never be detected, and a body other than the one the programmer intended might be executed without warning. Thus our new motto: @lquotes@;Overriding indicators @em don't derive a type without them!@rquotes]} @end{Discussion} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Overriding_indicator}s are new. These let the programmer state her overriding intentions to the compiler; if the compiler disagrees, an error will be produced rather than a hard to find bug.]} @end{Extend95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{Use Clauses} @begin{Intro} @redundant[A @nt{use_package_clause} achieves direct visibility of declarations that appear in the visible part of a package; a @nt{use_type_clause} achieves direct visibility of the primitive operators of a type.] @end{Intro} @begin{MetaRules} @Defn{equivalence of @nt{use_clause}s and @nt{selected_component}s} If and only if the visibility rules allow P.A, "@key[use] P;" should make A directly visible (barring name conflicts). This means, for example, that child library units, and generic formals of a formal package whose @nt{formal_package_actual_part} is (<>), should be made visible by a @nt{use_clause} for the appropriate package. @Defn{Beaujolais effect} The rules for @nt{use_clause}s were carefully constructed to avoid so-called @i(Beaujolais) effects, where the addition or removal of a single @nt{use_clause}, or a single declaration in a "use"d package, would change the meaning of a program from one legal interpretation to another. @end{MetaRules} @begin{Syntax} @Syn{lhs=<use_clause>,rhs="@Syn2{use_package_clause} | @Syn2{use_type_clause}"} @Syn{lhs=<use_package_clause>,rhs="@key{use} @SynI{package_}@Syn2{name} {, @SynI{package_}@Syn2{name}};"} @Syn{lhs=<use_type_clause>,rhs="@key{use type} @Syn2{subtype_mark} {, @Syn2{subtype_mark}};"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @SynI{package_}@nt{name} of a @nt{use_package_clause} shall denote @Chg{Version=[2],New=[a nonlimited view of ],Old=[]}a package. @begin{Ramification} This includes formal packages. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn2{Term=[scope], Sec=(of a @nt{use_clause})} For each @nt{use_clause}, there is a certain region of text called the @i{scope} of the @nt{use_clause}. For a @nt{use_clause} within a @nt{context_clause} of a @nt{library_unit_declaration} or @nt{library_unit_renaming_declaration}, the scope is the entire declarative region of the declaration. For a @nt{use_clause} within a @nt{context_clause} of a body, the scope is the entire body @Redundant[and any subunits (including multiply nested subunits). The scope does not include @nt<context_clause>s themselves.] For a @nt{use_clause} immediately within a declarative region, the scope is the portion of the declarative region starting just after the @nt{use_clause} and extending to the end of the declarative region. However, the scope of a @nt{use_clause} in the private part of a library unit does not include the visible part of any public descendant of that library unit. @begin{Reason} @leading@;The exception echoes the similar exception for @lquotes@;immediate scope (of a declaration)@rquotes@; (see @RefSecNum{Scope of Declarations}). It makes @nt{use_clause}s work like this: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[range] 1..10; @key[end] P; @key[with] P; @key[package] Parent @key[is] @key[private] @key[use] P; X : T; @key[end] Parent; @key[package] Parent.Child @key[is] Y : T; --@RI{ Illegal!} Z : P.T; @key[private] W : T; @key[end] Parent.Child; @end{Example} The declaration of Y is illegal because the scope of the @lquotes@;@key[use] P@rquotes@; does not include that place, so T is not directly visible there. The declarations of X, Z, and W are legal. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[A package is @i{named} in a @nt{use_package_clause} if it is denoted by a @SynI{package_}@nt{name} of that clause. A type is @i{named} in a @nt{use_type_clause} if it is determined by a @nt{subtype_mark} of that clause.@Defn2{Term=[named],Sec=[in a use clause]}],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @Defn{potentially use-visible} For each package @Chg{Version=[2],New=[named in ],Old=[denoted by a @SynI{package_}@nt{name} of ]}a @nt{use_package_clause} whose scope encloses a place, each declaration that occurs immediately within the declarative region of the package is @i(potentially use-visible) at this place if the declaration is visible at this place. For each type @i(T) or @i(T)'Class @Chg{Version=[2],New=[named in ],Old=[ determined by a @nt<subtype_mark> of ]}a @nt{use_type_clause} whose scope encloses a place, the declaration of each primitive operator of type @i(T) is potentially use-visible at this place if its declaration is visible at this place. @begin{Ramification} Primitive subprograms whose defining name is an @nt{identifier} are @i{not} made potentially visible by a @nt{use_type_clause}. A @nt{use_type_clause} is only for operators. The semantics described here should be similar to the semantics for expanded names given in @RefSec{Selected Components} so as to achieve the effect requested by the @lquotes@;principle of equivalence of @nt{use_clause}s and @nt{selected_component}s.@rquotes@; Thus, child library units and generic formal parameters of a formal package are potentially use-visible when their enclosing package is use'd. The "visible at that place" part implies that applying a @nt{use_clause} to a parent unit does not make all of its children use-visible @em only those that have been made visible by a @nt{with_clause}. It also implies that we don't have to worry about hiding in the definition of "directly visible" @em a declaration cannot be use-visible unless it is visible. Note that "@key[use type] T'Class;" is equivalent to "@key[use type] T;", which helps avoid breaking the generic contract model. @end{Ramification} @leading@Defn{use-visible} @Defn2{Term=[visibility],Sec=(use clause)} A declaration is @i{use-visible} if it is potentially use-visible, except in these naming-conflict cases: @begin{itemize} A potentially use-visible declaration is not use-visible if the place considered is within the immediate scope of a homograph of the declaration. Potentially use-visible declarations that have the same @nt{identifier} are not use-visible unless each of them is an overloadable declaration. @begin{Ramification} Overloadable declarations don't cancel each other out, even if they are homographs, though if they are not distinguishable by formal parameter names or the presence or absence of @nt{default_expression}s, any use will be ambiguous. We only mention @nt{identifier}s here, because declarations named by @nt<operator_symbol>s are always overloadable, and hence never cancel each other. Direct visibility is irrelevant for @nt{character_literal}s. @end{Ramification} @end{itemize} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(use_clause)} The elaboration of a @nt{use_clause} has no effect. @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of a use clause in a context clause:} @begin{Example} @key[with] Ada.Calendar; @key[use] Ada; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a use type clause:} @end{Wide} @begin{Example} @key[use type] Rational_Numbers.Rational; --@RI{ see @RefSecNum{Package Specifications and Declarations}} Two_Thirds: Rational_Numbers.Rational := 2/3; @end{Example} @begin{Ramification} In @lquotes@;@key[use] X, Y;@rquotes@;, Y cannot refer to something made visible by the @lquotes@;@key[use]@rquotes@; of X. Thus, it's not (quite) equivalent to @lquotes@;@key[use] X; @key[use] Y;@rquotes@;. If a given declaration is already immediately visible, then a @nt{use_clause} that makes it potentially use-visible has no effect. Therefore, a @nt{use_type_clause} for a type whose declaration appears in a place other than the visible part of a package has no effect; it cannot make a declaration use-visible unless that declaration is already immediately visible. "@key[Use] @key[type] S1;" and "@key[use] @key[type] S2;" are equivalent if S1 and S2 are both subtypes of the same type. In particular, "@key[use] @key[type] S;" and "@key[use] @key[type] S'Base;" are equivalent. @end{Ramification} @begin{Reason} We considered adding a rule that prevented several declarations of views of the same entity that all have the same semantics from cancelling each other out. For example, if a (possibly implicit) @nt{subprogram_declaration} for "+" is potentially use-visible, and a fully conformant renaming of it is also potentially use-visible, then they (annoyingly) cancel each other out; neither one is use-visible. The considered rule would have made just one of them use-visible. We gave up on this idea due to the complexity of the rule. It would have had to account for both overloadable and non-overloadable @nt{renaming_declaration}s, the case where the rule should apply only to some subset of the declarations with the same defining name, and the case of @nt{subtype_declaration}s (since they are claimed to be sufficient for renaming of subtypes). @end{Reason} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{use_type_clause} is new to Ada 95. @end{Extend83} @begin{DiffWord83} The phrase @lquotes@;omitting from this set any packages that enclose this place@rquotes@; is no longer necessary to avoid making something visible outside its scope, because we explicitly state that the declaration has to be visible in order to be potentially use-visible. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[Limited views of packages are not allowed in use clauses. Defined @i<named in a use clause> for use in other limited view rules (see @RefSecNum{Context Clauses - With Clauses}).],Old=[]} @end{DiffWord95} @LabeledClause{Renaming Declarations} @begin{Intro} @redundant[A @nt{renaming_declaration} declares another name for an entity, such as an object, exception, package, subprogram, entry, or generic unit. Alternatively, a @nt{subprogram_renaming_declaration} can be the completion of a previous @nt{subprogram_declaration}.] @ChgToGlossary{Version=[2],Kind=[Added],Term=<Renaming>, Text=<@ChgAdded{Version=[2],Text=[A @nt{renaming_declaration} is a declaration that does not define a new entity, but instead defines a view of an existing entity.]}>} @end{Intro} @begin{Syntax} @Syn{lhs=<renaming_declaration>,rhs=" @Syn2{object_renaming_declaration} | @Syn2{exception_renaming_declaration} | @Syn2{package_renaming_declaration} | @Syn2{subprogram_renaming_declaration} | @Syn2{generic_renaming_declaration}"} @end{Syntax} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(renaming_declaration)} The elaboration of a @nt{renaming_declaration} evaluates the @nt{name} that follows the reserved word @key{renames} and thereby determines the view and entity denoted by this name @Defn{renamed view} @Defn{renamed entity} (the @i{renamed view} and @i{renamed entity}). @Redundant[A @nt{name} that denotes the @nt{renaming_declaration} denotes (a new view of) the renamed entity.] @end{RunTime} @begin{Notes} Renaming may be used to resolve name conflicts and to act as a shorthand. Renaming with a different @nt{identifier} or @nt{operator_symbol} does not hide the old @nt{name}; the new @nt{name} and the old @nt{name} need not be visible at the same places. A task or protected object that is declared by an explicit @nt{object_declaration} can be renamed as an object. However, a single task or protected object cannot be renamed since the corresponding type is anonymous (meaning it has no nameable subtypes). For similar reasons, an object of an anonymous array or access type cannot be renamed. @leading@keepnext@;A subtype defined without any additional constraint can be used to achieve the effect of renaming another subtype (including a task or protected subtype) as in @begin{Example} @key[subtype] Mode @key[is] Ada.Text_IO.File_Mode; @end{Example} @end{Notes} @begin{DiffWord83} The second sentence of RM83-8.5(3), @lquotes@;At any point where a renaming declaration is visible, the identifier, or operator symbol of this declaration denotes the renamed entity.@rquotes@; is incorrect. It doesn't say directly visible. Also, such an @nt{identifier} might resolve to something else. The verbiage about renamings being legal @lquotes@;only if exactly one...@rquotes@;, which appears in RM83-8.5(4) (for objects) and RM83-8.5(7) (for subprograms) is removed, because it follows from the normal rules about overload resolution. For language lawyers, these facts are obvious; for programmers, they are irrelevant, since failing these tests is highly unlikely. @end{DiffWord83} @LabeledSubClause{Object Renaming Declarations} @begin{Intro} @redundant[An @nt{object_renaming_declaration} is used to rename an object.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00423-01]} @Syn{lhs=<object_renaming_declaration>,rhs="@Chg{Version=[2],New=[ ],Old=[]}@Syn2{defining_identifier} : @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} @key{renames} @SynI{object_}@Syn2{name};@Chg{Version=[2],New=[ | @Syn2{defining_identifier} : @Syn2{access_definition} @key{renames} @SynI{object_}@Syn2{name};],Old=[]}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} The type of the @SynI{object_}@nt{name} shall resolve to the type determined by the @nt{subtype_mark}@Chg{Version=[2],New=[, or in the case where the type is defined by an @nt{access_definition}, to an anonymous access type. If the anonymous access type is an access-to-object type, the type of the @SynI{object_}@nt{name} shall have the same designated type as that of the @nt{access_definition}. If the anonymous access type is an access-to-subprogram type, the type of the @SynI{object_}@nt{name} shall have a designated profile that is type conformant with that of the @nt{access_definition}],Old=[]}. @begin{Reason} @leading@;A previous version of Ada 9X used the usual @lquotes@;expected type@rquotes@; wording:@* @lquotes@;The expected type for the @SynI{object_}@nt{name} is that determined by the @nt{subtype_mark}.@rquotes@;@* We changed it so that this would be illegal: @begin{Example} X: T; Y: T'Class @key[renames] X; --@RI{ Illegal!} @end{Example} @leading@;When the above was legal, it was unclear whether Y was of type T or T'Class. Note that we still allow this: @begin{Example} Z: T'Class := ...; W: T @key[renames] F(Z); @end{Example} where F is a function with a controlling parameter and result. This is admittedly a bit odd. Note that the matching rule for generic formal parameters of mode @key[in out] was changed to keep it consistent with the rule for renaming. That makes the rule different for @key[in] vs. @key[in out]. @end{Reason} @end{Resolution} @begin{Legality} The renamed entity shall be an object. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In the case where the type is defined by an @nt{access_definition}, the type of the renamed object and the type defined by the @nt{access_definition}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-object types with statically matching designated subtypes and with both or neither being access-to-constant types; or @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-subprogram types with subtype conformant designated profiles. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an @nt{object_renaming_declaration} with a @nt{null_exclusion} or an @nt{access_definition} that has a @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @Syni{object_}@nt{name} denotes a generic formal object of a generic unit @i{G}, and the @nt{object_renaming_declaration} occurs within the body of @i{G} or within the body of a generic unit declared within the declarative region of @i{G}, then the declaration of the formal object of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the @Syni{object_}@nt{name} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of an object with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in one obscure case:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Acc_I @key{is access} Integer; @key{subtype} Acc_NN_I @key{is not null} Acc_I; Obj : Acc_I := @key{null};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} B : @key{in out} Acc_NN_I; @key{package} Gen @key{is} ... @key{end} Gen;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Gen @key{is} D : @key{not null} Acc_I @key{renames} B; @key{end} Gen;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Inst @key{is new} Gen (B => Obj);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Without the first bullet rule, D would be legal, and contain the value @key{null}, because the rule about lying is satisfied for generic matching (Obj matches B; B does not explicitly state @key{not null}), @LegalityTitle are not rechecked in the body of any instance, and the template passes the lying rule as well. The rule is so complex because it has to apply to formals used in bodies of child generics as well as in the bodies of generics.]} @end{Reason} @end{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} The renamed entity shall not be a subcomponent that depends on discriminants of a variable whose nominal subtype is unconstrained, unless this subtype is indefinite, or the variable is @Chg{Version=[2], New=[constrained by its initial value],Old=[aliased]}. A @nt{slice} of an array shall not be renamed if this restriction disallows renaming of the array. @Chg{New=[In addition to the places where Legality Rules normally apply, these rules apply also in the private part of an instance of a generic unit. These rules also apply for a renaming that appears in the body of a generic unit, with the additional requirement that even if the nominal subtype of the variable is indefinite, its type shall not be a descendant of an untagged generic formal derived type.],Old=[]} @begin{Reason} This prevents renaming of subcomponents that might disappear, which might leave dangling references. Similar restrictions exist for the Access attribute. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[The @lquotes@;recheck on instantiation@rquotes@; and @lquotes@;assume-the-worst in the body@rquotes@; restrictions on generics are necessary to avoid renaming of components which could disappear even when the nominal subtype would prevent the problem:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{type} T1 (D1 : Boolean) @key{is} @key{record} @key{case} D1 @key{is} @key{when} False => C1 : Integer; @key{when} True => @key{null}; @key{end} @key{case}; @key{end} @key{record};],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{generic} @key{type} F @key{is} @key{new} T1; X : @key{in out} F; @key{package} G @key{is} C1_Ren : Integer @key{renames} X.C1; @key{end} G;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{type} T2 (D2 : Boolean := False) @key{is} @key{new} T1 (D1 => D2); @Comment{Blank line} Y : T2; @Comment{Blank line} @key{package} I @key{is new} G (T2, Y); @Comment{Blank line} Y := (D1 => True); -- @RI[Oops! What happened to I.C1_Ren?]],Old=[]} @end{Example} @end{Reason} @begin{ImplNote} Note that if an implementation chooses to deallocate-then-reallocate on @nt{assignment_@!statement}s assigning to unconstrained definite objects, then it cannot represent renamings and access values as simple addresses, because the above rule does not apply to all components of such an object. @end{ImplNote} @begin{Ramification} If it is a generic formal object, then the assume-the-best or assume-the-worst rules are applied as appropriate. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If renamed entity is a subcomponent that depends on discriminants, and the subcomponent is a dereference of a general access type whose designated type is unconstrained and whose discriminants have defaults, the renaming is illegal. Such a general access type can designate an unconstrained (stack) object. Since such a type might not designate an object constrained by its initial value, the renaming is illegal @em the rule says @lquotes@;is@rquotes constrained by its initial value, not @lquotes@;might be@rquotes constrained by its initial value. No other interpretation makes sense, as we can't have legality depending on something (which object is designated) that is not known at compile-time, and we surely can't allow this for unconstrained objects. The wording of the rule should be much clearer on this point, but this was discovered after the completion of Amendment 1 when it was too late to fix it.]} @end{Honest} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00409-01]} An @nt{object_renaming_declaration} declares a new view @Redundant{of the renamed object} whose properties are identical to those of the renamed view. @Redundant[Thus, the properties of the renamed object are not affected by the @nt{renaming_declaration}. In particular, its value and whether or not it is a constant are unaffected; similarly, the@Chg{Version=[2],New=[ null exclusion or],Old=[]} constraints that apply to an object are not affected by renaming (any constraint implied by the @nt{subtype_mark} @Chg{Version=[2],New=[or @nt{access_definition} ],Old=[]}of the @nt{object_renaming_declaration} is ignored).] @begin{Discussion} Because the constraints are ignored, it is a good idea to use the nominal subtype of the renamed object when writing an @nt{object_renaming_declaration}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[If no @nt{null_exclusion} is given in the renaming, the object may or may not exclude null. This is similar to the way that constraints need not match, and @key{constant} is not specified. The renaming defines a view of the renamed entity, inheriting the original properties.]} @end{Discussion} @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming an object:} @begin{Example} @key[declare] L : Person @key[renames] Leftmost_Person; --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[begin] L.Age := L.Age + 1; @key[end]; @end{Example} @end{Examples} @begin{DiffWord83} The phrase @lquotes@;subtype ... as defined in a corresponding object declaration, component declaration, or component subtype indication,@rquotes@; from RM83-8.5(5), is incorrect in Ada 95; therefore we removed it. It is incorrect in the case of an object with an indefinite unconstrained nominal subtype. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Leading@;@Defn{incompatibilities with Ada 95} Aliased variables are not necessarily constrained in Ada 2005 (see @RefSecNum{Array Types}). Therefore, a subcomponent of an aliased variable may disappear or change shape, and renaming such a subcomponent thus is illegal, while the same operation would have been legal in Ada 95. Note that most allocated objects are still constrained by their initial value (see @RefSecNum{Allocators}), and thus have no change in the legality of renaming for them. For example, using the type T2 of the previous example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ AT2 : @key{aliased} T2; C1_Ren : Integer @key{renames} AT2.C1; -- @RI[Illegal in Ada 2005, legal in Ada 95] AT2 := (D1 => True); -- @RI[Raised Constraint_Error in Ada 95,] -- @RI[but does not in Ada 2005, so C1_Ren becomes] -- @RI[invalid when this is assigned.]]} @end{Example} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A renaming can have an anonymous access type. In that case, the accessibility of the renaming is that of the original object (accessibility is not lost as it is for a component or stand-alone object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[A renaming can have a @nt{null_exclusion}; if so, the renamed object must also exclude null, so that the @nt{null_exclusion} does not lie. On the other hand, if the renaming does not have a @nt{null_exclusion}. it excludes null of the renamed object does.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed to forbid renamings of depends-on-discriminant components if the type @i{might} be definite.]} @end{DiffWord95} @LabeledSubClause{Exception Renaming Declarations} @begin{Intro} @redundant[An @nt{exception_renaming_declaration} is used to rename an exception.] @end{Intro} @begin{Syntax} @Syn{lhs=<exception_renaming_declaration>,rhs="@Syn2{defining_identifier} : @key{exception} @key{renames} @SynI{exception_}@Syn2{name};"} @end{Syntax} @begin{Legality} The renamed entity shall be an exception. @end{Legality} @begin{StaticSem} An @nt{exception_renaming_declaration} declares a new view @Redundant{of the renamed exception}. @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming an exception:} @begin{Example} EOF : @key[exception] @key[renames] Ada.IO_Exceptions.End_Error; @RI{-- see @RefSecNum{Exceptions in Input-Output}} @end{Example} @end{Examples} @LabeledSubClause{Package Renaming Declarations} @begin{Intro} @redundant[A @nt{package_renaming_declaration} is used to rename a package.] @end{Intro} @begin{Syntax} @Syn{lhs=<package_renaming_declaration>,rhs="@key{package} @Syn2{defining_program_unit_name} @key{renames} @SynI{package_}@Syn2{name};"} @end{Syntax} @begin{Legality} The renamed entity shall be a package. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[If the @SynI{package_}@nt{name} of a @nt{package_renaming_declaration} denotes a limited view of a package @i{P}, then a name that denotes the @nt{package_renaming_declaration} shall occur only within the immediate scope of the renaming or the scope of a @nt{with_clause} that mentions the package @i{P} or, if @i{P} is a nested package, the innermost library package enclosing @i{P}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The use of a renaming that designates a limited view is restricted to locations where we know whether the view is limited or nonlimited (based on a @nt{with_clause}). We don't want to make an implicit limited view, as those are not transitive like a regular view. Implementations should be able to see all limited views needed based on the @nt{context_clause}.]} @end{Discussion} @end{Legality} @begin{StaticSem} A @nt{package_renaming_declaration} declares a new view @Redundant{of the renamed package}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[@Redundant[At places where the declaration of the limited view of the renamed package is visible, a @nt{name} that denotes the @nt{package_renaming_declaration} denotes a limited view of the package (see @RefSecNum{Compilation Units - Library Units}).]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This rule is found in @RefSec{Visibility}.]} @end{TheProof} @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming a package:} @begin{Example} @key[package] TM @key[renames] Table_Manager; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[Uses of renamed limited views of packages can only be used within the scope of a with_clause for the renamed package.]} @end{DiffWord95} @LabeledSubClause{Subprogram Renaming Declarations} @begin{Intro} A @nt{subprogram_renaming_declaration} can serve as the completion of a @nt{subprogram_declaration}; @Defn{renaming-as-body} such a @nt{renaming_declaration} is called a @i{renaming-as-body}. @Defn{renaming-as-declaration} A @nt{subprogram_renaming_declaration} that is not a completion is called a @i{renaming-as-declaration}@Redundant[, and is used to rename a subprogram (possibly an enumeration literal) or an entry]. @begin{Ramification} A renaming-as-body is a declaration, as defined in Section 3. @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @Syn{lhs=<subprogram_renaming_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=<>}@Syn2{subprogram_specification} @key{renames} @SynI{callable_entity_}@Syn2{name};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(subprogram_renaming_declaration)} The expected profile for the @i(callable_entity_)@nt<name> is the profile given in the @nt<subprogram_specification>. @end{Resolution} @begin{Legality} The profile of a renaming-as-declaration shall be mode-conformant with that of the renamed callable entity. @Defn2{Term=[mode conformance],Sec=(required)} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a parameter or result subtype of the @nt{subprogram_specification} that has an explicit @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @Syni{callable_entity_}@nt{name} denotes a generic formal subprogram of a generic unit @i{G}, and the @nt{subprogram_renaming_declaration} occurs within the body of a generic unit @i{G} or within the body of a generic unit declared within the declarative region of the generic unit @i{G}, then the corresponding parameter or result subtype of the formal subprogram of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the corresponding parameter or result type of the renamed callable entity shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of a parameter or result with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child units) when the formal subtype excludes null implicitly.]} @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0027],Ref=[8652/0028],ARef=[AI95-00135-01],ARef=[AI95-00145-01]} The profile of a renaming-as-body @Chg{New=[],Old=[shall be subtype-conformant with that of the renamed callable entity, and ]}shall conform fully to that of the declaration it completes. @Defn2{Term=[full conformance],Sec=(required)} If the renaming-as-body completes that declaration before the subprogram it declares is frozen, @Chg{New=[the profile shall be mode-conformant @Defn2{Term=[mode conformance],Sec=(required)}with that of the renamed callable entity and ],Old=[]}the subprogram it declares takes its convention from the renamed subprogram; otherwise@Chg{New=[, the profile shall be subtype-conformant with that of the renamed callable entity and],Old=[]} the convention of the renamed subprogram shall not be Intrinsic. @Defn2{Term=[subtype conformance],Sec=(required)} @Chg{New=[A renaming-as-body is illegal if the declaration occurs before the subprogram whose declaration it completes is frozen, and the renaming renames the subprogram itself, through one or more subprogram renaming declarations, none of whose subprograms has been frozen.],Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} The @Chg{New=[otherwise part of the second sentence],Old=[first part of the first sentence]} is to allow an implementation of a renaming-as-body as a single jump instruction to the target subprogram. Among other things, this prevents a subprogram from being completed with a renaming of an entry. (In most cases, the target of the jump can be filled in at link time. In some cases, such as a renaming of a name like "A(I).@key[all]", an indirect jump is needed. Note that the name is evaluated at renaming time, not at call time.) @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0028],ARef=[AI95-00145-01]} @Chg{New=[The first part of the second sentence is intended to allow renaming-as-body of predefined operators before the @nt{subprogram_declaration} is frozen. For some types (such as integer types), the parameter type for operators is the base type, and it would be very strange for@* @f{@ @ @ @key{function} Equal (A, B : @key{in} T) @key{return} Boolean;}@* @f{@ @ @ @key{function} Equal (A, B : @key{in} T) @key{return} Boolean @key{renames} "=";}@* to be illegal. (Note that predefined operators cannot be renamed this way after the @nt{subprogram_declaration} is frozen, as they have convention Intrinsic.)],Old=[]} @ChgRef{Version=[1],Kind=[Revised]} The @Chg{New=[],Old=[second part of the ]}first sentence is the normal rule for completions of @nt{subprogram_declaration}s. @end{Reason} @begin{Ramification} An @nt{entry_declaration}, unlike a @nt{subprogram_declaration}, cannot be completed with a @nt{renaming_@!declaration}. Nor can a @nt{generic_@!subprogram_@!declaration}. The syntax rules prevent a protected subprogram declaration from being completed by a renaming. This is fortunate, because it allows us to avoid worrying about whether the implicit protected object parameter of a protected operation is involved in the conformance rules. @end{Ramification} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[Circular renames before freezing is illegal, as the compiler would not be able to determine the convention of the subprogram. Other circular renames are handled below; see @BoundedTitle.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[The @Syni{callable_entity_}@nt{name} of a renaming shall not denote a subprogram that requires overriding (see @RefSecNum{Abstract Types and Subprograms}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[Such a rename cannot be of the inherited subprogram (which requires overriding because it cannot be called), and thus cannot squirrel away a subprogram (see below). That would be confusing, so we make it illegal. The renaming is allowed after the overriding, as then the @nt{name} will denote the overriding subprogram, not the inherited one.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[The @Syni{callable_entity_}@nt{name} of a renaming-as-body shall not denote an abstract subprogram.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[Such a subprogram has no body, so it hardly can replace one in the program.]} @end{Reason} A @nt{name} that denotes a formal parameter of the @nt{subprogram_specification} is not allowed within the @Syni{callable_entity_}@nt{name}. @begin{Reason} @leading@keepnext@;This is to prevent things like this: @begin{Example} @key[function] F(X : Integer) @key[return] Integer @key[renames] Table(X).@key[all]; @end{Example} @begin{Wide} @leading@;A similar rule in @RefSecNum{Subprogram Declarations} forbids things like this: @end{Wide} @begin{Example} @key[function] F(X : Integer; Y : Integer := X) @key[return] Integer; @end{Example} @end{Reason} @end{Legality} @begin{StaticSem} A renaming-as-declaration declares a new view of the renamed entity. The profile of this new view takes its subtypes, parameter modes, and calling convention from the original profile of the callable entity, while taking the formal parameter @nt{name}s and @nt{default_expression}s from the profile given in the @nt{subprogram_renaming_declaration}. The new view is a function or procedure, never an entry. @begin{Honest} When renaming an entry as a procedure, the compile-time rules apply as if the new view is a procedure, but the run-time semantics of a call are that of an entry call. @end{Honest} @begin{Ramification} For example, it is illegal for the @nt{entry_call_statement} of a @nt{timed_entry_call} to call the new view. But what looks like a procedure call will do things like barrier waiting. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0105],ARef=[AI95-00211-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00228-01]} @Chg{New=[All properties of the renamed entity are inherited by the new view unless otherwise stated by this International Standard. In particular, if the renamed entity is abstract@Chg{Version=[2],New=[],Old=[ or requires overriding (see @RefSecNum{Abstract Types and Subprograms})]}, the new view also is abstract@Chg{Version=[2],New=[.],Old=[ or requires overriding. (The renaming will often be illegal in these cases, as a renaming cannot be overridden.)]}],Old=[]} @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0014],ARef=[AI95-00064-01]} @Chg{New=[For a call to a subprogram whose body is given as a renaming-as-body, the execution of the renaming-as-body is equivalent to the execution of a @nt{subprogram_body} that simply calls the renamed subprogram with its formal parameters as the actual parameters and, if it is a function, returns the value of the call.],Old=[]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[This implies that the subprogram completed by the renaming-as-body has its own elaboration check.]} @end{Ramification} For a call on a renaming of a dispatching subprogram that is overridden, if the overriding occurred before the renaming, then the body executed is that of the overriding declaration, even if the overriding declaration is not visible at the place of the renaming; otherwise, the inherited or predefined subprogram is called. @begin{Discussion} Note that whether or not the renaming is itself primitive has nothing to do with the renamed subprogram. Note that the above rule is only for tagged types. @leading@keepnext@;Consider the following example: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; @key[function] Predefined_Equal(X, Y : T) @key[return] Boolean @key[renames] "="; @key[private] @key[function] "="(X, Y : T) @key[return] Boolean; --@RI{ Override predefined "=".} @key[end] P; @key[with] P; @key[use] P; @key[package] Q @key[is] @key[function] User_Defined_Equal(X, Y : T) @key[return] Boolean @key[renames] P."="; @key[end] Q; @end{Example} A call on Predefined_Equal will execute the predefined equality operator of T, whereas a call on User_Defined_Equal will execute the body of the overriding declaration in the private part of P. Thus a renaming allows one to squirrel away a copy of an inherited or predefined subprogram before later overriding it.@Defn{squirrel away} @end{Discussion} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If a subprogram directly or indirectly renames itself, then it is a bounded error to call that subprogram. Possible consequences are that Program_Error or Storage_Error is raised, or that the call results in infinite recursion.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[This has to be a bounded error, as it is possible for a renaming-as-body appearing in a package body to cause this problem. Thus it is not possible in general to detect this problem at compile time.]} @end{Reason} @end{Bounded} @begin{Notes} A procedure can only be renamed as a procedure. A function whose @nt{defining_designator} is either an @nt{identifier} or an @nt{operator_symbol} can be renamed with either an @nt{identifier} or an @nt{operator_symbol}; for renaming as an operator, the subprogram specification given in the @nt{renaming_declaration} is subject to the rules given in @RefSecNum{Overloading of Operators} for operator declarations. Enumeration literals can be renamed as functions; similarly, @nt{attribute_reference}s that denote functions (such as references to Succ and Pred) can be renamed as functions. An entry can only be renamed as a procedure; the new @nt{name} is only allowed to appear in contexts that allow a procedure @nt{name}. An entry of a family can be renamed, but an entry family cannot be renamed as a whole. The operators of the root numeric types cannot be renamed because the types in the profile are anonymous, so the corresponding specifications cannot be written; the same holds for certain attributes, such as Pos. Calls with the new @nt{name} of a renamed entry are @nt{procedure_call_statement}s and are not allowed at places where the syntax requires an @nt{entry_call_statement} in @ntf{conditional_} and @nt{timed_entry_call}s, nor in an @nt{asynchronous_select}; similarly, the Count attribute is not available for the new @nt{name}. The primitiveness of a renaming-as-declaration is determined by its profile, and by where it occurs, as for any declaration of (a view of) a subprogram; primitiveness is not determined by the renamed view. In order to perform a dispatching call, the subprogram name has to denote a primitive subprogram, not a non-primitive renaming of a primitive subprogram. @begin{Reason} A @nt{subprogram_renaming_declaration} could more properly be called @ntf{renaming_@!as_@!subprogram_@!declaration}, since you're renaming something as a subprogram, but you're not necessarily renaming a subprogram. But that's too much of a mouthful. Or, alternatively, we could call it a @ntf{callable_@!entity_@!renaming_@!declaration}, but that's even worse. Not only is it a mouthful, it emphasizes the entity being renamed, rather than the new view, which we think is a bad idea. We'll live with the oddity. @end{Reason} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of subprogram renaming declarations:} @begin{Example} @key[procedure] My_Write(C : @key[in] Character) @key[renames] Pool(K).Write; --@RI{ see @RefSecNum{Selected Components}} @key[function] Real_Plus(Left, Right : Real ) @key[return] Real @key[renames] "+"; @key[function] Int_Plus (Left, Right : Integer) @key[return] Integer @key[renames] "+"; @key[function] Rouge @key[return] Color @key[renames] Red; --@RI{ see @RefSecNum{Enumeration Types}} @key[function] Rot @key[return] Color @key[renames] Red; @key[function] Rosso @key[return] Color @key[renames] Rouge; @key[function] Next(X : Color) @key[return] Color @key[renames] Color'Succ; --@RI{ see @RefSecNum{Enumeration Types}} @end{Example} @begin{Wide} @leading@keepnext@i{Example of a subprogram renaming declaration with new parameter names:} @end{Wide} @begin{Example} @key[function] "*" (X,Y : Vector) @key[return] Real @key[renames] Dot_Product; --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @begin{Wide} @leading@keepnext@i{Example of a subprogram renaming declaration with a new default expression:} @end{Wide} @begin{Example} @key[function] Minimum(L : Link := Head) @key[return] Cell @key[renames] Min_Cell; --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0028],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b<Corrigendum:> Allowed a renaming-as-body to be just mode conformant with the specification if the subprogram is not yet frozen.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@nt{Overriding_indicator} (see @RefSecNum{Overriding Indicators}) is optionally added to subprogram renamings.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Described the semantics of renaming-as-body, so that the location of elaboration checks is clear.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that circular renaming-as-body is illegal (if it can be detected in time) or a bounded error.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Clarified that renaming a shall-be-overridden subprogram is illegal, as well as renaming-as-body an abstract subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[Added matching rules for @nt{null_exclusion}s.]} @end{DiffWord95} @LabeledSubClause{Generic Renaming Declarations} @begin{Intro} @redundant[A @nt{generic_renaming_declaration} is used to rename a generic unit.] @end{Intro} @begin{Syntax} @Syn{tabs=[P22], lhs=<generic_renaming_declaration>,rhs=" @key{generic package}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_package_}@Syn2{name}; | @key{generic procedure}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_procedure_}@Syn2{name}; | @key{generic function}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_function_}@Syn2{name};"} @end{Syntax} @begin{Legality} The renamed entity shall be a generic unit of the corresponding kind. @end{Legality} @begin{StaticSem} A @nt{generic_renaming_declaration} declares a new view @Redundant{of the renamed generic unit}. @end{StaticSem} @begin{Notes} Although the properties of the new view are the same as those of the renamed view, the place where the @nt<generic_renaming_declaration> occurs may affect the legality of subsequent renamings and instantiations that denote the @nt<generic_renaming_declaration>, in particular if the renamed generic unit is a library unit (see @RefSecNum{Compilation Units - Library Units}). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of renaming a generic unit:} @begin{Example} @key[generic package] Enum_IO @key[renames] Ada.Text_IO.Enumeration_IO; @RI{-- see @RefSecNum{Input-Output for Enumeration Types}} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Renaming of generic units is new to Ada 95. It is particularly important for renaming child library units that are generic units. For example, it might be used to rename Numerics.Generic_Elementary_Functions as simply Generic_Elementary_Functions, to match the name for the corresponding Ada-83-based package. @end{Extend83} @begin{DiffWord83} The information in RM83-8.6, @lquotes@;The Package Standard,@rquotes@; has been updated for the child unit feature, and moved to @RefSecNum{Predefined Language Environment}, except for the definition of @lquotes@;predefined type,@rquotes@; which has been moved to @RefSecNum{Type Declarations}. @end{DiffWord83} @LabeledClause{The Context of Overload Resolution} @begin{Intro} @redundant[@Defn{overload resolution} Because declarations can be overloaded, it is possible for an occurrence of a usage name to have more than one possible interpretation; in most cases, ambiguity is disallowed. This clause describes how the possible interpretations resolve to the actual interpretation. @Defn{overloading rules} Certain rules of the language (the @ResolutionTitle) are considered @lquotes@;overloading rules@rquotes@;. If a possible interpretation violates an overloading rule, it is assumed not to be the intended interpretation; some other possible interpretation is assumed to be the actual interpretation. On the other hand, violations of non-overloading rules do not affect which interpretation is chosen; instead, they cause the construct to be illegal. To be legal, there usually has to be exactly one acceptable interpretation of a construct that is a @lquotes@;complete context@rquotes@;, not counting any nested complete contexts. @Defn2{Term=[grammar],Sec=(resolution of ambiguity)} The syntax rules of the language and the visibility rules given in @RefSecNum{Visibility} determine the possible interpretations. Most type checking rules (rules that require a particular type, or a particular class of types, for example) are overloading rules. Various rules for the matching of formal and actual parameters are overloading rules.] @end{Intro} @begin{MetaRules} The type resolution rules are intended to minimize the need for implicit declarations and preference rules associated with implicit conversion and dispatching operations. @end{MetaRules} @begin{Resolution} @leading@Defn{complete context} @Redundant{Overload resolution is applied separately to each @i{complete context}, not counting inner complete contexts.} Each of the following constructs is a @i{complete context}: @begin{itemize} A @nt{context_item}. A @nt{declarative_item} or declaration. @begin{Ramification} A @nt{loop_parameter_specification} is a declaration, and hence a complete context. @end{Ramification} A @nt{statement}. A @nt{pragma_argument_association}. @begin{Reason} We would make it the whole @nt{pragma}, except that certain pragma arguments are allowed to be ambiguous, and ambiguity applies to a complete context. @end{Reason} The @nt{expression} of a @nt{case_statement}. @begin{Ramification} This means that the @nt{expression} is resolved without looking at the choices. @end{Ramification} @end{itemize} @leading@Defn2{Term=[interpretation], Sec=(of a complete context)} @Defn2{Term=[overall interpretation], Sec=(of a complete context)} An (overall) @i{interpretation} of a complete context embodies its meaning, and includes the following information about the constituents of the complete context, not including constituents of inner complete contexts: @begin{Itemize} for each constituent of the complete context, to which syntactic categories it belongs, and by which syntax rules; and @begin{Ramification} Syntactic categor@i{ies} is plural here, because there are lots of trivial productions @em an @nt{expression} might also be all of the following, in this order: @nt{identifier}, @nt{name}, @nt{primary}, @nt{factor}, @nt{term}, @nt{simple_expression}, and @nt{relation}. Basically, we're trying to capture all the information in the parse tree here, without using compiler-writer's jargon like @lquotes@;parse tree@rquotes@;. @end{Ramification} for each usage name, which declaration it denotes (and, therefore, which view and which entity it denotes); and @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} In most cases, a usage name denotes the view declared by the denoted declaration. However, in certain cases, a usage name that denotes a declaration and appears inside the declarative region of that same declaration, denotes the current instance of the declaration. For example, within a @nt{task_body}@Chg{Version=[2],New=[ other than in an @nt{access_definition}],Old=[]}, a usage name that denotes the @nt{task_type_declaration} denotes the object containing the currently executing task, and not the task type declared by the declaration. @end{Ramification} for a complete context that is a @nt{declarative_item}, whether or not it is a completion of a declaration, and (if so) which declaration it completes. @end{Itemize} @begin{Ramification} Unfortunately, we are not confident that the above list is complete. We'll have to live with that. @end{Ramification} @begin{Honest} For @lquotes@;possible@rquotes@; interpretations, the above information is tentative. @end{Honest} @begin{Discussion} A possible interpretation (an @i{input} to overload resolution) contains information about what a usage name @i{might} denote, but what it actually @i{does} denote requires overload resolution to determine. Hence the term @lquotes@;tentative@rquotes@; is needed for possible interpretations; otherwise, the definition would be circular. @end{Discussion} @Defn{possible interpretation} A @i{possible interpretation} is one that obeys the syntax rules and the visibility rules. @Defn{acceptable interpretation} @Defn2{Term=[resolve],Sec=(overload resolution)} @Defn2{Term=[interpretation],Sec=(overload resolution)} An @i{acceptable interpretation} is a possible interpretation that obeys the @i{overloading rules}@Redundant{, that is, those rules that specify an expected type or expected profile, or specify how a construct shall @i(resolve) or be @i(interpreted).} @begin{Honest} One rule that falls into this category, but does not use the above-mentioned magic words, is the rule about numbers of parameter associations in a call (see @RefSecNum{Subprogram Calls}). @end{Honest} @begin{Ramification} The @ResolutionName@;s are the ones that appear under the @ResolutionTitle heading. Some @SyntaxName@;s are written in English, instead of BNF. No rule is a @SyntaxName or @ResolutionName unless it appears under the appropriate heading. @end{Ramification} @Defn2{Term=[interpretation], Sec=(of a constituent of a complete context)} The @i{interpretation} of a constituent of a complete context is determined from the overall interpretation of the complete context as a whole. @Redundant{Thus, for example, @lquotes@;interpreted as a @nt{function_call},@rquotes@; means that the construct's interpretation says that it belongs to the syntactic category @nt{function_call}.} @leading@Defn{denote} @Redundant[Each occurrence of] a usage name @i{denotes} the declaration determined by its interpretation. It also denotes the view declared by its denoted declaration, except in the following cases: @begin{Ramification} As explained below, a pragma argument is allowed to be ambiguous, so it can denote several declarations, and all of the views declared by those declarations. @end{Ramification} @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Defn2{Term=[current instance], Sec=(of a type)} If a usage name appears within the declarative region of a @nt{type_declaration} and denotes that same @nt{type_declaration}, then it denotes the @i{current instance} of the type (rather than the type itself)@Chg{Version=[2],New=[; the],Old=[. The]} current instance of a type is the object or value of the type that is associated with the execution that evaluates the usage name.@Chg{Version=[2],New=[ This rule does not apply if the usage name appears within the @nt{subtype_mark} of an @nt{access_definition} for an access-to-object type, or within the subtype of a parameter or result of an access-to-subprogram type.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} This is needed, for example, for references to the Access attribute from within the @nt{type_declaration}. Also, within a @nt{task_body} or @nt{protected_body}, we need to be able to denote the current task or protected object. (For a @nt{single_task_declaration} or @nt{single_protected_declaration}, the rule about current instances is not needed.)@Chg{Version=[2],New=[ We exclude anonymous access types so that they can be used to create self-referencing types in the natural manner (otherwise such types would be illegal).],Old=[]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[The phrase @lquotes@;within the @nt{subtype_mark}@rquotes@; in the @lquotes@;this rule does not apply@rquotes@; part is intended to cover a case like @key{access} T'Class appearing within the declarative region of T: here T denotes the type, not the current instance.]} @end{Discussion} @Defn2{Term=[current instance], Sec=(of a generic unit)} If a usage name appears within the declarative region of a @nt{generic_declaration} (but not within its @nt{generic_formal_part}) and it denotes that same @nt{generic_declaration}, then it denotes the @i{current instance} of the generic unit (rather than the generic unit itself). See also @RefSecNum{Generic Instantiation}. @begin{Honest} The current instance of a generic unit is the instance created by whichever @nt{generic_instantiation} is of interest at any given time. @end{Honest} @begin{Ramification} Within a @nt{generic_formal_part}, a @nt{name} that denotes the @nt{generic_declaration} denotes the generic unit, which implies that it is not overloadable. @end{Ramification} @end(itemize) A usage name that denotes a view also denotes the entity of that view. @begin{Ramification} Usually, a usage name denotes only one declaration, and therefore one view and one entity. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @leading@RootDefn[expected type] The @i(expected type) for a given @nt<expression>, @nt<name>, or other construct determines, according to the @i{type resolution rules} given below, the types considered for the construct during overload resolution. @Defn{type resolution rules} @Redundant[ The type resolution rules provide support for class-wide programming, universal @Chg{Version=[2],New=[],Old=[numeric ]}literals, dispatching operations, and anonymous access types:] @begin{Ramification} Expected types are defined throughout the RM95. The most important definition is that, for a subprogram, the expected type for the actual parameter is the type of the formal parameter. The type resolution rules are trivial unless either the actual or expected type is universal, class-wide, or of an anonymous access type. @end{Ramification} @begin{Itemize} @PDefn2{Term=[type resolution rules], Sec=(if any type in a specified class of types is expected)} @PDefn2{Term=[type resolution rules], Sec=(if expected type is universal or class-wide)} If a construct is expected to be of any type in a class of types, or of the universal or class-wide type for a class, then the type of the construct shall resolve to a type in that class or to a universal type that covers the class. @begin{Ramification} This matching rule handles (among other things) cases like the Val attribute, which denotes a function that takes a parameter of type @i(universal_integer). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00021 - Quoted text doesn't match} The last part of the rule, @lquotes@;or to a universal type that @Chg{New=[covers],Old=[includes]} the class@rquotes implies that if the expected type for an expression is @i{universal_fixed}, then an expression whose type is @i{universal_real} (such as a real literal) is OK. @end{Ramification} @leading@PDefn2{Term=[type resolution rules], Sec=(if expected type is specific)} If the expected type for a construct is a specific type @i(T), then the type of the construct shall resolve either to @i(T), or: @begin{Ramification} @PDefn{Beaujolais effect} This rule is @i{not} intended to create a preference for the specific type @em such a preference would cause Beaujolais effects. @end{Ramification} @begin(Inneritemize) to @i(T)'Class; or @begin{Ramification} This will only be legal as part of a call on a dispatching operation; see @RefSec(Dispatching Operations of Tagged Types). Note that that rule is not a @ResolutionName. @end{Ramification} to a universal type that covers @i(T); or @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} when @i(T) is @Chg{Version=[2],New=[a specific],Old=[an]} anonymous access@Chg{Version=[2],New=[-to-object],Old=[]} type (see @RefSecNum{Access Types}) with designated type @i(D), to an access-to-@Chg{Version=[2],New=[object],Old=[variable]} type whose designated type is @i(D)'Class or is covered by @i(D)@Chg{Version=[2],New=[; or],Old=[.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00409-01]} @ChgNote{We use Chg here, rather than ChgDeleted so that the prefix is left behind.}@Chg{Version=[2],New=[],Old=[Because it says @lquotes@;access-to-variable@rquotes@; instead of @lquotes@;access-to-object,@rquotes@; two subprograms that differ only in that one has a parameter of an access-to-constant type, and the other has an access parameter, are distinguishable during overload resolution.]} The case where the actual is access-to-@i(D)'Class will only be legal as part of a call on a dispatching operation; see @RefSec(Dispatching Operations of Tagged Types). Note that that rule is not a @ResolutionName. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[when @i(T) is an anonymous access-to-subprogram type (see @RefSecNum{Access Types}), to an access-to-subprogram type whose designated profile is type-conformant with that of @i{T}.]} @end(Inneritemize) @end{Itemize} @RootDefn[expected profile] In certain contexts, @Redundant[such as in a @nt{subprogram_renaming_declaration},] the @ResolutionTitle define an @i(expected profile) for a given @nt<name>; @Defn2{Term=[profile resolution rule], Sec=(@nt<name> with a given expected profile)} in such cases, the @nt{name} shall resolve to the name of a callable entity whose profile is type conformant with the expected profile. @Defn2{Term=[type conformance],Sec=(required)} @begin{Ramification} The parameter and result @i{sub}types are not used in overload resolution. Only type conformance of profiles is considered during overload resolution. Legality rules generally require at least mode-conformance in addition, but those rules are not used in overload resolution. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00332-01]} @Defn2{Term=[single], Sec=[class expected type]} When @Chg{Version=[2],New=[],Old=[the expected type for ]}a construct is @Chg{Version=[2],New=[one that requires that its expected type], Old=[required to]} be a @i<single> type in a given class, the type @Chg{Version=[2],New=[of],Old=[expected for]} the construct shall be determinable solely from the context in which the construct appears, excluding the construct itself, but using the requirement that it be in the given class@Chg{Version=[2], New=[],Old=[; the type of the construct is then this single expected type]}. Furthermore, the context shall not be one that expects any type in some class that contains types of the given class; in particular, the construct shall not be the operand of a @nt{type_conversion}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}@ChgNote{Null no longer requires a single type} For example, the expected type for @Chg{Version=[2],New=[a string literal], Old=[the literal @key{null}]} is required to be a single @Chg{Version=[2],New=[string],Old=[access]} type. But the expected type for the operand of a @nt{type_conversion} is any type. Therefore, @Chg{Version=[2],New=[a string literal], Old=[the literal @key{null}]} is not allowed as the operand of a @nt{type_conversion}. This is true even if there is only one @Chg{Version=[2],New=[string], Old=[access]} type in scope@Chg{Version=[2],New=[ (which is never the case)],Old=[]}. The reason for these rules is so that the compiler will not have to search @lquotes@;everywhere@rquotes@; to see if there is exactly one type in a class in scope. @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00332-01]} @ChgAdded{Version=[2],Text=[The first sentence is carefully worded so that it only mentions @lquotes@;expected type@rquotes as part of identifying the interesting case, but doesn't require that the context actually provide such an expected type. This allows such constructs to be used inside of constructs that don't provide an expected type (like qualified expressions and renames). Otherwise, such constructs wouldn't allow @nt{aggregate}s, 'Access, and so on.]} @end{Discussion} A complete context shall have at least one acceptable interpretation; if there is exactly one, then that one is chosen. @begin{Ramification} This, and the rule below about ambiguity, are the ones that suck in all the @SyntaxName@;s and @ResolutionName@;s as compile-time rules. Note that this and the ambiguity rule have to be @LegalityName@;s. @end{Ramification} @Defn2{Term=[preference], Sec=(for root numeric operators and @nt<range>s)} There is a @i{preference} for the primitive operators (and @nt<range>s) of the root numeric types @i{root_integer} and @i{root_real}. In particular, if two acceptable interpretations of a constituent of a complete context differ only in that one is for a primitive operator (or @nt<range>) of the type @i{root_integer} or @i{root_real}, and the other is not, the interpretation using the primitive operator (or @nt<range>) of the root numeric type is @i{preferred}. @begin{Reason} @leading@;The reason for this preference is so that expressions involving literals and named numbers can be unambiguous. For example, without the preference rule, the following would be ambiguous: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00022} N : @key[constant] := 123; @key[if] N > 100 @key[then] --@RI{ Preference for root_integer "@Chg{New=[>],Old=[<]}" operator.} ... @key[end] @key[if]; @end{Example} @end{Reason} For a complete context, if there is exactly one overall acceptable interpretation where each constituent's interpretation is the same as or preferred (in the above sense) over those in all other overall acceptable interpretations, then that one overall acceptable interpretation is chosen. @Defn{ambiguous} Otherwise, the complete context is @i{ambiguous}. A complete context other than a @nt{pragma_argument_association} shall not be ambiguous. A complete context that is a @nt{pragma_argument_association} is allowed to be ambiguous (unless otherwise specified for the particular pragma), but only if every acceptable interpretation of the pragma argument is as a @nt{name} that statically denotes a callable entity. @PDefn2{Term=[denote],Sec=(name used as a pragma argument)} Such a @nt{name} denotes all of the declarations determined by its interpretations, and all of the views declared by these declarations. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]}@ChgNote{Pragma is obsolete} This applies to Inline, Suppress, Import, Export, and Convention @nt{pragma}s. For example, it is OK to say @lquotes@;@key[pragma] @Chg{Version=[2], New=[Export(C, Entity_Name],Old=[Suppress(Elaboration_Check, On]} => P.Q);@rquotes@;, even if there are two directly visible P's, and there are two Q's declared in the visible part of each P. In this case, P.Q denotes four different declarations. This rule also applies to certain pragmas defined in the Specialized Needs Annexes. It almost applies to Pure, Elaborate_Body, and Elaborate_All @nt{pragma}s, but those can't have overloading for other reasons. Note that if a pragma argument denotes a @i{call} to a callable entity, rather than the entity itself, this exception does not apply, and ambiguity is disallowed. Note that we need to carefully define which pragma-related rules are @ResolutionName@;s, so that, for example, a @nt{pragma} Inline does not pick up subprograms declared in enclosing declarative regions, and therefore make itself illegal. We say @lquotes@;statically denotes@rquotes@; in the above rule in order to avoid having to worry about how many times the @nt{name} is evaluated, in case it denotes more than one callable entity. @end{Ramification} @end{Legality} @begin{Notes} If a usage name has only one acceptable interpretation, then it denotes the corresponding entity. However, this does not mean that the usage name is necessarily legal since other requirements exist which are not considered for overload resolution; for example, the fact that an expression is static, whether an object is constant, mode and subtype conformance rules, freezing rules, order of elaboration, and so on. @NoPrefix@;Similarly, subtypes are not considered for overload resolution (the violation of a constraint does not make a program illegal but raises an exception during program execution). @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} @PDefn{Beaujolais effect} The new preference rule for operators of root numeric types is upward incompatible, but only in cases that involved @i(Beaujolais) effects in Ada 83. Such cases are ambiguous in Ada 95. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The rule that allows an expected type to match an actual expression of a universal type, in combination with the new preference rule for operators of root numeric types, subsumes the Ada 83 "implicit conversion" rules for universal types. @end{Extend83} @begin{DiffWord83} In Ada 83, it is not clear what the @lquotes@;syntax rules@rquotes@; are. AI83-00157 states that a certain textual rule is a syntax rule, but it's still not clear how one tells in general which textual rules are syntax rules. We have solved the problem by stating exactly which rules are syntax rules @em the ones that appear under the @lquotes@;@SyntaxTitle@rquotes@; heading. RM83 has a long list of the @lquotes@;forms@rquotes@; of rules that are to be used in overload resolution (in addition to the syntax rules). It is not clear exactly which rules fall under each form. We have solved the problem by explicitly marking all rules that are used in overload resolution. Thus, the list of kinds of rules is unnecessary. It is replaced with some introductory (intentionally vague) text explaining the basic idea of what sorts of rules are overloading rules. It is not clear from RM83 what information is embodied in a @lquotes@;meaning@rquotes@; or an @lquotes@;interpretation.@rquotes@; @lquotes@;Meaning@rquotes@; and @lquotes@;interpretation@rquotes@; were intended to be synonymous; we now use the latter only in defining the rules about overload resolution. @lquotes@;Meaning@rquotes@; is used only informally. This clause attempts to clarify what is meant by @lquotes@;interpretation.@rquotes@; @NoPrefix@;For example, RM83 does not make it clear that overload resolution is required in order to match @ntf{subprogram_bodies} with their corresponding declarations (and even to tell whether a given @nt{subprogram_body} is the completion of a previous declaration). Clearly, the information needed to do this is part of the @lquotes@;interpretation@rquotes@; of a @nt{subprogram_body}. The resolution of such things is defined in terms of the @lquotes@;expected profile@rquotes@; concept. Ada 95 has some new cases where expected profiles are needed @em the resolution of P'Access, where P might denote a subprogram, is an example. @Leading@NoPrefix@;RM83-8.7(2) might seem to imply that an interpretation embodies information about what is denoted by each usage name, but not information about which syntactic category each construct belongs to. However, it seems necessary to include such information, since the Ada grammar is highly ambiguous. For example, X(Y) might be a @nt{function_call} or an @nt{indexed_component}, and no context-free/syntactic information can tell the difference. It seems like we should view X(Y) as being, for example, @lquotes@;interpreted as a @nt{function_call}@rquotes@; (if that's what overload resolution decides it is). Note that there are examples where the denotation of each usage name does not imply the syntactic category. However, even if that were not true, it seems that intuitively, the interpretation includes that information. Here's an example: @begin{Example} @key[type] T; @key[type] A @key[is] @key[access] T; @key[type] T @key[is] @key[array](Integer @key[range] 1..10) @key[of] A; I : Integer := 3; @key[function] F(X : Integer := 7) @key[return] A; Y : A := F(I); --@RI{ Ambiguous? (We hope so.)} @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @NoPrefix@;Consider the declaration of Y (a complete context). In the above example, overload resolution can easily determine the declaration, and therefore the entity, denoted by Y, A, F, and I. However, given all of that information, we still don't know whether F(I) is a @nt{function_call} or an @nt{indexed_component} whose @Chg{New=[@nt{prefix}],Old=[prefix]} is a @nt{function_call}. (In the latter case, it is equivalent to F(7).@key[all](I).) @NoPrefix@;It seems clear that the declaration of Y ought to be considered ambiguous. We describe that by saying that there are two interpretations, one as a @nt{function_call}, and one as an @nt{indexed_component}. These interpretations are both acceptable to the overloading rules. Therefore, the complete context is ambiguous, and therefore illegal. @PDefn{Beaujolais effect} It is the intent that the Ada 95 preference rule for root numeric operators is more locally enforceable than that of RM83-4.6(15). It should also eliminate interpretation shifts due to the addition or removal of a @nt{use_clause} (the so called @i{Beaujolais} effect). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} RM83-8.7 seems to be missing some complete contexts, such as @nt{pragma_argument_association}s, @nt{declarative_item}s that are not declarations or @Chg{Version=[2],New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]}, and @nt{context_item}s. We have added these, and also replaced the @lquotes@;must be determinable@rquotes@; wording of RM83-5.4(3) with the notion that the expression of a @nt{case_statement} is a complete context. Cases like the Val attribute are now handled using the normal type resolution rules, instead of having special cases that explicitly allow things like @lquotes@;any integer type.@rquotes@; @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} Ada 95 allowed name resolution to distinguish between anonymous access-to-variable and access-to-constant types. This is similar to distinguishing between subprograms with @key{in} and @key{in out} parameters, which is known to be bad. Thus, that part of the rule was dropped as we now have anonymous access-to-constant types, making this much more likely.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Cacc @key{is access constant} Integer; @key{procedure} Proc (Acc : @key{access} Integer) ... @key{procedure} Proc (Acc : Cacc) ... List : Cacc := ...; Proc (List); -- @RI[OK in Ada 95, ambiguous in Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If there is any code like this (such code should be rare), it will be ambiguous in Ada 2005.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Generalized the anonymous access resolution rules to support the new capabilities of anonymous access types (that is, access-to-subprogram and access-to-constant).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[We now allow the creation of self-referencing types via anonymous access types. This is an extension in unusual cases involving task and protected types. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{task type} T;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{task body} T @key{is} @key{procedure} P (X : @key{access} T) @key{is} -- @RI[Illegal in Ada 95, legal in Ada 2005] ... @key{end} P; @key{begin} ... @key{end} T;]} @end{Example} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00332-01]} @ChgAdded{Version=[2],Text=[Corrected the @lquotes@;single expected type@rquotes@; so that it works in contexts that don't have expected types (like object renames and qualified expressions). This fixes a hole in Ada 95 that appears to prohibit using @nt{aggregate}s, 'Access, character literals, string literals, and @nt{allocator}s in qualified expressions.]} @end{DiffWord95} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/09.mss���������������������������������������������������������������0000755�0001752�0001001�00000674042�12273462240�016412� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(09, Root="ada.mss") @Comment{$Date: 2006/11/09 06:29:48 $} @LabeledSection{Tasks and Synchronization} @Comment{$Source: e:\\cvsroot/ARM/Source/09.mss,v $} @Comment{$Revision: 1.84 $} @begin{Intro} @PDefn2{Term=[execution], Sec=(Ada program)} The execution of an Ada program consists of the execution of one or more @i(tasks). @Defn{task} @Defn2{Term=[interaction], Sec=(between tasks)} Each task represents a separate thread of control that proceeds independently and concurrently between the points where it @i(interacts) with other tasks. The various forms of task interaction are described in this section, and include: @IndexSee{Term=[parallel processing],See=(task)} @Defn{synchronization} @IndexSee{Term=[concurrent processing],See=(task)} @IndexSeeAlso{Term=[intertask communication],See=(task)} @begin(Honest) The execution of an Ada program consists of the execution of one or more partitions (see @RefSecNum(Program Execution)), each of which in turn consists of the execution of an environment task and zero or more subtasks. @end(Honest) @begin(itemize) the activation and termination of a task; @Defn{protected object} a call on a protected subprogram of a @i(protected object), providing exclusive read-write access, or concurrent read-only access to shared data; a call on an entry, either of another task, allowing for synchronous communication with that task, or of a protected object, allowing for asynchronous communication with one or more other tasks using that same protected object; a timed operation, including a simple delay statement, a timed entry call or accept, or a timed asynchronous select statement (see next item); an asynchronous transfer of control as part of an asynchronous select statement, where a task stops what it is doing and begins execution at a different point in response to the completion of an entry call or the expiration of a delay; an abort statement, allowing one task to cause the termination of another task. @end(itemize) In addition, tasks can communicate indirectly by reading and updating (unprotected) shared variables, presuming the access is properly synchronized through some other kind of task interaction. @end{Intro} @begin{StaticSem} @Defn{task unit} The properties of a task are defined by a corresponding task declaration and @nt<task_body>, which together define a program unit called a @i(task unit). @end{StaticSem} @begin{RunTime} Over time, tasks proceed through various @i(states). @PDefn2{Term=[task state], Sec=(inactive)} @Defn2{Term=[inactive], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(blocked)} @Defn2{Term=[blocked], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(ready)} @Defn2{Term=[ready], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(terminated)} @Defn2{Term=[terminated], Sec=(a task state)} A task is initially @i(inactive); upon activation, and prior to its @i{termination} it is either @i(blocked) (as part of some task interaction) or @i(ready) to run. @Defn2{Term=[execution resource], Sec=(required for a task to run)} While ready, a task competes for the available @i(execution resources) that it requires to run. @begin(Discussion) @Defn{task dispatching policy} @Defn{dispatching policy for tasks} The means for selecting which of the ready tasks to run, given the currently available execution resources, is determined by the @i(task dispatching policy) in effect, which is generally implementation defined, but may be controlled by pragmas and operations defined in the Real-Time Annex (see @RefSecNum(Priority Scheduling) and @RefSecNum(Dynamic Priorities)). @end(Discussion) @end{RunTime} @begin{Notes} Concurrent task execution may be implemented on multicomputers, multiprocessors, or with interleaved execution on a single physical processor. On the other hand, whenever an implementation can determine that the required semantic effects can be achieved when parts of the execution of a given task are performed by different physical processors acting in parallel, it may choose to perform them in this way. @end{Notes} @begin{DiffWord83} The introduction has been rewritten. We use the term "concurrent" rather than "parallel" when talking about logically independent execution of threads of control. The term "parallel" is reserved for referring to the situation where multiple physical processors run simultaneously. @end{DiffWord83} @LabeledClause{Task Units and Task Objects} @begin{Intro} @Defn{task declaration} A task unit is declared by a @i(task declaration), which has a corresponding @nt<task_body>. A task declaration may be a @nt<task_type_declaration>, in which case it declares a named task type; alternatively, it may be a @nt<single_task_declaration>, in which case it defines an anonymous task type, as well as declaring a named task object of that type. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<task_type_declaration>,rhs=" @key{task} @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}] [@key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{task_definition}];"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00399-01]} @Syn{lhs=<single_task_declaration>,rhs=" @key{task} @Syn2{defining_identifier} [@key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{task_definition}];"} @Syn{lhs=<task_definition>,rhs=" {@Syn2{task_item}} [ @key{private} {@Syn2{task_item}}] @key{end} [@SynI{task_}@Syn2{identifier}]"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<task_item>,rhs="@Syn2{entry_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @Softpage @Syn{lhs=<task_body>,rhs=" @key{task} @key{body} @Syn2{defining_identifier} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{task_}@Syn2{identifier}];"} @begin{SyntaxText} If a @SynI{task_}@nt{identifier} appears at the end of a @nt{task_definition} or @nt{task_body}, it shall repeat the @nt{defining_identifier}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00345-01]}@ChgNote{This was just moved below} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{@nt{task_declaration}})} A task declaration requires a completion@redundant[, which shall be a @nt{task_body},] and every @nt{task_body} shall be the completion of some task declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @end{Legality} @begin{StaticSem} A @nt<task_definition> defines a task type and its first subtype. @PDefn2{Term=[visible part], Sec=(of a task unit)} The first list of @nt{task_item}s of a @nt{task_@!definition}, together with the @nt{known_@!discriminant_@!part}, if any, is called the visible part of the task unit. @Redundant[@PDefn2{Term=[private part], Sec=(of a task unit)} The optional list of @nt{task_item}s after the reserved word @key{private} is called the private part of the task unit.] @begin{TheProof} Private part is defined in Section 8. @end{theproof} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0029],ARef=[AI95-00116-01]} @ChgAdded{Version=[1],Text=[For a task declaration without a @nt{task_definition}, a @nt{task_definition} without @nt{task_item}s is assumed.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[For a task declaration with an @nt{interface_list}, the task type inherits user-defined primitive subprograms from each progenitor type (see @RefSecNum{Interface Types}), in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}). If the first parameter of a primitive inherited subprogram is of the task type or an access parameter designating the task type, and there is an @nt{entry_declaration} for a single entry with the same identifier within the task declaration, whose profile is type conformant with the prefixed view profile of the inherited subprogram, the inherited subprogram is said to be @i{implemented} by the conforming task entry.@PDefn2{Term=[implemented], Sec=[by a task entry]}@Defn2{Term=[type conformance],Sec=(required)}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inherited subprograms can only come from an interface given as part of the task declaration.]} @end{Ramification} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]}@ChgNote{This was just moved, not changed} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{@nt{task_declaration}})} A task declaration requires a completion@redundant[, which shall be a @nt{task_body},] and every @nt{task_body} shall be the completion of some task declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Text=[@Redundant[Each @i{interface_}@nt{subtype_mark} of an @nt{interface_list} appearing within a task declaration shall denote a limited interface type that is not a protected interface.]]} @begin(TheProof) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@RefSecNum{Interface Types} requires that an @nt{interface_list} only name interface types, and limits the descendants of the various kinds of interface types. Only a limited, task, or synchronized interface can have a task type descendant. Nonlimited or protected interfaces are not allowed, as they offer operations that a task does not have.]} @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[The prefixed view profile of an explicitly declared primitive subprogram of a tagged task type shall not be type conformant with any entry of the task type, if the first parameter of the subprogram is of the task type or is an access parameter designating the task type.]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the existence of two operations with the same name and profile which could be called with a prefixed view. If the operation was inherited, this would be illegal by the following rules; this rule puts inherited and non-inherited routines on the same footing. Note that this only applies to tagged task types (that is, those with an interface in their declaration); we do that as there is no problem with prefixed view calls of primitive operations for @lquotes@;normal@rquotes task types, and having this rule apply to all tasks would be incompatible with Ada 95.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each primitive subprogram inherited by the type declared by a task declaration, at most one of the following shall apply:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is overridden with a primitive subprogram of the task type, in which case the overriding subprogram shall be subtype conformant with the inherited subprogram and not abstract; or@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is implemented by a single entry of the task type; in which case its prefixed view profile shall be subtype conformant with that of the task entry. @Defn2{Term=[subtype conformance],Sec=(required)}]} @begin(Ramification) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An entry may implement two subprograms from the ancestors, one whose first parameter is of type @i<T> and one whose first parameter is of type @key{access} @i{T}. That doesn't cause implementation problems because @lquotes@;implemented by@rquotes (unlike @lquotes@;overridden@rquote) probably entails the creation of wrappers.]} @end(Ramification) @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If neither applies, the inherited subprogram shall be a null procedure. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each inherited subprogram can only have a single implementation (either from overriding a subprogram or implementing an entry), and must have an implementation unless the subprogram is a null procedure.]} @end{Reason} @end{Legality} @begin{RunTime} @redundant[@PDefn2{Term=[elaboration], Sec=(task declaration)} The elaboration of a task declaration elaborates the @nt<task_definition>. @PDefn2{Term=[elaboration], Sec=(single_task_declaration)} The elaboration of a @nt<single_@!task_@!declaration> also creates an object of an (anonymous) task type.] @begin(TheProof) This is redundant with the general rules for the elaboration of a @nt<full_type_declaration> and an @nt<object_declaration>. @end(TheProof) @PDefn2{Term=[elaboration], Sec=(task_definition)} @Redundant[The elaboration of a @nt<task_definition> creates the task type and its first subtype;] it also includes the elaboration of the @nt<entry_declaration>s in the given order. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @PDefn2{Term=[initialization], Sec=(of a task object)} As part of the initialization of a task object, any @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} and any per-object constraints associated with @nt<entry_@!declaration>s of the corresponding @nt<task_@!definition> are elaborated in the given order. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} The only @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} defined for task entries are ones that specify the Address of an entry, as part of defining an interrupt entry. These clearly need to be elaborated per-object, not per-type. Normally the address will be a function of a discriminant, if such an Address clause is in a task type rather than a single task declaration, though it could rely on a parameterless function that allocates sequential interrupt vectors. We do not mention representation pragmas, since each pragma may have its own elaboration rules. @end{Reason} @PDefn2{Term=[elaboration], Sec=(task_body)} The elaboration of a @nt{task_body} has no effect other than to establish that tasks of the type can from then on be activated without failing the Elaboration_Check. @redundant[The execution of a @nt<task_body> is invoked by the activation of a task of the corresponding type (see @RefSecNum(Task Execution - Task Activation)).] @leading@;The content of a task object of a given task type includes: @begin(itemize) The values of the discriminants of the task object, if any; An entry queue for each entry of the task object; @begin(Ramification) "For each entry" implies one queue for each single entry, plus one for each entry of each entry family. @end(Ramification) A representation of the state of the associated task. @end(itemize) @end{RunTime} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[Other than in an @nt{access_definition}, the name of a task unit within],Old=[Within]} the declaration or body of @Chg{Version=[2],New=[the],Old=[a]} task unit@Chg{Version=[2],New=[],Old=[, the name of the task unit]} denotes the current instance of the unit (see @RefSecNum(The Context of Overload Resolution)), rather than the first subtype of the corresponding task type (and thus the name cannot be used as a @nt<subtype_mark>). @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[It can be used as a @nt{subtype_mark} in an anonymous access type. In addition],Old=[However]}, it is possible to refer to some other subtype of the task type within its body, presuming such a subtype has been declared between the @nt<task_type_declaration> and the @nt<task_body>. @end(Discussion) The notation of a @nt<selected_component> can be used to denote a discriminant of a task (see @RefSecNum(Selected Components)). Within a task unit, the name of a discriminant of the task type denotes the corresponding discriminant of the current instance of the unit. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A task type is a limited type (see @RefSecNum(Limited Types)), and hence @Chg{Version=[2],New=[precludes use of @nt{assignment_statement}s and], Old=[has neither an assignment operation nor]} predefined equality operators. If an application needs to store and exchange task identities, it can do so by defining an access type designating the corresponding task objects and by using access values for identification purposes. Assignment is available for such an access type as for any access type. Alternatively, if the implementation supports the Systems Programming Annex, the Identity attribute can be used for task identification (see @Chg{Version=[2],New=[@RefSecNum(The Package Task_Identification)], Old=[@RefSecNum(Task Information)]}). @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of declarations of task types:} @begin{Example} @key(task) @key(type) Server @key(is) @key(entry) Next_Work_Item(WI : @key(in) Work_Item); @key(entry) Shut_Down; @key(end) Server; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(task) @key(type) Keyboard_Driver(ID : Keyboard_ID := New_ID) @key(is)@Chg{Version=[2],New=[ @key(new) Serial_Device @key(with) --@RI[ see @RefSecNum{Interface Types}]],Old=[]} @key(entry) Read (C : @key(out) Character); @key(entry) Write(C : @key(in) Character); @key(end) Keyboard_Driver; @end{Example} @leading@keepnext@i{Examples of declarations of single tasks:} @begin{Example} @key(task) Controller @key(is) @key(entry) Request(Level)(D : Item); --@RI[ a family of entries] @key(end) Controller; @key(task) Parser @key(is) @key(entry) Next_Lexeme(L : @key(in) Lexical_Element); @key(entry) Next_Action(A : @key(out) Parser_Action); @key(end); @key(task) User; --@RI[ has no entries] @end{Example} @begin{wide} @leading@keepnext@i{Examples of task objects:} @end{wide} @begin{Example} Agent : Server; Teletype : Keyboard_Driver(TTY_ID); Pool : @key(array)(1 .. 10) @key(of) Keyboard_Driver; @end{Example} @begin{wide} @leading@keepnext@i{Example of access type designating task objects:} @end{wide} @begin{Example} @key(type) Keyboard @key(is) @key(access) Keyboard_Driver; Terminal : Keyboard := @key(new) Keyboard_Driver(Term_ID); @end{Example} @end{Examples} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised]} @Defn{extensions to Ada 83} The syntax rules for task declarations are modified to allow a @nt{known_discriminant_part}, and to allow a private part. They are also modified to allow @nt{entry_declaration}s and @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} to be mixed. @end{Extend83} @begin{DiffWord83} The syntax rules for tasks have been split up according to task types and single tasks. In particular: The syntax rules for @ntf{task_declaration} and @ntf{task_specification} are removed. The syntax rules for @nt{task_type_declaration}, @nt{single_task_declaration}, @nt{task_definition} and @nt{task_item} are new. The syntax rule for @nt{task_body} now uses the nonterminal @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{task_body} is now required; that doesn't make any real difference, because a @nt{declarative_part} can be empty. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Task types and single tasks can be derived from one or more interfaces. Entries of the task type can implement the primitive operations of an interface. @nt{Overriding_indicator}s can be used to specify whether or not an entry implements a primitive operation.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0029],ARef=[AI95-00116-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a task type has an implicit empty @nt{task_definition} if none is given.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Revised the note on operations of task types to reflect that limited types do have an assignment operation, but not copying (@nt{assignment_statement}s).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[Revised the note on use of the name of a task type within itself to reflect the exception for anonymous access types.]} @end{DiffWord95} @LabeledClause{Task Execution - Task Activation} @begin{RunTime} @PDefn2{Term=[execution], Sec=(task)} The execution of a task of a given task type consists of the execution of the corresponding @nt{task_body}. @PDefn2{Term=[execution], Sec=(task_body)} @Defn2{Term=[task], Sec=(execution)} @Defn2{Term=[activation], Sec=(of a task)} @Defn2{Term=[task], Sec=(activation)} The initial part of this execution is called the @i(activation) of the task; it consists of the elaboration of the @nt<declarative_part> of the @nt<task_body>. @Defn{activation failure} Should an exception be propagated by the elaboration of its @nt<declarative_part>, the activation of the task is defined to have @i(failed), and it becomes a completed task. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} A task object (which represents one task) can be @Chg{Version=[2],New=[a part of a stand-alone object, of an object created by],Old=[created either as part of the elaboration of an @nt<object_@!declaration> occurring immediately within some declarative region, or as part of the evaluation of]} an @nt{allocator}@Chg{Version=[2],New=[, or of an anonymous object of a limited type, or a coextension of one of these],Old=[]}. All tasks@Chg{Version=[2],New=[ that are part or coextensions of any of the stand-alone objects],Old=[]} created by the elaboration of @nt<object_@!declaration>s@Chg{Version=[2], New=[ (or @nt{generic_association}s of formal objects of mode @key{in})],Old=[]} of a single declarative region@Chg{Version=[2], New=[],Old=[ (including subcomponents of the declared objects)]} are activated together. @Chg{Version=[2],New=[All tasks that are part or coextensions of a single object that is not a stand-alone object are activated together.],Old=[Similarly, all tasks created by the evaluation of a single @nt<allocator> are activated together. The activation of a task is associated with the innermost @nt<allocator> or @nt<object_@!declaration> that is responsible for its creation.]} @begin{Discussion} The initialization of an @nt{object_declaration} or @nt{allocator} can indirectly include the creation of other objects that contain tasks. For example, the default expression for a subcomponent of an object created by an @nt{allocator} might call a function that evaluates a completely different @nt{allocator}. Tasks created by the two allocators are @i{not} activated together. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} For @Chg{Version=[2],New=[the ],Old=[]}tasks@Chg{Version=[2],New=[],Old=[ created by the elaboration of @nt<object_declaration>s]} of a given declarative region, the activations are initiated within the context of the @nt<handled_@!sequence_of_@!statements> (and its associated @nt<exception_@!handler>s if any @em see @RefSecNum{Exception Handlers}), just prior to executing the statements of the @Chg{Version=[2],New=[@nt{handled_sequence_of_statements}], Old=[@ntf<_sequence>]}. @Redundant[For a package without an explicit body or an explicit @nt<handled_@!sequence_of_@!statements>, an implicit body or an implicit @nt<null_@!statement> is assumed, as defined in @RefSecNum(Package Bodies).] @begin(Ramification) If Tasking_Error is raised, it can be handled by handlers of the @nt<handled_@!sequence_of_@!statements>. @end(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} For tasks @Chg{Version=[2],New=[that are part or coextensions of a single object that is not a stand-alone object, activations are initiated after completing any initialization of the outermost object enclosing these tasks, prior to performing any other operation on the outermost object. In particular, for tasks that are part or coextensions of the object ], Old=[]}created by the evaluation of an @nt<allocator>, the activations are initiated as the last step of evaluating the @nt<allocator>, @Chg{Version=[2],New=[],Old=[after completing any initialization for the object created by the @nt<allocator>, and ]}prior to returning the new access value.@Chg{Version=[2],New=[ For tasks that are part or coextensions of an object that is the result of a function call, the activations are not initiated until after the function returns.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The intent is that @lquotes@;temporary@rquotes@; objects with task parts (or coextensions) are treated similarly to an object created by an allocator. The @lquotes@;whole@rquotes@; object is initialized, and then all of the task parts (including the coextensions) are activated together. Each such @lquotes@;whole@rquotes@; object has its own task activation sequence, involving the activating task being suspended until all the new tasks complete their activation.]} @end{Discussion} @Defn2{Term=[activator], Sec=(of a task)} @PDefn2{term=[blocked], Sec=(waiting for activations to complete)} The task that created the new tasks and initiated their activations (the @i(activator)) is blocked until all of these activations complete (successfully or not). @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Once all of these activations are complete, if the activation of any of the tasks has failed @Redundant[(due to the propagation of an exception)], Tasking_Error is raised in the activator, at the place at which it initiated the activations. Otherwise, the activator proceeds with its execution normally. Any tasks that are aborted prior to completing their activation are ignored when determining whether to raise Tasking_Error. @begin(Ramification) Note that a task created by an @nt<allocator> does not necessarily depend on its activator; in such a case the activator's termination can precede the termination of the newly created task. @end(Ramification) @begin(Discussion) Tasking_Error is raised only once, even if two or more of the tasks being activated fail their activation. @end(Discussion) @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[The pragma Partition_Elaboration_Policy (see @RefSecNum{Pragma Partition_Elaboration_Policy}) can be used to defer task activation to a later point, thus changing many of these rules.]} @end{Honest} Should the task that created the new tasks never reach the point where it would initiate the activations (due to an abort or the raising of an exception), the newly created tasks become terminated and are never activated. @end{RunTime} @begin{Notes} An entry of a task can be called before the task has been activated. If several tasks are activated together, the execution of any of these tasks need not await the end of the activation of the other tasks. A task can become completed during its activation either because of an exception or because it is aborted (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of task activation:} @begin{Example} @key(procedure) P @key(is) A, B : Server; --@RI[ elaborate the task objects A, B] C : Server; --@RI[ elaborate the task object C] @key(begin) --@RI[ the tasks A, B, C are activated together before the first statement] ... @key(end); @end{Example} @end{Examples} @begin{DiffWord83} We have replaced the term @i{suspended} with @i{blocked}, since we didn't want to consider a task blocked when it was simply competing for execution resources. "Suspended" is sometimes used more generally to refer to tasks that are not actually running on some processor, due to the lack of resources. This clause has been rewritten in an attempt to improve presentation. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Adjusted the wording for activating tasks to handle the case of anonymous function return objects. This is critical; we don't want to be waiting for the tasks in a return object when we exit the function normally.]} @end{DiffWord95} @LabeledClause{Task Dependence - Termination of Tasks} @begin{RunTime} @leading@Defn2{Term=[dependence], Sec=(of a task on a master)} @Defn2{Term=[task], Sec=(dependence)} @Defn2{Term=[task], Sec=(completion)} @Defn2{Term=[task], Sec=(termination)} Each task (other than an environment task @em see @RefSecNum(Program Execution)) @i(depends) on one or more masters (see @RefSecNum(Completion and Finalization)), as follows: @begin(itemize) If the task is created by the evaluation of an @nt<allocator> for a given access type, it depends on each master that includes the elaboration of the declaration of the ultimate ancestor of the given access type. If the task is created by the elaboration of an @nt<object_declaration>, it depends on each master that includes this elaboration. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Otherwise, the task depends on the master of the outermost object of which it is a part (as determined by the accessibility level of that object @em see @RefSecNum{Operations of Access Types} and @RefSecNum{Completion and Finalization}), as well as on any master whose execution includes that of the master of the outermost object.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The master of a task created by a return statement changes when the accessibility of the return object changes. Note that its activation happens, if at all, only after the function returns and all accessibility level changes have occurred.]} @end{Ramification} @end(itemize) @Defn2{term=[dependence], Sec=(of a task on another task)} Furthermore, if a task depends on a given master, it is defined to depend on the task that executes the master, and (recursively) on any master of that task. @begin{Discussion} Don't confuse these kinds of dependences with the dependences among compilation units defined in @RefSec{Compilation Units - Library Units}. @end{Discussion} A task is said to be @i(completed) when the execution of its corresponding @nt<task_body> is completed. A task is said to be @i(terminated) when any finalization of the @nt<task_body> has been performed (see @RefSecNum(Completion and Finalization)). @Redundant[The first step of finalizing a master (including a @nt<task_body>) is to wait for the termination of any tasks dependent on the master.] @PDefn2{Term=[blocked], Sec=(waiting for dependents to terminate)} The task executing the master is blocked until all the dependents have terminated. @Redundant[Any remaining finalization is then performed and the master is left.] @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Doubled word} @leading@;Completion of a task (and the corresponding @nt<task_body>) can occur when the task is blocked at a @nt<select_@!statement> with an @Chg{New=[],Old=[an ]}open @nt<terminate_alternative> (see @RefSecNum(Selective Accept)); the open @nt<terminate_alternative> is selected if and only if the following conditions are satisfied: @begin{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} The task depends on some completed master;@Chg{Version=[2],New=[ and],Old=[]} Each task that depends on the master considered is either already terminated or similarly blocked at a @nt<select_statement> with an open @nt{terminate_alternative}. @end{itemize} When both conditions are satisfied, the task considered becomes completed, together with all tasks that depend on the master considered that are not yet completed. @begin(Ramification) Any required finalization is performed after the selection of @nt<terminate_alternative>s. The tasks are not callable during the finalization. In some ways it is as though they were aborted. @end(Ramification) @end{RunTime} @begin{Notes} The full view of a limited private type can be a task type, or can have subcomponents of a task type. Creation of an object of such a type creates dependences according to the full type. An @nt<object_renaming_declaration> defines a new view of an existing entity and hence creates no further dependence. The rules given for the collective completion of a group of tasks all blocked on @nt<select_statement>s with open @nt<terminate_alternative>s ensure that the collective completion can occur only when there are no remaining active tasks that could call one of the tasks being collectively completed. If two or more tasks are blocked on @nt<select_statement>s with open @nt{terminate_alternative}s, and become completed collectively, their finalization actions proceed concurrently. @leading@keepnext@;The completion of a task can occur due to any of the following: @begin{itemize} the raising of an exception during the elaboration of the @nt{declarative_part} of the corresponding @nt{task_body}; the completion of the @nt{handled_sequence_of_statements} of the corresponding @nt{task_body}; the selection of an open @nt<terminate_alternative> of a @nt<select_statement> in the corresponding @nt<task_body>; the abort of the task. @end{itemize} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of task dependence:} @begin{Example} @key(declare) @key(type) Global @key(is) @key(access) Server; --@RI[ see @RefSecNum(Task Units and Task Objects)] A, B : Server; G : Global;@Softpage @key(begin) --@RI[ activation of A and B] @key(declare) @key(type) Local @key(is) @key(access) Server; X : Global := @key(new) Server; --@RI[ activation of X.@key{all}] L : Local := @key(new) Server; --@RI[ activation of L.@key{all}] C : Server;@Softpage @key(begin) --@RI[ activation of C] G := X; --@RI[ both G and X designate the same task object] ... @key(end;) --@RI[ await termination of C and L.@key{all} (but not X.@key{all})] ... @key(end;) --@RI[ await termination of A, B, and G.@key{all}] @end{Example} @end{Examples} @begin{DiffWord83} We have revised the wording to be consistent with the definition of master now given in @RefSec(Completion and Finalization). Tasks that used to depend on library packages in Ada 83, now depend on the (implicit) @nt<task_body> of the environment task (see @RefSecNum(Program Execution)). Therefore, the environment task has to wait for them before performing library level finalization and terminating the partition. In Ada 83 the requirement to wait for tasks that depended on library packages was not as clear. What was "collective termination" is now "collective completion" resulting from selecting @nt<terminate_alternative>s. This is because finalization still occurs for such tasks, and this happens after selecting the @nt<terminate_alternative>, but before termination. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added missing wording that explained the master of tasks that are neither object declarations nor allocators, such as function returns.]} @end{DiffWord95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{Protected Units and Protected Objects} @begin{Intro} @Defn{protected object} @Defn{protected operation} @Defn{protected subprogram} @Defn{protected entry} A @i(protected object) provides coordinated access to shared data, through calls on its visible @i(protected operations), which can be @i{protected subprograms} or @i{protected entries}. @Defn{protected declaration} @Defn{protected unit} @Defn{protected declaration} A @i{protected unit} is declared by a @i(protected declaration), which has a corresponding @nt<protected_body>. A protected declaration may be a @nt<protected_type_declaration>, in which case it declares a named protected type; alternatively, it may be a @nt<single_protected_declaration>, in which case it defines an anonymous protected type, as well as declaring a named protected object of that type. @IndexSee{Term=[broadcast signal],See=(protected object)} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<protected_type_declaration>,rhs=" @key{protected} @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}] @key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{protected_definition};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00399-01]} @Syn{lhs=<single_protected_declaration>,rhs=" @key{protected} @Syn2{defining_identifier} @key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{protected_definition};"} @Syn{lhs=<protected_definition>,rhs=" { @Syn2{protected_operation_declaration} } [ @key{private} { @Syn2{protected_element_declaration} } ] @key{end} [@SynI{protected_}@Syn2{identifier}]"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<protected_operation_declaration>, rhs="@Syn2{subprogram_declaration} | @Syn2{entry_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @Syn{lhs=<protected_element_declaration>, rhs="@Syn2<protected_operation_declaration> | @Syn2<component_declaration>"} @begin{Reason} We allow the operations and components to be mixed because that's how other things work (for example, package declarations). We have relaxed the ordering rules for the items inside @nt{declarative_part}s and @nt{task_definition}s as well. @end{Reason} @Syn{lhs=<protected_body>,rhs=" @key{protected} @key{body} @Syn2{defining_identifier} @key{is} { @Syn2{protected_operation_item} } @key{end} [@SynI{protected_}@Syn2{identifier}];"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<protected_operation_item>, rhs="@Syn2{subprogram_declaration} | @Syn2{subprogram_body} | @Syn2{entry_body} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @begin{SyntaxText} If a @SynI{protected_}@nt{identifier} appears at the end of a @nt{protected_definition} or @nt{protected_body}, it shall repeat the @nt{defining_identifier}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00345-01]}@ChgNote{This was just moved below} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{@nt{protected_declaration}})} A protected declaration requires a completion@redundant[, which shall be a @nt{protected_@!body},] and every @nt{protected_@!body} shall be the completion of some protected declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00401-01]}@Comment{This is no change here, but both of these AIs reference this paragraph, adding and removing text.} A @nt<protected_definition> defines a protected type and its first subtype. @PDefn2{Term=[visible part], Sec=(of a protected unit)} The list of @nt{protected_@!operation_@!declaration}s of a @nt{protected_@!definition}, together with the @nt{known_@!discriminant_@!part}, if any, is called the visible part of the protected unit. @Redundant[@PDefn2{Term=[private part], Sec=(of a protected unit)} The optional list of @nt{protected_@!element_@!declaration}s after the reserved word @key{private} is called the private part of the protected unit.] @begin{TheProof} Private part is defined in Section 8. @end{theproof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[For a protected declaration with an @nt{interface_list}, the protected type inherits user-defined primitive subprograms from each progenitor type (see @RefSecNum{Interface Types}), in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}). If the first parameter of a primitive inherited subprogram is of the protected type or an access parameter designating the protected type, and there is a @nt{protected_operation_declaration} for a protected subprogram or single entry with the same identifier within the protected declaration, whose profile is type conformant with the prefixed view profile of the inherited subprogram, the inherited subprogram is said to be @i{implemented} by the conforming protected subprogram or entry.@PDefn2{Term=[implemented], Sec=[by a protected subprogram]}@PDefn2{Term=[implemented], Sec=[by a protected entry]} @Defn2{Term=[type conformance],Sec=(required)}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inherited subprograms can only come from an interface given as part of the protected declaration.]} @end{Ramification} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]}@ChgNote{This was just moved, not changed} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{@nt{protected_declaration}})} A protected declaration requires a completion@redundant[, which shall be a @nt{protected_@!body},] and every @nt{protected_@!body} shall be the completion of some protected declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Text=[@Redundant[Each @i{interface_}@nt{subtype_mark} of an @nt{interface_list} appearing within a protected declaration shall denote a limited interface type that is not a task interface.]]} @begin(TheProof) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@RefSecNum{Interface Types} requires that an @nt{interface_list} only name interface types, and limits the descendants of the various kinds of interface types. Only a limited, protected, or synchronized interface can have a protected type descendant. Nonlimited or task interfaces are not allowed, as they offer operations that a protected type does not have.]} @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[The prefixed view profile of an explicitly declared primitive subprogram of a tagged protected type shall not be type conformant with any protected operation of the protected type, if the first parameter of the subprogram is of the protected type or is an access parameter designating the protected type.@Defn2{Term=[type conformance],Sec=(required)}]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the existence of two operations with the same name and profile which could be called with a prefixed view. If the operation was inherited, this would be illegal by the following rules; this rule puts inherited and non-inherited routines on the same footing. Note that this only applies to tagged protected types (that is, those with an interface in their declaration); we do that as there is no problem with prefixed view calls of primitive operations for @lquotes@;normal@rquotes protected types, and having this rule apply to all protected types would be incompatible with Ada 95.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each primitive subprogram inherited by the type declared by a protected declaration, at most one of the following shall apply:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is overridden with a primitive subprogram of the protected type, in which case the overriding subprogram shall be subtype conformant with the inherited subprogram and not abstract; or@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is implemented by a protected subprogram or single entry of the protected type, in which case its prefixed view profile shall be subtype conformant with that of the protected subprogram or entry. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If neither applies, the inherited subprogram shall be a null procedure. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each inherited subprogram can only have a single implementation (either from overriding a subprogram, implementing a subprogram, or implementing an entry), and must have an implementation unless the subprogram is a null procedure.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If an inherited subprogram is implemented by a protected procedure or an entry, then the first parameter of the inherited subprogram shall be of mode @key{out} or @key{in out}, or an access-to-variable parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For a protected procedure or entry, the protected object can be read or written (see @RefSecNum{Protected Subprograms and Protected Actions}}. A subprogram that is implemented by a protected procedure or entry must have a profile which reflects that in order to avoid confusion.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If a protected subprogram declaration has an @nt{overriding_indicator}, then at the point of the declaration:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the subprogram shall implement an inherited subprogram;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the subprogram shall not implement any inherited subprogram.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are subtly different than those for subprograms (see @RefSecNum{Overriding Indicators}) because there cannot be @lquotes@;late@rquotes inheritance of primitives from interfaces. Hidden (that is, private) interfaces are prohibited explicitly (see @RefSecNum{Private Types and Private Extensions}), as are hidden primitive operations (as private operations of public abstract types are prohibited @em see @RefSecNum{Abstract Types and Subprograms}).]} @end{Discussion} @end{Legality} @begin{RunTime} @redundant[@PDefn2{Term=[elaboration], Sec=(protected declaration)} The elaboration of a protected declaration elaborates the @nt<protected_definition>. @PDefn2{Term=[elaboration], Sec=(single_protected_declaration)} The elaboration of a @nt<single_@!protected_@!declaration> also creates an object of an (anonymous) protected type.] @begin(TheProof) This is redundant with the general rules for the elaboration of a @nt<full_type_declaration> and an @nt<object_declaration>. @end(TheProof) @PDefn2{Term=[elaboration], Sec=(protected_definition)} @Redundant[The elaboration of a @nt<protected_definition> creates the protected type and its first subtype;] it also includes the elaboration of the @nt<component_declaration>s and @nt<protected_operation_declaration>s in the given order. @redundant[@PDefn2{Term=[initialization], Sec=(of a protected object)} As part of the initialization of a protected object, any per-object constraints (see @RefSecNum{Record Types}) are elaborated.] @begin{Discussion} We do not mention pragmas since each pragma has its own elaboration rules. @end{Discussion} @PDefn2{Term=[elaboration], Sec=(protected_body)} The elaboration of a @nt{protected_body} has no other effect than to establish that protected operations of the type can from then on be called without failing the Elaboration_Check. @leading@keepnext@;The content of an object of a given protected type includes: @begin(itemize) The values of the components of the protected object, including (implicitly) an entry queue for each entry declared for the protected object; @begin(Ramification) "For each entry" implies one queue for each single entry, plus one for each entry of each entry family. @end(Ramification) @PDefn2{Term=[execution resource], Sec=(associated with a protected object)} A representation of the state of the execution resource @i(associated) with the protected object (one such resource is associated with each protected object). @end(itemize) @Redundant[The execution resource associated with a protected object has to be acquired to read or update any components of the protected object; it can be acquired (as part of a protected action @em see @RefSecNum(Protected Subprograms and Protected Actions)) either for concurrent read-only access, or for exclusive read-write access.] @PDefn2{Term=[finalization], Sec=(of a protected object)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} As the first step of the @i{finalization} of a protected object, each call remaining on any entry queue of the object is removed from its queue and Program_Error is raised at the place of the corresponding @nt<entry_@!call_@!statement>. @begin(Reason) @leading@;This is analogous to the raising of Tasking_Error in callers of a task that completes before accepting the calls. This situation can only occur due to a requeue (ignoring premature unchecked_deallocation), since any task that has accessibility to a protected object is awaited before finalizing the protected object. For example: @begin{Example} @key[procedure] Main @key[is] @key[task] T @key[is] @key[entry] E; @key[end] T; @key[task] @key[body] T @key[is] @key[protected] PO @key[is] @key[entry] Ee; @key[end] PO; @key[protected] @key[body] PO @key[is] @key[entry] Ee @key[when] False @key[is] @key[begin] @key[null]; @key[end] Ee; @key[end] PO; @key[begin] @key[accept] E @key[do] @key[requeue] PO.Ee; @key[end] E; @key[end] T; @key[begin] T.E; @key[end] Main; @end{Example} The environment task is queued on PO.EE when PO is finalized. In a real example, a server task might park callers on a local protected object for some useful purpose, so we didn't want to disallow this case. @end(Reason) @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call an entry or subprogram of a protected object after that object is finalized. If the error is detected, Program_Error is raised. Otherwise, the call proceeds normally, which may leave a task queued forever.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is very similar to the finalization rule. It is a bounded error so that an implementation can avoid the overhead of the check if it can ensure that the call still will operate properly. Such an implementation cannot need to return resources (such as locks) to an executive that it needs to execute calls.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This case can happen (and has happened in production code) when a protected object is accessed from the Finalize routine of a type. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Finalization.Controlled; @key{package} Window_Manager @key{is} ... @key{type} Root_Window @key{is new} Ada.Finalization.Controlled @key{with private}; @key{type} Any_Window @key{is access all} Root_Window; ... @key{private} ... @key{procedure} Finalize (Object : @key{in out} Root_Window); ... @key{end} Window_Manager;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Window_Manager @key{is} @key{protected type} Lock @key{is} @key{entry} Get_Lock; @key{procedure} Free_Lock; ... @key{end} Lock;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Window_Lock : Lock;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Finalize (Object : @key{in out} Root_Window) @key{is} @key{begin} Window_Lock.Get_Lock; ... Window_Lock.Free_Lock; @key{end} Finalize; ... A_Window : Any_Window := @key{new} Root_Window; @key{end} Window_Manager;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task will call Window_Lock for the object allocated for A_Window when the collection for Any_Window is finalized, which will happen after the finalization of Window_Lock (because finalization of the package body will occur before that of the package specification).]} @end{Reason} @end{Bounded} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} Within the declaration or body of a protected unit@Chg{Version=[2],New=[ other than in an @nt{access_definition}],Old=[]}, the name of the protected unit denotes the current instance of the unit (see @RefSecNum(The Context of Overload Resolution)), rather than the first subtype of the corresponding protected type (and thus the name cannot be used as a @nt<subtype_mark>). @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[It can be used as a @nt{subtype_mark} in an anonymous access type. In addition],Old=[However]}, it is possible to refer to some other subtype of the protected type within its body, presuming such a subtype has been declared between the @nt<protected_type_declaration> and the @nt<protected_body>. @end(Discussion) A @nt<selected_component> can be used to denote a discriminant of a protected object (see @RefSecNum(Selected Components)). Within a protected unit, the name of a discriminant of the protected type denotes the corresponding discriminant of the current instance of the unit. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A protected type is a limited type (see @RefSecNum(Limited Types)), and hence @Chg{Version=[2],New=[precludes use of @nt{assignment_statement}s and], Old=[has neither an assignment operation nor]} predefined equality operators. The bodies of the protected operations given in the @nt<protected_body> define the actions that take place upon calls to the protected operations. The declarations in the private part are only visible within the private part and the body of the protected unit. @begin{Reason} @nt{Component_declaration}s are disallowed in a @nt{protected_body} because, for efficiency, we wish to allow the compiler to determine the size of protected objects (when not dynamic); the compiler cannot necessarily see the body. Furthermore, the semantics of initialization of such objects would be problematic @em we do not wish to give protected objects complex initialization semantics similar to task activation. The same applies to @nt{entry_declaration}s, since an entry involves an implicit component @em the entry queue. @end{Reason} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of declaration of protected type and corresponding body:} @begin{Example} @key(protected) @key(type) Resource @key(is) @key(entry) Seize; @key(procedure) Release; @key(private) Busy : Boolean := False; @key(end) Resource; @key(protected) @key(body) Resource @key(is) @key(entry) Seize @key(when not) Busy @key(is) @key(begin) Busy := True; @key(end) Seize; @key(procedure) Release @key(is) @key(begin) Busy := False; @key(end) Release; @key(end) Resource; @end{Example} @begin{wide} @leading@keepnext@i{Example of a single protected declaration and corresponding body:} @end{wide} @begin{Example} @key(protected) Shared_Array @key(is) --@RI[ Index, Item, and Item_Array are global types] @key(function) Component (N : @key(in) Index) return Item; @key(procedure) Set_Component(N : @key(in) Index; E : @key(in) Item); @key(private) Table : Item_Array(Index) := (others => Null_Item); @key(end) Shared_Array; @key(protected) @key(body) Shared_Array @key(is) @key(function) Component(N : @key(in) Index) @key(return) Item @key(is) @key(begin) @key(return) Table(N); @key(end) Component; @key(procedure) Set_Component(N : @key(in) Index; E : @key(in) Item) @key(is) @key(begin) Table(N) := E; @key(end) Set_Component; @key(end) Shared_Array; @end{Example} @begin{wide} @leading@keepnext@i{Examples of protected objects:} @end{wide} @begin{Example} Control : Resource; Flags : @key(array)(1 .. 100) @key(of) Resource; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} This entire clause is new; protected units do not exist in Ada 83. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Protected types and single protected objects can be derived from one or more interfaces. Operations declared in the protected type can implement the primitive operations of an interface. @nt{Overriding_indicator}s can be used to specify whether or not a protected operation implements a primitive operation.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Described what happens when an operation of a finalized protected object is called.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Revised the note on operations of protected types to reflect that limited types do have an assignment operation, but not copying (@nt{assignment_statement}s).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[Revised the note on use of the name of a protected type within itself to reflect the exception for anonymous access types.]} @end{DiffWord95} @LabeledClause{Intertask Communication} @begin{Intro} @Defn{intertask communication} @IndexSee{Term=[critical section],See=(intertask communication)} The primary means for intertask communication is provided by calls on entries and protected subprograms. Calls on protected subprograms allow coordinated access to shared data objects. Entry calls allow for blocking the caller until a given condition is satisfied (namely, that the corresponding entry is open @em see @RefSecNum(Entry Calls)), and then communicating data or control information directly with another task or indirectly via a shared protected object. @end{Intro} @begin{StaticSem} @leading@Defn2{Term=[target object], Sec=(of a call on an entry or a protected subprogram)} Any call on an entry or on a protected subprogram identifies a @i(target object) for the operation, which is either a task (for an entry call) or a protected object (for an entry call or a protected subprogram call). The target object is considered an implicit parameter to the operation, and is determined by the operation @nt<name> (or @nt<prefix>) used in the call on the operation, as follows: @begin(Itemize) If it is a @nt<direct_name> or expanded name that denotes the declaration (or body) of the operation, then the target object is implicitly specified to be the current instance of the task or protected unit immediately enclosing the operation; @Defn{internal call} such a call is defined to be an @i(internal call); @leading@;If it is a @nt<selected_component> that is not an expanded name, then the target object is explicitly specified to be the task or protected object denoted by the @nt<prefix> of the @nt<name>; @Defn{external call} such a call is defined to be an @i(external call); @begin{Discussion} For example: @begin{Example} @key[protected] @key[type] Pt @key[is] @key[procedure] Op1; @key[procedure] Op2; @key[end] Pt; PO : Pt; Other_Object : Some_Other_Protected_Type; @key[protected] @key[body] Pt @key[is] @key[procedure] Op1 @key[is] @key[begin] ... @key[end] Op1; @key[procedure] Op2 @key[is] @key[begin] Op1; --@RI{ An internal call.} Pt.Op1; --@RI{ Another internal call.} PO.Op1; --@RI{ An external call. It the current instance is PO, then} --@RI{ this is a bounded error (see @RefSecNum{Protected Subprograms and Protected Actions}).} Other_Object.Some_Op; --@RI{ An external call.} @key[end] Op2; @key[end] Pt; @end{Example} @end{Discussion} If the @nt<name> or @nt<prefix> is a dereference (implicit or explicit) of an access-to-protected-subprogram value, then the target object is determined by the @nt<prefix> of the Access @nt<attribute_reference> that produced the access value originally, and the call is defined to be an @i(external call); If the @nt<name> or @nt<prefix> denotes a @nt<subprogram_renaming_declaration>, then the target object is as determined by the @nt<name> of the renamed entity. @end(Itemize) @Defn2{Term=[target object], Sec=(of a @nt<requeue_statement>)} @Defn{internal requeue} @Defn{external requeue} A corresponding definition of target object applies to a @nt<requeue_statement> (see @RefSecNum(Requeue Statements)), with a corresponding distinction between an @i(internal requeue) and an @i(external requeue). @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[The view of the target protected object associated with a call of a protected procedure or entry shall be a variable.]} @end{Legality} @begin{RunTime} Within the body of a protected operation, the current instance (see @RefSecNum(The Context of Overload Resolution)) of the immediately enclosing protected unit is determined by the target object specified (implicitly or explicitly) in the call (or requeue) on the protected operation. @begin{Honest} The current instance is defined in the same way within the body of a subprogram declared immediately within a @nt{protected_body}. @end{Honest} Any call on a protected procedure or entry of a target protected object is defined to be an update to the object, as is a requeue on such an entry. @begin(Reason) Read/write access to the components of a protected object is granted while inside the body of a protected procedure or entry. Also, any protected entry call can change the value of the Count attribute, which represents an update. Any protected procedure call can result in servicing the entries, which again might change the value of a Count attribute. @end(Reason) @end{RunTime} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added a @LegalityName to make it crystal-clear that the protected object of an entry or procedure call must be a variable. This rule was implied by the @RuntimeTitle here, along with the @StaticSemTitle of @RefSecNum{Objects and Named Numbers}, but it is much better to explicitly say it. While many implementations have gotten this wrong, this is not an incompatibility @em allowing updates of protected constants has always been wrong.]} @end{DiffWord95} @LabeledSubClause{Protected Subprograms and Protected Actions} @begin{Intro} @Defn{protected subprogram} @Defn{protected procedure} @Defn{protected function} A @i{protected subprogram} is a subprogram declared immediately within a @nt{protected_definition}. Protected procedures provide exclusive read-write access to the data of a protected object; protected functions provide concurrent read-only access to the data. @begin{Ramification} A subprogram declared immediately within a @nt{protected_body} is not a protected subprogram; it is an intrinsic subprogram. See @RefSec{Conformance Rules}. @end{Ramification} @end{Intro} @begin{StaticSem} Within the body of a protected function (or a function declared immediately within a @nt<protected_body>), the current instance of the enclosing protected unit is defined to be a constant @Redundant[(that is, its subcomponents may be read but not updated)]. Within the body of a protected procedure (or a procedure declared immediately within a @nt<protected_body>), and within an @nt<entry_body>, the current instance is defined to be a variable @Redundant[(updating is permitted)]. @begin(Ramification) The current instance is like an implicit parameter, of mode @key(in) for a protected function, and of mode @key(in out) for a protected procedure (or protected entry). @end(Ramification) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(protected subprogram call)} For the execution of a call on a protected subprogram, the evaluation of the @nt<name> or @nt<prefix> and of the parameter associations, and any assigning back of @key[in out] or @key[out] parameters, proceeds as for a normal subprogram call (see @RefSecNum{Subprogram Calls}). If the call is an internal call (see @RefSecNum(Intertask Communication)), the body of the subprogram is executed as for a normal subprogram call. If the call is an external call, then the body of the subprogram is executed as part of a new @i(protected action) on the target protected object; the protected action completes after the body of the subprogram is executed. @Redundant[A protected action can also be started by an entry call (see @RefSecNum{Entry Calls}).] @leading@Defn{protected action} A new protected action is not started on a protected object while another protected action on the same protected object is underway, unless both actions are the result of a call on a protected function. This rule is expressible in terms of the execution resource associated with the protected object: @begin(Itemize) @Defn2{Term=[protected action], Sec=(start)} @Defn2{Term=[acquire], Sec=(execution resource associated with protected object)} @i(Starting) a protected action on a protected object corresponds to @i(acquiring) the execution resource associated with the protected object, either for concurrent read-only access if the protected action is for a call on a protected function, or for exclusive read-write access otherwise; @Defn2{Term=[protected action], Sec=(complete)} @Defn2{Term=[release], Sec=(execution resource associated with protected object)} @i(Completing) the protected action corresponds to @i(releasing) the associated execution resource. @end(Itemize) @Redundant[After performing an operation on a protected object other than a call on a protected function, but prior to completing the associated protected action, the entry queues (if any) of the protected object are serviced (see @RefSecNum(Entry Calls)).] @end{RunTime} @begin{Bounded} @leading@PDefn2{Term=(bounded error),Sec=(cause)} During a protected action, it is a bounded error to invoke an operation that is @i(potentially blocking). @Defn{potentially blocking operation} @Defn{blocking, potentially} The following are defined to be potentially blocking operations: @begin{Reason} Some of these operations are not directly blocking. However, they are still treated as bounded errors during a protected action, because allowing them might impose an undesirable implementation burden. @end{Reason} @begin{itemize} a @nt{select_statement}; an @nt{accept_statement}; an @nt{entry_call_statement}; a @nt{delay_statement}; an @nt{abort_statement}; task creation or activation; an external call on a protected subprogram (or an external requeue) with the same target object as that of the protected action; @begin(Reason) This is really a deadlocking call, rather than a blocking call, but we include it in this list for simplicity. @end(Reason) a call on a subprogram whose body contains a potentially blocking operation. @begin(Reason) This allows an implementation to check and raise Program_Error as soon as a subprogram is called, rather than waiting to find out whether it actually reaches the potentially blocking operation. This in turn allows the potentially blocking operation check to be performed prior to run time in some environments. @end(Reason) @end{itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the bounded error is detected, Program_Error is raised. If not detected, the bounded error might result in deadlock or a (nested) protected action on the same target object. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[By @lquotes@;nested protected action@rquotes, we mean that an additional protected action can be started by another task on the same protected object. This means that mutual exclusion may be broken in this bounded error case. A way to ensure that this does not happen is to use pragma Detect_Blocking (see @RefSecNum{Pragma Detect_Blocking}).]} @end{Discussion} Certain language-defined subprograms are potentially blocking. In particular, the subprograms of the language-defined input-output packages that manipulate files (implicitly or explicitly) are potentially blocking. Other potentially blocking subprograms are identified where they are defined. When not specified as potentially blocking, a language-defined subprogram is nonblocking. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00178-01]} @ChgAdded{Version=[2],Text=[Any subprogram in a language-defined input-output package that has a file parameter or result or operates on a default file is considered to manipulate a file. An instance of a language-defined input-output generic package provides subprograms that are covered by this rule. The only subprograms in language-defined input-output packages not covered by this rule (and thus not potentially blocking) are the Get and Put routines that take string parameters defined in the packages nested in Text_IO.]}@ChgNote{This was the resolution of a ramification.} @end{Discussion} @end{Bounded} @begin{Notes} If two tasks both try to start a protected action on a protected object, and at most one is calling a protected function, then only one of the tasks can proceed. Although the other task cannot proceed, it is not considered blocked, and it might be consuming processing resources while it awaits its turn. There is no language-defined ordering or queuing presumed for tasks competing to start a protected action @em on a multiprocessor such tasks might use busy-waiting; for monoprocessor considerations, see @RefSec{Priority Ceiling Locking}. @begin{Discussion} The intended implementation on a multi-processor is in terms of @lquotes@;spin locks@rquotes@; @em the waiting task will spin. @end{Discussion} The body of a protected unit may contain declarations and bodies for local subprograms. These are not visible outside the protected unit. The body of a protected function can contain internal calls on other protected functions, but not protected procedures, because the current instance is a constant. On the other hand, the body of a protected procedure can contain internal calls on both protected functions and procedures. From within a protected action, an internal call on a protected subprogram, or an external call on a protected subprogram with a different target object is not considered a potentially blocking operation. @begin(Reason) This is because a task is not considered blocked while attempting to acquire the execution resource associated with a protected object. The acquisition of such a resource is rather considered part of the normal competition for execution resources between the various tasks that are ready. External calls that turn out to be on the same target object are considered potentially blocking, since they can deadlock the task indefinitely. @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[The @nt{pragma} Detect_Blocking may be used to ensure that all executions of potentially blocking operations during a protected action raise Program_Error. See @RefSecNum{Pragma Detect_Blocking}.]} @end{Notes} @begin{Examples} @leading@i{Examples of protected subprogram calls (see @RefSecNum(Protected Units and Protected Objects)):} @begin{Example} Shared_Array.Set_Component(N, E); E := Shared_Array.Component(M); Control.Release; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[Added a note pointing out the existence of @nt{pragma} Detect_Blocking. This pragma can be used to ensure portable (somewhat pessimistic) behavior of protected actions by converting the Bounded Error into a required check.]} @end{DiffWord95} @LabeledSubClause{Entries and Accept Statements} @begin{Intro} @nt<Entry_declaration>s, with the corresponding @ntf<entry_bodies> or @nt<accept_statement>s, are used to define potentially queued operations on tasks and protected objects. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00397-01]} @Syn{lhs=<entry_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}]>,Old=[]} @key{entry} @Syn2{defining_identifier} [(@Syn2{discrete_subtype_definition})] @Syn2{parameter_profile};"} @Syn{lhs=<accept_statement>,rhs=" @key{accept} @SynI{entry_}@Syn2{direct_name} [(@Syn2{entry_index})] @Syn2{parameter_profile} [@key{do} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{entry_}@Syn2{identifier}]];"} @begin{Reason} We cannot use @nt{defining_identifier} for @nt<accept_statement>s. Although an @nt{accept_statement} is sort of like a body, it can appear nested within a @nt{block_statement}, and therefore be hidden from its own entry by an outer homograph. @end{Reason} @Syn{lhs=<entry_index>,rhs="@Syn2{expression}"} @Syn{lhs=<entry_body>,rhs=" @key{entry} @Syn2{defining_identifier} @Syn2{entry_body_formal_part} @Syn2{entry_barrier} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{entry_}@Syn2{identifier}];"} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[We don't allow an @nt{overriding_indicator} on an @nt{entry_body} because entries always implement procedures at the point of the type declaration; there is no late implementation. And we don't want to have to think about @nt{overriding_indicator}s on @nt{accept_statement}s.]} @end{Discussion} @Syn{lhs=<entry_body_formal_part>, rhs="[(@Syn2{entry_index_specification})] @Syn2{parameter_profile}"} @Syn{lhs=<entry_barrier>, rhs="@key{when} @Syn2{condition}"} @Syn{lhs=<entry_index_specification>, rhs="@key{for} @Syn2{defining_identifier} @key{in} @Syn2{discrete_subtype_definition}"} @begin{SyntaxText} If an @SynI{entry_}@nt{identifier} appears at the end of an @nt{accept_statement}, it shall repeat the @SynI{entry_}@!@nt<direct_@!name>. If an @SynI{entry_}@!@nt{identifier} appears at the end of an @nt{entry_@!body}, it shall repeat the @nt{defining_@!identifier}. @Redundant[An @nt{entry_declaration} is allowed only in a protected or task declaration.] @begin(TheProof) This follows from the BNF. @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is not allowed in an @nt{entry_declaration} that includes a @nt{discrete_subtype_definition}.]} @begin(Reason) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[An entry family can never implement something, so allowing an indicator is felt by the majority of the ARG to be redundant.]} @end(Reason) @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(accept_statement @i{entry_}@nt<direct_name>)} In an @nt<accept_statement>, the expected profile for the @SynI{entry_}@nt<direct_name> is that of the @nt<entry_@!declaration>; @PDefn2{Term=[expected type], Sec=(entry_index)} the expected type for an @nt<entry_index> is that of the subtype defined by the @nt<discrete_@!subtype_@!definition> of the corresponding @nt<entry_@!declaration>. Within the @nt<handled_sequence_of_statements> of an @nt<accept_statement>, if a @nt<selected_@!component> has a @nt<prefix> that denotes the corresponding @nt<entry_@!declaration>, then the entity denoted by the @nt<prefix> is the @nt<accept_@!statement>, and the @nt<selected_@!component> is interpreted as an expanded name (see @RefSecNum(Selected Components))@Redundant[; the @nt<selector_name> of the @nt<selected_@!component> has to be the @nt<identifier> for some formal parameter of the @nt<accept_@!statement>]. @begin{TheProof} The only declarations that occur immediately within the declarative region of an @nt<accept_statement> are those for its formal parameters. @end{TheProof} @end{Resolution} @begin{Legality} An @nt<entry_declaration> in a task declaration shall not contain a specification for an access parameter (see @RefSecNum(Access Types)). @begin(Reason) @leading@;Access parameters for task entries would require a complex implementation. For example: @begin(Example) @key(task) T @key(is) @key(entry) E(Z : @key(access) Integer); --@RI{ Illegal!} @key(end) T; @key(task body) T @key(is) @key(begin) @key(declare) @key(type) A @key(is access all) Integer; X : A; Int : @key(aliased) Integer; @key(task) Inner; @key(task body) Inner @key(is) @key(begin) T.E(Int'Access); @key(end) Inner; @key(begin) @key(accept) E(Z : @key(access) Integer) @key(do) X := A(Z); --@RI{ Accessibility_Check} @key(end) E; @key(end); @key(end) T; @end(Example) Implementing the Accessibility_Check inside the @nt<accept_statement> for E is difficult, since one does not know whether the entry caller is calling from inside the immediately enclosing declare block or from outside it. This means that the lexical nesting level associated with the designated object is not sufficient to determine whether the Accessibility_Check should pass or fail. Note that such problems do not arise with protected entries, because @ntf<entry_bodies> are always nested immediately within the @nt<protected_body>; they cannot be further nested as can @nt<accept_statement>s, nor can they be called from within the @nt<protected_body> (since no entry calls are permitted inside a @nt<protected_body>). @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If an @nt{entry_declaration} has an @nt{overriding_indicator}, then at the point of the declaration:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the entry shall implement an inherited subprogram;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the entry shall not implement any inherited subprogram.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are subtly different than those for subprograms (see @RefSecNum{Overriding Indicators}) because there cannot be @lquotes@;late@rquotes inheritance of primitives from interfaces. Hidden (that is, private) interfaces are prohibited explicitly (see @RefSecNum{Private Types and Private Extensions}), as are hidden primitive operations (as private operations of public abstract types are prohibited @em see @RefSecNum{Abstract Types and Subprograms}).]} @end{Discussion} For an @nt<accept_statement>, the innermost enclosing body shall be a @nt<task_body>, and the @i(entry_)@!@nt<direct_@!name> shall denote an @nt<entry_@!declaration> in the corresponding task declaration; the profile of the @nt{accept_@!statement} shall conform fully to that of the corresponding @nt<entry_@!declaration>. @Defn2{Term=[full conformance],Sec=(required)} An @nt<accept_@!statement> shall have a parenthesized @nt<entry_@!index> if and only if the corresponding @nt<entry_@!declaration> has a @nt<discrete_@!subtype_@!definition>. An @nt<accept_statement> shall not be within another @nt{accept_statement} that corresponds to the same @nt<entry_@!declaration>, nor within an @nt<asynchronous_@!select> inner to the enclosing @nt<task_body>. @begin(Reason) @nt<Accept_statement>s are required to be immediately within the enclosing @nt<task_body> (as opposed to being in a nested subprogram) to ensure that a nested task does not attempt to accept the entry of its enclosing task. We considered relaxing this restriction, either by making the check a run-time check, or by allowing a nested task to accept an entry of its enclosing task. However, neither change seemed to provide sufficient benefit to justify the additional implementation burden. Nested @nt<accept_statement>s for the same entry (or entry family) are prohibited to ensure that there is no ambiguity in the resolution of an expanded name for a formal parameter of the entry. This could be relaxed by allowing the inner one to hide the outer one from all visibility, but again the small added benefit didn't seem to justify making the change for Ada 95. @nt<Accept_statement>s are not permitted within @nt<asynchronous_select> statements to simplify the semantics and implementation: an @nt<accept_statement> in an @nt<abortable_part> could result in Tasking_Error being propagated from an entry call even though the target task was still callable; implementations that use multiple tasks implicitly to implement an @nt<asynchronous_select> might have trouble supporting "up-level" accepts. Furthermore, if @nt<accept_statement>s were permitted in the @nt<abortable_part>, a task could call its own entry and then accept it in the @nt<abortable_part>, leading to rather unusual and possibly difficult-to-specify semantics. @end(Reason) @PDefn2{Term=[requires a completion], Sec=(protected @nt{entry_declaration})} An @nt{entry_declaration} of a protected unit requires a completion@redundant[, which shall be an @nt{entry_body},] @PDefn2{Term=[only as a completion], Sec=(@nt<entry_body>)} and every @nt<entry_@!body> shall be the completion of an @nt<entry_@!declaration> of a protected unit. @PDefn2{Term=[completion legality], Sec=(@nt<entry_body>)} The profile of the @nt<entry_@!body> shall conform fully to that of the corresponding declaration. @Defn2{Term=[full conformance],Sec=(required)} @begin{Ramification} An @nt<entry_declaration>, unlike a @nt<subprogram_declaration>, cannot be completed with a @nt<renaming_@!declaration>. @end{Ramification} @begin(Honest) The completion can be a @nt{pragma} Import, if the implementation supports it. @end(Honest) @begin{Discussion} The above applies only to protected entries, which are the only ones completed with @ntf{entry_bodies}. Task entries have corresponding @nt{accept_statement}s instead of having @ntf{entry_bodies}, and we do not consider an @nt{accept_statement} to be a @lquotes@;completion,@rquotes@; because a task @nt{entry_declaration} is allowed to have zero, one, or more than one corresponding @nt{accept_statement}s. @end{Discussion} An @nt{entry_body_formal_part} shall have an @nt{entry_@!index_@!specification} if and only if the corresponding @nt{entry_@!declaration} has a @nt<discrete_@!subtype_@!definition>. In this case, the @nt<discrete_@!subtype_@!definition>s of the @nt<entry_@!declaration> and the @nt<entry_@!index_@!specification> shall fully conform to one another (see @RefSecNum(Conformance Rules)). @Defn2{Term=[full conformance],Sec=(required)} A name that denotes a formal parameter of an @nt<entry_body> is not allowed within the @nt<entry_barrier> of the @nt<entry_body>. @end{Legality} @begin{StaticSem} The parameter modes defined for parameters in the @nt<parameter_profile> of an @nt{entry_declaration} are the same as for a @nt<subprogram_declaration> and have the same meaning (see @RefSecNum(Formal Parameter Modes)). @begin{Discussion} Note that access parameters are not allowed for task entries (see above). @end{Discussion} @Defn2{Term=[family], Sec=(entry)} @Defn{entry family} @Defn{entry index subtype} An @nt<entry_declaration> with a @nt<discrete_subtype_definition> (see @RefSecNum(Array Types)) declares a @i(family) of distinct entries having the same profile, with one such entry for each value of the @i(entry index subtype) defined by the @nt<discrete_@!subtype_@!definition>. @Redundant[A name for an entry of a family takes the form of an @nt<indexed_component>, where the @nt<prefix> denotes the @nt<entry_declaration> for the family, and the index value identifies the entry within the family.] @Defn{single entry} @Defn2{Term=[entry], Sec=(single)} The term @i(single entry) is used to refer to any entry other than an entry of an entry family. In the @nt<entry_body> for an entry family, the @nt<entry_index_specification> declares a named constant whose subtype is the entry index subtype defined by the corresponding @nt<entry_declaration>; @Defn{named entry index} the value of the @i(named entry index) identifies which entry of the family was called. @begin{Ramification} The @nt<discrete_subtype_definition> of the @nt<entry_index_specification> is not elaborated; the subtype of the named constant declared is defined by the @nt<discrete_subtype_definition> of the corresponding @nt<entry_declaration>, which is elaborated, either when the type is declared, or when the object is created, if its constraint is per-object. @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @PDefn2{Term=[elaboration], Sec=(entry_declaration)} @Chg{New=[The elaboration of an @nt<entry_declaration> for an entry family consists of the elaboration of the @nt<discrete_@!subtype_@!definition>, as described in @RefSecNum(Record Types).], Old=[For the elaboration of an @nt<entry_@!declaration> for an entry family, if the @nt{discrete_@!subtype_@!definition} contains no per-object expressions (see @RefSecNum(Record Types)), then the @nt<discrete_@!subtype_@!definition> is elaborated. Otherwise, the elaboration of the @nt<entry_@!declaration> consists of the evaluation of any expression of the @nt<discrete_@!subtype_@!definition> that is not a per-object expression (or part of one).]} The elaboration of an @nt<entry_@!declaration> for a single entry has no effect. @begin{Discussion} The elaboration of the declaration of a protected subprogram has no effect, as specified in clause @RefSecNum(Subprogram Declarations). The default initialization of an object of a task or protected type is covered in @RefSecNum(Object Declarations). @end{Discussion} @Redundant[The actions to be performed when an entry is called are specified by the corresponding @nt{accept_@!statement}s (if any) for an entry of a task unit, and by the corresponding @nt<entry_@!body> for an entry of a protected unit.] @PDefn2{Term=[execution], Sec=(accept_statement)} For the execution of an @nt{accept_statement}, the @nt<entry_index>, if any, is first evaluated and converted to the entry index subtype; this index value identifies which entry of the family is to be accepted. @PDefn2{Term=[implicit subtype conversion],Sec=(entry index)} @PDefn2{Term=[blocked], Sec=(on an @nt<accept_statement>)} @Defn2{Term=[selection], Sec=(of an entry caller)} Further execution of the @nt<accept_statement> is then blocked until a caller of the corresponding entry is selected (see @RefSecNum(Entry Calls)), whereupon the @nt<handled_sequence_of_statements>, if any, of the @nt<accept_statement> is executed, with the formal parameters associated with the corresponding actual parameters of the selected entry call. Upon completion of the @nt<handled_sequence_of_statements>, the @nt<accept_statement> completes and is left. When an exception is propagated from the @nt{handled_sequence_of_statements} of an @nt{accept_statement}, the same exception is also raised by the execution of the corresponding @nt{entry_call_statement}. @begin{Ramification} This is in addition to propagating it to the construct containing the @nt{accept_statement}. In other words, for a rendezvous, the raising splits in two, and continues concurrently in both tasks. The caller gets a new occurrence; this isn't considered propagation. Note that we say @lquotes@;propagated from the @nt{handled_sequence_of_statements} of an @nt{accept_statement}@rquotes@;, not @lquotes@;propagated from an @nt{accept_statement}.@rquotes@; The latter would be wrong @em we don't want exceptions propagated by the @nt<entry_index> to be sent to the caller (there is none yet!). @end{Ramification} @Defn{rendezvous} The above interaction between a calling task and an accepting task is called a @i(rendezvous). @Redundant[After a rendezvous, the two tasks continue their execution independently.] @Redundant[An @nt<entry_body> is executed when the @nt<condition> of the @nt<entry_barrier> evaluates to True and a caller of the corresponding single entry, or entry of the corresponding entry family, has been selected (see @RefSecNum(Entry Calls)).] @PDefn2{Term=[execution], Sec=(entry_body)} For the execution of the @nt<entry_@!body>, the @nt<declarative_@!part> of the @nt<entry_@!body> is elaborated, and the @nt<handled_@!sequence_of_@!statements> of the body is executed, as for the execution of a @nt<subprogram_body>. The value of the named entry index, if any, is determined by the value of the entry index specified in the @i(entry_)@nt<name> of the selected entry call (or intermediate @nt<requeue_@!statement> @em see @RefSecNum(Requeue Statements)). @begin(Honest) If the entry had been renamed as a subprogram, and the call was a @nt<procedure_call_statement> using the name declared by the renaming, the entry index (if any) comes from the entry @nt<name> specified in the @nt<subprogram_renaming_declaration>. @end(Honest) @end{RunTime} @begin{Notes} A task entry has corresponding accept_statements (zero or more), whereas a protected entry has a corresponding entry_body (exactly one). A consequence of the rule regarding the allowed placements of @nt{accept_statement}s is that a task can execute @nt{accept_statement}s only for its own entries. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} A @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} (see @RefSecNum(Return Statements)) or a @nt<requeue_statement> (see @RefSecNum(Requeue Statements)) may be used to complete the execution of an @nt<accept_statement> or an @nt<entry_body>. @begin{Ramification} An @nt<accept_statement> need not have a @nt<handled_sequence_of_statements> even if the corresponding entry has parameters. Equally, it can have a @nt<handled_sequence_of_statements> even if the corresponding entry has no parameters. @end{Ramification} @begin{Ramification} A single entry overloads a subprogram, an enumeration literal, or another single entry if they have the same @nt{defining_identifier}. Overloading is not allowed for entry family names. A single entry or an entry of an entry family can be renamed as a procedure as explained in @RefSecNum{Subprogram Renaming Declarations}. @end{Ramification} The @nt<condition> in the @nt{entry_barrier} may reference anything visible except the formal parameters of the entry. This includes the entry index (if any), the components (including discriminants) of the protected object, the Count attribute of an entry of that protected object, and data global to the protected unit. @NoPrefix@;The restriction against referencing the formal parameters within an @nt{entry_barrier} ensures that all calls of the same entry see the same barrier value. If it is necessary to look at the parameters of an entry call before deciding whether to handle it, the @nt<entry_barrier> can be @lquotes@;@key(when) True@rquotes@; and the caller can be requeued (on some private entry) when its parameters indicate that it cannot be handled immediately. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of entry declarations:} @begin{Example} @key(entry) Read(V : @key(out) Item); @key(entry) Seize; @key(entry) Request(Level)(D : Item); --@RI[ a family of entries] @end{Example} @begin{Wide} @leading@keepnext@i{Examples of accept statements:} @end{Wide} @begin{Example} @key(accept) Shut_Down; @key(accept) Read(V : @key(out) Item) @key(do) V := Local_Item; @key(end) Read; @key(accept) Request(Low)(D : Item) @key(do) ... @key(end) Request; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{entry_body} is new. @nt{Accept_statement}s can now have @nt{exception_handler}s. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the elaboration of per-object constraints.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[@nt{Overriding_indicator}s can be used on entries; this is only useful when a task or protected type inherits from an interface.]} @end{DiffWord95} @LabeledSubClause{Entry Calls} @begin{Intro} @Defn{entry call} @Redundant[An @nt<entry_call_statement> (an @i(entry call)) can appear in various contexts.] @Defn{simple entry call} @Defn2{Term={entry call}, Sec=(simple)} A @i(simple) entry call is a stand-alone statement that represents an unconditional call on an entry of a target task or a protected object. @Redundant[Entry calls can also appear as part of @nt<select_statement>s (see @RefSecNum(Select Statements)).] @end{Intro} @begin{Syntax} @Syn{lhs=<entry_call_statement>,rhs="@SynI{entry_}@Syn2{name} [@Syn2{actual_parameter_part}];"} @end{Syntax} @begin{Resolution} The @i(entry_)@nt<name> given in an @nt<entry_call_statement> shall resolve to denote an entry. The rules for parameter associations are the same as for subprogram calls (see @RefSecNum(Subprogram Calls) and @RefSecNum(Parameter Associations)). @end{Resolution} @begin{StaticSem} @Redundant[The @i(entry_)@nt<name> of an @nt<entry_call_statement> specifies (explicitly or implicitly) the target object of the call, the entry or entry family, and the entry index, if any (see @RefSecNum(Intertask Communication)).] @end{StaticSem} @begin{RunTime} @leading@Defn{open entry} @Defn2{Term=[entry], Sec=(open)} @Defn{closed entry} @Defn2{Term=[entry], Sec=(closed)} Under certain circumstances (detailed below), an entry of a task or protected object is checked to see whether it is @i(open) or @i(closed): @begin(Itemize) @Defn2{Term=[open entry], Sec=(of a task)} @Defn2{Term=[closed entry], Sec=(of a task)} An entry of a task is open if the task is blocked on an @nt<accept_statement> that corresponds to the entry (see @RefSecNum(Entries and Accept Statements)), or on a @nt<selective_accept> (see @RefSecNum(Selective Accept)) with an open @nt<accept_alternative> that corresponds to the entry; otherwise it is closed. @Defn2{Term=[open entry], Sec=(of a protected object)} @Defn2{Term=[closed entry], Sec=(of a protected object)} An entry of a protected object is open if the @nt<condition> of the @nt<entry_barrier> of the corresponding @nt<entry_body> evaluates to True; otherwise it is closed. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the evaluation of the @nt<condition> propagates an exception, the exception Program_Error is propagated to all current callers of all entries of the protected object. @begin(Reason) An exception during barrier evaluation is considered essentially a fatal error. All current entry callers are notified with a Program_Error. In a fault-tolerant system, a protected object might provide a Reset protected procedure, or equivalent, to support attempts to restore such a "broken" protected object to a reasonable state. @end(Reason) @end(Itemize) @begin(Discussion) Note that the definition of when a task entry is open is based on the state of the (accepting) task, whereas the "openness" of a protected entry is defined only when it is explicitly checked, since the barrier expression needs to be evaluated. Implementation permissions are given (below) to allow implementations to evaluate the barrier expression more or less often than it is checked, but the basic semantic model presumes it is evaluated at the times when it is checked. @end(Discussion) @leading@PDefn2{Term=[execution], Sec=(entry_call_statement)} For the execution of an @nt{entry_call_statement}, evaluation of the @nt<name> and of the parameter associations is as for a subprogram call (see @RefSecNum{Subprogram Calls}). @Defn2{Term=[issue], Sec=(an entry call)} The entry call is then @i(issued): For a call on an entry of a protected object, a new protected action is started on the object (see @RefSecNum(Protected Subprograms and Protected Actions)). The named entry is checked to see if it is open; @Defn2{Term=[select an entry call], Sec=(immediately)} if open, the entry call is said to be @i(selected immediately), and the execution of the call proceeds as follows: @begin(Itemize) For a call on an open entry of a task, the accepting task becomes ready and continues the execution of the corresponding @nt<accept_statement> (see @RefSecNum(Entries and Accept Statements)). For a call on an open entry of a protected object, the corresponding @nt<entry_body> is executed (see @RefSecNum(Entries and Accept Statements)) as part of the protected action. @end(Itemize) If the @nt<accept_statement> or @nt<entry_body> completes other than by a requeue (see @RefSecNum(Requeue Statements)), return is made to the caller (after servicing the entry queues @em see below); any necessary assigning back of formal to actual parameters occurs, as for a subprogram call (see @RefSecNum(Parameter Associations)); such assignments take place outside of any protected action. @begin(Ramification) The return to the caller will generally not occur until the protected action completes, unless some other thread of control is given the job of completing the protected action and releasing the associated execution resource. @end(Ramification) If the named entry is closed, the entry call is added to an @i(entry queue) (as part of the protected action, for a call on a protected entry), and the call remains queued until it is selected or cancelled; @Defn{entry queue} there is a separate (logical) entry queue for each entry of a given task or protected object @Redundant[(including each entry of an entry family)]. @Leading@Defn2{Term=[service], Sec=(an entry queue)} @Defn2{Term=[select an entry call], Sec=(from an entry queue)} When a queued call is @i{selected}, it is removed from its entry queue. Selecting a queued call from a particular entry queue is called @i{servicing} the entry queue. An entry with queued calls can be serviced under the following circumstances: @begin(Itemize) When the associated task reaches a corresponding @nt<accept_statement>, or a @nt<selective_accept> with a corresponding open @nt<accept_alternative>; If after performing, as part of a protected action on the associated protected object, an operation on the object other than a call on a protected function, the entry is checked and found to be open. @end(Itemize) @Defn2{Term=[select an entry call], Sec=(from an entry queue)} If there is at least one call on a queue corresponding to an open entry, then one such call is selected according to the @i(entry queuing policy) in effect (see below), and the corresponding @nt<accept_statement> or @nt<entry_body> is executed as above for an entry call that is selected immediately. @Defn{entry queuing policy} The entry queuing policy controls selection among queued calls both for task and protected entry queues. @Defn{default entry queuing policy} @Defn2{Term=[entry queuing policy], Sec=(default policy)} The default entry queuing policy is to select calls on a given entry queue in order of arrival. If calls from two or more queues are simultaneously eligible for selection, the default entry queuing policy does not specify which queue is serviced first. Other entry queuing policies can be specified by @nt{pragma}s (see @RefSecNum(Entry Queuing Policies)). For a protected object, the above servicing of entry queues continues until there are no open entries with queued calls, at which point the protected action completes. @begin(Discussion) While servicing the entry queues of a protected object, no new calls can be added to any entry queue of the object, except due to an internal requeue (see @RefSecNum(Requeue Statements)). This is because the first step of a call on a protected entry is to start a new protected action, which implies acquiring (for exclusive read-write access) the execution resource associated with the protected object, which cannot be done while another protected action is already in progress. @end(Discussion) @PDefn2{Term=[blocked], Sec=(during an entry call)} For an entry call that is added to a queue, and that is not the @nt<triggering_statement> of an @nt<asynchronous_@!select> (see @RefSecNum{Asynchronous Transfer of Control}), the calling task is blocked until the call is cancelled, or the call is selected and a corresponding @nt<accept_statement> or @nt<entry_body> completes without requeuing. In addition, the calling task is blocked during a rendezvous. @begin{Ramification} For a call on a protected entry, the caller is not blocked if the call is selected immediately, unless a requeue causes the call to be queued. @end{Ramification} @Defn2{Term=[cancellation], Sec=(of an entry call)} An attempt can be made to cancel an entry call upon an abort (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)) and as part of certain forms of @nt<select_statement> (see @RefSecNum(Timed Entry Calls), @RefSecNum(Conditional Entry Calls), and @RefSecNum(Asynchronous Transfer of Control)). The cancellation does not take place until a point (if any) when the call is on some entry queue, and not protected from cancellation as part of a requeue (see @RefSecNum(Requeue Statements)); at such a point, the call is removed from the entry queue and the call completes due to the cancellation. The cancellation of a call on an entry of a protected object is a protected action@Redundant[, and as such cannot take place while any other protected action is occurring on the protected object. Like any protected action, it includes servicing of the entry queues (in case some entry barrier depends on a Count attribute).] @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} In the case of an attempted cancellation due to abort, this removal might have to be performed by the calling task itself if the ceiling priority of the protected object is lower than the @Chg{Version=[2],New=[priority of the ],Old=[]}task initiating the abort. @end(ImplNote) @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} A call on an entry of a task that has already completed its execution raises the exception Tasking_Error at the point of the call; similarly, this exception is raised at the point of the call if the called task completes its execution or becomes abnormal before accepting the call or completing the rendezvous (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). This applies equally to a simple entry call and to an entry call as part of a @nt<select_statement>. @end{RunTime} @begin{ImplPerm} An implementation may perform the sequence of steps of a protected action using any thread of control; it need not be that of the task that started the protected action. If an @nt<entry_body> completes without requeuing, then the corresponding calling task may be made ready without waiting for the entire protected action to complete. @begin(Reason) These permissions are intended to allow flexibility for implementations on multiprocessors. On a monoprocessor, which thread of control executes the protected action is essentially invisible, since the thread is not abortable in any case, and the "current_task" function is not guaranteed to work during a protected action (see @Chg{Version=[2],New=[@RefSecNum(The Package Task_Identification)], Old=[@RefSecNum(Task Information)]}). @end(Reason) When the entry of a protected object is checked to see whether it is open, the implementation need not reevaluate the @nt<condition> of the corresponding @nt<entry_barrier> if no variable or attribute referenced by the @nt<condition> (directly or indirectly) has been altered by the execution (or cancellation) of a protected procedure or entry call on the object since the @nt<condition> was last evaluated. @begin(Ramification) Changes to variables referenced by an entry barrier that result from actions outside of a protected procedure or entry call on the protected object need not be "noticed." For example, if a global variable is referenced by an entry barrier, it should not be altered (except as part of a protected action on the object) any time after the barrier is first evaluated. In other words, globals can be used to "parameterize" a protected object, but they cannot reliably be used to control it after the first use of the protected object. @end(Ramification) @begin{ImplNote} Note that even if a global variable is volatile, the implementation need only reevaluate a barrier if the global is updated during a protected action on the protected object. This ensures that an entry-open bit-vector implementation approach is possible, where the bit-vector is computed at the end of a protected action, rather than upon each entry call. @end{ImplNote} An implementation may evaluate the @nt<condition>s of all @nt<entry_barrier>s of a given protected object any time any entry of the object is checked to see if it is open. @begin(Ramification) In other words, any side-effects of evaluating an entry barrier should be innocuous, since an entry barrier might be evaluated more or less often than is implied by the "official" dynamic semantics. @end(Ramification) @begin(ImplNote) It is anticipated that when the number of entries is known to be small, all barriers will be evaluated any time one of them needs to be, to produce an "entry-open bit-vector." The appropriate bit will be tested when the entry is called, and only if the bit is false will a check be made to see whether the bit-vector might need to be recomputed. This should allow an implementation to maximize the performance of a call on an open entry, which seems like the most important case. In addition to the entry-open bit-vector, an "is-valid" bit is needed per object, which indicates whether the current bit-vector setting is valid. A "depends-on-Count-attribute" bit is needed per type. The "is-valid" bit is set to false (as are all the bits of the bit-vector) when the protected object is first created, as well as any time an exception is propagated from computing the bit-vector. Is-valid would also be set false any time the Count is changed and "depends-on-Count-attribute" is true for the type, or a protected procedure or entry returns indicating it might have updated a variable referenced in some barrier. A single procedure can be compiled to evaluate all of the barriers, set the entry-open bit-vector accordingly, and set the is-valid bit to true. It could have a "when others" handler to set them all false, and call a routine to propagate Program_Error to all queued callers. For protected types where the number of entries is not known to be small, it makes more sense to evaluate a barrier only when the corresponding entry is checked to see if it is open. It isn't worth saving the state of the entry between checks, because of the space that would be required. Furthermore, the entry queues probably want to take up space only when there is actually a caller on them, so rather than an array of all entry queues, a linked list of nonempty entry queues make the most sense in this case, with the first caller on each entry queue acting as the queue header. @end(ImplNote) When an attempt is made to cancel an entry call, the implementation need not make the attempt using the thread of control of the task (or interrupt) that initiated the cancellation; in particular, it may use the thread of control of the caller itself to attempt the cancellation, even if this might allow the entry call to be selected in the interim. @begin{Reason} Because cancellation of a protected entry call is a protected action (which helps make the Count attribute of a protected entry meaningful), it might not be practical to attempt the cancellation from the thread of control that initiated the cancellation. For example, if the cancellation is due to the expiration of a delay, it is unlikely that the handler of the timer interrupt could perform the necessary protected action itself (due to being on the interrupt level). Similarly, if the cancellation is due to an abort, it is possible that the task initiating the abort has a priority higher than the ceiling priority of the protected object (for implementations that support ceiling priorities). Similar considerations could apply in a multiprocessor situation. @end{Reason} @end{ImplPerm} @begin{Notes} If an exception is raised during the execution of an @nt{entry_body}, it is propagated to the corresponding caller (see @RefSecNum(Exception Handling)). For a call on a protected entry, the entry is checked to see if it is open prior to queuing the call, and again thereafter if its Count attribute (see @RefSecNum{Task and Entry Attributes}) is referenced in some entry barrier. @begin(Ramification) Given this, extra care is required if a reference to the Count attribute of an entry appears in the entry's own barrier. @end(Ramification) @begin(Reason) An entry is checked to see if it is open prior to queuing to maximize the performance of a call on an open entry. @end(Reason) In addition to simple entry calls, the language permits timed, conditional, and asynchronous entry calls (see @RefSecNum(Timed Entry Calls), @RefSecNum(Conditional Entry Calls), and see @RefSecNum(Asynchronous Transfer of Control)). @begin{Ramification} A task can call its own entries, but the task will deadlock if the call is a simple entry call. @end{Ramification} The @nt<condition> of an @nt<entry_barrier> is allowed to be evaluated by an implementation more often than strictly necessary, even if the evaluation might have side effects. On the other hand, an implementation need not reevaluate the @nt<condition> if nothing it references was updated by an intervening protected action on the protected object, even if the @nt<condition> references some global variable that might have been updated by an action performed from outside of a protected action. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of entry calls:} @begin{Example} Agent.Shut_Down; --@RI[ see @RefSecNum(Task Units and Task Objects)] Parser.Next_Lexeme(E); --@RI[ see @RefSecNum(Task Units and Task Objects)] Pool(5).Read(Next_Char); --@RI[ see @RefSecNum(Task Units and Task Objects)] Controller.Request(Low)(Some_Item); --@RI[ see @RefSecNum(Task Units and Task Objects)] Flags(3).Seize; --@RI[ see @RefSecNum(Protected Units and Protected Objects)] @end{Example} @end{Examples} @LabeledSubClause{Requeue Statements} @begin{Intro} @redundant[A @nt<requeue_statement> can be used to complete an @nt<accept_statement> or @nt<entry_body>, while redirecting the corresponding entry call to a new (or the same) entry queue. @Defn{requeue} Such a @i(requeue) can be performed with or without allowing an intermediate cancellation of the call, due to an abort or the expiration of a delay. @IndexSee{Term=[preference control],See=(requeue)} @IndexSee{Term=[broadcast signal],See=(requeue)}] @end{Intro} @begin{Syntax} @Syn{lhs=<requeue_statement>, rhs="@key{requeue} @SynI{entry_}@Syn2{name} [@key{with} @key{abort}];"} @end{Syntax} @begin{Resolution} @Defn2{Term=[target entry], Sec=(of a @nt<requeue_statement>)} The @i(entry_)@nt{name} of a @nt{requeue_statement} shall resolve to denote an entry (the @i(target entry)) that either has no parameters, or that has a profile that is type conformant (see @RefSecNum(Conformance Rules)) with the profile of the innermost enclosing @nt<entry_@!body> or @nt<accept_@!statement>. @Defn2{Term=[type conformance],Sec=(required)} @end{Resolution} @begin{Legality} A @nt{requeue_statement} shall be within a callable construct that is either an @nt{entry_body} or an @nt{accept_statement}, and this construct shall be the innermost enclosing body or callable construct. If the target entry has parameters, then its profile shall be subtype conformant with the profile of the innermost enclosing callable construct. @Defn2{Term=[subtype conformance],Sec=(required)} @PDefn2{Term=[accessibility rule],Sec=(requeue statement)} In a @nt<requeue_statement> of an @nt<accept_statement> of some task unit, either the target object shall be a part of a formal parameter of the @nt<accept_statement>, or the accessibility level of the target object shall not be equal to or statically deeper than any enclosing @nt<accept_statement> of the task unit. In a @nt<requeue_@!statement> of an @nt<entry_@!body> of some protected unit, either the target object shall be a part of a formal parameter of the @nt<entry_@!body>, or the accessibility level of the target object shall not be statically deeper than that of the @nt<entry_declaration>. @begin{Ramification} In the @nt{entry_body} case, the intent is that the target object can be global, or can be a component of the protected unit, but cannot be a local variable of the @nt{entry_body}. @end{Ramification} @begin(Reason) These restrictions ensure that the target object of the requeue outlives the completion and finalization of the enclosing callable construct. They also prevent requeuing from a nested @nt<accept_statement> on a parameter of an outer @nt<accept_statement>, which could create some strange "long-distance" connections between an entry caller and its server. Note that in the strange case where a @nt<task_body> is nested inside an @nt<accept_statement>, it is permissible to requeue from an @nt<accept_statement> of the inner @nt<task_body> on parameters of the outer @nt<accept_statement>. This is not a problem because all calls on the inner task have to complete before returning from the outer @nt<accept_statement>, meaning no "dangling calls" will be created. @end(Reason) @begin(ImplNote) By disallowing certain requeues, we ensure that the normal @nt<terminate_alternative> rules remain sensible, and that explicit clearing of the entry queues of a protected object during finalization is rarely necessary. In particular, such clearing of the entry queues is necessary only (ignoring premature Unchecked_Deallocation) for protected objects declared in a @nt<task_body> (or created by an allocator for an access type declared in such a body) containing one or more @nt<requeue_statement>s. Protected objects declared in subprograms, or at the library level, will never need to have their entry queues explicitly cleared during finalization. @end(ImplNote) @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(requeue_statement)} The execution of a @nt{requeue_statement} proceeds by first evaluating the @i(entry_)@nt<name>@Redundant[, including the @nt<prefix> identifying the target task or protected object and the @nt<expression> identifying the entry within an entry family, if any]. The @nt{entry_body} or @nt{accept_statement} enclosing the @nt{requeue_statement} is then completed@Redundant[, finalized, and left (see @RefSecNum(Completion and Finalization))]. @PDefn2{Term=[execution], Sec=(requeue task entry)} For the execution of a requeue on an entry of a target task, after leaving the enclosing callable construct, the named entry is checked to see if it is open and the requeued call is either selected immediately or queued, as for a normal entry call (see @RefSecNum(Entry Calls)). @leading@PDefn2{Term=[execution], Sec=(requeue protected entry)} For the execution of a requeue on an entry of a target protected object, after leaving the enclosing callable construct: @begin(Itemize) if the requeue is an internal requeue (that is, the requeue is back on an entry of the same protected object @em see @RefSecNum(Intertask Communication)), the call is added to the queue of the named entry and the ongoing protected action continues (see @RefSecNum(Protected Subprograms and Protected Actions)); @begin(Ramification) Note that for an internal requeue, the call is queued without checking whether the target entry is open. This is because the entry queues will be serviced before the current protected action completes anyway, and considering the requeued call immediately might allow it to "jump" ahead of existing callers on the same queue. @end(Ramification) if the requeue is an external requeue (that is, the target protected object is not implicitly the same as the current object @em see @RefSecNum(Intertask Communication)), a protected action is started on the target object and proceeds as for a normal entry call (see @RefSecNum(Entry Calls)). @end(Itemize) If the new entry named in the @nt<requeue_statement> has formal parameters, then during the execution of the @nt<accept_statement> or @nt<entry_body> corresponding to the new entry, the formal parameters denote the same objects as did the corresponding formal parameters of the callable construct completed by the requeue. @Redundant[In any case, no parameters are specified in a @nt<requeue_statement>; any parameter passing is implicit.] @leading@Defn{requeue-with-abort} If the @nt<requeue_statement> includes the reserved words @key(with abort) (it is a @i(requeue-with-abort)), then: @begin(Itemize) if the original entry call has been aborted (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)), then the requeue acts as an abort completion point for the call, and the call is cancelled and no requeue is performed; if the original entry call was timed (or conditional), then the original expiration time is the expiration time for the requeued call. @end(Itemize) If the reserved words @key(with abort) do not appear, then the call remains protected against cancellation while queued as the result of the @nt<requeue_statement>. @begin(Ramification) This protection against cancellation lasts only until the call completes or a subsequent requeue-with-abort is performed on the call. @end(Ramification) @begin(Reason) We chose to protect a requeue, by default, against abort or cancellation. This seemed safer, since it is likely that extra steps need to be taken to allow for possible cancellation once the servicing of an entry call has begun. This also means that in the absence of @key(with abort) the usual Ada 83 behavior is preserved, namely that once an entry call is accepted, it cannot be cancelled until it completes. @end(Reason) @end{RunTime} @begin{Notes} A requeue is permitted from a single entry to an entry of an entry family, or vice-versa. The entry index, if any, plays no part in the subtype conformance check between the profiles of the two entries; an entry index is part of the @i(entry_)@nt<name> for an entry of a family. @PDefn{subtype conformance} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of requeue statements:} @begin{Example} @key[requeue] Request(Medium) @key[with abort]; --@RI[ requeue on a member of an entry family of the current task, see @RefSecNum{Task Units and Task Objects}] @key[requeue] Flags(I).Seize; --@RI[ requeue on an entry of an array component, see @RefSecNum{Protected Units and Protected Objects}] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt<requeue_statement> is new. @end{Extend83} @LabeledClause{Delay Statements, Duration, and Time} @begin{Intro} @redundant[@PDefn{expiration time} A @nt<delay_statement> is used to block further execution until a specified @i(expiration time) is reached. The expiration time can be specified either as a particular point in time (in a @nt<delay_@!until_@!statement>), or in seconds from the current time (in a @nt<delay_@!relative_@!statement>). The language-defined package Calendar provides definitions for a type Time and associated operations, including a function Clock that returns the current time. @IndexSee{Term=[timing],See=(delay_statement)}] @end{Intro} @begin{Syntax} @Syn{lhs=<delay_statement>, rhs="@Syn2{delay_until_statement} | @Syn2{delay_relative_statement}"} @Syn{lhs=<delay_until_statement>, rhs="@key{delay until} @SynI(delay_)@Syn2{expression};"} @Syn{lhs=<delay_relative_statement>, rhs="@key{delay} @SynI(delay_)@Syn2{expression};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(delay_relative_statement expression)} The expected type for the @i(delay_)@nt{expression} in a @nt{delay_relative_statement} is the predefined type Duration. @PDefn2{Term=[expected type], Sec=(delay_until_statement expression)} The @i(delay_)@nt<expression> in a @nt<delay_until_statement> is expected to be of any nonlimited type. @end{Resolution} @begin{Legality} @Defn{time type} @Defn{time base} @Defn{clock} There can be multiple time bases, each with a corresponding clock, and a corresponding @i{time type}. The type of the @i(delay_)@nt<expression> in a @nt{delay_until_statement} shall be a time type @em either the type Time defined in the language-defined package Calendar (see below), or some other implementation-defined time type (see @RefSecNum(Monotonic Time)). @ImplDef{Any implementation-defined time types.} @end{Legality} @begin{StaticSem} @Redundant[There is a predefined fixed point type named Duration, declared in the visible part of package Standard;] a value of type Duration is used to represent the length of an interval of time, expressed in seconds. @Redundant[The type Duration is not specific to a particular time base, but can be used with any time base.] A value of the type Time in package Calendar, or of some other implementation-defined time type, represents a time as reported by a corresponding clock. @leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChildUnit{Parent=[Ada],Child=[Calendar]} @key(package) Ada.Calendar @key(is) @key(type) @AdaTypeDefn{Time} @key(is) @key(private); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} @key(subtype) @AdaSubtypeDefn{Name=[Year_Number],Of=[Integer]} @key(is) Integer @key(range) 1901 .. @Chg{Version=[2],New=[2399],Old=[2099]}; @key(subtype) @AdaSubtypeDefn{Name=[Month_Number],Of=[Integer]} @key(is) Integer @key(range) 1 .. 12; @key(subtype) @AdaSubtypeDefn{Name=[Day_Number],Of=[Integer]} @key(is) Integer @key(range) 1 .. 31; @key(subtype) @AdaSubtypeDefn{Name=[Day_Duration],Of=[Duration]} @key(is) Duration @key(range) 0.0 .. 86_400.0; @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[A range of 500 years was chosen, as that only requires one extra bit for the year as compared to Ada 95. This was done to minimize disruptions with existing implementations. (One implementor reports that their time values represent nanoseconds, and this year range requires 63.77 bits to represent.)]} @end{Reason} @key(function) @AdaSubDefn{Clock} @key(return) Time; @key(function) @AdaSubDefn{Year} (Date : Time) @key(return) Year_Number; @key(function) @AdaSubDefn{Month} (Date : Time) @key(return) Month_Number; @key(function) @AdaSubDefn{Day} (Date : Time) @key(return) Day_Number; @key(function) @AdaSubDefn{Seconds}(Date : Time) @key(return) Day_Duration; @key(procedure) @AdaSubDefn{Split} (Date : @key(in) Time; Year : @key(out) Year_Number; Month : @key(out) Month_Number; Day : @key(out) Day_Number; Seconds : @key(out) Day_Duration); @key(function) @AdaSubDefn{Time_Of}(Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0) @key(return) Time; @key(function) "+" (Left : Time; Right : Duration) @key(return) Time; @key(function) "+" (Left : Duration; Right : Time) @key(return) Time; @key(function) "-" (Left : Time; Right : Duration) @key(return) Time; @key(function) "-" (Left : Time; Right : Time) @key(return) Duration; @key(function) "<" (Left, Right : Time) @key(return) Boolean; @key(function) "<="(Left, Right : Time) @key(return) Boolean; @key(function) ">" (Left, Right : Time) @key(return) Boolean; @key(function) ">="(Left, Right : Time) @key(return) Boolean; @AdaExcDefn{Time_Error} : @key(exception;) @key(private) ... -- @RI{not specified by the language} @key(end) Ada.Calendar; @end{Example} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(delay_statement)} For the execution of a @nt<delay_statement>, the @i(delay_)@nt<expression> is first evaluated. @Defn2{Term=[expiration time], Sec=(for a @nt<delay_until_statement>)} For a @nt<delay_until_statement>, the expiration time for the delay is the value of the @i(delay_)@nt<expression>, in the time base associated with the type of the @nt<expression>. @Defn2{Term=[expiration time], Sec=(for a @nt<delay_relative_statement>)} For a @nt<delay_relative_statement>, the expiration time is defined as the current time, in the time base associated with relative delays, plus the value of the @i(delay_)@nt<expression> converted to the type Duration, and then rounded up to the next clock tick. @PDefn2{Term=[implicit subtype conversion],Sec=(delay expression)} The time base associated with relative delays is as defined in @RefSec{Delay Accuracy} or is implementation defined. @ImplDef{The time base associated with relative delays.} @begin{Ramification} Rounding up to the next clock tick means that the reading of the delay-relative clock when the delay expires should be no less than the current reading of the delay-relative clock plus the specified duration. @end{Ramification} @PDefn2{Term=[blocked], Sec=(on a @nt<delay_statement>)} The task executing a @nt<delay_statement> is blocked until the expiration time is reached, at which point it becomes ready again. If the expiration time has already passed, the task is not blocked. @begin(Discussion) For a @nt<delay_relative_statement>, this case corresponds to when the value of the @i(delay_)@nt<expression> is zero or negative. Even though the task is not blocked, it might be put back on the end of its ready queue. See @RefSec(Priority Scheduling). @end(Discussion) @Defn2{Term=[cancellation], Sec=(of a @nt<delay_statement>)} If an attempt is made to @i(cancel) the @nt<delay_statement> @Redundant[(as part of an @nt<asynchronous_@!select> or abort @em see @RefSecNum{Asynchronous Transfer of Control} and @RefSecNum{Abort of a Task - Abort of a Sequence of Statements})], the @ntf<_statement> is cancelled if the expiration time has not yet passed, thereby completing the @nt<delay_statement>. @begin(Reason) This is worded this way so that in an @nt<asynchronous_select> where the @nt<triggering_statement> is a @nt<delay_statement>, an attempt to cancel the delay when the @nt<abortable_part> completes is ignored if the expiration time has already passed, in which case the optional statements of the @nt<triggering_alternative> are executed. @end(Reason) The time base associated with the type Time of package Calendar is implementation defined. The function Clock of package Calendar returns a value representing the current time for this time base. @Redundant[The implementation-defined value of the named number System.Tick (see @RefSecNum(The Package System)) is an approximation of the length of the real-time interval during which the value of Calendar.Clock remains constant.] @ImplDef{The time base of the type Calendar.Time.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} The functions Year, Month, Day, and Seconds return the corresponding values for a given value of the type Time, as appropriate to an implementation-defined @Chg{Version=[2],New=[time zone],Old=[timezone]}; the procedure Split returns all four corresponding values. Conversely, the function Time_Of combines a year number, a month number, a day number, and a duration, into a value of type Time. The operators "+" and "@en@;" for addition and subtraction of times and durations, and the relational operators for times, have the conventional meaning. @ChgImplDef{Version=[2],Kind=[Revised], Text=[The @Chg{Version=[2],New=[time zone],Old=[timezone]} used for package Calendar operations.]} If Time_Of is called with a seconds value of 86_400.0, the value returned is equal to the value of Time_Of for the next day with a seconds value of 0.0. The value returned by the function Seconds or through the Seconds parameter of the procedure Split is always less than 86_400.0. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0030],ARef=[AI95-00113-01]} The exception Time_Error is raised by the function Time_Of if the actual parameters do not form a proper date. This exception is also raised by the operators "+" and "@en@;" if the result is not representable in the type Time or Duration, as appropriate. This exception is also raised by the function@Chg{New=[s],Old=[]} Year@Chg{New=[, Month, Day, and Seconds and], Old=[or]} the procedure Split if the year number of the given date is outside of the range of the subtype Year_Number. @begin(Honest) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0106],ARef=[AI95-00160-01]} By "proper date" above we mean that the given year has a month with the given day. For example, February 29th is a proper date only for a leap year. @Chg{New=[We do not mean to include the Seconds in this notion; in particular, we do not mean to require implementations to check for the @lquotes@;missing hour@rquotes that occurs when Daylight Savings Time starts in the spring.],Old=[]} @end(Honest) @begin(Reason) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0030],ARef=[AI95-00113-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} We allow Year and Split to raise Time_Error because the arithmetic operators are allowed (but not required) to produce times that are outside the range of years from 1901 to @Chg{Version=[2],New=[2399],Old=[2099]}. This is similar to the way integer operators may return values outside the base range of their type so long as the value is mathematically correct. @Chg{New=[We allow the functions Month, Day and Seconds to raise Time_Error so that they can be implemented in terms of Split.],Old=[]} @end(Reason) @end{RunTime} @begin{ImplReq} The implementation of the type Duration shall allow representation of time intervals (both positive and negative) up to at least 86400 seconds (one day); Duration'Small shall not be greater than twenty milliseconds. The implementation of the type Time shall allow representation of all dates with year numbers in the range of Year_Number@Redundant[; it may allow representation of other dates as well (both earlier and later).] @end{ImplReq} @begin{ImplPerm} An implementation may define additional time types (see @RefSecNum{Monotonic Time}). An implementation may raise Time_Error if the value of a @i{delay_}@nt<expression> in a @nt<delay_until_statement> of a @nt<select_statement> represents a time more than 90 days past the current time. The actual limit, if any, is implementation-defined. @ImplDef{Any limit on @nt<delay_until_statement>s of @nt<select_statement>s.} @begin{ImplNote} This allows an implementation to implement @nt<select_statement> timeouts using a representation that does not support the full range of a time type. In particular 90 days of seconds can be represented in 23 bits, allowing a signed 24-bit representation for the seconds part of a timeout. There is no similar restriction allowed for stand-alone @nt<delay_until_statement>s, as these can be implemented internally using a loop if necessary to accommodate a long delay. @end{ImplNote} @end{ImplPerm} @begin{ImplAdvice} Whenever possible in an implementation, the value of Duration'Small should be no greater than 100 microseconds. @begin(ImplNote) This can be satisfied using a 32-bit 2's complement representation with a @i(small) of 2.0**(@en@;14) @em that is, 61 microseconds @em and a range of @PorM 2.0**17 @em that is, 131_072.0. @end(ImplNote) @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The value of Duration'Small should be no greater than 100 microseconds.]}]} The time base for @nt{delay_relative_statement}s should be monotonic; it need not be the same time base as used for Calendar.Clock. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The time base for @nt{delay_relative_statement}s should be monotonic.]}]} @end{ImplAdvice} @begin{Notes} A @nt{delay_relative_statement} with a negative value of the @i(delay_)@nt<expression> is equivalent to one with a zero value. A @nt{delay_statement} may be executed by the environment task; consequently @nt{delay_statement}s may be executed as part of the elaboration of a @nt{library_item} or the execution of the main subprogram. Such statements delay the environment task (see @RefSecNum(Program Execution)). @PDefn2{Term=[potentially blocking operation],Sec=(delay_statement)} @PDefn2{Term=[blocking, potentially],Sec=(delay_statement)} A @nt{delay_statement} is an abort completion point and a potentially blocking operation, even if the task is not actually blocked. There is no necessary relationship between System.Tick (the resolution of the clock of package Calendar) and Duration'Small (the @i(small) of type Duration). @begin{Ramification} The inaccuracy of the @nt{delay_statement} has no relation to System.Tick. In particular, it is possible that the clock used for the @nt{delay_statement} is less accurate than Calendar.Clock. We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in @RefSec{Real-Time Systems}. @end{Ramification} Additional requirements associated with @nt<delay_statement>s are given in @RefSec(Delay Accuracy). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a relative delay statement:} @begin{example} @key(delay) 3.0; --@RI[ delay 3.0 seconds] @end{example} @begin{Wide} @leading@keepnext@Defn2{Term=[periodic task],Sec=(example)} @IndexSee{Term=[periodic task],See=(delay_until_statement)} @i{Example of a periodic task:} @end{Wide} @begin{example} @key(declare) @key(use) Ada.Calendar; Next_Time : Time := Clock + Period; --@RI[ Period is a global constant of type Duration] @key(begin) @key(loop) --@RI[ repeated every Period seconds] @key(delay) @key(until) Next_Time; ... --@RI[ perform some actions] Next_Time := Next_Time + Period; @key(end) @key(loop;) @key(end;) @end{example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} For programs that raise Time_Error on "+" or "@en@;" in Ada 83,the exception might be deferred until a call on Split or Year_Number, or might not be raised at all (if the offending time is never Split after being calculated). This should not affect typical programs, since they deal only with times corresponding to the relatively recent past or near future. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{delay_statement} is modified to allow @nt{delay_until_statement}s. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} The type Time may represent dates with year numbers outside of Year_Number. Therefore, the operations "+" and "@en@;" need only raise Time_Error if the result is not representable in Time (or Duration); also, Split or Year will now raise Time_Error if the year number is outside of Year_Number. This change is intended to simplify the implementation of "+" and "@en@;" (allowing them to depend on overflow for detecting when to raise Time_Error) and to allow local @Chg{Version=[2],New=[time zone],Old=[timezone]} information to be considered at the time of Split rather than Clock (depending on the implementation approach). For example, in a POSIX environment, it is natural for the type Time to be based on GMT, and the results of procedure Split (and the functions Year, Month, Day, and Seconds) to depend on local time zone information. In other environments, it is more natural for the type Time to be based on the local time zone, with the results of Year, Month, Day, and Seconds being pure functions of their input. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00351-01]} @ChgDeleted{Version=[2],Text=[We anticipate that implementations will provide child packages of Calendar to provide more explicit control over time zones and other environment-dependent time-related issues. These would be appropriate for standardization in a given environment (such as POSIX).]} @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95}The upper bound of Year_Number has been changed to avoid a year 2100 problem. A program which expects years past 2099 to raise Constraint_Error will fail in Ada 2005. We don't expect there to be many programs which are depending on an exception to be raised. A program that uses Year_Number'Last as a magic number may also fail if values of Time are stored outside of the program. Note that the lower bound of Year_Number wasn't changed, because it is not unusual to use that value in a constant to represent an unknown time.]} @end{Inconsistent95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Month, Day, and Seconds can raise Time_Error.]} @end{DiffWord95} @LabeledAddedSubclause{Version=[2],Name=[Formatting, Time Zones, and other operations for Time]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Text=[The following language-defined library packages exist:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Time_Zones]}@key(package) Ada.Calendar.Time_Zones @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Time zone manipulation:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Time_Offset} @key<is range> -28*60 .. 28*60;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We want to be able to specify the difference between any two arbitrary time zones. You might think that 1440 (24 hours) would be enough, but there are places (like Tonga, which is UTC+13hr) which are more than 12 hours than UTC. Combined with summer time (known as daylight saving time in some parts of the world) @en which switches opposite in the northern and souther hemispheres @en and even greater differences are possible. We know of cases of a 26 hours difference, so we err on the safe side by selecting 28 hours as the limit.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Unknown_Zone_Error} : @key<exception>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{UTC_Time_Offset} (Date : Time := Clock) @key<return> Time_Offset;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Time_Zones;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Arithmetic]} @key(package) Ada.Calendar.Arithmetic @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Arithmetic on days:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Day_Count} @key<is range> -366*(1+Year_Number'Last - Year_Number'First) .. 366*(1+Year_Number'Last - Year_Number'First);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<subtype> @AdaSubtypeDefn{Name=[Leap_Seconds_Count],Of=[Integer]} @key<is> Integer @key<range> -2047 .. 2047;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The maximum number of leap seconds is likely to be much less than this, but we don't want to reach the limit too soon if the earth's behavior suddenly changes. We believe that the maximum number is 1612, based on the current rules, but that number is too weird to use here.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Difference} (Left, Right : @key<in> Time; Days : @key<out> Day_Count; Seconds : @key<out> Duration; Leap_Seconds : @key<out> Leap_Seconds_Count);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "+" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "+" (Left : Day_Count; Right : Time) @key<return> Time; @key<function> "-" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "-" (Left, Right : Time) @key<return> Day_Count;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Arithmetic;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Formatting]} @key<with> Ada.Calendar.Time_Zones; @key(package) Ada.Calendar.Formatting @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Day of the week:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Day_Name} @key<is> (@AdaObjDefn{Monday}, @AdaObjDefn{Tuesday}, @AdaObjDefn{Wednesday}, @AdaObjDefn{Thursday}, @AdaObjDefn{Friday}, @AdaObjDefn{Saturday}, @AdaObjDefn{Sunday});]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Day_of_Week} (Date : Time) @key<return> Day_Name;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Hours:Minutes:Seconds access:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<subtype> @AdaSubtypeDefn{Name=[Hour_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 23; @key<subtype> @AdaSubtypeDefn{Name=[Minute_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 59; @key<subtype> @AdaSubtypeDefn{Name=[Second_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 59; @key<subtype> @AdaSubtypeDefn{Name=[Second_Duration],Of=[Day_Duration]} @key<is> Day_Duration @key<range> 0.0 .. 1.0;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Year} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Year_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Month} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Month_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Day} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Day_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Hour} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Hour_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Minute} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Minute_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Second} (Date : Time) @key<return> Second_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Sub_Second} (Date : Time) @key<return> Second_Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Seconds_Of} (Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number := 0; Sub_Second : Second_Duration := 0.0) @key<return> Day_Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Seconds : @key<in> Day_Duration; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Time_Of} (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Time_Of} (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Seconds : @key<out> Day_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Simple image and value:] @key<function> @AdaSubDefn{Image} (Date : Time; Include_Time_Fraction : Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Date : String; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Image} (Elapsed_Time : Duration; Include_Time_Fraction : Boolean := False) @key<return> String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Elapsed_Time : String) @key<return> Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Formatting;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[Type Time_Offset represents the number of minutes difference between the implementation-defined time zone used by Calendar and another time zone.]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> UTC_Time_Offset (Date : Time := Clock) @key<return> Time_Offset;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns, as a number of minutes, the difference between the implementation-defined time zone of Calendar, and UTC time, at the time Date. If the time zone of the Calendar implementation is unknown, then Unknown_Zone_Error is raised.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Date parameter is needed to take into account time differences caused by daylight-savings time and other time changes. This parameter is measured in the time zone of Calendar, if any, not necessarily the UTC time zone.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Other time zones can be supported with a child package. We don't define one because of the lack of agreement on the definition of a time zone.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The accuracy of this routine is not specified; the intent is that the facilities of the underlying target operating system are used to implement it.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Difference (Left, Right : @key<in> Time; Days : @key<out> Day_Count; Seconds : @key<out> Duration; Leap_Seconds : @key<out> Leap_Seconds_Count);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the difference between Left and Right. Days is the number of days of difference, Seconds is the remainder seconds of difference excluding leap seconds, and Leap_Seconds is the number of leap seconds. If Left < Right, then Seconds <= 0.0, Days <= 0, and Leap_Seconds <= 0. Otherwise, all values are nonnegative. The absolute value of Seconds is always less than 86_400.0. For the returned values, if Days = 0, then Seconds + Duration(Leap_Seconds) = Calendar."@en" (Left, Right).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Leap_Seconds, if any, are not included in Seconds. However, Leap_Seconds should be included in calculations using the operators defined in Calendar, as is specified for "@en" above.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "+" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "+" (Left : Day_Count; Right : Time) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Adds a number of days to a time value. Time_Error is raised if the result is not representable as a value of type Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "-" (Left : Time; Right : Day_Count) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Subtracts a number of days from a time value. Time_Error is raised if the result is not representable as a value of type Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "-" (Left, Right : Time) @key<return> Day_Count;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Subtracts two time values, and returns the number of days between them. This is the same value that Difference would return in Days.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Day_of_Week (Date : Time) @key<return> Day_Name;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the day of the week for Time. This is based on the Year, Month, and Day values of Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Year (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Year_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the year for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Month (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Month_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the month for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Day (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Day_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the day number for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Hour (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Hour_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the hour for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Minute (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Minute_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the minute within the hour for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Second (Date : Time) @key<return> Second_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the second within the hour and minute for Date.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Sub_Second (Date : Time) @key<return> Second_Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the fraction of second for Date (this has the same accuracy as Day_Duration). The value returned is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Seconds_Of (Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number := 0; Sub_Second : Second_Duration := 0.0) @key<return> Day_Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Day_Duration value for the combination of the given Hour, Minute, Second, and Sub_Second. This value can be used in Calendar.Time_Of as well as the argument to Calendar."+" and Calendar."@en". If Seconds_Of is called with a Sub_Second value of 1.0, the value returned is equal to the value of Seconds_Of for the next second with a Sub_Second value of 0.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Seconds : @key<in> Day_Duration; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Splits Seconds into Hour, Minute, Second and Sub_Second in such a way that the resulting values all belong to their respective subtypes. The value returned in the Sub_Second parameter is always less than 1.0.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is only one way to do the split which meets all of the requirements.]} @end{Ramification} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Leap_Second is False, returns a Time built from the date and time values, relative to the specified time zone offset. If Leap_Second is True, returns the Time that represents the time within the leap second that is one second later than the time specified by the other parameters. Time_Error is raised if the parameters do not form a proper date or time. If Time_Of is called with a Sub_Second value of 1.0, the value returned is equal to the value of Time_Of for the next second with a Sub_Second value of 0.0.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Time_Error should be raised if Leap_Second is True, and the date and time values do not represent the second before a leap second. A leap second always occurs at midnight UTC, and is 23:59:60 UTC in ISO notation. So, if the time zone is UTC and Leap_Second is True, if any of Hour /= 23, Minute /= 59, or Second /= 59, then Time_Error should be raised. However, we do not say that, because other time zones will have different values where a leap second is allowed.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Leap_Second is False, returns a Time built from the date and time values, relative to the specified time zone offset. If Leap_Second is True, returns the Time that represents the time within the leap second that is one second later than the time specified by the other parameters. Time_Error is raised if the parameters do not form a proper date or time. If Time_Of is called with a Seconds value of 86_400.0, the value returned is equal to the value of Time_Of for the next day with a Seconds value of 0.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Date does not represent a time within a leap second, splits Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified time zone offset, and sets Leap_Second to False. If Date represents a time within a leap second, set the constituent parts to values corresponding to a time one second earlier than that given by Date, relative to the specified time zone offset, and sets Leap_Seconds to True. The value returned in the Sub_Second parameter is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Splits Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified time zone offset. The value returned in the Sub_Second parameter is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Seconds : @key<out> Day_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Date does not represent a time within a leap second, splits Date into its constituent parts (Year, Month, Day, Seconds), relative to the specified time zone offset, and sets Leap_Second to False. If Date represents a time within a leap second, set the constituent parts to values corresponding to a time one second earlier than that given by Date, relative to the specified time zone offset, and sets Leap_Seconds to True. The value returned in the Seconds parameter is always less than 86_400.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Image (Date : Time; Include_Time_Fraction : Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a string form of the Date relative to the given Time_Zone. The format is "Year-Month-Day Hour:Minute:Second", where the Year is a 4-digit value, and all others are 2-digit values, of the functions defined in Calendar and Calendar.Formatting, including a leading zero, if needed. The separators between the values are a minus, another minus, a colon, and a single space between the Day and Hour. If Include_Time_Fraction is True, the integer part of Sub_Seconds*100 is suffixed to the string as a point followed by a 2-digit value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Image provides a string in ISO 8601 format, the international standard time format. Alternative representations allowed in ISO 8601 are not supported here.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO 8601 allows 24:00:00 for midnight; and a seconds value of 60 for leap seconds. These are not allowed here (the routines mentioned above cannot produce those results).]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The fractional part is truncated, not rounded. It would be quite hard to define the result with proper rounding, as it can change all of the values of the image. Values can be rounded up by adding an appropriate constant (0.5 if Include_Time_Fraction is False, 0.005 otherwise) to the time before taking the image.]} @end{Ramification} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Value (Date : String; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Time value for the image given as Date, relative to the given time zone. Constraint_Error is raised if the string is not formatted as described for Image, or the function cannot interpret the given string as a Time value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intent is that the implementation enforce the same range rules on the string as the appropriate function Time_Of, except for the hour, so @lquotes@;cannot interpret the given string as a Time value@rquotes happens when one of the values is out of the required range. For example, "2005-08-31 24:0:0" should raise Constraint_Error (the hour is out of range).]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Image (Elapsed_Time : Duration; Include_Time_Fraction : Boolean := False) @key<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a string form of the Elapsed_Time. The format is "Hour:Minute:Second", where all values are 2-digit values, including a leading zero, if needed. The separators between the values are colons. If Include_Time_Fraction is True, the integer part of Sub_Seconds*100 is suffixed to the string as a point followed by a 2-digit value. If Elapsed_Time < 0.0, the result is Image (@key<abs> Elapsed_Time, Include_Time_Fraction) prefixed with a minus sign. If @key<abs> Elapsed_Time represents 100 hours or more, the result is implementation-defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The result of Calendar.Formating.Image if its argument represents more than 100 hours.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This cannot be implemented (directly) by calling Calendar.Formatting.Split, since it may be out of the range of Day_Duration, and thus the number of hours may be out of the range of Hour_Number.]} @ChgAdded{Version=[2],Text=[If a Duration value can represent more then 100 hours, the implementation will need to define a format for the return of Image.]} @end{ImplNote} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Value (Elapsed_Time : String) @key<return> Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Duration value for the image given as Elapsed_Time. Constraint_Error is raised if the string is not formatted as described for Image, or the function cannot interpret the given string as a Duration value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intent is that the implementation enforce the same range rules on the string as the appropriate function Time_Of, except for the hour, so @lquotes@;cannot interpret the given string as a Time value@rquotes happens when one of the values is out of the required range. For example, "10:23:60" should raise Constraint_Error (the seconds value is out of range).]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[An implementation should support leap seconds if the target system supports them. If leap seconds are not supported, Difference should return zero for Leap_Seconds, Split should return False for Leap_Second, and Time_Of should raise Time_Error if Leap_Second is True.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Leap seconds should be supported if the target system supports them. Otherwise, operations in Calendar.Formatting should return results consistent with no leap seconds.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An implementation can always support leap seconds when the target system does not; indeed, this isn't particularly hard (all that is required is a table of when leap seconds were inserted). As such, leap second support isn't @lquotes@;impossible or impractical@rquotes in the sense of @RefSecNum{Conformity of an Implementation with the Standard}. However, for some purposes, it may be important to follow the target system's lack of leap second support (if the target is a GPS satellite, which does not use leap seconds, leap second support would be a handicap to work around). Thus, this @ImplAdviceTitle should be read as giving permission to not support leap seconds on target systems that don't support leap seconds. Implementers should use the needs of their customers to determine whether or not support leap seconds on such targets.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[The implementation-defined time zone of package Calendar may, but need not, be the local time zone. UTC_Time_Offset always returns the difference relative to the implementation-defined time zone of package Calendar. If UTC_Time_Offset does not raise Unknown_Zone_Error, UTC time can be safely calculated (within the accuracy of the underlying time-base).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[The time in the time zone known as Greenwich Mean Time (GMT) is generally very close to UTC time; for most purposes they can be treated the same. GMT is the time based on the rotation of the Earth; UTC is the time based on atomic clocks, with leap seconds periodically inserted to realign with GMT (because most human activities depend on the rotation of the Earth). At any point in time, there will be a sub-second difference between GMT and UTC.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[Calling Split on the results of subtracting Duration(UTC_Time_Offset*60) from Clock provides the components (hours, minutes, and so on) of the UTC time. In the United States, for example, UTC_Time_Offset will generally be negative.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is an illustration to help specify the value of UTC_Time_Offset. A user should pass UTC_Time_Offset as the Time_Zone parameter of Split, rather than trying to make the above calculation.]} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Packages Calendar.Time_Zones, Calendar.Arithmetic, and Calendar.Formatting are new.]} @end{Extend95} @LabeledClause{Select Statements} @begin{Intro} @redundant[There are four forms of the @nt{select_statement}. One form provides a selective wait for one or more @nt{select_alternative}s. Two provide timed and conditional entry calls. The fourth provides asynchronous transfer of control.] @end{Intro} @begin{Syntax} @Syn{lhs=<select_statement>,rhs=" @Syn2{selective_accept} | @Syn2{timed_entry_call} | @Syn2{conditional_entry_call} | @Syn2{asynchronous_select}"} @end{Syntax} @begin{Examples} @leading@keepnext@i{Example of a select statement:} @begin{Example} @key(select) @key(accept) Driver_Awake_Signal; @key(or) @key(delay) 30.0*Seconds; Stop_The_Train; @key(end) @key(select); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} @nt{Asynchronous_select} is new. @end{Extend83} @LabeledSubClause{Selective Accept} @begin{Intro} @redundant[This form of the @nt{select_statement} allows a combination of waiting for, and selecting from, one or more alternatives. The selection may depend on conditions associated with each alternative of the @nt{selective_accept}. @IndexSee{Term=[time-out],See=(selective_accept)}] @end{Intro} @begin{Syntax} @Syn{lhs=<selective_accept>,rhs=" @key{select} [@Syn2{guard}] @Syn2{select_alternative} { @key{or} [@Syn2{guard}] @Syn2{select_alternative} } [ @key{else} @Syn2{sequence_of_statements} ] @key{end select};"} @Syn{lhs=<guard>,rhs="@key{when} @Syn2{condition} =>"} @Syn{lhs=<select_alternative>,rhs=" @Syn2{accept_alternative} | @Syn2{delay_alternative} | @Syn2{terminate_alternative}"} @Syn{lhs=<accept_alternative>,rhs=" @Syn2{accept_statement} [@Syn2{sequence_of_statements}]"} @Syn{lhs=<delay_alternative>,rhs=" @Syn2{delay_statement} [@Syn2{sequence_of_statements}]"} @Syn{lhs=<terminate_alternative>,rhs="@key{terminate};"} @begin(SyntaxText) @leading@;A @nt{selective_accept} shall contain at least one @nt{accept_alternative}. In addition, it can contain: @begin{itemize} a @nt{terminate_alternative} (only one); or one or more @nt{delay_alternative}s; or @Defn2{Term=[else part], Sec=(of a @nt<selective_accept>)} an @i(else part) (the reserved word @key(else) followed by a @nt<sequence_of_statements>). @end{itemize} These three possibilities are mutually exclusive. @end(SyntaxText) @end{Syntax} @begin{Legality} If a @nt{selective_accept} contains more than one @nt{delay_alternative}, then all shall be @nt<delay_@!relative_@!statement>s, or all shall be @nt<delay_@!until_@!statement>s for the same time type. @begin{Reason} This simplifies the implementation and the description of the semantics. @end{Reason} @end{Legality} @begin{RunTime} @Defn{open alternative} A @nt<select_alternative> is said to be @i(open) if it is not immediately preceded by a @nt<guard>, or if the @nt<condition> of its @nt<guard> evaluates to True. It is said to be @i(closed) otherwise. @PDefn2{Term=[execution], Sec=(selective_accept)} For the execution of a @nt{selective_accept}, any @nt{guard} @nt{condition}s are evaluated; open alternatives are thus determined. For an open @nt{delay_alternative}, the @i(delay_)@nt<expression> is also evaluated. Similarly, for an open @nt{accept_alternative} for an entry of a family, the @nt{entry_index} is also evaluated. These evaluations are performed in an arbitrary order, except that a @i(delay_)@nt<expression> or @nt<entry_index> is not evaluated until after evaluating the corresponding @nt<condition>, if any. Selection and execution of one open alternative, or of the else part, then completes the execution of the @nt{selective_accept}; the rules for this selection are described below. Open @nt{accept_alternative}s are first considered. Selection of one such alternative takes place immediately if the corresponding entry already has queued calls. If several alternatives can thus be selected, one of them is selected according to the entry queuing policy in effect (see @RefSecNum(Entry Calls) and @RefSecNum(Entry Queuing Policies)). When such an alternative is selected, the selected call is removed from its entry queue and the @nt<handled_sequence_of_@!statements> (if any) of the corresponding @nt{accept_statement} is executed; after the rendezvous completes any subsequent @nt<sequence_of_@!statements> of the alternative is executed. @PDefn2{Term=[blocked], Sec=(execution of a @nt<selective_accept>)} If no selection is immediately possible (in the above sense) and there is no else part, the task blocks until an open alternative can be selected. @leading@;Selection of the other forms of alternative or of an else part is performed as follows: @begin{itemize} An open @nt{delay_alternative} is selected when its expiration time is reached if no @nt{accept_@!alternative} or other @nt<delay_@!alternative> can be selected prior to the expiration time. If several @nt{delay_@!alternative}s have this same expiration time, one of them is selected according to the queuing policy in effect (see @RefSecNum{Entry Queuing Policies}); the default queuing policy chooses arbitrarily among the @nt<delay_@!alternative>s whose expiration time has passed. The else part is selected and its @nt<sequence_of_@!statements> is executed if no @nt{accept_alternative} can immediately be selected; in particular, if all alternatives are closed. An open @nt{terminate_alternative} is selected if the conditions stated at the end of clause @RefSecNum{Task Dependence - Termination of Tasks} are satisfied. @begin(Ramification) In the absence of a @nt<requeue_statement>, the conditions stated are such that a @nt<terminate_alternative> cannot be selected while there is a queued entry call for any entry of the task. In the presence of requeues from a task to one of its subtasks, it is possible that when a @nt<terminate_alternative> of the subtask is selected, requeued calls (for closed entries only) might still be queued on some entry of the subtask. Tasking_Error will be propagated to such callers, as is usual when a task completes while queued callers remain. @end(Ramification) @end{itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if all alternatives are closed and there is no else part. @end{RunTime} @begin{Notes} A @nt{selective_accept} is allowed to have several open @nt{delay_alternative}s. A @nt{selective_accept} is allowed to have several open @nt{accept_alternative}s for the same entry. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a task body with a selective accept:} @begin{Example} @key(task) @key(body) Server @key(is) Current_Work_Item : Work_Item; @key(begin) @key(loop) @key(select) @key(accept) Next_Work_Item(WI : @key(in) Work_Item) @key(do) Current_Work_Item := WI; @key(end); Process_Work_Item(Current_Work_Item); @key(or) @key(accept) Shut_Down; @key(exit); --@RI[ Premature shut down requested] @key(or) @key(terminate); --@RI[ Normal shutdown at end of scope] @key(end) @key(select); @key(end) @key(loop); @key(end) Server; @end{Example} @end{Examples} @begin{DiffWord83} The name of @ntf{selective_wait} was changed to @nt{selective_accept} to better describe what is being waited for. We kept @nt{select_alternative} as is, because @ntf<selective_accept_alternative> was too easily confused with @nt<accept_alternative>. @end{DiffWord83} @LabeledSubClause{Timed Entry Calls} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @redundant[A @nt{timed_entry_call} issues an entry call that is cancelled if the call (or a requeue-with-abort of the call) is not selected before the expiration time is reached.@Chg{Version=[2],New=[ A procedure call may appear rather than an entry call for cases where the procedure might be implemented by an entry.],Old=[]} @IndexSee{Term=[time-out],See=(timed_entry_call)}] @end{Intro} @begin{Syntax} @Syn{lhs=<timed_entry_call>,rhs=" @key{select} @Syn2{entry_call_alternative} @key{or} @Syn2{delay_alternative} @key{end select};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<entry_call_alternative>,rhs=" @Chg{Version=[2],New=[@Syn2{procedure_or_entry_call}],Old=[@Syn2{entry_call_statement}]} [@Syn2{sequence_of_statements}]"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[procedure_or_entry_call],Old=[]}>,rhs=" @Chg{Version=[2],New=[@Syn2{procedure_call_statement} | @Syn2{entry_call_statement}],Old=[]}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If a @nt{procedure_call_statement} is used for a @nt{procedure_or_entry_call}, the @SynI{procedure_}@nt{name} or @SynI{procedure_}@nt{prefix} of the @nt{procedure_call_statement} shall statically denote an entry renamed as a procedure or (a view of) a primitive subprogram of a limited interface whose first parameter is a controlling parameter (see @RefSecNum{Dispatching Operations of Tagged Types}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This would be a confusing way to call a procedure, so we only allow it when it is possible that the procedure is actually an entry. We could have allowed formal subprograms here, but we didn't because we'd have to allow all formal subprograms, and it would increase the difficulty of generic code sharing.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We say @lquotes@;statically denotes@rquotes because an access-to-subprogram cannot be primitive, and we don't have anything like access-to-entry. So only names of entries or procedures are possible.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If a @nt{procedure_call_statement} is used for a @nt{procedure_or_entry_call}, and the procedure is implemented by an entry, then the @SynI{procedure_}@nt{name}, or @SynI{procedure_}@nt{prefix} and possibly the first parameter of the @nt{procedure_call_statement}, determine the target object of the call and the entry to be called.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above says @lquotes@;possibly the first parameter@rquotes@;, because Ada allows entries to be renamed and passed as formal subprograms. In those cases, the task or protected object is implicit in the name of the routine; otherwise the object is an explicit parameter to the call.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(timed_entry_call)} For the execution of a @nt{timed_entry_call}, the @SynI(entry_)@nt<name>@Chg{Version=[2], New=[, @Syni{procedure_}@nt{name}, or @Syni{procedure_}@nt{prefix},],Old=[]} and any actual parameters are evaluated, as for a simple entry call (see @RefSecNum(Entry Calls))@Chg{Version=[2],New=[ or procedure call (see @RefSecNum{Subprogram Calls})],Old=[]}. The expiration time (see @RefSecNum(Delay Statements, Duration, and Time)) for the call is determined by evaluating the @i(delay_)@nt<expression> of the @nt<delay_alternative>@Chg{Version=[2],New=[. If the call is an entry call or a call on a procedure implemented by an entry,],Old=[;]} the entry call is then issued.@Chg{Version=[2],New=[ Otherwise, the call proceeds as described in @RefSecNum{Subprogram Calls} for a procedure call, followed by the @nt{sequence_of_@!statements} of the @nt{entry_call_@!alternative}; the @nt{sequence_of_@!statements} of the @nt{delay_@!alternative} is ignored.],Old=[]} If the call is queued (including due to a requeue-with-abort), and not selected before the expiration time is reached, an attempt to cancel the call is made. If the call completes due to the cancellation, the optional @nt<sequence_of_@!statements> of the @nt<delay_@!alternative> is executed; if the entry call completes normally, the optional @nt<sequence_of_@!statements> of the @nt<entry_call_@!alternative> is executed. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00345-01]} @ChgDeleted{Version=[2],Text=[The fact that the syntax calls for an @nt{entry_call_statement} means that this fact is used in overload resolution. For example, if there is a procedure X and an entry X (both with no parameters), then "select X; ..." is legal, because overload resolution knows that the entry is the one that was meant.]} @end{Ramification} @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of a timed entry call:} @begin{Example} @key(select) Controller.Request(Medium)(Some_Item); @key(or) @key(delay) 45.0; --@RI[ controller too busy, try something else] @key(end) @key(select); @end{Example} @end{Examples} @begin{DiffWord83} This clause comes before the one for Conditional Entry Calls, so we can define conditional entry calls in terms of timed entry calls. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} A procedure can be used as the in a timed or conditional entry call, if the procedure might actually be an entry. Since the fact that something is an entry could be used in resolving these calls in Ada 95, it is possible for timed or conditional entry calls that resolved in Ada 95 to be ambiguous in Ada 2005. That could happen if both an entry and procedure with the same name and profile exist, which should be rare.]} @end{Incompatible95} @LabeledSubClause{Conditional Entry Calls} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Redundant[A @nt{conditional_entry_call} issues an entry call that is then cancelled if it is not selected immediately (or if a requeue-with-abort of the call is not selected immediately).@Chg{Version=[2],New=[ A procedure call may appear rather than an entry call for cases where the procedure might be implemented by an entry.],Old=[]}] @begin(Honest) In the case of an entry call on a protected object, it is OK if the entry is closed at the start of the corresponding protected action, so long as it opens and the call is selected before the end of that protected action (due to changes in the Count attribute). @end(Honest) @end{Intro} @begin{Syntax} @Syn{lhs=<conditional_entry_call>,rhs=" @key{select} @Syn2{entry_call_alternative} @key{else} @Syn2{sequence_of_statements} @key{end select};"} @end{Syntax} @begin{RunTime} @PDefn2{Term=[execution], Sec=(conditional_entry_call)} The execution of a @nt<conditional_entry_call> is defined to be equivalent to the execution of a @nt<timed_@!entry_@!call> with a @nt<delay_@!alternative> specifying an immediate expiration time and the same @nt<sequence_of_@!statements> as given after the reserved word @key(else). @end{RunTime} @begin{Notes} A @nt{conditional_entry_call} may briefly increase the Count attribute of the entry, even if the conditional call is not selected. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a conditional entry call:} @begin{Example} @key(procedure) Spin(R : @key[in] Resource) @key(is) @key(begin) @key(loop) @key(select) R.Seize; @key(return); @key(else) @key(null); --@RI[ busy waiting] @key(end) @key(select); @key(end) @key(loop); @key(end); @end{Example} @end{Examples} @begin{DiffWord83} This clause comes after the one for Timed Entry Calls, so we can define conditional entry calls in terms of timed entry calls. We do that so that an "expiration time" is defined for both, thereby simplifying the definition of what happens on a requeue-with-abort. @end{DiffWord83} @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledSubClause{Asynchronous Transfer of Control} @begin{Intro} @redundant[An asynchronous @nt{select_statement} provides asynchronous transfer of control upon completion of an entry call or the expiration of a delay.] @end{Intro} @begin{Syntax} @Syn{lhs=<asynchronous_select>,rhs=" @key{select} @Syn2{triggering_alternative} @key{then abort} @Syn2{abortable_part} @key{end select};"} @Syn{lhs=<triggering_alternative>,rhs="@Syn2{triggering_statement} [@Syn2{sequence_of_statements}]"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<triggering_statement>,rhs="@Chg{Version=[2],New=[@Syn2{procedure_or_entry_call}],Old=[@Syn2{entry_call_statement}]} | @Syn2{delay_statement}"} @Syn{lhs=<abortable_part>,rhs="@Syn2{sequence_of_statements}"} @end{Syntax} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(asynchronous_select with an entry call trigger)} @Chg{Version=[2],New=[@PDefn2{Term=[execution], Sec=(asynchronous_select with a procedure call trigger)}],Old=[]} For the execution of an @nt{asynchronous_select} whose @nt<triggering_@!statement> is @Chg{Version=[2], New=[a @nt<procedure_or_entry_call>],Old=[an @nt<entry_call_statement>]}, the @Syni(entry_)@nt<name>@Chg{Version=[2],New=[, @Syni{procedure_}@nt{name}, or @Syni{procedure_}@nt{prefix},],Old=[]} and actual parameters are evaluated as for a simple entry call (see @RefSecNum(Entry Calls))@Chg{Version=[2],New=[ or procedure call (see @RefSecNum{Subprogram Calls}). If the call is an entry call or a call on a procedure implemented by an entry,],Old=[, and]} the entry call is issued. If the entry call is queued (or requeued-with-abort), then the @nt<abortable_part> is executed. @Redundant[If the entry call is selected immediately, and never requeued-with-abort, then the @nt<abortable_part> is never started.]@Chg{Version=[2],New=[ If the call is on a procedure that is not implemented by an entry, the call proceeds as described in @RefSecNum{Subprogram Calls}, followed by the @nt{sequence_of_@!statements} of the @nt{triggering_@!alternative}@Redundant[; the @nt{abortable_part} is never started].],Old=[]} @PDefn2{Term=[execution], Sec=(asynchronous_select with a delay_statement trigger)} For the execution of an @nt<asynchronous_select> whose @nt<triggering_@!statement> is a @nt<delay_statement>, the @i(delay_)@nt<expression> is evaluated and the expiration time is determined, as for a normal @nt<delay_statement>. If the expiration time has not already passed, the @nt<abortable_part> is executed. If the @nt<abortable_part> completes and is left prior to completion of the @nt<triggering_@!statement>, an attempt to cancel the @nt<triggering_@!statement> is made. If the attempt to cancel succeeds (see @RefSecNum(Entry Calls) and @RefSecNum(Delay Statements, Duration, and Time)), the @nt<asynchronous_select> is complete. If the @nt<triggering_@!statement> completes other than due to cancellation, the @nt<abortable_part> is aborted (if started but not yet completed @em see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). If the @nt<triggering_@!statement> completes normally, the optional @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> is executed after the @nt<abortable_part> is left. @begin(Discussion) We currently don't specify when the by-copy [@key(in)] @key(out) parameters are assigned back into the actuals. We considered requiring that to happen after the @nt<abortable_part> is left. However, that doesn't seem useful enough to justify possibly overspecifying the implementation approach, since some of the parameters are passed by reference anyway. In an earlier description, we required that the @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> execute after aborting the @nt<abortable_part>, but before waiting for it to complete and finalize, to provide more rapid response to the triggering event in case the finalization was unbounded. However, various reviewers felt that this created unnecessary complexity in the description, and a potential for undesirable concurrency (and nondeterminism) within a single task. We have now reverted to simpler, more deterministic semantics, but anticipate that further discussion of this issue might be appropriate during subsequent reviews. One possibility is to leave this area implementation defined, so as to encourage experimentation. The user would then have to assume the worst about what kinds of actions are appropriate for the @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> to achieve portability. @end(Discussion) @end{RunTime} @begin{Examples} @leading@keepnext@Defn2{Term=[signal handling], Sec=(example)} @Defn2{Term=[interrupt],Sec=(example using @nt<asynchronous_select>)} @Defn2{Term=[terminal interrupt], Sec=(example)} @i(Example of a main command loop for a command interpreter:) @begin(Example) @key(loop) @key(select) Terminal.Wait_For_Interrupt; Put_Line("Interrupted"); @key(then abort) -- @RI(This will be abandoned upon terminal interrupt) Put_Line("-> "); Get_Line(Command, Last); Process_Command(Command(1..Last)); @key(end) @key(select); @key(end) @key(loop); @end(Example) @begin{Wide} @leading@keepnext@i(Example of a time-limited calculation:) @IndexSee{Term=[time-out],See=(asynchronous_select)} @Defn2{Term=[time-out],Sec=(example)} @Defn2{Term=[time limit],Sec=(example)} @Defn2{Term=[interrupt],Sec=(example using @nt<asynchronous_select>)} @Defn2{Term=[timer interrupt],Sec=(example)} @end{Wide} @begin(Example) @key(select) @key(delay) 5.0; Put_Line("Calculation does not converge"); @key(then abort) -- @RI(This calculation should finish in 5.0 seconds;) -- @RI( if not, it is assumed to diverge.) Horribly_Complicated_Recursive_Function(X, Y); @key(end) @key(select); @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} @nt<Asynchronous_select> is new. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A procedure can be used as the @nt{triggering_@!statement} of an @nt<asynchronous_select>, if the procedure might actually be an entry]} @end{Extend95} @LabeledClause{Abort of a Task - Abort of a Sequence of Statements} @begin{Intro} @redundant[An @nt{abort_statement} causes one or more tasks to become abnormal, thus preventing any further interaction with such tasks. The completion of the @nt<triggering_@!statement> of an @nt<asynchronous_select> causes a @nt{sequence_of_@!statements} to be aborted.] @end{Intro} @begin{Syntax} @Syn{lhs=<abort_statement>, rhs="@key{abort} @SynI{task_}@Syn2{name} {, @SynI{task_}@Syn2{name}};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(abort_statement task_name)} Each @SynI{task_}@nt{name} is expected to be of any task type@Redundant[; they need not all be of the same task type.] @end{Resolution} @begin{RunTime} @PDefn2{Term=[execution], Sec=(abort_statement)} For the execution of an @nt<abort_statement>, the given @i(task_)@nt<name>s are evaluated in an arbitrary order. @Defn2{Term=[abort], Sec=(of a task)} @Defn{abnormal task} @PDefn2{Term=[task state], Sec=(abnormal)} Each named task is then @i(aborted), which consists of making the task @i(abnormal) and aborting the execution of the corresponding @nt<task_body>, unless it is already completed. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Note that aborting those tasks is not defined to be an abort-deferred operation. Therefore, if one of the named tasks is the task executing the @nt{abort_statement}, or if the task executing the @nt{abort_statement} depends on one of the named tasks, then it is possible for the execution of the @nt{abort_statement} to be aborted, thus leaving some of the tasks unaborted. This allows the implementation to use either a sequence of calls to an @lquotes@;abort task@rquotes@; @Chg{Version=[2],New=[run-time system],Old=[RTS]} primitive, or a single call to an @lquotes@;abort list of tasks@rquotes@; @Chg{Version=[2],New=[run-time system],Old=[RTS]} primitive. @end{Ramification} @leading@PDefn2{Term=[execution], Sec=(aborting the execution of a construct)} @Defn2{Term=[abort], Sec=(of the execution of a construct)} When the execution of a construct is @i(aborted) (including that of a @nt<task_@!body> or of a @nt<sequence_of_@!statements>), the execution of every construct included within the aborted execution is also aborted, except for executions included within the execution of an @i(abort-deferred) operation; the execution of an abort-deferred operation continues to completion without being affected by the abort; @Defn{abort-deferred operation} the following are the abort-deferred operations: @begin(Itemize) a protected action; waiting for an entry call to complete (after having initiated the attempt to cancel it @em see below); waiting for the termination of dependent tasks; the execution of an Initialize procedure as the last step of the default initialization of a controlled object; the execution of a Finalize procedure as part of the finalization of a controlled object; an assignment operation to an object with a controlled part. @end(Itemize) @Redundant[The last three of these are discussed further in @RefSecNum(User-Defined Assignment and Finalization).] @begin{Reason} Deferring abort during Initialize and finalization allows, for example, the result of an allocator performed in an Initialize operation to be assigned into an access object without being interrupted in the middle, which would cause storage leaks. For an object with several controlled parts, each individual Initialize is abort-deferred. Note that there is generally no semantic difference between making each Finalize abort-deferred, versus making a group of them abort-deferred, because if the task gets aborted, the first thing it will do is complete any remaining finalizations. Individual objects are finalized prior to an assignment operation (if nonlimited controlled) and as part of Unchecked_Deallocation. @end{Reason} @begin(Ramification) Abort is deferred during the entire assignment operation to an object with a controlled part, even if only some subcomponents are controlled. Note that this says "assignment operation," not "@nt{assignment_statement}." Explicit calls to Initialize, Finalize, or Adjust are not abort-deferred. @end(Ramification) When a master is aborted, all tasks that depend on that master are aborted. @PDefn{unspecified} The order in which tasks become abnormal as the result of an @nt<abort_statement> or the abort of a @nt<sequence_of_@!statements> is not specified by the language. @leading@;If the execution of an entry call is aborted, an immediate attempt is made to cancel the entry call (see @RefSecNum(Entry Calls)). If the execution of a construct is aborted at a time when the execution is blocked, other than for an entry call, at a point that is outside the execution of an abort-deferred operation, then the execution of the construct completes immediately. For an abort due to an @nt<abort_statement>, these immediate effects occur before the execution of the @nt<abort_statement> completes. Other than for these immediate cases, the execution of a construct that is aborted does not necessarily complete before the @nt<abort_statement> completes. However, the execution of the aborted construct completes no later than its next @i(abort completion point) (if any) that occurs outside of an abort-deferred operation; @Defn{abort completion point} the following are abort completion points for an execution: @begin(Itemize) the point where the execution initiates the activation of another task; the end of the activation of a task; the start or end of the execution of an entry call, @nt<accept_statement>, @nt<delay_statement>, or @nt<abort_statement>; @begin(Ramification) Although the abort completion point doesn't occur until the end of the entry call or @nt<delay_statement>, these operations might be cut short because an abort attempts to cancel them. @end(Ramification) the start of the execution of a @nt<select_statement>, or of the @nt<sequence_of_@!statements> of an @nt<exception_handler>. @begin(Reason) The start of an @nt<exception_handler> is considered an abort completion point simply because it is easy for an implementation to check at such points. @end(Reason) @begin(ImplNote) Implementations may of course check for abort more often than at each abort completion point; ideally, a fully preemptive implementation of abort will be provided. If preemptive abort is not supported in a given environment, then supporting the checking for abort as part of subprogram calls and loop iterations might be a useful option. @end(ImplNote) @end(Itemize) @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} An attempt to execute an @nt<asynchronous_select> as part of the execution of an abort-deferred operation is a bounded error. Similarly, an attempt to create a task that depends on a master that is included entirely within the execution of an abort-deferred operation is a bounded error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} In both cases, Program_Error is raised if the error is detected by the implementation; otherwise the operations proceed as they would outside an abort-deferred operation, except that an abort of the @nt<abortable_part> or the created task might or might not have an effect. @begin(Reason) An @nt<asynchronous_select> relies on an abort of the @nt<abortable_part> to effect the asynchronous transfer of control. For an @nt<asynchronous_select> within an abort-deferred operation, the abort might have no effect. Creating a task dependent on a master included within an abort-deferred operation is considered an error, because such tasks could be aborted while the abort-deferred operation was still progressing, undermining the purpose of abort-deferral. Alternatively, we could say that such tasks are abort-deferred for their entire execution, but that seems too easy to abuse. Note that task creation is already a bounded error in protected actions, so this additional rule only applies to local task creation as part of Initialize, Finalize, or Adjust. @end(Reason) @end{Bounded} @begin{Erron} @PDefn{normal state of an object} @PDefn{abnormal state of an object} @Defn{disruption of an assignment} @PDefn2{Term=(erroneous execution),Sec=(cause)} If an assignment operation completes prematurely due to an abort, the assignment is said to be @i{disrupted}; the target of the assignment or its parts can become abnormal, and certain subsequent uses of the object can be erroneous, as explained in @RefSecNum{Data Validity}. @end{Erron} @begin{Notes} An @nt{abort_statement} should be used only in situations requiring unconditional termination. A task is allowed to abort any task it can name, including itself. Additional requirements associated with abort are given in @RefSec(Preemptive Abort). @end{Notes} @begin{DiffWord83} This clause has been rewritten to accommodate the concept of aborting the execution of a construct, rather than just of a task. @end{DiffWord83} @LabeledClause{Task and Entry Attributes} @begin{RunTime} @leading@; For @PrefixType{a @nt<prefix> T that is of a task type @Redundant[(after any implicit dereference)]}, the following attributes are defined: @begin{Description} @Comment{@ChgAttribute{Version=[2], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<T>, AttrName=<Callable>, ARef=[AI95-00345], Text=<Yields the value True when the task denoted by T is @i(callable), and False otherwise;>} @PDefn2{Term=[task state], Sec=(callable)} @Defn{callable} a task is callable unless it is completed or abnormal. The value of this attribute is of the predefined type Boolean.} @Attribute{Prefix=<T>, AttrName=<Callable>, Text=<Yields the value True when the task denoted by T is @i(callable), and False otherwise;>} @PDefn2{Term=[task state], Sec=(callable)} @Defn{callable} a task is callable unless it is completed or abnormal. The value of this attribute is of the predefined type Boolean. @Attribute{Prefix=<T>, AttrName=<Terminated>, Text=<Yields the value True if the task denoted by T is terminated, and False otherwise. The value of this attribute is of the predefined type Boolean.>} @end{Description} @EndPrefixType{} For @PrefixType{a @nt<prefix> E that denotes an entry of a task or protected unit}, the following attribute is defined. This attribute is only allowed within the body of the task or protected unit, but excluding, in the case of an entry of a task unit, within any program unit that is, itself, inner to the body of the task unit. @begin{Description} @Attribute{Prefix=<E>, AttrName=<Count>, Text=<Yields the number of calls presently queued on the entry E of the current instance of the unit. The value of this attribute is of the type @i{universal_integer}.>} @end{Description} @EndPrefixType{} @end{RunTime} @begin{Notes} For the Count attribute, the entry can be either a single entry or an entry of a family. The name of the entry or entry family can be either a @nt<direct_name> or an expanded name. Within task units, algorithms interrogating the attribute E'Count should take precautions to allow for the increase of the value of this attribute for incoming entry calls, and its decrease, for example with @nt{timed_entry_call}s. Also, a @nt{conditional_entry_call} may briefly increase this value, even if the conditional call is not accepted. Within protected units, algorithms interrogating the attribute E'Count in the @nt<entry_barrier> for the entry E should take precautions to allow for the evaluation of the @nt<condition> of the barrier both before and after queuing a given caller. @end{Notes} @LabeledClause{Shared Variables} @begin{StaticSem} @Defn2{Term=[shared variable], Sec=(protection of)} @Defn{independently addressable} If two different objects, including nonoverlapping parts of the same object, are @i{independently addressable}, they can be manipulated concurrently by two different tasks without synchronization. Normally, any two nonoverlapping objects are independently addressable. However, if packing, record layout, or Component_Size is specified for a given composite object, then it is implementation defined whether or not two nonoverlapping parts of that composite object are independently addressable. @ImplDef{Whether or not two nonoverlapping parts of a composite object are independently addressable, in the case where packing, record layout, or Component_Size is specified for the object.} @begin{ImplNote} Independent addressability is the only high level semantic effect of a @nt{pragma} Pack. If two objects are independently addressable, the implementation should allocate them in such a way that each can be written by the hardware without writing the other. For example, unless the user asks for it, it is generally not feasible to choose a bit-packed representation on a machine without an atomic bit field insertion instruction, because there might be tasks that update neighboring subcomponents concurrently, and locking operations on all subcomponents is generally not a good idea. Even if packing or one of the other above-mentioned aspects is specified, subcomponents should still be updated independently if the hardware efficiently supports it. @end{ImplNote} @end{StaticSem} @begin{RunTime} @leading@redundant[Separate tasks normally proceed independently and concurrently with one another. However, task interactions can be used to synchronize the actions of two or more tasks to allow, for example, meaningful communication by the direct updating and reading of variables shared between the tasks.] The actions of two different tasks are synchronized in this sense when an action of one task @i(signals) an action of the other task; @Defn2{Term=[signal], Sec=(as defined between actions)} an action A1 is defined to signal an action A2 under the following circumstances: @begin(Itemize) If A1 and A2 are part of the execution of the same task, and the language rules require A1 to be performed before A2; If A1 is the action of an activator that initiates the activation of a task, and A2 is part of the execution of the task that is activated; If A1 is part of the activation of a task, and A2 is the action of waiting for completion of the activation; If A1 is part of the execution of a task, and A2 is the action of waiting for the termination of the task; @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0031],ARef=[AI95-00118-01]} @ChgAdded{Version=[1],Text=[If A1 is the termination of a task T, and A2 is either the evaluation of the expression T'Terminated or a call to Ada.Task_Identification.Is_Terminated with an actual parameter that identifies T (see @RefSecNum(The Package Task_Identification));]} If A1 is the action of issuing an entry call, and A2 is part of the corresponding execution of the appropriate @nt<entry_body> or @nt<accept_statement>. @begin(Ramification) Evaluating the @nt<entry_index> of an @nt<accept_statement> is not synchronized with a corresponding entry call, nor is evaluating the entry barrier of an @nt<entry_body>. @end(Ramification) If A1 is part of the execution of an @nt<accept_statement> or @nt<entry_body>, and A2 is the action of returning from the corresponding entry call; If A1 is part of the execution of a protected procedure body or @nt<entry_body> for a given protected object, and A2 is part of a later execution of an @nt<entry_body> for the same protected object; @begin(Reason) The underlying principle here is that for one action to @lquotes@;signal@rquotes@; a second, the second action has to follow a potentially blocking operation, whose blocking is dependent on the first action in some way. Protected procedures are not potentially blocking, so they can only be "signalers," they cannot be signaled. @end(Reason) @begin(Ramification) Protected subprogram calls are not defined to signal one another, which means that such calls alone cannot be used to synchronize access to shared data outside of a protected object. @end(Ramification) @begin(Reason) The point of this distinction is so that on multiprocessors with inconsistent caches, the caches only need to be refreshed at the beginning of an entry body, and forced out at the end of an entry body or protected procedure that leaves an entry open. Protected function calls, and protected subprogram calls for entryless protected objects do not require full cache consistency. Entryless protected objects are intended to be treated roughly like atomic objects @em each operation is indivisible with respect to other operations (unless both are reads), but such operations cannot be used to synchronize access to other nonvolatile shared variables. @end(Reason) @Leading@Comment{This "Leading" is to help fit the next example on one page.} If A1 signals some action that in turn signals A2. @end(Itemize) @end{RunTime} @begin{Erron} @Leading@;@PDefn2{Term=(erroneous execution),Sec=(cause)} Given an action of assigning to an object, and an action of reading or updating a part of the same object (or of a neighboring object if the two are not independently addressable), then the execution of the actions is erroneous unless the actions are @i(sequential). @Defn2{Term=[sequential], Sec=(actions)} Two actions are sequential if one of the following is true: @begin(Itemize) One action signals the other; Both actions occur as part of the execution of the same task; @begin{Reason} Any two actions of the same task are sequential, even if one does not signal the other because they can be executed in an @lquotes@;arbitrary@rquotes@; (but necessarily equivalent to some @lquotes@;sequential@rquotes@;) order. @end{Reason} Both actions occur as part of protected actions on the same protected object, and at most one of the actions is part of a call on a protected function of the protected object. @begin(Reason) Because actions within protected actions do not always imply signaling, we have to mention them here explicitly to make sure that actions occurring within different protected actions of the same protected object are sequential with respect to one another (unless both are part of calls on protected functions). @end(Reason) @begin(Ramification) It doesn't matter whether or not the variable being assigned is actually a subcomponent of the protected object; globals can be safely updated from within the bodies of protected procedures or entries. @end(Ramification) @end(Itemize) A @nt{pragma} Atomic or Atomic_Components may also be used to ensure that certain reads and updates are sequential @em see @RefSecNum(Shared Variable Control). @begin(Ramification) If two actions are @lquotes@;sequential@rquotes@; it is known that their executions don't overlap in time, but it is not necessarily specified which occurs first. For example, all actions of a single task are sequential, even though the exact order of execution is not fully specified for all constructs. @end(Ramification) @begin(Discussion) Note that if two assignments to the same variable are sequential, but neither signals the other, then the program is not erroneous, but it is not specified which assignment ultimately prevails. Such a situation usually corresponds to a programming mistake, but in some (rare) cases, the order makes no difference, and for this reason this situation is not considered erroneous nor even a bounded error. In Ada 83, this was considered an @lquotes@;incorrect order dependence@rquotes@; if the @lquotes@;effect@rquotes@; of the program was affected, but @lquotes@;effect@rquotes@; was never fully defined. In Ada 95, this situation represents a potential nonportability, and a friendly compiler might want to warn the programmer about the situation, but it is not considered an error. An example where this would come up would be in gathering statistics as part of referencing some information, where the assignments associated with statistics gathering don't need to be ordered since they are just accumulating aggregate counts, sums, products, etc. @end(Discussion) @end{Erron} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0031],ARef=[AI95-00118-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a task T2 can rely on values of variables that are updated by another task T1, if task T2 first verifies that T1'Terminated is True.]} @end{DiffWord95} @LabeledClause{Example of Tasking and Synchronization} @begin{Examples} @Leading@;The following example defines a buffer protected object to smooth variations between the speed of output of a producing task and the speed of input of some consuming task. For instance, the producing task might have the following structure: @begin(Example) @key(task) Producer; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(task body) Producer @key(is) @Chg{Version=[2],New=[Person : Person_Name; --@RI[ see @RefSecNum{Incomplete Type Declarations}]],Old=[Char : Character;]} @key(begin) @key(loop) ... --@RI[ @Chg{Version=[2],New=[simulate arrival of the next customer],Old=[produce the next character Char]}] Buffer.@Chg{Version=[2],New=[Append_Wait(Person)],Old=[Write(Char)]}; @key(exit) @key(when) @Chg{Version=[2],New=[Person = @key(null)],Old=[Char = ASCII.EOT]}; @key(end) @key(loop); @key(end) Producer; @end(Example) @leading@keepnext@;and the consuming task might have the following structure: @begin(Example) @key(task) Consumer; @Trailing@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]}@key(task body) Consumer @key(is) @Chg{Version=[2],New=[Person : Person_Name;],Old=[Char : Character;]} @key(begin) @key(loop) Buffer.@Chg{Version=[2],New=[Remove_First_Wait(Person)],Old=[Read(Char)]}; @key(exit) @key(when) @Chg{Version=[2],New=[Person = @key(null)],Old=[Char = ASCII.EOT]}; ... --@RI[ @Chg{Version=[2],New=[simulate serving a customer],Old=[consume the character Char]}] @key(end) @key(loop); @key(end) Consumer; @end(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} The buffer object contains an internal @Chg{Version=[2],New=[array],Old=[pool]} of @Chg{Version=[2],New=[person names],Old=[characters]} managed in a round-robin fashion. The @Chg{Version=[2],New=[array],Old=[pool]} has two indices, an In_Index denoting the @Chg{Version=[2],New=[index],Old=[space]} for the next input @Chg{Version=[2],New=[person name],Old=[character]} and an Out_Index denoting the @Chg{Version=[2],New=[index],Old=[space]} for the next output @Chg{Version=[2],New=[person name],Old=[character]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The Buffer is defined as an extension of the Synchronized_Queue interface (see @RefSecNum{Interface Types}), and as such promises to implement the abstraction defined by that interface. By doing so, the Buffer can be passed to the Transfer class-wide operation defined for objects of a type covered by Queue'Class.]} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(protected) Buffer @key(is)@Chg{Version=[2],New=[ @key(new) Synchronized_Queue @key(with) --@RI[ see @RefSecNum{Interface Types}]],Old=[]} @key(entry) @Chg{Version=[2],New=[Append_Wait(Person : @key(in) Person_Name);],Old=[Read (C : @key(out) Character);]} @key(entry) @Chg{Version=[2],New=[Remove_First_Wait(Person : @key(out) Person_Name); @key(function) Cur_Count @key(return) Natural; @key(function) Max_Count @key(return) Natural; @key(procedure) Append(Person : @key(in) Person_Name); @key(procedure) Remove_First(Person : @key(out) Person_Name);],Old=[Write(C : @key(in) Character);]} @key(private) Pool : @Chg{Version=[2],New=[Person_Name_Array],Old=[String]}(1 .. 100); Count : Natural := 0; In_Index, Out_Index : Positive := 1; @key(end) Buffer; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(protected body) Buffer @key(is) @key(entry) @Chg{Version=[2],New=[Append_Wait(Person : @key(in) Person_Name)],Old=[Write(C : @key(in) Character)]} @key(when) Count < Pool'Length @key(is) @key(begin) @Chg{Version=[2],New=[Append(Person);],Old=[Pool(In_Index) := C; In_Index := (In_Index @key(mod) Pool'Length) + 1; Count := Count + 1;]} @key(end) @Chg{Version=[2],New=[Append_Wait],Old=[Write]}; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(procedure) Append(Person : @key(in) Person_Name) @key(is) @key(begin) @key(if) Count = Pool'Length @key(then) @key(raise) Queue_Error @key(with) "Buffer Full"; --@RI[ see @RefSecNum{Raise Statements}] @key(end if); Pool(In_Index) := Person; In_Index := (In_Index @key(mod) Pool'Length) + 1; Count := Count + 1; @key(end) Append;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(entry) @Chg{Version=[2],New=[Remove_First_Wait(Person : @key(out) Person_Name)],Old=[Read(C : @key(out) Character)]} @key(when) Count > 0 @key(is) @key(begin) @Chg{Version=[2],New=[Remove_First(Person);],Old=[C := Pool(Out_Index); Out_Index := (Out_Index @key(mod) Pool'Length) + 1; Count := Count - 1;]} @key(end) @Chg{Version=[2],New=[Remove_First_Wait],Old=[Read; @key(end) Buffer]}; @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(procedure) Remove_First(Person : @key(out) Person_Name) @key(is) @key(begin) @key(if) Count = 0 @key(then) @key(raise) Queue_Error @key(with) "Buffer Empty"; --@RI[ see @RefSecNum{Raise Statements}] @key(end if); Person := Pool(Out_Index); Out_Index := (Out_Index @key(mod) Pool'Length) + 1; Count := Count - 1; @key(end) Remove_First;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(function) Cur_Count @key(return) Natural @key(is) @key(begin) @key(return) Buffer.Count; @key(end) Cur_Count;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(function) Max_Count @key(return) Natural @key(is) @key(begin) @key(return) Pool'Length; @key(end) Max_Count; @key(end) Buffer;]} @end(Example) @end{Examples} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/10.mss���������������������������������������������������������������0000755�0001752�0001001�00000460532�12273462240�016377� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(10, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:25 $} @LabeledSection{Program Structure and Compilation Issues} @Comment{$Source: e:\\cvsroot/ARM/Source/10.mss,v $} @Comment{$Revision: 1.72 $} @Comment{Corrigendum changes added, 2000/04/24, RLB} @begin{Intro} @redundant[The overall structure of programs and the facilities for separate compilation are described in this section. A @i(program) is a set of @i(partitions), each of which may execute in a separate address space, possibly on a separate computer. @ToGlossary{Term=<Program>, Text=<A @i(program) is a set of @i(partitions), each of which may execute in a separate address space, possibly on a separate computer. A partition consists of a set of library units.>} @ToGlossary{Term=<Partition>, Text=<A @i(partition) is a part of a program. Each partition consists of a set of library units. Each partition may run in a separate address space, possibly on a separate computer. A program may contain just one partition. A distributed program typically contains multiple partitions, which can execute concurrently.>} @Defn2{Term=[library unit],Sec=(informal introduction)} @Defn2{Term=[library_item],Sec=(informal introduction)} @Defn2{Term=[library],Sec=(informal introduction)} As explained below, a partition is constructed from @i{library units}. Syntactically, the declaration of a library unit is a @nt{library_item}, as is the body of a library unit. An implementation may support a concept of a @i{program library} (or simply, a @lquotes@;library@rquotes@;), which contains @nt{library_item}s and their subunits. @IndexSee{Term=[program library],See=(library)} Library units may be organized into a hierarchy of children, grandchildren, and so on.] This section has two clauses: @RefSec{Separate Compilation} discusses compile-time issues related to separate compilation. @RefSec{Program Execution} discusses issues related to what is traditionally known as @lquotes@;link time@rquotes@; and @lquotes@;run time@rquotes@; @em building and executing partitions. @end{Intro} @begin{MetaRules} @Defn{avoid overspecifying environmental issues} We should avoid specifying details that are outside the domain of the language itself. The standard is intended (at least in part) to promote portability of Ada programs at the source level. It is not intended to standardize extra-language issues such as how one invokes the compiler (or other tools), how one's source is represented and organized, version management, the format of error messages, etc. @Defn{safe separate compilation} @Defn2{Term=[separate compilation], Sec=(safe)} The rules of the language should be enforced even in the presence of separate compilation. Using separate compilation should not make a program less safe. @Defn{legality determinable via semantic dependences} It should be possible to determine the legality of a compilation unit by looking only at the compilation unit itself and the compilation units upon which it depends semantically. As an example, it should be possible to analyze the legality of two compilation units in parallel if they do not depend semantically upon each other. On the other hand, it may be necessary to look outside that set in order to generate code @em this is generally true for generic instantiation and inlining, for example. Also on the other hand, it is generally necessary to look outside that set in order to check @LinkTimeName@;s. See also the @lquotes@;generic contract model@rquotes@; @MetaRulesName of @RefSec{Generic Instantiation}. @end{MetaRules} @begin{DiffWord83} The section organization mentioned above is different from that of RM83. @end{DiffWord83} @LabeledClause{Separate Compilation} @begin{Intro} @redundant[@Defn{separate compilation} @Defn2{Term=[compilation], Sec=(separate)} @ToGlossaryAlso{Term=<Program unit>, Text=<A @i(program unit) is either a package, a task unit, a protected unit, a protected entry, a generic unit, or an explicitly declared subprogram other than an enumeration literal. Certain kinds of program units can be separately compiled. Alternatively, they can appear physically nested within other program units.>} @ToGlossaryAlso{Term=<Compilation unit>, Text=<The text of a program can be submitted to the compiler in one or more @nt(compilation)s. Each @nt(compilation) is a succession of @nt(compilation_unit)s. A @nt(compilation_unit) contains either the declaration, the body, or a renaming of a program unit.>}] The representation for a @nt<compilation> is implementation-defined. @ImplDef{The representation for a @nt{compilation}.} @begin{Ramification} Some implementations might choose to make a @nt{compilation} be a source (text) file. Others might allow multiple source files to be automatically concatenated to form a single @nt{compilation}. Others still may represent the source in a nontextual form such as a parse tree. Note that the RM95 does not even define the concept of a source file. Note that a protected subprogram is a subprogram, and therefore a program unit. An instance of a generic unit is a program unit. A protected entry is a program unit, but protected entries cannot be separately compiled. @end{Ramification} @ToGlossaryAlso{Term=<Library unit>, Text=<A library unit is a separately compiled program unit, and is always a package, subprogram, or generic unit. Library units may have other (logically nested) library units as children, and may have other program units physically nested within them. @Defn(subsystem) A root library unit, together with its children and grandchildren and so on, form a @i(subsystem).>} @end{Intro} @begin{ImplPerm} An implementation may impose implementation-defined restrictions on @nt{compilation}s that contain multiple @nt<compilation_unit>s. @ImplDef{Any restrictions on @nt<compilation>s that contain multiple @nt<compilation_unit>s.} @begin{Discussion} For example, an implementation might disallow a @nt{compilation} that contains two versions of the same compilation unit, or that contains the declarations for library packages P1 and P2, where P1 precedes P2 in the @nt<compilation> but P1 has a @nt<with_clause> that mentions P2. @end{Discussion} @end{ImplPerm} @begin{DiffWord83} The interactions between language issues and environmental issues are left open in Ada 95. The environment concept is new. In Ada 83, the concept of the program library, for example, appeared to be quite concrete, although the rules had no force, since implementations could get around them simply by defining various mappings from the concept of an Ada program library to whatever data structures were actually stored in support of separate compilation. Indeed, implementations were encouraged to do so. In RM83, it was unclear which was the official definition of @lquotes@;program unit.@rquotes@; Definitions appeared in RM83-5, 6, 7, and 9, but not 12. Placing it here seems logical, since a program unit is sort of a potential compilation unit. @end{DiffWord83} @LabeledSubClause{Compilation Units - Library Units} @begin{Intro} @redundant[A @nt{library_item} is a compilation unit that is the declaration, body, or renaming of a library unit. Each library unit (except Standard) has a @i{parent unit}, which is a library package or generic library package.] @Defn2{Term=[child], Sec=(of a library unit)} A library unit is a @i{child} of its parent unit. The @i{root} library units are the children of the predefined library package Standard. @begin{Ramification} Standard is a library unit. @end{Ramification} @end{Intro} @begin{Syntax} @Syn{lhs=<compilation>,rhs="{@Syn2{compilation_unit}}"} @Syn{lhs=<compilation_unit>,rhs=" @Syn2{context_clause} @Syn2{library_item} | @Syn2{context_clause} @Syn2{subunit}"} @Syn{lhs=<library_item>,rhs="[@key{private}] @Syn2{library_unit_declaration} | @Syn2{library_unit_body} | [@key{private}] @Syn2{library_unit_renaming_declaration}"} @Syn{tabs=[P25], lhs=<library_unit_declaration>,rhs=" @Syn2{subprogram_declaration}@\| @Syn2{package_declaration} | @Syn2{generic_declaration}@\| @Syn2{generic_instantiation}"} @Syn{lhs=<library_unit_renaming_declaration>,rhs=" @Syn2{package_renaming_declaration} | @Syn2{generic_renaming_declaration} | @Syn2{subprogram_renaming_declaration}"} @Syn{lhs=<library_unit_body>,rhs="@Syn2{subprogram_body} | @Syn2{package_body}"} @Syn{lhs=<parent_unit_name>,rhs="@Syn2{name}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is not allowed in a @nt{subprogram_declaration}, @nt{generic_instantiation}, or @nt{subprogram_renaming_declaration} that declares a library unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[All of the listed items syntactically include @nt{overriding_indicator}, but a library unit can never override anything. A majority of the ARG thought that allowing @key{not overriding} in that case would be confusing instead of helpful.]} @end{Reason} @end{Syntax} @begin{Intro} @Defn{library unit} @PDefn{library}@Comment{There is a different definition of library in 10.1.4.} @Seealso{Primary=[library],Other=[library level]} @Seealso{Primary=[library],Other=[library unit]} @Seealso{Primary=[library],Other=[library_item]} A @i{library unit} is a program unit that is declared by a @nt{library_item}. When a program unit is a library unit, the prefix @lquotes@;library@rquotes@; is used to refer to it (or @lquotes@;generic library@rquotes@; if generic), as well as to its declaration and body, as in @lquotes@;library procedure@rquotes@;, @lquotes@;library @nt{package_body}@rquotes@;, or @lquotes@;generic library package@rquotes@;. @Defn{compilation unit} The term @i{compilation unit} is used to refer to a @nt{compilation_unit}. When the meaning is clear from context, the term is also used to refer to the @nt{library_item} of a @nt{compilation_unit} or to the @nt{proper_body} of a @nt{subunit} @Redundant[(that is, the @nt{compilation_unit} without the @nt{context_clause} and the @key[separate] (@nt{parent_unit_name}))]. @begin{Discussion} @leading@keepnext@;In this example: @begin{Example} @key[with] Ada.Text_IO; @key[package] P @key[is] ... @key[end] P; @end{Example} the term @lquotes@;compilation unit@rquotes@; can refer to this text: @lquotes@;@key[with] Ada.Text_IO; @key[package] P @key[is] ... @key[end] P;@rquotes@; or to this text: @lquotes@;@key[package] P @key[is] ... @key[end] P;@rquotes@;. We use this shorthand because it corresponds to common usage. We like to use the word @lquotes@;unit@rquotes@; for declaration-plus-body things, and @lquotes@;item@rquotes@; for declaration or body separately (as in @nt{declarative_item}). The terms @lquotes@;@nt{compilation_unit},@rquotes@; @lquotes@;compilation unit,@rquotes@; and @lquotes@;@nt{subunit}@rquotes@; are exceptions to this rule. We considered changing @lquotes@;@nt{compilation_unit},@rquotes@; @lquotes@;compilation unit@rquotes@; to @lquotes@;@ntf{compilation_item},@rquotes@; @lquotes@;compilation item,@rquotes@; respectively, but we decided not to. @end{Discussion} @Defn2{Term=[parent declaration], Sec=(of a @nt{library_item})} @Defn2{Term=[parent declaration], Sec=(of a library unit)} The @i{parent declaration} of a @nt{library_item} (and of the library unit) is the declaration denoted by the @nt{parent_@!unit_name}, if any, of the @nt{defining_@!program_@!unit_name} of the @nt<library_item>. @Defn{root library unit} If there is no @nt{parent_@!unit_name}, the parent declaration is the declaration of Standard, the @nt{library_item} is a @i{root} @nt{library_item}, and the library unit (renaming) is a @i{root} library unit (renaming). The declaration and body of Standard itself have no parent declaration. @Defn2{Term=[parent unit], Sec=(of a library unit)} The @i{parent unit} of a @nt{library_item} or library unit is the library unit declared by its parent declaration. @begin{Discussion} The declaration and body of Standard are presumed to exist from the beginning of time, as it were. There is no way to actually write them, since there is no syntactic way to indicate lack of a parent. An attempt to compile a package Standard would result in Standard.Standard. @end{Discussion} @begin{Reason} Library units (other than Standard) have @lquotes@;parent declarations@rquotes@; and @lquotes@;parent units@rquotes@;. Subunits have @lquotes@;parent bodies@rquotes@;. We didn't bother to define the other possibilities: parent body of a library unit, parent declaration of a subunit, parent unit of a subunit. These are not needed, and might get in the way of a correct definition of @lquotes@;child.@rquotes@; @end{Reason} @Redundant[The children of a library unit occur immediately within the declarative region of the declaration of the library unit.] @Defn2{Term=[ancestor], Sec=(of a library unit)} The @i{ancestors} of a library unit are itself, its parent, its parent's parent, and so on. @Redundant[(Standard is an ancestor of every library unit.)] @Defn{descendant} The @i{descendant} relation is the inverse of the ancestor relation. @begin{Reason} These definitions are worded carefully to avoid defining subunits as children. Only library units can be children. We use the unadorned term @lquotes@;ancestors@rquotes@; here to concisely define both @lquotes@;ancestor unit@rquotes@; and @lquotes@;ancestor declaration.@rquotes@; @end{Reason} @Defn{public library unit} @Defn{public declaration of a library unit} @Defn{private library unit} @Defn{private declaration of a library unit} A @nt<library_unit_declaration> or a @nt<library_@!unit_@!renaming_@!declaration> is @i{private} if the declaration is immediately preceded by the reserved word @key{private}; it is otherwise @i{public}. A library unit is private or public according to its declaration. @Defn2{Term=[public descendant], Sec=(of a library unit)} The @i{public descendants} of a library unit are the library unit itself, and the public descendants of its public children. @Defn2{Term=[private descendant], Sec=(of a library unit)} Its other descendants are @i{private descendants}. @begin{Discussion} The first concept defined here is that a @nt<library_item> is either public or private (not in relation to anything else @em it's just a property of the library unit). The second concept is that a @nt<library_item> is a public descendant or private descendant @i{of a given ancestor}. A given @nt<library_item> can be a public descendant of one of its ancestors, but a private descendant of some other ancestor. A subprogram declared by a @nt{subprogram_body} (as opposed to a @nt{subprogram_declaration}) is always public, since the syntax rules disallow the reserved word @key[private] on a body. Note that a private library unit is a @i{public} descendant of itself, but a @i{private} descendant of its parent. This is because it is visible outside itself @em its privateness means that it is not visible outside its parent. Private children of Standard are legal, and follow the normal rules. It is intended that implementations might have some method for taking an existing environment, and treating it as a package to be @lquotes@;imported@rquotes@; into another environment, treating children of Standard in the imported environment as children of the imported package. @end{Discussion} @begin{Ramification} @leading@;Suppose we have a public library unit A, a private library unit A.B, and a public library unit A.B.C. A.B.C is a public descendant of itself and of A.B, but a private descendant of A; since A.B is private to A, we don't allow A.B.C to escape outside A either. This is similar to the situation that would occur with physical nesting, like this: @begin{Example} @key[package] A @key[is] @key[private] @key[package] B @key[is] @key[package] C @key[is] @key[end] C; @key[private] @key[end] B; @key[end] A; @end{Example} Here, A.B.C is visible outside itself and outside A.B, but not outside A. (Note that this example is intended to illustrate the visibility of program units from the outside; the visibility within child units is not quite identical to that of physically nested units, since child units are nested after their parent's declaration.) @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[For each library @nt{package_declaration} in the environment, there is an implicit declaration of a @i{limited view} of that library package.@Defn{limited view} The limited view of a package contains:]} @begin(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[For each nested @nt{package_declaration}, a declaration of the limited view of that package, with the same @nt{defining_program_unit_name}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[For each @nt{type_declaration} in the visible part, an incomplete view of the type; if the @nt{type_declaration} is tagged, then the view is a tagged incomplete view.]} @end(Itemize) @begin(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The implementation model of a limited view is that it can be determined solely from the syntax of the source of the unit, without any semantic analysis. That allows it to be created without the semantic dependences of a full unit, which is necessary for it to break mutual dependences of units.]} @end(Discussion) @begin(Ramification) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The limited view does not include package instances and their contents. Semantic analysis of a unit (and dependence on its @nt{with_clause}s) would be needed to determine the contents of an instance.]} @end(Ramification) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The limited view of a library @nt{package_declaration} is private if that library @nt{package_declaration} is immediately preceded by the reserved word @key{private}.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Redundant[There is no syntax for declaring limited views of packages, because they are always implicit.] The implicit declaration of a limited view of a library package @Redundant[is not the declaration of a library unit (the library @nt{package_declaration} is); nonetheless, it] is a @nt{library_item}. The implicit declaration of the limited view of a library package forms an (implicit) compilation unit whose @nt{context_clause} is empty.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A library @nt{package_declaration} is the completion of the declaration of its limited view.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is notwithstanding the rule in @RefSecNum{Completions of Declarations} that says that implicit declarations don't have completions.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule explains where to find the completions of the incomplete views defined by the limited view.]} @end{Reason} @end{Intro} @begin{Legality} The parent unit of a @nt<library_item> shall be a @Redundant[library] package or generic @Redundant[library] package. If a @nt{defining_program_unit_name} of a given declaration or body has a @nt{parent_unit_name}, then the given declaration or body shall be a @nt<library_item>. The body of a program unit shall be a @nt{library_item} if and only if the declaration of the program unit is a @nt<library_item>. In a @nt{library_@!unit_@!renaming_@!declaration}, the @Redundant[(old)] @nt{name} shall denote a @nt<library_item>. @begin{Discussion} We could have allowed nested program units to be children of other program units; their semantics would make sense. We disallow them to keep things simpler and because they wouldn't be particularly useful. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @nt{parent_unit_name} @Redundant[(which can be used within a @nt<defining_program_unit_name> of a @nt<library_item> and in the @key[separate] clause of a @nt<subunit>)], and each of its @nt{prefix}es, shall not denote a @nt{renaming_declaration}. @Redundant[On the other hand, a name that denotes a @nt{library_@!unit_@!renaming_@!declaration} is allowed in a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} and other places where the name of a library unit is allowed.] If a library package is an instance of a generic package, then every child of the library package shall either be itself an instance or be a renaming of a library unit. @begin{Discussion} A child of an instance of a given generic unit will often be an instance of a (generic) child of the given generic unit. This is not required, however. @end{Discussion} @begin{Reason} @leading@;Instances are forbidden from having noninstance children for two reasons: @begin(Enumerate) We want all source code that can depend on information from the private part of a library unit to be inside the "subsystem" rooted at the library unit. If an instance of a generic unit were allowed to have a noninstance as a child, the source code of that child might depend on information from the private part of the generic unit, even though it is outside the subsystem rooted at the generic unit. Disallowing noninstance children simplifies the description of the semantics of children of generic packages. @end(Enumerate) @end{Reason} A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit. The renaming of a child of a generic package shall occur only within the declarative region of the generic package. A child of a parent generic package shall be instantiated or renamed only within the declarative region of the parent generic. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00331-01]} For each @Chg{Version=[2],New=[child @i<C>], Old=[declaration or renaming of a generic unit as a child]} of some parent generic package@Chg{Version=[2],New=[ @i<P>],Old=[]}, there is a corresponding declaration @Chg{Version=[2],New=[@i<C>],Old=[]} nested immediately within each instance @Chg{Version=[2],New=[of @i<P>. For the purposes of this rule, if a child @i<C> itself has a child @i<D>, each corresponding declaration for @i<C> has a corresponding child @i<D>], Old=[of the parent]}. @Redundant[@Chg{Version=[2],New=[The corresponding],Old=[This]} declaration @Chg{Version=[2],New=[for a child within an instance ],Old=[]}is visible only within the scope of a @nt{with_clause} that mentions the @Chg{Version=[2],New=[(original) ],Old=[]}child generic unit.] @begin{ImplNote} Within the child, like anything nested in a generic unit, one can make up-level references to the current instance of its parent, and thereby gain access to the formal parameters of the parent, to the types declared in the parent, etc. This @lquotes@;nesting@rquotes@; model applies even within the @nt{generic_formal_part} of the child, as it does for a generic child of a nongeneric unit. @end{ImplNote} @begin{Ramification} Suppose P is a generic library package, and P.C is a generic child of P. P.C can be instantiated inside the declarative region of P. Outside P, P.C can be mentioned only in a @nt{with_clause}. Conceptually, an instance I of P is a package that has a nested generic unit called I.C. Mentioning P.C in a @nt{with_clause} allows I.C to be instantiated. I need not be a library unit, and the instantiation of I.C need not be a library unit. If I is a library unit, and an instance of I.C is a child of I, then this instance has to be called something other than C. @end{Ramification} A library subprogram shall not override a primitive subprogram. @begin{Reason} This prevents certain obscure anomalies. For example, if a library subprogram were to override a subprogram declared in its parent package, then in a compilation unit that depends @i{in}directly on the library subprogram, the library subprogram could hide the overridden operation from all visibility, but the library subprogram itself would not be visible. Note that even without this rule, such subprograms would be illegal for tagged types, because of the freezing rules. @end{Reason} The defining name of a function that is a compilation unit shall not be an @nt{operator_symbol}. @begin{Reason} Since overloading is not permitted among compilation units, it seems unlikely that it would be useful to define one as an operator. Note that a subunit could be renamed within its parent to be an operator. @end{Reason} @end{Legality} @begin{StaticSem} A @nt<subprogram_renaming_declaration> that is a @nt{library_@!unit_@!renaming_@!declaration} is a renaming-as-declaration, not a renaming-as-body. @leading@keepnext@redundant[There are two kinds of dependences among compilation units:] @begin{Itemize} @redundant[The @i{semantic dependences} (see below) are the ones needed to check the compile-time rules across compilation unit boundaries; a compilation unit depends semantically on the other compilation units needed to determine its legality. The visibility rules are based on the semantic dependences. The @i{elaboration dependences} (see @RefSecNum{Program Execution}) determine the order of elaboration of @nt{library_item}s.] @end{Itemize} @begin{Discussion} Don't confuse these kinds of dependences with the run-time dependences among tasks and masters defined in @RefSec{Task Dependence - Termination of Tasks}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @Defn2{Term=[semantic dependence], Sec=(of one compilation unit upon another)} @Defn2{Term=[dependence], Sec=(semantic)} A @nt{library_item} depends semantically upon its parent declaration. A subunit depends semantically upon its parent body. A @nt{library_unit_body} depends semantically upon the corresponding @nt{library_unit_declaration}, if any. @Chg{Version=[2],New=[The declaration of the limited view of a library package depends semantically upon the declaration of the limited view of its parent. The declaration of a library package depends semantically upon the declaration of its limited view.],Old=[]} A compilation unit depends semantically upon each @nt<library_item> mentioned in a @nt{with_clause} of the compilation unit. In addition, if a given compilation unit contains an @nt{attribute_reference} of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. The semantic dependence relationship is transitive. @begin{Discussion} The @lquotes@;if any@rquotes@; in the third sentence is necessary because library subprograms are not required to have a @nt{subprogram_declaration}. @end{Discussion} @begin{Honest} If a given compilation unit contains a @nt{choice_parameter_specification}, then the given compilation unit depends semantically upon the declaration of Ada.Exceptions. If a given compilation unit contains a @nt{pragma} with an argument of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. @end{Honest} @begin{Discussion} For example, a compilation unit containing X'Address depends semantically upon the declaration of package System. For the Address attribute, this fixes a hole in Ada 83. Note that in almost all cases, the dependence will need to exist due to @nt{with_clause}s, even without this rule. Hence, the rule has very little effect on programmers. Note that the semantic dependence does not have the same effect as a @nt{with_clause}; in order to denote a declaration in one of those packages, a @nt{with_clause} will generally be needed. Note that no special rule is needed for an @nt{attribute_definition_clause}, since an expression after @key[use] will require semantic dependence upon the compilation unit containing the @nt{type_declaration} of interest. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Unlike a full view of a package, a limited view does not depend semantically on units mentioned in @nt{with_clause}s of the @nt{compilation_unit} that defines the package. Formally, this is achieved by saying that the limited view has an empty @nt{context_clause}. This is necessary so that they can be useful for their intended purpose: allowing mutual dependences between packages. The lack of semantic dependence limits the contents of a limited view to the items that can be determined solely from the syntax of the source of the package, without any semantic analysis. That allows it to be created without the semantic dependences of a full package.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The elaboration of the declaration of the limited view of a package has no effect.]} @end{RunTime} @begin{Notes} A simple program may consist of a single compilation unit. A @nt{compilation} need not have any compilation units; for example, its text can consist of @nt{pragma}s. @begin{Ramification} Such @nt{pragma}s cannot have any arguments that are @nt{name}s, by a previous rule of this subclause. A @nt{compilation} can even be entirely empty, which is probably not useful. Some interesting properties of the three kinds of dependence: The elaboration dependences also include the semantic dependences, except that subunits are taken together with their parents. The semantic dependences partly determine the order in which the compilation units appear in the environment at compile time. At run time, the order is partly determined by the elaboration dependences. @leading@;The model whereby a child is inside its parent's declarative region, after the parent's declaration, as explained in @RefSecNum{Declarative Region}, has the following ramifications: @begin(itemize) The restrictions on @lquotes@;early@rquotes@; use of a private type (RM83-7.4.1(4)) or a deferred constant (RM83-7.4.3(2)) do not apply to uses in child units, because they follow the full declaration. A library subprogram is never primitive, even if its profile includes a type declared immediately within the parent's @nt{package_specification}, because the child is not declared immediately within the same @nt{package_specification} as the type (so it doesn't declare a new primitive subprogram), and because the child is forbidden from overriding an old primitive subprogram. It is immediately within the same declarative region, but not the same @nt{package_specification}. Thus, for a tagged type, it is not possible to call a child subprogram in a dispatching manner. (This is also forbidden by the freezing rules.) Similarly, it is not possible for the user to declare primitive subprograms of the types declared in the declaration of Standard, such as Integer (even if the rules were changed to allow a library unit whose name is an operator symbol). When the parent unit is @lquotes@;used@rquotes@; the simple names of the with'd child units are directly visible (see @RefSec{Use Clauses}). When a parent body with's its own child, the defining name of the child is directly visible, and the parent body is not allowed to include a declaration of a homograph of the child unit immediately within the @nt{declarative_part} of the body (RM83-8.3(17)). @end(itemize) Note that @lquotes@;declaration of a library unit@rquotes@; is different from @lquotes@;@nt{library_unit_declaration}@rquotes@; @em the former includes @nt{subprogram_body}. Also, we sometimes really mean @lquotes@;declaration of a view of a library unit@rquotes@;, which includes @nt{library_@!unit_@!renaming_@!declaration}s. The visibility rules generally imply that the renamed view of a @nt{library_@!unit_@!renaming_@!declaration} has to be mentioned in a @nt{with_@!clause} of the @nt{library_@!unit_@!renaming_@!declaration}. @end{Ramification} @begin{Honest} The real rule is that the renamed library unit has to be visible in the @nt{library_@!unit_@!renaming_@!declaration}. @end{Honest} @begin{Reason} In most cases, @lquotes@;has to be visible@rquotes@; means there has to be a @nt{with_clause}. However, it is possible in obscure cases to avoid the need for a @nt{with_clause}; in particular, a compilation unit such as @lquotes@;@key[package] P.Q @key[renames] P;@rquotes@; is legal with no @nt{with_clause}s (though not particularly interesting). ASCII is physically nested in Standard, and so is not a library unit, and cannot be renamed as a library unit. @end{Reason} The @nt{designator} of a library function cannot be an @nt{operator_symbol}, but a nonlibrary @nt{renaming_declaration} is allowed to rename a library function as an operator. Within a partition, two library subprograms are required to have distinct names and hence cannot overload each other. However, @nt{renaming_declaration}s are allowed to define overloaded names for such subprograms, and a locally declared subprogram is allowed to overload a library subprogram. The expanded name Standard.L can be used to denote a root library unit L (unless the declaration of Standard is hidden) since root library unit declarations occur immediately within the declarative region of package Standard. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of library units:} @begin{Example} @key[package] Rational_Numbers.IO @key[is] --@RI[ public child of Rational_Numbers, see @RefSecNum{Package Specifications and Declarations}] @key[procedure] Put(R : @key[in] Rational); @key[procedure] Get(R : @key[out] Rational); @key[end] Rational_Numbers.IO; @key[private procedure] Rational_Numbers.Reduce(R : @key[in out] Rational); --@RI[ private child of Rational_Numbers] @key[with] Rational_Numbers.Reduce; --@RI[ refer to a private child] @key[package body] Rational_Numbers @key[is] ... @key[end] Rational_Numbers; @key[with] Rational_Numbers.IO; @key[use] Rational_Numbers; @key[with] Ada.Text_io; --@RI[ see @RefSecNum{Text Input-Output}] @key[procedure] Main @key[is] --@RI[ a root library procedure] R : Rational; @key[begin] R := 5/3; --@RI[ construct a rational number, see @RefSecNum{Package Specifications and Declarations}] Ada.Text_IO.Put("The answer is: "); IO.Put(R); Ada.Text_IO.New_Line; @key[end] Main; @key[with] Rational_Numbers.IO; @key[package] Rational_IO @key[renames] Rational_Numbers.IO; --@RI[ a library unit renaming declaration] @end{Example} Each of the above @nt{library_item}s can be submitted to the compiler separately. @begin{Discussion} @leading@keepnext@i{Example of a generic package with children:} @begin{Example} @key[generic] @key[type] Element @key[is] @key[private]; @key[with] @key[function] Image(E : Element) @key[return] String; @key[package] Generic_Bags @key[is] @key[type] Bag @key[is] @key[limited] @key[private]; --@RI{ A bag of Elements.} @key[procedure] Add(B : @key[in] @key[out] Bag; E : Element); @key[function] Bag_Image(B : Bag) @key[return] String; @key[private] @key[type] Bag @key[is] ...; @key[end] Generic_Bags; @key[generic] @key[package] Generic_Bags.Generic_Iterators @key[is] ... --@RI{ various additional operations on Bags.} @key[generic] @key[with] @key[procedure] Use_Element(E : @key[in] Element); --@RI{ Called once per bag element.} @key[procedure] Iterate(B : @key[in] Bag); @key[end] Generic_Bags.Generic_Iterators; @end{Example} @begin{Wide} @leading@keepnext@;A package that instantiates the above generic units: @end{Wide} @begin{Example} @key[with] Generic_Bags; @key[with] Generic_Bags.Generic_Iterators; @key[package] My_Abstraction @key[is] @key[type] My_Type @key[is] ...; @key[function] Image(X : My_Type) @key[return] String; @key[package] Bags_Of_My_Type @key[is] @key[new] Generic_Bags(My_Type, Image); @key[package] Iterators_Of_Bags_Of_My_Type @key[is] @key[new] Bags_Of_My_Type.Generic_Iterators; @key[end] My_Abstraction; @end{Example} In the above example, Bags_Of_My_Type has a nested generic unit called Generic_Iterators. The second @nt{with_clause} makes that nested unit visible. @leading@;Here we show how the generic body could depend on one of its own children: @begin{Example} @key[with] Generic_Bags.Generic_Iterators; @key[package] @key[body] Generic_Bags @key[is] @key[procedure] Add(B : @key[in] @key[out] Bag; E : Element) @key[is] ... @key[end] Add; @key[package] Iters @key[is] @key[new] Generic_Iterators; @key[function] Bag_Image(B : Bag) @key[return] String @key[is] Buffer : String(1..10_000); Last : Integer := 0; @key[procedure] Append_Image(E : @key[in] Element) @key[is] Im : @key[constant] String := Image(E); @key[begin] @key[if] Last /= 0 @key[then] --@RI{ Insert a comma.} Last := Last + 1; Buffer(Last) := ','; @key[end] @key[if]; Buffer(Last+1 .. Last+Im'Length) := Im; Last := Last + Im'Length; @key[end] Append_Image; @key[procedure] Append_All @key[is] @key[new] Iters.Iterate(Append_Image); @key[begin] Append_All(B); @key[return] Buffer(1..Last); @key[end] Bag_Image; @key[end] Generic_Bags; @end{Example} @end{Discussion} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{library_item} is modified to allow the reserved word @key{private} before a @nt{library_unit_declaration}. Children (other than children of Standard) are new in Ada 95. Library unit renaming is new in Ada 95. @end{Extend83} @begin{DiffWord83} Standard is considered a library unit in Ada 95. This simplifies the descriptions, since it implies that the parent of each library unit is a library unit. (Standard itself has no parent, of course.) As in Ada 83, the language does not define any way to recompile Standard, since the name given in the declaration of a library unit is always interpreted in relation to Standard. That is, an attempt to compile a package Standard would result in Standard.Standard. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The concept of a limited view is new. Combined with @nt{limited_with_clause}s (see @RefSecNum{Context Clauses - With Clauses}), they facilitate construction of mutually recursive types in multiple packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00331-01]} @ChgAdded{Version=[2],Text=[Clarified the wording so that a grandchild generic unit will work as expected.]} @end{DiffWord95} @LabeledSubClause{Context Clauses - With Clauses} @begin{Intro} @redundant[A @nt{context_clause} is used to specify the @nt<library_item>s whose names are needed within a compilation unit.] @end{Intro} @begin{MetaRules} @Defn{one-pass @nt{context_clause}s} The reader should be able to understand a @nt{context_clause} without looking ahead. Similarly, when compiling a @nt{context_clause}, the compiler should not have to look ahead at subsequent @nt{context_item}s, nor at the compilation unit to which the @nt{context_clause} is attached. (We have not completely achieved this.) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{ripple effect}A @i<ripple effect> occurs when the legality of a compilation unit could be affected by adding or removing an otherwise unneeded @nt{with_clause} on some compilation unit on which the unit depends, directly or indirectly. We try to avoid ripple effects because they make understanding and maintenance more difficult. However, ripple effects can occur because of direct visibility (as in child units); this seems impossible to eliminate. The ripple effect for @nt{with_clause}s is somewhat similar to the Beaujolais effect (see @RefSecNum{Use Clauses}) for @nt{use_clause}s, which we also try to avoid.]} @end{MetaRules} @begin{Syntax} @Syn{lhs=<context_clause>,rhs="{@Syn2{context_item}}"} @Syn{lhs=<context_item>,rhs="@Syn2{with_clause} | @Syn2{use_clause}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00262-01]} @Syn{lhs=<with_clause>,rhs="@Chg{Version=[2],New=<@Syn2{limited_with_clause} | @Syn2{nonlimited_with_clause}>,Old=<@key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>}"} @ChgRef{Version=[2],Kind=[Added]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<limited_with_clause>,Old=<>}>,rhs="@Chg{Version=[2],New=<@key{limited} [@key{private}] @key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<nonlimited_with_clause>,Old=<>}>,rhs="@Chg{Version=[2],New=<[@key{private}] @key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>,Old=<>}"} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[A @nt{limited_with_clause} makes a limited view of a unit visible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[@Defn{private with_clause}A @nt{with_clause} containing the reserved word @key{private} is called a @i{private with_clause}. It can be thought of as making items visible only in the private part, although it really makes items visible everywhere except the visible part. It can be used both for documentation purposes (to say that a unit is not used in the visible part), and to allow access to private units that otherwise would be prohibited.]} @end{Discussion} @end{Syntax} @begin{Resolution} @Defn2{Term=[scope], Sec=(of a @nt{with_clause})} The @i{scope} of a @nt{with_clause} that appears on a @nt{library_@!unit_@!declaration} or @nt{library_@!unit_@!renaming_@!declaration} consists of the entire declarative region of the declaration@Redundant[, which includes all children and subunits]. The scope of a @nt{with_clause} that appears on a body consists of the body@Redundant[, which includes all subunits]. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} Suppose a @Chg{Version=[2],New=[non-private ],Old=[]} @nt{with_clause} of a public library unit mentions one of its private siblings. (This is only allowed on the body of the public library unit.) We considered making the scope of that @nt{with_clause} not include the visible part of the public library unit. (This would only matter for a @nt{subprogram_body}, since those are the only kinds of body that have a visible part, and only if the @nt{subprogram_body} completes a @nt{subprogram_declaration}, since otherwise the @nt{with_clause} would be illegal.) We did not put in such a rule for two reasons: (1) It would complicate the wording of the rules, because we would have to split each @nt{with_clause} into pieces, in order to correctly handle @lquotes@;@key[with] P, Q;@rquotes@; where P is public and Q is private. (2) The conformance rules prevent any problems. It doesn't matter if a type name in the spec of the body denotes the completion of a @nt{private_type_declaration}. A @nt{with_clause} also affects visibility within subsequent @nt{use_clause}s and @nt{pragma}s of the same @nt{context_clause}, even though those are not in the scope of the @nt{with_clause}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @Defn{Term=[mentioned],Sec=[in a @nt<with_clause>]} @Defn2{Term=[with_clause], Sec=(mentioned in)} A @nt<library_item> @Chg{Version=[2],New=[(and the corresponding library unit) ],Old=[]}is @Chg{Version=[2],New=[@i{named} @Defn2{Term=[named],Sec=[in a @nt<with_clause>]} @Defn2{Term=[with_clause], Sec=(named in)}],Old=[@i{mentioned} ]}in a @nt<with_clause> if it is denoted by a @i(library_unit_)@nt<name> @Chg{Version=[2],New=[],Old=[or a @nt<prefix> ]} in the @nt<with_clause>. @Chg{Version=[2],New=[A @nt{library_item} (and the corresponding library unit) is @i<mentioned> in a @nt{with_clause} if it is named in the @nt{with_clause} or if it is denoted by a @nt{prefix} in the @nt{with_clause}.],Old=[]} @begin{Discussion} @nt{With_clause}s control the visibility of declarations or renamings of library units. Mentioning a root library unit in a @nt{with_clause} makes its declaration directly visible. Mentioning a non-root library unit makes its declaration visible. See Section 8 for details. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Note that this rule implies that @lquotes@;@key{with} A.B.C;@rquotes@; is @chg{Version=[2],New=[almost ],Old=[]}equivalent to @lquotes@;@key{with} A, A.B, A.B.C;@rquotes@;@Chg{Version=[2],New=[.],Old=[]} The reason for making a @nt{with_clause} apply to all the ancestor units is to avoid @lquotes@;visibility holes@rquotes@; @em situations in which an inner program unit is visible while an outer one is not. Visibility holes would cause semantic complexity and implementation difficulty.@Chg{Version=[2],New=[ (This is not exactly equivalent because the latter @nt{with_clause} names A and A.B, while the previous one does not. Whether a unit is @ldquote@;named@rdquote does not have any effect on visibility, however, so it is equivalent for visibility purposes.))],Old=[]} @end{Discussion} @redundant[Outside its own declarative region, the declaration or renaming of a library unit can be visible only within the scope of a @nt{with_clause} that mentions it. The visibility of the declaration or renaming of a library unit otherwise follows from its placement in the environment.] @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} If a @nt{with_clause} of a given @nt<compilation_unit> mentions a private child of some library unit, then the given @nt{compilation_unit} shall be @Chg{Version=[2],New=[one of:], Old=[either the declaration of a private descendant of that library unit or the body or subunit of a @Redundant[(public or private)] descendant of that library unit.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the declaration, body, or subunit of a private descendant of that library unit;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00220-01],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the body or subunit of a public descendant of that library unit, but not a subprogram body acting as a subprogram declaration (see @RefSecNum{The Compilation Process}); or]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the declaration of a public descendant of that library unit, in which case the @nt<with_clause> shall include the reserved word @key<private>.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} The purpose of this rule is to prevent a private child from being visible @Chg{Version=[2],New=[],Old=[(or even semantically depended-on) ]}from outside the subsystem rooted at its parent. @Chg{Version=[2],New=[A private child can be semantically depended-on without violating this principle if it is used in a private @nt{with_clause}.],Old=[]} @end{Reason} @begin{Discussion} This rule violates the one-pass @nt{context_clause}s @MetaRulesName. We rationalize this by saying that at least that @MetaRulesName works for legal compilation units. @leading@keepnext@;Example: @begin{Example} @key[package] A @key[is] @key[end] A; @key[package] A.B @key[is] @key[end] A.B; @key[private] @key[package] A.B.C @key[is] @key[end] A.B.C; @key[package] A.B.C.D @key[is] @key[end] A.B.C.D; @key[with] A.B.C; -- @RI[(1)] @key[private] @key[package] A.B.X @key[is] @key[end] A.B.X; @key[package] A.B.Y @key[is] @key[end] A.B.Y; @key[with] A.B.C; -- @RI[(2)] @key[package] @key[body] A.B.Y @key[is] @key[end] A.B.Y; @ChgRef{Version=[2],Kind=[Added]}@ChgAdded{Version=[2],Text=[@key[private] @key[with] A.B.C; -- @RI[(3)] @key[package] A.B.Z @key[is] @key[end] A.B.Z;]} @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} (1) is OK because it's a private child of A.B @em it would be illegal if we made A.B.X a public child of A.B. (2) is OK because it's the body of a child of A.B. @Chg{Version=[2],New=[(3) is OK because it's a child of A.B, and it is a private @nt{with_clause}.],Old=[]} It would be illegal to say @lquotes@;@key[with] A.B.C;@rquotes@; on any @nt{library_item} whose name does not start with @lquotes@;A.B@rquotes@;. Note that mentioning A.B.C.D in a @nt{with_clause} automatically mentions A.B.C as well, so @lquotes@;@key[with] A.B.C.D;@rquotes@; is illegal in the same places as @lquotes@;@key[with] A.B.C;@rquotes@;. @end{Discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} For the purposes of this rule, if a @nt{subprogram_body} has no preceding @nt{subprogram_declaration}, the @nt{subprogram_body} should be considered a declaration and not a body. Thus, it is illegal for such a @nt{subprogram_body} to mention one of its siblings in a @Chg{Version=[2],New=[non-private ],Old=[]}@nt{with_clause} if the sibling is a private library unit. @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A @nt<name> denoting a library item that is visible only due to being mentioned in one or more @nt<with_clause>s that include the reserved word @key<private> shall appear only within:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a private part;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a body, but not within the @nt<subprogram_specification> of a library subprogram body;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a private descendant of the unit on which one of these @nt<with_clause>s appear; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a pragma within a context clause.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules apply only if all of the @nt{with_clause}s that mention the name include the reserved word @key{private}. They do not apply if the name is mentioned in any @nt{with_clause} that does not include @key{private}.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules make the library item visible anywhere that is not visible outside the subsystem rooted at the @nt{compilation_unit} having the private @nt{with_clause}, including private parts of packages nested in the visible part, private parts of child packages, the visible part of private children, and context clause pragmas like Elaborate_All.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We considered having the scope of a private @nt{with_clause} not include the visible part. However, that rule would mean that moving a declaration between the visible part and the private part could change its meaning from one legal interpretation to a different legal interpretation. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} A @key{is} @key{function} B @key{return} Integer; @key{end} A;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{function} B @key{return} Integer;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} A; @key{private} @key{with} B; @key{package} C @key{is} @key{use} A; V1 : Integer := B; -- (1) @key{private} V2 : Integer := B; -- (2) @key{end} C;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If we say that library subprogram B is not in scope in the visible part of C, then the B at (1) resolves to A.B, while (2) resolves to library unit B. Simply moving a declaration could silently change its meaning. With the legality rule defined above, the B at (1) is illegal. If the user really meant A.B, they still can say that.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Redundant[A @nt{library_item} mentioned in a @nt{limited_with_clause} shall be the implicit declaration of the limited view of a library package, not the declaration of a subprogram, generic unit, generic instance, or a renaming.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is redundant because only such implicit declarations are visible in a @nt{limited_with_clause}. See @RefSecNum{Environment-Level Visibility Rules}.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[A @nt{limited_with_clause} shall not appear on a @nt{library_unit_body}, @nt{subunit}, or @nt{library_@!unit_@!renaming_@!declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[We don't allow a @nt{limited_with_clause} on a @nt{library_@!unit_@!renaming_@!declaration} because it would be useless and therefore probably is a mistake. A renaming cannot appear in a @nt{limited_with_clause} (by the rule prior to this one), and a renaming of a limited view cannot appear in a @nt{nonlimited_with_clause} (because the name would not be within the scope of a @nt{with_clause} denoting the package, see @RefSecNum{Package Renaming Declarations}). Nor could it be the parent of another unit. That doesn't leave anywhere that the name of such a renaming @b<could> appear, so we simply make writing it illegal.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[A @nt{limited_with_clause} that names a library package shall not appear:]} @begin(Itemize) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[in the @nt{context_clause} for the explicit declaration of the named library package;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to explicitly disallow]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{limited} @key{with} P; @key{package} P @key{is} ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[as we can't depend on the semantic dependence rules to do it for us as with regular withs. This says @lquotes@;named@rquotes and not @lquotes@;mentioned@rquotes in order that]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{limited} @key{private} @key{with} P.Child; @key{package} P @key{is} ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[can be used to allow a mutual dependence between the private part of P and the private child P.Child, which occurs in interfacing and other problems. Since the child always semantically depends on the parent, this is the only way such a dependence can be broken.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[in the same @nt{context_clause} as, or within the scope of, a @nt{nonlimited_with_clause} that mentions the same library package; or]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such a @nt{limited_with_clause} could have no effect, and would be confusing. If it is within the scope of a @nt{nonlimited_with_clause}, or if such a clause is in the @nt{context_clause}, the full view is available, which strictly provides more information than the limited view.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[in the same @nt{context_clause} as, or within the scope of, a @nt{use_clause} that names an entity declared within the declarative region of the library package.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents visibility issues, where whether an entity is an incomplete or full view depends on how the name of the entity is written. The @nt{limited_with_clause} cannot be useful, as we must have the full view available in the parent in order for the @nt{use_clause} to be legal.]} @end{Reason} @end(Itemize) @end{Legality} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @nt<library_item> mentioned in a @Chg{Version=[2], New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} of a compilation unit is visible within the compilation unit and hence acts just like an ordinary declaration. Thus, within a compilation unit that mentions its declaration, the name of a library package can be given in @nt{use_clause}s and can be used to form expanded names, a library subprogram can be called, and instances of a generic library unit can be declared. If a child of a parent generic package is mentioned in a @Chg{Version=[2], New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]}, then the corresponding declaration nested within each visible instance is visible within the compilation unit.@Chg{Version=[2], New=[ Similarly, a @nt{library_item} mentioned in a @nt{limited_with_clause} of a compilation unit is visible within the compilation unit and thus can be used to form expanded names.],Old=[]} @begin{Ramification} The rules given for @nt{with_clause}s are such that the same effect is obtained whether the name of a library unit is mentioned once or more than once by the applicable @nt{with_clause}s, or even within a given @nt{with_clause}. If a @nt{with_clause} mentions a @nt{library_@!unit_@!renaming_@!declaration}, it only @lquotes@;mentions@rquotes@; the @nt<prefix>es appearing explicitly in the @nt<with_clause> (and the renamed view itself); the @nt{with_clause} is not defined to mention the ancestors of the renamed entity. Thus, if X renames Y.Z, then @lquotes@;with X;@rquotes@; does not make the declarations of Y or Z visible. Note that this does not cause the dreaded visibility holes mentioned above. @end{Ramification} @end{Notes} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(package) Office @key(is) @key{end} Office;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(with) Ada.Strings.Unbounded; @key(package) Office.Locations @key(is) @key(type) Location @key(is new) Ada.Strings.Unbounded.Unbounded_String; @key(end) Office.Locations;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(limited with) Office.Departments; --@RI[ types are incomplete] @key(private with) Office.Locations; --@RI[ only visible in private part] @key(package) Office.Employees @key(is) @key(type) Employee @key(is private);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key(function) Dept_Of(Emp : Employee) @key(return access) Departments.Department; @key(procedure) Assign_Dept(Emp : @key(in out) Employee; Dept : @key(access) Departments.Department);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key(private type) Employee @key(is record) Dept : @key(access) Departments.Department; Loc : Locations.Location; ... @key(end record); @key(end) Office.Employees;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key(limited with) Office.Employees; @key(package) Office.Departments @key(is) @key(type) Department @key(is private);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key(function) Manager_Of(Dept : Department) @key(return access) Employees.Employee; @key(procedure) Assign_Manager(Dept : @key(in out) Department; Mgr : @key(access) Employees.Employee); ... @key(end) Office.Departments;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The @nt{limited_with_clause} may be used to support mutually dependent abstractions that are split across multiple packages. In this case, an employee is assigned to a department, and a department has a manager who is an employee. If a @nt{with_clause} with the reserved word @key(private) appears on one library unit and mentions a second library unit, it provides visibility to the second library unit, but restricts that visibility to the private part and body of the first unit. The compiler checks that no use is made of the second unit in the visible part of the first unit.]} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{with_clause} is modified to allow expanded name notation. A @nt<use_clause> in a @nt<context_clause> may be for a package (or type) nested in a library package. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{context_clause} is modified to more closely reflect the semantics. The Ada 83 syntax rule implies that the @nt{use_clause}s that appear immediately after a particular @nt{with_clause} are somehow attached to that @nt{with_clause}, which is not true. The new syntax allows a @nt{use_clause} to appear first, but that is prevented by a textual rule that already exists in Ada 83. The concept of @lquotes@;scope of a @nt{with_clause}@rquotes@; (which is a region of text) replaces RM83's notion of @lquotes@;apply to@rquotes@; (a @nt{with_clause} applies to a @nt{library_item}) The visibility rules are interested in a region of text, not in a set of compilation units. No need to define @lquotes@;apply to@rquotes@; for @nt{use_clause}s. Their semantics are fully covered by the @lquotes@;scope (of a @nt{use_clause})@rquotes@; definition in @RefSecNum{Use Clauses}. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00220-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] A subprogram body acting as a declaration cannot @key[with] a private child unit. This would allow public export of types declared in private child packages, and thus cannot be allowed. This was allowed by mistake in Ada 95; a subprogram that does this will now be illegal.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{limited_with_clause}s are new. They make a limited view of a package visible, where all of the types in the package are incomplete. They facilitate construction of mutually recursive types in multiple packages.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The syntax rules for @nt{with_clause} are modified to allow the reserved word @key{private}. Private @nt{with_clause}s do not allow the use of their library item in the visible part of their @nt{compilation_unit}. They also allow using private units in more locations than in Ada 95.]} @end{Extend95} @LabeledSubClause{Subunits of Compilation Units} @begin{Intro} @redundant[Subunits are like child units, with these (important) differences: subunits support the separate compilation of bodies only (not declarations); the parent contains a @nt{body_stub} to indicate the existence and place of each of its subunits; declarations appearing in the parent's body can be visible within the subunits.] @end{Intro} @begin{Syntax} @Syn{lhs=<body_stub>,rhs="@Syn2{subprogram_body_stub} | @Syn2{package_body_stub} | @Syn2{task_body_stub} | @Syn2{protected_body_stub}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @Syn{lhs=<subprogram_body_stub>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=[]}@Syn2{subprogram_specification} @key{is} @key{separate};"} @begin{Discussion} Although this syntax allows a @nt{parent_unit_name}, that is disallowed by @RefSec{Compilation Units - Library Units}. @end{Discussion} @Syn{lhs=<package_body_stub>,rhs="@key{package} @key{body} @Syn2{defining_identifier} @key{is} @key{separate};"} @Syn{lhs=<task_body_stub>,rhs="@key{task} @key{body} @Syn2{defining_identifier} @key{is} @key{separate};"} @Syn{lhs=<protected_body_stub>,rhs="@key{protected} @key{body} @Syn2{defining_identifier} @key{is} @key{separate};"} @Syn{lhs=<subunit>,rhs="@key{separate} (@Syn2{parent_unit_name}) @Syn2{proper_body}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00243-01]} @Defn2{Term=[parent body], Sec=(of a subunit)} The @i{parent body} of a subunit is the body of the program unit denoted by its @nt{parent_unit_name}. @Defn{subunit} The term @i{subunit} is used to refer to a @nt{subunit} and also to the @nt{proper_body} of a @nt{subunit}. @Chg{Version=[2],New=<The @i<subunits of a program unit> include any subunit that names that program unit as its parent, as well as any subunit that names such a subunit as its parent (recursively).@Defn2{Term=[subunit], Sec=(of a program unit)}>,Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00243-01]} @ChgAdded{Version=[2],Text=[We want any rule that applies to a subunit to apply to a subunit of a subunit as well.]} @end{Reason} The parent body of a subunit shall be present in the current environment, and shall contain a corresponding @nt{body_stub} with the same @nt{defining_identifier} as the subunit. @begin{Discussion} This can't be a @ResolutionName, because a @nt{subunit} is not a complete context. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised]} A @nt{package_body_stub} shall be the completion of a @nt{package_@!declaration} or @nt{generic_@!package_@!declaration}; a @nt{task_@!body_@!stub} shall be the completion of a @Chg{Version=[2],New=[task declaration],Old=[@ntf{task_@!declaration}]}; a @nt{protected_@!body_stub} shall be the completion of a @Chg{Version=[2],New=[protected declaration],Old=[@ntf{protected_@!declaration}]}. In contrast, a @nt{subprogram_body_stub} need not be the completion of a previous declaration, @Redundant[in which case the @ntf{_stub} declares the subprogram]. If the @ntf{_stub} is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of a @nt{subprogram_body_stub} that completes a declaration shall conform fully to that of the declaration. @Defn2{Term=[full conformance],Sec=(required)} @begin{Discussion} The part about @nt{subprogram_body_stub}s echoes the corresponding rule for @ntf{subprogram_bodies} in @RefSec{Subprogram Bodies}. @end{Discussion} A subunit that corresponds to a @nt{body_stub} shall be of the same kind (@ntf{package_}, @ntf{subprogram_}, @ntf{task_}, or @ntf{protected_}) as the @nt{body_stub}. The profile of a @nt{subprogram_body} subunit shall be fully conformant to that of the corresponding @nt{body_stub}. @Defn2{Term=[full conformance],Sec=(required)} A @nt{body_stub} shall appear immediately within the @nt{declarative_part} of a compilation unit body. This rule does not apply within an instance of a generic unit. @begin{Discussion} @Defn{methodological restriction} This is a methodological restriction; that is, it is not necessary for the semantics of the language to make sense. @end{Discussion} The @nt{defining_identifier}s of all @nt{body_stub}s that appear immediately within a particular @nt{declarative_part} shall be distinct. @end{Legality} @begin{LinkTime} For each @nt{body_stub}, there shall be a subunit containing the corresponding @nt{proper_body}. @end{LinkTime} @begin{Notes} @leading@;The rules in @RefSec{The Compilation Process} say that a @nt{body_stub} is equivalent to the corresponding @nt{proper_body}. This implies: @begin{Itemize} Visibility within a subunit is the visibility that would be obtained at the place of the corresponding @nt{body_stub} (within the parent body) if the @nt{context_clause} of the subunit were appended to that of the parent body. @begin{Ramification} Recursively. Note that this transformation might make the parent illegal; hence it is not a true equivalence, but applies only to visibility within the subunit. @end{Ramification} The effect of the elaboration of a @nt{body_stub} is to elaborate the subunit. @begin{Ramification} The elaboration of a subunit is part of its parent body's elaboration, whereas the elaboration of a child unit is not part of its parent declaration's elaboration. @end{Ramification} @end{Itemize} @begin{Ramification} A @nt<library_item> that is mentioned in a @nt{with_clause} of a subunit can be hidden (from direct @Chg{Version=[2],New=[visibility], Old=[visiblity]}) by a declaration (with the same @nt{identifier}) given in the subunit. Moreover, such a @nt<library_item> can even be hidden by a declaration given within the parent body since a library unit is declared in its parent's declarative region; this however does not affect the interpretation of the @nt{with_clause}s themselves, since only @nt<library_item>s are visible or directly visible in @nt{with_clause}s. The body of a protected operation cannot be a subunit. This follows from the syntax rules. The body of a protected unit can be a subunit. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@;The package Parent is first written without subunits: @begin{Example} @key[package] Parent @key[is] @key[procedure] Inner; @key[end] Parent; @key[with] Ada.Text_IO; @key[package] @key[body] Parent @key[is] Variable : String := "Hello, there."; @key[procedure] Inner @key[is] @key[begin] Ada.Text_IO.Put_Line(Variable); @key[end] Inner; @key[end] Parent; @end{Example} @begin{Wide} @leading@;The body of procedure Inner may be turned into a subunit by rewriting the package body as follows (with the declaration of Parent remaining the same): @end{Wide} @begin{Example} @key[package] @key[body] Parent @key[is] Variable : String := "Hello, there."; @key[procedure] Inner @key[is] @key[separate]; @key[end] Parent; @key[with] Ada.Text_IO; @key[separate](Parent) @key[procedure] Inner @key[is] @key[begin] Ada.Text_IO.Put_Line(Variable); @key[end] Inner; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Subunits of the same ancestor library unit are no longer restricted to have distinct identifiers. Instead, we require only that the full expanded names be distinct. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{overriding_indicator} (see @RefSecNum{Overriding Indicators}) is allowed on a subprogram stub.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00243-01]} @ChgAdded{Version=[2],Text=[Clarified that a subunit of a subunit is still a subunit.]} @end{DiffWord95} @LabeledSubClause{The Compilation Process} @begin{Intro} @Defn{environment} @Defn{environment @nt<declarative_part>} Each compilation unit submitted to the compiler is compiled in the context of an @i{environment} @nt<declarative_part> (or simply, an @i{environment}), which is a conceptual @nt<declarative_part> that forms the outermost declarative region of the context of any @nt{compilation}. At run time, an environment forms the @nt<declarative_part> of the body of the environment task of a partition (see @RefSec{Program Execution}). @begin{Ramification} At compile time, there is no particular construct that the declarative region is considered to be nested within @em the environment is the universe. @end{Ramification} @begin{Honest} The environment is really just a portion of a @nt{declarative_part}, since there might, for example, be bodies that do not yet exist. @end{Honest} The @nt{declarative_item}s of the environment are @nt{library_item}s appearing in an order such that there are no forward semantic dependences. Each included subunit occurs in place of the corresponding stub. The visibility rules apply as if the environment were the outermost declarative region, except that @nt{with_@!clause}s are needed to make declarations of library units visible (see @RefSecNum{Context Clauses - With Clauses}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} The mechanisms for creating an environment and for adding and replacing compilation units within an environment are implementation defined.@Chg{Version=[2],New=[ The mechanisms for adding a compilation unit mentioned in a @nt{limited_with_clause} to an environment are implementation defined.],Old=[]} @ImplDef{The mechanisms for creating an environment and for adding and replacing compilation units.} @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[The mechanisms for adding a compilation unit mentioned in a @nt{limited_with_clause} to an environment.],Old=[]}]} @begin{Ramification} The traditional model, used by most Ada 83 implementations, is that one places a compilation unit in the environment by compiling it. Other models are possible. For example, an implementation might define the environment to be a directory; that is, the compilation units in the environment are all the compilation units in the source files contained in the directory. In this model, the mechanism for replacing a compilation unit with a new one is simply to edit the source file containing that compilation unit. @end{Ramification} @end{Intro} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0032],ARef=[AI95-00192-01]} If a @nt<library_unit_body> that is a @nt<subprogram_body> is submitted to the compiler, it is interpreted only as a completion if a @nt<library_unit_declaration> @Chg{New=[], Old=[for a subprogram or a generic subprogram ]}with the same @nt<defining_program_unit_name> already exists in the environment @Chg{New=[for a subprogram other than an instance of a generic subprogram or for a generic subprogram ], Old=[]} (even if the profile of the body is not type conformant with that of the declaration); otherwise the @nt<subprogram_body> is interpreted as both the declaration and body of a library subprogram. @PDefn{type conformance} @begin{Ramification} The principle here is that a @nt{subprogram_body} should be interpreted as only a completion if and only if it @lquotes@;might@rquotes@; be legal as the completion of some preexisting declaration, where @lquotes@;might@rquotes@; is defined in a way that does not require overload resolution to determine. Hence, if the preexisting declaration is a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}, we treat the new @nt{subprogram_body} as its completion, because it @lquotes@;might@rquotes@; be legal. If it turns out that the profiles don't fully conform, it's an error. In all other cases (the preexisting declaration is a package or a generic package, or an instance of a generic subprogram, or a renaming, or a @lquotes@;spec-less@rquotes@; subprogram, or in the case where there is no preexisting thing), the @nt{subprogram_body} declares a new subprogram. See also AI83-00266/09. @end{Ramification} @end{Resolution} @begin{Legality} When a compilation unit is compiled, all compilation units upon which it depends semantically shall already exist in the environment; @Defn2{Term=[consistency], Sec=(among compilation units)} the set of these compilation units shall be @i{consistent} in the sense that the new compilation unit shall not semantically depend (directly or indirectly) on two different versions of the same compilation unit, nor on an earlier version of itself. @begin{Discussion} For example, if package declarations A and B both say @lquotes@;@key[with] X;@rquotes@;, and the user compiles a compilation unit that says @lquotes@;@key[with] A, B;@rquotes@;, then the A and B have to be talking about the same version of X. @end{Discussion} @begin{Ramification} What it means to be a @lquotes@;different version@rquotes@; is not specified by the language. In some implementations, it means that the compilation unit has been recompiled. In others, it means that the source of the compilation unit has been edited in some significant way. Note that an implementation cannot require the existence of compilation units upon which the given one does not semantically depend. For example, an implementation is required to be able to compile a compilation unit that says "@key{with} A;" when A's body does not exist. It has to be able to detect errors without looking at A's body. Similarly, the implementation has to be able to compile a call to a subprogram for which a @nt{pragma} Inline has been specified without seeing the body of that subprogram @em inlining would not be achieved in this case, but the call is still legal. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The second rule applies to limited views as well as the full view of a compilation unit. That means that an implementation needs a way to enforce consistency of limited views, not just of full views.]} @end{Ramification} @end{Legality} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} The implementation may require that a compilation unit be legal before @Chg{Version=[2],New=[it can be mentioned in a @nt{limited_with_clause} or it can be inserted],Old=[inserting it]} into the environment. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00214-01]} When a compilation unit that declares or renames a library unit is added to the environment, the implementation may remove from the environment any preexisting @nt<library_item> @Chg{Version=[2],New=[or @nt<subunit> with the same full expanded name], Old=[with the same @nt<defining_@!program_@!unit_name>]}. When a compilation unit that is a subunit or the body of a library unit is added to the environment, the implementation may remove from the environment any preexisting version of the same compilation unit. @Chg{Version=[2],New=[When a compilation unit that contains a @nt<body_stub> is added to the environment, the implementation may remove any preexisting @nt<library_item> or @nt<subunit> with the same full expanded name as the @nt<body_stub>.],Old=[]} When a given compilation unit is removed from the environment, the implementation may also remove any compilation unit that depends semantically upon the given one. If the given compilation unit contains the body of a subprogram to which a @nt{pragma} Inline applies, the implementation may also remove any compilation unit containing a call to that subprogram. @begin{Ramification} The permissions given in this paragraph correspond to the traditional model, where compilation units enter the environment by being compiled into it, and the compiler checks their legality at that time. A implementation model in which the environment consists of all source files in a given directory might not want to take advantage of these permissions. Compilation units would not be checked for legality as soon as they enter the environment; legality checking would happen later, when compilation units are compiled. In this model, compilation units might never be automatically removed from the environment; they would be removed when the user explicitly deletes a source file. Note that the rule is recursive: if the above permission is used to remove a compilation unit containing an inlined subprogram call, then compilation units that depend semantically upon the removed one may also be removed, and so on. Note that here we are talking about dependences among existing compilation units in the environment; it doesn't matter what @nt{with_clause}s are attached to the new compilation unit that triggered all this. An implementation may have other modes in which compilation units in addition to the ones mentioned above are removed. For example, an implementation might inline subprogram calls without an explicit @nt{pragma} Inline. If so, it either has to have a mode in which that optimization is turned off, or it has to automatically regenerate code for the inlined calls without requiring the user to resubmit them to the compiler. @end{Ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0108],ARef=[AI95-00077-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @ChgAdded{Version=[1],Text=[In the standard mode, implementations may only remove units from the environment for one of the reasons listed here, or in response to an explicit user command to modify the environment. It is not intended that the act of compiling a unit is one of the @lquotes@;@Chg{Version=[2],New=[mechanisms],Old=[mechansisms]}@rquotes for removing units other than those specified by this International Standard.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00214-01]} @ChgAdded{Version=[2],Text=[These rules are intended to ensure that an implementation never need keep more than one compilation unit with any full expanded name. In particular, it is not necessary to be able to have a subunit and a child unit with the same name in the environment at one time.]} @end{Discussion} @end{ImplPerm} @begin{Notes} The rules of the language are enforced across @nt{compilation} and compilation unit boundaries, just as they are enforced within a single compilation unit. @begin{Ramification} Note that Section 1 requires an implementation to detect illegal compilation units at compile time. @end{Ramification} @Defn{library} An implementation may support a concept of a @i{library}, which contains @nt{library_item}s. If multiple libraries are supported, the implementation has to define how a single environment is constructed when a compilation unit is submitted to the compiler. Naming conflicts between different libraries might be resolved by treating each library as the root of a hierarchy of child library units. @IndexSee{Term=[program library],See=(library)} @begin{ImplNote} Alternatively, naming conflicts could be resolved via some sort of hiding rule. @end{ImplNote} @begin{Discussion} For example, the implementation might support a command to import library Y into library X. If a root library unit called LU (that is, Standard.LU) exists in Y, then from the point of view of library X, it could be called Y.LU. X might contain library units that say, @lquotes@;@key[with] Y.LU;@rquotes@;. @end{Discussion} A compilation unit containing an instantiation of a separately compiled generic unit does not semantically depend on the body of the generic unit. Therefore, replacing the generic body in the environment does not result in the removal of the compilation unit containing the instantiation. @begin{ImplNote} Therefore, implementations have to be prepared to automatically instantiate generic bodies at link-time, as needed. This might imply a complete automatic recompilation, but it is the intent of the language that generic bodies can be (re)instantiated without forcing all of the compilation units that semantically depend on the compilation unit containing the instantiation to be recompiled. @end{ImplNote} @end{Notes} @begin{Extend83} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00077-01],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 83} Ada 83 allowed implementations to require that the body of a generic unit be available when the instantiation is compiled; that permission is dropped in Ada 95. This isn't really an extension (it doesn't allow Ada users to write anything that they couldn't in Ada 83), but there isn't a more appropriate category, and it does allow users more flexibility when developing programs.]} @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0032],ARef=[AI95-00192-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was clarified to ensure that a @nt{subprogram_body} is not considered a completion of an instance of a generic subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00214-01]} @ChgAdded{Version=[2],Text=[The permissions to remove a unit from the environment were clarified to ensure that it is never necessary to keep multiple (sub)units with the same full expanded name in the environment.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Units mentioned in a @nt{limited_with_clause} were added to several rules; limited views have the same presence in the environment as the corresponding full views.]} @end{DiffWord95} @LabeledSubClause{Pragmas and Program Units} @begin{Intro} @Redundant[This subclause discusses pragmas related to program units, library units, and @nt{compilation}s.] @end{Intro} @begin{Resolution} @RootDefn{program unit pragma} @RootDefn{pragma, program unit} Certain @nt{pragma}s are defined to be @i{program unit pragmas}. @PDefn2{Term=[apply], Sec=(to a program unit by a program unit pragma)} A @nt{name} given as the argument of a program unit pragma shall resolve to denote the declarations or renamings of one or more program units that occur immediately within the declarative region or @nt<compilation> in which the @nt<pragma> immediately occurs, or it shall resolve to denote the declaration of the immediately enclosing program unit (if any); the @nt{pragma} applies to the denoted program unit(s). If there are no @nt{name}s given as arguments, the @nt{pragma} applies to the immediately enclosing program unit. @begin{Ramification} The fact that this is a @ResolutionName means that the @nt{pragma} will not apply to declarations from outer declarative regions. @end{Ramification} @end{Resolution} @begin{Legality} @leading@keepnext@;A program unit pragma shall appear in one of these places: @begin{Itemize} At the place of a @nt{compilation_unit}, in which case the @nt<pragma> shall immediately follow in the same @nt<compilation> (except for other @nt{pragma}s) a @nt{library_@!unit_@!declaration} that is a @nt<subprogram_@!declaration>, @nt<generic_@!subprogram_@!declaration>, or @nt<generic_@!instantiation>, and the @nt<pragma> shall have an argument that is a @nt<name> denoting that declaration. @begin{Ramification} The @nt{name} has to denote the immediately preceding @nt{library_unit_declaration}. @end{Ramification} @ChgRef{Version=[1], Kind=[Revised], Ref=[8652/0033], ARef=[AI95-00136-01]} Immediately within the @Chg{New=[visible part],Old=[declaration]} of a program unit and before any nested declaration@Chg{New=[ (but not within a generic formal part)], Old=[]}, in which case the argument, if any, shall be a @nt{direct_name} that denotes the immediately enclosing program unit declaration. @begin{Ramification} The argument is optional in this case. @end{Ramification} At the place of a declaration other than the first, of a @nt{declarative_part} or program unit declaration, in which case the @nt{pragma} shall have an argument, which shall be a @nt{direct_name} that denotes one or more of the following (and nothing else): a @nt{subprogram_@!declaration}, a @nt{generic_@!subprogram_@!declaration}, or a @nt{generic_@!instantiation}, of the same @nt<declarative_@!part> or program unit declaration. @begin{Ramification} If you want to denote a @nt<subprogram_body> that is not a completion, or a @nt{package_declaration}, for example, you have to put the @nt{pragma} inside. @end{Ramification} @end{Itemize} @RootDefn{library unit pragma} @RootDefn{pragma, library unit} @PDefn2{Term=[program unit pragma], Sec=(library unit pragmas)} @PDefn2{Term=[pragma, program unit], Sec=(library unit pragmas)} Certain program unit pragmas are defined to be @i{library unit pragmas}. The @nt{name}, if any, in a library unit pragma shall denote the declaration of a library unit. @begin{Ramification} This, together with the rules for program unit pragmas above, implies that if a library unit pragma applies to a @nt{subprogram_declaration} (and similar things), it has to appear immediately after the @nt{compilation_unit}, whereas if the @nt{pragma} applies to a @nt{package_declaration}, a @nt{subprogram_body} that is not a completion (and similar things), it has to appear inside, as the first @nt{declarative_item}. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1], Kind=[Added], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[1],Text=[A library unit pragma that applies to a generic unit does not apply to its instances, unless a specific rule for the pragma specifies the contrary.]} @end{StaticSem} @begin{LinkTime} @RootDefn{configuration pragma} @RootDefn{pragma, configuration} Certain @nt{pragma}s are defined to be @i{configuration pragmas}; they shall appear before the first @nt{compilation_unit} of a @nt{compilation}. @Redundant[They are generally used to select a partition-wide or system-wide option.] The @nt<pragma> applies to all @nt{compilation_unit}s appearing in the @nt{compilation}, unless there are none, in which case it applies to all future @nt{compilation_unit}s compiled into the same environment. @end{LinkTime} @begin{ImplPerm} @ChgRef{Version=[2], Kind=[Revised], ARef=[AI95-00212-01]} An implementation may @Chg{Version=[2], New=[require that configuration pragmas that select partition-wide or system-wide options be compiled], Old=[place restrictions on configuration pragmas, so long as it allows them]} when the environment contains no @nt{library_item}s other than those of the predefined environment. @Chg{Version=[2], New=[In this case, the implementation shall still accept configuration pragmas in individual compilations that confirm the initially selected partition-wide or system-wide options.],Old=[]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[1], Kind=[AddedNormal], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[1],Text=[When applied to a generic unit, a program unit pragma that is not a library unit pragma should apply to each instance of the generic unit for which there is not an overriding pragma applied directly to the instance.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When applied to a generic unit, a program unit pragma that is not a library unit pragma should apply to each instance of the generic unit for which there is not an overriding pragma applied directly to the instance.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2], Kind=[AddedNormal], Ref=[8652/0033], ARef=[AI95-00136-01]} @ChgAdded{Version=[2], Text=[@B<Corrigendum:> The wording was corrected to ensure that a program unit pragma cannot appear in private parts or generic formal parts.]} @ChgRef{Version=[2], Kind=[AddedNormal], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[2], Text=[@B<Corrigendum:> The wording was clarified to explain the meaning of program unit and library unit pragmas in generic units.]} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[The Implementation Advice added by the Corrigendum was moved, as it was not in the normal order. (This changes the paragraph number.) It originally was directly after the new Static Semantics rule.]} @ChgRef{Version=[2], Kind=[AddedNormal], ARef=[AI95-00212-01]} @ChgAdded{Version=[2], Type=[Leading],Keepnext=[T],Text=[The permission to place restrictions was clarified to:]} @begin{itemize} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[Ensure that it applies only to partition-wide configuration pragmas, not ones like Assertion_Policy (see @RefSecNum{Pragmas Assert and Assertion_Policy}), which can be different in different units; and]} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[Ensure that confirming pragmas are always allowed.]} @end{itemize} @end{DiffWord95} @LabeledSubClause{Environment-Level Visibility Rules} @begin{Intro} @Redundant[The normal visibility rules do not apply within a @nt{parent_unit_name} or a @nt{context_clause}, nor within a @nt{pragma} that appears at the place of a compilation unit. The special visibility rules for those contexts are given here.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00312-01]} @PDefn2{Term=[directly visible], Sec=(within the @nt{parent_unit_name} of a library unit)} @PDefn2{Term=[visible], Sec=(within the @nt{parent_unit_name} of a library unit)} @PDefn2{Term=[directly visible], Sec=(within a @nt{with_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{with_clause})} Within the @nt{parent_unit_name} at the beginning of @Chg{Version=[2],New=[an explicit],Old=[a]} @nt{library_item}, and within a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}], Old=[@nt{with_clause}]}, the only declarations that are visible are those that are@Chg{Version=[2],New=[ explicit],Old=[]} @nt<library_item>s of the environment, and the only declarations that are directly visible are those that are@Chg{Version=[2],New=[ explicit],Old=[]} root @nt<library_item>s of the environment. @Chg{Version=[2],New=[Within a @nt{limited_with_clause}, the only declarations that are visible are those that are the implicit declaration of the limited view of a library package of the environment, and the only declarations that are directly visible are those that are the implicit declaration of the limited view of a root library package.], Old=[@Defn{notwithstanding} Notwithstanding the rules of @RefSecNum(Selected Components), an expanded name in a @nt{with_clause} may consist of a @nt<prefix> that denotes a generic package and a @nt<selector_name> that denotes a child of that generic package. @Redundant[(The child is necessarily a generic unit; see @RefSecNum{Compilation Units - Library Units}.)]]} @begin{Ramification} In @lquotes@;@key{package} P.Q.R @key{is} ... @key{end} P.Q.R;@rquotes@;, this rule requires P to be a root library unit, and Q to be a library unit (because those are the things that are directly visible and visible). Note that visibility does not apply between the @lquotes@;@key{end}@rquotes@; and the @lquotes@;;@rquotes@;. Physically nested declarations are not visible at these places. @ChgNote{Changed the classification of this note from Reason to Ramification, as it certainly isn't a "reason". Besides, there were two reasons, which was goofy.} Although Standard is visible at these places, it is impossible to name it, since it is not directly visible, and it has no parent. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Only compilation units defining limited views can be mentioned in a @nt{limited_with_clause}, while only compilation units defining full views (that is, the explicit declarations) can be mentioned in a @nt{nonlimited_with_clause}. This resolves the conflict inherent in having two compilation units with the same defining name.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00312-01]} @ChgDeleted{Version=[2],Text=[The @lquotes@;notwithstanding@rquotes@; part allows @lquotes@;@key[with] A.B;@rquotes@; where A is a generic library package and B is one of its (generic) children. This is necessary because it is not normally legal to use an expanded name to reach inside a generic package.]} @end{Reason} @PDefn2{Term=[directly visible], Sec=(within a @nt{use_clause} in a @nt{context_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{use_clause} in a @nt{context_clause})} @PDefn2{Term=[directly visible], Sec=(within a @nt{pragma} in a @nt{context_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{pragma} in a @nt{context_clause})} Within a @nt{use_clause} or @nt{pragma} that is within a @nt{context_clause}, each @nt<library_item> mentioned in a previous @nt{with_clause} of the same @nt{context_clause} is visible, and each root @nt<library_item> so mentioned is directly visible. In addition, within such a @nt{use_clause}, if a given declaration is visible or directly visible, each declaration that occurs immediately within the given declaration's visible part is also visible. No other declarations are visible or directly visible. @begin{Discussion} Note the word @lquotes@;same@rquotes@;. For example, if a @nt{with_clause} on a declaration mentions X, this does not make X visible in @nt{use_clause}s and @nt{pragma}s that are on the body. The reason for this rule is the one-pass @nt{context_clause}s @MetaRulesName. Note that the second part of the rule does not mention @nt{pragma}s. @end{Discussion} @PDefn2{Term=[directly visible], Sec=(within the @nt{parent_unit_name} of a subunit)} @PDefn2{Term=[visible], Sec=(within the @nt{parent_unit_name} of a subunit)} Within the @nt{parent_unit_name} of a subunit, @nt<library_item>s are visible as they are in the @nt{parent_unit_name} of a @nt{library_item}; in addition, the declaration corresponding to each @nt{body_stub} in the environment is also visible. @begin{Ramification} For a subprogram without a separate @nt<subprogram_declaration>, the @nt<body_stub> itself is the declaration. @end{Ramification} @PDefn2{Term=[directly visible], Sec=(within a @nt{pragma} that appears at the place of a compilation unit)} @PDefn2{Term=[visible], Sec=(within a @nt{pragma} that appears at the place of a compilation unit)} Within a @nt{pragma} that appears at the place of a compilation unit, the immediately preceding @nt<library_item> and each of its ancestors is visible. The ancestor root @nt<library_item> is directly visible. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00312-01]} @ChgAdded{Version=[2],Text=[@Defn{notwithstanding} Notwithstanding the rules of @RefSecNum(Selected Components), an expanded name in a @nt{with_clause}, a @nt{pragma} in a @nt{context_clause}, or a @nt{pragma} that appears at the place of a compilation unit may consist of a @nt{prefix} that denotes a generic package and a @nt<selector_name> that denotes a child of that generic package. @Redundant[(The child is necessarily a generic unit; see @RefSecNum{Compilation Units - Library Units}.)]]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule allows @key[with] A.B; and @key[pragma] Elaborate(A.B); where A is a generic library package and B is one of its (generic) children. This is necessary because it is not normally legal to use an expanded name to reach inside a generic package.]} @end{Reason} @end{StaticSem} @begin{DiffWord83} The special visibility rules that apply within a @nt{parent_unit_name} or a @nt{context_clause}, and within a @nt{pragma} that appears at the place of a @nt{compilation_unit} are clarified. Note that a @nt{context_clause} is not part of any declarative region. We considered making the visibility rules within @nt{parent_unit_name}s and @nt{context_clause}s follow from the context of compilation. However, this attempt failed for various reasons. For example, it would require @nt{use_clause}s in @nt{context_clause}s to be within the declarative region of Standard, which sounds suspiciously like a kludge. And we would still need a special rule to prevent seeing things (in our own @nt{context_clause}) that were with-ed by our parent, etc. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Added separate visibility rules for @nt{limited_with_clause}s; the existing rules apply only to @nt{nonlimited_with_clause}s.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00312-01]} @ChgAdded{Version=[2],Text=[Clarified that the name of a generic child unit may appear in a @nt{pragma} in a @nt{context_clause}.]} @end{DiffWord95} @NewPage @LabeledClause{Program Execution} @begin{Intro} @Defn{program} @Defn{program execution} @IndexSee{Term=[running a program],See=(program execution)} An Ada @i{program} consists of a set of @i{partitions}@Redundant[, which can execute in parallel with one another, possibly in a separate address space, and possibly on a separate computer.] @end{Intro} @begin{LinkTime} @RootDefn{partition} @Defn{partition building} A partition is a program or part of a program that can be invoked from outside the Ada implementation. @Redundant[For example, on many systems, a partition might be an executable file generated by the system linker.] @Defn{explicitly assign} The user can @i{explicitly assign} library units to a partition. The assignment is done in an implementation-defined manner. The compilation units included in a partition are those of the explicitly assigned library units, as well as other compilation units @i{needed by} those library units. The compilation units needed by a given compilation unit are determined as follows (unless specified otherwise via an implementation-defined @nt{pragma}, or by some other implementation-defined means): @IndexSee{Term=[linking],See=(partition building)} @RootDefn2{Term=[compilation units needed], Sec=(by a compilation unit)} @RootDefn2{Term=[needed], Sec=(of a compilation unit by another)} @begin{Discussion} From a run-time point of view, an Ada 95 partition is identical to an Ada 83 program @em implementations were always allowed to provide inter-program communication mechanisms. The additional semantics of partitions is that interfaces between them can be defined to obey normal language rules (as is done in @RefSec{Distributed Systems}), whereas interfaces between separate programs had no particular semantics. @end{Discussion} @ImplDef{The manner of explicitly assigning library units to a partition.} @ImplDef{The implementation-defined means, if any, of specifying which compilation units are needed by a given compilation unit.} @begin{Discussion} There are no pragmas that @lquotes@;specify otherwise@rquotes@; defined by the core language. However, an implementation is allowed to provide such pragmas, and in fact @RefSec{Distributed Systems} defines some pragmas whose semantics includes reducing the set of compilation units described here. @end{Discussion} @begin{Itemize} A compilation unit needs itself; If a compilation unit is needed, then so are any compilation units upon which it depends semantically; If a @nt{library_unit_declaration} is needed, then so is any corresponding @nt{library_unit_body}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} If a compilation unit with stubs is needed, then so are any corresponding subunits@Chg{Version=[2],New=[;],Old=[.]} @begin{Discussion} Note that in the environment, the stubs are replaced with the corresponding @ntf{proper_bodies}. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[If the (implicit) declaration of the limited view of a library package is needed, then so is the explicit declaration of the library package.]} @end{Itemize} @begin{Discussion} Note that a child unit is not included just because its parent is included @em to include a child, mention it in a @nt{with_clause}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[A package is included in a partition even if the only reference to it is in a @nt{limited_with_clause}. While this isn't strictly necessary (no objects of types imported from such a unit can be created), it ensures that all incomplete types are eventually completed, and is the least surprising option.]} @end{Discussion} @Defn2{Term=[main subprogram], Sec=(for a partition)} The user can optionally designate (in an implementation-defined manner) one subprogram as the @i{main subprogram} for the partition. A main subprogram, if specified, shall be a subprogram. @begin{Discussion} This may seem superfluous, since it follows from the definition. But we would like to have every error message that might be generated (before run time) by an implementation correspond to some explicitly stated @lquotes@;shall@rquotes@; rule. Of course, this does not mean that the @lquotes@;shall@rquotes@; rules correspond one-to-one with an implementation's error messages. For example, the rule that says overload resolution @lquotes@;shall@rquotes@; succeed in producing a single interpretation would correspond to many error messages in a good implementation @em the implementation would want to explain to the user exactly why overload resolution failed. This is especially true for the syntax rules @em they are considered part of overload resolution, but in most cases, one would expect an error message based on the particular syntax rule that was violated. @end{Discussion} @ImplDef{The manner of designating the main subprogram of a partition.} @begin{Ramification} An implementation cannot require the user to specify, say, all of the library units to be included. It has to support, for example, perhaps the most typical case, where the user specifies just one library unit, the main program. The implementation has to do the work of tracking down all the other ones. @end{Ramification} @Defn{environment task} Each partition has an anonymous @i{environment task}@Redundant[, which is an implicit outermost task whose execution elaborates the @nt{library_item}s of the environment @nt{declarative_part}, and then calls the main subprogram, if there is one. A partition's execution is that of its tasks.] @begin{Ramification} An environment task has no master; all nonenvironment tasks have masters. An implementation is allowed to support multiple concurrent executions of the same partition. @end{Ramification} @Redundant[The order of elaboration of library units is determined primarily by the @i{elaboration dependences}.] @Defn2{Term=[elaboration dependence], Sec=(library_item on another)} @Defn2{Term=[dependence], Sec=(elaboration)} There is an elaboration dependence of a given @nt{library_item} upon another if the given @nt{library_item} or any of its subunits depends semantically on the other @nt{library_item}. In addition, if a given @nt{library_item} or any of its subunits has a @nt{pragma} Elaborate or Elaborate_All that @Chg{Version=[2],New=[names],Old=[mentions]} another library unit, then there is an elaboration dependence of the given @nt{library_item} upon the body of the other library unit, and, for Elaborate_All only, upon each @nt{library_item} needed by the declaration of the other library unit. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0107],ARef=[AI95-00180-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[@Lquotes@;Mentions@rquotes @Chg{Version=[2],New=[was],Old=[is]} used informally in the above rule; it @Chg{Version=[2],New=[was],Old=[is]} not intended to refer to the definition of @i{mentions} in @RefSecNum{Context Clauses - With Clauses}. @Chg{Version=[2],New=[It was changed to @Lquotes@;names@rquotes to make this clear.], Old=[It would have been better to use @Lquotes@;names@rquotes instead of @Lquotes@;mentions@rquotes above.]}]} See above for a definition of which @nt{library_item}s are @lquotes@;needed by@rquotes@; a given declaration. Note that elaboration dependences are among @nt{library_item}s, whereas the other two forms of dependence are among compilation units. Note that elaboration dependence includes semantic dependence. It's a little bit sad that pragma Elaborate_Body can't be folded into this mechanism. It follows from the definition that the elaboration dependence relationship is transitive. Note that the wording of the rule does not need to take into account a semantic dependence of a @nt{library_item} or one of its subunits upon a subunit of a different library unit, because that can never happen. @end{Discussion} @leading@keepnext@;The environment task for a partition has the following structure: @begin{Example} @key[task] @RI{Environment_Task}; @ChgRef{Version=[2],Kind=[Revised]}@Comment{The fonts corrected below} @key[task] @key[body] @RI{Environment_Task} @key[is] ... (1) --@RI{ The environment }@nt{declarative_part} --@RI{ (that is, the sequence of }@nt{library_item}@RI{s) goes here.} @key[begin] ... (2) --@RI{ Call the main subprogram, if there is one.} @key[end] @RI{Environment_Task}; @end{Example} @begin{Ramification} The name of the environment task is written in italics here to indicate that this task is anonymous. @end{Ramification} @begin{Discussion} The model is different for a @lquotes@;passive partition@rquotes@; (see @RefSecNum{Partitions}). Either there is no environment task, or its @nt<sequence_of_statements> is an infinite loop rather than a call on a main subprogram. @end{Discussion} @leading@PDefn2{Term=[environment @nt<declarative_part>], Sec=(for the environment task of a partition)} The environment @nt{declarative_part} at (1) is a sequence of @nt{declarative_item}s consisting of copies of the @nt{library_item}s included in the partition@Redundant[. The order of elaboration of @nt{library_item}s is the order in which they appear in the environment @nt{declarative_part}]: @begin{Itemize} The order of all included @nt<library_item>s is such that there are no forward elaboration dependences. @begin{Ramification} This rule is written so that if a @nt{library_item} depends on itself, we don't require it to be elaborated before itself. See AI83-00113/12. This can happen only in pathological circumstances. For example, if a library @nt{subprogram_body} has no corresponding @nt{subprogram_declaration}, and one of the subunits of the @nt{subprogram_body} mentions the @nt{subprogram_body} in a @nt{with_clause}, the @nt{subprogram_body} will depend on itself. For another example, if a @nt{library_unit_body} applies a @nt{pragma} Elaborate_All to its own declaration, then the @nt{library_unit_body} will depend on itself. @end{Ramification} Any included @nt{library_unit_declaration} to which a @nt{pragma} Elaborate_Body applies is immediately followed by its @nt{library_unit_body}, if included. @begin{Discussion} This implies that the body of such a library unit shall not @lquotes@;with@rquotes@; any of its own children, or anything else that depends semantically upon the declaration of the library unit. @end{Discussion} All @nt{library_item}s declared pure occur before any that are not declared pure. All preelaborated @nt<library_item>s occur before any that are not preelaborated. @end{Itemize} @begin{Discussion} Normally, if two partitions contain the same compilation unit, they each contain a separate @i{copy} of that compilation unit. See @RefSec{Distributed Systems} for cases where two partitions share the same copy of something. There is no requirement that the main subprogram be elaborated last. In fact, it is possible to write a partition in which the main subprogram cannot be elaborated last. @end{Discussion} @begin{Ramification} This @nt{declarative_part} has the properties required of all environments (see @RefSecNum{The Compilation Process}). However, the environment @nt{declarative_part} of a partition will typically contain fewer compilation units than the environment @nt{declarative_part} used at compile time @em only the @lquotes@;needed@rquotes@; ones are included in the partition. @end{Ramification} There shall be a total order of the @nt{library_item}s that obeys the above rules. The order is otherwise implementation defined. @begin{Discussion} The only way to violate this rule is to have Elaborate, Elaborate_All, or Elaborate_Body @nt{pragma}s that cause circular ordering requirements, thus preventing an order that has no forward elaboration dependences. @end{Discussion} @ImplDef{The order of elaboration of @nt{library_item}s.} @begin{Honest} @PDefn2{Term=[requires a completion], Sec=(library_unit_declaration)} @Defn{notwithstanding} Notwithstanding what the RM95 says elsewhere, each rule that requires a declaration to have a corresponding completion is considered to be a @LinkTimeName when the declaration is that of a library unit. @end{Honest} @begin{Discussion} Such rules may be checked at @lquotes@;link time,@rquotes@; for example. Rules requiring the completion to have certain properties, on the other hand, are checked at compile time of the completion. @end{Discussion} The full expanded names of the library units and subunits included in a given partition shall be distinct. @begin{Reason} This is a @LinkTimeName because making it a @LegalityName would violate the @MetaRulesName labeled @lquotes@;legality determinable via semantic dependences.@rquotes@; @end{Reason} @leading@;The @nt{sequence_of_statements} of the environment task (see (2) above) consists of either: @begin{Itemize} A call to the main subprogram, if the partition has one. If the main subprogram has parameters, they are passed; where the actuals come from is implementation defined. What happens to the result of a main function is also implementation defined. @ImplDef{Parameter passing and function return for the main subprogram.} @end{Itemize} @leading@keepnext@;or: @begin{Itemize} A @nt{null_statement}, if there is no main subprogram. @begin{Discussion} For a passive partition, either there is no environment task, or its @nt<sequence_of_statements> is an infinite loop. See @RefSecNum{Partitions}. @end{Discussion} @end{Itemize} The mechanisms for building and running partitions are implementation defined. @Redundant[These might be combined into one operation, as, for example, in dynamic linking, or @lquotes@;load-and-go@rquotes@; systems.] @ImplDef{The mechanisms for building and running partitions.} @end{LinkTime} @begin{RunTime} @PDefn2{Term=[execution], Sec=(program)} The execution of a program consists of the execution of a set of partitions. Further details are implementation defined. @PDefn2{Term=[execution], Sec=(partition)} The execution of a partition starts with the execution of its environment task, ends when the environment task terminates, and includes the executions of all tasks of the partition. @Redundant[The execution of the (implicit) @nt<task_body> of the environment task acts as a master for all other tasks created as part of the execution of the partition. When the environment task completes (normally or abnormally), it waits for the termination of all such tasks, and then finalizes any remaining objects of the partition.] @begin{Ramification} The @lquotes@;further details@rquotes@; mentioned above include, for example, program termination @em it is implementation defined. There is no need to define it here; it's entirely up to the implementation whether it wants to consider the program as a whole to exist beyond the existence of individual partitions. @end{Ramification} @ImplDef{The details of program execution, including program termination.} @begin{Honest} @PDefn2{Term=[termination], Sec=(of a partition)} @PDefn2{Term=[normal termination], Sec=(of a partition)} @PDefn2{Term=[termination], Sec=(normal)} @PDefn2{Term=[abnormal termination], Sec=(of a partition)} @PDefn2{Term=[termination], Sec=(abnormal)} The execution of the partition terminates (normally or abnormally) when the environment task terminates (normally or abnormally, respectively). @end{Honest} @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Once the environment task has awaited the termination of all other tasks of the partition, any further attempt to create a task (during finalization) is a bounded error, and may result in the raising of Program_Error either upon creation or activation of the task. @PDefn{unspecified} If such a task is activated, it is not specified whether the task is awaited prior to termination of the environment task. @end{Bounded} @begin{ImplReq} @Leading@;The implementation shall ensure that all compilation units included in a partition are consistent with one another, and are legal according to the rules of the language. @begin{Discussion} The consistency requirement implies that a partition cannot contain two versions of the same compilation unit. That is, a partition cannot contain two different library units with the same full expanded name, nor two different bodies for the same program unit. For example, suppose we compile the following: @begin{Example} @key[package] A @key[is] --@RI{ Version 1.} ... @key[end] A; @key[with] A; @key[package] B @key[is] @key[end] B; @key[package] A @key[is] --@RI{ Version 2.} ... @key[end] A; @key[with] A; @key[package] C @key[is] @key[end] C; @end{Example} It would be wrong for a partition containing B and C to contain both versions of A. Typically, the implementation would require the use of Version 2 of A, which might require the recompilation of B. Alternatively, the implementation might automatically recompile B when the partition is built. A third alternative would be an incremental compiler that, when Version 2 of A is compiled, automatically patches the object code for B to reflect the changes to A (if there are any relevant changes @em there might not be any). An implementation that supported fancy version management might allow the use of Version 1 in some circumstances. In no case can the implementation allow the use of both versions in the same partition (unless, of course, it can prove that the two versions are semantically identical). The core language says nothing about inter-partition consistency; see also @RefSec{Distributed Systems}. @end{Discussion} @end{ImplReq} @begin{ImplPerm} @Defn{active partition} The kind of partition described in this clause is known as an @i{active} partition. An implementation is allowed to support other kinds of partitions, with implementation-defined semantics. @ImplDef{The semantics of any nonactive partitions supported by the implementation.} @begin{Discussion} @RefSec{Distributed Systems} defines the concept of passive partitions; they may be thought of as a partition without an environment task, or as one with a particularly simple form of environment task, having an infinite loop rather than a call on a main subprogram as its @nt<sequence_of_statements>. @end{Discussion} An implementation may restrict the kinds of subprograms it supports as main subprograms. However, an implementation is required to support all main subprograms that are public parameterless library procedures. @begin{Ramification} The implementation is required to support main subprograms that are procedures declared by @nt{generic_instantiation}s, as well as those that are children of library units other than Standard. Generic units are, of course, not allowed to be main subprograms, since they are not subprograms. Note that renamings are irrelevant to this rule. This rules says which subprograms (not views) have to be supported. The implementation can choose any way it wants for the user to indicate which subprogram should be the main subprogram. An implementation might allow any name of any view, including those declared by renamings. Another implementation might require it to be the original name. Another implementation still might use the name of the source file or some such thing. @end{Ramification} If the environment task completes abnormally, the implementation may abort any dependent tasks. @begin{Reason} If the implementation does not take advantage of this permission, the normal action takes place @em the environment task awaits those tasks. The possibility of aborting them is not shown in the @i{Environment_Task} code above, because there is nowhere to put an @nt{exception_handler} that can handle exceptions raised in both the environment @nt{declarative_part} and the main subprogram, such that the dependent tasks can be aborted. If we put an @nt{exception_handler} in the body of the environment task, then it won't handle exceptions that occur during elaboration of the environment @nt{declarative_part}. If we were to move those things into a nested @nt{block_statement}, with the @nt{exception_handler} outside that, then the @nt{block_statement} would await the library tasks we are trying to abort. Furthermore, this is merely a permission, and is not fundamental to the model, so it is probably better to state it separately anyway. Note that implementations (and tools like debuggers) can have modes that provide other behaviors in addition. @end{Reason} @end{ImplPerm} @begin{Notes} An implementation may provide inter-partition communication mechanism(s) via special packages and pragmas. Standard pragmas for distribution and methods for specifying inter-partition communication are defined in @RefSec{Distributed Systems}. If no such mechanisms are provided, then each partition is isolated from all others, and behaves as a program in and of itself. @begin{Ramification} Not providing such mechanisms is equivalent to disallowing multi-partition programs. An implementation may provide mechanisms to facilitate checking the consistency of library units elaborated in different partitions; @RefSec{Distributed Systems} does so. @end{Ramification} Partitions are not required to run in separate address spaces. For example, an implementation might support dynamic linking via the partition concept. An order of elaboration of @nt{library_item}s that is consistent with the partial ordering defined above does not always ensure that each @nt{library_unit_body} is elaborated before any other compilation unit whose elaboration necessitates that the @nt{library_unit_body} be already elaborated. (In particular, there is no requirement that the body of a library unit be elaborated as soon as possible after the @nt{library_unit_declaration} is elaborated, unless the pragmas in subclause @RefSecNum{Elaboration Control} are used.) A partition (active or otherwise) need not have a main subprogram. In such a case, all the work done by the partition would be done by elaboration of various @nt{library_item}s, and by tasks created by that elaboration. Passive partitions, which cannot have main subprograms, are defined in @RefSec{Distributed Systems}. @begin{Ramification} The environment task is the outermost semantic level defined by the language. Standard has no private part. This prevents strange implementation-dependences involving private children of Standard having visibility upon Standard's private part. It doesn't matter where the body of Standard appears in the environment, since it doesn't do anything. See @RefSec{Predefined Language Environment}. Note that elaboration dependence is carefully defined in such a way that if (say) the body of something doesn't exist yet, then there is no elaboration dependence upon the nonexistent body. (This follows from the fact that @lquotes@;needed by@rquotes@; is defined that way, and the elaboration dependences caused by a @nt{pragma} Elaborate or Elaborate_All are defined in terms of @lquotes@;needed by@rquotes@;.) This property allows us to use the environment concept both at compile time and at partition-construction time/run time. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concept of partitions is new to Ada 95. A main subprogram is now optional. The language-defined restrictions on main subprograms are relaxed. @end{Extend83} @begin{DiffWord83} Ada 95 uses the term @lquotes@;main subprogram@rquotes@; instead of Ada 83's @lquotes@;main program@rquotes@; (which was inherited from Pascal). This is done to avoid confusion @em a main subprogram is a subprogram, not a program. The program as a whole is an entirely different thing. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[The mistaken use of @lquotes@;mentions@rquotes@; in the elaboration dependence rule was fixed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The @i<needs> relationship was extended to include limited views.]} @end{DiffWord95} @LabeledSubClause{Elaboration Control} @begin{Intro} @Redundant[@Defn{elaboration control} This subclause defines pragmas that help control the elaboration order of @nt{library_item}s.] @end{Intro} @begin{MetaRules} The rules governing preelaboration are designed to allow it to be done largely by bulk initialization of statically allocated storage from information in a @lquotes@;load module@rquotes@; created by a linker. Some implementations may require run-time code to be executed in some cases, but we consider these cases rare enough that we need not further complicate the rules. It is important that programs be able to declare data structures that are link-time initialized with @nt{aggregate}s, @nt{string_literal}s, and concatenations thereof. It is important to be able to write link-time evaluated expressions involving the First, Last, and Length attributes of such data structures (including variables), because they might be initialized with positional @nt{aggregate}s or @nt{string_literal}s, and we don't want the user to have to count the elements. There is no corresponding need for accessing discriminants, since they can be initialized with a static constant, and then the constant can be referred to elsewhere. It is important to allow link-time initialized data structures involving discriminant-dependent components. It is important to be able to write link-time evaluated expressions involving pointers (both access values and addresses) to the above-mentioned data structures. The rules also ensure that no Elaboration_Check need be performed for calls on library-level subprograms declared within a preelaborated package. This is true also of the Elaboration_Check on task activation for library level task types declared in a preelaborated package. However, it is not true of the Elaboration_Check on instantiations. A static expression should never prevent a library unit from being preelaborable. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Preelaborate is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Preelaborate)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(Preelaborate)} @PDefn2{Term=[pragma, library unit], Sec=(Preelaborate)} A @nt{pragma} Preelaborate is a library unit pragma. @end{SyntaxText} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Preelaborable_Initialization is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Preelaborable_Initialization>(@Syn2{direct_name});'>} @end{Syntax} @begin{Legality} @Leading@RootDefn2{Term=[preelaborable], Sec=(of an elaborable construct)} An elaborable construct is preelaborable unless its elaboration performs any of the following actions: @begin{Ramification} A @i{preelaborable} construct can be elaborated without using any information that is available only at run time. Note that we don't try to prevent exceptions in preelaborable constructs; if the implementation wishes to generate code to raise an exception, that's OK. Because there is no flow of control and there are no calls (other than to predefined subprograms), these run-time properties can actually be detected at compile time. This is necessary in order to require compile-time enforcement of the rules. @end{Ramification} @begin{Itemize} The execution of a @nt{statement} other than a @nt{null_statement}. @begin{Ramification} A preelaborable construct can contain @nt{label}s and @nt{null_statement}s. @end{Ramification} A call to a subprogram other than a static function. The evaluation of a @nt{primary} that is a @nt{name} of an object, unless the @nt{name} is a static expression, or statically denotes a discriminant of an enclosing type. @begin{Ramification} One can evaluate such a @nt{name}, but not as a @nt{primary}. For example, one can evaluate an attribute of the object. One can evaluate an @nt{attribute_reference}, so long as it does not denote an object, and its @nt{prefix} does not disobey any of these rules. For example, Obj'Access, Obj'Unchecked_Access, and Obj'Address are generally legal in preelaborated library units. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} The creation of a@Chg{Version=[2],New=[n object @Redundant[(including a component)] of a type that does not have preelaborable initialization. Similarly,], Old=[ default-initialized object @Redundant[(including a component)] of a descendant of a private type, private extension, controlled type, task type, or protected type with @nt{entry_@!declaration}s; similarly]} the evaluation of an @nt<extension_@!aggregate> with an ancestor @nt<subtype_@!mark> denoting a subtype of such a type. @begin{Ramification} One can declare these kinds of types, but one cannot create objects of those types. It is also non-preelaborable to create an object if that will cause the evaluation of a default expression that will call a user-defined function. This follows from the rule above forbidding non-null statements. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00161-01]} @ChgDeleted{Version=[2],Text=[Controlled objects are disallowed because most implementations will have to take some run-time action during initialization, even if the Initialize procedure is null.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Phony addition to get conditional leading} A generic body is preelaborable only if elaboration of a corresponding instance body would not perform any such actions, presuming that@Chg{Version=[2],New=[:],Old=[ the actual for each formal private type (or extension) is a private type (or extension), and the actual for each formal subprogram is a user-defined subprogram.]} @Defn{generic contract issue} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal private type (or extension) declared within the formal part of the generic unit is a private type (or extension) that does not have preelaborable initialization;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal type is nonstatic;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal object is nonstatic; and]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal subprogram is a user-defined subprogram.]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[This is an @lquotes@;assume-the-worst@rquotes rule. The elaboration of a generic unit doesn't perform any of the actions listed above, because its sole effect is to establish that the generic can from now on be instantiated. So the elaboration of the generic itself is not the interesting part when it comes to preelaboration rules. The interesting part is what happens when you elaborate @lquotes@;any instantiation@rquotes of the generic. For instance, declaring an object of a limited formal private type might well start tasks, call functions, and do all sorts of non-preelaborable things. We prevent these situations by assuming that the actual parameters are as badly behaved as possible.]} @end{Discussion} @begin{Reason} Without this rule about generics, we would have to forbid instantiations in preelaborated library units, which would significantly reduce their usefulness. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} @PDefn{preelaborated} If a @nt{pragma} Preelaborate (or @nt<pragma> Pure @em see below) applies to a library unit, then it is @i{preelaborated}. @Redundant[ @RootDefn{preelaborated} If a library unit is preelaborated, then its declaration, if any, and body, if any, are elaborated prior to all non-preelaborated @nt{library_item}s of the partition.] @Chg{New=[The declaration and body of a preelaborated library unit, and all subunits that are elaborated as part of elaborating the library unit,], Old=[All compilation units of a preelaborated library unit]} shall be preelaborable. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. In addition, all compilation units of a preelaborated library unit shall depend semantically only on compilation units of other preelaborated library units. @begin{Ramification} In a generic body, we assume the worst about formal private types and extensions. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0035],ARef=[AI95-00002-01]} @ChgAdded{Version=[1],Text=[Subunits of a preelaborated subprogram unit do not need to be preelaborable. This is needed in order to be consistent with units nested in a subprogram body, which do not need to be preelaborable even if the subprogram is preelaborated. However, such subunits cannot depend semantically on non-preelaborated units, which is also consistent with nested units.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@defn{preelaborable initialization}The following rules specify which entities have @i{preelaborable initialization}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The partial view of a private type or private extension, a protected type without @nt<entry_declaration>s, a generic formal private type, or a generic formal derived type, have preelaborable initialization if and only if the @nt<pragma> Preelaborable_Initialization has been applied to them. @Redundant[A protected type with @nt{entry_declaration}s or a task type never has preelaborable initialization.]]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A component (including a discriminant) of a record or protected type has preelaborable initialization if its declaration includes a @nt<default_expression> whose execution does not perform any actions prohibited in preelaborable constructs as described above, or if its declaration does not include a default expression and its type has preelaborable initialization.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A derived type has preelaborable initialization if its parent type has preelaborable initialization and (in the case of a derived record extension) if the non-inherited components all have preelaborable initialization. However, a user-defined controlled type with an overriding Initialize procedure does not have preelaborable initialization.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A view of a type has preelaborable initialization if it is an elementary type, an array type whose component type has preelaborable initialization, a record type whose components all have preelaborable initialization, or an interface type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[A @nt<pragma> Preelaborable_Initialization specifies that a type has preelaborable initialization. This pragma shall appear in the visible part of a package or generic package.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If the pragma appears in the first list of @nt{basic_declarative_item}s of a @nt<package_specification>, then the @nt<direct_name> shall denote the first subtype of a private type, private extension, or protected type that is not an interface type and is without @nt<entry_declaration>s, and the type shall be declared immediately within the same package as the @nt<pragma>. If the @nt<pragma> is applied to a private type or a private extension, the full view of the type shall have preelaborable initialization. If the @nt<pragma> is applied to a protected type, each component of the protected type shall have preelaborable initialization. In addition to the places where Legality Rules normally apply, these rules apply also in the private part of an instance of a generic unit.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[If the @nt<pragma> appears in a @nt<generic_formal_part>, then the @nt<direct_name> shall denote a generic formal private type or a generic formal derived type declared in the same @nt<generic_formal_part> as the @nt<pragma>. In a @nt<generic_instantiation> the corresponding actual type shall have preelaborable initialization.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Not only do protected types with @nt{entry_declaration}s and task types not have preelaborable initialization, but they cannot have pragma Preelaborable_Initialization applied to them.]} @end{Ramification} @end{Legality} @begin{ImplAdvice} In an implementation, a type declared in a preelaborated package should have the same representation in every elaboration of a given version of the package, whether the elaborations occur in distinct executions of the same program, or in executions of distinct programs or partitions that include the given version. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A type declared in a preelaborated package should have the same representation in every elaboration of a given version of the package.]}]} @end{ImplAdvice} @begin{Syntax} @begin{SyntaxText} @leading@keepnext@;The form of a @nt{pragma} Pure is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Pure)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(Pure)} @PDefn2{Term=[pragma, library unit], Sec=(Pure)} A @nt{pragma} Pure is a library unit pragma. @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{pure} A @i{pure} @nt{library_item} is a preelaborable @nt{library_item} whose elaboration does not perform any of the following actions:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the elaboration of a variable declaration;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the evaluation of an @nt{allocator} of an access-to-variable type; for the purposes of this rule, the partial view of a type is presumed to have non-visible components whose default initialization evaluates such an @nt{allocator};]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule is needed because aggregates can specify the default initialization of a private type or extension using <> or the ancestor subtype of an extension aggregate. The subtype of a component could use an @nt{allocator} to initialize an access discriminant. Ada 95 did not allow such private types to have preelaborable initialization, so they could not have occurred. Thus this rule is not incompatible with Ada 95.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the elaboration of the declaration of a named access-to-variable type unless the Storage_Size of the type has been specified by a static expression with value zero or is defined by the language to be zero;]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A remote access-to-class-wide type (see @RefSecNum{Remote Types Library Units}) has its Storage_Size defined to be zero.]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[We disallow most named access-to-object types because an @nt{allocator} has a side effect; the pool constitutes variable data. We allow access-to-subprogram types because they don't have @nt{allocator}s. We even allow named access-to-object types if they have an empty predefined pool (they can't have a user-defined pool as System.Storage_Pools is not pure). In this case, most attempts to use an @nt{allocator} are illegal, and any others (in a generic body) will raise Storage_Error.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the elaboration of the declaration of a named access-to-constant type for which the Storage_Size has been specified by an expression other than a static expression with value zero.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow access-to-constant types so long as there is no user-specified non-zero Storage_Size; if there were a user-specified non-zero Storage_Size restricting the size of the storage pool, allocators would be problematic since the package is supposedly @lquote@;stateless@rquote, and the allocated size count for the storage pool would represent state.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[ The Storage_Size for an anonymous access-to-variable type declared at library level in a library unit that is declared pure is defined to be zero.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This makes @nt{allocator}s illegal for such types (see @RefSecNum{Allocators}), making a storage pool unnecessary for these types. A storage pool would represent state.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that access discriminants and access parameters are never library-level, even when they are declared in a type or subprogram declared at library-level. That's because they have their own special accessibility rules (see @RefSecNum{Operations of Access Types}).]} @end{Ramification} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00366-01]} @ChgDeleted{Version=[2],Text=[@Defn{pure} A @i{pure} @nt{library_item} is a preelaborable @nt{library_item} that does not contain the declaration of any variable or named access within a subprogram, generic subprogram, task unit, or protected unit.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @Defn{declared pure} A @nt{pragma} Pure is used to declare that a library unit is pure. If a @nt{pragma} Pure applies to a library unit, then its compilation units shall be pure, and they shall depend semantically only on compilation units of other library units that are declared pure.@Chg{Version=[2],New=[ Furthermore, the full view of any partial view declared in the visible part of the library unit that has any available stream attributes shall support external streaming (see @RefSecNum{Stream-Oriented Attributes}).],Old=[]} @begin{Honest} A @i{declared-pure} library unit is one to which a @nt{pragma} Pure applies. Its declaration and body are also said to be declared pure. @end{Honest} @begin{Discussion} A declared-pure package is useful for defining types to be shared between partitions with no common address space. @end{Discussion} @begin{Reason} Note that generic packages are not mentioned in the list of things that can contain variable declarations. Note that the Ada 95 rules for deferred constants make them allowable in library units that are declared pure; that isn't true of Ada 83's deferred constants. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} Anonymous access types @Chg{Version=[2],New=[],Old=[(that is, access discriminants and access parameters) ]}are allowed. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @Chg{Version=[2],New=[Ada 95 didn't allow any access types as], Old=[The primary reason for disallowing named access types is that an @nt{allocator} has a side effect; the pool constitutes variable data. We considered somehow allowing @nt{allocator}-less access types. However,]} these (including access-to-subprogram types) @Chg{Version=[2],New=[],Old=[would ]}cause trouble for @RefSec{Distributed Systems}, because such types @Chg{Version=[2],New=[], Old=[would ]} allow access values in a shared passive partition to designate objects in an active partition, thus allowing inter-address space references.@Chg{Version=[2],New=[ We decided to disallow such uses in the relatively rare cases where they cause problems, rather than making life harder for the majority of users. Types declared in a pure package can be used in remote operations only if they are externally streamable. That simply means that there is a means to transport values of the type; that's automatically true for nonlimited types that don't have an access part. The only tricky part about this is to avoid privacy leakage; that was handled by ensuring that any private types (and private extensions) declared in a pure package that have available stream attributes (which include all nonlimited types by definition) have to be externally streamable.], Old=[Furthermore, a named access-to-object type without a pool would be a new concept, adding complexity from the user's point of view. Finally, the prevention of @nt{allocator}s would have to be a run-time check, in order to avoid violations of the generic contract model.]} @end{Reason} @end{Legality} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} If a library unit is declared pure, then the implementation is permitted to omit a call on a library-level subprogram of the library unit if the results are not needed after the call. @Chg{Version=[2],New=[In addition, the implementation],Old=[Similarly, it]} may omit @Chg{Version=[2],New=[], Old=[such ]}a call@Chg{Version=[2],New=[ on such a subprogram],Old=[]} and simply reuse the results produced by an earlier call on the same subprogram, provided that none of the parameters @Chg{Version=[2],New=[nor any object accessible via access values from the parameters ],Old=[]}are of a limited type, and the addresses and values of all by-reference actual parameters, @Chg{Version=[2],New=[],Old=[and ]}the values of all by-copy-in actual parameters, @Chg{Version=[2],New=[and the values of all objects accessible via access values from the parameters, ],Old=[]}are the same as they were at the earlier call. @Redundant[This permission applies even if the subprogram produces other side effects when called.] @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} A declared-pure @nt{library_item} has no variable state. Hence, a call on one of its (nonnested) subprograms cannot @Chg{Version=[2],New=[normally],Old=[@lquotes@;normally@rquotes]} have side effects. The only possible side effects from such a call would be through machine code insertions,@Chg{Version=[2],New=[ imported subprograms,], Old=[]}unchecked conversion to an access type declared within the subprogram, and similar features. The compiler may omit a call to such a subprogram even if such side effects exist, so the writer of such a subprogram has to keep this in mind. @end{Discussion} @end{ImplPerm} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Elaborate, Elaborate_All, or Elaborate_Body is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Elaborate)(@SynI{library_unit_}@Syn2{name}{, @SynI{library_unit_}@Syn2{name}});' @PragmaSyn`@key{pragma} @prag(Elaborate_All)(@SynI{library_unit_}@Syn2{name}{, @SynI{library_unit_}@Syn2{name}});' @PragmaSyn`@key{pragma} @prag(Elaborate_Body)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} A @nt{pragma} Elaborate or Elaborate_All is only allowed within a @nt{context_clause}. @begin{Ramification} @lquotes@;Within a @nt{context_clause}@rquotes@; allows it to be the last item in the @nt{context_clause}. It can't be first, because the @nt{name} has to denote something mentioned earlier. @end{Ramification} @PDefn2{Term=[library unit pragma], Sec=(Elaborate_Body)} @PDefn2{Term=[pragma, library unit], Sec=(Elaborate_Body)} A @nt{pragma} Elaborate_Body is a library unit pragma. @end{SyntaxText} @begin{Discussion} Hence, a @nt{pragma} Elaborate or Elaborate_All is not elaborated, not that it makes any practical difference. Note that a @nt{pragma} Elaborate or Elaborate_All is neither a program unit pragma, nor a library unit pragma. @end{Discussion} @end{Syntax} @begin{Legality} @PDefn2{Term=[requires a completion], Sec=(declaration to which a @nt{pragma} Elaborate_Body applies)} If a @nt{pragma} Elaborate_Body applies to a declaration, then the declaration requires a completion @Redundant[(a body)]. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The @SynI{library_unit_}@nt{name} of a @nt{pragma} Elaborate or Elaborate_All shall denote a nonlimited view of a library unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These @nt{pragma}s are intended to prevent elaboration check failures. But a limited view does not make anything visible that has an elaboration check, so the @nt{pragma}s cannot do anything useful. Moreover, the @nt{pragma}s would probably reintroduce the circularity that the @nt{limited_with_clause} was intended to break. So we make such uses illegal.]} @end{Reason} @end{Legality} @begin{StaticSem} @redundant[A @nt{pragma} Elaborate specifies that the body of the named library unit is elaborated before the current @nt{library_item}. A @nt{pragma} Elaborate_All specifies that each @nt{library_item} that is needed by the named library unit declaration is elaborated before the current @nt{library_item}. A @nt{pragma} Elaborate_Body specifies that the body of the library unit is elaborated immediately after its declaration.] @begin{TheProof} The official statement of the semantics of these @nt{pragma}s is given in @RefSecNum{Program Execution}. @end{TheProof} @begin{ImplNote} The presence of a @nt{pragma} Elaborate_Body simplifies the removal of unnecessary Elaboration_Checks. For a subprogram declared immediately within a library unit to which a @nt{pragma} Elaborate_Body applies, the only calls that can fail the Elaboration_Check are those that occur in the library unit itself, between the declaration and body of the called subprogram; if there are no such calls (which can easily be detected at compile time if there are no @ntf{stub}s), then no Elaboration_Checks are needed for that subprogram. The same is true for Elaboration_Checks on task activations and instantiations, and for library subprograms and generic units. @end{ImplNote} @begin{Ramification} The fact that the unit of elaboration is the @nt{library_item} means that if a @nt{subprogram_body} is not a completion, it is impossible for any @nt{library_item} to be elaborated between the declaration and the body of such a subprogram. Therefore, it is impossible for a call to such a subprogram to fail its Elaboration_Check. @end{Ramification} @begin{Discussion} The visibility rules imply that each @i{library_unit_}@nt{name} of a @nt{pragma} Elaborate or Elaborate_All has to denote a library unit mentioned by a previous @nt{with_clause} of the same @nt{context_clause}. @end{Discussion} @end{StaticSem} @begin{Notes} A preelaborated library unit is allowed to have non-preelaborable children. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} But @Chg{New=[generally ], Old=[]}not non-preelaborated subunits. @Chg{New=[(Non-preelaborated subunits of subprograms are allowed as discussed above.)], Old=[]} @end{Ramification} A library unit that is declared pure is allowed to have impure children. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} But @Chg{New=[generally ], Old=[]}not impure subunits. @Chg{New=[(Impure subunits of subprograms are allowed as discussed above.)], Old=[]} @end{Ramification} @begin{Ramification} Pragma Elaborate is mainly for closely related library units, such as when two package bodies 'with' each other's declarations. In such cases, Elaborate_All sometimes won't work. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concepts of preelaborability and purity are new to Ada 95. The Elaborate_All, Elaborate_Body, Preelaborate, and Pure @nt{pragma}s are new to Ada 95. Pragmas Elaborate are allowed to be mixed in with the other things in the @nt{context_clause} @em in Ada 83, they were required to appear last. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The requirement that a partial view with available stream attributes be externally streamable can cause an incompatibility in rare cases. If there is a limited tagged type declared in a pure package with available attributes, and that type is used to declare a private extension in another pure package, and the full type for the private extension has a component of an explicitly limited record type, a protected type, or a type with access discriminants, then the stream attributes will have to be user-specified in the visible part of the package. That is not a requirement for Ada 95, but this combination seems very unlikely in pure packages. Note that this cannot be an incompatibility for a nonlimited type, as all of the types that are allowed in Ada 95 that would require explicitly defined stream attributes are limited (and thus cannot be used as components in a nonlimited type).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Added wording to cover missing cases for preelaborated generic units. This is incompatible as a preelaborated unit could have used a formal object to initialize a library-level object; that isn't allowed in Ada 2005. But such a unit wouldn't really be preelaborable, and Ada 95 compilers can reject such units (as this is a Binding Interpretation), so such units should be very rare.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] The concept of preelaborable initialization and @nt{pragma} Preelaborable_Initialization are new. These allow more types of objects to be created in preelaborable units, and fix holes in the old rules.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Access-to-subprogram types and access-to-object types with a Storage_Size of 0 are allowed in pure units. The permission to omit calls was adjusted accordingly (which also fixes a hole in Ada 95, as access parameters are allowed, and changes in the values accessed by them must be taken into account).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00002-01]} @ChgAdded{Version=[2],Text=[@B<Corrigendum:> The wording was changed so that subunits of a preelaborated subprogram are also preelaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Disallowed pragma Elaborate and Elaborate_All for packages that are mentioned in a @nt{limited_with_clause}.]} @end{DiffWord95} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/11.mss���������������������������������������������������������������0000755�0001752�0001001�00000262524�12273462240�016401� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(11, Root="ada.mss") @Comment{$Date: 2006/10/19 20:44:13 $} @LabeledSection{Exceptions} @Comment{$Source: e:\\cvsroot/ARM/Source/11.mss,v $} @Comment{$Revision: 1.64 $} @begin{Intro} @redundant[This section defines the facilities for dealing with errors or other exceptional situations that arise during program execution.] @Defn{exception occurrence} @IndexSeeAlso{Term=[condition],See=(exception)} @IndexSee{Term=[signal (an exception)],See=(raise)} @IndexSee{Term=[throw (an exception)],See=(raise)} @IndexSee{Term=[catch (an exception)],See=(handle)} @ToGlossaryAlso{Term=<Exception>, Text=<An @i(exception) represents a kind of exceptional situation; an occurrence of such a situation (at run time) is called an @i(exception occurrence). @redundant[@PDefn2{Term=[raise], Sec=(an exception)} To @i{raise} an exception is to abandon normal program execution so as to draw attention to the fact that the corresponding situation has arisen. @PDefn2{Term=[handle], Sec=(an exception)} Performing some actions in response to the arising of an exception is called @i{handling} the exception. ]>} @begin{Honest} @PDefn2{Term=[handle], Sec=(an exception occurrence)} ...or handling the exception occurrence. @end{Honest} @begin{Ramification} For example, an exception End_Error might represent error situations in which an attempt is made to read beyond end-of-file. During the execution of a partition, there might be numerous occurrences of this exception. @end{Ramification} @begin{Honest} @Defn{occurrence (of an exception)} When the meaning is clear from the context, we sometimes use @lquotes@;@i{occurrence}@rquotes@; as a short-hand for @lquotes@;exception occurrence.@rquotes@; @end{Honest} @redundant[An @nt{exception_declaration} declares a name for an exception. An exception is raised initially either by a @nt{raise_statement} or by the failure of a language-defined check. When an exception arises, control can be transferred to a user-provided @nt{exception_handler} at the end of a @nt{handled_@!sequence_of_@!statements}, or it can be propagated to a dynamically enclosing execution.] @end{Intro} @begin{DiffWord83} We are more explicit about the difference between an exception and an occurrence of an exception. This is necessary because we now have a type (Exception_Occurrence) that represents exception occurrences, so the program can manipulate them. Furthermore, we say that when an exception is propagated, it is the same occurrence that is being propagated (as opposed to a new occurrence of the same exception). The same issue applies to a re-raise statement. In order to understand these semantics, we have to make this distinction. @end{DiffWord83} @LabeledClause{Exception Declarations} @begin{Intro} @Defn{exception} An @nt{exception_declaration} declares a name for an exception. @end{Intro} @begin{Syntax} @Syn{lhs=<exception_declaration>,rhs="@Syn2{defining_identifier_list} : @key{exception};"} @end{Syntax} @begin{StaticSem} Each single @nt{exception_declaration} declares a name for a different exception. If a generic unit includes an @nt{exception_declaration}, the @nt{exception_declaration}s implicitly generated by different instantiations of the generic unit refer to distinct exceptions (but all have the same @nt{defining_identifier}). The particular exception denoted by an exception name is determined at compilation time and is the same regardless of how many times the @nt{exception_declaration} is elaborated. @begin{Reason} We considered removing this requirement inside generic bodies, because it is an implementation burden for implementations that wish to share code among several instances. In the end, it was decided that it would introduce too much implementation dependence. @end{Reason} @begin{Ramification} Hence, if an @nt{exception_declaration} occurs in a recursive subprogram, the exception name denotes the same exception for all invocations of the recursive subprogram. The reason for this rule is that we allow an exception occurrence to propagate out of its declaration's innermost containing master; if exceptions were created by their declarations like other entities, they would presumably be destroyed upon leaving the master; we would have to do something special to prevent them from propagating to places where they no longer exist. @end{Ramification} @begin{Ramification} Exception identities are unique across all partitions of a program. @end{Ramification} @Defn{predefined exception} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} The @i{predefined} exceptions are the ones declared in the declaration of package Standard: Constraint_Error, Program_Error, Storage_Error, and Tasking_Error@Redundant[; one of them is raised when a language-defined check fails.] @begin{Ramification} The exceptions declared in the language-defined package IO_Exceptions, for example, are not predefined. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(exception_declaration)} The elaboration of an @nt{exception_declaration} has no effect. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} The execution of any construct raises Storage_Error if there is insufficient storage for that execution. @PDefn{unspecified} The amount of storage needed for the execution of constructs is unspecified. @begin{Ramification} Note that any execution whatsoever can raise Storage_Error. This allows much implementation freedom in storage management. @end{Ramification} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of user-defined exception declarations:} @begin{Example} Singular : @key[exception]; Error : @key[exception]; Overflow, Underflow : @key[exception]; @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The exception Numeric_Error is now defined in the Obsolescent features Annex, as a rename of Constraint_Error. All checks that raise Numeric_Error in Ada 83 instead raise Constraint_Error in Ada 95. To increase upward compatibility, we also changed the rules to allow the same exception to be named more than once by a given handler. Thus, @lquotes@;@key[when] Constraint_Error | Numeric_Error =>@rquotes@; will remain legal in Ada 95, even though Constraint_Error and Numeric_Error now denote the same exception. However, it will not be legal to have separate handlers for Constraint_Error and Numeric_Error. This change is inconsistent in the rare case that an existing program explicitly raises Numeric_Error at a point where there is a handler for Constraint_Error; the exception will now be caught by that handler. @end{Inconsistent83} @begin{DiffWord83} We explicitly define elaboration for @nt{exception_declaration}s. @end{DiffWord83} @LabeledClause{Exception Handlers} @begin{Intro} @redundant[The response to one or more exceptions is specified by an @nt{exception_handler}.] @end{Intro} @begin{Syntax} @Syn{lhs=<handled_sequence_of_statements>,rhs=" @Syn2{sequence_of_statements} [@key{exception} @Syn2{exception_handler} {@Syn2{exception_handler}}]"} @Syn{lhs=<exception_handler>,rhs=" @key{when} [@Syn2{choice_parameter_specification}:] @Syn2{exception_choice} {| @Syn2{exception_choice}} => @Syn2{sequence_of_statements}"} @Syn{lhs=<choice_parameter_specification>,rhs="@Syn2{defining_identifier}"} @Syn{lhs=<exception_choice>,rhs="@SynI{exception_}@Syn2{name} | @key{others}"} @begin{Honest} @Defn{handler} @lquotes@;@i{Handler}@rquotes@; is an abbreviation for @lquotes@;@nt{exception_handler}.@rquotes@; @Defn2{term=<choice>, Sec=<of an @nt{exception_handler}>} Within this section, we sometimes abbreviate @lquotes@;@nt{exception_choice}@rquotes@; to @lquotes@;@i{choice}.@rquotes@; @end{Honest} @end{Syntax} @begin{Legality} @Defn2{term=<cover>, Sec=<of a choice and an exception>} A choice with an @SynI{exception_}@nt{name} @i{covers} the named exception. A choice with @key{others} covers all exceptions not named by previous choices of the same @nt{handled_@!sequence_of_@!statements}. Two choices in different @nt<exception_handler>s of the same @nt{handled_@!sequence_of_@!statements} shall not cover the same exception. @begin{Ramification} Two @nt<exception_choice>s of the same @nt<exception_handler> may cover the same exception. For example, given two renaming declarations in separate packages for the same exception, one may nevertheless write, for example, @lquotes@;@key[when] Ada.Text_IO.Data_Error | My_Seq_IO.Data_Error =>@rquotes@;. An @key{others} choice even covers exceptions that are not visible at the place of the handler. Since exception raising is a dynamic activity, it is entirely possible for an @key{others} handler to handle an exception that it could not have named. @end{Ramification} A choice with @key{others} is allowed only for the last handler of a @nt{handled_sequence_of_statements} and as the only choice of that handler. An @SynI{exception_}@nt{name} of a choice shall not denote an exception declared in a generic formal package. @begin{Reason} This is because the compiler doesn't know the identity of such an exception, and thus can't enforce the coverage rules. @end{Reason} @end{Legality} @begin{StaticSem} @Defn{choice parameter} A @nt{choice_parameter_specification} declares a @i{choice parameter}, which is a constant object of type Exception_Occurrence (see @RefSecNum{The Package Exceptions}). During the handling of an exception occurrence, the choice parameter, if any, of the handler represents the exception occurrence that is being handled. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(handled_sequence_of_statements)} The execution of a @nt<handled_sequence_of_statements> consists of the execution of the @nt<sequence_of_@!statements>. @Redundant[The optional handlers are used to handle any exceptions that are propagated by the @nt{sequence_of_@!statements}.] @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of an exception handler:} @begin{Example} @key[begin] Open(File, In_File, "input.txt"); --@RI[ see @RefSecNum{File Management}] @key[exception] @key[when] E : Name_Error => Put("Cannot open input file : "); Put_Line(Exception_Message(E)); --@RI[ see @RefSecNum{The Package Exceptions}] @key[raise]; @key[end]; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{exception_handler} is modified to allow a @nt{choice_parameter_specification}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Different @Chg{Version=[2],New=[@nt{exception_choice}s],Old=[@ntf<choice>s]} of the same @nt<exception_handler> may cover the same exception. This allows for @lquotes@;when Numeric_Error | Constraint_Error =>@rquotes@; even though Numeric_Error is a rename of Constraint_Error. This also allows one to @lquotes@;with@rquotes@; two different I/O packages, and then write, for example, @lquotes@;when Ada.Text_IO.Data_Error | My_Seq_IO.Data_Error =>@rquotes@; even though these might both be renames of the same exception. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{handled_sequence_of_statements} is new. These are now used in all the places where handlers are allowed. This obviates the need to explain (in Sections 5, 6, 7, and 9) what portions of the program are handled by the handlers. Note that there are more such cases in Ada 95. The syntax rule for @nt{choice_parameter_specification} is new. @end{DiffWord83} @LabeledClause{Raise Statements} @begin{Intro} @redundant[A @nt{raise_statement} raises an exception.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} @Syn{lhs=<raise_statement>,rhs="@Chg{Version=[2],New=<@key{raise}; | @key{raise} @SynI{exception_}@Syn2{name} [@key{with} @SynI{string_}@Syn2{expression}];>, Old=<@key{raise} [@SynI{exception_}@Syn2{name}];>}"} @end{Syntax} @begin{Legality} The @nt{name}, if any, in a @nt{raise_statement} shall denote an exception. @Defn{re-raise statement} A @nt{raise_statement} with no @SynI{exception_}@nt{name} (that is, a @i{re-raise statement}) shall be within a handler, but not within a body enclosed by that handler. @end{Legality} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The @nt<expression>, if any, in a @nt<raise_statement>, is expected to be of type String.]} @end{Resolution} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} @Defn2{Term=[raise], Sec=(an exception)} To @i(raise an exception) is to raise a new occurrence of that exception@Redundant[, as explained in @RefSecNum{Exception Handling}]. @PDefn2{Term=[execution], Sec=(raise_statement with an exception_name)} For the execution of a @nt{raise_statement} with an @SynI{exception_}@nt{name}, the named exception is raised. @Chg{Version=[2],New=[@redundant{If a @SynI<string_>@nt<expression> is present, the @nt{expression} is evaluated and its value is associated with the exception occurrence.}],Old=[]} @PDefn2{Term=[execution], Sec=(re-raise statement)} For the execution of a re-raise statement, the exception occurrence that caused transfer of control to the innermost enclosing handler is raised @Redundant[again]. @begin{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The definition of Exceptions.Exception_Message includes a statement that the string is returned (see @RefSecNum{The Package Exceptions}). We describe the use of the string here so that we don't have an unexplained parameter in this subclause.]} @end{TheProof} @begin{ImplNote} For a re-raise statement, the implementation does not create a new Exception_Occurrence, but instead propagates the same Exception_Occurrence value. This allows the original cause of the exception to be determined. @end{ImplNote} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of raise statements:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[raise] Ada.IO_Exceptions.Name_Error; --@RI[ see @RefSecNum{Exceptions In Input-Output}]@Chg{Version=[2],New=[ @key[raise] Queue_Error @key[with] "Buffer Full"; --@RI[ see @RefSecNum{Example of Tasking and Synchronization}]],Old=[]} @key[raise]; --@RI[ re-raise the current exception] @end{Example} @end{Examples} @begin{DiffWord83} The fact that the @nt{name} in a @nt{raise_statement} has to denote an exception is not clear from RM83. Clearly that was the intent, since the italicized part of the syntax rules so indicate, but there was no explicit rule. RM83-1.5(11) doesn't seem to give the italicized parts of the syntax any force. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}The syntax of a @nt{raise_statement} is extended to include a string message. This is more convenient than calling Exceptions.Exception_Message (@SynI{exception_}@nt{name}'Identity, @SynI{string_}@nt{expression}), and should encourage the use of message strings when raising exceptions.]} @end{Extend95} @LabeledClause{Exception Handling} @begin{Intro} @redundant[When an exception occurrence is raised, normal program execution is abandoned and control is transferred to an applicable @nt{exception_handler}, if any. @Defn2{Term=[handle], Sec=(an exception occurrence)} To @i(handle) an exception occurrence is to respond to the exceptional event. @Defn{propagate} To @i(propagate) an exception occurrence is to raise it again in another context; that is, to fail to respond to the exceptional event in the present context.] @begin{Ramification} In other words, if the execution of a given construct raises an exception, but does not handle it, the exception is propagated to an enclosing execution (except in the case of a @nt{task_body}). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00023} Propagation involves re-raising the same exception occurrence@Chg{New=[], Old=[(assuming the implementation has not taken advantage of the @ImplPermName of @RefSecNum{Raise Statements})]}. For example, calling an entry of an uncallable task raises Tasking_Error; this is not propagation. @end{Ramification} @end{Intro} @begin{RunTime} @Defn2{Term=[dynamically enclosing], Sec=(of one execution by another)} @Defn2{Term=[execution], Sec=(dynamically enclosing)} Within a given task, if the execution of construct @i{a} is defined by this International Standard to consist (in part) of the execution of construct @i{b}, then while @i{b} is executing, the execution of @i{a} is said to @i(dynamically enclose) the execution of @i{b}. @Defn{innermost dynamically enclosing} The @i(innermost dynamically enclosing) execution of a given execution is the dynamically enclosing execution that started most recently. @begin{Honest} @Defn2{Term=[included], Sec=(one execution by another)} @Defn2{Term=[execution], Sec=(included by another execution)} If the execution of @i{a} dynamically encloses that of @i{b}, then we also say that the execution of @i{b} is @i{included in} the execution of @i{a}. @end{Honest} @begin{Ramification} Examples: The execution of an @nt{if_statement} dynamically encloses the evaluation of the @nt{condition} after the @key{if} (during that evaluation). (Recall that @lquotes@;execution@rquotes@; includes both @lquotes@;elaboration@rquotes@; and @lquotes@;evaluation@rquotes@;, as well as other executions.) The evaluation of a function call dynamically encloses the execution of the @nt{sequence_of_statements} of the function @nt{body} (during that execution). Note that, due to recursion, several simultaneous executions of the same construct can be occurring at once during the execution of a particular task. Dynamically enclosing is not defined across task boundaries; a task's execution does not include the execution of any other tasks. Dynamically enclosing is only defined for executions that are occurring at a given moment in time; if an @nt{if_statement} is currently executing the @nt{sequence_of_statements} after @key{then}, then the evaluation of the @nt{condition} is no longer dynamically enclosed by the execution of the @nt{if_statement} (or anything else). @end{Ramification} @Leading@Defn2{Term=[raise], Sec=(an exception occurrence)} When an exception occurrence is raised by the execution of a given construct, the rest of the execution of that construct is @i{abandoned}; that is, any portions of the execution that have not yet taken place are not performed. The construct is first completed, and then left, as explained in @RefSecNum{Completion and Finalization}. Then: @begin{Itemize} If the construct is a @nt<task_body>, the exception does not propagate further; @begin{Ramification} When an exception is raised by the execution of a @nt{task_body}, there is no dynamically enclosing execution, so the exception does not propagate any further. If the exception occurred during the activation of the task, then the activator raises Tasking_Error, as explained in @RefSec{Task Execution - Task Activation}, but we don't define that as propagation; it's a special rule. Otherwise (the exception occurred during the execution of the @nt{handled_sequence_of_statements} of the task), the task silently disappears. Thus, abnormal termination of tasks is not always considered to be an error. @end{Ramification} If the construct is the @nt{sequence_of_statements} of a @nt{handled_sequence_of_statements} that has a handler with a choice covering the exception, the occurrence is handled by that handler; @Defn2{Term=[propagate], Sec=(an exception occurrence by an execution, to a dynamically enclosing execution)} Otherwise, the occurrence is @i{propagated} to the innermost dynamically enclosing execution, which means that the occurrence is raised again in that context. @begin{Honest} @Defn2{Term=[propagate], Sec=(an exception by an execution)} @Defn2{Term=[propagate], Sec=(an exception by a construct)} As shorthands, we refer to the @i{propagation of an exception}, and the @i{propagation by a construct}, if the execution of the construct propagates an exception occurrence. @end{Honest} @end{Itemize} @Defn2{Term=[handle], Sec=(an exception occurrence)} @PDefn2{Term=[execution], Sec=(handler)} @PDefn2{Term=[elaboration], Sec=(choice_parameter_specification)} When an occurrence is @i(handled) by a given handler, the @nt{choice_parameter_specification}, if any, is first elaborated, which creates the choice parameter and initializes it to the occurrence. Then, the @nt{sequence_of_statements} of the handler is executed; this execution replaces the abandoned portion of the execution of the @nt{sequence_of_statements}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} This @lquotes@;replacement@rquotes@; semantics implies that the handler can do pretty much anything the abandoned sequence could do; for example, in a function, the handler can execute a @Chg{Version=[2],New=[return statement], Old=[@nt{return_statement}]} that applies to the function. @end{Ramification} @begin{Ramification} The rules for exceptions raised in library units, main subprograms and partitions follow from the normal rules, plus the semantics of the environment task described in Section 10 (for example, the environment task of a partition elaborates library units and calls the main subprogram). If an exception is propagated by the main subprogram, it is propagated to the environment task, which then terminates abnormally, causing the partition to terminate abnormally. Although abnormal termination of tasks is not necessarily an error, abnormal termination of a partition due to an exception @i{is} an error. @end{Ramification} @end{RunTime} @begin{Notes} Note that exceptions raised in a @nt{declarative_part} of a body are not handled by the handlers of the @nt{handled_@!sequence_of_@!statements} of that body. @end{Notes} @LabeledSubClause{The Package Exceptions} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01],ARef=[AI95-00400-01],ARef=[AI95-00438-01]} @ChildUnit{Parent=[Ada],Child=[Exceptions]}@Chg{Version=[2],New=[@key[with] Ada.Streams; ],Old=[]}@key[package] Ada.Exceptions @key[is]@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Exceptions);],Old=[]} @key[type] @AdaTypeDefn{Exception_Id} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Exception_Id);],Old=[]} @AdaObjDefn{Null_Id} : @key[constant] Exception_Id; @key[function] @AdaSubDefn{Exception_Name}(Id : Exception_Id) @key[return] String;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Exception_Name}(Id : Exception_Id) @key[return] Wide_String; @key[function] @AdaSubDefn{Wide_Wide_Exception_Name}(Id : Exception_Id) @key[return] Wide_Wide_String;],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[type] @AdaTypeDefn{Exception_Occurrence} @key[is] @key[limited] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Exception_Occurrence);],Old=[]} @key[type] @AdaTypeDefn{Exception_Occurrence_Access} @key[is] @key[access] @key[all] Exception_Occurrence; @AdaObjDefn{Null_Occurrence} : @key[constant] Exception_Occurrence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00329-01]} @key[procedure] @AdaSubDefn{Raise_Exception}(E : @key[in] Exception_Id; Message : @key[in] String := "");@Chg{Version=[2],New=[ @key[pragma] No_Return(Raise_Exception);],Old=[]} @key[function] @AdaSubDefn{Exception_Message}(X : Exception_Occurrence) @key[return] String; @key[procedure] @AdaSubDefn{Reraise_Occurrence}(X : @key[in] Exception_Occurrence); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} @key[function] @AdaSubDefn{Exception_Identity}(X : Exception_Occurrence) @key[return] Exception_Id; @key[function] @AdaSubDefn{Exception_Name}(X : Exception_Occurrence) @key[return] String; --@RI{ Same as Exception_Name(Exception_Identity(X)).}@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Exception_Name}(X : Exception_Occurrence) @key[return] Wide_String; --@RI{ Same as Wide_Exception_Name(Exception_Identity(X)).} @key[function] @AdaSubDefn{Wide_Wide_Exception_Name}(X : Exception_Occurrence) @key[return] Wide_Wide_String; --@RI{ Same as Wide_Wide_Exception_Name(Exception_Identity(X)).}],Old=[]} @key[function] @AdaSubDefn{Exception_Information}(X : Exception_Occurrence) @key[return] String; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00438-01]} @key[procedure] @AdaSubDefn{Save_Occurrence}(Target : @key[out] Exception_Occurrence; Source : @key[in] Exception_Occurrence); @key[function] @AdaSubDefn{Save_Occurrence}(Source : Exception_Occurrence) @key[return] Exception_Occurrence_Access;@Chg{Version=[2],New=[],Old=[ @key[private] ... --@RI{ not specified by the language} @key[end] Ada.Exceptions;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] Read_Exception_Occurrence (Stream : @key[not null access] Ada.Streams.Root_Stream_Type'Class; Item : @key[out] Exception_Occurrence); @key[procedure] Write_Exception_Occurrence (Stream : @key[not null access] Ada.Streams.Root_Stream_Type'Class; Item : @key[in] Exception_Occurrence);]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[ @key[for] Exception_Occurrence'Read @key[use] Read_Exception_Occurrence; @key[for] Exception_Occurrence'Write @key[use] Write_Exception_Occurrence;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[@key[private] ... --@RI{ not specified by the language} @key[end] Ada.Exceptions;]} @end{Example} Each distinct exception is represented by a distinct value of type Exception_Id. Null_Id does not represent any exception, and is the default initial value of type Exception_Id. Each occurrence of an exception is represented by a value of type Exception_Occurrence. Null_Occurrence does not represent any exception occurrence, and is the default initial value of type Exception_Occurrence. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} E that denotes an exception]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<E>, AttrName=<Identity>, Text=[E'Identity returns the unique identity of the exception. The type of this attribute is Exception_Id.]} @begin{Ramification} In a distributed program, the identity is unique across an entire program, not just across a single partition. Exception propagation works properly across RPC's. An exception can be propagated from one partition to another, and then back to the first, where its identity is known. @end{Ramification} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} Raise_Exception raises a new occurrence of the identified exception.@Chg{Version=[2],New=[],Old=[ In this case Exception_Message returns the Message parameter of Raise_Exception. For a @nt{raise_statement} with an @i{exception_}@nt{name}, Exception_Message returns implementation-defined information about the exception occurrence. Reraise_Occurrence reraises the specified exception occurrence.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01],ARef=[AI95-00378-01]} @ChgAdded{Version=[2],Text=[Exception_Message returns the message associated with the given Exception_Occurrence. For an occurrence raised by a call to Raise_Exception, the message is the Message parameter passed to Raise_Exception. For the occurrence raised by a @nt{raise_statement} with an @SynI{exception_}@nt{name} and a @SynI{string_}@nt{expression}, the message is the @Syni{string_}@nt{expression}. For the occurrence raised by a @nt{raise_statement} with an @Syni{exception_}@nt{name} but without a @Syni{string_}@nt{expression}, the message is a string giving implementation-defined information about the exception occurrence. In all cases, Exception_Message returns a string with lower bound 1.]} @ImplDef{The information returned by Exception_Message.} @begin{Ramification} @Leading@Keepnext@;Given an exception E, the @nt{raise_statement}: @begin{Example} @key[raise] E; @end{Example} @Leading@keepnext@;is equivalent to this call to Raise_Exception: @begin{Example} Raise_Exception(E'Identity, Message => @RI{implementation-defined-string}); @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Similarly, the @nt{raise_statement}:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[raise] E @key[with] "some information";]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[is equivalent to this call to Raise_Exception:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Raise_Exception(E'Identity, Message => "some information");]} @end{Example} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[Reraise_Occurrence reraises the specified exception occurrence.]} @begin{Ramification} @Leading@keepnext@;The following handler: @begin{Example} @key[when] @key[others] => Cleanup; @key[raise]; @end{Example} @begin{Wide} @Leading@keepnext@;is equivalent to this one: @end{Wide} @begin{Example} @key[when] X : @key[others] => Cleanup; Reraise_Occurrence(X); @end{Example} @end{Ramification} Exception_Identity returns the identity of the exception of the occurrence. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} The @Chg{Version=[2],New=[Wide_@!Wide_@!Exception_Name],Old=[Exception_Name]} functions return the full expanded name of the exception, in upper case, starting with a root library unit. For an exception declared immediately within package Standard, the @nt{defining_@!identifier} is returned. The result is implementation defined if the exception is declared within an unnamed @nt{block_statement}. @begin{Ramification} See the @ImplPermName below. @end{Ramification} @begin{Honest} This name, as well as each @nt{prefix} of it, does not denote a @nt{renaming_declaration}. @end{Honest} @ChgImplDef{Version=[2],Kind=[Revised],Text=[The result of @Chg{Version=[2], New=[Exceptions.@!Wide_@!Wide_@!Exception_@!Name],Old=[Exceptions.@!Exception_@!Name]} for @Chg{Version=[2],New=[exceptions],Old=[types]} declared within an unnamed @nt{block_statement}.]} @begin{Ramification} Note that we're talking about the name of the exception, not the name of the occurrence. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[The Exception_Name functions (respectively, Wide_Exception_Name) return the same sequence of graphic characters as that defined for Wide_Wide_Exception_Name, if all the graphic characters are defined in Character (respectively, Wide_Character); otherwise, the sequence of characters is implementation defined, but no shorter than that returned by Wide_Wide_Exception_Name for the same value of the argument.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[ The sequence of characters of the value returned by Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name) when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name are not defined in Character (respectively, Wide_Character).],Old=[]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00378-01],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=[The string returned by the Exception_Name, Wide_Exception_Name, and Wide_Wide_Exception_Name functions has lower bound 1.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00378-01]} Exception_Information returns implementation-defined information about the exception occurrence. @Chg{Version=[2],New=[The returned string has lower bound 1.],Old=[]} @ImplDef{The information returned by Exception_Information.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00241-01],ARef=[AI95-00446-01]} @Chg{Version=[2],New=[],Old=[Raise_Exception and ]}Reraise_Occurrence @Chg{Version=[2],New=[has],Old=[have]} no effect in the case of @Chg{Version=[2],New=[],Old=[Null_Id or ]}Null_Occurrence. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Chg{Version=[2],New=[Raise_Exception and Exception_Name raise Constraint_Error for a Null_Id. Exception_Message, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Occurrence. Exception_Identity applied to Null_Occurrence returns Null_Id.], Old=[Exception_Message, Exception_Identity, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Id or Null_Occurrence.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00241-01]} @ChgAdded{Version=[2],Text=[Null_Occurrence can be tested for by comparing Exception_Identity(Occurrence) to Null_Id.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00446-01]} @ChgAdded{Version=[2],Text=[Raise_Exception was changed so that it always raises an exception and thus can be a No_Return procedure. A similar change was not made for Reraise_Occurrence, as doing so was determined to be a significant incompatibility. It is not unusual to pass an Exception_Occurrence to other code to delay raising it. If there was no exception, passing Null_Occurrence works fine (nothing is raised). Moreover, as there is no test for Null_Occurrence in Ada 95, this is the only way to write such code without using additional flags. Breaking this sort of code is unacceptable.]} @end{Discussion} The Save_Occurrence procedure copies the Source to the Target. The Save_Occurrence function uses an @nt{allocator} of type Exception_Occurrence_Access to create a new object, copies the Source to this new object, and returns an access value designating this new object; @Redundant[the result may be deallocated using an instance of Unchecked_Deallocation.] @begin{Ramification} It's OK to pass Null_Occurrence to the Save_Occurrence subprograms; they don't raise an exception, but simply save the Null_Occurrence. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[Write_Exception_Occurrence writes a representation of an exception occurrence to a stream; Read_Exception_Occurrence reconstructs an exception occurrence from a stream (including one written in a different partition).]} @ChgNote{All of these notes (except the first) are moved from below.} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routines are used to define the stream attributes (see @RefSecNum{Stream-Oriented Attributes}) for Exception_Occurrence.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The identity of the exception, as well as the Exception_Name and Exception_Message, have to be preserved across partitions.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The string returned by Exception_Name or Exception_Message on the result of calling the Read attribute on a given stream has to be the same as the value returned by calling the corresponding function on the exception occurrence that was written into the stream with the Write attribute. The string returned by Exception_Information need not be the same, since it is implementation defined anyway.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important for supporting writing exception occurrences to external files for post-mortem analysis, as well as propagating exceptions across remote subprogram calls in a distributed system (see @RefSecNum{Remote Subprogram Calls}).]} @end{Reason} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00438-01]} @ChgDeleted{Version=[2],Text=[The implementation of the Write attribute (see @RefSecNum{Stream-Oriented Attributes}) of Exception_Occurrence shall support writing a representation of an exception occurrence to a stream; the implementation of the Read attribute of Exception_Occurrence shall support reconstructing an exception occurrence from a stream (including one written in a different partition).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The identity of the exception, as well as the Exception_Name and Exception_Message, have to be preserved across partitions.]} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The string returned by Exception_Name or Exception_Message on the result of calling the Read attribute on a given stream has to be the same as the value returned by calling the corresponding function on the exception occurrence that was written into the stream with the Write attribute. The string returned by Exception_Information need not be the same, since it is implementation defined anyway.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[This is important for supporting writing exception occurrences to external files for post-mortem analysis, as well as propagating exceptions across remote subprogram calls in a distributed system (see @RefSecNum{Remote Subprogram Calls}).]} @end{Reason} @end{ImplReq} @begin{ImplPerm} An implementation of Exception_Name in a space-constrained environment may return the @nt{defining_@!identifier} instead of the full expanded name. The string returned by Exception_Message may be truncated (to no less than 200 characters) by the Save_Occurrence procedure @Redundant[(not the function)], the Reraise_Occurrence procedure, and the re-raise statement. @begin{Reason} The reason for allowing truncation is to ease implementations. The reason for choosing the number 200 is that this is the minimum source line length that implementations have to support, and this feature seems vaguely related since it's usually a @lquotes@;one-liner@rquotes@;. Note that an implementation is allowed to do this truncation even if it supports arbitrarily long lines. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} Exception_Message (by default) and Exception_Information should produce information useful for debugging. Exception_Message should be short (about one line), whereas Exception_Information can be long. Exception_Message should not include the Exception_Name. Exception_Information should include both the Exception_Name and the Exception_Message. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Exception_Information should provide information useful for debugging, and should include the Exception_Name and Exception_Message.]}]} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Exception_Message by default should be short, provide information useful for debugging, and should not include the Exception_Name.]}]} @begin{Reason} It may seem strange to define two subprograms whose semantics is implementation defined. The idea is that a program can print out debugging/error-logging information in a portable way. The program is portable in the sense that it will work in any implementation; it might print out different information, but the presumption is that the information printed out is appropriate for debugging/error analysis on that system. @end{Reason} @begin{ImplNote} As an example, Exception_Information might include information identifying the location where the exception occurred, and, for predefined exceptions, the specific kind of language-defined check that failed. There is an implementation trade-off here, between how much information is represented in an Exception_Occurrence, and how much can be passed through a re-raise. The string returned should be in a form suitable for printing to an error log file. This means that it might need to contain line-termination control characters with implementation-defined I/O semantics. The string should neither start nor end with a newline. If an implementation chooses to provide additional functionality related to exceptions and their occurrences, it should do so by providing one or more children of Ada.Exceptions. Note that exceptions behave as if declared at library level; there is no @lquotes@;natural scope@rquotes@; for an exception; an exception always exists. Hence, there is no harm in saving an exception occurrence in a data structure, and reraising it later. The reraise has to occur as part of the same program execution, so saving an exception occurrence in a file, reading it back in from a different program execution, and then reraising it is not required to work. This is similar to I/O of access types. Note that it is possible to use RPC to propagate exceptions across partitions. @Leading@;Here's one way to implement Exception_Occurrence in the private part of the package. Using this method, an implementation need store only the actual number of characters in exception messages. If the user always uses small messages, then exception occurrences can be small. If the user never uses messages, then exception occurrences can be smaller still: @begin{Example} @key[type] Exception_Occurrence(Message_Length : Natural := 200) @key[is] @key[limited] @key[record] Id : Exception_Id; Message : String(1..Message_Length); @key[end] @key[record]; @end{Example} @Leading@;At the point where an exception is raised, an Exception_Occurrence can be allocated on the stack with exactly the right amount of space for the message @em none for an empty message. This is just like declaring a constrained object of the type: @begin{Example} Temp : Exception_Occurrence(10); --@RI{ for a 10-character message} @end{Example} After finding the appropriate handler, the stack can be cut back, and the Temp copied to the right place. This is similar to returning an unknown-sized object from a function. It is not necessary to allocate the maximum possible size for every Exception_Occurrence. If, however, the user declares an Exception_Occurrence object, the discriminant will be permanently set to 200. The Save_Occurrence procedure would then truncate the Exception_Message. Thus, nothing is lost until the user tries to save the occurrence. If the user is willing to pay the cost of heap allocation, the Save_Occurrence function can be used instead. Note that any arbitrary-sized implementation-defined Exception_Information can be handled in a similar way. For example, if the Exception_Occurrence includes a stack traceback, a discriminant can control the number of stack frames stored. The traceback would be truncated or entirely deleted by the Save_Occurrence procedure @em as the implementation sees fit. If the internal representation involves pointers to data structures that might disappear, it would behoove the implementation to implement it as a controlled type, so that assignment can either copy the data structures or else null out the pointers. Alternatively, if the data structures being pointed at are in a task control block, the implementation could keep a unique sequence number for each task, so it could tell when a task's data structures no longer exist. Using the above method, heap space is never allocated unless the user calls the Save_Occurrence function. @Leading@;An alternative implementation would be to store the message strings on the heap when the exception is raised. (It could be the global heap, or it could be a special heap just for this purpose @em it doesn't matter.) This representation would be used only for choice parameters. For normal user-defined exception occurrences, the Save_Occurrence procedure would copy the message string into the occurrence itself, truncating as necessary. Thus, in this implementation, Exception_Occurrence would be implemented as a variant record: @begin{Example} @key[type] Exception_Occurrence_Kind @key[is] (Normal, As_Choice_Param); @key[type] Exception_Occurrence(Kind : Exception_Occurrence_Kind := Normal) @key[is] @key[limited] @key[record] @key[case] Kind @key[is] @key[when] Normal => ... --@RI{ space for 200 characters} @key[when] As_Choice_Param => ... --@RI{ pointer to heap string} @key[end] @key[case]; @key[end] @key[record]; @end{Example} Exception_Occurrences created by the run-time system during exception raising would be As_Choice_Param. User-declared ones would be Normal @em the user cannot see the discriminant, and so cannot set it to As_Choice_Param. The strings in the heap would be freed upon completion of the handler. This alternative implementation corresponds to a heap-based implementation of functions returning unknown-sized results. @Leading@;One possible implementation of Reraise_Occurrence is as follows: @begin{Example} @key[procedure] Reraise_Occurrence(X : @key[in] Exception_Occurrence) @key[is] @key[begin] Raise_Exception(Identity(X), Exception_Message(X)); @key[end] Reraise_Occurrence; @end{Example} However, some implementations may wish to retain more information across a re-raise @em a stack traceback, for example. @end{ImplNote} @begin{Ramification} Note that Exception_Occurrence is a definite subtype. Hence, values of type Exception_Occurrence may be written to an error log for later analysis, or may be passed to subprograms for immediate error analysis. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00400-01]} @ChgDeleted{Version=[2],Text=[If an implementation chooses to have a mode in which it supports non-Latin-1 characters in identifiers, then it needs to define what the above functions return in the case where the name of an exception contains such a character.]} @end{ImplNote} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} The Identity attribute of exceptions is new, as is the package Exceptions. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00241-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @B[Amendment Correction:] Exception_Identity of an Exception_Occurrence now is defined to return Null_Id for Null_Occurrence, rather than raising Constraint_Error. This provides a simple way to test for Null_Occurrence. We expect that programs that need Constraint_Error raised will be very rare; they can be easily fixed by explicitly testing for Null_Id or by using Exception_Name instead.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00378-01],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=<@B[Amendment Correction:] We now define the lower bound of the string returned from [[Wide_]Wide_]Exception_Name, Exception_Message, and Exception_Information. This makes working with the returned string easier, and is consistent with many other string-returning functions in Ada. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from one of these functions, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.>} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00446-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Raise_Exception now raises Constraint_Error if passed Null_Id. This means that it always raises an exception, and thus we can apply pragma No_Return to it. We expect that programs that call Raise_Exception with Null_Id will be rare, and programs that do that and expect no exception to be raised will be rarer; such programs can be easily fixed by explicitly testing for Null_Id before calling Raise_Exception.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00400-01],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Functions Wide_Exception_Name and Wide_Wide_Exception_Name, and procedures Read_Exception_Occurrence and Write_Exception_Occurrence are newly added to Exceptions. If Exceptions is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Exceptions is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Exceptions is preelaborated, and types Exception_Id and Exception_Occurrence have preelaborable initialization, allowing this package to be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The meaning of Exception_Message is reworded to reflect that the string can come from a @nt{raise_statement} as well as a call of Raise_Exception.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[Added Wide_Exception_Name and Wide_Wide_Exception_Name because identifiers can now contain characters outside of Latin-1.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Pragmas Assert and Assertion_Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Pragma Assert is used to assert the truth of a Boolean expression at any point within a sequence of declarations or statements. Pragma Assertion_Policy is used to control whether such assertions@Defn{Assertions} are to be ignored by the implementation, checked at run-time, or handled in some implementation-defined manner.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Assert is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Assert>([Check =>] @SynI{boolean_}@Syn2{expression}[, [Message =>] @SynI{string_}@Syn2{expression}]);''} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A @nt{pragma} Assert is allowed at the place where a @nt{declarative_item} or a @nt{statement} is allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Assertion_Policy is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=<@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Assertion_Policy>(@SynI{policy_}@Syn2{identifier});'>} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Assertion_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Assertion_Policy)} A @nt{pragma} Assertion_Policy is a configuration pragma.]} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The expected type for the @Syni{boolean_}@nt{expression} of a @nt{pragma} Assert is any boolean type. The expected type for the @Syni{string_}@nt{expression} of a @nt{pragma} Assert is type String.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow any boolean type to be like @nt{if_statement}s and other conditionals; we only allow String for the message in order to match @nt{raise_statement}s.]} @end{Reason} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The @SynI<policy_>@nt<identifier> of a @nt{pragma} Assertion_Policy shall be either Check, Ignore, or an implementation-defined identifier.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[Implementation-defined @SynI<policy_>@nt<identifier>s allowed in a @nt{pragma} Assertion_Policy.],Old=[]}]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[A @nt<pragma> Assertion_Policy is a configuration pragma that specifies the assertion policy in effect for the compilation units to which it applies. Different policies may apply to different compilation units within the same partition. The default assertion policy is implementation-defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The default assertion policy.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Assertions]}@key[package] Ada.Assertions @key[is] @key[pragma] Pure(Assertions);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Assertion_Error : @key<exception>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> Assert(Check : @key<in> Boolean); @key<procedure> Assert(Check : @key<in> Boolean; Message : @key<in> String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Assertions;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[A compilation unit containing a @nt{pragma} Assert has a semantic dependence on the Assertions library unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The assertion policy that applies to a generic unit also applies to all its instances.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[An assertion policy @defn{assertion policy}specifies how a @nt{pragma} Assert is interpreted by the implementation. If the assertion policy is Ignore at the point of a @nt{pragma} Assert, the pragma is ignored. If the assertion policy is Check at the point of a @nt{pragma} Assert, the elaboration of the pragma consists of evaluating the boolean expression, and if the result is False, evaluating the Message argument, if any, and raising the exception Assertions.Assertion_Error, with a message if the Message argument is provided.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Calling the procedure Assertions.Assert without a Message parameter is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<if> Check = False @key<then> @key<raise> Ada.Assertions.Assertion_Error; @key{end} @key{if};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Calling the procedure Assertions.Assert with a Message parameter is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<if> Check = False @key<then> @key<raise> Ada.Assertions.Assertion_Error @key<with> Message; @key{end} @key{if};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The procedures Assertions.Assert have these effects independently of the assertion policy in effect.]} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Assertion_Error may be declared by renaming an implementation-defined exception from another package.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This permission is intended to allow implementations which had an implementation-defined Assert pragma to continue to use their originally defined exception. Without this permission, such an implementation would be incorrect, as Exception_Name would return the wrong name.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Implementations may define their own assertion policies.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Normally, the boolean expression in a @nt{pragma} Assert should not call functions that have significant side-effects when the result of the expression is True, so that the particular assertion policy in effect will not affect normal operation of the program.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Pragmas Assert and Assertion_Policy, and package Assertions are new.]} @end{Extend95} @LabeledSubClause{Example of Exception Handling} @begin{Examples} @Leading@;Exception handling may be used to separate the detection of an error from the response to that error: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @Chg{Version=[2],New=[],Old=[@key[with] Ada.Exceptions; @key[use] Ada; ]}@key[package] File_System @key[is] @key[type] File_Handle @key[is] @key[limited] @key[private]; File_Not_Found : @key[exception]; @key[procedure] Open(F : @key[in] @key[out] File_Handle; Name : String); --@RI{ raises File_Not_Found if named file does not exist} End_Of_File : @key[exception]; @key[procedure] Read(F : @key[in] @key[out] File_Handle; Data : @key[out] Data_Type); --@RI{ raises End_Of_File if the file is not open} ... @key[end] File_System; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[package] @key[body] File_System @key[is] @key[procedure] Open(F : @key[in] @key[out] File_Handle; Name : String) @key[is] @key[begin] @key[if] File_Exists(Name) @key[then] ... @key[else] @Chg{Version=[2],New=[@key[raise] ],Old=[Exceptions.Raise_Exception(]}File_Not_Found@Chg{Version=[2],New=[ @key[with] ],Old=['Identity, ]}"File not found: " & Name & "."@Chg{Version=[2],New=[],Old=[)]}; @key[end] @key[if]; @key[end] Open; @key[procedure] Read(F : @key[in] @key[out] File_Handle; Data : @key[out] Data_Type) @key[is] @key[begin] @key[if] F.Current_Position <= F.Last_Position @key[then] ... @key[else] @key[raise] End_Of_File; @key[end] @key[if]; @key[end] Read; ... @key[end] File_System; @key[with] Ada.Text_IO; @key[with] Ada.Exceptions; @key[with] File_System; @key[use] File_System; @key[use] Ada; @key[procedure] Main @key[is] @key[begin] ... --@RI{ call operations in File_System} @key[exception] @key[when] End_Of_File => Close(Some_File); @key[when] Not_Found_Error : File_Not_Found => Text_IO.Put_Line(Exceptions.Exception_Message(Not_Found_Error)); @key[when] The_Error : @key[others] => Text_IO.Put_Line("Unknown error:"); @key[if] Verbosity_Desired @key[then] Text_IO.Put_Line(Exceptions.Exception_Information(The_Error)); @key[else] Text_IO.Put_Line(Exceptions.Exception_Name(The_Error)); Text_IO.Put_Line(Exceptions.Exception_Message(The_Error)); @key[end] @key[if]; @key[raise]; @key[end] Main; @end{Example} In the above example, the File_System package contains information about detecting certain exceptional situations, but it does not specify how to handle those situations. Procedure Main specifies how to handle them; other clients of File_System might have different handlers, even though the exceptional situations arise from the same basic causes. @end{Examples} @begin{DiffWord83} The sections labeled @lquotes@;Exceptions Raised During ...@rquotes@; are subsumed by this clause, and by parts of Section 9. @end{DiffWord83} @LabeledClause{Suppressing Checks} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @Chg{Version=[2],New=[@i{Checking pragmas}@Defn{Checking pragmas} give instructions to an implementation on handling language-defined checks.],Old=[]} A @nt{pragma} Suppress gives permission to an implementation to omit certain language-defined checks@Chg{Version=[2], New=[, while a @nt<pragma> Unsuppress revokes the permission to omit checks.],Old=[]}. @Defn{language-defined check} @Defn2{Term=[check], Sec=(language-defined)} @IndexSee{Term=[run-time check],See=(language-defined check)} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} A @i{language-defined check} (or simply, a @lquotes@;check@rquotes@;) is one of the situations defined by this International Standard that requires a check to be made at run time to determine whether some condition is true. @Defn2{Term=[failure],Sec=(of a language-defined check)} A check @i{fails} when the condition being checked is false, causing an exception to be raised. @begin{Discussion} All such checks are defined under @lquotes@;@RunTimeTitle@rquotes@; in clauses and subclauses throughout the standard. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @Leading@Keepnext@;The form@Chg{Version=[2],New=[s of checking pragmas are],Old=[ of a @nt{pragma} Suppress is]} as follows: @end{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @PragmaSyn`@key{pragma} @prag(Suppress)(@Syn2{identifier}@Chg{Version=[2],New=<>,Old=( [, [On =>] @Syn2{name}])});' @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=<@AddedPragmaSyn`Version=[2],@key{pragma} @prag(Unsuppress)(@Syn2{identifier});'>} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @PDefn2{Term=[configuration pragma], Sec=(Suppress)} @PDefn2{Term=[pragma, configuration], Sec=(Suppress)} @Chg{Version=[2],New=[@PDefn2{Term=[configuration pragma], Sec=(Unsuppress)} @PDefn2{Term=[pragma, configuration], Sec=(Unsuppress)}],Old=[]} A @Chg{Version=[2],New=<checking pragma>,Old=<@nt{pragma} Suppress>} is allowed only immediately within a @nt{declarative_part}, immediately within a @nt{package_@!specification}, or as a configuration pragma. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} The @nt{identifier} shall be the name of a check. @Chg{Version=[2],New=<>,Old=<The @nt{name} (if present) shall statically denote some entity.>} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00224-01]} @ChgDeleted{Version=[2],Text=<For a @nt{pragma} Suppress that is immediately within a @nt{package_specification} and includes a @nt<name>, the @nt<name> shall denote an entity (or several overloaded subprograms) declared immediately within the @nt{package_specification}.>} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A checking pragma applies to the named check in a specific region, and applies to all entities in that region. A checking pragma given in a @nt<declarative_part> or immediately within a @nt<package_specification> applies from the place of the @nt<pragma> to the end of the innermost enclosing declarative region. The region for a checking pragma given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[If a checking pragma applies to a generic instantiation, then the checking pragma also applies to the instance. If a checking pragma applies to a call to a subprogram that has a @nt<pragma> Inline applied to it, then the checking pragma also applies to the inlined subprogram body.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} A @nt{pragma} Suppress gives permission to an implementation to omit the named check @Chg{Version=[2],New=[(or every check in the case of All_Checks) for any entities to which it applies.],Old=[from the place of the @nt{pragma} to the end of the innermost enclosing declarative region, or, if the @nt{pragma} is given in a @nt{package_@!specification} and includes a @nt<name>, to the end of the scope of the named entity. If the @nt{pragma} includes a @nt{name}, the permission applies only to checks performed on the named entity, or, for a subtype, on objects and values of its type. Otherwise, the permission applies to all entities.]} @Defn{suppressed check} If permission has been given to suppress a given check, the check is said to be @i{suppressed}. @begin{Ramification} A check is suppressed even if the implementation chooses not to actually generate better code. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This allows the implementation to raise Program_Error, for example, if the erroneousness is detected. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A @nt{pragma} Unsuppress revokes the permission to omit the named check (or every check in the case of All_Checks) given by any @nt{pragma} Suppress that applies at the point of the @nt{pragma} Unsuppress. The permission is revoked for the region to which the @nt{pragma} Unsuppress applies. If there is no such permission at the point of a @nt{pragma} Unsuppress, then the @nt{pragma} has no effect. A later @nt{pragma} Suppress can renew the permission.]} @Leading@Keepnext@;The following are the language-defined checks: @begin{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Leading@Redundant[The following checks correspond to situations in which the exception Constraint_Error is raised upon failure.] @begin{Description} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0036],ARef=[AI95-00176-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @RootDefn{Access_Check} Access_Check @\@Redundant[When evaluating a dereference (explicit or implicit), check that the value of the @nt{name} is not @key{null}. @Chg{Version=[2],New=[When converting to a subtype that excludes null, check that the converted value is not @key{null}.], Old=[When passing an actual parameter to a formal access parameter, check that the value of the actual parameter is not @key{null}. @Chg{Version=[1],New=[When evaluating a @nt{discriminant_association} for an access discriminant, check that the value of the discriminant is not @key{null}.], Old=[]}]}] @RootDefn{Discriminant_Check} Discriminant_Check @\@Redundant[Check that the discriminants of a composite value have the values imposed by a discriminant constraint. Also, when accessing a record component, check that it exists for the current discriminant values.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @RootDefn{Division_Check} Division_Check @\@Redundant[Check that the second operand is not zero for the operations /, @Chg{Version=[2],New=[@key[rem]],Old=[rem]} and @Chg{Version=[2],New=[@key[mod]],Old=[mod]}.] @RootDefn{Index_Check} Index_Check @\@Redundant[Check that the bounds of an array value are equal to the corresponding bounds of an index constraint. Also, when accessing a component of an array object, check for each dimension that the given index value belongs to the range defined by the bounds of the array object. Also, when accessing a slice of an array object, check that the given discrete range is compatible with the range defined by the bounds of the array object.] @RootDefn{Length_Check} Length_Check @\@Redundant[Check that two arrays have matching components, in the case of array subtype conversions, and logical operators for arrays of boolean components.] @RootDefn{Overflow_Check} Overflow_Check @\@Redundant[Check that a scalar value is within the base range of its type, in cases where the implementation chooses to raise an exception instead of returning the correct mathematical result.] @RootDefn{Range_Check} Range_Check @\@Redundant[Check that a scalar value satisfies a range constraint. Also, for the elaboration of a @nt<subtype_indication>, check that the @nt<constraint> (if present) is compatible with the subtype denoted by the @nt{subtype_mark}. Also, for an @nt<aggregate>, check that an index or discriminant value belongs to the corresponding subtype. Also, check that when the result of an operation yields an array, the value of each component belongs to the component subtype.] @RootDefn{Tag_Check} Tag_Check @\@Redundant[Check that operand tags in a dispatching call are all equal. Check for the correct tag on tagged type conversions, for an @nt{assignment_statement}, and when returning a tagged limited object from a function.] @end{Description} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Leading@Redundant[The following checks correspond to situations in which the exception Program_Error is raised upon failure.] @begin{Description} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280]} @ChgAdded{Version=[2],Text=[@RootDefn{Accessibility_Check} Accessibility_Check @\@Redundant[Check the accessibility level of an entity or view.]]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280]} @ChgAdded{Version=[2],Text=[@RootDefn{Allocation_Check} Allocation_Check @\@Redundant[For an @nt<allocator>, check that the master of any tasks to be created by the @nt{allocator} is not yet completed or some dependents have not yet terminated, and that the finalization of the collection has not started.]]} @RootDefn{Elaboration_Check} Elaboration_Check @\@Redundant[When a subprogram or protected entry is called, a task activation is accomplished, or a generic instantiation is elaborated, check that the body of the corresponding unit has already been elaborated.] @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00280]} @ChgNote{This item is not in alphabetical order} @ChgDeleted{Version=[2],Text=[@RootDefn{Accessibility_Check} Accessibility_Check @\@Redundant[Check the accessibility level of an entity or view.]]} @end{Description} @Leading@Redundant[The following check corresponds to situations in which the exception Storage_Error is raised upon failure.] @begin{Description} @RootDefn{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} Storage_Check @\@Redundant[Check that evaluation of an @nt{allocator} does not require more space than is available for a storage pool. Check that the space available for a task or subprogram has not been exceeded.] @begin{Reason} We considered splitting this out into three categories: Pool_Check (for @nt{allocator}s), Stack_Check (for stack usage), and Heap_Check (for implicit use of the heap @em use of the heap other than through an @nt{allocator}). Storage_Check would then represent the union of these three. However, there seems to be no compelling reason to do this, given that it is not feasible to split Storage_Error. @end{Reason} @end{Description} @Leading@Redundant[The following check corresponds to all situations in which any predefined exception is raised.] @begin{Description} @RootDefn{All_Checks} All_Checks @\Represents the union of all checks; @Redundant[suppressing All_Checks suppresses all checks.] @begin{Ramification} All_Checks includes both language-defined and implementation-defined checks. @end{Ramification} @end{Description} @end{Itemize} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a given check has been suppressed, and the corresponding error situation occurs, the execution of the program is erroneous. @end{Erron} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} An implementation is allowed to place restrictions on @Chg{Version=[2],New=[checking pragmas, subject only to the requirement that @nt{pragma} Unsuppress shall allow any check names supported by @nt{pragma} Suppress],Old=[Suppress @nt<pragma>s]}. An implementation is allowed to add additional check names, with implementation-defined semantics. @PDefn{unspecified} When Overflow_Check has been suppressed, an implementation may also suppress an unspecified subset of the Range_Checks. @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00224-01]} @ChgDeleted{Version=[2],Text=[The permission to restrict is given so the implementation can give an error message when the requested suppression is nonsense, such as suppressing a Range_Check on a task type. It would be verbose and pointless to list all the cases of nonsensical language-defined checks in the standard, and since the list of checks is open-ended, we can't list the restrictions for implementation-defined checks anyway.]} @end{Reason} @ImplDef{Implementation-defined check names.} @begin{Discussion} For Overflow_Check, the intention is that the implementation will suppress any Range_Checks that are implemented in the same manner as Overflow_Checks (unless they are free). @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation may support an additional parameter on @nt{pragma} Unsuppress similar to the one allowed for @nt{pragma} Suppress (see @RefSecNum{Specific Suppression of Checks}). The meaning of such a parameter is implementation-defined.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[Existence and meaning of second parameter of @nt{pragma} Unsuppress.],Old=[]}]} @end{ImplPerm} @begin{ImplAdvice} The implementation should minimize the code executed for checks that have been suppressed. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Code executed for checks that have been suppressed should be minimized.]}]} @begin{ImplNote} However, if a given check comes for free (for example, the hardware automatically performs the check in parallel with doing useful work) or nearly free (for example, the check is a tiny portion of an expensive run-time system call), the implementation should not bother to suppress the check. Similarly, if the implementation detects the failure at compile time and provides a warning message, there is no need to actually suppress the check. @end{ImplNote} @end{ImplAdvice} @begin{Notes} @Defn{optimization} @Defn{efficiency} There is no guarantee that a suppressed check is actually removed; hence a @nt{pragma} Suppress should be used only for efficiency reasons. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[It is possible to give both a @nt{pragma} Suppress and Unsuppress for the same check immediately within the same @nt{declarative_part}. In that case, the last @nt{pragma} given determines whether or not the check is suppressed. Similarly, it is possible to resuppress a check which has been unsuppressed by giving a @nt{pragma} Suppress in an inner declarative region.]} @end{Notes} @begin{Examples} @Leading@Keepnext@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @i{Examples of suppressing @Chg{Version=[2],New=[and unsuppressing ],Old=[]}checks:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @key[pragma] Suppress(@Chg{Version=[2],New=[Index_Check); @key[pragma] Unsuppress(Overflow_Check);],Old=[Range_Check); @key[pragma] Suppress(Index_Check, On => Table);]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} A @nt{pragma} Suppress is allowed as a configuration pragma. A @nt{pragma} Suppress without a @nt<name> is allowed in a @nt{package_specification}. Additional check names are added. We allow implementations to define their own checks. @end{Extend83} @begin{DiffWord83} We define the checks in a distributed manner. Therefore, the long list of what checks apply to what is merely a NOTE. We have removed the detailed rules about what is allowed in a @nt{pragma} Suppress, and allow implementations to invent their own. The RM83 rules weren't quite right, and such a change is necessary anyway in the presence of implementation-defined checks. We make it clear that the difference between a Range_Check and an Overflow_Check is fuzzy. This was true in Ada 83, given RM83-11.6, but it was not clear. We considered removing Overflow_Check from the language or making it obsolescent, just as we did for Numeric_Error. However, we kept it for upward compatibility, and because it may be useful on machines where range checking costs more than overflow checking, but overflow checking still costs something. Different compilers will suppress different checks when asked to suppress Overflow_Check @em the non-uniformity in this case is not harmful, and removing it would have a serious impact on optimizers. Under Access_Check, dereferences cover the cases of @nt{selected_component}, @nt{indexed_component}, @nt{slice}, and attribute that are listed in RM83, as well as the new @nt{explicit_dereference}, which was included in @nt{selected_component} in RM83. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Pragma Unsuppress is new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Allocation_Check was added to support suppressing the new check on @nt{allocator}s (see @RefSecNum{Allocators}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0036],ARef=[AI95-00176-01],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The description of Access_Check was corrected by the Corrigendum to include the discriminant case. This change was then replaced by the more general notion of checking conversions to subtypes that exclude null in Ada 2005.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The On parameter of pragma Suppress was moved to Annex J. This feature's effect is inherently non-portable, depending on the implementation's model of computation. Compiler surveys demonstrated this, showing that implementations vary widely in the interpretation of these parameters, even on the same target. While this is relatively harmless for Suppress (which is never required to do anything), it would be a significant problem for Unsuppress (we want the checks to be made for all implementations). By moving it, we avoid needing to define the meaning of Unsuppress with an On parameter.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[The order of the Program_Error checks was corrected to be alphabetical.]} @end{DiffWord95} @LabeledClause{Exceptions and Optimization} @begin{Intro} @redundant[@Defn{language-defined check} @Defn2{Term=[check], Sec=(language-defined)} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} @Defn{optimization} @Defn{efficiency} This clause gives permission to the implementation to perform certain @lquotes@;optimizations@rquotes@; that do not necessarily preserve the canonical semantics.] @end{Intro} @begin{RunTime} @Defn{canonical semantics} The rest of this International Standard (outside this clause) defines the @i{canonical semantics} of the language. @Redundant[The canonical semantics of a given (legal) program determines a set of possible external effects that can result from the execution of the program with given inputs.] @begin{Ramification} Note that the canonical semantics is a set of possible behaviors, since some reordering, parallelism, and non-determinism is allowed by the canonical semantics. @end{Ramification} @begin{Discussion} @Leading@;The following parts of the canonical semantics are of particular interest to the reader of this clause: @begin{Itemize} Behavior in the presence of abnormal objects and objects with invalid representations (see @RefSecNum{Data Validity}). Various actions that are defined to occur in an arbitrary order. Behavior in the presence of a misuse of Unchecked_Deallocation, Unchecked_Access, or imported or exported entity (see Section 13). @end{Itemize} @end{Discussion} @Redundant[As explained in @RefSec{Conformity of an Implementation with the Standard}, the external effect of a program is defined in terms of its interactions with its external environment. Hence, the implementation can perform any internal actions whatsoever, in any order or in parallel, so long as the external effect of the execution of the program is one that is allowed by the canonical semantics, or by the rules of this clause.] @begin{Ramification} Note that an optimization can change the external effect of the program, so long as the changed external effect is an external effect that is allowed by the semantics. Note that the canonical semantics of an erroneous execution allows any external effect whatsoever. Hence, if the implementation can prove that program execution will be erroneous in certain circumstances, there need not be any constraints on the machine code executed in those circumstances. @end{Ramification} @end{RunTime} @begin{ImplPerm} @Leading@;The following additional permissions are granted to the implementation: @begin{Itemize} @Defn{extra permission to avoid raising exceptions} @Defn{undefined result} An implementation need not always raise an exception when a language-defined check fails. Instead, the operation that failed the check can simply yield an @i{undefined result}. The exception need be raised by the implementation only if, in the absence of raising it, the value of this undefined result would have some effect on the external interactions of the program. In determining this, the implementation shall not presume that an undefined result has a value that belongs to its subtype, nor even to the base range of its type, if scalar. @Redundant[Having removed the raise of the exception, the canonical semantics will in general allow the implementation to omit the code for the check, and some or all of the operation itself.] @begin{Ramification} Even without this permission, an implementation can always remove a check if it cannot possibly fail. @end{Ramification} @begin{Reason} We express the permission in terms of removing the raise, rather than the operation or the check, as it minimizes the disturbance to the canonical semantics (thereby simplifying reasoning). By allowing the implementation to omit the raise, it thereby does not need to "look" at what happens in the exception handler to decide whether the optimization is allowed. @end{Reason} @begin{Discussion} The implementation can also omit checks if they cannot possibly fail, or if they could only fail in erroneous executions. This follows from the canonical semantics. @end{Discussion} @begin{ImplNote} @Leading@;This permission is intended to allow normal "dead code removal" optimizations, even if some of the removed code might have failed some language-defined check. However, one may not eliminate the raise of an exception if subsequent code presumes in some way that the check succeeded. For example: @begin{Example} @key[if] X * Y > Integer'Last @key[then] Put_Line("X * Y overflowed"); @key[end] @key[if]; @key[exception] @key[when] @key[others] => Put_Line("X * Y overflowed"); @end{Example} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}If X*Y does overflow, you may not remove the raise of the exception if the code that does the comparison against Integer'Last presumes that it is comparing it with an in-range Integer value, and hence always yields False. @Leading@;As another example where a raise may not be eliminated: @begin{Example} @key[subtype] Str10 @key[is] String(1..10); @key[type] P10 @key[is] @key[access] Str10; X : P10 := @key[null]; @key[begin] @key[if] X.all'Last = 10 @key[then] Put_Line("Oops"); @key[end] @key[if]; @end{Example} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} In the above code, it would be wrong to eliminate the raise of Constraint_Error on the "X.all" (since X is null), if the code to evaluate 'Last always yields 10 by presuming that X.all belongs to the subtype Str10, without even "looking." @end{ImplNote} @Defn{extra permission to reorder actions} If an exception is raised due to the failure of a language-defined check, then upon reaching the corresponding @nt<exception_handler> (or the termination of the task, if none), the external interactions that have occurred need reflect only that the exception was raised somewhere within the execution of the @nt<sequence_of_statements> with the handler (or the @nt<task_body>), possibly earlier (or later if the interactions are independent of the result of the checked operation) than that defined by the canonical semantics, but not within the execution of some abort-deferred operation or @i(independent) subprogram that does not dynamically enclose the execution of the construct whose check failed. @Defn{independent subprogram} An independent subprogram is one that is defined outside the library unit containing the construct whose check failed, and has no Inline @nt<pragma> applied to it. @Defn{normal state of an object} @PDefn{abnormal state of an object} @PDefn{disruption of an assignment} Any assignment that occurred outside of such abort-deferred operations or independent subprograms can be disrupted by the raising of the exception, causing the object or its parts to become abnormal, and certain subsequent uses of the object to be erroneous, as explained in @RefSecNum{Data Validity}. @begin{Reason} We allow such variables to become abnormal so that assignments (other than to atomic variables) can be disrupted due to @lquotes@;imprecise@rquotes@; exceptions or instruction scheduling, and so that assignments can be reordered so long as the correct results are produced in the end if no language-defined checks fail. @end{Reason} @begin{Ramification} If a check fails, no result dependent on the check may be incorporated in an external interaction. In other words, there is no permission to output meaningless results due to postponing a check. @end{Ramification} @end{Itemize} @begin{Discussion} We believe it is important to state the extra permission to reorder actions in terms of what the programmer can expect at run time, rather than in terms of what the implementation can assume, or what transformations the implementation can perform. Otherwise, how can the programmer write reliable programs? This clause has two conflicting goals: to allow as much optimization as possible, and to make program execution as predictable as possible (to ease the writing of reliable programs). The rules given above represent a compromise. Consider the two extremes: The extreme conservative rule would be to delete this clause entirely. The semantics of Ada would be the canonical semantics. This achieves the best predictability. It sounds like a disaster from the efficiency point of view, but in practice, implementations would provide modes in which less predictability but more efficiency would be achieved. Such a mode could even be the out-of-the-box mode. In practice, implementers would provide a compromise based on their customer's needs. Therefore, we view this as one viable alternative. The extreme liberal rule would be @lquotes@;the language does not specify the execution of a program once a language-defined check has failed; such execution can be unpredictable.@rquotes@; This achieves the best efficiency. It sounds like a disaster from the predictability point of view, but in practice it might not be so bad. A user would have to assume that exception handlers for exceptions raised by language-defined checks are not portable. They would have to isolate such code (like all nonportable code), and would have to find out, for each implementation of interest, what behaviors can be expected. In practice, implementations would tend to avoid going so far as to punish their customers too much in terms of predictability. The most important thing about this clause is that users understand what they can expect at run time, and implementers understand what optimizations are allowed. Any solution that makes this clause contain rules that can interpreted in more than one way is unacceptable. We have chosen a compromise between the extreme conservative and extreme liberal rules. The current rule essentially allows arbitrary optimizations within a library unit and inlined subprograms reachable from it, but disallow semantics-disrupting optimizations across library units in the absence of inlined subprograms. This allows a library unit to be debugged, and then reused with some confidence that the abstraction it manages cannot be broken by bugs outside the library unit. @end{Discussion} @end{ImplPerm} @begin{Notes} The permissions granted by this clause can have an effect on the semantics of a program only if the program fails a language-defined check. @end{Notes} @begin{DiffWord83} @Leading@;RM83-11.6 was unclear. It has been completely rewritten here; we hope this version is clearer. Here's what happened to each paragraph of RM83-11.6: @begin{Itemize} Paragraphs 1 and 2 contain no semantics; they are merely pointing out that anything goes if the canonical semantics is preserved. We have similar introductory paragraphs, but we have tried to clarify that these are not granting any @lquotes@;extra@rquotes@; permission beyond what the rest of the document allows. Paragraphs 3 and 4 are reflected in the @lquotes@;extra permission to reorder actions@rquotes@;. Note that this permission now allows the reordering of assignments in many cases. Paragraph 5 is moved to @RefSec{Operators and Expression Evaluation}, where operator association is discussed. Hence, this is no longer an @lquotes@;extra permission@rquotes@; but is part of the canonical semantics. Paragraph 6 now follows from the general permission to store out-of-range values for unconstrained subtypes. Note that the parameters and results of all the predefined operators of a type are of the unconstrained subtype of the type. Paragraph 7 is reflected in the @lquotes@;extra permission to avoid raising exceptions@rquotes@;. @end{Itemize} We moved clause @RefSec{Suppressing Checks} from after 11.6 to before 11.6, in order to preserve the famous number @lquotes@;11.6@rquotes@; (given the changes to earlier clauses in Section 11). @end{DiffWord83} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/12.mss���������������������������������������������������������������0000755�0001752�0001001�00000427321�12273462240�016400� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(12, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:25 $} @LabeledSection{Generic Units} @Comment{$Source: e:\\cvsroot/ARM/Source/12.mss,v $} @Comment{$Revision: 1.65 $} @begin{Intro} @Defn{generic unit} A @i{generic unit} is a program unit that is either a generic subprogram or a generic package. @Defn{template} A generic unit is a @i{template}@Redundant[, which can be parameterized, and from which corresponding (nongeneric) subprograms or packages can be obtained]. The resulting program units are said to be @i{instances} of the original generic unit. @IndexSee{Term=[template],See=(generic unit)} @IndexSee{Term=[macro],See=(generic unit)} @IndexSee{Term=[parameter],See=[generic formal parameter]} @ToGlossary{Term=<Generic unit>, Text=<A generic unit is a template for a (nongeneric) program unit; the template can be parameterized by objects, types, subprograms, and packages. An instance of a generic unit is created by a @nt(generic_instantiation). The rules of the language are enforced when a generic unit is compiled, using a generic contract model; additional checks are performed upon instantiation to verify the contract is met. That is, the declaration of a generic unit represents a contract between the body of the generic and instances of the generic. Generic units can be used to perform the role that macros sometimes play in other languages.>}@ChgNote{Correction for AI-00024, no mechism to correct glossary entries.} @redundant[A generic unit is declared by a @nt{generic_declaration}. This form of declaration has a @nt{generic_@!formal_@!part} declaring any generic formal parameters. An instance of a generic unit is obtained as the result of a @nt{generic_instantiation} with appropriate generic actual parameters for the generic formal parameters. An instance of a generic subprogram is a subprogram. An instance of a generic package is a package. Generic units are templates. As templates they do not have the properties that are specific to their nongeneric counterparts. For example, a generic subprogram can be instantiated but it cannot be called. In contrast, an instance of a generic subprogram is a (nongeneric) subprogram; hence, this instance can be called but it cannot be used to produce further instances.] @end{Intro} @LabeledClause{Generic Declarations} @begin{Intro} @redundant[A @nt{generic_declaration} declares a generic unit, which is either a generic subprogram or a generic package. A @nt{generic_declaration} includes a @nt{generic_formal_part} declaring any generic formal parameters. A generic formal parameter can be an object; alternatively (unlike a parameter of a subprogram), it can be a type, a subprogram, or a package.] @end{Intro} @begin{Syntax} @Syn{lhs=<generic_declaration>,rhs="@Syn2{generic_subprogram_declaration} | @Syn2{generic_package_declaration}"} @Syn{lhs=<generic_subprogram_declaration>,rhs=" @Syn2{generic_formal_part} @Syn2{subprogram_specification};"} @Syn{lhs=<generic_package_declaration>,rhs=" @Syn2{generic_formal_part} @Syn2{package_specification};"} @Syn{lhs=<generic_formal_part>,rhs="@key{generic} {@Syn2{generic_formal_parameter_declaration} | @Syn2{use_clause}}"} @Syn{lhs=<generic_formal_parameter_declaration>,rhs=" @Syn2{formal_object_declaration} | @Syn2{formal_type_declaration} | @Syn2{formal_subprogram_declaration} | @Syn2{formal_package_declaration}"} @begin{SyntaxText} The only form of @nt{subtype_indication} allowed within a @nt{generic_formal_part} is a @nt{subtype_mark} @Redundant[(that is, the @nt{subtype_indication} shall not include an explicit @nt{constraint})]. The defining name of a generic subprogram shall be an @nt{identifier} @Redundant[(not an @nt{operator_symbol})]. @begin{Reason} The reason for forbidding @nt{constraint}s in @nt{subtype_indication}s is that it simplifies the elaboration of @nt{generic_declaration}s (since there is nothing to evaluate), and that it simplifies the matching rules, and makes them more checkable at compile time. @end{Reason} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Defn{generic package} @Defn{generic subprogram} @Defn{generic procedure} @Defn{generic function} A @nt{generic_declaration} declares a generic unit @em a generic package, generic procedure@Chg{Version=[2],New=[,],Old=[]} or generic function, as appropriate. @Defn{generic formal} An entity is a @i{generic formal} entity if it is declared by a @nt<generic_formal_parameter_declaration>. @lquotes@;Generic formal,@rquotes@; or simply @lquotes@;formal,@rquotes@; is used as a prefix in referring to objects, subtypes (and types), functions, procedures and packages, that are generic formal entities, as well as to their respective declarations. @Redundant[Examples: @lquotes@;generic formal procedure@rquotes@; or a @lquotes@;formal integer type declaration.@rquotes@;] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic_declaration)} The elaboration of a @nt{generic_declaration} has no effect. @end{RunTime} @begin{Notes} Outside a generic unit a @nt{name} that denotes the @nt{generic_declaration} denotes the generic unit. In contrast, within the declarative region of the generic unit, a @nt{name} that denotes the @nt{generic_declaration} denotes the current instance. @begin{TheProof} This is stated officially as part of the @lquotes@;current instance@rquotes@; rule in @RefSec{The Context of Overload Resolution}. See also @RefSec{Generic Instantiation}. @end{TheProof} Within a generic @nt{subprogram_body}, the name of this program unit acts as the name of a subprogram. Hence this name can be overloaded, and it can appear in a recursive call of the current instance. For the same reason, this name cannot appear after the reserved word @key{new} in a (recursive) @nt{generic_instantiation}. A @nt{default_expression} or @nt{default_name} appearing in a @nt{generic_formal_part} is not evaluated during elaboration of the @nt{generic_formal_part}; instead, it is evaluated when used. (The usual visibility rules apply to any @nt{name} used in a default: the denoted declaration therefore has to be visible at the place of the expression.) @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic formal parts:} @begin{Example} @key[generic] --@RI{ parameterless } @key[generic] Size : Natural; --@RI{ formal object } @key[generic] Length : Integer := 200; --@RI{ formal object with a default expression} Area : Integer := Length*Length; --@RI{ formal object with a default expression} @key[generic] @key[type] Item @key[is] @key[private]; --@RI{ formal type} @key[type] Index @key[is] (<>); --@RI{ formal type} @key[type] Row @key[is] @key[array](Index @key[range] <>) @key[of] Item; --@RI{ formal type} @key[with] @key[function] "<"(X, Y : Item) @key[return] Boolean; --@RI{ formal subprogram } @end{Example} @begin{Wide} @leading@keepnext@i{Examples of generic declarations declaring generic subprograms Exchange and Squaring:} @end{Wide} @begin{Example} @key[generic] @key[type] Elem @key[is] @key[private]; @key[procedure] Exchange(U, V : @key[in] @key[out] Elem); @key[generic] @key[type] Item @key[is] @key[private]; @key[with] @key[function] "*"(U, V : Item) @key[return] Item @key[is] <>; @key[function] Squaring(X : Item) @key[return] Item; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a generic declaration declaring a generic package:} @end{Wide} @begin{Example} @key[generic] @key[type] Item @key[is] @key[private]; @key[type] Vector @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; @key[with] @key[function] Sum(X, Y : Item) @key[return] Item; @key[package] On_Vectors @key[is] @key[function] Sum (A, B : Vector) @key[return] Vector; @key[function] Sigma(A : Vector) @key[return] Item; Length_Error : @key[exception]; @key[end] On_Vectors; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{generic_formal_parameter_declaration} is modified to allow the reserved words @key{tagged} and @key{abstract}, to allow formal derived types, and to allow formal packages. @nt{Use_clause}s are allowed in @nt{generic_formal_part}s. This is necessary in order to allow a @nt{use_clause} within a formal part to provide direct visibility of declarations within a generic formal package. @end{Extend83} @begin{DiffWord83} The syntax for @nt{generic_formal_parameter_declaration} and @nt{formal_type_definition} is split up into more named categories. The rules for these categories are moved to the appropriate clauses and subclauses. The names of the categories are changed to be more intuitive and uniform. For example, we changed @ntf{generic_parameter_declaration} to @nt{generic_formal_parameter_declaration}, because the thing it declares is a generic formal, not a generic. In the others, we abbreviate @lquotes@;generic_formal@rquotes@; to just @lquotes@;formal@rquotes@;. We can't do that for @nt{generic_formal_parameter_declaration}, because of confusion with normal formal parameters of subprograms. @end{DiffWord83} @RmNewPage@Comment{Insert page break so printed RM's look better.} @LabeledClause{Generic Bodies} @begin{Intro} @Defn{generic body} The body of a generic unit (a @i{generic body}) @Redundant[is a template for the instance bodies. The syntax of a generic body is identical to that of a nongeneric body]. @begin{Ramification} We also use terms like @lquotes@;generic function body@rquotes@; and @lquotes@;nongeneric package body.@rquotes@; @end{Ramification} @end{Intro} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic body)} The elaboration of a generic body has no other effect than to establish that the generic unit can from then on be instantiated without failing the Elaboration_Check. If the generic body is a child of a generic package, then its elaboration establishes that each corresponding declaration nested in an instance of the parent (see @RefSecNum{Compilation Units - Library Units}) can from then on be instantiated without failing the Elaboration_Check. @end{RunTime} @begin{Notes} The syntax of generic subprograms implies that a generic subprogram body is always the completion of a declaration. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a generic procedure body:} @begin{Example} @key[procedure] Exchange(U, V : @key[in] @key[out] Elem) @key[is] --@RI{ see @RefSecNum{Generic Declarations}} T : Elem; --@RI{ the generic formal type} @key[begin] T := U; U := V; V := T; @key[end] Exchange; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a generic function body:} @end{Wide} @begin{Example} @key[function] Squaring(X : Item) @key[return] Item @key[is] --@RI{ see @RefSecNum{Generic Declarations}} @key[begin] @key[return] X*X; --@RI{ the formal operator "*"} @key[end] Squaring; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a generic package body:} @end{Wide} @begin{Example} @key[package] @key[body] On_Vectors @key[is] --@RI{ see @RefSecNum{Generic Declarations}} @key[function] Sum(A, B : Vector) @key[return] Vector @key[is] Result : Vector(A'Range); --@RI{ the formal type Vector} Bias : @key[constant] Integer := B'First - A'First; @key[begin] @key[if] A'Length /= B'Length @key[then] @key[raise] Length_Error; @key[end] @key[if]; @key[for] N @key[in] A'Range @key[loop] Result(N) := Sum(A(N), B(N + Bias)); --@RI{ the formal function Sum} @key[end] @key[loop]; @key[return] Result; @key[end] Sum; @key[function] Sigma(A : Vector) @key[return] Item @key[is] Total : Item := A(A'First); --@RI{ the formal type Item} @key[begin] @key[for] N @key[in] A'First + 1 .. A'Last @key[loop] Total := Sum(Total, A(N)); --@RI{ the formal function Sum} @key[end] @key[loop]; @key[return] Total; @key[end] Sigma; @key[end] On_Vectors; @end{Example} @end{Examples} @LabeledClause{Generic Instantiation} @begin{Intro} @redundant[@Defn2{Term=[instance], Sec=(of a generic unit)} An instance of a generic unit is declared by a @nt{generic_instantiation}.] @end{Intro} @begin{MetaRules} @Defn{generic contract model} @Defn{contract model of generics} The legality of an instance should be determinable without looking at the generic body. Likewise, the legality of a generic body should be determinable without looking at any instances. Thus, the @nt{generic_declaration} forms a contract between the body and the instances; if each obeys the rules with respect to the @nt{generic_declaration}, then no legality problems will arise. This is really a special case of the @lquotes@;legality determinable via semantic dependences@rquotes@; @MetaRulesName (see Section 10), given that a @nt{generic_instantiation} does not depend semantically upon the generic body, nor vice-versa. Run-time issues are another story. For example, whether parameter passing is by copy or by reference is determined in part by the properties of the generic actuals, and thus cannot be determined at compile time of the generic body. Similarly, the contract model does not apply to @LinkTimeTitle. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @Syn{lhs=<generic_instantiation>,rhs=" @key{package} @Syn2{defining_program_unit_name} @key{is} @key{new} @SynI{generic_package_}@Syn2{name} [@Syn2{generic_actual_part}]; | @Chg{Version=[2],New=<[@Syn2{overriding_indicator}] >,Old=<>}@key{procedure} @Syn2{defining_program_unit_name} @key{is} @key{new} @SynI{generic_procedure_}@Syn2{name} [@Syn2{generic_actual_part}]; | @Chg{Version=[2],New=<[@Syn2{overriding_indicator}] >,Old=<>}@key{function} @Syn2{defining_designator} @key{is} @key{new} @SynI{generic_function_}@Syn2{name} [@Syn2{generic_actual_part}];"} @Syn{lhs=<generic_actual_part>,rhs=" (@Syn2{generic_association} {, @Syn2{generic_association}})"} @Syn{lhs=<generic_association>,rhs=" [@SynI{generic_formal_parameter_}@Syn2{selector_name} =>] @Syn2{explicit_generic_actual_parameter}"} @Syn{lhs=<explicit_generic_actual_parameter>,rhs="@Syn2{expression} | @SynI{variable_}@Syn2{name} | @SynI{subprogram_}@Syn2{name} | @SynI{entry_}@Syn2{name} | @Syn2{subtype_mark} | @SynI{package_instance_}@Syn2{name}"} @begin{SyntaxText} @Defn{named association} @Defn{positional association} A @nt{generic_association} is @i{named} or @i{positional} according to whether or not the @i{generic_@!formal_@!parameter_}@!@nt<selector_@!name> is specified. Any positional associations shall precede any named associations. @end{SyntaxText} @end{Syntax} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised]} @Defn{generic actual parameter} @Defn{generic actual} @Defn{actual} The @i{generic actual parameter} is either the @nt{explicit_generic_actual_parameter} given in a @Chg{Version=[2],New=[@nt{generic_@!association}],Old=[@ntf{generic_@!parameter_@!association}]} for each formal, or the corresponding @nt{default_@!expression} or @nt{default_@!name} if no @Chg{Version=[2],New=[@nt{generic_@!association}],Old=[@ntf{generic_@!parameter_@!association}]} is given for the formal. When the meaning is clear from context, the term @lquotes@;generic actual,@rquotes@; or simply @lquotes@;actual,@rquotes@; is used as a synonym for @lquotes@;generic actual parameter@rquotes@; and also for the view denoted by one, or the value of one. @end{Intro} @begin{Legality} In a @nt<generic_instantiation> for a particular kind of program unit @Redundant[(package, procedure, or function)], the @nt<name> shall denote a generic unit of the corresponding kind @Redundant[(generic package, generic procedure, or generic function, respectively)]. The @SynI{generic_formal_parameter_}@nt{selector_name} of a @nt{generic_association} shall denote a @nt{generic_formal_parameter_declaration} of the generic unit being instantiated. If two or more formal subprograms have the same defining name, then named associations are not allowed for the corresponding actuals. A @nt{generic_instantiation} shall contain at most one @nt<generic_association> for each formal. Each formal without an association shall have a @nt{default_expression} or @nt{subprogram_default}. In a generic unit @LegalityName@;s are enforced at compile time of the @nt{generic_declaration} and generic body, given the properties of the formals. In the visible part and formal part of an instance, @LegalityName@;s are enforced at compile time of the @nt{generic_instantiation}, given the properties of the actuals. In other parts of an instance, @LegalityName@;s are not enforced; this rule does not apply when a given rule explicitly specifies otherwise. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Since rules are checked using the properties of the formals, and since these properties do not always carry over to the actuals, we need to check the rules again in the visible part of the instance. For example, only if a tagged type is limited may an extension of it have limited components in the @Chg{Version=[2],New=[@nt{record_extension_part}],Old=[@ntf<extension_part>]}. A formal tagged limited type is limited, but the actual might be nonlimited. Hence any rule that requires a tagged type to be limited runs into this problem. Such rules are rare; in most cases, the rules for matching of formals and actuals guarantee that if the rule is obeyed in the generic unit, then it has to be obeyed in the instance. @end{Reason} @begin{Ramification} @leading@;The @lquotes@;properties@rquotes@; of the formals are determined without knowing anything about the actuals: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0095],ARef=[AI95-00034-01]} A formal derived subtype is constrained if and only if the ancestor subtype is constrained. A formal array type is constrained if and only if the declarations @Chg{New=[say],Old=[says]} so.@Chg{New=[ A formal private type is constrained if it does not have a discriminant part.],Old=[]} Other formal subtypes are unconstrained, even though they might be constrained in an instance. A formal subtype can be indefinite, even though the copy might be definite in an instance. A formal object of mode @key[in] is not a static constant; in an instance, the copy is static if the actual is. A formal subtype is not static, even though the actual might be. Formal types are specific, even though the actual can be class-wide. The subtype of a formal object of mode @key[in out] is not static. (This covers the case of AI83-00878.) The subtype of a formal parameter of a formal subprogram does not provide an applicable index constraint. The profile of a formal subprogram is not subtype-conformant with any other profile. @Defn{subtype conformance} A generic formal function is not static. @end{Itemize} @end{Ramification} @begin{Ramification} @leading@;The exceptions to the above rule about when legality rules are enforced fall into these categories: @begin{Itemize} @leading@;Some rules are checked in the generic declaration, and then again in both the visible and private parts of the instance: @begin{InnerItemize} The parent type of a record extension has to be specific (see @RefSecNum{Type Extensions}). This rule is not checked in the instance body. The parent type of a private extension has to be specific (see @RefSecNum{Private Types and Private Extensions}). This rule is not checked in the instance body. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00402-01]} A type with @Chg{Version=[2],New=[a @nt{default_expression} of ],Old=[]}an access discriminant has to be a descendant of @Chg{Version=[2],New=[an explicitly limited record type],Old=[a type declared with @key[limited]]}, or be a task or protected type. This rule is irrelevant in the instance body.]} In the declaration of a record extension, if the parent type is nonlimited, then each of the components of the @nt{record_extension_part} have to be nonlimited (see @RefSecNum{Type Extensions}). In the generic body, this rule is checked in an assume-the-worst manner. A preelaborated library unit has to be preelaborable (see @RefSecNum{Elaboration Control}). In the generic body, this rule is checked in an assume-the-worst manner. @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00402-01]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The corrections made by the Corrigendum added a number of such rules, and the Amendment added many more. There doesn't seem to be much value in repeating all of these rules here (as of this writing, there are roughly 17 such rules). As noted below, all such rules are indexed in the AARM.]} @PDefn2{Term=[accessibility rule],Sec=(checking in generic units)} For the accessibility rules, the formals have nothing to say about the property in question. Like the above rules, these rules are checked in the generic declaration, and then again in both the visible and private parts of the instance. In the generic body, we have explicit rules that essentially assume the worst (in the cases of type extensions and access-to-subprogram types), and we have run-time checks (in the case of access-to-object types). See @RefSecNum{Type Extensions}, @RefSecNum{Operations of Access Types}, and @RefSecNum{Type Conversions}. @NoPrefix@;We considered run-time checks for access-to-subprogram types as well. However, this would present difficulties for implementations that share generic bodies. The rules requiring @lquotes@;reasonable@rquotes@; values for static expressions are ignored when the expected type for the expression is a descendant of a generic formal type other than a generic formal derived type, and do not apply in an instance. The rule forbidding two explicit homographs in the same declarative region does not apply in an instance of a generic unit, except that it @i{does} apply in the declaration of a record extension that appears in the visible part of an instance. @leading@;Some rules do not apply at all in an instance, not even in the visible part: @begin{InnerItemize} @nt{Body_stub}s are not normally allowed to be multiply nested, but they can be in instances. @end{InnerItemize} @end{Itemize} @RootDefn{generic contract issue} Each rule that is an exception is marked with @lquotes@;generic contract issue;@rquotes@; look that up in the index to find them all. @end{Ramification} @begin{Ramification} The @LegalityName@;s are the ones labeled @LegalityTitle. We are talking about all @LegalityName@;s in the entire language here. Note that, with some exceptions, the legality of a generic unit is checked even if there are no instantiations of the generic unit. @end{Ramification} @begin{Ramification} The @LegalityName@;s are described here, and the overloading rules were described earlier in this clause. Presumably, every @StaticSemName is sucked in by one of those. Thus, we have covered all the compile-time rules of the language. There is no need to say anything special about the @LinkTimeName@;s or the @RunTimeName@;s. @end{Ramification} @begin{Discussion} Here is an example illustrating how this rule is checked: @lquotes@;In the declaration of a record extension, if the parent type is nonlimited, then each of the components of the @nt{record_extension_part} shall be nonlimited.@rquotes@; @begin{Example} @key[generic] @key[type] Parent @key[is] @key[tagged] @key[private]; @key[type] Comp @key[is] @key[limited] @key[private]; @key[package] G1 @key[is] @key[type] Extension @key[is] @key[new] Parent @key[with] @key[record] C : Comp; --@RI{ Illegal!} @key[end] @key[record]; @key[end] G1; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} The parent type is nonlimited, and the component type is limited, which is illegal. It doesn't matter that @Chg{New=[],Old=[an ]}one could imagine writing an instantiation with the actual for Comp being nonlimited @em we never get to the instance, because the generic itself is illegal. @leading@;On the other hand: @begin{Example} @key[generic] @key[type] Parent @key[is] @key[tagged] @key[limited] @key[private]; --@RI{ Parent is limited.} @key[type] Comp @key[is] @key[limited] @key[private]; @key[package] G2 @key[is] @key[type] Extension @key[is] @key[new] Parent @key[with] @key[record] C : Comp; --@RI{ OK.} @key[end] @key[record]; @key[end] G2; @key[type] Limited_Tagged @key[is] @key[tagged] @key[limited] @key[null] @key[record]; @key[type] Non_Limited_Tagged @key[is] @key[tagged] @key[null] @key[record]; @key[type] Limited_Untagged @key[is] @key[limited] @key[null] @key[record]; @key[type] Non_Limited_Untagged @key[is] @key[null] @key[record]; @key[package] Good_1 @key[is] @key[new] G2(Parent => Limited_Tagged, Comp => Limited_Untagged); @key[package] Good_2 @key[is] @key[new] G2(Parent => Non_Limited_Tagged, Comp => Non_Limited_Untagged); @key[package] Bad @key[is] @key[new] G2(Parent => Non_Limited_Tagged, Comp => Limited_Untagged); --@RI{ Illegal!} @end{Example} The first instantiation is legal, because in the instance the parent is limited, so the rule is not violated. Likewise, in the second instantiation, the rule is not violated in the instance. However, in the Bad instance, the parent type is nonlimited, and the component type is limited, so this instantiation is illegal. @end{Discussion} @end{Legality} @begin{StaticSem} A @nt{generic_instantiation} declares an instance; it is equivalent to the instance declaration (a @nt{package_@!declaration} or @nt{subprogram_@!declaration}) immediately followed by the instance body, both at the place of the instantiation. @begin{Ramification} The declaration and the body of the instance are not @lquotes@;implicit@rquotes@; in the technical sense, even though you can't see them in the program text. Nor are declarations within an instance @lquotes@;implicit@rquotes@; (unless they are implicit by other rules). This is necessary because implicit declarations have special semantics that should not be attached to instances. For a generic subprogram, the profile of a @nt{generic_instantiation} is that of the instance declaration, by the stated equivalence. @end{Ramification} @begin{Ramification} @PDefn2{Term=[visible part], Sec=(of an instance)} @PDefn2{Term=[private part], Sec=(of a package)} The visible and private parts of a package instance are defined in @RefSec{Package Specifications and Declarations} and @RefSec{Formal Packages}. The visible and private parts of a subprogram instance are defined in @RefSec{Scope of Declarations}. @end{Ramification} The instance is a copy of the text of the template. @Redundant[Each use of a formal parameter becomes (in the copy) a use of the actual, as explained below.] @Defn{package instance} @Defn{subprogram instance} @Defn{procedure instance} @Defn{function instance} @Defn2{Term=[instance], Sec=(of a generic package)} @Defn2{Term=[instance], Sec=(of a generic subprogram)} @Defn2{Term=[instance], Sec=(of a generic procedure)} @Defn2{Term=[instance], Sec=(of a generic function)} An instance of a generic package is a package, that of a generic procedure is a procedure, and that of a generic function is a function. @begin{Ramification} An instance is a package or subprogram (because we say so), even though it contains a copy of the @nt{generic_formal_part}, and therefore doesn't look like one. This is strange, but it's OK, since the syntax rules are overloading rules, and therefore do not apply in an instance. @end{Ramification} @begin{Discussion} We use a macro-expansion model, with some explicitly-stated exceptions (see below). The main exception is that the interpretation of each construct in a generic unit (especially including the denotation of each name) is determined when the declaration and body of the generic unit (as opposed to the instance) are compiled, and in each instance this interpretation is (a copy of) the template interpretation. In other words, if a construct is interpreted as a @nt{name} denoting a declaration D, then in an instance, the copy of the construct will still be a name, and will still denote D (or a copy of D). From an implementation point of view, overload resolution is performed on the template, and not on each copy. We describe the substitution of generic actual parameters by saying (in most cases) that the copy of each generic formal parameter declares a view of the actual. Suppose a name in a generic unit denotes a @nt{generic_formal_parameter_declaration}. The copy of that name in an instance will denote the copy of that @nt{generic_formal_parameter_declaration} in the instance. Since the @nt{generic_formal_parameter_declaration} in the instance declares a view of the actual, the name will denote a view of the actual. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Other properties of the copy (for example, staticness, @Chg{Version=[2],New=[categories],Old=[classes]} to which types belong) are recalculated for each instance; this is implied by the fact that it's a copy. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} Although the @nt{generic_formal_part} is included in an instance, the declarations in the @nt{generic_formal_part} are only visible outside the instance in the case of a generic formal package whose @nt{formal_package_actual_part} @Chg{Version=[2],New=[includes one or more <> indicators],Old=[is (<>)]} @em see @RefSecNum{Formal Packages}. @end{Discussion} The interpretation of each construct within a generic declaration or body is determined using the overloading rules when that generic declaration or body is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the @nt{generic_declaration} or some declaration within the generic unit; the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. The overloading rules do not apply in the instance. @begin{Ramification} See @RefSec{The Context of Overload Resolution} for definitions of @lquotes@;interpretation@rquotes@; and @lquotes@;overloading rule.@rquotes@; Even the @nt{generic_formal_parameter_declaration}s have corresponding declarations in the instance, which declare views of the actuals. Although the declarations in the instance are copies of those in the generic unit, they often have quite different properties, as explained below. For example a constant declaration in the generic unit might declare a nonstatic constant, whereas the copy of that declaration might declare a static constant. This can happen when the staticness depends on some generic formal. This rule is partly a ramification of the @lquotes@;current instance@rquotes@; rule in @RefSec{The Context of Overload Resolution}. Note that that rule doesn't cover the @nt{generic_formal_part}. Although the overloading rules are not observed in the instance, they are, of course, observed in the @ntf{_instantiation} in order to determine the interpretation of the constituents of the @ntf{_instantiation}. Since children are considered to occur within their parent's declarative region, the above rule applies to a name that denotes a child of a generic unit, or a declaration inside such a child. Since the @SyntaxName@;s are overloading rules, it is possible (legal) to violate them in an instance. For example, it is possible for an instance body to occur in a @nt{package_specification}, even though the @SyntaxName@;s forbid bodies in @nt{package_specification}s. @end{Ramification} In an instance, a @nt{generic_formal_parameter_declaration} declares a view whose properties are identical to those of the actual, except as specified in @RefSec{Formal Objects} and @RefSec{Formal Subprograms}. Similarly, for a declaration within a @nt{generic_formal_parameter_declaration}, the corresponding declaration in an instance declares a view whose properties are identical to the corresponding declaration within the declaration of the actual. @begin{Ramification} In an instance, there are no @lquotes@;properties@rquotes@; of types and subtypes that come from the formal. The primitive operations of the type come from the formal, but these are declarations in their own right, and are therefore handled separately. Note that certain properties that come from the actuals are irrelevant in the instance. For example, if an actual type is of a class deeper in the derived-type hierarchy than the formal, it is impossible to call the additional operations of the deeper class in the instance, because any such call would have to be a copy of some corresponding call in the generic unit, which would have been illegal. However, it is sometimes possible to reach into the specification of the instance from outside, and notice such properties. For example, one could pass an object declared in the instance specification to one of the additional operations of the deeper type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A @nt{formal_type_declaration} can contain @nt{discriminant_specification}s, a @nt{formal_subprogram_declaration} can contain @Chg{Version=[2],New=[@nt{parameter_specification}s],Old=[@ntf{formal_parameter_specification}s]}, and a @nt{formal_package_declaration} can contain many kinds of declarations. These are all inside the generic unit, and have corresponding declarations in the instance. This rule implies, for example, that if a subtype in a generic unit is a subtype of a generic formal subtype, then the corresponding subtype in the instance is a subtype of the corresponding actual subtype. For a @nt{generic_instantiation}, if a generic actual is a static @Redundant[(scalar or string)] subtype, then each use of the corresponding formal parameter within the specification of the instance is considered to be static. (See AI83-00409.) Similarly, if a generic actual is a static expression and the corresponding formal parameter has a static @Redundant[(scalar or string)] subtype, then each use of the formal parameter in the specification of the instance is considered to be static. (See AI83-00505.) @leading@;If a primitive subprogram of a type derived from a generic formal derived tagged type is not overriding (that is, it is a new subprogram), it is possible for the copy of that subprogram in an instance to override a subprogram inherited from the actual. For example: @begin{Example} @key[type] T1 @key[is] @key[tagged] @key[record] ... @key[end] @key[record]; @key[generic] @key[type] Formal @key[is] @key[new] T1; @key[package] G @key[is] @key[type] Derived_From_Formal @key[is] @key[new] Formal @key[with] @key[record] ... @key[end] @key[record]; @key[procedure] Foo(X : @key[in] Derived_From_Formal); --@RI{ Does not override anything.} @key[end] G; @key[type] T2 @key[is] @key[new] T1 @key[with] @key[record] ... @key[end] @key[record]; @key[procedure] Foo(X : @key[in] T2); @key[package] Inst @key[is] @key[new] G(Formal => T2); @end{Example} In the instance Inst, the declaration of Foo for Derived_From_Formal overrides the Foo inherited from T2. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} For formal types, an implementation that shares the code among multiple instances of the same generic unit needs to beware that things like parameter passing mechanisms (by-copy vs. by-reference) and @Chg{New=[@nt{aspect_clause}s],Old=[@nt{representation_clause}s]} are determined by the actual. @end{ImplNote} @redundant[Implicit declarations are also copied, and a name that denotes an implicit declaration in the generic denotes the corresponding copy in the instance. However, for a type declared within the visible part of the generic, a whole new set of primitive subprograms is implicitly declared for use outside the instance, and may differ from the copied set if the properties of the type in some way depend on the properties of some actual type specified in the instantiation. For example, if the type in the generic is derived from a formal private type, then in the instance the type will inherit subprograms from the corresponding actual type. @Defn{override} These new implicit declarations occur immediately after the type declaration in the instance, and override the copied ones. The copied ones can be called only from within the instance; the new ones can be called only from outside the instance, although for tagged types, the body of a new one can be executed by a call to an old one.] @begin{TheProof} This rule is stated officially in @RefSec{Visibility}. @end{TheProof} @begin{Ramification} The new ones follow from the class(es) of the formal types. For example, for a type T derived from a generic formal private type, if the actual is Integer, then the copy of T in the instance has a "+" primitive operator, which can be called from outside the instance (assuming T is declared in the visible part of the instance). AI83-00398. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Since an actual type is always in the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal, the new subprograms hide all of the copied ones, except for a declaration of "/=" that corresponds to an explicit declaration of "=". Such "/=" operators are special, because unlike other implicit declarations of primitive subprograms, they do not appear by virtue of the class, but because of an explicit declaration of "=". If the declaration of "=" is implicit (and therefore overridden in the instance), then a corresponding implicitly declared "/=" is also overridden. But if the declaration of "=" is explicit (and therefore not overridden in the instance), then a corresponding implicitly declared "/=" is not overridden either, even though it's implicit. Note that the copied ones can be called from inside the instance, even though they are hidden from all visibility, because the names are resolved in the generic unit @em visibility is irrelevant for calls in the instance. @end{Ramification} @Redundant[In the visible part of an instance, an explicit declaration overrides an implicit declaration if they are homographs, as described in @RefSecNum{Visibility}.] On the other hand, an explicit declaration in the private part of an instance overrides an implicit declaration in the instance, only if the corresponding explicit declaration in the generic overrides a corresponding implicit declaration in the generic. Corresponding rules apply to the other kinds of overriding described in @RefSecNum{Visibility}. @begin{Ramification} @leading@;For example: @begin{Example} @key[type] Ancestor @key[is] @key[tagged] @key[null] @key[record]; @key[generic] @key[type] Formal @key[is] @key[new] Ancestor @key[with] @key[private]; @key[package] G @key[is] @key[type] T @key[is] @key[new] Formal @key[with] @key[null] @key[record]; @key[procedure] P(X : @key[in] T); --@RI{ (1)} @key[private] @key[procedure] Q(X : @key[in] T); --@RI{ (2)} @key[end] G; @key[type] Actual @key[is] @key[new] Ancestor @key[with] @key[null] @key[record]; @key[procedure] P(X : @key[in] Actual); @key[procedure] Q(X : @key[in] Actual); @key[package] Instance @key[is] @key[new] G(Formal => Actual); @end{Example} In the instance, the copy of P at (1) overrides Actual's P, whereas the copy of Q at (2) does not override anything; in implementation terms, it occupies a separate slot in the type descriptor. @end{Ramification} @begin{Reason} The reason for this rule is so a programmer writing an @ntf{_instantiation} need not look at the private part of the generic in order to determine which subprograms will be overridden. @end{Reason} @end{StaticSem} @begin{LinkTime} Recursive generic instantiation is not allowed in the following sense: if a given generic unit includes an instantiation of a second generic unit, then the instance generated by this instantiation shall not include an instance of the first generic unit @Redundant[(whether this instance is generated directly, or indirectly by intermediate instantiations)]. @begin{Discussion} Note that this rule is not a violation of the generic contract model, because it is not a @LegalityName. Some implementations may be able to check this rule at compile time, but that requires access to all the bodies, so we allow implementations to check the rule at link time. @end{Discussion} @end{LinkTime} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic_instantiation)} For the elaboration of a @nt{generic_instantiation}, each @nt{generic_association} is first evaluated. If a default is used, an implicit @nt{generic_association} is assumed for this rule. These evaluations are done in an arbitrary order, except that the evaluation for a default actual takes place after the evaluation for another actual if the default includes a @nt{name} that denotes the other one. Finally, the instance declaration and body are elaborated. @begin{Ramification} Note that if the evaluation of a default depends on some side-effect of some other evaluation, the order is still arbitrary. @end{Ramification} @PDefn2{Term=[evaluation], Sec=(generic_association)} For the evaluation of a @nt{generic_association} the generic actual parameter is evaluated. Additional actions are performed in the case of a formal object of mode @key{in} (see @RefSecNum{Formal Objects}). @begin{Honest} Actually, the actual is evaluated only if evaluation is defined for that kind of construct @em we don't actually @lquotes@;evaluate@rquotes@; @nt{subtype_mark}s. @end{Honest} @end{RunTime} @begin{Notes} If a formal type is not tagged, then the type is treated as an untagged type within the generic body. Deriving from such a type in a generic body is permitted; the new type does not get a new tag value, even if the actual is tagged. Overriding operations for such a derived type cannot be dispatched to from outside the instance. @begin{Ramification} If two overloaded subprograms declared in a generic package specification differ only by the (formal) type of their parameters and results, then there exist legal instantiations for which all calls of these subprograms from outside the instance are ambiguous. For example: @begin{Example} @key[generic] @key[type] A @key[is] (<>); @key[type] B @key[is] @key[private]; @key[package] G @key[is] @key[function] Next(X : A) @key[return] A; @key[function] Next(X : B) @key[return] B; @key[end] G; @key[package] P @key[is] @key[new] G(A => Boolean, B => Boolean); --@RI{ All calls of P.Next are ambiguous.} @end{Example} @end{Ramification} @begin{Ramification} @leading@;The following example illustrates some of the subtleties of the substitution of formals and actuals: @begin{Example} @key[generic] @key[type] T1 @key[is] @key[private]; --@RI{ A predefined "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : T1) return Boolean;} --@RI{ Call this "="@-{1}.} @key[package] G @key[is] @key[subtype] S1 @key[is] T1; --@RI{ So we can get our hands on the type from} --@RI{ outside an instance.} @key[type] T2 @key[is] @key[new] T1; --@RI{ An inherited "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : T2) return Boolean;} --@RI{ Call this "="@-{2}.} T1_Obj : T1 := ...; Bool_1 : Boolean := T1_Obj = T1_Obj; T2_Obj : T2 := ...; Bool_2 : Boolean := T2_Obj = T2_Obj; @key[end] G; ... @key[package] P @key[is] @key[type] My_Int @key[is] @key[new] Integer; --@RI{ A predefined "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : My_Int) return Boolean;} --@RI{ Call this "="@-{3}.} @key[function] "="(X, Y : My_Int) @key[return] Boolean; --@RI{ Call this "="@-{4}.} --@RI{ "="@-{3} is hidden from all visibility by "="@-{4}.} --@RI{ Nonetheless, "="@-{3} can @lquotes@;reemerge@rquotes@; in certain circumstances.} @key[end] P; @key[use] P; ... @key[package] I @key[is] @key[new] G(T1 => My_Int); --@RI{ "="@-{5} is declared in I (see below).} @key[use] I; Another_T1_Obj : S1 := 13; --@RI{ Can't denote T1, but S1 will do.} Bool_3 : Boolean := Another_T1_Obj = Another_T1_Obj; Another_T2_Obj : T2 := 45; Bool_4 : Boolean := Another_T2_Obj = Another_T2_Obj; Double : T2 := T2_Obj + Another_T2_Obj; @end{Example} In the instance I, there is a copy of "="@-{1} (call it "="@-{1i}) and "="@-{2} (call it "="@-{2i}). The "="@-{1i} and "="@-{2i} declare views of the predefined "=" of My_Int (that is, "="@-{3}). In the initialization of Bool_1 and Bool_2 in the generic unit G, the names "=" denote "="@-{1} and "="@-{2}, respectively. Therefore, the copies of these names in the instances denote "="@-{1i} and "="@-{2i}, respectively. Thus, the initialization of I.Bool_1 and I.Bool_2 call the predefined equality operator of My_Int; they will not call "="@-{4}. The declarations "="@-{1i} and "="@-{2i} are hidden from all visibility. This prevents them from being called from outside the instance. The declaration of Bool_3 calls "="@-{4}. The instance I also contains implicit declarations of the primitive operators of T2, such as "=" (call it "="@-{5}) and "+". These operations cannot be called from within the instance, but the declaration of Bool_4 calls "="@-{5}. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic instantiations (see @RefSecNum{Generic Declarations}):} @begin{Example} @tabclear()@tabset(P49) @key[procedure] Swap @key[is] @key[new] Exchange(Elem => Integer); @key[procedure] Swap @key[is] @key[new] Exchange(Character); @\--@RI{ Swap is overloaded } @key[function] Square @key[is] @key[new] Squaring(Integer); @\--@RI{ "*" of Integer used by default} @key[function] Square @key[is] @key[new] Squaring(Item => Matrix, "*" => Matrix_Product); @key[function] Square @key[is] @key[new] Squaring(Matrix, Matrix_Product); --@RI{ same as previous } @key[package] Int_Vectors @key[is] @key[new] On_Vectors(Integer, Table, "+"); @end{Example} @begin{Wide} @leading@keepnext@i{Examples of uses of instantiated units:} @end{Wide} @begin{Example} Swap(A, B); A := Square(A); T : Table(1 .. 5) := (10, 20, 30, 40, 50); N : Integer := Int_Vectors.Sigma(T); --@RI{ 150 (see @RefSec{Generic Bodies} for the body of Sigma)} @key[use] Int_Vectors; M : Integer := Sigma(T); --@RI{ 150} @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} In Ada 83, all explicit actuals are evaluated before all defaults, and the defaults are evaluated in the order of the formal declarations. This ordering requirement is relaxed in Ada 95. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} We have attempted to remove every violation of the contract model. Any remaining contract model violations should be considered bugs in the RM95. The unfortunate property of reverting to the predefined operators of the actual types is retained for upward compatibility. (Note that fixing this would require subtype conformance rules.) However, tagged types do not revert in this sense. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{explicit_generic_actual_parameter} is modified to allow a @SynI{package_instance_}@nt{name}. @end{Extend83} @begin{DiffWord83} The fact that named associations cannot be used for two formal subprograms with the same defining name is moved to AARM-only material, because it is a ramification of other rules, and because it is not of interest to the average user. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The rule that @lquotes@;An explicit @nt{explicit_generic_actual_parameter} shall not be supplied more than once for a given @Chg{Version=[2],New=[generic formal parameter], Old=[@ntf{generic_formal_parameter}]}@rquotes@; seems to be missing from RM83, although it was clearly the intent. In the explanation that the instance is a copy of the template, we have left out RM83-12.3(5)'s @lquotes@;apart from the generic formal part@rquotes@;, because it seems that things in the formal part still need to exist in instances. This is particularly true for generic formal packages, where you're sometimes allowed to reach in and denote the formals of the formal package from outside it. This simplifies the explanation of what each name in an instance denotes: there are just two cases: the declaration can be inside or outside (where inside needs to include the generic unit itself). Note that the RM83 approach of listing many cases (see RM83-12.5(5-14)) would have become even more unwieldy with the addition of generic formal packages, and the declarations that occur therein. We have corrected the definition of the elaboration of a @nt{generic_instantiation} (RM83-12.3(17)); we don't elaborate entities, and the instance is not @lquotes@;implicit.@rquotes@; In RM83, there is a rule saying the formal and actual shall match, and then there is much text defining what it means to match. Here, we simply state all the latter text as rules. For example, @lquotes@;A formal foo is matched by an actual greenish bar@rquotes@; becomes @lquotes@;For a formal foo, the actual shall be a greenish bar.@rquotes@; This is necessary to split the @ResolutionName@;s from the @LegalityName@;s. Besides, there's really no need to define the concept of matching for generic parameters. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{overriding_indicator} (see @RefSecNum{Overriding Indicators}) is allowed on a subprogram instantiation.]} @end{Extend95} @LabeledClause{Formal Objects} @begin{Intro} @redundant[@Defn{generic formal object} @Defn{formal object, generic} A generic formal object can be used to pass a value or variable to a generic unit.] @end{Intro} @begin{MetaRules} A generic formal object of mode @key{in} is like a constant initialized to the value of the @nt{explicit_generic_actual_parameter}. A generic formal object of mode @key{in out} is like a renaming of the @nt{explicit_generic_actual_parameter}. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00423-01]} @Syn{lhs=<formal_object_declaration>,rhs=" @Syn2{defining_identifier_list} : @Syn2{mode} @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [:= @Syn2{default_expression}];@Chg{Version=[2],New=< @Syn2{defining_identifier_list} : @Syn2{mode} @Syn2{access_definition} [:= @Syn2{default_expression}];>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(generic formal object default_expression)} The expected type for the @nt{default_expression}, if any, of a formal object is the type of the formal object. @PDefn2{Term=[expected type], Sec=(generic formal in object actual)} For a generic formal object of mode @key[in], the expected type for the actual is the type of the formal. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00423-01]} For a generic formal object of mode @key[in out], the type of the actual shall resolve to the type @Chg{Version=[2], New=[determined by the @nt{subtype_mark}, or for a @nt{formal_object_declaration} with an @nt{access_definition}, to a specific anonymous access type. If the anonymous access type is an access-to-object type, the type of the actual shall have the same designated type as that of the @nt{access_definition}. If the anonymous access type is an access-to-subprogram type, the type of the actual shall have a designated profile which is type conformant with that of the @nt{access_definition}. @Defn2{Term=[type conformance],Sec=(required)}],Old=[of the formal]}. @begin{Reason} See the corresponding rule for @nt{object_renaming_declaration}s for a discussion of the reason for this rule. @end{Reason} @end{Resolution} @begin{Legality} If a generic formal object has a @nt{default_expression}, then the mode shall be @key{in} @Redundant[(either explicitly or by default)]; otherwise, its mode shall be either @key{in} or @key{in out}. @begin{Ramification} Mode @key{out} is not allowed for generic formal objects. @end{Ramification} For a generic formal object of mode @key{in}, the actual shall be an @nt{expression}. For a generic formal object of mode @key{in out}, the actual shall be a @nt{name} that denotes a variable for which renaming is allowed (see @RefSecNum{Object Renaming Declarations}). @begin{Honest} The part of this that requires an @nt{expression} or @nt{name} is a @ResolutionName, but that's too pedantic to worry about. (The part about denoting a variable, and renaming being allowed, is most certainly @i{not} a @ResolutionName.) @end{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{Conditional leading} @Chg{Version=[2],New=[In the case where the type of the formal is defined by an @nt{access_definition}, the type of the actual and the type of the formal:], Old=[The type of a generic formal object of mode @key{in} shall be nonlimited.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-object types with statically matching designated subtypes and with both or neither being access-to-constant types; or @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-subprogram types with subtype conformant designated profiles. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a @nt{formal_object_declaration} with a @nt{null_exclusion} or an @nt{access_definition} that has a @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the actual matching the @nt{formal_object_declaration} denotes the generic formal object of another generic unit @i{G}, and the instantiation containing the actual occurs within the body of @i{G} or within the body of a generic unit declared within the declarative region of @i{G}, then the declaration of the formal object of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the actual matching the @nt{formal_object_declaration} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00423-01]} @Chg{Version=[2],New=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of an object with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child units) when the subtype of the formal object excludes null implicitly.], Old=[Since a generic formal object is like a constant of mode @key{in} initialized to the value of the actual, a limited type would not make sense, since initializing a constant is not allowed for a limited type. That is, generic formal objects of mode @key{in} are passed by copy, and limited types are not supposed to be copied.]} @end{Reason} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00255-01],ARef=[AI95-00423-01]} A @nt{formal_object_declaration} declares a generic formal object. The default mode is @key{in}. @PDefn2{Term=[nominal subtype], Sec=(of a generic formal object)} For a formal object of mode @key{in}, the nominal subtype is the one denoted by the @nt{subtype_mark} @Chg{Version=[2],New=[or @nt{access_definition} ],Old=[]}in the declaration of the formal. @PDefn2{Term=[static], Sec=(subtype)} For a formal object of mode @key{in out}, its type is determined by the @nt<subtype_mark> @Chg{Version=[2], New=[or @nt{access_definition} ],Old=[]}in the declaration; its nominal subtype is nonstatic, even if the @nt<subtype_mark> denotes a static subtype@Chg{Version=[2], New=[; for a composite type, its nominal subtype is unconstrained if the first subtype of the type is unconstrained@Redundant[, even if the @nt{subtype_mark} denotes a constrained subtype]],Old=[]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00255-01]} @ChgAdded{Version=[2],Text=[We require that the subtype is unconstrained because a formal @key{in out} acts like a renaming, and thus the given subtype is ignored for purposes of matching; any value of the type can be passed. Thus we can assume only that the object is constrained if the first subtype is constrained (and thus there can be no unconstrained subtypes for the type). If we didn't do this, it would be possible to rename or take 'Access of components that could disappear due to an assignment to the whole object.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[The two @lquotes@;even if@rquotes clauses are OK even though they don't mention @nt{access_definition}s; an access subtype can neither be a static subtype nor be a composite type.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} @Chg{Version=[2],New=[@Defn2{Term=[full constant declaration], Sec=(corresponding to a formal object of mode @key[in])}],Old=[]} @Defn2{Term=[stand-alone constant], Sec=(corresponding to a formal object of mode @key[in])} @PDefn{stand-alone object} In an instance, a @nt{formal_object_declaration} of mode @key{in} @Chg{Version=[2],New=[is a @i<full constant declaration> and ], Old=[]}declares a new stand-alone constant object whose initialization expression is the actual, whereas a @nt{formal_object_declaration} of mode @key{in out} declares a view whose properties are identical to those of the actual. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} These rules imply that generic formal objects of mode @key{in} are passed by copy@Chg{Version=[2],New=[ (or are built-in-place for a limited type)],Old=[]}, whereas generic formal objects of mode @key{in out} are passed by reference. Initialization and finalization happen for the constant declared by a @nt{formal_object_declaration} of mode @key{in} as for any constant; see @RefSec{Object Declarations} and @RefSec{User-Defined Assignment and Finalization}. @PDefn2{Term=[subtype], Sec=(of a generic formal object)} In an instance, the subtype of a generic formal object of mode @key{in} is as for the equivalent constant. In an instance, the subtype of a generic formal object of mode @key{in out} is the subtype of the corresponding generic actual. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(generic_association for a formal object of mode @key{in})} @Defn2{Term=[assignment operation], Sec=(during evaluation of a @nt{generic_association} for a formal object of mode @key{in})} For the evaluation of a @nt{generic_association} for a formal object of mode @key{in}, a constant object is created, the value of the actual parameter is converted to the nominal subtype of the formal object, and assigned to the object@Redundant[, including any value adjustment @em see @RefSecNum{User-Defined Assignment and Finalization}]. @PDefn2{Term=[implicit subtype conversion],Sec=(generic formal object of mode @key[in])} @begin{Ramification} This includes evaluating the actual and doing a subtype conversion, which might raise an exception. @end{Ramification} @begin{Discussion} The rule for evaluating a @nt<generic_association> for a formal object of mode @key{in out} is covered by the general Dynamic Semantics rule in @RefSecNum{Generic Instantiation}. @end{Discussion} @end{RunTime} @begin{Notes} The constraints that apply to a generic formal object of mode @key{in out} are those of the corresponding generic actual parameter (not those implied by the @nt{subtype_mark} that appears in the @nt{formal_object_declaration}). Therefore, to avoid confusion, it is recommended that the name of a first subtype be used for the declaration of such a formal object. @begin{Ramification} Constraint checks are done at instantiation time for formal objects of mode @key{in}, but not for formal objects of mode @key{in out}. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, it is forbidden to pass a (nongeneric) formal parameter of mode @key{out}, or a subcomponent thereof, to a generic formal object of mode @key{in out}. This restriction is removed in Ada 95. @end{Extend83} @begin{DiffWord83} We make @lquotes@;@nt{mode}@rquotes@; explicit in the syntax. RM83 refers to the mode without saying what it is. This is also more uniform with the way (nongeneric) formal parameters are defined. We considered allowing mode @key{out} in Ada 95, for uniformity with (nongeneric) formal parameters. The semantics would be identical for modes @key{in out} and @key{out}. (Note that generic formal objects of mode @key{in out} are passed by reference. Note that for (nongeneric) formal parameters that are allowed to be passed by reference, the semantics of @key{in out} and @key{out} is the same. The difference might serve as documentation. The same would be true for generic formal objects, if @key{out} were allowed, so it would be consistent.) We decided not to make this change, because it does not produce any important benefit, and any change has some cost. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A generic formal @key{in} object can have a limited type. The actual for such an object must be built-in-place via a @nt{function_call} or @nt{aggregate}, see @RefSecNum{Limited Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[A generic formal object can have a @nt{null_exclusion} or an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00255-01]} @ChgAdded{Version=[2],Text=[Clarified that the nominal subtype of a composite formal @key{in out} object is unconstrained if the first subtype of the type is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[Clarified that a formal @key{in} object can be static when referenced from outside of the instance (by declaring such an object to be a full constant declaration).]} @end{DiffWord95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{Formal Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @redundant[A generic formal subtype can be used to pass to a generic unit a subtype whose type is in a certain @Chg{Version=[2],New=[category], Old=[class]} of types.] @begin{Reason} We considered having intermediate syntactic categories @ntf{formal_integer_type_definition}, @ntf{formal_real_type_definition}, and @ntf{formal_fixed_point_definition}, to be more uniform with the syntax rules for non-generic-formal types. However, that would make the rules for formal types slightly more complicated, and it would cause confusion, since @nt{formal_discrete_type_definition} would not fit into the scheme very well. @end{Reason} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_type_declaration>,rhs=" @key{type} @Syn2{defining_identifier}[@Syn2{discriminant_part}] @key{is} @Syn2{formal_type_definition};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Syn{lhs=<formal_type_definition>,rhs=" @Syn2{formal_private_type_definition} | @Syn2{formal_derived_type_definition} | @Syn2{formal_discrete_type_definition} | @Syn2{formal_signed_integer_type_definition} | @Syn2{formal_modular_type_definition} | @Syn2{formal_floating_point_definition} | @Syn2{formal_ordinary_fixed_point_definition} | @Syn2{formal_decimal_fixed_point_definition} | @Syn2{formal_array_type_definition} | @Syn2{formal_access_type_definition}@Chg{Version=[2],New=[ | @Syn2{formal_interface_type_definition}],Old=[]}"} @end{Syntax} @begin{Legality} @Defn{generic actual subtype} @Defn{actual subtype} @Defn{generic actual type} @Defn{actual type} For a generic formal subtype, the actual shall be a @nt{subtype_mark}; it denotes the @i{(generic) actual subtype}. @begin{Ramification} When we say simply @lquotes@;formal@rquotes@; or @lquotes@;actual@rquotes@; (for a generic formal that denotes a subtype) we're talking about the subtype, not the type, since a name that denotes a @nt{formal_type_declaration} denotes a subtype, and the corresponding actual also denotes a subtype. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{generic formal type} @Defn{formal type} @Defn{generic formal subtype} @Defn{formal subtype} A @nt{formal_type_declaration} declares a @i{(generic) formal type}, and its first subtype, the @i{(generic) formal subtype}. @begin{Ramification} A subtype (other than the first subtype) of a generic formal type is not a generic formal subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[@Defn{determined category for a formal type} @Defn{category determined for a formal type}], Old=[@Defn{determined class for a formal type} @Defn{class determined for a formal type}]} The form of a @nt{formal_type_definition} @i{determines a @Chg{Version=[2],New=[category (of types)],Old=[class]}} to which the formal type belongs. For a @nt{formal_private_type_definition} the reserved words @key{tagged} and @key{limited} indicate the @Chg{Version=[2],New=[category of types],Old=[class]} (see @RefSecNum{Formal Private and Derived Types}). For a @nt{formal_derived_type_definition} the @Chg{Version=[2],New=[category of types],Old=[class]} is the derivation class rooted at the ancestor type. For other formal types, the name of the syntactic category indicates the @Chg{Version=[2],New=[category of types],Old=[class]}; a @nt{formal_discrete_type_definition} defines a discrete type, and so on. @begin{Reason} This rule is clearer with the flat syntax rule for @nt{formal_type_definition} given above. Adding @ntf{formal_integer_type_definition} and others would make this rule harder to state clearly. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We use @lquotes@;category@rquote rather than @lquotes@;class@rquotes above, because the requirement that classes are closed under derivation is not important here. Moreover, there are interesting categories that are not closed under derivation. For instance, limited and interface are categories that do not form classes.]} @end{Reason} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The actual type shall be in the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} For example, if the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal is the @Chg{Version=[2],New=[category],Old=[class]} of all discrete types, then the actual has to be discrete. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Note that this rule does not require the actual to belong to every @Chg{Version=[2],New=[category],Old=[class]} to which the formal belongs. For example, formal private types are in the @Chg{Version=[2],New=[category],Old=[class]} of composite types, but the actual need not be composite. Furthermore, one can imagine an infinite number of @Chg{Version=[2], New=[categories],Old=[classes]} that are just arbitrary sets of types @Chg{Version=[2],New=[],Old=[that obey the closed-under-derivation rule, and are therefore technically classes]} (even though we don't give them names, since they are uninteresting). We don't want this rule to apply to @i{those} @Chg{Version=[2],New=[categories],Old=[classes]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01],ARef=[AI95-00442-01]} @lquotes@;Limited@rquotes@; is not @Chg{Version=[2],New=[an],Old=[a]} @lquotes@;interesting@rquotes@; @Chg{Version=[2],New=[category],Old=[class]}, but @lquotes@;nonlimited@rquotes@; is; it is legal to pass a nonlimited type to a limited formal type, but not the other way around. The reserved word @Chg{Version=[2],New=[@key[limited]],Old=[@ntf{limited}]} really represents a @Chg{Version=[2],New=[category],Old=[class]} containing both limited and nonlimited types. @lquotes@;Private@rquotes@; is not a @Chg{Version=[2],New=[category for this purpose], Old=[class]}; a generic formal private type accepts both private and nonprivate actual types. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} It is legal to pass a class-wide subtype as the actual if it is in the right @Chg{Version=[2],New=[category],Old=[class]}, so long as the formal has unknown discriminants. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0037],ARef=[AI95-00043-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01],ARef=[AI95-00442-01]} @Redundant[The formal type also belongs to each @Chg{Version=[2],New=[category],Old=[class]} that contains the determined @Chg{Version=[2],New=[category],Old=[class]}.] The primitive subprograms of the type are as for any type in the determined @Chg{Version=[2],New=[category],Old=[class]}. For a formal type other than a formal derived type, these are the predefined operators of the type@Chg{New=[. For an elementary formal type, the predefined operators are implicitly declared immediately after the declaration of the formal type. For a composite formal type, the predefined operators are implicitly declared either immediately after the declaration of the formal type, or later @Chg{Version=[2],New=[immediately within the declarative region in which the type is declared],Old=[in its immediate scope]} according to the rules of @RefSecNum(Private Operations).], Old=[; they are implicitly declared immediately after the declaration of the formal type.]} In an instance, the copy of such an implicit declaration declares a view of the predefined operator of the actual type, even if this operator has been overridden for the actual type. @Redundant[The rules specific to formal derived types are given in @RefSecNum{Formal Private and Derived Types}.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} All properties of the type are as for any type in the @Chg{Version=[2],New=[category],Old=[class]}. Some examples: The primitive operations available are as defined by the language for each @Chg{Version=[2],New=[category],Old=[class]}. The form of @nt{constraint} applicable to a formal type in a @nt{subtype_indication} depends on the @Chg{Version=[2],New=[category],Old=[class]} of the type as for a nonformal type. The formal type is tagged if and only if it is declared as a tagged private type, or as a type derived from a (visibly) tagged type. (Note that the actual type might be tagged even if the formal type is not.) @end{Ramification} @end{StaticSem} @begin{Notes} Generic formal types, like all types, are not named. Instead, a @nt{name} can denote a generic formal subtype. Within a generic unit, a generic formal type is considered as being distinct from all other (formal or nonformal) types. @begin{TheProof} This follows from the fact that each @nt{formal_type_declaration} declares a type. @end{TheProof} A @nt{discriminant_part} is allowed only for certain kinds of types, and therefore only for certain kinds of generic formal types. See @RefSecNum{Discriminants}. @begin{Ramification} The term @lquotes@;formal floating point type@rquotes@; refers to a type defined by a @nt{formal_floating_point_definition}. It does not include a formal derived type whose ancestor is floating point. Similar terminology applies to the other kinds of @nt{formal_type_definition}. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic formal types:} @begin{Example} @key[type] Item @key[is] @key[private]; @key[type] Buffer(Length : Natural) @key[is] @key[limited] @key[private]; @key[type] Enum @key[is] (<>); @key[type] Int @key[is] @key[range] <>; @key[type] Angle @key[is] @key[delta] <>; @key[type] Mass @key[is] @key[digits] <>; @key[type] Table @key[is] @key[array] (Enum) @key[of] Item; @end{Example} @begin{Wide} @leading@keepnext@i{Example of a generic formal part declaring a formal integer type:} @end{Wide} @begin{Example} @key[generic] @key[type] Rank @key[is] @key[range] <>; First : Rank := Rank'First; Second : Rank := First + 1; --@RI{ the operator "+" of the type Rank } @end{Example} @end{Examples} @begin{DiffWord83} RM83 has separate sections @lquotes@;Generic Formal Xs@rquotes@; and @lquotes@;Matching Rules for Formal Xs@rquotes@; (for various X's) with most of the text redundant between the two. We have combined the two in order to reduce the redundancy. In RM83, there is no @lquotes@;Matching Rules for Formal Types@rquotes@; section; nor is there a @lquotes@;Generic Formal Y Types@rquotes@; section (for Y = Private, Scalar, Array, and Access). This causes, for example, the duplication across all the @lquotes@;Matching Rules for Y Types@rquotes@; sections of the rule that the actual passed to a formal type shall be a subtype; the new organization avoids that problem. The matching rules are stated more concisely. We no longer consider the multiplying operators that deliver a result of type @i{universal_fixed} to be predefined for the various types; there is only one of each in package Standard. Therefore, we need not mention them here as RM83 had to. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0037],ARef=[AI95-00043-01],ARef=[AI95-00233-01]} @ChgAdded{Version=[2],Text=[Corrigendum 1 corrected the wording to properly define the location where operators are defined for formal array types. The wording here was inconsistent with that in @RefSec{Private Operations}. For the Amendment, this wording was corrected again, because it didn't reflect the Corrigendum 1 revisions in @RefSecNum{Private Operations}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Formal interface types are defined; see @RefSec{Formal Interface Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We use @lquotes@;determines a category@rquotes rather than class, since not all interesting properties form a class.]} @end{DiffWord95} @LabeledSubClause{Formal Private and Derived Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Redundant[@Chg{Version=[2],New=[In its most general form, the category], Old=[The class]} determined for a formal private type @Chg{Version=[2],New=[is all types, but it can be restricted to only nonlimited types or to only tagged types], Old=[can be either limited or nonlimited, and either tagged or untagged; no more specific class is known for such a type]}. The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal derived type is the derivation class rooted at the ancestor type.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The first rule is given normatively below, and the second rule is given normatively in @RefSecNum{Formal Types}; they are repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_private_type_definition>, rhs="[[@key{abstract}] @key{tagged}] [@key{limited}] @key{private}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Syn{lhs=<formal_derived_type_definition>, rhs="@Chg{Version=[2],New=[ ],Old=[]}[@key{abstract}] @Chg{Version=[2],New=<[@key{limited} | @key{synchronized}] >,Old=[]}@key{new} @Syn2{subtype_mark} [@Chg{Version=[2],New=<[@key{and} @Syn2{interface_list}]>,Old=<>}@key{with} @key{private}]"} @end{Syntax} @begin{Legality} If a generic formal type declaration has a @nt{known_discriminant_part}, then it shall not include a @nt{default_expression} for a discriminant. @begin{Ramification} Consequently, a generic formal subtype with a @nt{known_discriminant_part} is an indefinite subtype, so the declaration of a stand-alone variable has to provide a constraint on such a subtype, either explicitly, or by its initial value. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Defn2{Term=[ancestor subtype], Sec=(of a formal derived type)} @PDefn{private extension} The @i(ancestor subtype) of a formal derived type is the subtype denoted by the @nt<subtype_mark> of the @nt<formal_derived_type_definition>. For a formal derived type declaration, the reserved words @key{with private} shall appear if and only if the ancestor type is a tagged type; in this case the formal derived type is a private extension of the ancestor type and the ancestor shall not be a class-wide type. @Redundant[Similarly, @Chg{Version=[2],New=[an @nt{interface_list} or ],Old=[]} the optional reserved @Chg{Version=[2],New=[words],Old=[word]} @key{abstract} @Chg{Version=[2],New=[or @key{synchronized} ],Old=[]}shall appear only if the ancestor type is a tagged type].@Chg{Version=[2], New=[ The reserved word @key{limited} or @key{synchronized} shall appear only if the ancestor type @Redundant[and any progenitor types] are limited types. The reserved word @key{synchronized} shall appear (rather than @key{limited}) if the ancestor type or any of the progenitor types are synchronized interfaces.],Old=[]} @begin{Reason} We use the term @lquotes@;ancestor@rquotes@; here instead of @lquotes@;parent@rquotes@; because the actual can be any descendant of the ancestor, not necessarily a direct descendant. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[We require the ancestor type to be limited when @key{limited} appears so that we avoid oddies like limited integer types. Normally, @key{limited} means @lquotes@;match anything@rquotes for a generic formal, but it was felt that allowing limited elementary types to be declared was just too weird. Integer still matches a formal limited private type; it is only a problem when the type is known to be elementary. Note that the progenitors are required to be limited by rules in @RefSecNum{Interface Types}, thus that part of the rule is redundant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[We require that @key{synchronized} appear if the ancestor or any of the progenitors are synchronized, so that property is explicitly given in the program text @en it is not automatically inherited from the ancestors. However, it can be given even if neither the ancestor nor the progenitors are synchronized.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[The actual type for a formal derived type shall be a descendant of @Redundant[the ancestor type and] every progenitor of the formal type. If the reserved word @key[synchronized] appears in the declaration of the formal derived type, the actual type shall be a synchronized tagged type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual type has to be a descendant of the ancestor type, in order that it be in the correct class. Thus, that part of the rule is redundant.]} @end{TheProof} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For a non-formal private extension, we require the partial view to be synchronized if the full view is synchronized tagged. This does not apply to a formal private extension @em it is OK if the formal is not synchronized. Any attempt to extend the formal type will be rechecked in the instance, where the rule disallowing extending a sychronized non-interface type will be enforced. This is consistent with the @lquotes@;no hidden interfaces@rquotes rule also applying only to non-formal private extensions, as well as the rule that a limited non-formal private extension implies a limited full type. Formal private extensions are exempted from all these rules to enable the construction of generics that can be used with the widest possible range of types. In particular, an indefinite tagged limited formal private type can match any @lquotes@;concrete@rquotes actual tagged type.]} @end{Discussion} If the formal subtype is definite, then the actual subtype shall also be definite. @begin{Ramification} On the other hand, for an indefinite formal subtype, the actual can be either definite or indefinite. @end{Ramification} @leading@;For a generic formal derived type with no @nt<discriminant_part>: @begin(Itemize) If the ancestor subtype is constrained, the actual subtype shall be constrained, and shall be statically compatible with the ancestor; @begin{Ramification} In other words, any constraint on the ancestor subtype is considered part of the @lquotes@;contract.@rquotes@; @end{Ramification} If the ancestor subtype is an unconstrained access or composite subtype, the actual subtype shall be unconstrained. @begin{Reason} This rule ensures that if a composite constraint is allowed on the formal, one is also allowed on the actual. If the ancestor subtype is an unconstrained scalar subtype, the actual is allowed to be constrained, since a scalar constraint does not cause further constraints to be illegal. @end{Reason} If the ancestor subtype is an unconstrained discriminated subtype, then the actual shall have the same number of discriminants, and each discriminant of the actual shall correspond to a discriminant of the ancestor, in the sense of @RefSecNum{Discriminants}. @begin{Reason} This ensures that if a discriminant constraint is given on the formal subtype, the corresponding constraint in the instance will make sense, without additional run-time checks. This is not necessary for arrays, since the bounds cannot be overridden in a type extension. An @nt<unknown_discriminant_part> may be used to relax these matching requirements. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If the ancestor subtype is an access subtype, the actual subtype shall exclude null if and only if the ancestor subtype excludes null.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require that the @lquotes@;excludes null@rquotes property match, because it would be difficult to write a correct generic for a formal access type without knowing this property. Many typical algorithms and techniques will not work for a subtype that excludes null (setting an unused component to @key{null}, default-initialized objects, and so on). We want this sort of requirement to be reflected in the contract of the generic.]} @end{Reason} @end(Itemize) @Leading@;The declaration of a formal derived type shall not have a @nt{known_discriminant_part}. For a generic formal private type with a @nt{known_discriminant_part}: @begin{Itemize} The actual type shall be a type with the same number of discriminants. The actual subtype shall be unconstrained. The subtype of each discriminant of the actual type shall statically match the subtype of the corresponding discriminant of the formal type. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Reason} We considered defining the first and third rule to be called @lquotes@;subtype conformance@rquotes@; for @nt{discriminant_part}s. We rejected that idea, because it would require implicit (inherited) @nt{discriminant_part}s, which seemed like too much mechanism. @end{Reason} @end{Itemize} @Redundant[For a generic formal type with an @nt{unknown_discriminant_part}, the actual may, but need not, have discriminants, and may be definite or indefinite.] @end{Legality} @begin{StaticSem} @leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal private type is as follows: @ChgRef{Version=[2],Kind=[Revised]} @TabClear{}@Tabset(P32) @begin{Display} @i(Type Definition) @\@i(Determined @Chg{Version=[2],New=[Category],Old=[Class]})@* @key{limited private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all types @key{private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all nonlimited types @key{tagged limited private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all tagged types @key{tagged private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all nonlimited tagged types @end{Display} @Redundant[The presence of the reserved word @key{abstract} determines whether the actual type may be abstract.] A formal private or derived type is a private or derived type, respectively. A formal derived tagged type is a private extension. @Redundant[A formal private or derived type is abstract if the reserved word @key(abstract) appears in its declaration.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01]} If the ancestor type is a composite type that is not an array type, the formal type inherits components from the ancestor type (including discriminants if a new @nt<discriminant_part> is not specified), as for a derived type defined by a @nt<derived_type_definition> (see @RefSecNum(Derived Types and Classes)@Chg{Version=[2],New=[ and @RefSecNum{Private Operations}],Old=[]}). @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0038],ARef=[AI95-00202]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01],ARef=[AI95-00401-01]} For a formal derived type, the predefined operators and inherited user-defined subprograms are determined by the ancestor type@Chg{Version=[2],New=[ and any progenitor types],Old=[]}, and are implicitly declared at the earliest place, if any, @Chg{Version=[2],New=[immediately within the declarative region in which], Old=[within the immediate scope of]} the formal type@Chg{Version=[2],New=[ is declared],Old=[]}, where the corresponding primitive subprogram of the ancestor @Chg{Version=[2],New=[or progenitor ],Old=[]}is visible (see @RefSecNum{Private Operations}). In an instance, the copy of such an implicit declaration declares a view of the corresponding primitive subprogram of the ancestor@Chg{New=[@Chg{Version=[2], New=[ or progenitor],Old=[]} of the formal derived type],Old=[]}, even if this primitive has been overridden for the actual type. @Chg{New=[When the ancestor@Chg{Version=[2], New=[ or progenitor],Old=[]} of the formal derived type is itself a formal type, the copy of the implicit declaration declares a view of the corresponding copied operation of the ancestor@Chg{Version=[2], New=[ or progenitor],Old=[]}.],Old=[]} @Redundant[In the case of a formal private extension, however, the tag of the formal type is that of the actual type, so if the tag in a call is statically determined to be that of the formal type, the body executed will be that corresponding to the actual type.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} The above rule defining the properties of primitive subprograms in an instance applies even if the subprogram has been overridden or hidden for the actual type. This rule is necessary for untagged types, because their primitive subprograms might have been overridden by operations that are not subtype-conformant with the operations defined for the class. For tagged types, the rule still applies, but the primitive subprograms will dispatch to the appropriate implementation based on the type and tag of the operands. Even for tagged types, the formal parameter names and @nt{default_expression}s are determined by those of the primitive subprograms of the specified ancestor type@Chg{Version=[2],New=[ (or progenitor type, for subprograms inherited from an interface type)],Old=[]}. @end{Ramification} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} S that denotes a formal indefinite subtype]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<S>, AttrName=<Definite>, Text=[S'Definite yields True if the actual subtype corresponding to S is definite; otherwise it yields False. The value of this attribute is of the predefined type Boolean.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Whether an actual subtype is definite or indefinite may have a major effect on the algorithm used in a generic. For example, in a generic I/O package, whether to use fixed-length or variable-length records could depend on whether the actual is definite or indefinite. This attribute is essentially a replacement for the Constrained attribute@Chg{Version=[2],New=[,],Old=[]} which is now considered obsolete. @end{Discussion} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case where a formal type is tagged with unknown discriminants, and the actual type is a class-wide type @i<T>'Class:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[For the purposes of defining the primitive operations of the formal type, each of the primitive operations of the actual type is considered to be a subprogram (with an intrinsic calling convention @em see @RefSecNum{Conformance Rules}) whose body consists of a dispatching call upon the corresponding operation of @i<T>, with its formal parameters as the actual parameters. If it is a function, the result of the dispatching call is returned.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[If the corresponding operation of @i<T> has no controlling formal parameters, then the controlling tag value is determined by the context of the call, according to the rules for tag-indeterminate calls (see @RefSecNum{Dispatching Operations of Tagged Types} and @RefSecNum{Assignment Statements}). In the case where the tag would be statically determined to be that of the formal type, the call raises Program_Error. If such a function is renamed, any call on the renaming raises Program_Error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As it states in @RefSecNum{Conformance Rules}, the convention of an inherited subprogram of a generic formal tagged type with unknown discriminants is intrinsic.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case of a corresponding primitive of T with no controlling formal parameters, the context of the call provides the controlling tag value for the dispatch. If no tag is provided by context, Program_Error is raised rather than resorting to a nondispatching call. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} NT(<>) @key{is new} T @key{with private}; -- @RI[Assume T has operation "]@key{function} Empty @key{return} T;@RI["] @key{package} G @key{is} @key{procedure} Test(X : @key{in out} NT); @key{end} G;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} G @key{is} @key{procedure} Test(X : @key{in out} NT) @key{is} @key{begin} X := Empty; -- @RI[Dispatching based on X'Tag takes] -- @RI[place if actual is class-wide.] @key{declare} Y : NT := Empty; -- @RI[If actual is class-wide, this raises Program_Error] -- @RI[as there is no tag provided by context.] @key{begin} X := Y; -- @RI[We never get this far.] @key{end}; @key{end} Test; @key{end} G;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} T1 @key{is new} T @key{with null record}; @key{package} I @key{is new} G(T1'Class);]} @end{Example} @end{Discussion} @end{RunTime} @begin{Notes} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} In accordance with the general rule that the actual type shall belong to the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal (see @RefSec(Formal Types)): @begin(itemize) If the formal type is nonlimited, then so shall be the actual; For a formal derived type, the actual shall be in the class rooted at the ancestor subtype. @end(itemize) The actual type can be abstract only if the formal type is abstract (see @RefSecNum{Abstract Types and Subprograms}). @begin{Reason} This is necessary to avoid contract model problems, since one or more of its primitive subprograms are abstract; it is forbidden to create objects of the type, or to declare functions returning the type. @end{Reason} @begin{Ramification} On the other hand, it is OK to pass a non-abstract actual to an abstract formal @em @key[abstract] on the formal indicates that the actual might be abstract. @end{Ramification} If the formal has a @nt{discriminant_part}, the actual can be either definite or indefinite. Otherwise, the actual has to be definite. @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Ada 83 does not have @nt{unknown_discriminant_part}s, so it allows indefinite subtypes to be passed to definite formals, and applies a legality rule to the instance body. This is a contract model violation. Ada 95 disallows such cases at the point of the instantiation. The workaround is to add (<>) as the @nt{discriminant_part} of any formal subtype if it is intended to be used with indefinite actuals. If that's the intent, then there can't be anything in the generic body that would require a definite subtype. The check for discriminant subtype matching is changed from a run-time check to a compile-time check. @end{Incompatible83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A generic formal derived type can include progenitors (interfaces) as well as a primary ancestor. It also may include @key{limited} to indicate that it is a limited type, and @key{synchronized} to indicate that it is a synchronized type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0038],ARef=[AI95-00202-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected wording to define the operations that are inherited when the ancestor of a formal type is itself a formal type to avoid anomalies.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[Added a semantic description of the meaning of operations of an actual class-wide type, as such a type does not have primitive operations of its own.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a matching rule for access subtypes that exclude null.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00233-01]} @ChgAdded{Version=[2],Text=[The wording for the declaration of implicit operations is corrected to be consistent with @RefSecNum{Private Operations} as modified by Corrigendum 1.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @LabeledSubClause{Formal Scalar Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} A @i{formal scalar type} is one defined by any of the @nt{formal_type_definition}s in this subclause. @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal scalar type is @Chg{Version=[2],New=[the category of all ],Old=[]}discrete, signed integer, modular, floating point, ordinary fixed point, or decimal@Chg{Version=[2],New=[ types],Old=[]}.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The second rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The @lquotes@;category of a type@rquotes includes any classes that the type belongs to.]} @end{Ramification} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_discrete_type_definition>,rhs="(<>)"} @Syn{lhs=<formal_signed_integer_type_definition>,rhs="@key{range} <>"} @Syn{lhs=<formal_modular_type_definition>,rhs="@key{mod} <>"} @Syn{lhs=<formal_floating_point_definition>,rhs="@key{digits} <>"} @Syn{lhs=<formal_ordinary_fixed_point_definition>,rhs="@key{delta} <>"} @Syn{lhs=<formal_decimal_fixed_point_definition>,rhs="@key{delta} <> @key{digits} <>"} @end{Syntax} @begin{Legality} The actual type for a formal scalar type shall not be a nonstandard numeric type. @begin{Reason} This restriction is necessary because nonstandard numeric types have some number of restrictions on their use, which could cause contract model problems in a generic body. Note that nonstandard numeric types can be passed to formal derived and formal private subtypes, assuming they obey all the other rules, and assuming the implementation allows it (being nonstandard means the implementation might disallow anything). @end{Reason} @end{Legality} @begin{Notes} The actual type shall be in the class of types implied by the syntactic category of the formal type definition (see @RefSec(Formal Types)). For example, the actual for a @nt<formal_modular_type_definition> shall be a modular type. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @LabeledSubClause{Formal Array Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal array type is the @Chg{Version=[2],New=[category],Old=[class]} of all array types.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_array_type_definition>,rhs="@Syn2{array_type_definition}"} @end{Syntax} @begin{Legality} The only form of @nt{discrete_subtype_definition} that is allowed within the declaration of a generic formal (constrained) array subtype is a @nt{subtype_mark}. @begin{Reason} The reason is the same as for forbidding @nt{constraint}s in @nt{subtype_indication}s (see @RefSecNum{Generic Declarations}). @end{Reason} @Leading@;For a formal array subtype, the actual subtype shall satisfy the following conditions: @begin{Itemize} The formal array type and the actual array type shall have the same dimensionality; the formal subtype and the actual subtype shall be either both constrained or both unconstrained. For each index position, the index types shall be the same, and the index subtypes (if unconstrained), or the index ranges (if constrained), shall statically match (see @RefSecNum{Statically Matching Constraints and Subtypes}). @PDefn2{Term=[statically matching],Sec=(required)} The component subtypes of the formal and actual array types shall statically match. @PDefn2{Term=[statically matching],Sec=(required)} If the formal type has aliased components, then so shall the actual. @begin{Ramification} On the other hand, if the formal's components are not aliased, then the actual's components can be either aliased or not. @end{Ramification} @end{Itemize} @end{Legality} @begin{Examples} @Leading@Keepnext@i{Example of formal array types:} @begin{Example} --@RI{ given the generic package } @key[generic] @key[type] Item @key[is] @key[private]; @key[type] Index @key[is] (<>); @key[type] Vector @key[is] @key[array] (Index @key[range] <>) @key[of] Item; @key[type] Table @key[is] @key[array] (Index) @key[of] Item; @key[package] P @key[is] ... @key[end] P; --@RI{ and the types } @key[type] Mix @key[is] @key[array] (Color @key[range] <>) @key[of] Boolean; @key[type] Option @key[is] @key[array] (Color) @key[of] Boolean; --@RI{ then Mix can match Vector and Option can match Table } @key[package] R @key[is] @key[new] P(Item => Boolean, Index => Color, Vector => Mix, Table => Option); --@RI{ Note that Mix cannot match Table and Option cannot match Vector} @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The check for matching of component subtypes and index subtypes or index ranges is changed from a run-time check to a compile-time check. The Ada 83 rule that @lquotes@;If the component type is not a scalar type, then the component subtypes shall be either both constrained or both unconstrained@rquotes@; is removed, since it is subsumed by static matching. Likewise, the rules requiring that component types be the same is subsumed. @end{Incompatible83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledSubClause{Formal Access Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal access type is the @Chg{Version=[2],New=[category],Old=[class]} of all access types.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_access_type_definition>,rhs="@Syn2{access_type_definition}"} @end{Syntax} @begin{Legality} For a formal access-to-object type, the designated subtypes of the formal and actual types shall statically match. @PDefn2{Term=[statically matching],Sec=(required)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} If and only if the @nt{general_access_modifier} @key{constant} applies to the formal, the actual shall be an access-to-constant type. If the @nt{general_access_modifier} @key{all} applies to the formal, then the actual shall be a general access-to-variable type (see @RefSecNum{Access Types}).@Chg{Version=[2],New=[ If and only if the formal subtype excludes null, the actual subtype shall exclude null.],Old=[]} @begin{Ramification} If no @ntf{_modifier} applies to the formal, then the actual type may be either a pool-specific or a general access-to-variable type. @end{Ramification} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0109],ARef=[AI95-00025-01]} @ChgAdded{Version=[1],Text=[Matching an access-to-variable to a formal access-to-constant type cannot be allowed. If it were allowed, it would be possible to create an access-to-variable value designating a constant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[We require that the @lquotes@;excludes null@rquotes property match, because it would be difficult to write a correct generic for a formal access type without knowing this property. Many typical algorithms and techniques will not work for a subtype that excludes null (setting an unused component to @key{null}, default-initialized objects, and so on). Even Ada.Unchecked_Deallocation would fail for a subtype that excludes null. Most generics would end up with comments saying that they are not intended to work for subtypes that exclude null. We would rather that this sort of requirement be reflected in the contract of the generic.]} @end{Reason} For a formal access-to-subprogram subtype, the designated profiles of the formal and the actual shall be mode-conformant, and the calling convention of the actual shall be @i{protected} if and only if that of the formal is @i{protected}. @Defn2{Term=[mode conformance],Sec=(required)} @begin{Reason} We considered requiring subtype conformance here, but mode conformance is more flexible, given that there is no way in general to specify the convention of the formal. @end{Reason} @end{Legality} @begin{Examples} @Leading@keepnext@i{Example of formal access types:} @begin{Example} --@RI{ the formal types of the generic package } @key[generic] @key[type] Node @key[is] @key[private]; @key[type] Link @key[is] @key[access] Node; @key[package] P @key[is] ... @key[end] P; --@RI{ can be matched by the actual types } @key[type] Car; @key[type] Car_Name @key[is] @key[access] Car; @key[type] Car @key[is] @key[record] Pred, Succ : Car_Name; Number : License_Number; Owner : Person; @key[end] @key[record]; --@RI{ in the following generic instantiation } @key[package] R @key[is] @key[new] P(Node => Car, Link => Car_Name); @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The check for matching of designated subtypes is changed from a run-time check to a compile-time check. The Ada 83 rule that @lquotes@;If the designated type is other than a scalar type, then the designated subtypes shall be either both constrained or both unconstrained@rquotes@; is removed, since it is subsumed by static matching. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Formal access-to-subprogram subtypes and formal general access types are new concepts. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a matching rule for subtypes that exclude null.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Formal Interface Types]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Redundant[The category determined for a formal interface type is the category of all interface types.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Here we're taking advantage of our switch in terminology from @lquotes@;determined class@rquotes to @lquotes@;determined category@rquotes; by saying @lquotes@;category@rquotes rather than @lquotes@;class@rquotes, we require that any actual type be an interface type, not just some type derived from an interface type.]} @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_interface_type_definition>,Old=<>}>, rhs="@Chg{Version=[2],New=<@Syn2{interface_type_definition}>,Old=<>}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251],ARef=[AI95-00401]} @ChgAdded{Version=[2],Text=[The actual type shall be a descendant of every progenitor of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345]} @ChgAdded{Version=[2],Text=[The actual type shall be a limited, task, protected, or synchronized interface if and only if the formal type is also, respectively, a limited, task, protected, or synchronized interface.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require the kind of interface type to match exactly because without that it is almost impossible to properly implement the interface.]} @end{Discussion} @end{Legality} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key{type} Root_Work_Item @key{is tagged private};]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Managed_Task @key{is task interface}; @key{type} Work_Item(<>) @key{is new} Root_Work_Item @key{with private}; @key{package} Server_Manager @key{is} @key{task type} Server @key{is new} Managed_Task @key{with} @key{entry} Start(Data : @key{in out} Work_Item); @key{end} Server; @key{end} Server_Manager;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[This generic allows an application to establish a standard interface that all tasks need to implement so they can be managed appropriately by an application-specific scheduler.]} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01],ARef=[AI95-00401-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The formal interface type is new.]} @end{Extend95} @LabeledClause{Formal Subprograms} @begin{Intro} @redundant[@Defn{generic formal subprogram} @Defn{formal subprogram, generic} Formal subprograms can be used to pass callable entities to a generic unit.] @end{Intro} @begin{MetaRules} Generic formal subprograms are like renames of the @nt{explicit_generic_actual_parameter}. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} @Syn{lhs=<formal_subprogram_declaration>,rhs="@Chg{Version=[2], New=<@Syn2{formal_concrete_subprogram_declaration} | @Syn2{formal_abstract_subprogram_declaration}>, Old=<@key{with} @Syn2{subprogram_specification} [@key{is} @Syn2{subprogram_default}];>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_concrete_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< @key{with} @Syn2{subprogram_specification} [@key{is} @Syn2{subprogram_default}];>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_abstract_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< @key{with} @Syn2{subprogram_specification} @key{is abstract} [@Syn2{subprogram_default}];>,Old=<>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Syn{lhs=<subprogram_default>,rhs="@Syn2{default_name} | <>@Chg{Version=[2],New=< | @key{null}>,Old=<>}"} @Syn{lhs=<default_name>,rhs="@Syn2{name}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A @nt{subprogram_default} of @key{null} shall not be specified for a formal function or for a @nt{formal_abstract_subprogram_declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no null functions because the return value has to be constructed somehow. We don't allow null for abstract formal procedures, as the operation is dispatching. It doesn't seem appropriate (or useful) to say that the implementation of something is null in the formal type and all possible descendants of that type. This also would define a dispatching operation that doesn't correspond to a slot in the tag of the controlling type, which would be a new concept. Finally, additional rules would be needed to define the meaning of a dispatching null procedure (for instance, the convention of such a subprogram should be intrinsic, but that's not what the language says). It doesn't seem worth the effort.]} @end{Reason} @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(formal subprogram default_name)} The expected profile for the @nt<default_name>, if any, is that of the formal subprogram. @begin{Ramification} This rule, unlike others in this clause, is observed at compile time of the @nt{generic_declaration}. The evaluation of the @nt{default_name} takes place during the elaboration of each instantiation that uses the default, as defined in @RefSec{Generic Instantiation}. @end{Ramification} @PDefn2{Term=[expected profile], Sec=(formal subprogram actual)} For a generic formal subprogram, the expected profile for the actual is that of the formal subprogram. @end{Resolution} @begin{Legality} The profiles of the formal and any named default shall be mode-conformant. @Defn2{Term=[mode conformance],Sec=(required)} @begin{Ramification} This rule, unlike others in this clause, is checked at compile time of the @nt{generic_declaration}. @end{Ramification} The profiles of the formal and actual shall be mode-conformant. @Defn2{Term=[mode conformance],Sec=(required)} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a parameter or result subtype of a @nt{formal_subprogram_declaration} that has an explicit @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the actual matching the @nt{formal_subprogram_declaration} denotes a generic formal object of another generic unit @i{G}, and the instantiation containing the actual that occurs within the body of a generic unit @i{G} or within the body of a generic unit declared within the declarative region of the generic unit @i{G}, then the corresponding parameter or result type of the formal subprogram of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the corresponding parameter or result type of the actual matching the @nt{formal_subprogram_declaration} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of a parameter or result with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child generics) when the formal subtype excludes null implicitly.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[If a formal parameter of a @nt{formal_@!abstract_@!subprogram_@!declaration} is of a specific tagged type @i<T> or of an anonymous access type designating a specific tagged type @i<T>, @i<T> is called a @i<controlling type> of the @nt{formal_@!abstract_@!subprogram_@!declaration}. Similarly, if the result of a @nt{formal_@!abstract_@!subprogram_@!declaration} for a function is of a specific tagged type @i<T> or of an anonymous access type designating a specific tagged type @i<T>, @i<T> is called a controlling type of the @nt{formal_@!abstract_@!subprogram_@!declaration}. A @nt{formal_@!abstract_@!subprogram_@!declaration} shall have exactly one controlling type. @Defn2{Term=[controlling type],Sec=[of a @nt{formal_abstract_subprogram_declaration}]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The specific tagged type could be any of a formal tagged private type, a formal derived type, a formal interface type, or a normal tagged type. While the last case doesn't seem to be very useful, there isn't any good reason for disallowing it. This rule ensures that the operation is a dispatching operation of some type, and that we unambiguously know what that type is.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We informally call a subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} an @i{abstract formal subprogram}, but we do not use this term in normative wording. @Defn{abstract formal subprogram} (We do use it often in these notes.)]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The actual subprogram for a @nt{formal_@!abstract_@!subprogram_@!declaration} shall be a dispatching operation of the controlling type or of the actual type corresponding to the controlling type.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We mean the controlling type of the @nt{formal_@!abstract_@!subprogram_@!declaration}, of course. Saying that gets unwieldy and redundant (so says at least one reviewer, anyway).]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This means that the actual is either a primitive operation of the controlling type, or an abstract formal subprogram. Also note that this prevents the controlling type from being class-wide (with one exception explained below), as only specific types have primitive operations (and a formal subprogram eventually has to have an actual that is a primitive of some type). This could happen in a case like:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T(<>) @key{is tagged private}; @key{with procedure} Foo (Obj : @key{in} T) @key{is abstract}; @key{package} P ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} New_P @key{is new} P (Something'Class, Some_Proc);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The instantiation here is always illegal, because Some_Proc could never be a primitive operation of Something'Class (there are no such operations). That's good, because we want calls to Foo always to be dispatching calls.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Since it is possible for a formal tagged type to be instantiated with a class-wide type, it is possible for the (real) controlling type to be class-wide in one unusual case:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} NT(<>) @key{is new} T @key{with private}; -- @RI[Presume that T has the following primitive operation:] -- @key{with procedure} Bar (Obj : @key{in} T); @key{package} Gr ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Gr @key{is} @key{package} New_P2 @key{is new} P (NT, Foo => Bar); @key{end} Gr;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} New_Gr @key{is new} Gr (Something'Class);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The instantiation of New_P2 is legal, since Bar is a dispatching operation of the actual type of the controlling type of the abstract formal subprogram Foo. This is not a problem, since the rules given in @RefSecNum{Formal Private and Derived Types} explain how this routine dispatches even though its parameter is class-wide.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that this legality rule never needs to be rechecked in an instance (that contains a nested instantiation). The rule only talks about the actual type of the instantiation; it does not require looking further; if the actual type is in fact a formal type, we do not intend looking at the actual for that formal.]} @end{Ramification} @end{Legality} @begin{StaticSem} A @nt{formal_subprogram_declaration} declares a generic formal subprogram. The types of the formal parameters and result, if any, of the formal subprogram are those determined by the @nt<subtype_mark>s given in the @nt{formal_subprogram_declaration}; however, independent of the particular subtypes that are denoted by the @nt<subtype_mark>s, the nominal subtypes of the formal parameters and result, if any, are defined to be nonstatic, and unconstrained if of an array type @Redundant[(no applicable index constraint is provided in a call on a formal subprogram)]. In an instance, a @nt{formal_subprogram_declaration} declares a view of the actual. The profile of this view takes its subtypes and calling convention from the original profile of the actual entity, while taking the formal parameter @nt{name}s and @nt{default_@!expression}s from the profile given in the @nt{formal_@!subprogram_@!declaration}. The view is a function or procedure, never an entry. @begin{Discussion} This rule is intended to be the same as the one for renamings-as-declarations, where the @nt{formal_subprogram_declaration} is analogous to a renaming-as-declaration, and the actual is analogous to the renamed view. @end{Discussion} If a generic unit has a @nt<subprogram_default> specified by a box, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a usage name identical to the defining name of the formal. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[If a generic unit has a @nt{subprogram_default} specified by the reserved word @key{null}, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a null procedure having the profile given in the @nt{formal_@!subprogram_@!declaration}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} with a controlling type @i<T> is a dispatching operation of type @i<T>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This is necessary to trigger all of the dispatching operation rules. It otherwise would not be considered a dispatching operation, as formal subprograms are never primitive operations.]} @end{Reason} @end{StaticSem} @begin{Notes} The matching rules for formal subprograms state requirements that are similar to those applying to @nt{subprogram_renaming_declaration}s (see @RefSecNum{Subprogram Renaming Declarations}). In particular, the name of a parameter of the formal subprogram need not be the same as that of the corresponding parameter of the actual subprogram; similarly, for these parameters, @nt{default_expression}s need not correspond. The constraints that apply to a parameter of a formal subprogram are those of the corresponding formal parameter of the matching actual subprogram (not those implied by the corresponding @nt{subtype_mark} in the @ntf{_specification} of the formal subprogram). A similar remark applies to the result of a function. Therefore, to avoid confusion, it is recommended that the @nt{name} of a first subtype be used in any declaration of a formal subprogram. The subtype specified for a formal parameter of a generic formal subprogram can be any visible subtype, including a generic formal subtype of the same @nt{generic_formal_part}. A formal subprogram is matched by an attribute of a type if the attribute is a function with a matching specification. An enumeration literal of a given type matches a parameterless formal function whose result type is the given type. A @nt{default_name} denotes an entity that is visible or directly visible at the place of the @nt{generic_declaration}; a box used as a default is equivalent to a name that denotes an entity that is directly visible at the place of the @ntf{_instantiation}. @begin{TheProof} Visibility and name resolution are applied to the equivalent explicit actual parameter. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} The actual subprogram cannot be abstract@Chg{Version=[2],New=[ unless the formal subprogram is a @nt{formal_@!abstract_@!subprogram_@!declaration}], Old=[]} (see @RefSecNum{Abstract Types and Subprograms}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} is an abstract subprogram. All calls on a subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} must be dispatching calls. See @RefSecNum{Abstract Types and Subprograms}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A null procedure as a subprogram default has convention Intrinsic (see @RefSecNum{Conformance Rules}).]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This is an implicitly declared subprogram, so it has convention Intrinsic as defined in @RefSecNum{Conformance Rules}.]} @end{TheProof} @end{Notes} @begin{Examples} @Leading@Keepnext@i{Examples of generic formal subprograms:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[with] @key[function] "+"(X, Y : Item) @key[return] Item @key[is] <>; @key[with] @key[function] Image(X : Enum) @key[return] String @key[is] Enum'Image; @key[with] @key[procedure] Update @key[is] Default_Update;@Chg{Version=[2],New=[ @key[with] @key[procedure] Pre_Action(X : @key[in] Item) @key[is null]; --@RI[ defaults to no action] @key[with] @key[procedure] Write(S : @key[not null access] Root_Stream_Type'Class; Desc : Descriptor) @b<is abstract> Descriptor'Write; --@RI[ see @RefSecNum{Stream-Oriented Attributes}] --@RI[ Dispatching operation on Descriptor with default]],Old=[]} --@RI{ given the generic procedure declaration } @key[generic] @key[with] @key[procedure] Action (X : @key[in] Item); @key[procedure] Iterate(Seq : @key[in] Item_Sequence); --@RI{ and the procedure } @key[procedure] Put_Item(X : @key[in] Item); --@RI{ the following instantiation is possible } @key[procedure] Put_List @key[is] @key[new] Iterate(Action => Put_Item); @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{formal_abstract_subprogram_declaration} is new. It allows the passing of dispatching operations to generic units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[ The formal subprogram default of @key{null} is new. It allows the default of a generic procedure to do nothing, such as for passing a debugging routine.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[Added matching rules for @nt{null_exclusion}s.]} @end{Diffword95} @LabeledClause{Formal Packages} @begin{Intro} @redundant[@Defn{generic formal package} @Defn{formal package, generic} Formal packages can be used to pass packages to a generic unit. The @nt{formal_package_declaration} declares that the formal package is an instance of a given generic package. Upon instantiation, the actual package has to be an instance of that generic package.] @end{Intro} @begin{Syntax} @Syn{lhs=<formal_package_declaration>,rhs=" @key{with} @key{package} @Syn2{defining_identifier} @key{is} @key{new} @SynI{generic_package_}@Syn2{name} @Syn2{formal_package_actual_part};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @Syn{lhs=<formal_package_actual_part>,rhs=" @Chg{Version=[2],New=`([@key{others} =>] <>) | [@Syn2{generic_actual_part}] | (@Syn2{formal_package_association} {, @Syn2{formal_package_association}} [, @key{others} => <>])', Old=[(<>) | [@Syn2{generic_actual_part}]]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_package_association>,Old=<>}>, rhs="@Chg{Version=[2],New={ @Syn2{generic_association} | @SynI{generic_formal_parameter_}@Syn2{selector_name} => <>},Old={}}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[Any positional @nt{formal_package_association}s shall precede any named @nt{formal_package_association}s.]} @end{SyntaxText} @end{Syntax} @begin{Legality} @Defn2{Term=[template], Sec=(for a formal package)} The @i(generic_package_)@nt<name> shall denote a generic package (the @i(template) for the formal package); the formal package is an instance of the template. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00398-01]} @ChgAdded{Version=[2],Text=[A @nt<formal_package_actual_part> shall contain at most one @nt<formal_package_association> for each formal parameter. If the @nt<formal_package_actual_part> does not include @lquotes@key[others] => <>@rquotes, each formal parameter without an association shall have a @nt<default_expression> or @nt<subprogram_default>.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @Leading@;The actual shall be an instance of the template. If the @nt<formal_package_actual_part> is (<>)@Chg{Version=[2], New=[ or (@key{others} => <>)],Old=[]}, @Redundant[then the actual may be any instance of the template]; otherwise, @Chg{Version=[2],New=[certain of the actual parameters], Old=[each actual parameter]} of the actual instance shall match the corresponding actual @Chg{Version=[2],New=[parameters],Old=[parameter]} of the formal package@Chg{Version=[2],New=[, determined], Old=[ @Redundant[(whether the actual parameter is given explicitly or by default)],]} as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[If the @nt{formal_@!package_@!actual_@!part} includes @nt{generic_association}s as well as associations with <>, then only the actual parameters specified explicitly with @nt{generic_association}s are required to match;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[Otherwise, all actual parameters shall match@Redundant[, whether any actual parameter is given explicitly or by default].]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The rules for matching of actual parameters between the actual instance and the formal package are as follows:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} For a formal object of mode @key[in]@Chg{Version=[2],New=[,],Old=[]} the actuals match if they are static expressions with the same value, or if they statically denote the same constant, or if they are both the literal @key[null]. @begin{Reason} We can't simply require full conformance between the two actual parameter expressions, because the two expressions are being evaluated at different times. @end{Reason} For a formal subtype, the actuals match if they denote statically matching subtypes. @PDefn2{Term=[statically matching],Sec=(required)} For other kinds of formals, the actuals match if they statically denote the same entity. @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0039],ARef=[AI95-00213-01]} @ChgAdded{Version=[1],Text=[For the purposes of matching, any actual parameter that is the name of a formal object of mode @key{in} is replaced by the formal object's actual expression (recursively).]} @end{Legality} @begin{StaticSem} A @nt{formal_package_declaration} declares a generic formal package. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @PDefn2{Term=[visible part], Sec=(of a formal package)} The visible part of a formal package includes the first list of @nt{basic_declarative_item}s of the @nt{package_@!specification}. In addition, @Chg{Version=[2],New=[for each actual parameter that is not required to match, a copy of the declaration of the corresponding formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible part of], Old=[if the @nt{formal_@!package_@!actual_@!part} is (<>), it also includes the @nt{generic_@!formal_@!part} of the template for]} the formal package. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} If the @nt<formal_package_actual_part> is (<>), then the declarations that occur immediately within the @nt<generic_formal_part> of the template for the formal package are visible outside the formal package, and can be denoted by expanded names outside the formal package.@Chg{Version=[2],New=[If only some of the actual parameters are given by <>, then the declaration corresponding to those parameters (but not the others) are made visible.],Old=[]} @end{Ramification} @begin{Reason} We always want either the actuals or the formals of an instance to be namable from outside, but never both. If both were namable, one would get some funny anomalies since they denote the same entity, but, in the case of types at least, they might have different and inconsistent sets of primitive operators due to predefined operator @lquotes@;reemergence.@rquotes@; Formal derived types exacerbate the difference. We want the implicit declarations of the @nt<generic_formal_part> as well as the explicit declarations, so we get operations on the formal types. @end{Reason} @begin{Ramification} A generic formal package is a package, and is an instance. Hence, it is possible to pass a generic formal package as an actual to another generic formal package. @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[ For the purposes of matching, if the actual instance @i<A> is itself a formal package, then the actual parameters of @i<A> are those specified explicitly or implicitly in the @nt{formal_package_actual_part} for @i<A>, plus, for those not specified, the copies of the formal parameters of the template included in the visible part of @i<A>.]} @end{StaticSem} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@i{Example of a generic package with formal package parameters:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Containers.Ordered_Maps; --@RI[ see @RefSecNum{The Package Containers.Ordered_Maps}] @key[generic] @key[with package] Mapping_1 @key[is new] Ada.Containers.Ordered_Maps(<>); @key[with package] Mapping_2 @key[is new] Ada.Containers.Ordered_Maps (Key_Type => Mapping_1.Element_Type, @key[others] => <>); @key[package] Ordered_Join @key[is] --@RI[ Provide a "join" between two mappings]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[subtype] Key_Type @key[is] Mapping_1.Key_Type; @key[subtype] Element_Type @key[is] Mapping_2.Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] Lookup(Key : Key_Type) @key[return] Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key[end] Ordered_Join;]} @end{Example} @RMNewPage@Comment{For printed Ada 2005 RM only} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@i{Example of an instantiation of a package with formal packages:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Containers.Ordered_Maps; @key[package] Symbol_Package @key[is]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[type] String_Id @key[is] ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[type] Symbol_Info @key[is] ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] String_Table @key[is new] Ada.Containers.Ordered_Maps (Key_Type => String, Element_Type => String_Id);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] Symbol_Table @key[is new] Ada.Containers.Ordered_Maps (Key_Type => String_Id, Element_Type => Symbol_Info);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] String_Info @key[is new] Ordered_Join(Mapping_1 => String_Table, Mapping_2 => Symbol_Table);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Apple_Info : @key[constant] Symbol_Info := String_Info.Lookup("Apple");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[end] Symbol_Package;]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Formal packages are new to Ada 95. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01],ARef=[AI95-00398-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} It's now allowed to mix actuals of a formal package that are specified with those that are not specified.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0039],ARef=[AI95-00213-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the description of formal package matching to say that formal parameters are always replaced by their actual parameters (recursively). This matches the actual practice of compilers, as the ACATS has always required this behavior.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[The description of which operations are visible in a formal package has been clarified. We also specify how matching is done when the actual is a formal package.]} @end{DiffWord95} @LabeledClause{Example of a Generic Package} @begin{Intro} The following example provides a possible formulation of stacks by means of a generic package. The size of each stack and the type of the stack elements are provided as generic formal parameters. @end{Intro} @begin{Examples} @Leading @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Example} @key[generic] Size : Positive; @key[type] Item @key[is] @key[private]; @key[package] Stack @key[is] @key[procedure] Push(E : @key[in] Item); @key[procedure] Pop (E : @key[out] Item); Overflow, Underflow : @key[exception]; @key[end] Stack; @key[package] @key[body] Stack @key[is] @key[type] Table @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; Space : Table(1 .. Size); Index : Natural := 0; @key[procedure] Push(E : @key[in] Item) @key[is] @key[begin] @key[if] Index >= Size @key[then] @key[raise] Overflow; @key[end] @key[if]; Index := Index + 1; Space(Index) := E; @key[end] Push; @key[procedure] Pop(E : @key[out] Item) @key[is] @key[begin] @key[if] Index = 0 @key[then] @key[raise] Underflow; @key[end] @key[if]; E := Space(Index); Index := Index - 1; @key[end] Pop; @key[end] Stack; @end{Example} @begin{Wide} @Leading@Keepnext@;Instances of this generic package can be obtained as follows: @end{Wide} @begin{Example} @key[package] Stack_Int @key[is] @key[new] Stack(Size => 200, Item => Integer); @key[package] Stack_Bool @key[is] @key[new] Stack(100, Boolean); @end{Example} @begin{Wide} @Leading@Keepnext@;Thereafter, the procedures of the instantiated packages can be called as follows: @end{Wide} @begin{Example} Stack_Int.Push(N); Stack_Bool.Push(True); @end{Example} @begin{Wide} @Leading@Keepnext@;Alternatively, a generic formulation of the type Stack can be given as follows (package body omitted): @end{Wide} @begin{Example} @key[generic] @key[type] Item @key[is] @key[private]; @key[package] On_Stacks @key[is] @key[type] Stack(Size : Positive) @key[is] @key[limited] @key[private]; @key[procedure] Push(S : @key[in] @key[out] Stack; E : @key[in] Item); @key[procedure] Pop (S : @key[in] @key[out] Stack; E : @key[out] Item); Overflow, Underflow : @key[exception]; @key[private] @key[type] Table @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; @key[type] Stack(Size : Positive) @key[is] @key[record] Space : Table(1 .. Size); Index : Natural := 0; @key[end] @key[record]; @key[end] On_Stacks; @end{Example} @begin{Wide} @Leading@Keepnext@;In order to use such a package, an instance has to be created and thereafter stacks of the corresponding type can be declared: @end{Wide} @begin{Example} @key[declare] @key[package] Stack_Real @key[is] @key[new] On_Stacks(Real); @key[use] Stack_Real; S : Stack(100); @key[begin] ... Push(S, 2.54); ... @key[end]; @end{Example} @end{Examples} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/13a.mss��������������������������������������������������������������0000755�0001752�0001001�00000467144�12273462240�016551� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(13, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:29 $} @LabeledSection{Representation Issues} @Comment{$Source: e:\\cvsroot/ARM/Source/13a.mss,v $} @Comment{$Revision: 1.69 $} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @redundant[This section describes features for querying and controlling @Chg{New=[certain aspects of entities], Old=[aspects of representation]} and for interfacing to hardware.] @end{Intro} @begin{DiffWord83} The clauses of this section have been reorganized. This was necessary to preserve a logical order, given the new Ada 95 semantics given in this section. @end{DiffWord83} @LabeledRevisedClause{Version=[1],New=[Operational and Representation Items],Old=[Representation Items]} @begin{Intro} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[@Redundant[Representation and operational items can be used to specify aspects of entities. Two kinds of aspects of entities can be specified: aspects of representation and operational aspects. Representation items specify how the types and other entities of the language are to be mapped onto the underlying machine. Operational items specify other properties of entities.]]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Defn{representation item} @RootDefn{representation pragma} @RootDefn{pragma, representation} There are @Chg{New=[six],Old=[three]} kinds of @i{representation items}: @Chg{New=[@nt{attribute_@!definition_@!clause}s for representation attributes, @nt{enumeration_@!representation_@!clause}s, @nt{record_@!representation_@!clause}s, @nt{at_clause}s, ], Old=[@nt{representation_@!clause}s, ]}@nt<component_clause>s, and @i{representation pragmas}. @Redundant[@Chg{New=[],Old=[Representation items specify how the types and other entities of the language are to be mapped onto the underlying machine.]} They can be provided to give more efficient representation or to interface with features that are outside the domain of the language (for example, peripheral hardware). @Chg{New=[],Old=[Representation items also specify other specifiable properties of entities. A representation item applies to an entity identified by a @nt<local_name>, which denotes an entity declared local to the current declarative region, or a library unit declared immediately preceding a representation pragma in a @nt<compilation>.]}] @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[An @Defn{operational item}@i<operational item> is an @nt<attribute_definition_clause> for an operational attribute.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[@Redundant[An operational item or a representation item applies to an entity identified by a @nt<local_name>, which denotes an entity declared local to the current declarative region, or a library unit declared immediately preceding a representation pragma in a @nt<compilation>.]]} @end{Intro} @begin{Metarules} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[Aspects of representation are intended to refer to properties that need to be known before the compiler can generate code to create or access an entity. For instance, the size of an object needs to be known before the object can be created. Conversely, operational aspects are those that only need to be known before they can be used. For instance, how an object is read from a stream only needs to be known when a stream read is executed. Thus, aspects of representation have stricter rules as to when they can be specified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Confirming the value of an aspect with an operational or representation item should never change the semantics of the aspect. Thus Size = 8 (for example) means the same thing whether it was specified with a representation item or whether the compiler chose this value by default.]} @end{Metarules} @begin{Syntax} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<@Chg{New=[aspect_clause],Old=[representation_clause]}>,rhs="@Syn2{attribute_definition_clause} | @Syn2{enumeration_representation_clause} | @Syn2{record_representation_clause} | @Syn2{at_clause}"} @Syn{lhs=<local_name>,rhs="@Syn2{direct_name} | @Syn2{direct_name}@SingleQuote@Syn2{attribute_designator} | @SynI{library_unit_}@Syn2{name}"} @begin{SyntaxText} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} A representation pragma is allowed only at places where @Chg{New=[an @nt{aspect_clause}],Old=[a @nt{representation_clause}]} or @nt{compilation_unit} is allowed. @Chg{New=[@IndexSee(Term=(representation_clause),See=(aspect_clause))],Old=[]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} In @Chg{New=[an operational item or],Old=[a]} representation item, if the @nt<local_name> is a @nt<direct_name>, then it shall resolve to denote a declaration (or, in the case of a @nt{pragma}, one or more declarations) that occurs immediately within the same declarative region as the @Chg{New=[],Old=[representation ]}item. If the @nt<local_name> has an @nt<attribute_designator>, then it shall resolve to denote an implementation-defined component (see @RefSecNum{Record Representation Clauses}) or a class-wide type implicitly declared immediately within the same declarative region as the @Chg{New=[],Old=[representation ]}item. A @nt<local_name> that is a @i{library_unit_}@nt<name> (only permitted in a representation pragma) shall resolve to denote the @nt<library_item> that immediately precedes (except for other pragmas) the representation pragma. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} This is a @ResolutionName, because we don't want @Chg{New=[an operational or],Old=[a]} representation item for X to be ambiguous just because there's another X declared in an outer declarative region. It doesn't make much difference, since most @Chg{New=[operational or ],Old=[]}representation items are for types or subtypes, and type and subtype names can't be overloaded. @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The visibility rules imply that the declaration has to occur before the @Chg{New=[operational or ],Old=[]}representation item. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} For objects, this implies that @Chg{New=[operational or ],Old=[]}representation items can be applied only to stand-alone objects. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The @nt{local_name} of @Chg{New=[an @nt<aspect_clause>], Old=[a @nt<representation_clause>]} or representation pragma shall statically denote an entity (or, in the case of a @nt{pragma}, one or more entities) declared immediately preceding it in a @nt<compilation>, or within the same @nt{declarative_@!part}, @nt{package_@!specification}, @nt{task_@!definition}, @nt{protected_@!definition}, or @nt{record_@!definition} as the representation @Chg{New=[or operational ],Old=[]}item. If a @nt<local_name> denotes a @Redundant[local] callable entity, it may do so through a @Redundant[local] @nt<subprogram_@!renaming_@!declaration> @Redundant[(as a way to resolve ambiguity in the presence of overloading)]; otherwise, the @nt<local_name> shall not denote a @nt<renaming_@!declaration>. @begin{Ramification} The @lquotes@;statically denote@rquotes@; part implies that it is impossible to specify the representation of an object that is not a stand-alone object, except in the case of a representation item like pragma Atomic that is allowed inside a @nt{component_list} (in which case the representation item specifies the representation of components of all objects of the type). It also prevents the problem of renamings of things like @lquotes@;P.@key[all]@rquotes@; (where P is an access-to-subprogram value) or @lquotes@;E(I)@rquotes@; (where E is an entry family). The part about where the denoted entity has to have been declared appears twice @em once as a @ResolutionName, and once as a @LegalityName. Suppose P renames Q, and we have a representation item in a @nt{declarative_part} whose @nt<local_name> is P. The fact that the representation item has to appear in the same @nt{declarative_part} as P is a @ResolutionName, whereas the fact that the representation item has to appear in the same @nt{declarative_part} as Q is a @LegalityName. This is subtle, but it seems like the least confusing set of rules. @end{Ramification} @begin{Discussion} A separate @LegalityName applies for @nt<component_clause>s. See @RefSec{Record Representation Clauses}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Defn{representation of an object} @Defn2{Term=[size], Sec=(of an object)}The @i{representation} of an object consists of a certain number of bits (the @i(size) of the object). @Chg{Version=[2],New=[For an object of an elementary type, these],Old=[These]} are the bits that are normally read or updated by the machine code when loading, storing, or operating-on the value of the object. @Chg{Version=[2],New=[For an object of a composite type, these are the bits reserved for this object, and include bits occupied by subcomponents of the object. If],Old=[This includes some padding bits, when]} the size of @Chg{Version=[2],New=[an],Old=[the]} object is greater than @Chg{Version=[2],New=[that],Old=[the size]} of its subtype@Chg{Version=[2], New=[, the additional bits are padding bits.],Old=[. @Defn{gaps}]} @Defn{padding bits} @Chg{Version=[2],New=[For an elementary object, these],Old=[Such]} padding bits @Chg{Version=[2],New=[],Old=[are considered to be part of the representation of the object, rather than being gaps between objects, if these bits ]}are normally read and updated@Chg{Version=[2],New=[ along with the others. For a composite object, padding bits might not be read or updated in any given composite operation, depending on the implementation],Old=[]}. @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @PDefn{contiguous representation} @PDefn{discontiguous representation} Discontiguous representations are allowed, but the ones we're interested in here are generally contiguous sequences of bits.@Chg{Version=[2],New=[ For a discontiguous representation, the size doesn't necessarily describe the @lquotes@;footprint@rquotes of the object in memory (that is, the amount of space taken in the address space for the object).],Old=[]} @end{Honest} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[In the case of composite objects, we want the implementation to have the flexibility to either do operations component-by-component, or with a block operation covering all of the bits. We carefully avoid giving a preference in the wording. There is no requirement for the choice to be documented, either, as the implementation can make that choice based on many factors, and could make a different choice for different operations on the same object.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[In the case of a properly aligned, contiguous object whose size is a multiple of the storage unit size, no other bits should be read or updated as part of operating on the object. We don't say this normatively because it would be difficult to normatively define @lquotes@;properly aligned@rquotes or @lquotes@;contiguous@rquotes.]} @end{Discussion} @begin{Ramification} @Leading@;Two objects with the same value do not necessarily have the same representation. For example, an implementation might represent False as zero and True as any odd value. Similarly, two objects (of the same type) with the same sequence of bits do not necessarily have the same value. For example, an implementation might use a biased representation in some cases but not others: @begin{Example} @key[subtype] S @key[is] Integer @key[range] 1..256; @key[type] A @key[is] @key[array](Natural @key[range] 1..4) @key[of] S; @key[pragma] Pack(A); X : S := 3; Y : A := (1, 2, 3, 4); @end{Example} The implementation might use a biased-by-1 representation for the array elements, but not for X. X and Y(3) have the same value, but different representation: the representation of X is a sequence of (say) 32 bits: 0...011, whereas the representation of Y(3) is a sequence of 8 bits: 00000010 (assuming a two's complement representation). Such tricks are not required, but are allowed. @end{Ramification} @begin{Discussion} The value of any padding bits is not specified by the language, though for a numeric type, it will be much harder to properly implement the predefined operations if the padding bits are not either all zero, or a sign extension. @end{Discussion} @begin{Ramification} For example, suppose S'Size = 2, and an object X is of subtype S. If the machine code typically uses a 32-bit load instruction to load the value of X, then X'Size should be 32, even though 30 bits of the value are just zeros or sign-extension bits. On the other hand, if the machine code typically masks out those 30 bits, then X'Size should be 2. Usually, such masking only happens for components of a composite type for which packing, Component_Size, or record layout is specified. Note, however, that the formal parameter of an instance of Unchecked_Conversion is a special case. Its Size is required to be the same as that of its subtype. Note that we don't generally talk about the representation of a value. A value is considered to be an amorphous blob without any particular representation. An object is considered to be more concrete. @end{Ramification} @RootDefn{aspect of representation} @Defn{representation aspect} @Defn2{Term=[directly specified], Sec=(of an aspect of representation of an entity)} A representation item @i{directly specifies} an @i{aspect of representation} of the entity denoted by the @nt{local_name}, except in the case of a type-related representation item, whose @nt{local_name} shall denote a first subtype, and which directly specifies an aspect of the subtype's type. @RootDefn2{Term=[type-related], Sec=(representation item)} @RootDefn2{term=[subtype-specific], Sec=(of a representation item)} @RootDefn2{Term=[type-related], Sec=(aspect)} @RootDefn2{term=[subtype-specific], Sec=(of an aspect)} A representation item that names a subtype is either @i(subtype-specific) (Size and Alignment clauses) or @i{type-related} (all others). @Redundant[Subtype-specific aspects may differ for different subtypes of the same type.] @begin{Honest} @i{Type-related} and @i{subtype-specific} are defined likewise for the corresponding aspects of representation. @end{Honest} @begin{Honest} Some representation items directly specify more than one aspect. @end{Honest} @begin{Discussion} For example, a @nt{pragma} Export specifies the convention of an entity, and also specifies that it is exported. @end{Discussion} @begin{Ramification} Each specifiable attribute constitutes a separate aspect. An @nt{enumeration_representation_clause} specifies the coding aspect. A @nt{record_representation_clause} (without the @nt{mod_clause}) specifies the record layout aspect. Each representation pragma specifies a separate aspect. @end{Ramification} @begin{Reason} We don't need to say that an @nt{at_clause} or a @nt{mod_clause} specify separate aspects, because these are equivalent to @nt{attribute_definition_clause}s. See @RefSec{At Clauses}, and @RefSec{Mod Clauses}. @end{Reason} @begin{Ramification} @Leading@;The following representation items are type-related: @begin{Itemize} @nt{enumeration_representation_clause} @nt{record_representation_clause} Component_Size clause @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[External_Tag clause]} Small clause Bit_Order clause Storage_Pool clause Storage_Size clause @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[Stream_Size clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Read clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Write clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Input clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Output clause]} Machine_Radix clause pragma Pack pragmas Import, Export, and Convention (when applied to a type) pragmas Atomic and Volatile (when applied to a type) pragmas Atomic_Components and Volatile_Components (when applied to an array type) pragma Discard_Names (when applied to an enumeration or tagged type) @end{Itemize} @Leading@;The following representation items are subtype-specific: @begin{Itemize} Alignment clause (when applied to a first subtype) Size clause (when applied to a first subtype) @end{Itemize} @Leading@;The following representation items do not apply to subtypes, so they are neither type-related nor subtype-specific: @begin{Itemize} Address clause (applies to objects and program units) Alignment clause (when applied to an object) Size clause (when applied to an object) pragmas Import, Export, and Convention (when applied to anything other than a type) pragmas Atomic and Volatile (when applied to an object or a component) pragmas Atomic_Components and Volatile_Components (when applied to an array object) pragma Discard_Names (when applied to an exception) pragma Asynchronous (applies to procedures) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[pragma No_Return (applies to procedures)]} @end{Itemize} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[An operational item @i<directly specifies> an @i<operational aspect> of the type of the subtype denoted by the @nt{local_name}. The @nt{local_name} of an operational item shall denote a first subtype. An operational item that names a subtype is type-related. @RootDefn{operational aspect} @Defn2{Term=[directly specified], Sec=(of an operational aspect of an entity)} @RootDefn2{Term=[type-related], Sec=(operational item)} @PDefn2{Term=[type-related], Sec=(aspect)}]} @begin{Ramification} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[The following operational items are type-related:]} @begin{Itemize} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[External_Tag clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Read clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Write clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Input clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Output clause]} @end{Itemize} @end{Ramification} A representation item that directly specifies an aspect of a subtype or type shall appear after the type is completely defined (see @RefSecNum{Completions of Declarations}), and before the subtype or type is frozen (see @RefSecNum{Freezing Rules}). If a representation item is given that directly specifies an aspect of an entity, then it is illegal to give another representation item that directly specifies the same aspect of the entity. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The fact that a representation item @Chg{New=[(or operational item, see next paragraph) ],Old=[]}that directly specifies an aspect of an entity is required to appear before the entity is frozen prevents changing the representation of an entity after using the entity in ways that require the representation to be known. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[An operational item that directly specifies an aspect of a type shall appear before the type is frozen (see @RefSecNum{Freezing Rules}). If an operational item is given that directly specifies an aspect of a type, then it is illegal to give another operational item that directly specifies the same aspect of the type.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[Unlike representation items, operational items can be specified on partial views. Since they don't affect the representation, the full declaration need not be known to determine their legality.]} @end{Ramification} For an untagged derived type, no type-related representation items are allowed if the parent type is a by-reference type, or has any user-defined primitive subprograms. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} On the other hand, subtype-specific representation items may be given for the first subtype of such a type@Chg{New=[, as can operational items], Old=[]}. @end{Ramification} @begin{Reason} The reason for forbidding type-related representation items on untagged by-reference types is because a change of representation is impossible when passing by reference (to an inherited subprogram). The reason for forbidding type-related representation items on untagged types with user-defined primitive subprograms was to prevent implicit change of representation for type-related aspects of representation upon calling inherited subprograms, because such changes of representation are likely to be expensive at run time. Changes of subtype-specific representation attributes, however, are likely to be cheap. This rule is not needed for tagged types, because other rules prevent a type-related representation item from changing the representation of the parent part; we want to allow a type-related representation item on a type extension to specify aspects of the extension part. For example, a @nt{pragma} Pack will cause packing of the extension part, but not of the parent part. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Chg{New=[Operational and r],Old=[R]}epresentation aspects of a generic formal parameter are the same as those of the actual. @Chg{New=[Operational and representation aspects @Chg{Version=[2],New=[], Old=[of a partial view ]}are the same @Chg{Version=[2],New=[for all views of a type],Old=[as those of the full view]}.],Old=[]} A type-related representation item is not allowed for a descendant of a generic formal untagged type. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} Representation items are allowed for types whose subcomponent types or index subtypes are generic formal types. @Chg{New=[Operational items and subtype-related representation items are allowed on descendants of generic formal types.],Old=[]} @end{Ramification} @begin{Reason} Since it is not known whether a formal type has user-defined primitive subprograms, specifying type-related representation items for them is not allowed, unless they are tagged (in which case only the extension part is affected in any case). @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[All views of a type, including the incomplete and partial views, have the same operational and representation aspects. That's important so that the properties don't change when changing views. While most aspects are not available for an incomplete view, we don't want to leave any holes by not saying that they are the same.]} @end{Ramification} A representation item that specifies the Size for a given subtype, or the size or storage place for an object (including a component) of a given subtype, shall allow for enough storage space to accommodate any value of the subtype. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} A representation @Chg{New=[or operational ],Old=[]}item that is not supported by the implementation is illegal, or raises an exception at run time. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[A @nt{type_declaration} is illegal if it has one or more progenitors, and a representation item applies to an ancestor, and this representation item conflicts with the representation of some other ancestor. The cases that cause conflicts are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The cases that cause conflicts between the representation of the ancestors of a @nt{type_declaration}.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule is needed because it may be the case that only the combination of types in a type declaration causes a conflict. Thus it is not possible, in general, to reject the original representation item. For instance:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Pkg1 @key{is} @key{type} Ifc @key{is interface}; @key{type} T @key{is tagged record} Fld : Integer; @key{end record}; @key{for} T @key{use record} Fld @key{at} 0 @key{range} 0 .. Integer'Size - 1; @key{end record}; @key{end} Pkg1;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Assume the implementation uses a single tag with a default offset of zero, and that it allows the use of non-default locations for the tag (and thus accepts representation items like the one above). The representation item will force a non-default location for the tag (by putting a component other than the tag into the default location). Clearly, this package will be accepted by the implementation. However, other declarations could cause trouble. For instance, the implementation could reject:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Pkg1; @key{package} Pkg2 @key{is} @key{type} NewT @key{is new} Pkg1.T @key{and} Pkg1.Ifc @key{with null record}; @key{end} Pkg2;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[because the declarations of T and Ifc have a conflict in their representation items. This is clearly necessary (it's hard to imagine how Ifc'Class could work with the tag at a location other than the one it is expecting).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Conflicts will usually involve implementation-defined attributes (for specifying the location of the tag, for instance), although the example above shows that doesn't have to be the case. For this reason, we didn't try to specify exactly what causes a conflict; it will depend on the implementation's implementation model and what representation items it allows.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An implementation can only use this rule to reject @nt{type_declaration}s where one its ancestors has a representation item. An implementation must ensure that the default representations of ancestors cannot conflict.]} @end{ImplNote} @end{Legality} @begin{StaticSem} If two subtypes statically match, then their subtype-specific aspects (Size and Alignment) are the same. @PDefn2{Term=[statically matching],Sec=(effect on subtype-specific aspects)} @begin{Reason} This is necessary because we allow (for example) conversion between access types whose designated subtypes statically match. Note that it is illegal to specify an aspect (including a subtype-specific one) for a nonfirst subtype. @Leading@Keepnext@;Consider, for example: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] P1 @key[is] @key[subtype] S1 @key[is] Integer @key[range] 0..2**16-1; @key[for] S1'Size @key[use] 16; --@RI{ Illegal!} --@RI{ S1'Size would be 16 by default.} @key[type] A1 @key[is] @key[access] @Chg{New=[@Key[all] ],Old=[]}S1; X1: A1; @key[end] P1; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] P2 @key[is] @key[subtype] S2 @key[is] Integer @key[range] 0..2**16-1; @key[for] S2'Size @key[use] 32; --@RI{ Illegal!} @key[type] A2 @key[is] @key[access] @Chg{New=[@Key[all] ],Old=[]}S2; X2: A2; @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[procedure] Q @key[is] @key[use] P1, P2; @key[type] Array1 @key[is] @key[array](Integer @key[range] <>) @key[of] @key[aliased] S1; @key[pragma] Pack(Array1); Obj1: Array1(1..100); @key[type] Array2 @key[is] @key[array](Integer @key[range] <>) @key[of] @key[aliased] S2; @key[pragma] Pack(Array2); Obj2: Array2(1..100); @key[begin] X1 := Obj2(17)'@Chg{New=[Unchecked_],Old=[]}Access; X2 := Obj1(17)'@Chg{New=[Unchecked_],Old=[]}Access; @key[end] Q; @end{Example} Loads and stores through X1 would read and write 16 bits, but X1 points to a 32-bit location. Depending on the endianness of the machine, loads might load the wrong 16 bits. Stores would fail to zero the other half in any case. Loads and stores through X2 would read and write 32 bits, but X2 points to a 16-bit location. Thus, adjacent memory locations would be trashed. Hence, the above is illegal. Furthermore, the compiler is forbidden from choosing different Sizes by default, for the same reason. The same issues apply to Alignment. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} A derived type inherits each type-related aspect @Chg{New=[of representation ],Old=[]}of its parent type that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent type from the grandparent type. A derived subtype inherits each subtype-specific aspect @Chg{New=[of representation ],Old=[]}of its parent subtype that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent subtype from the grandparent subtype, but only if the parent subtype statically matches the first subtype of the parent type. An inherited aspect of representation is overridden by a subsequent representation item that specifies the same aspect of the type or subtype. @begin{Honest} A @nt{record_representation_clause} for a record extension does not override the layout of the parent part; if the layout was specified for the parent type, it is inherited by the record extension. @end{Honest} @begin{Ramification} If a representation item for the parent appears after the @nt{derived_@!type_@!definition}, then inheritance does not happen for that representation item. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgAdded{Version=[1],Text=[In contrast, whether operational aspects are inherited by @Chg{Version=[2],New=[an untagged],Old=[a]} derived type depends on each specific aspect. @Chg{Version=[2],New=[@Redundant[Operational aspects are never inherited for a tagged type.] ],Old=[]}When operational aspects are inherited by @Chg{Version=[2],New=[an untagged],Old=[a]} derived type, aspects that were directly specified @Chg{Version=[2],New=[by operational items that are visible at the point],Old=[before the declaration]} of the derived type@Chg{Version=[2],New=[ declaration],Old=[]}, or (in the case where the parent is derived) that were inherited by the parent type from the grandparent type are inherited. An inherited operational aspect is overridden by a subsequent operational item that specifies the same aspect of the type.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[As with representation items, if an operational item for the parent appears after the @nt{derived_@!type_@!definition}, then inheritance does not happen for that operational item.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgAdded{Version=[1],Text=[@Chg{Version=[2],New=[Only],Old=[Currently, only]} untagged types inherit operational aspects. @Chg{Version=[2],New=[Inheritance from tagged types causes problems, as the different views can have different visibility on operational items @em potentially leading to operational items that depend on the view. We want aspects to be the same for all views. Untagged types don't have this problem as plain private types don't have ancestors, and thus can't inherit anything. In addition, it seems unlikely that we'll need inheritance for tagged types, as usually we'll want to incorporate the parent's operation into a new one that also handles any extension components.],Old=[We considered writing this rule that way, but rejected it as that could be too specific for future operational aspects. (After all, that is precisely the problem that caused us to introduce @lquotes@;operational aspects@rquotes in the first place.)]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[When an aspect that is a subprogram is inherited, the derived type inherits the aspect in the same way that a derived type inherits a user-defined primitive subprogram from its parent (see @RefSecNum{Derived Types and Classes}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This defines the parameter names and types, and the needed implicit conversions.]} @end{Reason} @Leading@;Each aspect of representation of an entity is as follows: @begin{Itemize} @Defn2{Term=[specified], Sec=(of an aspect of representation of an entity)} If the aspect is @i{specified} for the entity, meaning that it is either directly specified or inherited, then that aspect of the entity is as specified, except in the case of Storage_Size, which specifies a minimum. @begin{Ramification} This rule implies that queries of the aspect return the specified value. For example, if the user writes @lquotes@;@key{for} X'Size @key{use} 32;@rquotes@;, then a query of X'Size will return 32. @end{Ramification} @PDefn{unspecified} If an aspect of representation of an entity is not specified, it is chosen by default in an unspecified manner. @end{Itemize} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} Note that @Chg{New=[representation items],Old=[@nt{representation_clause}s]} can affect the semantics of the entity. The rules forbid things like @lquotes@;@key[for] S'Base'Alignment @key[use] ...@rquotes@; and @lquotes@;@key[for] S'Base @key[use] record ...@rquotes@;. @end{Ramification} @begin{Discussion} The intent is that implementations will represent the components of a composite value in the same way for all subtypes of a given composite type. Hence, Component_Size and record layout are type-related aspects. @end{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[specified], Sec=(of an operational aspect of an entity)} If an operational aspect is @i<specified> for an entity (meaning that it is either directly specified or inherited), then that aspect of the entity is as specified. Otherwise, the aspect of the entity has the default value for that aspect.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[A representation item that specifies an aspect of representation that would have been chosen in the absence of the representation item is said to be @i{confirming}.@Defn2{Term=[confirming], Sec=(representation item)}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[@PDefn2{Term=[elaboration], Sec=(aspect_clause)}], Old=[@PDefn2{Term=[elaboration], Sec=(representation_clause)}]} For the elaboration of @Chg{New=[an @nt{aspect_clause}], Old=[a @nt{representation_clause}]}, any evaluable constructs within it are evaluated. @begin{Ramification} Elaboration of representation pragmas is covered by the general rules for pragmas in Section 2. @end{Ramification} @end{RunTime} @begin{ImplPerm} An implementation may interpret aspects of representation in an implementation-defined manner. An implementation may place implementation-defined restrictions on representation items. @RootDefn{recommended level of support} A @i{recommended level of support} is specified for representation items and related features in each subclause. These recommendations are changed to requirements for implementations that support the Systems Programming Annex (see @RefSec{Required Representation Support}). @ImplDef{The interpretation of each aspect of representation.} @ImplDef{Any restrictions placed upon representation items.} @begin{Ramification} Implementation-defined restrictions may be enforced either at compile time or at run time. There is no requirement that an implementation justify any such restrictions. They can be based on avoiding implementation complexity, or on avoiding excessive inefficiency, for example. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[There is no such permission for operational aspects.]} @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(with respect to nonstatic expressions)} The recommended level of support for all representation items is qualified as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[A confirming representation item should be supported.]} @begin{Honest} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A confirming representation item might not be possible for some entities. For instance, consider an unconstrained array. The size of such a type is implementation-defined, and might not actually be a representable value, or might not be static.]} @end{Honest} An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes a constant declared before the entity. @begin{Reason} @Leading@;This is to avoid the following sort of thing: @begin{Example} X : Integer := F(...); Y : Address := G(...); @key[for] X'Address @key[use] Y; @end{Example} In the above, we have to evaluate the initialization expression for X before we know where to put the result. This seems like an unreasonable implementation burden. @Leading@;The above code should instead be written like this: @begin{Example} Y : @key[constant] Address := G(...); X : Integer := F(...); @key[for] X'Address @key[use] Y; @end{Example} This allows the expression @lquotes@;Y@rquotes@; to be safely evaluated before X is created. The constant could be a formal parameter of mode @key[in]. An implementation can support other nonstatic expressions if it wants to. Expressions of type Address are hardly ever static, but their value might be known at compile time anyway in many cases. @end{Reason} An implementation need not support a specification for the Size for a given composite subtype, nor the size or storage place for an object (including a component) of a given composite subtype, unless the constraints on the subtype and its composite subcomponents (if any) are all static constraints. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Chg{Version=[2],New=[An implementation need not support a nonconfirming representation item if it could cause an aliased object or an object of a by-reference type to be allocated at a nonaddressable location or, when the alignment attribute of the subtype of such an object is nonzero, at an address that is not an integral multiple of that alignment.],Old=[An aliased component, or a component whose type is by-reference, should always be allocated at an addressable location.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-0079} The intent is that access types, type System.Address, and the pointer used for a by-reference parameter should be implementable as a single machine address @em bit-field pointers should not be required. (There is no requirement that this implementation be used @em we just want to make sure @Chg{New=[it's],Old=[its]} feasible.) @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Chg{Version=[2],New=[We want subprograms to be able to assume the properties of the types of their parameters inside of subprograms. While many objects can be copied to allow this (and thus do not need limitations), aliased or by-reference objects cannot be copied (their memory location is part of their identity). Thus,], Old=[Note that]} the above rule does not apply to types that merely allow by-reference parameter passing; for such types, a copy typically needs to be made at the call site when a bit-aligned component is passed as a parameter. @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support a nonconfirming representation item if it could cause an aliased object of an elementary type to have a size other than that which would have been chosen by default.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since all bits of elementary objects participate in operations, aliased objects must not have a different size than that assumed by users of the access type.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support a nonconfirming representation item if it could cause an aliased object of a composite type, or an object whose type is by-reference, to have a size smaller than that which would have been chosen by default.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike elementary objects, there is no requirement that all bits of a composite object participate in operations. Thus, as long as the object is the same or larger in size than that expected by the access type, all is well.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule presumes that the implementation allocates an object of a size specified to be larger than the default size in such a way that access of the default size suffices to correctly read and write the value of the object.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support a nonconfirming subtype-specific representation item specifying an aspect of representation of an indefinite or abstract subtype.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Aspects of representations are often not well-defined for such types.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00075} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} A pragma Pack will typically not pack so tightly as to disobey the above @Chg{Version=[2],New=[rules],Old=[rule]}. A Component_Size clause or @nt{record_representation_clause} will typically @Chg{New=[be],Old=[by]} illegal if it disobeys the above @Chg{Version=[2],New=[rules],Old=[rule]}. Atomic components have similar restrictions (see @RefSec{Shared Variable Control}). @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[For purposes of these rules, the determination of whether a representation item applied to a type @i{could cause} an object to have some property is based solely on the properties of the type itself, not on any available information about how the type is used. In particular, it presumes that minimally aligned objects of this type might be declared at some point.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for all representation items should be followed.]}]} @end{ImplAdvice} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} It is now illegal for a representation item to cause a derived by-reference type to have a different record layout from its parent. This is necessary for by-reference parameter passing to be feasible. This only affects programs that specify the representation of types derived from types containing tasks; most by-reference types are new to Ada 95. For example, if A1 is an array of tasks, and A2 is derived from A1, it is illegal to apply a @nt{pragma} Pack to A2. @end{Incompatible83} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Defn{extensions to Ada 83} Ada 95 allows additional @Chg{New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]} for objects. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The syntax rule for @ntf{type_representation_clause} is removed; the right-hand side of that rule is moved up to where it was used, in @Chg{New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]}. There are two references to @lquotes@;type representation clause@rquotes@; in RM83, both in Section 13; these have been reworded. @Chg{New=[Also, the @ntf{representation_clause} has been renamed the @nt{aspect_clause} to reflect that it can be used to control more than just representation aspects.],Old=[]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We have defined a new term @lquotes@;representation item,@rquotes@; which includes @Chg{New=[all representation clauses], Old=[@nt{representation_clause}s]} and representation pragmas, as well as @nt<component_clause>s. This is convenient because the rules are almost identical for all @Chg{New=[of them], Old=[three]}. @Chg{New=[We have also defined the new terms @lquotes@;operational item@rquotes@; and @lquotes@;operational aspects@rquotes@; in order to conveniently handle new types of @Chg{Version=[2],New=[specifiable],Old=[specifable]} entities.],Old=[]} All of the forcing occurrence stuff has been moved into its own subclause (see @RefSecNum{Freezing Rules}), and rewritten to use the term @lquotes@;freezing@rquotes@;. RM83-13.1(10) requires implementation-defined restrictions on representation items to be enforced at compile time. However, that is impossible in some cases. If the user specifies a junk (nonstatic) address in an address clause, and the implementation chooses to detect the error (for example, using hardware memory management with protected pages), then it's clearly going to be a run-time error. It seems silly to call that @lquotes@;semantics@rquotes@; rather than @lquotes@;a restriction.@rquotes@; RM83-13.1(10) tries to pretend that @ntf{representation_clause}s don't affect the semantics of the program. One counter-example is the Small clause. Ada 95 has more counter-examples. We have noted the opposite above. Some of the more stringent requirements are moved to @RefSec{Required Representation Support}. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Confirming representation items are defined, and the recommended level of support is now that they always be supported.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added operational items in order to eliminate unnecessary restrictions and permissions on stream attributes. As part of this, @ntf{representation_clause} was renamed to @nt{aspect_clause}.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to say that the partial and full views have the same operational and representation aspects. Ada 2005 extends this to cover all views, including the incomplete view.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed operational items to have inheritance specified for each such aspect.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording to allow the rejection of types with progenitors that have conflicting representation items.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[The description of the representation of an object was clarified (with great difficulty reaching agreement). Added wording to say that representation items on aliased and by-reference objects never need be supported if they would not be implementable without distributed overhead even if other recommended level of support says otherwise. This wording matches the rules with reality.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[Added wording so that inheritance depends on whether operational items are visible rather than whether they occur before the declaration (we don't want to look into private parts). Limited operational inheritance to untagged types to avoid anomolies with private extensions (this is not incompatible, no existing operational attribute used this capability). Also added wording to clearly define that subprogram inheritance works like derivation of subprograms.]} @end{DiffWord95} @LabeledClause{Pragma Pack} @begin{Intro} @redundant[A @nt{pragma} Pack specifies that storage minimization should be the main criterion when selecting the representation of a composite type.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Pack is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Pack)(@SynI{first_subtype_}@Syn2{local_name});' @end{Syntax} @begin{Legality} The @SynI{first_subtype_}@nt{local_name} of a @nt{pragma} Pack shall denote a composite subtype. @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Pack)} @PDefn2{Term=[pragma, representation], Sec=(Pack)} @PDefn2{Term=[aspect of representation], Sec=(packing)} @Defn2{Term=[packing], Sec=(aspect of representation)} @Defn{packed} A @nt{pragma} Pack specifies the @i{packing} aspect of representation; the type (or the extension part) is said to be @i{packed}. For a type extension, the parent part is packed as for the parent type, and a @nt{pragma} Pack causes packing only of the extension part. @begin{Ramification} The only high level semantic effect of a @nt{pragma} Pack is independent addressability (see @RefSec{Shared Variables}). @end{Ramification} @end{StaticSem} @begin{ImplAdvice} If a type is packed, then the implementation should try to minimize storage allocated to objects of the type, possibly at the expense of speed of accessing components, subject to reasonable complexity in addressing calculations. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Storage allocated to objects of a packed type should be minimized.]}]} @begin{Ramification} A @nt{pragma} Pack is for gaining space efficiency, possibly at the expense of time. If more explicit control over representation is desired, then a @nt{record_representation_clause}, a Component_Size clause, or a Size clause should be used instead of, or in addition to, a @nt{pragma} Pack. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[If a packed type has a component that is not of a by-reference type and has no aliased part, then such a component need not be aligned according to the Alignment of its subtype; in particular it need not be allocated on a storage element boundary.]} @Comment{No "should" here; thus no ImplAdvice entry. This really qualifies the item above} @Leading@PDefn2{Term=[recommended level of support], Sec=(pragma Pack)} The recommended level of support for pragma Pack is: @begin{Itemize} For a packed record type, the components should be packed as tightly as possible subject to the Sizes of the component subtypes, and subject to any @nt{record_representation_clause} that applies to the type; the implementation may, but need not, reorder components or cross aligned word boundaries to improve the packing. A component whose Size is greater than the word size may be allocated an integral number of words. @begin{Ramification} The implementation can always allocate an integral number of words for a component that will not fit in a word. The rule also allows small component sizes to be rounded up if such rounding does not waste space. For example, if Storage_Unit = 8, then a component of size 8 is probably more efficient than a component of size 7 plus a 1-bit gap (assuming the gap is needed anyway). @end{Ramification} For a packed array type, if the component subtype's Size is less than or equal to the word size, and Component_Size is not specified for the type, Component_Size should be less than or equal to the Size of the component subtype, rounded up to the nearest factor of the word size. @begin{Ramification} If a component subtype is aliased, its Size will generally be a multiple of Storage_Unit, so it probably won't get packed very tightly. @end{Ramification} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for pragma Pack should be followed.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Added clarification that pragma Pack can ignore alignment requirements on types that don't have by-reference or aliased parts. This was always intended, but there was no wording to that effect.]} @end{DiffWord95} @LabeledRevisedClause{Version=[1],New=[Operational and Representation Attributes], Old=[Representation Attributes]} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @redundant[@Defn{representation attribute} @Defn2{Term=[attribute], Sec=(representation)} The values of certain implementation-dependent characteristics can be obtained by interrogating appropriate @Chg{New=[operational or ],Old=[]}representation attributes. @RootDefn2{Term=[attribute], Sec=(specifying)} Some of these attributes are specifiable via an @nt{attribute_definition_clause}.] @end{Intro} @begin{MetaRules} In general, the meaning of a given attribute should not depend on whether the attribute was specified via an @nt{attribute_definition_clause}, or chosen by default by the implementation. @end{MetaRules} @begin{Syntax} @Syn{lhs=<attribute_definition_clause>,rhs=" @key{for} @Syn2{local_name}@SingleQuote@Syn2{attribute_designator} @key{use} @Syn2{expression}; | @key{for} @Syn2{local_name}@SingleQuote@Syn2{attribute_designator} @key{use} @Syn2{name};"} @end{Syntax} @begin{Resolution} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a value, the form with an @nt{expression} shall be used. Otherwise, the form with a @nt{name} shall be used. @PDefn2{Term=[expected type], Sec=(attribute_definition_clause expression or name)} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a value or an object, the expected type for the expression or @nt{name} is that of the attribute. @PDefn2{Term=[expected profile], Sec=(attribute_definition_clause name)} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a subprogram, the expected profile for the @nt{name} is the profile required for the attribute. For an @nt{attribute_definition_clause} that specifies an attribute that denotes some other kind of entity, the @nt{name} shall resolve to denote an entity of the appropriate kind. @begin{Ramification} For example, the Size attribute is of type @i{universal_integer}. Therefore, the expected type for Y in @lquotes@;@key[for] X'Size @key[use] Y;@rquotes@; is @i{universal_integer}, which means that Y can be of any integer type. @end{Ramification} @begin{Discussion} For attributes that denote subprograms, the required profile is indicated separately for the individual attributes. @end{Discussion} @begin{Ramification} @Leading@;For an @nt{attribute_definition_clause} with a @nt{name}, the @nt{name} need not statically denote the entity it denotes. For example, the following kinds of things are allowed: @begin{Example} @key[for] Some_Access_Type'Storage_Pool @key[use] Storage_Pool_Array(I); @key[for] Some_Type'Read @key[use] Subprogram_Pointer.@key[all]; @end{Example} @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @RootDefn{specifiable (of an attribute and for an entity)} @RootDefn2{Term=[attribute], Sec=(specifiable)} An @nt{attribute_designator} is allowed in an @nt{attribute_definition_clause} only if this International Standard explicitly allows it, or for an implementation-defined attribute if the implementation allows it. @PDefn2{Term=[aspect of representation], Sec=(specifiable attributes)} Each specifiable attribute constitutes an @Chg{New=[@PDefn2{Term=[operational aspect], Sec=(specifiable attributes)} operational aspect or ],Old=[]}aspect of representation. @begin{Discussion} For each specifiable attribute, we generally say something like, @lquotes@;The ... attribute may be specified for ... via an @nt{attribute_definition_clause}.@rquotes@; The above wording allows for T'Class'Alignment, T'Class'Size, T'Class'Input, and T'Class'Output to be specifiable. A specifiable attribute is not necessarily specifiable for all entities for which it is defined. For example, one is allowed to ask T'Component_Size for an array subtype T, but @lquotes@;@key[for] T'Component_Size @key[use] ...@rquotes@; is only allowed if T is a first subtype, because Component_Size is a type-related aspect. @end{Discussion} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a subprogram, the profile shall be mode conformant with the one required for the attribute, and the convention shall be Ada. Additional requirements are defined for particular attributes. @Defn2{Term=[mode conformance],Sec=(required)} @begin{Ramification} @Leading@;This implies, for example, that if one writes: @begin{Example} @key[for] T'Read @key[use] R; @end{Example} R has to be a procedure with two parameters with the appropriate subtypes and modes as shown in @RefSecNum{Stream-Oriented Attributes}. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00270-01]} @Defn{Address clause} @Defn{Alignment clause} @Defn{Size clause} @Defn{Component_Size clause} @Defn{External_Tag clause} @Defn{Small clause} @Defn{Bit_Order clause} @Defn{Storage_Pool clause} @Defn{Storage_Size clause}@Chg{Version=[2],New=[ @Defn{Stream_Size clause}],Old=[]} @Defn{Read clause} @Defn{Write clause} @Defn{Input clause} @Defn{Output clause} @Defn{Machine_Radix clause} A @i{Size clause} is an @nt{attribute_definition_clause} whose @nt{attribute_designator} is Size. Similar definitions apply to the other specifiable attributes. @begin{Honest} @PDefn2{Term=[type-related], Sec=(attribute_definition_clause)} @PDefn2{Term=[subtype-specific], Sec=(attribute_definition_clause)} An @nt{attribute_definition_clause} is type-related or subtype-specific if the @nt{attribute_designator} denotes a type-related or subtype-specific attribute, respectively. @end{Honest} @Defn{storage element} @IndexSee{Term=[byte],See=(storage element)} A @i{storage element} is an addressable element of storage in the machine. @Defn{word} A @i{word} is the largest amount of storage that can be conveniently and efficiently manipulated by the hardware, given the implementation's run-time model. A word consists of an integral number of storage elements. @begin{Discussion} A storage element is not intended to be a single bit, unless the machine can efficiently address individual bits. @end{Discussion} @begin{Ramification} For example, on a machine with 8-bit storage elements, if there exist 32-bit integer registers, with a full set of arithmetic and logical instructions to manipulate those registers, a word ought to be 4 storage elements @em that is, 32 bits. @end{Ramification} @begin{Discussion} The @lquotes@;given the implementation's run-time model@rquotes@; part is intended to imply that, for example, on an 80386 running MS-DOS, the word might be 16 bits, even though the hardware can support 32 bits. A word is what ACID refers to as a @lquotes@;natural hardware boundary@rquotes@;. Storage elements may, but need not be, independently addressable (see @RefSec{Shared Variables}). Words are expected to be independently addressable. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[@Defn{machine scalar} A @i{machine scalar} is an amount of storage that can be conveniently and efficiently loaded, stored, or operated upon by the hardware. Machine scalars consist of an integral number of storage elements. The set of machine scalars is implementation defined, but must include at least the storage element and the word. Machine scalars are used to interpret @nt{component_clause}s when the nondefault bit ordering applies.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The set of machine scalars.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[The following representation attributes are defined: Address, Alignment, Size, Storage_Size, and Component_Size.], Old=[@Leading@;The following attributes are defined:]} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an object, program unit, or label]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Address>, Text=<Denotes the address of the first of the storage elements allocated to X. For a program unit or label, this value refers to the machine code associated with the corresponding body or @nt{statement}. The value of this attribute is of type System.Address.>} @begin{Ramification} Here, the @lquotes@;first of the storage elements@rquotes@; is intended to mean the one with the lowest address; the endianness of the machine doesn't matter. @end{Ramification} @NoPrefix@;@PDefn2{Term=[specifiable], Sec=(of Address for stand-alone objects and for program units)} @Defn{Address clause} @ChgNote{Removed Redundant here, as per AI-00114. Did not mark change, as it is AARM-only, not to the text of the item.}Address may be specified for stand-alone objects and for program units via an @nt{attribute_definition_clause}. @begin{Ramification} Address is not allowed for enumeration literals, predefined operators, derived task types, or derived protected types, since they are not program units. The validity of a given address depends on the run-time model; thus, in order to use Address clauses correctly, one needs intimate knowledge of the run-time model. If the Address of an object is specified, any explicit or implicit initialization takes place as usual, unless a @nt{pragma} Import is also specified for the object (in which case any necessary initialization is presumably done in the foreign language). Any compilation unit containing an @nt<attribute_reference> of a given type depends semantically on the declaration of the package in which the type is declared, even if not mentioned in an applicable @nt<with_clause> @em see @RefSecNum{Compilation Units - Library Units}. In this case, it means that if a compilation unit contains X'Address, then it depends on the declaration of System. Otherwise, the fact that the value of Address is of a type in System wouldn't make sense; it would violate the @lquotes@;legality determinable via semantic dependences@rquotes@; @MetaRulesName. AI83-00305 @em If X is a task type, then within the body of X, X denotes the current task object; thus, X'Address denotes the object's address. Interrupt entries and their addresses are described in @RefSec{Interrupt Entries}. If X is not allocated on a storage element boundary, X'Address points at the first of the storage elements that contains any part of X. This is important for the definition of the Position attribute to be sensible. @end{Ramification} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)}If an Address is specified, it is the programmer's responsibility to ensure that the address is valid; otherwise, program execution is erroneous. @end{Erron} @begin{ImplAdvice} For an array X, X'Address should point at the first component of the array, and not at the array bounds. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For an array X, X'Address should point at the first component of the array rather than the array bounds.]}]} @begin{Ramification} On the other hand, we have no advice to offer about discriminants and tag fields; whether or not the address points at them is not specified by the language. If discriminants are stored separately, then the Position of a discriminant might be negative, or might raise an exception. @end{Ramification} @PDefn2{Term=[recommended level of support], Sec=(Address attribute)} @Leading@;The recommended level of support for the Address attribute is: @begin{Itemize} X'Address should produce a useful result if X is an object that is aliased or of a by-reference type, or is an entity whose Address has been specified. @begin{Reason} Aliased objects are the ones for which the Unchecked_Access attribute is allowed; hence, these have to be allocated on an addressable boundary anyway. Similar considerations apply to objects of a by-reference type. An implementation need not go to any trouble to make Address work in other cases. For example, if an object X is not aliased and not of a by-reference type, and the implementation chooses to store it in a register, X'Address might return System.Null_Address (assuming registers are not addressable). For a subprogram whose calling convention is Intrinsic, or for a package, the implementation need not generate an out-of-line piece of code for it. @end{Reason} An implementation should support Address clauses for imported subprograms. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Text=[Objects (including subcomponents) that are aliased or of a by-reference type should be allocated on storage element boundaries.]} @Comment{There is a now a blanket permission to this effect} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[This is necessary for the Address attribute to be useful (since First_Bit and Last_Bit apply only to components). Implementations generally need to do this anyway, for tasking to work properly.]} @end{Reason} If the Address of an object is specified, or it is imported or exported, then the implementation should not perform optimizations based on assumptions of no aliases. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Address attribute should be followed.]}]} @end{ImplAdvice} @begin{Notes} The specification of a link name in a @nt{pragma} Export (see @RefSecNum{Interfacing Pragmas}) for a subprogram or object is an alternative to explicit specification of its link-time address, allowing a link-time directive to place the subprogram or object within memory. The rules for the Size attribute imply, for an aliased object X, that if X'Size = Storage_Unit, then X'Address points at a storage element containing all of the bits of X, and only the bits of X. @end{Notes} @begin{DiffWord83} The intended meaning of the various attributes, and their @nt{attribute_definition_clause}s, is more explicit. The @ntf{address_clause} has been renamed to @nt{at_clause} and moved to @RefSec{Obsolescent Features}. One can use an Address clause (@lquotes@;for T'Address @key[use] ...;@rquotes@;) instead. The attributes defined in RM83-13.7.3 are moved to @RefSecNum{Numerics}, @RefSecNum{Attributes of Floating Point Types}, and @RefSecNum{Attributes of Fixed Point Types}. @end{DiffWord83} @begin{MetaRules} By default, the Alignment of a subtype should reflect the @lquotes@;natural@rquotes@; alignment for objects of the subtype on the machine. The Alignment, whether specified or default, should be known at compile time, even though Addresses are generally not known at compile time. (The generated code should never need to check at run time the number of zero bits at the end of an address to determine an alignment). There are two symmetric purposes of Alignment clauses, depending on whether or not the implementation has control over object allocation. If the implementation allocates an object, the implementation should ensure that the Address and Alignment are consistent with each other. If something outside the implementation allocates an object, the implementation should be allowed to assume that the Address and Alignment are consistent, but should not assume stricter alignments than that. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes @Chg{Version=[2],New=[an], Old=[a subtype or]} object]}: @begin{Description} @ChgAttribute{Version=[2], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<X>, AttrName=<Alignment>, ARef=[AI95-00291-02], Text=[@Chg{Version=[2],New=[The value of this attribute is of type @i{universal_integer}, and nonnegative; zero means that the object is not necessarily aligned on a storage element boundary. If X'Alignment is not zero, then X is aligned on a storage unit boundary and X'Address], Old=[The Address of an object that is allocated under control of the implementation]} is an integral multiple of @Chg{Version=[2],New=[X'Alignment],Old=[the Alignment of the object]} (that is, the Address modulo the Alignment is zero).@Chg{Version=[2], New=[],Old=[The offset of a record component is a multiple of the Alignment of the component. For an object that is not allocated under control of the implementation (that is, one that is imported, that is allocated by a user-defined allocator, whose Address has been specified, or is designated by an access value returned by an instance of Unchecked_Conversion), the implementation may assume that the Address is an integral multiple of its Alignment. The implementation shall not assume a stricter alignment.]} @Comment{Deleted below causes trouble in the generated text for attributes, but no fix appears to be possible. And the trouble is much worse in the RTF version than the HTML version, so for now we're making a hand fix.} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The value of this attribute is of type @i{universal_integer}, and nonnegative; zero means that the object is not necessarily aligned on a storage element boundary.]}]}@Comment{End X'Alignment} @EndPrefixType{} @begin{Ramification} The Alignment is passed by an @nt{allocator} to the Allocate operation; the implementation has to choose a value such that if the address returned by Allocate is aligned as requested, the generated code can correctly access the object. The above mention of @lquotes@;modulo@rquotes@; is referring to the "@key[mod]" operator declared in System.Storage_Elements; if X @key[mod] N = 0, then X is by definition aligned on an N-storage-element boundary. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @NoPrefix@Chg{Version=[2],New=[@PDefn2{Term=[specifiable], Sec=(of Alignment for objects)}], Old=[@PDefn2{Term=[specifiable], Sec=(of Alignment for first subtypes and objects)}]} @Defn{Alignment clause} Alignment may be specified for@Chg{Version=[2],New=[],Old=[ first subtypes and]} @Redundant[stand-alone] objects via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative.@Chg{Version=[2],New=[],Old=[If the Alignment of a subtype is specified, then the Alignment of an object of the subtype is at least as strict, unless the object's Alignment is also specified. The Alignment of an object created by an allocator is that of the designated subtype.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00247-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[If an Alignment is specified for a composite subtype or object, this Alignment shall be equal to the least common multiple of any specified Alignments of the subcomponent subtypes, or an integer multiple thereof.]} @end{Description} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T], Text=[For @PrefixType{every subtype S}:]} @begin{Description} @ChgAttribute{Version=[2], Kind=[Added], ChginAnnex=[T], Leading=[F], Prefix=<S>, AttrName=<Alignment>, ARef=[AI95-00291-02], Text=[@Chg{Version=[2],New=[The value of this attribute is of type @i{universal_integer}, and nonnegative.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],NoPrefix=[T], Text=[For an object X of subtype S, if S'Alignment is not zero, then X'Alignment is a nonzero integral multiple of S'Alignment unless specified otherwise by a representation item.]}]}@Comment{End S'Alignment} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],NoPrefix=[T], Text=[@PDefn2{Term=[specifiable], Sec=(of Alignment for first subtypes)} @Defn{Alignment clause} Alignment may be specified for first subtypes via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative.]} @end{Description} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if an Address clause is given that conflicts with the Alignment. @begin{Ramification} The user has to either give an Alignment clause also, or else know what Alignment the implementation will choose by default. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @PDefn2{Term=(erroneous execution),Sec=(cause)} @Chg{Version=[2],New=[For],Old=[If the Alignment is specified for]} an object that is not allocated under control of the implementation, execution is erroneous if the object is not aligned according to @Chg{Version=[2],New=[its],Old=[the]} Alignment. @end{Erron} @begin{ImplAdvice} @PDefn2{Term=[recommended level of support], Sec=(Alignment attribute for subtypes)} @Leading@;The recommended level of support for the Alignment attribute for subtypes is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation should support @Chg{Version=[2],New=[an Alignment clause for a discrete type, fixed point type, record type, or array type, specifying an Alignment value that is zero or a power of two],Old=[specified Alignments that are factors and multiples of the number of storage elements per word]}, subject to the following: @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation need not support @Chg{Version=[2], New=[an Alignment clause for a signed integer type specifying an Alignment greater than the largest Alignment value that is ever chosen by default by the implementation for any signed integer type. A corresponding limitation may be imposed for modular integer types, fixed point types, enumeration types, record types, and array types],Old=[specified Alignments for combinations of Sizes and Alignments that cannot be easily loaded and stored by available machine instructions]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation need not support @Chg{Version=[2],New=[a nonconfirming Alignment clause which could enable the creation of an object of an elementary type which cannot be easily loaded and stored by available machine instructions.], Old=[specified Alignments that are greater than the maximum Alignment the implementation ever returns by default.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support an Alignment specified for a derived tagged type which is not a multiple of the Alignment of the parent type. An implementation need not support a nonconfirming Alignment specified for a derived untagged by-reference type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[There is no recommendation to support any nonconfirming Alignment clauses for types not mentioned above. Remember that @RefSecNum{Operational and Representation Items} requires support for confirming Alignment clauses for all types.]} @end{Ramification} @end{Itemize} @Leading@PDefn2{Term=[recommended level of support], Sec=(Alignment attribute for objects)} The recommended level of support for the Alignment attribute for objects is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Text=[Same as above, for subtypes, but in addition:]} For stand-alone library-level objects of statically constrained subtypes, the implementation should support all Alignments supported by the target linker. For example, page alignment is likely to be supported for such objects, but not for subtypes. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[For other objects, an implementation should at least support the alignments supported for their subtype, subject to the following:]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support Alignments specified for objects of a by-reference type or for objects of types containing aliased subcomponents if the specified Alignment is not a multiple of the Alignment of the subtype of the object.]} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Alignment attribute should be followed.]}]} @end{ImplAdvice} @begin{Notes} Alignment is a subtype-specific attribute. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00247-01]} @ChgDeleted{Version=[2],Text=[The Alignment of a composite object is always equal to the least common multiple of the Alignments of its components, or a multiple thereof.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[For default Alignments, this follows from the semantics of Alignment. For specified Alignments, it follows from a @LegalityName stated above.]} @end{Discussion} A @nt{component_clause}, Component_Size clause, or a @nt{pragma} Pack can override a specified Alignment. @begin{Discussion} Most objects are allocated by the implementation; for these, the implementation obeys the Alignment. The implementation is of course allowed to make an object @i{more} aligned than its Alignment requires @em an object whose Alignment is 4 might just happen to land at an address that's a multiple of 4096. For formal parameters, the implementation might want to force an Alignment stricter than the parameter's subtype. For example, on some systems, it is customary to always align parameters to 4 storage elements. Hence, one might initially assume that the implementation could evilly make all Alignments 1 by default, even though integers, say, are normally aligned on a 4-storage-element boundary. However, the implementation cannot get away with that @em if the Alignment is 1, the generated code cannot assume an Alignment of 4, at least not for objects allocated outside the control of the implementation. Of course implementations can assume anything they can prove, but typically an implementation will be unable to prove much about the alignment of, say, an imported object. Furthermore, the information about where an address @lquotes@;came from@rquotes@; can be lost to the compiler due to separate compilation. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The Alignment of an object that is a component of a packed composite object will usually be 0, to indicate that the component is not necessarily aligned on a storage element boundary. For a subtype, an Alignment of 0 means that objects of the subtype are not normally aligned on a storage element boundary at all. For example, an implementation might choose to make Component_Size be @Chg{Version=[2],New=[1],Old=[0]} for an array of Booleans, even when @nt{pragma} Pack has not been specified for the array. In this case, Boolean'Alignment would be 0. (In the presence of tasking, this would in general be feasible only on a machine that had atomic test-bit and set-bit instructions.) If the machine has no particular natural alignments, then all subtype Alignments will probably be 1 by default. Specifying an Alignment of 0 in an @nt{attribute_definition_clause} does not require the implementation to do anything (except return 0 when the Alignment is queried). However, it might be taken as advice on some implementations. It is an error for an Address clause to disobey the object's Alignment. The error cannot be detected at compile time, in general, because the Address is not necessarily known at compile time (and is almost certainly not static). We do not require a run-time check, since efficiency seems paramount here, and Address clauses are treading on thin ice anyway. Hence, this misuse of Address clauses is just like any other misuse of Address clauses @em it's erroneous. A type extension can have a stricter Alignment than its parent. This can happen, for example, if the Alignment of the parent is 4, but the extension contains a component with Alignment 8. The Alignment of a class-wide type or object will have to be the maximum possible Alignment of any extension. The recommended level of support for the Alignment attribute is intended to reflect a minimum useful set of capabilities. An implementation can assume that all Alignments are multiples of each other @em 1, 2, 4, and 8 might be the only supported Alignments for subtypes. An Alignment of 3 or 6 is unlikely to be useful. For objects that can be allocated statically, we recommend that the implementation support larger alignments, such as 4096. We do not recommend such large alignments for subtypes, because the maximum subtype alignment will also have to be used as the alignment of stack frames, heap objects, and class-wide objects. Similarly, we do not recommend such large alignments for stack-allocated objects. If the maximum default Alignment is 8 (say, Long_Float'Alignment = 8), then the implementation can refuse to accept stricter alignments for subtypes. This simplifies the generated code, since the compiler can align the stack and class-wide types to this maximum without a substantial waste of space (or time). Note that the recommended level of support takes into account interactions between Size and Alignment. For example, on a 32-bit machine with 8-bit storage elements, where load and store instructions have to be aligned according to the size of the thing being loaded or stored, the implementation might accept an Alignment of 1 if the Size is 8, but might reject an Alignment of 1 if the Size is 32. On a machine where unaligned loads and stores are merely inefficient (as opposed to causing hardware traps), we would expect an Alignment of 1 to be supported for any Size. @end{Discussion} @end{Notes} @begin{DiffWord83} The nonnegative part is missing from RM83 (for @nt{mod_clause}s, nee @ntf{alignment_clause}s, which are an obsolete version of Alignment clauses). @end{DiffWord83} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an object]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Size>, Text=<Denotes the size in bits of the representation of the object. The value of this attribute is of the type @i{universal_integer}.>} @EndPrefixType{} @begin{Ramification} Note that Size is in bits even if Machine_Radix is 10. Each decimal digit (and the sign) is presumably represented as some number of bits. @end{Ramification} @NoPrefix@PDefn2{Term=[specifiable], Sec=(of Size for stand-alone objects)} @Defn{Size clause} Size may be specified for @Redundant[stand-alone] objects via an @nt{attribute_definition_clause}; the expression of such a clause shall be static and its value nonnegative. @end{Description} @end{StaticSem} @begin{ImplAdvice} @ChgNote{Moved from 13.9} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[The size of an array object should not include its bounds.]} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The Size of an array object should not include its bounds.]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Type=[Leading],Text=[]}@Comment{A fake to get a conditional Leading} @PDefn2{Term=[recommended level of support], Sec=(Size attribute)} The recommended level of support for the Size attribute of objects is@Chg{Version=[2],New=[ the same as for subtypes (see below), except that only a confirming Size clause need be supported for an aliased elementary object.],Old=[:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00051-02]} @ChgDeleted{Version=[2],Text=[A Size clause should be supported for an object if the specified Size is at least as large as its subtype's Size, and corresponds to a size in storage elements that is a multiple of the object's Alignment (if the Alignment is nonzero).]} @Comment{No ImplDef summary here; there is no reason to separately mention it} @end{Itemize} @end{ImplAdvice} @begin{StaticSem} @Leading@Keepnext@;For @PrefixType{every subtype S}: @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Size>, Text=<If S is definite, denotes the size @Redundant{(in bits)} that the implementation would choose for the following objects of subtype S: @begin{Itemize} A record component of subtype S when the record type is packed. The formal parameter of an instance of Unchecked_Conversion that converts from subtype S to some other subtype. @end{Itemize} @NoPrefix@;If S is indefinite, the meaning is implementation defined. The value of this attribute is of the type @i{universal_integer}.>} @PDefn2{Term=[specifiable], Sec=(of Size for first subtypes)} @Defn{Size clause} The Size of an object is at least as large as that of its subtype, unless the object's Size is determined by a Size clause, a component_clause, or a Component_Size clause. Size may be specified for first subtypes via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static and its value nonnegative. @ImplDef{The meaning of Size for indefinite subtypes.} @begin{Reason} @Leading@;The effects of specifying the Size of a subtype are: @begin{Itemize} Unchecked_Conversion works in a predictable manner. A composite type cannot be packed so tightly as to override the specified Size of a component's subtype. Assuming the @ImplAdviceName is obeyed, if the specified Size allows independent addressability, then the Size of certain objects of the subtype should be equal to the subtype's Size. This applies to stand-alone objects and to components (unless a @nt{component_clause} or a Component_Size clause applies). @end{Itemize} A @nt{component_clause} or a Component_Size clause can cause an object to be smaller than its subtype's specified size. A @nt{pragma} Pack cannot; if a component subtype's size is specified, this limits how tightly the composite object can be packed. The Size of a class-wide (tagged) subtype is unspecified, because it's not clear what it should mean; it should certainly not depend on all of the descendants that happen to exist in a given program. Note that this cannot be detected at compile time, because in a generic unit, it is not necessarily known whether a given subtype is class-wide. It might raise an exception on some implementations. @end{Reason} @begin{Ramification} @Leading@;A Size clause for a numeric subtype need not affect the underlying numeric type. For example, if I say: @begin{Example} @key[type] S @key[is] @key[range] 1..2; @key[for] S'Size @key[use] 64; @end{Example} I am not guaranteed that S'Base'Last >= 2**63@en@;1, nor that intermediate results will be represented in 64 bits. @end{Ramification} @begin{Reason} There is no need to complicate implementations for this sort of thing, because the right way to affect the base range of a type is to use the normal way of declaring the base range: @begin{Example} @key[type] Big @key[is] @key[range] -2**63 .. 2**63 - 1; @key[subtype] Small @key[is] Big @key[range] 1..1000; @end{Example} @end{Reason} @begin{Ramification} The Size of a large unconstrained subtype (e.g. String'Size) is likely to raise Constraint_Error, since it is a nonstatic expression of type @i{universal_integer} that might overflow the largest signed integer type. There is no requirement that the largest integer type be able to represent the size in bits of the largest possible object. @end{Ramification} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplReq} In an implementation, Boolean'Size shall be 1. @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} @Leading@;If the Size of a subtype @Chg{Version=[2],New=[],Old=[is specified, and ]}allows for efficient independent addressability (see @RefSecNum{Shared Variables}) on the target architecture, then the Size of the following objects of the subtype should equal the Size of the subtype: @begin{Itemize} Aliased objects (including components). Unaliased components, unless the Size of the component is determined by a @nt{component_clause} or Component_Size clause. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If the Size of a subtype allows for efficient independent addressability, then the Size of most objects of the subtype should equal the Size of the subtype.]}]} @begin{Ramification} Thus, on a typical 32-bit machine, @lquotes@;@key[for] S'Size @key[use] 32;@rquotes@; will guarantee that aliased objects of subtype S, and components whose subtype is S, will have Size = 32 (assuming the implementation chooses to obey this @ImplAdviceTitle). On the other hand, if one writes, @lquotes@;@key[for] S2'Size @key[use] 5;@rquotes@; then stand-alone objects of subtype S2 will typically have their Size rounded up to ensure independent addressability. Note that @lquotes@;@key[for] S'Size @key[use] 32;@rquotes@; does not cause things like formal parameters to have Size = 32 @em the implementation is allowed to make all parameters be at least 64 bits, for example. Note that @lquotes@;@key[for] S2'Size @key[use] 5;@rquotes@; requires record components whose subtype is S2 to be exactly 5 bits if the record type is packed. The same is not true of array components; their Size may be rounded up to the nearest factor of the word size. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Defn{gaps} On most machines, arrays don't contain gaps between @Chg{Version=[2], New=[elementary ],Old=[]}components; if the Component_Size is greater than the Size of the component subtype, the extra bits are generally considered part of each component, rather than gaps between components. On the other hand, a record might contain gaps between @Chg{Version=[2], New=[elementary ],Old=[]}components, depending on what sorts of loads, stores, and masking operations are generally done by the generated code. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} For an array, any extra bits stored for each @Chg{Version=[2], New=[elementary ],Old=[]}component will generally be part of the component @em the whole point of storing extra bits is to make loads and stores more efficient by avoiding the need to mask out extra bits. The PDP-10 is one counter-example; since the hardware supports byte strings with a gap at the end of each word, one would want to pack in that manner. @end{ImplNote} A Size clause on a composite subtype should not affect the internal layout of components. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[A Size clause on a composite subtype should not affect the internal layout of components.]}]} @begin{Reason} That's what Pack @nt{pragma}s, @nt{record_representation_clause}s, and Component_Size clauses are for. @end{Reason} @Leading@PDefn2{Term=[recommended level of support], Sec=(Size attribute)} The recommended level of support for the Size attribute of subtypes is: @begin{Itemize} The Size (if not specified) of a static discrete or fixed point subtype should be the number of bits needed to represent each value belonging to the subtype using an unbiased representation, leaving space for a sign bit only if the subtype contains negative values. If such a subtype is a first subtype, then an implementation should support a specified Size for it that reflects this representation. @begin{ImplNote} This applies to static enumeration subtypes, using the internal codes used to represent the values. For a two's-complement machine, this implies that for a static signed integer subtype S, if all values of S are in the range 0 .. 2@+{@i{n}}@en@;1, or all values of S are in the range @en@;2@+{@i{n@en@;1}} .. 2@+{@i{n@en@;1}}@en@;1, for some @i{n} less than or equal to the word size, then S'Size should be <= the smallest such @i{n}. For a one's-complement machine, it is the same except that in the second range, the lower bound @lquotes@;@en@;2@+{@i{n@en@;1}}@rquotes@; is replaced by @lquotes@;@en@;2@+{@i{n@en@;1}}+1@rquotes@;. If an integer subtype (whether signed or unsigned) contains no negative values, the Size should not include space for a sign bit. Typically, the implementation will choose to make the Size of a subtype be exactly the smallest such @i{n}. However, it might, for example, choose a biased representation, in which case it could choose a smaller value. On most machines, it is in general not a good idea to pack (parts of) multiple stand-alone objects into the same storage element, because (1) it usually doesn't save much space, and (2) it requires locking to prevent tasks from interfering with each other, since separate stand-alone objects are independently addressable. Therefore, if S'Size = 2 on a machine with 8-bit storage elements, the size of a stand-alone object of subtype S will probably not be 2. It might, for example, be 8, 16 or 32, depending on the availability and efficiency of various machine instructions. The same applies to components of composite types, unless packing, Component_Size, or record layout is specified. For an unconstrained discriminated object, if the implementation allocates the maximum possible size, then the Size attribute should return that maximum possible size. @end{ImplNote} @begin{Ramification} The Size of an object X is not usually the same as that of its subtype S. If X is a stand-alone object or a parameter, for example, most implementations will round X'Size up to a storage element boundary, or more, so X'Size might be greater than S'Size. On the other hand, X'Size cannot be less than S'Size, even if the implementation can prove, for example, that the range of values actually taken on by X during execution is smaller than the range of S. For example, if S is a first integer subtype whose range is 0..3, S'Size will be probably be 2 bits, and components of packed composite types of this subtype will be 2 bits (assuming Storage_Unit is a multiple of 2), but stand-alone objects and parameters will probably not have a size of 2 bits; they might be rounded up to 32 bits, for example. On the other hand, Unchecked_Conversion will use the 2-bit size, even when converting a stand-alone object, as one would expect. Another reason for making the Size of an object bigger than its subtype's Size is to support the run-time detection of uninitialized variables. @PDefn{uninitialized variables} The implementation might add an extra value to a discrete subtype that represents the uninitialized state, and check for this value on use. In some cases, the extra value will require an extra bit in the representation of the object. Such detection is not required by the language. If it is provided, the implementation has to be able to turn it off. For example, if the programmer gives a @nt{record_representation_clause} or Component_Size clause that makes a component too small to allow the extra bit, then the implementation will not be able to perform the checking (not using this method, anyway). @Leading@;The fact that the size of an object is not necessarily the same as its subtype can be confusing: @begin{Example} @key[type] Device_Register @key[is] @key[range] 0..2**8 - 1; @key[for] Device_Register'Size @key[use] 8; --@RI{ Confusing!} My_Device : Device_Register; @key[for] My_Device'Address @key[use] To_Address(16#FF00#); @end{Example} The programmer might think that My_Device'Size is 8, and that My_Device'Address points at an 8-bit location. However, this is not true. In Ada 83 (and in Ada 95), My_Device'Size might well be 32, and My_Device'Address might well point at the high-order 8 bits of the 32-bit object, which are always all zero bits. If My_Device'Address is passed to an assembly language subprogram, based on the programmer's assumption, the program will not work properly. @end{Ramification} @begin{Reason} It is not reasonable to require that an implementation allocate exactly 8 bits to all objects of subtype Device_Register. For example, in many run-time models, stand-alone objects and parameters are always aligned to a word boundary. Such run-time models are generally based on hardware considerations that are beyond the control of the implementer. (It is reasonable to require that an implementation allocate exactly 8 bits to all components of subtype Device_Register, if packed.) @end{Reason} @begin{Ramification} @Leading@;The correct way to write the above code is like this: @begin{Example} @key[type] Device_Register @key[is] @key[range] 0..2**8 - 1; My_Device : Device_Register; @key[for] My_Device'Size @key[use] 8; @key[for] My_Device'Address @key[use] To_Address(16#FF00#); @end{Example} If the implementation cannot accept 8-bit stand-alone objects, then this will be illegal. However, on a machine where an 8-bit device register exists, the implementation will probably be able to accept 8-bit stand-alone objects. Therefore, My_Device'Size will be 8, and My_Device'Address will point at those 8 bits, as desired. If an object of subtype Device_Register is passed to a foreign language subprogram, it will be passed according to that subprogram's conventions. Most foreign language implementations have similar run-time model restrictions. For example, when passing to a C function, where the argument is of the C type char* (that is, pointer to char), the C compiler will generally expect a full word value, either on the stack, or in a register. It will @i{not} expect a single byte. Thus, Size clauses for subtypes really have nothing to do with passing parameters to foreign language subprograms. @end{Ramification} For a subtype implemented with levels of indirection, the Size should include the size of the pointers, but not the size of what they point at. @begin{Ramification} For example, if a task object is represented as a pointer to some information (including a task stack), then the size of the object should be the size of the pointer. The Storage_Size, on the other hand, should include the size of the stack. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[An implementation should support a Size clause for a discrete type, fixed point type, record type, or array type, subject to the following:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[An implementation need not support a Size clause for a signed integer type specifying a Size greater than that of the largest signed integer type supported by the implementation in the absence of a size clause (that is, when the size is chosen by default). A corresponding limitation may be imposed for modular integer types, fixed point types, enumeration types, record types, and array types.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[Note that the @lquotes@;corresponding limitation@rquotes for a record or array type implies that an implementation may impose some reasonable maximum size for records and arrays (e.g. 2**32 bits), which is an upper bound (@lquotes@;capacity@rquotes limit) on the size, whether chosen by default or by being specified by the user. The largest size supported for records need not be the same as the largest size supported for arrays.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[A nonconfirming size clause for the first subtype of a derived untagged by-reference type need not be supported.]} @end{InnerItemize} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Size attribute should be followed.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[There is no recommendation to support any nonconfirming Size clauses for types not mentioned above. Remember that @RefSecNum{Operational and Representation Items} requires support for confirming Size clauses for all types.]} @end{Ramification} @end{ImplAdvice} @begin{Notes} Size is a subtype-specific attribute. A @nt{component_clause} or Component_Size clause can override a specified Size. A @nt{pragma} Pack cannot. @end{Notes} @begin{Inconsistent83} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[We specify the meaning of Size in much more detail than Ada 83. This is not technically an inconsistency, but it is in practice, as most Ada 83 compilers use a different definition for Size than is required here. This should have been documented more explicitly during the Ada 9X process.]} @end{Inconsistent83} @begin{DiffWord83} The requirement for a nonnegative value in a Size clause was not in RM83, but it's hard to see how it would make sense. For uniformity, we forbid negative sizes, rather than letting implementations define their meaning. @end{DiffWord83} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} T that denotes a task object @Redundant[(after any implicit dereference)]]}: @begin{Description} @Attribute{Prefix=<T>, AttrName=<Storage_Size>, Text=<Denotes the number of storage elements reserved for the task. The value of this attribute is of the type @i{universal_integer}. The Storage_Size includes the size of the task's stack, if any. The language does not specify whether or not it includes other storage associated with the task (such as the @lquotes@;task control block@rquotes@; used by some implementations.)>} If a @nt{pragma} Storage_Size is given, the value of the Storage_Size attribute is at least the value specified in the @nt{pragma}. @EndPrefixType{} @begin{Ramification} The value of this attribute is never negative, since it is impossible to @lquotes@;reserve@rquotes@; a negative number of storage elements. If the implementation chooses to allocate an initial amount of storage, and then increase this as needed, the Storage_Size cannot include the additional amounts (assuming the allocation of the additional amounts can raise Storage_Error); this is inherent in the meaning of @lquotes@;reserved.@rquotes@; The implementation is allowed to allocate different amounts of storage for different tasks of the same subtype. Storage_Size is also defined for access subtypes @em see @RefSecNum{Storage Management}. @end{Ramification} @end{Description} @end{StaticSem} @begin{Intro} @redundant[@IndexSeeAlso{Term=[Storage_Size clause],See=[pragma Storage_Size]} A @nt{pragma} Storage_Size specifies the amount of storage to be reserved for the execution of a task.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@;The form of a @nt{pragma} Storage_Size is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Storage_Size)(@Syn2{expression});' @begin{SyntaxText} A @nt{pragma} Storage_Size is allowed only immediately within a @nt{task_definition}. @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(Storage_Size pragma argument)} The @nt{expression} of a @nt<pragma> Storage_Size is expected to be of any integer type. @end{Resolution} @begin{RunTime} A @nt<pragma> Storage_Size is elaborated when an object of the type defined by the immediately enclosing @nt<task_definition> is created. @PDefn2{Term=[elaboration],Sec=(Storage_Size pragma)} For the elaboration of a @nt<pragma> Storage_Size, the @nt<expression> is evaluated; the Storage_Size attribute of the newly created task object is at least the value of the @nt<expression>. @begin{Ramification} The implementation is allowed to round up a specified Storage_Size amount. For example, if the implementation always allocates in chunks of 4096 bytes, the number 200 might be rounded up to 4096. Also, if the user specifies a negative number, the implementation has to normalize this to 0, or perhaps to a positive number. @end{Ramification} @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} At the point of task object creation, or upon task activation, Storage_Error is raised if there is insufficient free storage to accommodate the requested Storage_Size. @end{RunTime} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an array subtype or array object @Redundant[(after any implicit dereference)]]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Component_Size>, Text=<Denotes the size in bits of components of the type of X. The value of this attribute is of type @i{universal_integer}.>} @EndPrefixType{} @NoPrefix@PDefn2{Term=[specifiable], Sec=(of Component_Size for array types)}@Defn{Component_Size clause} Component_Size may be specified for array types via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative. @begin{ImplNote} The intent is that the value of X'Component_Size is always nonnegative. If the array is stored @lquotes@;backwards@rquotes@; in memory (which might be caused by an implementation-defined pragma), X'Component_Size is still positive. @end{ImplNote} @begin{Ramification} For an array object A, A'Component_Size = A(I)'Size for any index I. @end{Ramification} @end{Description} @end{StaticSem} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(Component_Size attribute)} The recommended level of support for the Component_Size attribute is: @begin{Itemize} An implementation need not support specified Component_Sizes that are less than the Size of the component subtype. An implementation should support specified Component_Sizes that are factors and multiples of the word size. For such Component_Sizes, the array should contain no gaps between components. For other Component_Sizes (if supported), the array should contain no gaps between components when packing is also specified; the implementation should forbid this combination in cases where it cannot support a no-gaps representation. @begin{Ramification} For example, if Storage_Unit = 8, and Word_Size = 32, then the user is allowed to specify a Component_Size of 1, 2, 4, 8, 16, and 32, with no gaps. In addition, @i{n}*32 is allowed for positive integers @i{n}, again with no gaps. If the implementation accepts Component_Size = 3, then it might allocate 10 components per word, with a 2-bit gap at the end of each word (unless packing is also specified), or it might not have any internal gaps at all. (There can be gaps at either end of the array.) @end{Ramification} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Component_Size attribute should be followed.]}]} @end{ImplAdvice} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[The following operational attribute is defined: External_Tag.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Leading@;For @PrefixType{every subtype S of a tagged type @i(T) (specific or class-wide)}@Chg{New=[],Old=[, the following attribute is defined]}: @begin{Description} @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<External_Tag>, Ref=[8652/0040], ARef=[AI95-00108-01], Text=[@Defn{External_Tag clause} @PDefn2{Term=(specifiable), Sec=(of External_Tag for a tagged type)} S'External_Tag denotes an external string representation for S'Tag; it is of the predefined type String. External_Tag may be specified for a specific tagged type via an @nt{attribute_definition_clause}; the expression of such a clause shall be static. The default external tag representation is implementation defined. See @RefSecNum{Dispatching Operations of Tagged Types} and @RefSecNum{Stream-Oriented Attributes}.]} @Chg{New=[The value of External_Tag is never inherited@Redundant[; the default value is always used unless a new value is directly specified for a type].],Old=[]} @ImplDef{The default external representation for a type tag.} @end{Description} @EndPrefixType() @end{StaticSem} @begin{ImplReq} In an implementation, the default external tag for each specific tagged type declared in a partition shall be distinct, so long as the type is declared outside an instance of a generic body. If the compilation unit in which a given tagged type is declared, and all compilation units on which it semantically depends, are the same in two different partitions, then the external tag for the type shall be the same in the two partitions. What it means for a compilation unit to be the same in two different partitions is implementation defined. At a minimum, if the compilation unit is not recompiled between building the two different partitions that include it, the compilation unit is considered the same in the two partitions. @ImplDef{What determines whether a compilation unit is the same in two different partitions.} @begin{Reason} These requirements are important because external tags are used for input/output of class-wide types. These requirements ensure that what is written by one program can be read back by some other program so long as they share the same declaration for the type (and everything it depends on). The user may specify the external tag if (s)he wishes its value to be stable even across changes to the compilation unit in which the type is declared (or changes in some unit on which it depends). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We use a String rather than a @Chg{Version=[2], New=[Stream_Element_Array],Old=[Storage_Array]} to represent an external tag for portability. @end{Reason} @begin{Ramification} Note that the characters of an external tag need not all be graphic characters. In other words, the external tag can be a sequence of arbitrary 8-bit bytes. @end{Ramification} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00270-01]} The following language-defined attributes are specifiable, at least for some of the kinds of entities to which they apply: Address, @Chg{Version=[2],New=[],Old=[Size, Component_Size, ]}Alignment, @Chg{Version=[2],New=[Bit_Order, Component_Size, ],Old=[]} External_Tag, @Chg{Version=[2],New=[Input, Machine_Radix, Output, Read, Size, ],Old=[]} Small, @Chg{Version=[2],New=[],Old=[Bit_Order, ]} Storage_Pool, Storage_Size, @Chg{Version=[2],New=[Stream_Size, and ],Old=[]} Write@Chg{Version=[2],New=[],Old=[, Output, Read, Input, and Machine_Radix]}. It follows from the general rules in @RefSecNum{Operational and Representation Items} that if one writes @lquotes@;@key[for] X'Size @key[use] Y;@rquotes@; then the X'Size @nt{attribute_reference} will return Y (assuming the implementation allows the Size clause). The same is true for all of the specifiable attributes except Storage_Size. @begin{Ramification} An implementation may specify that an implementation-defined attribute is specifiable for certain entities. This follows from the fact that the semantics of implementation-defined attributes is implementation defined. An implementation is not allowed to make a language-defined attribute specifiable if it isn't. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of attribute definition clauses:} @begin{Example} Byte : @key[constant] := 8; Page : @key[constant] := 2**12; @key[type] Medium @key[is] @key[range] 0 .. 65_000; @key[for] Medium'Size @key[use] 2*Byte; @key[for] Medium'Alignment @key[use] 2; Device_Register : Medium; @key[for] Device_Register'Size @key[use] Medium'Size; @key[for] Device_Register'Address @key[use] System.Storage_Elements.To_Address(16#FFFF_0020#); @key[type] Short @key[is] @key[delta] 0.01 @key[range] -100.0 .. 100.0; @key[for] Short'Size @key[use] 15; @key[for] Car_Name'Storage_Size @key[use] --@RI{ specify access type's storage pool size} 2000*((Car'Size/System.Storage_Unit) +1); --@RI{ approximately 2000 cars} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key[function] @Chg{Version=[2],New=[My_Input],Old=[My_Read]}(Stream : @key[@Chg{Version=[2],New=[not null ],Old=[]}access] Ada.Streams.Root_Stream_Type'Class) @key[return] T; @key(for) T'@Chg{Version=[2],New=[Input],Old=[Read]} @key(use) @Chg{Version=[2],New=[My_Input],Old=[My_Read]}; --@RI{ see @RefSecNum{Stream-Oriented Attributes}} @end{Example} @end{Examples} @begin{Notes} @i{Notes on the examples:} In the Size clause for Short, fifteen bits is the minimum necessary, since the type definition requires Short'Small <= 2**(@en@;7). @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @ntf{length_clause} is replaced with the new syntax rule for @nt{attribute_definition_clause}, and it is modified to allow a @nt{name} (as well as an expression). @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{attribute_definition_clause} now requires that the prefix of the attribute be a @nt{local_name}; in Ada 83 this rule was stated in the text. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} In Ada 83, the relationship between a @Chg{Version=[2],New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]} specifying a certain aspect and an attribute that queried that aspect was unclear. In Ada 95, they are the same, except for certain explicit exceptions. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify for each attribute whether it is an operational or representation attribute.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that External_Tag is never inherited.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-01],ARef=[AI95-00291-01]} @ChgAdded{Version=[2],Text=[Adjusted the Recommended Level of Support for Alignment to eliminate nonsense requirements and to ensure that useful capabilities are required.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-01],ARef=[AI95-00291-01]} @ChgAdded{Version=[2],Text=[Adjusted the Recommended Level of Support for Size to eliminate nonsense requirements and to ensure that useful capabilities are required. Also eliminated any dependence on whether an aspect was specified (a confirming representation item should not affect the semantics).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[Added the definition of machine scalar.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00247-01]} @ChgAdded{Version=[2],Text=[Removed the requirement that specified alignments for a composite type cannot override those for their components, because it was never intended to apply to components whose location was specified with a representation item. Moreover, it causes a difference in legality when a confirming alignment is specified for one of the composite types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Removed recommended level of support rules about types with by-reference and aliased parts, because there are now blanket rules covering all recommended level of support rules.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Split the definition of Alignment for subtypes and for objects. This simplified the wording and eliminated confusion about which rules applied to objects, which applied to subtypes, and which applied to both.]} @end{DiffWord95} @LabeledClause{Enumeration Representation Clauses} @begin{Intro} @redundant[An @nt{enumeration_representation_clause} specifies the internal codes for enumeration literals.] @end{Intro} @begin{Syntax} @Syn{lhs=<enumeration_representation_clause>,rhs=" @key{for} @SynI{first_subtype_}@Syn2{local_name} @key{use} @Syn2{enumeration_aggregate};"} @Syn{lhs=<enumeration_aggregate>,rhs="@Syn2{array_aggregate}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(enumeration_representation_clause expressions)} The @nt<enumeration_aggregate> shall be written as a one-dimensional @nt<array_aggregate>, for which the index subtype is the unconstrained subtype of the enumeration type, and each component expression is expected to be of any integer type. @begin{Ramification} The @lquotes@;full coverage rules@rquotes@; for @nt<aggregate>s applies. An @key{others} is not allowed @em there is no applicable index constraint in this context. @end{Ramification} @end{Resolution} @begin{Legality} The @SynI{first_subtype_}@nt{local_name} of an @nt{enumeration_representation_clause} shall denote an enumeration subtype. @begin{Ramification} As for all type-related representation items, the @nt{local_name} is required to denote a first subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Chg{Version=[2],New=[Each component of the @nt{array_aggregate} shall be given by an @nt{expression} rather than a <>. ],Old=[]}The @Chg{Version=[2],New=[@nt{expression}s],Old=[expressions]} given in the @nt{array_aggregate} shall be static, and shall specify distinct integer codes for each value of the enumeration type; the associated integer codes shall satisfy the predefined ordering relation of the type. @begin{Reason} Each value of the enumeration type has to be given an internal code, even if the first subtype of the enumeration type is constrained to only a subrange (this is only possible if the enumeration type is a derived type). This @lquotes@;full coverage@rquotes@; requirement is important because one may refer to Enum'Base'First and Enum'Base'Last, which need to have defined representations. @end{Reason} @end{Legality} @begin{StaticSem} @PDefn2{Term=[aspect of representation], Sec=(coding)} @Defn2{Term=[coding], Sec=(aspect of representation)} An @nt{enumeration_representation_clause} specifies the @i{coding} aspect of representation. @Defn{internal code} The coding consists of the @i{internal code} for each enumeration literal, that is, the integral value used internally to represent each literal. @end{StaticSem} @begin{ImplReq} For nonboolean enumeration types, if the coding is not specified for the type, then for each value of the type, the internal code shall be equal to its position number. @begin{Reason} This default representation is already used by all known Ada compilers for nonboolean enumeration types. Therefore, we make it a requirement so users can depend on it, rather than feeling obliged to supply for every enumeration type an enumeration representation clause that is equivalent to this default rule. @end{Reason} @begin{Discussion} For boolean types, it is relatively common to use all ones for True, and all zeros for False, since some hardware supports that directly. Of course, for a one-bit Boolean object (like in a packed array), False is presumably zero and True is presumably one (choosing the reverse would be extremely unfriendly!). @end{Discussion} @end{ImplReq} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(@nt{enumeration_representation_clause})} The recommended level of support for @nt{enumeration_representation_clause}s is: @begin{Itemize} An implementation should support at least the internal codes in the range System.Min_Int..System.Max_Int. An implementation need not support @nt{enumeration_@!representation_@!clause}s for boolean types. @begin{Ramification} The implementation may support numbers outside the above range, such as numbers greater than System.Max_Int. See AI83-00564. @end{Ramification} @begin{Reason} The benefits of specifying the internal coding of a boolean type do not outweigh the implementation costs. Consider, for example, the implementation of the logical operators on a packed array of booleans with strange internal codes. It's implementable, but not worth it. @end{Reason} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for @nt{enumeration_representation_clause}s should be followed.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} Unchecked_Conversion may be used to query the internal codes used for an enumeration type. The attributes of the type, such as Succ, Pred, and Pos, are unaffected by the @Chg{New=[@nt{enumeration_representation_clause}],Old=[@nt{representation_clause}]}. For example, Pos always returns the position number, @i{not} the internal integer code that might have been specified in @Chg{New=[an @nt{enumeration_representation_clause}], Old=[a @nt{representation_clause}]}}. @begin{Discussion} @Leading@;Suppose the enumeration type in question is derived: @begin{Example} @key[type] T1 @key[is] (Red, Green, Blue); @key[subtype] S1 @key[is] T1 @key[range] Red .. Green; @key[type] S2 @key[is] @key[new] S1; @key[for] S2 @key[use] (Red => 10, Green => 20, Blue => 30); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Leading@;The @Chg{New=[@nt{enumeration_representation_clause}],Old=[@nt{representation_clause}]} has to specify values for all enumerals, even ones that are not in S2 (such as Blue). The Base attribute can be used to get at these values. For example: @begin{Example} @key[for] I @key[in] S2'Base @key[loop] ... --@RI{ When I equals Blue, the internal code is 30.} @key[end] @key[loop]; @end{Example} We considered allowing or requiring @lquotes@;@key[for] S2'Base @key[use] ...@rquotes@; in cases like this, but it didn't seem worth the trouble. @end{Discussion} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of an enumeration representation clause:} @begin{Example} @key[type] Mix_Code @key[is] (ADD, SUB, MUL, LDA, STA, STZ); @key[for] Mix_Code @key[use] (ADD => 1, SUB => 2, MUL => 3, LDA => 8, STA => 24, STZ =>33); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} As in other similar contexts, Ada 95 allows expressions of any integer type, not just expressions of type @i{universal_integer}, for the component expressions in the @nt<enumeration_aggregate>. The preference rules for the predefined operators of @i{root_integer} eliminate any ambiguity. For portability, we now require that the default coding for an enumeration type be the @lquotes@;obvious@rquotes@; coding using position numbers. This is satisfied by all known implementations. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Updated to reflect that we no longer have something called @ntf{representation_clause}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent the use of <> in a @nt{enumeration_representation_clause}. (<> is newly added to @nt{array_aggregate}s.)]} @end{DiffWord95} @LabeledClause{Record Layout} @begin{Intro} @PDefn2{Term=[aspect of representation], Sec=(layout)} @Defn2{Term=[layout], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(record layout)} @Defn2{Term=[record layout], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(storage place)} @Defn2{Term=[storage place], Sec=(of a component)} The @i{(record) layout} aspect of representation consists of the @i{storage places} for some or all components, that is, storage place attributes of the components. The layout can be specified with a @nt{record_@!representation_@!clause}. @end{Intro} @LabeledSubClause{Record Representation Clauses} @begin{Intro} @redundant[A @nt{record_representation_clause} specifies the storage representation of records and record extensions, that is, the order, position, and size of components (including discriminants, if any). @IndexSee{Term=[bit field],See=(record_representation_clause)}] @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} It should be feasible for an implementation to use negative offsets in the representation of composite types. However, no implementation should be forced to support negative offsets. Therefore@Chg{Version=[2],New=[, in the interest of uniformity],Old=[]}, negative offsets should be disallowed in @nt{record_representation_clause}s. @end{MetaRules} @begin{Syntax} @Syn{lhs=<record_representation_clause>,rhs=" @key{for} @SynI{first_subtype_}@Syn2{local_name} @key{use} @key{record} [@Syn2{mod_clause}] {@Syn2{component_clause}} @key{end} @key{record};"} @Syn{lhs=<component_clause>,rhs=" @SynI{component_}@Syn2{local_name} @key{at} @Syn2{position} @key{range} @Syn2{first_bit} .. @Syn2{last_bit};"} @Syn{lhs=<position>,rhs="@SynI{static_}@Syn2{expression}"} @Syn{lhs=<first_bit>,rhs="@SynI{static_}@Syn2{simple_expression}"} @Syn{lhs=<last_bit>,rhs="@SynI{static_}@Syn2{simple_expression}"} @begin{Reason} @nt{First_bit} and @nt{last_bit} need to be @nt{simple_expression} instead of @nt{expression} for the same reason as in @nt{range} (see @RefSec{Scalar Types}). @end{Reason} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(component_clause expressions)} @PDefn2{Term=[expected type], Sec=(position)} @PDefn2{Term=[expected type], Sec=(first_bit)} @PDefn2{Term=[expected type], Sec=(last_bit)} Each @nt{position}, @nt{first_bit}, and @nt{last_bit} is expected to be of any integer type. @begin{Ramification} These need not have the same integer type. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00436-01]} The @SynI{first_subtype_}@nt{local_name} of a @nt{record_representation_clause} shall denote a specific @Chg{Version=[2],New=[],Old=[nonlimited ]}record or record extension subtype. @begin{Ramification} As for all type-related representation items, the @nt{local_name} is required to denote a first subtype. @end{Ramification} If the @i{component_}@nt<local_name> is a @nt<direct_name>, the @nt{local_name} shall denote a component of the type. For a record extension, the component shall not be inherited, and shall not be a discriminant that corresponds to a discriminant of the parent type. If the @i{component_}@!@nt<local_@!name> has an @nt{attribute_@!designator}, the @nt{direct_@!name} of the @nt<local_@!name> shall denote either the declaration of the type or a component of the type, and the @nt{attribute_@!designator} shall denote an implementation-defined implicit component of the type. The @nt{position}, @nt{first_bit}, and @nt{last_bit} shall be static expressions. The value of @nt{position} and @nt{first_bit} shall be nonnegative. The value of @nt{last_bit} shall be no less than @nt{first_bit} @en 1. @begin{Ramification} A @nt{component_clause} such as @lquotes@;X @key{at} 4 @key{range} 0..@en@;1;@rquotes@; is allowed if X can fit in zero bits. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[If the nondefault bit ordering applies to the type, then either:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the value of @nt{last_bit} shall be less than the size of the largest machine scalar; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the value of @nt{first_bit} shall be zero and the value of @nt{last_bit} + 1 shall be a multiple of System.Storage_Unit.]} @end{Itemize} At most one @nt{component_clause} is allowed for each component of the type, including for each discriminant (@nt{component_clause}s may be given for some, all, or none of the components). Storage places within a @nt{component_list} shall not overlap, unless they are for components in distinct @nt{variant}s of the same @nt{variant_part}. A name that denotes a component of a type is not allowed within a @nt{record_representation_clause} for the type, except as the @SynI{component_}@nt<local_name> of a @nt{component_clause}. @begin{Reason} @Leading@;It might seem strange to make the @nt{record_representation_clause} part of the declarative region, and then disallow mentions of the components within almost all of the @nt{record_representation_clause}. The alternative would be to treat the @SynI{component_}@nt<local_name> like a formal parameter name in a subprogram call (in terms of visibility). However, this rule would imply slightly different semantics, because (given the actual rule) the components can hide other declarations. This was the rule in Ada 83, and we see no reason to change it. The following, for example, was and is illegal: @begin{Example} @key[type] T @key[is] @key[record] X : Integer; @key[end] @key[record]; X : @key[constant] := 31; --@RI{ Same defining name as the component.} @key[for] T @key[use] @key[record] X @key[at] 0 @key[range] 0..X; --@RI{ Illegal!} @key[end] @key[record]; @end{Example} The component X hides the named number X throughout the @nt{record_representation_clause}. @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} A @nt{record_representation_clause} (without the @nt{mod_clause}) specifies the layout.@Chg{Version=[2],New=[],Old=[ The storage place attributes (see @RefSecNum{Storage Place Attributes}) are taken from the values of the @nt{position}, @nt{first_bit}, and @nt{last_bit} expressions after normalizing those values so that @nt{first_bit} is less than Storage_Unit.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[If the default bit ordering applies to the type, the @nt{position}, @nt{first_bit}, and @nt{last_bit} of each @nt{component_clause} directly specify the position and size of the corresponding component.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the nondefault bit ordering applies to the type then the layout is determined as follows:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the @nt{component_clause}s for which the value of @nt{last_bit} is greater than or equal to the size of the largest machine scalar directly specify the position and size of the corresponding component;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[for other @nt{component_clause}s, all of the components having the same value of @nt{position} are considered to be part of a single machine scalar, located at that @nt{position}; this machine scalar has a size which is the smallest machine scalar size larger than the largest @nt{last_bit} for all @nt{component_clause}s at that @nt{position}; the @nt{first_bit} and @nt{last_bit} of each @nt{component_clause} are then interpreted as bit offsets in this machine scalar.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00133-01]} @ChgNote{We want the header title to remain, so we use @Chg instead if @ChgDeleted.} @Chg{Version=[2],New=[],Old=[For example, if Storage_Unit is 8, then @lquotes@;C @key[at] 0 @key[range] 24..31;@rquotes@; defines C'Position = 3, C'First_Bit = 0, and C'Last_Bit = 7. This is true of machines with either bit ordering.]} A @nt{component_clause} also determines the value of the Size attribute of the component, since this attribute is related to First_Bit and Last_Bit. @end{Ramification} @Redundant[A @nt{record_representation_clause} for a record extension does not override the layout of the parent part;] if the layout was specified for the parent type, it is inherited by the record extension. @end{StaticSem} @begin{ImplPerm} An implementation may generate implementation-defined components (for example, one containing the offset of another component). An implementation may generate names that denote such implementation-defined components; such names shall be implementation-defined @nt{attribute_reference}s. An implemen@!tation may allow such implementation-defined names to be used in @nt{record_@!representation_@!clause}s. An implementation can restrict such @nt{component_@!clause}s in any manner it sees fit. @ImplDef{Implementation-defined components.} @begin{Ramification} Of course, since the semantics of implementation-defined attributes is implementation defined, the implementation need not support these names in all situations. They might be purely for the purpose of @nt{component_clause}s, for example. The visibility rules for such names are up to the implementation. We do not allow such component names to be normal identifiers @em that would constitute blanket permission to do all kinds of evil things. @end{Ramification} @begin{Discussion} @Defn{dope} Such implementation-defined components are known in the vernacular as @lquotes@;dope.@rquotes@; Their main purpose is for storing offsets of components that depend on discriminants. @end{Discussion} If a @nt<record_representation_clause> is given for an untagged derived type, the storage place attributes for all of the components of the derived type may differ from those of the corresponding components of the parent type, even for components whose storage place is not specified explicitly in the @nt<record_@!representation_@!clause>. @begin{Reason} This is clearly necessary, since the whole record may need to be laid out differently. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(@nt{record_representation_clause})} The recommended level of support for @nt{record_representation_clause}s is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[An implementation should support machine scalars that correspond to all of the integer, floating point, and address formats supported by the machine.]} An implementation should support storage places that can be extracted with a load, mask, shift sequence of machine code, and set with a load, shift, mask, store sequence, given the available machine instructions and run-time model. A storage place should be supported if its size is equal to the Size of the component subtype, and it starts and ends on a boundary that obeys the Alignment of the component subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[For],Old=[If the default bit ordering applies to the declaration of a given type, then for]} a component @Chg{Version=[2],New=[with a subtype ],Old=[]}whose @Chg{Version=[2],New=[],Old=[subtype's ]}Size is less than the word size, any storage place that does not cross an aligned word boundary should be supported. @begin{Reason} The above recommendations are sufficient to define interfaces to most interesting hardware. This causes less implementation burden than the definition in ACID, which requires arbitrary bit alignments of arbitrarily large components. Since the ACID definition is neither enforced by the ACVC, nor supported by all implementations, it seems OK for us to weaken it. @end{Reason} An implementation may reserve a storage place for the tag field of a tagged type, and disallow other components from overlapping that place. @begin{Ramification} Similar permission for other dope is not granted. @end{Ramification} An implementation need not support a @nt{component_clause} for a component of an extension part if the storage place is not after the storage places of all components of the parent type, whether or not those storage places had been specified. @begin{Reason} These restrictions are probably necessary if block equality operations are to be feasible for class-wide types. For block comparison to work, the implementation typically has to fill in any gaps with zero (or one) bits. If a @lquotes@;gap@rquotes@; in the parent type is filled in with a component in a type extension, then this won't work when a class-wide object is passed by reference, as is required. @end{Reason} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for @nt{record_representation_clause}s should be followed.]}]} @end{ImplAdvice} @begin{Notes} If no @nt{component_clause} is given for a component, then the choice of the storage place for the component is left to the implementation. If @nt{component_clause}s are given for all components, the @nt{record_representation_clause} completely specifies the representation of the type and will be obeyed exactly by the implementation. @begin{Ramification} The visibility rules prevent the name of a component of the type from appearing in a @nt{record_representation_clause} at any place @i{except} for the @SynI{component_}@nt<local_name> of a @nt{component_clause}. However, since the @nt{record_representation_clause} is part of the declarative region of the type declaration, the component names hide outer homographs throughout. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} A @nt{record_representation_clause} cannot be given for a protected type, even though protected types, like record types, have components. The primary reason for this rule is that there is likely to be too much dope in a protected type @em entry queues, bit maps for barrier values, etc. In order to control the representation of the user-defined components, simply declare a record type, give it a @Chg{New=[@nt{record_@!representation_@!clause}],Old=[@nt{representation_clause}]}, and give the protected type one component whose type is the record type. Alternatively, if the protected object is protecting something like a device register, it makes more sense to keep the thing being protected outside the protected object (possibly with a pointer to it in the protected object), in order to keep implementation-defined components out of the way. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of specifying the layout of a record type:} @begin{Example} Word : @key[constant] := 4; --@RI{ storage element is byte, 4 bytes per word} @key[type] State @key[is] (A,M,W,P); @key[type] Mode @key[is] (Fix, Dec, Exp, Signif); @key[type] Byte_Mask @key[is] @key[array] (0..7) @key[of] Boolean; @key[type] State_Mask @key[is] @key[array] (State) @key[of] Boolean; @key[type] Mode_Mask @key[is] @key[array] (Mode) @key[of] Boolean; @key[type] Program_Status_Word @key[is] @key[record] System_Mask : Byte_Mask; Protection_Key : Integer @key[range] 0 .. 3; Machine_State : State_Mask; Interrupt_Cause : Interruption_Code; Ilc : Integer @key[range] 0 .. 3; Cc : Integer @key[range] 0 .. 3; Program_Mask : Mode_Mask; Inst_Address : Address; @key[end] @key[record]; @key[for] Program_Status_Word @key[use] @key[record] System_Mask @key[at] 0*Word @key[range] 0 .. 7; Protection_Key @key[at] 0*Word @key[range] 10 .. 11; --@RI{ bits 8,9 unused} Machine_State @key[at] 0*Word @key[range] 12 .. 15; Interrupt_Cause @key[at] 0*Word @key[range] 16 .. 31; Ilc @key[at] 1*Word @key[range] 0 .. 1; --@RI{ second word} Cc @key[at] 1*Word @key[range] 2 .. 3; Program_Mask @key[at] 1*Word @key[range] 4 .. 7; Inst_Address @key[at] 1*Word @key[range] 8 .. 31; @key[end] @key[record]; @key[for] Program_Status_Word'Size @key[use] 8*System.Storage_Unit; @key[for] Program_Status_Word'Alignment @key[use] 8; @end{Example} @end{Examples} @begin{Notes} @i{Note on the example:} The @nt{record_representation_clause} defines the record layout. The Size clause guarantees that (at least) eight storage elements are used for objects of the type. The Alignment clause guarantees that aliased, imported, or exported objects of the type will have addresses divisible by eight. @end{Notes} @begin{DiffWord83} The @ntf{alignment_clause} has been renamed to @nt{mod_clause} and moved to @RefSec{Obsolescent Features}. We have clarified that implementation-defined component names have to be in the form of an @nt{attribute_reference} of a component or of the first subtype itself; surely Ada 83 did not intend to allow arbitrary identifiers. The RM83-13.4(7) wording incorrectly allows components in non-variant records to overlap. We have corrected that oversight. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The meaning of a @nt{record_representation_clause} for the nondefault bit order is now clearly defined. Thus, such clauses can be portably written. In order to do that though, the equivalence of bit 1 in word 1 to bit 9 in word 0 (for a machine with Storage_Unit = 8) had to be dropped for the nondefault bit order. Any @nt{record_representation_clause}s which depends on that equivalence will break (although such code would imply a non-contiguous representation for a component, and it seems unlikely that compilers were supporting that anyway).]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00436-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] The undocumented (and likely unintentional) incompatibility with Ada 83 caused by not allowing @nt{record_representation_clause}s on limited record types is removed.]} @end{Extend95} @LabeledSubClause{Storage Place Attributes} @begin{StaticSem} @Leading@Defn2{Term=[storage place attributes], Sec=(of a component)} For @PrefixType{a component C of a composite, non-array object R}, the @i{storage place attributes} are defined: @begin{Ramification} The storage place attributes are not (individually) specifiable, but the user may control their values by giving a @nt{record_representation_clause}. @end{Ramification} @begin{Description} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<Position>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{position} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the same value as R.C'Address @en@; R'Address. The value of this attribute is of the type @i{universal_integer}.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} Thus, @Chg{Version=[2],New=[for the default bit order, ],Old=[]}R.C'Position is the offset of C in storage elements from the beginning of the object, where the first storage element of an object is numbered zero. R'Address + R.C'Position = R.C'Address. For record extensions, the offset is not measured from the beginning of the extension part, but from the beginning of the whole object, as usual. In @lquotes@;R.C'Address @en@; R'Address@rquotes@;, the "@en@;" operator is the one in System.Storage_Elements that takes two Addresses and returns a Storage_Offset. @end{Ramification} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<First_Bit>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{first_bit} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the offset, from the start of the first of the storage elements occupied by C, of the first bit occupied by C. This offset is measured in bits. The first bit of a storage element is numbered zero. The value of this attribute is of the type @i{universal_integer}.>} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<Last_Bit>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{last_bit} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the offset, from the start of the first of the storage elements occupied by C, of the last bit occupied by C. This offset is measured in bits. The value of this attribute is of the type @i{universal_integer}.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The ordering of bits in a storage element is @Chg{Version=[2],New=[],Old=[is ]}defined in @RefSec{Bit Ordering}. R.C'Size = R.C'Last_Bit @en@; R.C'First_Bit + 1. (Unless the implementation chooses an indirection representation.) If a @nt{component_clause} applies to a component, then that component will be at the same relative storage place in all objects of the type. Otherwise, there is no such requirement. @end{Ramification} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} @PDefn{contiguous representation} @PDefn{discontiguous representation} If a component is represented using some form of pointer (such as an offset) to the actual data of the component, and this data is contiguous with the rest of the object, then the storage place attributes should reflect the place of the actual data, not the pointer. If a component is allocated discontiguously from the rest of the object, then a warning should be generated upon reference to one of its storage place attributes. @begin{Reason} For discontiguous components, these attributes make no sense. For example, an implementation might allocate dynamic-sized components on the heap. For another example, an implementation might allocate the discriminants separately from the other components, so that multiple objects of the same subtype can share discriminants. Such representations cannot happen if there is a @nt{component_clause} for that component. @end{Reason} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If a component is represented using a pointer to the actual data of the component which is contiguous with the rest of the object, then the storage place attributes should reflect the place of the actual data. If a component is allocated discontiguously from the rest of the object, then a warning should be generated upon reference to one of its storage place attributes.]}]} @end{ImplAdvice} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The meaning of the storage place attributes for the nondefault bit order is now clearly defined, and can be different than that given by strictly following the Ada 95 wording. Any code which depends on the original Ada 95 values for a type using the nondefault bit order where they are different will break.]} @end{Incompatible95} @LabeledSubClause{Bit Ordering} @begin{Intro} @redundant[The Bit_Order attribute specifies the interpretation of the storage place attributes.] @begin{Reason} The intention is to provide uniformity in the interpretation of storage places across implementations on a particular machine by allowing the user to specify the Bit_Order. It is not intended to fully support data interoperability across different machines, although it can be used for that purpose in some situations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We can't require all implementations on a given machine to use the same bit ordering by default; if the user cares, a @Chg{Version=[2],New=[],Old=[@nt{pragma} ]}Bit_Order @Chg{Version=[2],New=[@nt{attribute_definition_clause} ],Old=[]}can be used to force all implementations to use the same bit ordering. @end{Reason} @end{Intro} @begin{StaticSem} @Defn{bit ordering} A bit ordering is a method of interpreting the meaning of the storage place attributes. @Defn{High_Order_First} @Defn{big endian} @Defn2{Term=[endian], Sec=(big)} High_Order_First @Redundant[(known in the vernacular as @lquotes@;big endian@rquotes@;)] means that the first bit of a storage element (bit 0) is the most significant bit (interpreting the sequence of bits that represent a component as an unsigned integer value). @Defn{Low_Order_First} @Defn{little endian} @Defn2{Term=[endian], Sec=(little)} Low_Order_First @Redundant[(known in the vernacular as @lquotes@;little endian@rquotes@;)] means the opposite: the first bit is the least significant. @Leading@;For @PrefixType{every specific record subtype S}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<S>, AttrName=<Bit_Order>, Text=<Denotes the bit ordering for the type of S. The value of this attribute is of type System.Bit_Order.>} @EndPrefixType{} @PDefn2{Term=[specifiable], Sec=(of Bit_Order for record types and record extensions)} @Defn{Bit_Order clause} Bit_Order may be specified for specific record types via an @nt{attribute_definition_clause}; the expression of such a clause shall be static. @end{Description} If Word_Size = Storage_Unit, the default bit ordering is implementation defined. If Word_Size > Storage_Unit, the default bit ordering is the same as the ordering of storage elements in a word, when interpreted as an integer. @IndexSee{Term=[byte sex],See=(ordering of storage elements in a word)} @ImplDef{If Word_Size = Storage_Unit, the default bit ordering.} @begin{Ramification} Consider machines whose Word_Size = 32, and whose Storage_Unit = 8. Assume the default bit ordering applies. On a machine with big-endian addresses, the most significant storage element of an integer is at the address of the integer. Therefore, bit zero of a storage element is the most significant bit. On a machine with little-endian addresses, the least significant storage element of an integer is at the address of the integer. Therefore, bit zero of a storage element is the least significant bit. @end{Ramification} The storage place attributes of a component of a type are interpreted according to the bit ordering of the type. @begin{Ramification} This implies that the interpretation of the @nt{position}, @nt{first_bit}, and @nt{last_bit} of a @nt{component_clause} of a @nt{record_representation_clause} obey the bit ordering given in a representation item. @end{Ramification} @end{StaticSem} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(bit ordering)} The recommended level of support for the nondefault bit ordering is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[The],Old=[If Word_Size = Storage_Unit, then the]} implementation should support the nondefault bit ordering in addition to the default bit ordering. @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[The],Old=[If Word_Size = Storage_Unit, the]} implementation should support both bit orderings. @Chg{Version=[2],New=[Implementations],Old=[We don't push for support of the nondefault bit ordering when Word_Size > Storage_Unit (except of course for upward compatibility with a preexisting implementation whose Ada 83 bit order did not correspond to the required Ada 95 default bit order), because implementations]} are required to support storage positions that cross storage element boundaries when Word_Size > Storage_Unit@Chg{Version=[2], New=[ but the definition of the storage place attributes for the nondefault bit order ensures that such],Old=[. Such]} storage positions will @Chg{Version=[2], New=[not ],Old=[]}be split into two or three pieces@Chg{Version=[2],New=[. Thus, there is no significant implementation burden to supporting the nondefault bit order, given that the set of machine scalars is implementation-defined], Old=[ if the nondefault bit ordering is used, which could be onerous to support. However, if Word_Size = Storage_Unit, there might not be a natural bit ordering, but the splitting problem need not occur]}. @end{Ramification} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the nondefault bit ordering should be followed.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[Bit_Order clauses make it possible to write @nt{record_representation_clause}s that can be ported between machines having different bit ordering. They do not guarantee transparent exchange of data between such machines.]} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The Bit_Order attribute is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[We now suggest that all implementations support the nondefault bit order.]} @end{Diffword95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{Change of Representation} @begin{Intro} @redundant[@Defn{change of representation} @Defn2{Term=[representation], Sec=(change of)} A @nt{type_conversion} (see @RefSecNum{Type Conversions}) can be used to convert between two different representations of the same array or record. To convert an array from one representation to another, two array types need to be declared with matching component subtypes, and convertible index types. If one type has packing specified and the other does not, then explicit conversion can be used to pack or unpack an array. To convert a record from one representation to another, two record types with a common ancestor type need to be declared, with no inherited subprograms. Distinct representations can then be specified for the record types, and explicit conversion between the types can be used to effect a change in representation.] @begin{Ramification} This technique does not work if the first type is an untagged type with user-defined primitive subprograms. It does not work at all for tagged types. @end{Ramification} @end{Intro} @begin{Examples} @leading@keepnext@i{Example of change of representation:} @begin{Example} --@RI{ Packed_Descriptor and Descriptor are two different types} --@RI{ with identical characteristics, apart from their} --@RI{ representation} @key[type] Descriptor @key[is] @key[record] --@RI{ components of a descriptor} @key[end] @key[record]; @key[type] Packed_Descriptor @key[is] @key[new] Descriptor; @key[for] Packed_Descriptor @key[use] @key[record] --@RI{ component clauses for some or for all components} @key[end] @key[record]; @RI{-- Change of representation can now be accomplished by explicit type conversions:} D : Descriptor; P : Packed_Descriptor; P := Packed_Descriptor(D); --@RI{ pack D} D := Descriptor(P); --@RI{ unpack P} @end{Example} @end{Examples} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/13b.mss��������������������������������������������������������������0000755�0001752�0001001�00000601566�12273462240�016550� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(13, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:26 $} @Comment{$Source: e:\\cvsroot/ARM/Source/13b.mss,v $} @Comment{$Revision: 1.53 $} @RMNewPage @LabeledClause{The Package System} @begin{Intro} @redundant[For each implementation there is a library package called System which includes the definitions of certain configuration-dependent characteristics.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @ChgImplDef{Version=[2],Kind=[Revised],Text=[The contents of the visible part of package System@Chg{Version=[2],New=[],Old=[and its language-defined children]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @RootLibUnit{System}@key[package] System @key[is] @key{pragma} @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(System); @key[type] @AdaTypeDefn{Name} @key[is] @RI{implementation-defined-enumeration-type}; @AdaObjDefn{System_Name} : @key[constant] Name := @RI{implementation-defined}; --@RI{ System-Dependent Named Numbers:} @AdaObjDefn{Min_Int} : @key[constant] := @RI{root_integer}'First; @AdaObjDefn{Max_Int} : @key[constant] := @RI{root_integer}'Last; @AdaObjDefn{Max_Binary_Modulus} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Nonbinary_Modulus} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Base_Digits} : @key[constant] := @RI{root_real}'Digits; @AdaObjDefn{Max_Digits} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Mantissa} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Fine_Delta} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Tick} : @key[constant] := @RI{implementation-defined}; --@RI{ Storage-related Declarations:} @key[type] @AdaTypeDefn{Address} @key[is] @RI{implementation-defined}; @AdaObjDefn{Null_Address} : @key[constant] Address; @AdaObjDefn{Storage_Unit} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Word_Size} : @key[constant] := @RI{implementation-defined} * Storage_Unit; @AdaObjDefn{Memory_Size} : @key[constant] := @RI{implementation-defined}; --@RI{ @Defn2{Term=[address], Sec=(comparison)}Address Comparison:} @key(function) "<" (Left, Right : Address) @key(return) Boolean; @key(function) "<="(Left, Right : Address) @key(return) Boolean; @key(function) ">" (Left, Right : Address) @key(return) Boolean; @key(function) ">="(Left, Right : Address) @key(return) Boolean; @key(function) "=" (Left, Right : Address) @key(return) Boolean; -- @key(function) "/=" (Left, Right : Address) @key(return) Boolean; --@RI{ "/=" is implicitly defined} @key[pragma] Convention(Intrinsic, "<"); ... --@RI{ and so on for all language-defined subprograms in this package} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00221-01]} --@RI{ Other System-Dependent Declarations:} @key[type] @AdaTypeDefn{Bit_Order} @key[is] (@AdaObjDefn{High_Order_First}, @AdaObjDefn{Low_Order_First}); @AdaObjDefn{Default_Bit_Order} : @key[constant] Bit_Order@Chg{Version=[2],New=[ := @RI{implementation-defined}],Old=[]}; --@RI{ Priority-related declarations (see @RefSecNum{Task Priorities}):} @key{subtype} @AdaSubtypeDefn{Name=[Any_Priority],Of=[Integer]} @key{is} Integer @key{range} @RI{implementation-defined}; @key{subtype} @AdaSubtypeDefn{Name=[Priority],Of=[Any_Priority]} @key{is} Any_Priority @key{range} Any_Priority'First .. @RI{implementation-defined}; @key{subtype} @AdaSubtypeDefn{Name=[Interrupt_Priority],Of=[Any_Priority]} @key{is} Any_Priority @key{range} Priority'Last+1 .. Any_Priority'Last; @AdaObjDefn{Default_Priority} : @key{constant} Priority := (Priority'First + Priority'Last)/2; @key[private] ... -- @RI{not specified by the language} @key[end] System; @end{Example} Name is an enumeration subtype. Values of type Name are the names of alternative machine configura@!tions handled by the implementation. System_Name represents the current machine configuration. The named numbers Fine_Delta and Tick are of the type @i{universal_real}; the others are of the type @i{universal_integer}. @Leading@;The meanings of the named numbers are: @begin{Description} @Redundant[ Min_Int @\The smallest (most negative) value allowed for the expressions of a @nt{signed_@!integer_@!type_@!definition}. Max_Int @\The largest (most positive) value allowed for the expressions of a @nt{signed_@!integer_@!type_@!definition}. Max_Binary_Modulus @\A power of two such that it, and all lesser positive powers of two, are allowed as the modulus of a @nt<modular_type_definition>. Max_Nonbinary_Modulus @\A value such that it, and all lesser positive integers, are allowed as the modulus of a @nt<modular_type_definition>. @begin{Ramification} There is no requirement that Max_Nonbinary_Modulus be less than or equal to Max_Binary_Modulus, although that's what makes most sense. On a typical 32-bit machine, for example, Max_Binary_Modulus will be 2**32 and Max_Nonbinary_Modulus will be 2**31, because supporting nonbinary moduli in above 2**31 causes implementation difficulties. @end{Ramification} Max_Base_Digits @\The largest value allowed for the requested decimal precision in a @nt{floating_@!point_@!definition}. Max_Digits @\The largest value allowed for the requested decimal precision in a @nt{floating_@!point_@!definition} that has no @nt{real_@!range_@!specification}. Max_Digits is less than or equal to Max_Base_Digits. Max_Mantissa @\The largest possible number of binary digits in the mantissa of machine numbers of a user-defined ordinary fixed point type. (The mantissa is defined in @RefSecNum{Numerics}.) Fine_Delta @\The smallest delta allowed in an @nt{ordinary_fixed_point_definition} that has the @nt{real_@!range_@!specification} @key{range} @en@;1.0 .. 1.0. ] Tick @\A period in seconds approximating the real time interval during which the value of Calendar.Clock remains constant. @begin{Ramification} There is no required relationship between System.Tick and Duration'Small, other than the one described here. The inaccuracy of the @nt{delay_statement} has no relation to Tick. In particular, it is possible that the clock used for the @nt{delay_statement} is less accurate than Calendar.Clock. We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in @RefSec{Real-Time Systems}. @end{Ramification} Storage_Unit @\The number of bits per storage element. Word_Size @\The number of bits per word. Memory_Size @\An implementation-defined value @Redundant[that is intended to reflect the memory size of the configuration in storage elements.] @begin{Discussion} It is unspecified whether this refers to the size of the address space, the amount of physical memory on the machine, or perhaps some other interpretation of @lquotes@;memory size.@rquotes@; In any case, the value has to be given by a static expression, even though the amount of memory on many modern machines is a dynamic quantity in several ways. Thus, Memory_Size is not very useful. @end{Discussion} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} Address is @Chg{Version=[2],New=[],Old=[of ]}a definite, nonlimited type@Chg{Version=[2],New=[ with preelaborable initialization (see @RefSecNum{Elaboration Control})],Old=[]}. Address represents machine addresses capable of addressing individual storage elements. Null_Address is an address that is distinct from the address of any object or program unit. @IndexSee{Term=[pointer],See=(type System.Address)} @begin{Ramification} The implementation has to ensure that there is at least one address that nothing will be allocated to; Null_Address will be one such address. @end{Ramification} @begin{Ramification} Address is the type of the result of the attribute Address. @end{Ramification} @begin{Reason} Address is required to be nonlimited and definite because it is important to be able to assign addresses, and to declare uninitialized address variables. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[If System.Address is defined as a private type (as suggested below), it might be necessary to add a pragma Preelaborable_Initialization to the specification of System in order that Address have preelaborable initialization as required.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00221-01]} @Chg{Version=[2],New=[ Default_Bit_Order shall be a static constant. ],Old=[]}See @RefSecNum{Bit Ordering} for an explanation of Bit_Order and Default_Bit_Order. @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} An implementation may add additional implementation-defined declarations to package System and its children. @Redundant[However, it is usually better for the implementation to provide additional functionality via implementation-defined children of System.]@Chg{Version=[2],New=[],Old=[ Package System may be declared pure.]} @begin{Ramification} The declarations in package System and its children can be implicit. For example, since Address is not limited, the predefined "=" and "/=" operations are probably sufficient. However, the implementation is not @i{required} to use the predefined "=". @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgNote{Version=[1],Kind=[Revised]}@ChgNote{Remove bogus "of"} Address should be @Chg{New=[],Old=[of ]}a private type. @begin{Reason} This promotes uniformity by avoiding having implementation-defined predefined operations for the type. We don't require it, because implementations may want to stick with what they have. @end{Reason} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Type System.Address should be a private type.]}]} @begin{ImplNote} It is not necessary for Address to be able to point at individual bits within a storage element. Nor is it necessary for it to be able to point at machine registers. It is intended as a memory address that matches the hardware's notion of an address. The representation of the @key{null} value of a general access type should be the same as that of Null_Address; instantiations of Unchecked_Conversion should work accordingly. If the implementation supports interfaces to other languages, the representation of the @key{null} value of a general access type should be the same as in those other languages, if appropriate. Note that the children of the Interfaces package will generally provide foreign-language-specific null values where appropriate. See UI-0065 regarding Null_Address. @end{ImplNote} @end{ImplAdvice} @begin{Notes} There are also some language-defined child packages of System defined elsewhere. @end{Notes} @begin{Extend83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00114} @ChgAdded{Version=[1],Text=[@Defn{extensions to Ada 83} The declarations Max_Binary_Modulus, Max_Nonbinary_Modulus, Max_Base_Digits, Null_Address, Word_Size, Bit_Order, Default_Bit_Order, Any_Priority, Interrupt_Priority, and Default_Priority are added to System in Ada 95. The presence of ordering operators for type Address is also guaranteed (the existence of these depends on the definition of Address in an Ada 83 implementation). We do not list these as incompatibilities, as the contents of System can vary between implementations anyway; thus a program that depends on the contents of System (by using @f{@key[use] System;} for example) is already at risk of being incompatible when moved between Ada implementations.]} @end{Extend83} @begin{DiffWord83} Much of the content of System is standardized, to provide more uniformity across implementations. Implementations can still add their own declarations to System, but are encouraged to do so via children of System. Some of the named numbers are defined more explicitly in terms of the standard numeric types. The pragmas System_Name, Storage_Unit, and Memory_Size are no longer defined by the language. However, the corresponding declarations in package System still exist. Existing implementations may continue to support the three pragmas as implementation-defined pragmas, if they so desire. Priority semantics, including subtype Priority, have been moved to the Real Time Annex. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Type Address is defined to have preelaborable initialization, so that it can be used without restriction in preelaborated units. (If Address is defined to be a private type, as suggested by the @ImplAdviceTitle, in Ada 95 it cannot be used in some contexts in a preelaborated units. This is an unnecessary portability issue.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00221-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] Default_Bit_Order is now a static constant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Package System is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)]} @end{Extend95} @LabeledSubClause{The Package System.Storage_Elements} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[System],Child=[Storage_Elements]}@key[package] System.Storage_Elements @key[is] @key{pragma} @Chg{Version=[2],New=[Pure(],Old=[Preelaborate(System.]}Storage_Elements); @key[type] @AdaTypeDefn{Storage_Offset} @key[is] @key[range] @RI(implementation-defined); @key[subtype] @AdaSubtypeDefn{Name=[Storage_Count],Of=[Storage_Offset]} @key[is] Storage_Offset @key[range] 0..Storage_Offset'Last; @key[type] @AdaTypeDefn{Storage_Element} @key[is] @key[mod] @RI{implementation-defined}; @key[for] Storage_Element'Size @key[use] Storage_Unit; @key[type] @AdaTypeDefn{Storage_Array} @key[is] @key[array] (Storage_Offset @key[range] <>) @key[of] @key[aliased] Storage_Element; @key[for] Storage_Array'Component_Size @key[use] Storage_Unit; --@RI{ @Defn2{Term=[address], Sec=(arithmetic)}Address Arithmetic:} @key(function) "+"(Left : Address; Right : Storage_Offset) @key(return) Address; @key(function) "+"(Left : Storage_Offset; Right : Address) @key(return) Address; @key(function) "-"(Left : Address; Right : Storage_Offset) @key(return) Address; @key(function) "-"(Left, Right : Address) @key(return) Storage_Offset; @key(function) "@key(mod)"(Left : Address; Right : Storage_Offset) @key(return) Storage_Offset; --@RI{ Conversion to/from integers:} @key[type] @AdaTypeDefn{Integer_Address} @key[is] @RI{implementation-defined}; @key[function] @AdaSubDefn{To_Address}(Value : Integer_Address) @key[return] Address; @key[function] @AdaSubDefn{To_Integer}(Value : Address) @key[return] Integer_Address; @key[pragma] Convention(Intrinsic, "+"); @RI(-- ...and so on for all language-defined subprograms declared in this package.) @key[end] System.Storage_Elements; @end{Example} @begin{Reason} The Convention @nt{pragma}s imply that the attribute Access is not allowed for those operations. The @key(mod) function is needed so that the definition of Alignment makes sense. @end{Reason} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The range of Storage_Elements.Storage_Offset, the modulus of Storage_Elements.Storage_Element, and the declaration of Storage_Elements.Integer_Address.]}.]} Storage_Element represents a storage element. Storage_Offset represents an offset in storage elements. Storage_Count represents a number of storage elements. @PDefn{contiguous representation} @PDefn{discontiguous representation} Storage_Array represents a contiguous sequence of storage elements. @begin{Reason} The index subtype of Storage_Array is Storage_Offset because we wish to allow maximum flexibility. Most Storage_Arrays will probably have a lower bound of 0 or 1, but other lower bounds, including negative ones, make sense in some situations. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[Note that there are some language-defined subprograms that fill part of a Storage_Array, and return the index of the last element filled as a Storage_Offset. The Read procedures in Streams (see @RefSecNum{The Package Streams}), Streams.Stream_IO (see @RefSecNum{The Package Streams.Stream_IO}), and System.RPC (see @RefSecNum{Partition Communication Subsystem}) behave in this manner. These will raise Constraint_Error if the resulting Last value is not in Storage_Offset. This implies that the Storage_Array passed to these subprograms should not have a lower bound of Storage_Offset'First, because then a read of 0 elements would always raise Constraint_Error. A better choice of lower bound is 1.]} @end{Reason} Integer_Address is a @Redundant[(signed or modular)] integer subtype. To_Address and To_Integer convert back and forth between this type and Address. @end{StaticSem} @begin{ImplReq} Storage_Offset'Last shall be greater than or equal to Integer'Last or the largest possible storage offset, whichever is smaller. Storage_Offset'First shall be <= (@en@;Storage_Offset'Last). @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00362-01]} @ChgDeleted{Version=[2],Text=[Package System.Storage_Elements may be declared pure.]} @end{ImplPerm} @begin{ImplAdvice} Operations in System and its children should reflect the target environment semantics as closely as is reasonable. For example, on most machines, it makes sense for address arithmetic to @lquotes@;wrap around.@rquotes@; @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Operations that do not make sense should raise Program_Error. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Operations in System and its children should reflect the target environment; operations that do not make sense should raise Program_Error.]}]} @begin{Discussion} For example, on a segmented architecture, X < Y might raise Program_Error if X and Y do not point at the same segment (assuming segments are unordered). Similarly, on a segmented architecture, the conversions between Integer_Address and Address might not make sense for some values, and so might raise Program_Error. @end{Discussion} @begin{Reason} We considered making Storage_Element a private type. However, it is better to declare it as a modular type in the visible part, since code that uses it is already low level, and might as well have access to the underlying representation. We also considered allowing Storage_Element to be any integer type, signed integer or modular, but it is better to have uniformity across implementations in this regard, and viewing storage elements as unsigned seemed to make the most sense. @end{Reason} @begin{ImplNote} To_Address is intended for use in Address clauses. Implementations should overload To_Address if appropriate. For example, on a segmented architecture, it might make sense to have a record type representing a segment/offset pair, and have a To_Address conversion that converts from that record type to type Address. @end{ImplNote} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package System.Storage_Elements is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)]} @end{Extend95} @LabeledSubClause{The Package System.Address_To_Access_Conversions} @begin{StaticSem} @Leading@;The following language-defined generic library package exists: @begin{Example} @ChildUnit{Parent=[System],Child=[Address_@!To_@!Access_@!Conversions]}@key[generic] @key[type] Object(<>) @key[is] @key[limited] @key[private]; @key[package] System.Address_To_Access_Conversions @key[is] @key[pragma] Preelaborate(Address_To_Access_Conversions); @key[type] Object_Pointer @key[is] @key[access] @key[all] Object; @key[function] @AdaSubDefn{To_Pointer}(Value : Address) @key[return] Object_Pointer; @key[function] @AdaSubDefn{To_Address}(Value : Object_Pointer) @key[return] Address; @key[pragma] Convention(Intrinsic, To_Pointer); @key[pragma] Convention(Intrinsic, To_Address); @key[end] System.Address_To_Access_Conversions; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The To_Pointer and To_Address subprograms convert back and forth between values of types Object_Pointer and Address. To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that allows Unchecked_Access. To_Pointer(Null_Address) returns @key[null]. @PDefn{unspecified} For other addresses, the behavior is unspecified. To_Address(@key[null]) returns Null_Address@Chg{Version=[2],New=[],Old=[ (for @key[null] of the appropriate type)]}. To_Address(Y), where Y /= @key[null], returns Y.@key[all]'Address. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The programmer should ensure that the address passed to To_Pointer is either Null_Address, or the address of an object of type Object. @Chg{Version=[2],New=[(If Object is not a not by-reference type, the object ought to be aliased; recall that the Address attribute is not required to provide a useful result other objects.)],Old=[]} Otherwise, the behavior of the program is unspecified; it might raise an exception or crash, for example. @end{Discussion} @begin{Reason} Unspecified is almost the same thing as erroneous; they both allow arbitrarily bad behavior. We don't say erroneous here, because the implementation might allow the address passed to To_Pointer to point at some memory that just happens to @lquotes@;look like@rquotes@; an object of type Object. That's not necessarily an error; it's just not portable. However, if the actual type passed to Object is (for example) an array type, the programmer would need to be aware of any dope that the implementation expects to exist, when passing an address that did not come from the Address attribute of an object of type Object. One might wonder why To_Pointer and To_Address are any better than unchecked conversions. The answer is that Address does not necessarily have the same representation as an access type. For example, an access value might point at the bounds of an array when an address would point at the first element. Or an access value might be an offset in words from someplace, whereas an address might be an offset in bytes from the beginning of memory. @end{Reason} @end{StaticSem} @begin{ImplPerm} An implementation may place restrictions on instantiations of Address_To_Access_Conversions. @begin{Ramification} For example, if the hardware requires aligned loads and stores, then dereferencing an access value that is not properly aligned might raise an exception. For another example, if the implementation has chosen to use negative component offsets (from an access value), it might not be possible to preserve the semantics, since negative offsets from the Address are not allowed. (The Address attribute always points at @lquotes@;the first of the storage elements....@rquotes@;) Note that while the implementation knows how to convert an access value into an address, it might not be able to do the reverse. To avoid generic contract model violations, the restriction might have to be detected at run time in some cases. @end{Ramification} @end{ImplPerm} @LabeledClause{Machine Code Insertions} @begin{Intro} @redundant[@Defn{machine code insertion} A machine code insertion can be achieved by a call to a subprogram whose @nt{sequence_of_statements} contains @nt{code_statement}s.] @end{Intro} @begin{Syntax} @Syn{lhs=<code_statement>,rhs="@Syn2{qualified_expression};"} @begin{SyntaxText} A @nt{code_statement} is only allowed in the @nt{handled_sequence_of_@!statements} of a @nt{subprogram_@!body}. If a @nt{subprogram_@!body} contains any @nt{code_@!statement}s, then within this @nt{subprogram_@!body} the only allowed form of @nt{statement} is a @nt{code_@!statement} (labeled or not), the only allowed @nt{declarative_@!item}s are @nt{use_@!clause}s, and no @nt{exception_@!handler} is allowed (@nt{comment}s and @nt{pragma}s are allowed as usual). @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(code_statement)} The @nt{qualified_expression} is expected to be of any type. @end{Resolution} @begin{Legality} The @nt{qualified_expression} shall be of a type declared in package System.Machine_Code. @begin{Ramification} This includes types declared in children of System.Machine_Code. @end{Ramification} A @nt<code_statement> shall appear only within the scope of a @nt<with_clause> that mentions package System.Machine_Code. @begin{Ramification} Note that this is not a note; without this rule, it would be possible to write machine code in compilation units which depend on System.Machine_Code only indirectly. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{System.Machine_Code} @ChildUnit{Parent=[System],Child=[Machine_Code]} The contents of the library package System.Machine_Code (if provided) are implementation defined. The meaning of @nt{code_statement}s is implementation defined. @Redundant{Typically, each @nt{qualified_expression} represents a machine instruction or assembly directive.} @begin{Discussion} For example, an instruction might be a record with an Op_Code component and other components for the operands. @end{Discussion} @ImplDef{The contents of the visible part of package System.Machine_Code, and the meaning of @nt{code_statement}s.} @end{StaticSem} @begin{ImplPerm} An implementation may place restrictions on @nt{code_statement}s. An implementation is not required to provide package System.Machine_Code. @end{ImplPerm} @begin{Notes} An implementation may provide implementation-defined pragmas specifying register conventions and calling conventions. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} Machine code functions are exempt from the rule that a @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} is required. In fact, @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} are forbidden, since only @nt{code_statement}s are allowed. @begin{Discussion} The idea is that the author of a machine code subprogram knows the calling conventions, and refers to parameters and results accordingly. The implementation should document where to put the result of a machine code function, for example, @lquotes@;Scalar results are returned in register 0.@rquotes@; @end{Discussion} Intrinsic subprograms (see @RefSec{Conformance Rules}) can also be used to achieve machine code insertions. Interface to assembly language can be achieved using the features in @RefSec{Interface to Other Languages}. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a code statement:} @begin{Example} M : Mask; @key[procedure] Set_Mask; @key[pragma] Inline(Set_Mask); @key[procedure] Set_Mask @key[is] @key[use] System.Machine_Code; --@RI{ assume @lquotes@;@key[with] System.Machine_Code;@rquotes@; appears somewhere above} @key[begin] SI_Format'(Code => SSM, B => M'Base_Reg, D => M'Disp); --@RI{ Base_Reg and Disp are implementation-defined attributes} @key[end] Set_Mask; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Machine code functions are allowed in Ada 95; in Ada 83, only procedures were allowed. @end{Extend83} @begin{DiffWord83} The syntax for @nt{code_statement} is changed to say @lquotes@;@nt{qualified_expression}@rquotes@; instead of @lquotes@;@Syn2{subtype_mark}'@Syn2{record_aggregate}@rquotes@;. Requiring the type of each instruction to be a record type is overspecification. @end{DiffWord83} @LabeledClause{Unchecked Type Conversions} @begin{Intro} @redundant[@Defn{unchecked type conversion} @Defn2{Term=[type conversion], Sec=(unchecked)} @Defn2{Term=[conversion], Sec=(unchecked)} @IndexSeeAlso{Term=[type_conversion],See=(unchecked type conversion)} @IndexSee{Term=[cast],See=(unchecked type conversion)} An unchecked type conversion can be achieved by a call to an instance of the generic function Unchecked_Conversion.] @end{Intro} @begin{StaticSem} @Leading@keepnext@;The following language-defined generic library function exists: @begin{Example} @key[generic] @key[type] Source(<>) @key[is] @key[limited] @key[private]; @key[type] Target(<>) @key[is] @key[limited] @key[private]; @SubChildUnit{Parent=[Ada],Child=[Unchecked_Conversion]}@key[function] Ada.Unchecked_Conversion(S : Source) @key[return] Target; @key[pragma] Convention(Intrinsic, Ada.Unchecked_Conversion); @key[pragma] Pure(Ada.Unchecked_Conversion); @end{Example} @begin{Reason} The @nt{pragma} Convention implies that the attribute Access is not allowed for instances of Unchecked_Conversion. @end{Reason} @end{StaticSem} @begin{RunTime} The size of the formal parameter S in an instance of Unchecked_Conversion is that of its subtype. @Redundant[This is the actual subtype passed to Source, except when the actual is an unconstrained composite subtype, in which case the subtype is constrained by the bounds or discriminants of the value of the actual expression passed to S.] @Leading@;If all of the following are true, the effect of an unchecked conversion is to return the value of an object of the target subtype whose representation is the same as that of the source object S: @begin{Itemize} S'Size = Target'Size. @begin{Ramification} Note that there is no requirement that the Sizes be known at compile time. @end{Ramification} S'Alignment = Target'Alignment. The target subtype is not an unconstrained composite subtype. @PDefn{contiguous representation} @PDefn{discontiguous representation} S and the target subtype both have a contiguous representation. The representation of S is a representation of an object of the target subtype. @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00426-01]} Otherwise, @Chg{Version=[2],New=[if the result type is scalar, the result of the function is implementation defined, and can have an invalid representation (see @RefSecNum{Data Validity}). If the result type is nonscalar, ],Old=[]}the effect is implementation defined; in particular, the result can be abnormal (see @RefSecNum{Data Validity}). @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[The result of unchecked conversion for instances with scalar result types whose result is not defined by the language.],Old=[]}]} @ChgImplDef{Version=[2],Kind=[Revised],Text=[The effect of unchecked conversion@Chg{Version=[2],New=[ for instances with nonscalar result types whose effect is not defined by the language],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Note the difference between these sentences; the first only says that the bits returned are implementation defined, while the latter allows any effect. The difference is because scalar objects should never be abnormal unless their assignment was disrupted or if they are a subcomponent of an abnormal composite object. Neither exception applies to instances of Unchecked_Conversion.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} Whenever unchecked conversions are used, it is the programmer's responsibility to ensure that these conversions maintain the properties that are guaranteed by the language for objects of the target type. @Chg{Version=[2],New=[For nonscalar types, this],Old=[This]} requires the user to understand the underlying run-time model of the implementation. The execution of a program that violates these properties by means of unchecked conversions @Chg{Version=[2],New=[returning a nonscalar type ], Old=[]}is erroneous.@Chg{Version=[2],New=[ Properties of scalar types can be checked by using the Valid attribute (see @RefSecNum{The Valid Attribute}); programs can avoid violating properties of the type (and erroneous execution) by careful use of this attribute.],Old=[]} An instance of Unchecked_Conversion can be applied to an object of a private type, assuming the implementation allows it. @end{Ramification} @end{RunTime} @begin{ImplPerm} An implementation may return the result of an unchecked conversion by reference, if the Source type is not a by-copy type. @Redundant[In this case, the result of the unchecked conversion represents simply a different (read-only) view of the operand of the conversion.] @begin{Ramification} In other words, the result object of a call on an instance of Unchecked_Conversion can occupy the same storage as the formal parameter S. @end{Ramification} An implementation may place restrictions on Unchecked_Conversion. @begin{Ramification} For example, an instantiation of Unchecked_Conversion for types for which unchecked conversion doesn't make sense may be disallowed. @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} @Chg{Version=[2],New=[Since the],Old=[The]} Size of an array object @Chg{Version=[2],New=[generally does],Old=[should]} not include its bounds@Chg{Version=[2],New=[],Old=[; hence]}, the bounds should not be part of the converted data. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Since the Size of an array object generally does not include its bounds, the bounds should not be part of the converted data in an instance of Unchecked_Conversion.]}]} @begin{Ramification} On the other hand, we have no advice to offer about discriminants and tag fields. @end{Ramification} The implementation should not generate unnecessary run-time checks to ensure that the representation of S is a representation of the target type. It should take advantage of the permission to return by reference when possible. Restrictions on unchecked conversions should be avoided unless required by the target environment. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[There should not be unnecessary run-time checks on the result of an Unchecked_Conversion; the result should be returned by reference when possible. Restrictions on Unchecked_Conversions should be avoided.]}]} @begin{ImplNote} As an example of an unnecessary run-time check, consider a record type with gaps between components. The compiler might assume that such gaps are always zero bits. If a value is produced that does not obey that assumption, then the program might misbehave. The implementation should not generate extra code to check for zero bits (except, perhaps, in a special error-checking mode). @end{ImplNote} @Leading@PDefn2{Term=[recommended level of support], Sec=(unchecked conversion)} The recommended level of support for unchecked conversions is: @begin{Itemize} Unchecked conversions should be supported and should be reversible in the cases where this clause defines the result. @PDefn{contiguous representation} @PDefn{discontiguous representation} To enable meaningful use of unchecked conversion, a contiguous representation should be used for elementary subtypes, for statically constrained array subtypes whose component subtype is one of the subtypes described in this paragraph, and for record subtypes without discriminants whose component subtypes are described in this paragraph. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for Unchecked_Conversion should be followed.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[The implementation advice about the size of array objects was moved to 13.3 so that all of the advice about Size is in one place.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Clarified that the result of Unchecked_Conversion for scalar types can be invalid, but not abnormal.]} @end{DiffWord95} @LabeledSubClause{Data Validity} @begin{Intro} Certain actions that can potentially lead to erroneous execution are not directly erroneous, but instead can cause objects to become @i{abnormal}. Subsequent uses of abnormal objects can be erroneous. A scalar object can have an @i{invalid representation}, which means that the object's representation does not represent any value of the object's subtype. @RootDefn{uninitialized variables} The primary cause of invalid representations is uninitialized variables. Abnormal objects and invalid representations are explained in this subclause. @end{Intro} @begin{RunTime} @Leading@RootDefn{normal state of an object} @RootDefn{abnormal state of an object} When an object is first created, and any explicit or default initializations have been performed, the object and all of its parts are in the @i{normal} state. Subsequent operations generally leave them normal. However, an object or part of an object can become @i{abnormal} in the following ways: @begin{Itemize} @Defn{disruption of an assignment} An assignment to the object is disrupted due to an abort (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}) or due to the failure of a language-defined check (see @RefSecNum{Exceptions and Optimization}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00426-01]} The object is not scalar, and is passed to an @key[in out] or @key[out] parameter of an imported procedure@Chg{Version=[2],New=[, the Read procedure of an instance of Sequential_IO, Direct_IO, or Storage_IO, or the stream attribute T'Read], Old=[ or language-defined input procedure]}, if after return from the procedure the representation of the parameter does not represent a value of the parameter's subtype. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The object is the return object of a function call of a nonscalar type, and the function is an imported function, an instance of Unchecked_Conversion, or the stream attribute T'Input, if after return from the function the representation of the return object does not represent a value of the function's subtype.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We explicitly list the routines involved in order to avoid future arguments. All possibilities are listed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We did not include Stream_IO.Read in the list above. A Stream_Element should include all possible bit patterns, and thus it cannot be invalid. Therefore, the parameter will always represent a value of its subtype. By omitting this routine, we make it possible to write arbitrary I/O operations without any possibility of abnormal objects.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[@Redundant[For an imported object, it is the programmer's responsibility to ensure that the object remains in a normal state.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This follows (and echos) the standard rule of interfacing; the programmer must ensure that Ada semantics are followed (see @RefSecNum{Interfacing Pragmas}).]} @end{TheProof} @PDefn{unspecified} Whether or not an object actually becomes abnormal in these cases is not specified. An abnormal object becomes normal again upon successful completion of an assignment to the object as a whole. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to evaluate a @nt<primary> that is a @nt<name> denoting an abnormal object, or to evaluate a @nt{prefix} that denotes an abnormal object. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @Comment{There appears to be no justification for this statement; everything can become abnormal. We leave the prefix for the next paragraph, so we use Chg rather than ChgDeleted.} @Chg{Version=[2],New=[],Old=[Although a composite object with no subcomponents of an access type, and with static constraints all the way down cannot become abnormal, a scalar subcomponent of such an object can become abnormal.]} The @key[in out] or @key[out] parameter case does not apply to scalars; bad scalars are merely invalid representations, rather than abnormal, in this case. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The reason we allow access objects, and objects containing subcomponents of an access type, to become abnormal is because the correctness of an access value cannot necessarily be determined merely by looking at the bits of the object. The reason we allow scalar objects to become abnormal is that we wish to allow the compiler to optimize assuming that the value of a scalar object belongs to the object's subtype, if the compiler can prove that the object is initialized with a value that belongs to the subtype. The reason we allow composite objects to become abnormal @Chg{Version=[2],New=[],Old=[if some constraints are nonstatic ]}is that such object might be represented with implicit levels of indirection; if those are corrupted, then even assigning into a component of the object, or simply asking for its Address, might have an unpredictable effect. The same is true if the discriminants have been destroyed. @end{Reason} @end{Erron} @begin{Bounded} @Leading@Defn{invalid representation}@PDefn2{Term=(bounded error),Sec=(cause)} If the representation of a scalar object does not represent a value of the object's subtype (perhaps because the object was not initialized), the object is said to have an @i{invalid representation}. It is a bounded error to evaluate the value of such an object. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the error is detected, either Constraint_Error or Program_Error is raised. Otherwise, execution continues using the invalid representation. The rules of the language outside this subclause assume that all objects have valid representations. The semantics of operations on invalid representations are as follows: @begin{Discussion} The AARM is more explicit about what happens when the value of the case expression is an invalid representation. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[This includes the result object of functions, including the result of Unchecked_Conversion, T'Input, and imported functions.]} @end{Ramification} @begin{Itemize} If the representation of the object represents a value of the object's type, the value of the type is used. If the representation of the object does not represent a value of the object's type, the semantics of operations on such representations is implementation-defined, but does not by itself lead to erroneous or unpredictable execution, or to other objects becoming abnormal. @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[This means that the implementation must take care not to use an invalid representation in a way that might cause erroneous execution. For instance, the exception mandated for @nt{case_statement}s must be raised. Array indexing must not cause memory outside of the array to be written (and usually, not read either). These cases and similar cases may require explicit checks by the implementation.]} @end{ImplNote} @end{Itemize} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} @PDefn2{Term=(erroneous execution),Sec=(cause)} A call to an imported function or an instance of Unchecked_Conversion is erroneous if the result is scalar, @Chg{Version=[2],New=[],Old=[and ]}the result object has an invalid representation@Chg{Version=[2],New=[, and the result is used other than as the @nt{expression} of an @nt{assignment_statement} or an @nt{object_declaration}, or as the @nt{prefix} of a Valid attribute. If such a result object is used as the source of an assignment, and the assigned value is an invalid representation for the target of the assignment, then any use of the target object prior to a further assignment to the target object, other than as the @nt{prefix} of a Valid attribute reference, is erroneous],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} In a typical implementation, every bit pattern that fits in an object of @Chg{Version=[2],New=[a signed],Old=[an]} integer subtype will represent a value of the type, if not of the subtype. However, for an enumeration or floating point type,@Chg{Version=[2],New=[ as well as some modular types,],Old=[]} there are typically bit patterns that do not represent any value of the type. In such cases, the implementation ought to define the semantics of operations on the invalid representations in the obvious manner (assuming the bounded error is not detected): a given representation should be equal to itself, a representation that is in between the internal codes of two enumeration literals should behave accordingly when passed to comparison operators and membership tests, etc. We considered @i{requiring} such sensible behavior, but it resulted in too much arcane verbiage, and since implementations have little incentive to behave irrationally, such verbiage is not important to have. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} If a stand-alone scalar object is initialized to a an in-range value, then the implementation can take advantage of the fact that @Chg{Version=[2],New=[the use of ],Old=[]}any out-of-range value has to be @Chg{Version=[2],New=[erroneous],Old=[abnormal]}.@ChgNote{Do you see "abnormal" in the rules above? Thought not.} Such an out-of-range value can be produced only by things like unchecked conversion, @Chg{Version=[2],New=[imported functions],Old=[input]}, and @Chg{Version=[2],New=[abnormal values caused by ],Old=[]}disruption of an assignment due to abort or to failure of a language-defined check. This depends on out-of-range values being checked before assignment (that is, checks are not optimized away unless they are proven redundant). @Leading@;Consider the following example: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} @key[type] My_Int @key[is] @key[range] 0..99; @key[function] Safe_Convert @key[is] @key[new] Unchecked_Conversion(My_Int, Integer); @key[function] Unsafe_Convert @key[is] @key[new] Unchecked_Conversion(My_Int, Positive); X : Positive := Safe_Convert(0); --@RI{ Raises Constraint_Error.} Y : Positive := Unsafe_Convert(0); --@Chg{Version=[2],New=[@RI{ Bounded Error, may be invalid.} B : Boolean := Y'Valid; --@RI{ OK, B = False.} Z : Positive := Y+1; --@RI{ Erroneous to use Y.}],Old=[@RI{ Erroneous.}]} @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01],ARef=[AI95-00426-01]} The call to Unsafe_Convert @Chg{Version=[2],New=[ is a bounded error, which might raise Constraint_Error, Program_Error, or return an invalid value. Moreover, if an exception is not raised, most uses of that invalid value (including the use of Y) cause],Old=[causes]} erroneous execution. The call to Safe_Convert is not erroneous. The result object is an object of subtype Integer containing the value 0. The assignment to X is required to do a constraint check; the fact that the conversion is unchecked does not obviate the need for subsequent checks required by the language rules. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00167-01],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The reason for delaying erroneous execution until the object is used is so that the invalid representation can be tested for validity using the Valid attribute (see @RefSecNum{The Valid Attribute}) without causing execution to become erroneous. Note that this delay does not imply an exception will not be raised; an implementation could treat both conversions in the example in the same way and raise Constraint_Error.]} @end{Ramification} @begin{ImplNote} If an implementation wants to have a @lquotes@;friendly@rquotes@; mode, it might always assign an uninitialized scalar a default initial value that is outside the object's subtype (if there is one), and check for this value on some or all reads of the object, so as to help detect references to uninitialized scalars. Alternatively, an implementation might want to provide an @lquotes@;unsafe@rquotes@; mode where it presumed even uninitialized scalars were always within their subtype. @end{ImplNote} @begin{Ramification} The above rules imply that it is a bounded error to apply a predefined operator to an object with a scalar subcomponent having an invalid representation, since this implies reading the value of each subcomponent. Either Program_Error or Constraint_Error is raised, or some result is produced, which if composite, might have a corresponding scalar subcomponent still with an invalid representation. Note that it is not an error to assign, convert, or pass as a parameter a composite object with an uninitialized scalar subcomponent. In the other hand, it is a (bounded) error to apply a predefined operator such as =, <, and @key(xor) to a composite operand with an invalid scalar subcomponent. @end{Ramification} @PDefn2{Term=(erroneous execution),Sec=(cause)} The dereference of an access value is erroneous if it does not designate an object of an appropriate type or a subprogram with an appropriate profile, if it designates a nonexistent object, or if it is an access-to-variable value that designates a constant object. @Redundant[Such an access value can exist, for example, because of Unchecked_Deallocation, Unchecked_Access, or Unchecked_Conversion.] @begin{Ramification} The above mentioned Unchecked_... features are not the only causes of such access values. For example, interfacing to other languages can also cause the problem. One obscure example is if the Adjust subprogram of a controlled type uses Unchecked_Access to create an access-to-variable value designating a subcomponent of its controlled parameter, and saves this access value in a global object. When Adjust is called during the initialization of a constant object of the type, the end result will be an access-to-variable value that designates a constant object. @end{Ramification} @end{Erron} @begin{Notes} Objects can become abnormal due to other kinds of actions that directly update the object's representation; such actions are generally considered directly erroneous, however. @end{Notes} @begin{DiffWord83} In order to reduce the amount of erroneousness, we separate the concept of an undefined value into objects with invalid representation (scalars only) and abnormal objects. Reading an object with an invalid representation is a bounded error rather than erroneous; reading an abnormal object is still erroneous. In fact, the only safe thing to do to an abnormal object is to assign to the object as a whole. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00167-01]} @ChgAdded{Version=[2],Text=[The description of erroneous execution for Unchecked_Conversion and imported objects was tightened up so that using the Valid attribute to test such a value is not erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Clarified the definition of objects that can become abnormal; made sure that all of the possibilities are included.]} @end{DiffWord95} @LabeledSubClause{The Valid Attribute} @begin{Intro} The Valid attribute can be used to check the validity of data produced by unchecked conversion, input, interface to foreign languages, and the like. @end{Intro} @begin{StaticSem} @Leading@;For @PrefixType{a @nt<prefix> X that denotes a scalar object @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @Attribute{Prefix=<X>, AttrName=<Valid>, Text=<Yields True if and only if the object denoted by X is normal and has a valid representation. The value of this attribute is of the predefined type Boolean.>} @begin{Ramification} Having checked that X'Valid is True, it is safe to read the value of X without fear of erroneous execution caused by abnormality, or a bounded error caused by an invalid representation. Such a read will produce a value in the subtype of X. @end{Ramification} @end{description} @EndPrefixType{} @end{StaticSem} @begin{Notes} @Leading@;Invalid data can be created in the following cases (not counting erroneous or unpredictable execution): @begin{Itemize} an uninitialized scalar object, the result of an unchecked conversion, input, interface to another language (including machine code), aborting an assignment, disrupting an assignment due to the failure of a language-defined check (see @RefSecNum{Exceptions and Optimization}), and use of an object whose Address has been specified. @end{Itemize} X'Valid is not considered to be a read of X; hence, it is not an error to check the validity of invalid data. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The Valid attribute may be used to check the result of calling an instance of Unchecked_Conversion (or any other operation that can return invalid values). However, an exception handler should also be provided because implementations are permitted to raise Constraint_Error or Program_Error if they detect the use of an invalid representation (see @RefSecNum{Data Validity}).]} @begin{Ramification} If X is of an enumeration type with a representation clause, then X'Valid checks that the value of X when viewed as an integer is one of the specified internal codes. @end{Ramification} @begin{Reason} Valid is defined only for scalar objects because the implementation and description burden would be too high for other types. For example, given a typical run-time model, it is impossible to check the validity of an access value. The same applies to composite types implemented with internal pointers. One can check the validity of a composite object by checking the validity of each of its scalar subcomponents. The user should ensure that any composite types that need to be checked for validity are represented in a way that does not involve implementation-defined components, or gaps between components. Furthermore, such types should not contain access subcomponents. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgNote{This was never true, even in Ada 95} @ChgDeleted{Version=[2],Text=[Note that one can safely check the validity of a composite object with an abnormal value only if the constraints on the object and all of its subcomponents are static. Otherwise, evaluation of the @nt{prefix} of the @nt{attribute_reference} causes erroneous execution (see @RefSecNum{Names}).]} @end{Reason} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} X'Valid is new in Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Added a note explaining that handlers for Constraint_Error and Program_Error are needed in the general case of testing for validity. (An implementation could document cases where these are not necessary, but there is no language requirement.]} @end{DiffWord95} @LabeledClause{Unchecked Access Value Creation} @begin{Intro} @redundant[The attribute Unchecked_Access is used to create access values in an unsafe manner @em the programmer is responsible for preventing @lquotes@;dangling references.@rquotes@;] @end{Intro} @begin{StaticSem} @Leading@;The following attribute is defined for @PrefixType{a @nt{prefix} X that denotes an aliased view of an object}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Unchecked_Access>, Text=<All rules and semantics that apply to X'Access (see @RefSecNum{Operations of Access Types}) apply also to X'Unchecked_Access, except that, for the purposes of accessibility rules and checks, it is as if X were declared immediately within a library package.>} @IndexSeeAlso{Term=[Access attribute],See=(Unchecked_Access attribute)} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Notes} This attribute is provided to support the situation where a local object is to be inserted into a global linked data structure, when the programmer knows that it will always be removed from the data structure prior to exiting the object's scope. The Access attribute would be illegal in this case (see @RefSec{Operations of Access Types}). @begin{Ramification} @PDefn2{Term=[expected type], Sec=(Unchecked_Access attribute)} The expected type for X'Unchecked_Access is as for X'Access. If an @nt<attribute_reference> with Unchecked_Access is used as the actual parameter for an access parameter, an Accessibility_Check can never fail on that access parameter. @end{Ramification} There is no Unchecked_Access attribute for subprograms. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} Such an attribute would allow @Chg{Version=[2],New=[unsafe ], Old=[]}@lquotes@;downward closures@rquotes@;, where an access value designating a more nested subprogram is passed to a less nested subprogram.@Chg{Version=[2],New=[ (Anonymous access-to-subprogram parameters provide safe @lquotes@;downward closures@rquotes@;.)],Old=[]} This requires some means of reconstructing the global environment for the more nested subprogram, so that it can do up-level references to objects. The two methods of implementing up-level references are displays and static links. If @Chg{Version=[2],New=[unsafe ],Old=[]}downward closures were supported, each access-to-subprogram value would have to carry the static link or display with it. @Chg{Version=[2],New=[We don't want to require the space and time overhead of requiring the extra information for all access-to-subprogram types, especially as including it would make interfacing to other languages (like C) harder],Old=[In the case of displays, this was judged to be infeasible, and we don't want to disrupt implementations by forcing them to use static links if they already use displays]}. If desired, an instance of Unchecked_Conversion can be used to create an access value of a global access-to-subprogram type that designates a local subprogram. The semantics of using such a value are not specified by the language. In particular, it is not specified what happens if such subprograms make up-level references; even if the frame being referenced still exists, the up-level reference might go awry if the representation of a value of a global access-to-subprogram type doesn't include a static link. @end{Reason} @end{Notes} @LabeledClause{Storage Management} @begin{Intro} @Redundant[ @Defn{user-defined storage management} @Defn2{Term=[storage management], Sec=(user-defined)} @Defn{user-defined heap management} @Defn2{Term=[heap management], Sec=(user-defined)} Each access-to-object type has an associated storage pool. The storage allocated by an @nt{allocator} comes from the pool; instances of Unchecked_Deallocation return storage to the pool. Several access types can share the same pool.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00435-01]} @Redundant[A storage pool is a variable of a type in the class rooted at Root_Storage_Pool, which is an abstract limited controlled type. By default, the implementation chooses a @i{standard storage pool} for each access@Chg{Version=[2],New=[-to-object],Old=[]} type. The user may define new pool types, and may override the choice of pool for an access@Chg{Version=[2],New=[-to-object],Old=[]} type by specifying Storage_Pool for the type.] @begin{Ramification} By default, the implementation might choose to have a single global storage pool, which is used (by default) by all access types, which might mean that storage is reclaimed automatically only upon partition completion. Alternatively, it might choose to create a new pool at each accessibility level, which might mean that storage is reclaimed for an access type when leaving the appropriate scope. Other schemes are possible. @end{Ramification} @end{Intro} @begin{Legality} If Storage_Pool is specified for a given access type, Storage_Size shall not be specified for it. @begin{Reason} The Storage_Pool determines the Storage_Size; hence it would not make sense to specify both. Note that this rule is simplified by the fact that the aspects in question cannot be specified for derived types, nor for non-first subtypes, so we don't have to worry about whether, say, Storage_Pool on a derived type overrides Storage_Size on the parent type. For the same reason, @lquotes@;specified@rquotes@; means the same thing as @lquotes@;directly specified@rquotes@; here. @end{Reason} @end{Legality} @begin{StaticSem} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @key[with] Ada.Finalization; @key[with] System.Storage_Elements; @ChildUnit{Parent=[System],Child=[Storage_Pools]}@key[package] System.Storage_Pools @key[is] @key{pragma} Preelaborate(System.Storage_Pools); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Root_Storage_Pool} @key[is] @key[abstract] @key[new] Ada.Finalization.Limited_Controlled @key[with] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Root_Storage_Pool);],Old=[]} @key[procedure] @AdaSubDefn{Allocate}( Pool : @key[in] @key[out] Root_Storage_Pool; Storage_Address : @key[out] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count) @key[is] @key[abstract]; @key[procedure] @AdaSubDefn{Deallocate}( Pool : @key[in] @key[out] Root_Storage_Pool; Storage_Address : @key[in] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count) @key[is] @key[abstract]; @key[function] @AdaSubDefn{Storage_Size}(Pool : Root_Storage_Pool) @key[return] Storage_Elements.Storage_Count @key[is] @key[abstract]; @key[private] ... -- @RI{not specified by the language} @key[end] System.Storage_Pools; @end{Example} @begin{Reason} The Alignment parameter is provided to Deallocate because some allocation strategies require it. If it is not needed, it can be ignored. @end{Reason} @Defn{storage pool type} @Defn{pool type} A @i{storage pool type} (or @i{pool type}) is a descendant of Root_Storage_Pool. @Defn{storage pool element} @Defn{pool element} @Defn2{Term=[element], Sec=(of a storage pool)} The @i{elements} of a storage pool are the objects allocated in the pool by @nt{allocator}s. @begin{Discussion} In most cases, an element corresponds to a single memory block allocated by Allocate. However, in some cases the implementation may choose to associate more than one memory block with a given pool element. @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00435-01]} @Leading@;For @PrefixType{every access@Chg{Version=[2],New=[-to-object],Old=[]} subtype S}, the following @Chg{New=[representation ],Old=[]}attributes are defined: @begin{Description} @Attribute{Prefix=<S>, AttrName=<Storage_Pool>, Text=<Denotes the storage pool of the type of S. The type of this attribute is Root_@!Storage_@!Pool'Class.>} @Attribute{Prefix=<S>, AttrName=<Storage_Size>, Text=<Yields the result of calling Storage_Size(S'Storage_Pool)@Redundant{, which is intended to be a measure of the number of storage elements reserved for the pool.} The type of this attribute is @i{universal_integer}.>} @EndPrefixType{} @begin{Ramification} Storage_Size is also defined for task subtypes and objects @em see @RefSecNum{Operational and Representation Attributes}. Storage_Size is not a measure of how much un-allocated space is left in the pool. That is, it includes both allocated and unallocated space. Implementations and users may provide a Storage_Available function for their pools, if so desired. @end{Ramification} @end{Description} @PDefn2{Term=[specifiable], Sec=(of Storage_Size for a non-derived access-to-object type)} @PDefn2{Term=[specifiable], Sec=(of Storage_Pool for a non-derived access-to-object type)} @Defn{Storage_Pool clause} @Defn{Storage_Size clause} Storage_Size or Storage_Pool may be specified for a non-derived access-to-object type via an @nt{attribute_@!definition_@!clause}; the @nt{name} in a Storage_Pool clause shall denote a variable. An @nt{allocator} of type T allocates storage from T's storage pool. If the storage pool is a user-defined object, then the storage is allocated by calling Allocate, passing T'Storage_Pool as the Pool parameter. The Size_In_Storage_Elements parameter indicates the number of storage elements to be allocated, and is no more than D'Max_Size_In_Storage_Elements, where D is the designated subtype. The Alignment parameter is D'Alignment. @PDefn{contiguous representation} @PDefn{discontiguous representation} The result returned in the Storage_Address parameter is used by the @nt{allocator} as the address of the allocated storage, which is a contiguous block of memory of Size_In_@!Storage_@!Elements storage elements. @Redundant[Any exception propagated by Allocate is propagated by the @nt{allocator}.] @begin{Ramification} If the implementation chooses to represent the designated subtype in multiple pieces, one @nt{allocator} evaluation might result in more than one call upon Allocate. In any case, @nt{allocator}s for the access type obtain all the required storage for an object of the designated type by calling the specified Allocate procedure. Note that the implementation does not turn other exceptions into Storage_Error. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0111],ARef=[AI95-00103-01]} @ChgAdded{Version=[1],Text=[If D (the designated type of T) includes subcomponents of other access types, they will be allocated from the storage pools for those types, even if those @nt{allocator}s are executed as part of the @nt{allocator} of T (as part of the initialization of the object). For instance, an access-to-task type TT may allocate the data structures used to implement the task value from other storage pools. (In particular, the task stack does not necessarily need to be allocated from the storage pool for TT.)]} @end{Ramification} @Defn{standard storage pool} If Storage_Pool is not specified for a type defined by an @nt{access_to_object_definition}, then the implementation chooses a standard storage pool for it in an implementation-defined manner. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} In this case, the exception Storage_Error is raised by an @nt{allocator} if there is not enough storage. It is implementation defined whether or not the implementation provides user-accessible names for the standard pool type(s). @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2],Text=[The manner of choosing a storage pool for an access type when Storage_Pool is not specified for the type.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The manner of choosing a storage pool is covered by a @DocReqName below, so it is not summarized here.]} @end{Discussion} @ImplDef{Whether or not the implementation provides user-accessible names for the standard pool type(s).} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @ChgNote{This was never true.}@Chg{Version=[2],New=[],Old=[An anonymous access type has no pool. ]}An access-to-object type defined by a @nt{derived_type_definition} inherits its pool from its parent type, so all access-to-object types in the same derivation class share the same pool. Hence the @lquotes@;defined by an @nt{access_to_object_definition}@rquotes@; wording above. @PDefn{contiguous representation} @PDefn{discontiguous representation} There is no requirement that all storage pools be implemented using a contiguous block of memory (although each allocation returns a pointer to a contiguous block of memory). @end{Ramification} If Storage_Size is specified for an access type, then the Storage_Size of this pool is at least that requested, and the storage for the pool is reclaimed when the master containing the declaration of the access type is left. @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If the implementation cannot satisfy the request, Storage_Error is raised at the point of the @nt{attribute_@!definition_@!clause}. If neither Storage_Pool nor Storage_Size are specified, then the meaning of Storage_Size is implementation defined. @ChgImplDef{Version=[2],Kind=[Revised],Text=[The meaning of Storage_Size@Chg{Version=[2], New=[ when neither the Storage_Size nor the Storage_Pool is specified for an access type],Old=[]}.]} @begin{Ramification} The Storage_Size function and attribute will return the actual size, rather than the requested size. Comments about rounding up, zero, and negative on task Storage_Size apply here, as well. See also AI83-00557, AI83-00558, and AI83-00608. The expression in a Storage_Size clause need not be static. The reclamation happens after the master is finalized. @end{Ramification} @begin{ImplNote} For a pool allocated on the stack, normal stack cut-back can accomplish the reclamation. For a library-level pool, normal partition termination actions can accomplish the reclamation. @end{ImplNote} If Storage_Pool is specified for an access type, then the specified pool is used. @PDefn{unspecified} The effect of calling Allocate and Deallocate for a standard storage pool directly (rather than implicitly via an @nt{allocator} or an instance of Unchecked_Deallocation) is unspecified. @begin{Ramification} For example, an @nt{allocator} might put the pool element on a finalization list. If the user directly Deallocates it, instead of calling an instance of Unchecked_Deallocation, then the implementation would probably try to finalize the object upon master completion, which would be bad news. Therefore, the implementation should define such situations as erroneous. @end{Ramification} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If Storage_Pool is specified for an access type, then if Allocate can satisfy the request, it should allocate a contiguous block of memory, and return the address of the first storage element in Storage_Address. The block should contain Size_In_Storage_Elements storage elements, and should be aligned according to Alignment. The allocated storage should not be used for any other purpose while the pool element remains in existence. If the request cannot be satisfied, then Allocate should propagate an exception @Redundant[(such as Storage_Error)]. If Allocate behaves in any other manner, then the program execution is erroneous. @end{Erron} @begin{DocReq} An implementation shall document the set of values that a user-defined Allocate procedure needs to accept for the Alignment parameter. An implementation shall document how the standard storage pool is chosen, and how storage is allocated by standard storage pools. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of storage pools.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The set of values that a user-defined Allocate procedure needs to accept for the Alignment parameter. How the standard storage pool is chosen, and how storage is allocated by standard storage pools.]}]} @end{DocReq} @begin{ImplAdvice} An implementation should document any cases in which it dynamically allocates heap storage for a purpose other than the evaluation of an @nt{allocator}. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any cases in which heap storage is dynamically allocated other than as part of the evaluation of an @nt{allocator} should be documented.]}]} @begin{Reason} This is @lquotes@;@ImplAdviceTitle@rquotes@; because the term @lquotes@;heap storage@rquotes@; is not formally definable; therefore, it is not testable whether the implementation obeys this advice. @end{Reason} A default (implementation-provided) storage pool for an access-to-constant type should not have overhead to support deallocation of individual objects. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[A default storage pool for an access-to-constant type should not have overhead to support deallocation of individual objects.]}]} @begin{Ramification} Unchecked_Deallocation is not defined for such types. If the access-to-constant type is library-level, then no deallocation (other than at partition completion) will ever be necessary, so if the size needed by an @nt{allocator} of the type is known at link-time, then the allocation should be performed statically. If, in addition, the initial value of the designated object is known at compile time, the object can be allocated to read-only memory. @end{Ramification} @begin{ImplNote} If the Storage_Size for an access type is specified, the storage pool should consist of a contiguous block of memory, possibly allocated on the stack. The pool should contain approximately this number of storage elements. These storage elements should be reserved at the place of the Storage_Size clause, so that @nt{allocator}s cannot raise Storage_Error due to running out of pool space until the appropriate number of storage elements has been used up. This approximate (possibly rounded-up) value should be used as a maximum; the implementation should not increase the size of the pool on the fly. If the Storage_Size for an access type is specified as zero, then the pool should not take up any storage space, and any @nt{allocator} for the type should raise Storage_Error. @end{ImplNote} @begin{Ramification} Note that most of this is approximate, and so cannot be (portably) tested. That's why we make it an Implementation Note. There is no particular number of allocations that is guaranteed to succeed, and there is no particular number of allocations that is guaranteed to fail. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @ChgNote{Use ChgAdded to get conditional Leading}@ChgAdded{Version=[2], Type=[Leading],Text=[]}@Chg{Version=[2],New=[The],Old=[A]} storage pool @Chg{Version=[2],New=[used ],Old=[]}for @Chg{Version=[2],New=[an @nt{allocator} of ],Old=[]}an anonymous access type should be @Chg{Version=[2],New=[determined as follows:],Old=[created at the point of an allocator for the type, and be reclaimed when the designated object becomes inaccessible;]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the @nt{allocator} is defining a coextension (see @RefSecNum{Operations of Access Types}) of an object being created by an outer @nt{allocator}, then the storage pool used for the outer @nt{allocator} should also be used for the coextension;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For other access discriminants and access parameters, the storage pool should be created at the point of the @nt{allocator}, and be reclaimed when the allocated object becomes inaccessible;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Otherwise, a default storage pool should be created at the point where the anonymous access type is elaborated; such a storage pool need not support deallocation of individual objects.]} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Usually, a storage pool for an access discriminant or access parameter should be created at the point of an @nt{allocator}, and be reclaimed when the designated object becomes inaccessible. For other anonymous access types, the pool should be created at the point where the type is elaborated and need not support deallocation of individual objects.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[For access parameters and access discriminants,], Old=[Normally]} the "storage pool" for an anonymous access type would not @Chg{Version=[2],New=[normally ],Old=[]}exist as a separate entity. Instead, the designated object of the allocator would be allocated, in the case of an access parameter, as a local aliased variable at the call site, and in the case of an access discriminant, contiguous with the object containing the discriminant. This is similar to the way storage for @nt{aggregate}s is typically managed. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For other sorts of anonymous access types, this implementation is not possible in general, as the accessibility of the anonymous access type is that of its declaration, while the @nt{allocator} could be more nested. In this case, a "real" storage pool is required. Note, however, that this storage pool need not support (separate) deallocation, as it is not possible to instantiate Unchecked_Deallocation with an anonymous access type. (If deallocation is needed, the object should be allocated for a named access type and converted.) Thus, deallocation only need happen when the anonymous access type itself goes out of scope; this is similar to the case of an access-to-constant type.]} @end{ImplNote} @end{ImplAdvice} @begin{Notes} A user-defined storage pool type can be obtained by extending the Root_Storage_Pool type, and overriding the primitive subprograms Allocate, Deallocate, and Storage_Size. A user-defined storage pool can then be obtained by declaring an object of the type extension. The user can override Initialize and Finalize if there is any need for non-trivial initialization and finalization for a user-defined pool type. For example, Finalize might reclaim blocks of storage that are allocated separately from the pool object itself. @Leading@;The writer of the user-defined allocation and deallocation procedures, and users of @nt{allocator}s for the associated access type, are responsible for dealing with any interactions with tasking. In particular: @begin{itemize} If the @nt{allocator}s are used in different tasks, they require mutual exclusion. If they are used inside protected objects, they cannot block. If they are used by interrupt handlers (see @RefSec{Interrupt Support}), the mutual exclusion mechanism has to work properly in that context. @end{itemize} The primitives Allocate, Deallocate, and Storage_Size are declared as abstract (see @RefSecNum{Abstract Types and Subprograms}), and therefore they have to be overridden when a new (non-abstract) storage pool type is declared. @begin{Ramification} Note that the Storage_Pool attribute denotes an object, rather than a value, which is somewhat unusual for attributes. The calls to Allocate, Deallocate, and Storage_Size are dispatching calls @em this follows from the fact that the actual parameter for Pool is T'Storage_Pool, which is of type Root_Storage_Pool'Class. In many cases (including all cases in which Storage_Pool is not specified), the compiler can determine the tag statically. However, it is possible to construct cases where it cannot. All access types in the same derivation class share the same pool, whether implementation defined or user defined. This is necessary because we allow type conversions among them (even if they are pool-specific), and we want pool-specific access values to always designate an element of the right pool. @end{Ramification} @begin{ImplNote} If an access type has a standard storage pool, then the implementation doesn't actually have to follow the pool interface described here, since this would be semantically invisible. For example, the allocator could conceivably be implemented with inline code. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@;To associate an access type with a storage pool object, the user first declares a pool object of some type derived from Root_Storage_Pool. Then, the user defines its Storage_Pool attribute, as follows: @begin{Example} Pool_Object : Some_Storage_Pool_Type; @key[type] T @key[is] @key[access] Designated; @key[for] T'Storage_Pool @key[use] Pool_Object; @end{Example} @begin{Wide} @Leading@;Another access type may be added to an existing storage pool, via: @end{Wide} @begin{Example} @key[for] T2'Storage_Pool @key[use] T'Storage_Pool; @end{Example} The semantics of this is implementation defined for a standard storage pool. @begin{Reason} For example, the implementation is allowed to choose a storage pool for T that takes advantage of the fact that T is of a certain size. If T2 is not of that size, then the above will probably not work. @end{Reason} @Leading@;As usual, a derivative of Root_Storage_Pool may define additional operations. For example, presuming that Mark_Release_Pool_Type has two additional operations, Mark and Release, the following is a possible use: @begin{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0041],ARef=[AI95-00066-01]} @key[type] Mark_Release_Pool_Type (Pool_Size : Storage_Elements.Storage_Count; Block_Size : Storage_Elements.Storage_Count) @key[is] @key[new] Root_Storage_Pool @key[with @Chg{New=[],Old=[limited ]}private]; ... MR_Pool : Mark_Release_Pool_Type (Pool_Size => 2000, Block_Size => 100); @key[type] Acc @key[is] @key[access] ...; @key[for] Acc'Storage_Pool @key[use] MR_Pool; ... Mark(MR_Pool); ... --@RI{ Allocate objects using @lquotes@;@key[new] Designated(...)@rquotes@;.} Release(MR_Pool); --@RI{ Reclaim the storage.} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} User-defined storage pools are new to Ada 95. @end{Extend83} @begin{DiffWord83} Ada 83 had a concept called a @lquotes@;collection,@rquotes@; which is similar to what we call a storage pool. All access types in the same derivation class shared the same collection. In Ada 95, all access types in the same derivation class share the same storage pool, but other (unrelated) access types can also share the same storage pool, either by default, or as specified by the user. A collection was an amorphous collection of objects; a storage pool is a more concrete concept @em hence the different name. RM83 states the erroneousness of reading or updating deallocated objects incorrectly by missing various cases. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00435-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b<Amendment Correction:> Storage pools (and Storage_Size) are not defined for access-to-subprogram types. The original Ada 95 wording defined the attributes, but said nothing about their values. If a program uses attributes Storage_Pool or Storage_Size on an access-to-subprogram type, it will need to be corrected for Ada 2005. That's a good thing, as such a use is a bug @em the concepts never were defined for such types.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type Root_Storage_Pool, so that extensions of it can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that these are representation attributes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that an @nt{allocator} for a coextension nested inside an outer @nt{allocator} shares the pool with the outer @nt{allocator}.]} @end{DiffWord95} @LabeledSubClause{The Max_Size_In_Storage_Elements Attribute} @begin{Intro} @redundant[The Max_Size_In_Storage_Elements attribute is useful in writing user-defined pool types.] @end{Intro} @begin{StaticSem} @Leading@;For @PrefixType{every subtype S}, the following attribute is defined: @begin{Description} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<S>, AttrName=<Max_Size_In_Storage_Elements>, ARef=[AI95-00256-01],ARef=[AI95-00416-01], Text=<Denotes the maximum value for Size_In_Storage_Elements that @Chg{Version=[2],New=[could],Old=[will]} be requested @Chg{Version=[2], New=[by the implementation ],Old=[]}via Allocate for an access type whose designated subtype is S.@Chg{Version=[2],New=[ For a type with access discriminants, if the implementation allocates space for a coextension in the same pool as that of the object having the access discriminant, then this accounts for any calls on Allocate that could be performed to provide space for such coextensions.],Old=[]} The value of this attribute is of type @i{universal_integer}.>} @EndPrefixType{} @begin{Ramification} If S is an unconstrained array subtype, or an unconstrained subtype with discriminants, S'Max_Size_In_Storage_Elements might be very large. @end{Ramification} @end{Description} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Corrected the wording so that a fortune-telling compiler that can see the future execution of the program is not required.]} @end{DiffWord95} @RMNewPage@Comment{For printed Ada 2005 RM only} @LabeledSubClause{Unchecked Storage Deallocation} @begin{Intro} @redundant[@Defn{unchecked storage deallocation} @Defn2{Term=[storage deallocation], Sec=(unchecked)} @Defn{deallocation of storage} @Defn{reclamation of storage} @Defn{freeing storage} Unchecked storage deallocation of an object designated by a value of an access type is achieved by a call to an instance of the generic procedure Unchecked_Deallocation.] @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined generic library procedure exists: @begin{Example} @key[generic] @key[type] Object(<>) @key[is] @key[limited] @key[private]; @key[type] Name @key[is] @key[access] Object; @SubChildUnit{Parent=[Ada],Child=[Unchecked_Deallocation]}@key[procedure] Ada.Unchecked_Deallocation(X : @key[in] @key[out] Name); @key[pragma] Convention(Intrinsic, Ada.Unchecked_Deallocation); @key[pragma] Preelaborate(Ada.Unchecked_Deallocation); @end{Example} @begin{Reason} The @nt{pragma} Convention implies that the attribute Access is not allowed for instances of Unchecked_Deallocation. @end{Reason} @end{StaticSem} @begin{RunTime} @Leading@;Given an instance of Unchecked_Deallocation declared as follows: @begin{Example} @key[procedure] Free @key[is] @key[new] Ada.Unchecked_Deallocation( @RI[object_subtype_name], @RI[access_to_variable_subtype_name]); @end{Example} @begin{Wide} @Leading@Keepnext@;Procedure Free has the following effect: @end{Wide} @begin{Enumerate} After executing Free(X), the value of X is @key{null}. Free(X), when X is already equal to @key{null}, has no effect. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} Free(X), when X is not equal to @key{null} first performs finalization@Chg{Version=[2],New=[ of the object designated by X (and any coextensions of the object @em see @RefSecNum{Operations of Access Types})], Old=[]}, as described in @Chg{Version=[2],New=[@RefSecNum{Completion and Finalization}], Old=[@RefSecNum{User-Defined Assignment and Finalization}]}. It then deallocates the storage occupied by the object designated by X@Chg{Version=[2],New=[ (and any coextensions)],Old=[]}. If the storage pool is a user-defined object, then the storage is deallocated by calling Deallocate, passing @i[access_to_@!variable_@!subtype_name]'Storage_Pool as the Pool parameter. Storage_Address is the value returned in the Storage_Address parameter of the corresponding Allocate call. Size_In_@!Storage_@!Elements and Alignment are the same values passed to the corresponding Allocate call. There is one exception: if the object being freed contains tasks, the object might not be deallocated. @begin{Ramification} Free calls only the specified Deallocate procedure to do deallocation. For any given object deallocation, the number of calls to Free (usually one) will be equal to the number of Allocate calls it took to allocate the object. We do not define the relative order of multiple calls used to deallocate the same object @em that is, if the @nt{allocator} allocated two pieces @i{x} and @i{y}, then Free might deallocate @i{x} and then @i{y}, or it might deallocate @i{y} and then @i{x}. @end{Ramification} @end{Enumerate} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @IndexSee{Term=[freed],See=(nonexistent)} @Defn{nonexistent} @PDefn2{Term=[exist],Sec=[cease to]} @PDefn2{Term=[cease to exist],Sec=[object]} After Free(X), the object designated by X, and any subcomponents @Chg{Version=[2],New=[(and coextensions) ],Old=[]}thereof, no longer exist; their storage can be reused for other purposes. @end{RunTime} @begin{Bounded} @Leading@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to free a discriminated, unterminated task object. The possible consequences are: @begin{Reason} This is an error because the task might refer to its discriminants, and the discriminants might be deallocated by freeing the task object. @end{Reason} @begin{Itemize} No exception is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Program_Error or Tasking_Error is raised at the point of the deallocation. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Program_Error or Tasking_Error is raised in the task the next time it references any of the discriminants. @begin{ImplNote} This last case presumes an implementation where the task references its discriminants indirectly, and the pointer is nulled out when the task object is deallocated. @end{ImplNote} @end{Itemize} In the first two cases, the storage for the discriminants (and for any enclosing object if it is designated by an access discriminant of the task) is not reclaimed prior to task termination. @begin{Ramification} The storage might never be reclaimed. @end{Ramification} @end{Bounded} @begin{Erron} @Defn{nonexistent}@PDefn2{Term=(erroneous execution),Sec=(cause)} Evaluating a name that denotes a nonexistent object is erroneous. The execution of a call to an instance of Unchecked_Deallocation is erroneous if the object was created other than by an @nt<allocator> for an access type whose pool is Name'Storage_Pool. @end{Erron} @begin{ImplAdvice} For a standard storage pool, Free should actually reclaim the storage. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For a standard storage pool, an instance of Unchecked_Deallocation should actually reclaim the storage.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This is not a testable property, since we do not @Chg{Version=[2],New=[know ],Old=[]}how much storage is used by a given pool element, nor whether fragmentation can occur. @end{Ramification} @end{ImplAdvice} @begin{Notes} The rules here that refer to Free apply to any instance of Unchecked_Deallocation. Unchecked_Deallocation cannot be instantiated for an access-to-constant type. This is implied by the rules of @RefSecNum{Formal Access Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The rules for coextensions are clarified (mainly by adding that term). In theory, this reflects no change from Ada 95 (coextensions existed in Ada 95, they just didn't have a name).]} @end{DiffWord95} @LabeledSubClause{Pragma Controlled} @begin{Intro} @Redundant[Pragma Controlled is used to prevent any automatic reclamation of storage (garbage collection) for the objects created by @nt<allocator>s of a given access type.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Controlled is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Controlled)(@SynI{first_subtype_}@Syn2{local_name});' @begin{Discussion} Not to be confused with type Finalization.Controlled. @end{Discussion} @end{Syntax} @begin{Legality} The @SynI{first_subtype_}@nt<local_name> of a @nt{pragma} Controlled shall denote a non-derived access subtype. @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Controlled)} @PDefn2{Term=[pragma, representation], Sec=(Controlled)} A @nt{pragma} Controlled is a representation pragma @PDefn2{Term=[aspect of representation], Sec=(controlled)} @Defn2{Term=[controlled], Sec=(aspect of representation)} that specifies the @i{controlled} aspect of representation. @Defn{garbage collection} @i{Garbage collection} is a process that automatically reclaims storage, or moves objects to a different address, while the objects still exist. @begin{Ramification} Storage reclamation upon leaving a master is not considered garbage collection. Note that garbage collection includes compaction of a pool (@lquotes@;moved to a different Address@rquotes@;), even if storage reclamation is not done. @end{Ramification} @begin{Reason} Programs that will be damaged by automatic storage reclamation are just as likely to be damaged by having objects moved to different locations in memory. A @nt{pragma} Controlled should turn off both flavors of garbage collection. @end{Reason} @begin{ImplNote} If garbage collection reclaims the storage of a controlled object, it should first finalize it. Finalization is not done when moving an object; any self-relative pointers will have to be updated by the garbage collector. If an implementation provides garbage collection for a storage pool containing controlled objects (see @RefSecNum{User-Defined Assignment and Finalization}), then it should provide a means for deferring garbage collection of those controlled objects. @end{ImplNote} @begin{Reason} @Leading@;This allows the manager of a resource released by a Finalize operation to defer garbage collection during its critical regions; it is up to the author of the Finalize operation to do so. Garbage collection, at least in some systems, can happen asynchronously with respect to normal user code. Note that it is not enough to defer garbage collection during Initialize, Adjust, and Finalize, because the resource in question might be used in other situations as well. For example: @begin{Example} @key[with] Ada.Finalization; @key[package] P @key[is] @key[type] My_Controlled @key[is] @key[new] Ada.Finalization.Limited_Controlled @key[with] @key[private]; @key[procedure] Finalize(Object : @key[in] @key[out] My_Controlled); @key[type] My_Controlled_Access @key[is] @key[access] My_Controlled; @key[procedure] Non_Reentrant; @key[private] ... @key[end] P; @key[package] @key[body] P @key[is] X : Integer := 0; A : @key[array](Integer @key[range] 1..10) @key[of] Integer; @key[procedure] Non_Reentrant @key[is] @key[begin] X := X + 1; --@RI{ If the system decides to do a garbage collection here,} --@RI{ then we're in trouble, because it will call Finalize on} --@RI{ the collected objects; we essentially have two threads} --@RI{ of control erroneously accessing shared variables.} --@RI{ The garbage collector behaves like a separate thread} --@RI{ of control, even though the user hasn't declared} --@RI{ any tasks.} A(X) := ...; @key[end] Non_Reentrant; @key[procedure] Finalize(Object : @key[in] @key[out] My_Controlled) @key[is] @key[begin] Non_Reentrant; @key[end] Finalize; @key[end] P; @key[with] P; @key[use] P; @key[procedure] Main @key[is] @key[begin] ... @key[new] My_Controlled ... --@RI{ allocate some objects} ... @RI{ forget the pointers to some of them, so they become garbage} Non_Reentrant; @key[end] Main; @end{Example} It is the user's responsibility to protect against this sort of thing, and the implementation's responsibility to provide the necessary operations. We do not give these operations names, nor explain their exact semantics, because different implementations of garbage collection might have different needs, and because garbage collection is not supported by most Ada implementations, so portability is not important here. Another reason not to turn off garbage collection during each entire Finalize operation is that it would create a serial bottleneck; it might be only part of the Finalize operation that conflicts with some other resource. It is the intention that the mechanisms provided be finer-grained than pragma Controlled. @end{Reason} If a @nt{pragma} Controlled is specified for an access type with a standard storage pool, then garbage collection is not performed for objects in that pool. @begin{Ramification} If Controlled is not specified, the implementation may, but need not, perform garbage collection. If Storage_Pool is specified, then a @nt{pragma} Controlled for that type is ignored. @end{Ramification} @begin{Reason} Controlled means that implementation-provided garbage collection is turned off; if the Storage_Pool is specified, the pool controls whether garbage collection is done. @end{Reason} @end{StaticSem} @begin{ImplPerm} An implementation need not support garbage collection, in which case, a pragma Controlled has no effect. @end{ImplPerm} @begin{DiffWord83} Ada 83 used the term @lquotes@;automatic storage reclamation@rquotes@; to refer to what is known traditionally as @lquotes@;garbage collection@rquotes@;. Because of the existence of storage pools (see @RefSecNum{Storage Management}), we need to distinguish this from the storage reclamation that might happen upon leaving a master. Therefore, we now use the term @lquotes@;garbage collection@rquotes@; in its normal computer-science sense. This has the additional advantage of making our terminology more accessible to people outside the Ada world. @end{DiffWord83} @LabeledClause{Pragma Restrictions} @begin{Intro} @redundant[A @nt{pragma} Restrictions expresses the user's intent to abide by certain restrictions. This may facilitate the construction of simpler run-time environments.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@keepnext@;The form of a @nt{pragma} Restrictions is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Restrictions)(@Syn2{restriction}{, @Syn2{restriction}});' @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00381-01]} @Syn{lhs=(restriction), rhs="@SynI{restriction_}@Syn2{identifier} | @SynI{restriction_parameter_}@Syn2{identifier} => @Chg{Version=[2],New=[@Syn2{restriction_parameter_argument}],Old=[@Syn2{expression}]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00381-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<restriction_parameter_argument>,Old=<>}>, rhs="@Chg{Version=[2],New=<@Syn2{name} | @Syn2{expression}>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(restriction parameter expression)} Unless otherwise specified for a particular restriction, the @nt{expression} is expected to be of any integer type. @end{Resolution} @begin{Legality} Unless otherwise specified for a particular restriction, the @nt{expression} shall be static, and its value shall be nonnegative. @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00394-01]} The set of @Chg{Version=[2],New=[restrictions],Old=[@ntf{restrictions}]} is implementation defined. @ChgImplDef{Version=[2],Kind=[Revised],Text=[The set of @Chg{Version=[2],New=[restrictions],Old=[@ntf{restrictions}]} allowed in a @nt{pragma} Restrictions.]} @end{StaticSem} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Restrictions)} @PDefn2{Term=[pragma, configuration], Sec=(Restrictions)} A @nt{pragma} Restrictions is a configuration pragma; unless otherwise specified for a particular restriction, a partition shall obey the restriction if a @nt{pragma} Restrictions applies to any compilation unit included in the partition. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[For the purpose of checking whether a partition contains constructs that violate any restriction (unless specified otherwise for a particular restriction):]} @begin{itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[Generic instances are logically expanded at the point of instantiation;]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[If an object of a type is declared or allocated and not explicitly initialized, then all expressions appearing in the definition for the type and any of its ancestors are presumed to be used;]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[A @nt{default_expression} for a formal parameter or a generic formal object is considered to be used if and only if the corresponding actual parameter is not provided in a given call or instantiation.]} @end{itemize} @end{LinkTime} @begin{ImplPerm} An implementation may place limitations on the values of the @nt{expression} that are supported, and limitations on the supported combinations of restrictions. The consequences of violating such limitations are implementation defined. @ImplDef{The consequences of violating limitations on Restrictions @nt{pragma}s.} @begin{Ramification} Such limitations may be enforced at compile time or at run time. Alternatively, the implementation is allowed to declare violations of the restrictions to be erroneous, and not enforce them at all. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[An implementation is permitted to omit restriction checks for code that is recognized at compile time to be unreachable and for which no code is generated.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0043],ARef=[AI95-00190-01]} @ChgAdded{Version=[1],Text=[Whenever enforcement of a restriction is not required prior to execution, an implementation may nevertheless enforce the restriction prior to execution of a partition to which the restriction applies, provided that every execution of the partition would violate the restriction.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00347-01]} Restrictions intended to facilitate the construction of efficient tasking run-time systems are defined in @RefSecNum{Tasking Restrictions}. @Chg{Version=[2],New=[Restrictions intended for use when constructing high integrity systems],Old=[Safety- and security-related restrictions]} are defined in @RefSecNum{High Integrity Restrictions}. An implementation has to enforce the restrictions in cases where enforcement is required, even if it chooses not to take advantage of the restrictions in terms of efficiency. @begin{Discussion} It is not the intent that an implementation will support a different run-time system for every possible combination of restrictions. An implementation might support only two run-time systems, and document a set of restrictions that is sufficient to allow use of the more efficient and safe one. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Pragma Restrictions is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording so that restrictions are checked inside of generic instantiations and in default expressions. Since not making these checks would violate the purpose of restrictions, we are not documenting this as an incompatibility.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0043],ARef=[AI95-00190-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added a permission that restrictions can be enforced at compile-time. While this is technically incompatible, documenting it as such would be unnecessarily alarming - there should not be any programs depending on the runtime failure of restrictions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[The syntax of a @nt{restriction_parameter_argument} has been defined to better support restriction No_Dependence (see @RefSecNum{Language-Defined Restrictions}).]} @end{DiffWord95} @LabeledAddedSubclause{Version=[2], Name=[Language-Defined Restrictions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_}@nt{identifier}s are language-defined (additional restrictions are defined in the Specialized Needs Annexes):]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Implementation_Attributes)}No_Implementation_Attributes @\There are no implementation-defined attributes. This restriction applies only to the current compilation or environment, not the entire partition.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This restriction (as well as No_Implementation_Pragmas) only applies to the current compilation, because it is likely that the runtime (and possibly user-written low-level code) will need to use implementation-defined entities. But a partition-wide restriction applies everywhere, including the runtime.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Implementation_Pragmas)}No_Implementation_Pragmas @\There are no implementation-defined pragmas or pragma arguments. This restriction applies only to the current compilation or environment, not the entire partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00368-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Obsolescent_Features)}No_Obsolescent_Features @\There is no use of language features defined in Annex J. It is implementation-defined if uses of the renamings of @RefSecNum{Renamings of Ada 83 Library Units} are detected by this restriction. This restriction applies only to the current compilation or environment, not the entire partition.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[A user could compile a rename like]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Text_IO; @key{package} Text_IO @key{renames} Ada.Text_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such a rename must not be disallowed by this restriction, nor should the compilation of such a rename be restricted by an implementation. Many implementations implement the renames of @RefSecNum{Renamings of Ada 83 Library Units} by compiling them normally; we do not want to require implementations to use a special mechanism to implement these renames.]} @end{Reason} @end{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_parameter_}@nt{identifier} is language defined:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Dependence)}No_Dependence @\Specifies a library unit on which there are no semantic dependences.]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[The @nt{restriction_parameter_argument} of a No_Dependence restriction shall be a @nt{name}; the @nt{name} shall have the form of a full expanded name of a library unit, but need not denote a unit present in the environment.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This @nt{name} is not resolved.]} @end{Ramification} @end{Legality} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[No compilation unit included in the partition shall depend semantically on the library unit identified by the @nt{name}.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no requirement that the library unit actually exist. One possible use of the pragma is to prevent the use of implementation-defined units; when the program is ported to a different compiler, it is perfectly reasonable that no unit with the name exist.]} @end{Ramification} @end{LinkTime} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01],ARef=[AI95-00368-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Restrictions No_Implementation_Attributes, No_Implementation_Pragmas, and No_Obsolescent_Features are new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence is new.]} @end{Extend95} @LabeledClause{Streams} @begin{Intro} @Defn{stream} @Defn{stream type} A @i{stream} is a sequence of elements comprising values from possibly different types and allowing sequential access to these values. A @i{stream type} is a type in the class whose root type is Streams.Root_Stream_Type. A stream type may be implemented in various ways, such as an external sequential file, an internal buffer, or a network channel. @begin{Discussion} A stream element will often be the same size as a storage element, but that is not required. @end{Discussion} @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} Streams are new in Ada 95. @end{Extend83} @LabeledSubClause{The Package Streams} @begin{StaticSem} The abstract type Root_Stream_Type is the root type of the class of stream types. The types in this class represent different kinds of streams. A new stream type is defined by extending the root type (or some other stream type), overriding the Read and Write operations, and optionally defining additional primitive subprograms, according to the requirements of the particular kind of stream. The predefined stream-oriented attributes like T'Read and T'Write make dispatching calls on the Read and Write procedures of the Root_Stream_Type. (User-defined T'Read and T'Write attributes can also make such calls, or can call the Read and Write attributes of other types.) @begin{example} @ChildUnit{Parent=[Ada],Child=[Streams]}@key[package] Ada.Streams @key[is] @key[pragma] Pure(Streams)@Defn{unpolluted};@Comment{This *must* be a Duff joke} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Root_Stream_Type} @key[is] @key[abstract tagged limited private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Root_Stream_Type);],Old=[]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0044],ARef=[AI95-00181-01]} @key[type] @AdaTypeDefn{Stream_Element} @key[is] @key[mod] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Stream_Element_Offset} @key[is] @key[range] @RI{implementation-defined}; @key[subtype] @AdaSubtypeDefn{Name=[Stream_Element_Count],Of=[Stream_Element_Offset]} @key[is] Stream_Element_Offset @key[range] 0..Stream_Element_Offset'Last; @key[type] @AdaTypeDefn{Stream_Element_Array} @key[is] @key[array](Stream_Element_Offset @key[range] <>) @key[of]@Chg{New=[@key[ aliased]],Old=[]} Stream_Element; @key[procedure] @AdaSubDefn{Read}( Stream : @key[in] @key[out] Root_Stream_Type; Item : @key[out] Stream_Element_Array; Last : @key[out] Stream_Element_Offset) @key[is abstract]; @key[procedure] @AdaSubDefn{Write}( Stream : @key[in] @key[out] Root_Stream_Type; Item : @key[in] Stream_Element_Array) @key[is abstract]; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Streams; @end{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00227-01]} The Read operation transfers @Chg{Version=[2],New=[],Old=[Item'Length ]}stream elements from the specified stream to fill the array Item. @Chg{Version=[2],New=[Elements are transferred until Item'Length elements have been transferred, or until the end of the stream is reached. If any elements are transferred, the],Old=[The]} index of the last stream element transferred is returned in Last. @Chg{Version=[2],New=[Otherwise, Item'First - 1 is returned in Last. ],Old=[]}Last is less than Item'Last only if the end of the stream is reached.@Comment{This last sentence should be marked Redundant.} The Write operation appends Item to the specified stream. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgNote{This was moved from 13.7.1.} @ChgAdded{Version=[2],Text=[The index subtype of Stream_Element_Array is Stream_Element_Offset because we wish to allow maximum flexibility. Most Stream_Element_Arrays will probably have a lower bound of 0 or 1, but other lower bounds, including negative ones, make sense in some situations.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgNote{This was moved from 13.7.1, where it was totally bogus.} @ChgAdded{Version=[2],Text=[Note that there are some language-defined subprograms that fill part of a Stream_Element_Array, and return the index of the last element filled as a Stream_Element_Offset. The Read procedures declared here, Streams.Stream_IO (see @RefSecNum{The Package Streams.Stream_IO}), and System.RPC (see @RefSecNum{Partition Communication Subsystem}) behave in this manner. These will raise Constraint_Error if the resulting Last value is not in Stream_Element_Offset. This implies that the Stream_Element_Array passed to these subprograms should not have a lower bound of Stream_Element_Offset'First, because then a read of 0 elements would always raise Constraint_Error. A better choice of lower bound is 1.]} @end{Discussion} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0044],ARef=[AI95-00181-01]} @ChgAdded{Version=[1],Text=[If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_@!Element_@!Array need not be aliased.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @ChgAdded{Version=[1],Text=[If the Stream_Element'Size is less than the size of System.Storage_Unit, then components of Stream_@!Element_@!Array need not be aliased. This is necessary as the components of type Stream_Element size might not be addressable on the target @Chg{Version=[2],New=[architecture],Old=[architechture]}.]} @end{Ramification} @end{ImplPerm} @begin{Notes} See @RefSec{The Package Streams.Stream_IO} for an example of extending type Root_Stream_Type. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00227-01]} @ChgAdded{Version=[2],Text=[If the end of stream has been reached, and Item'First is Stream_Element_Offset'First, Read will raise Constraint_Error.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, Stream_Element_Arrays should start at 0 or 1, not Stream_Element_Offset'First.]} @end{Ramification} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type Root_Stream_Type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0044],ARef=[AI95-00181-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Stream elements are aliased presuming that makes sense.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00227-01]} @ChgAdded{Version=[2],Text=[Fixed the wording for Read to properly define the result in Last when no stream elements are transfered.]} @end{DiffWord95} @LabeledSubClause{Stream-Oriented Attributes} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The @Chg{New=[operational attributes ],Old=[]}Write, Read, Output, and Input @Chg{New=[],Old=[attributes ]}convert values to a stream of elements and reconstruct values from a stream. @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For @PrefixType{every subtype S of an elementary type @i(T)}, the following representation attribute is defined:]} @begin{Description} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Stream_Size>, ARef=[AI95-00270-01], Text=[@Chg{Version=[2],New=[Denotes the number of bits occupied in a stream by items of subtype S. Hence, the number of stream elements required per item of elementary type @i<T> is:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@i<T>'Stream_Size / Ada.Streams.Stream_Element'Size]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The value of this attribute is of type @i{universal_integer} and is a multiple of Stream_Element'Size.]}]}@Comment{end attribute Stream_Size} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[Stream_Size may be specified for first subtypes via an @nt{attribute_definition_clause}; the @nt{expression} of such a clause shall be static, nonnegative, and a multiple of Stream_Element'Size.]} @end{Description} @EndPrefixType{} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Stream_Size is a type-related attribute (see @RefSecNum{Operational and Representation Items}).]} @end{Discussion} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[If not specified, the value of Stream_Size for an elementary type should be the number of bits that corresponds to the minimum number of stream elements required by the first subtype of the type, rounded up to the nearest factor or multiple of the word size that is also a multiple of the stream element size.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If not specified, the value of Stream_Size for an elementary type should be the number of bits that corresponds to the minimum number of stream elements required by the first subtype of the type, rounded up to the nearest factor or multiple of the word size that is also a multiple of the stream element size.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[This is @ImplAdviceTitle because we want to allow implementations to remain compatible with their Ada 95 implementations, which may have a different handling of the number of stream elements. Users can always specify Stream_Size if they need a specific number of stream elements.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@PDefn2{Term=[recommended level of support], Sec=(Stream_Size attribute)} The recommended level of support for the Stream_Size attribute is:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[A Stream_Size clause should be supported for a discrete or fixed point type @i<T> if the specified Stream_Size is a multiple of Stream_Element'Size and is no less than the size of the first subtype of @i<T>, and no greater than the size of the largest type of the same elementary class (signed integer, modular integer, enumeration, ordinary fixed point, or decimal fixed point).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Stream_Size attribute should be followed.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no requirements beyond supporting confirming Stream_Size clauses for floating point and access types. Floating point and access types usually only have a handful of defined formats, streaming anything else makes no sense for them.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For discrete and fixed point types, this may require support for sizes other than the @lquotes@;natural@rquotes ones. For instance, on a typical machine with 32-bit integers and a Stream_Element'Size of 8, setting Stream_Size to 24 must be supported. This is required as such formats can be useful for interoperability with unusual machines, and there is no difficulty with the implementation (drop extra bits on output, sign extend on input).]} @end{Ramification} @end{Itemize} @end{ImplAdvice} @RMNewPage@Comment{For printed Ada 2005 RM} @begin{StaticSem} For @PrefixType{every subtype S of a specific type @i(T)}, the following attributes are defined. @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Write>, Text=<S'Write denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Write( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)) @end{DescExample} @noprefix@;S'Write writes the value of @i{Item} to @i{Stream}.>} @AttributeLeading{Prefix=<S>, AttrName=<Read>, Text=<S'Read denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Read( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{out} @RI(T)) @end{DescExample} @noprefix@;S'Read reads the value of @i{Item} from @i{Stream}.>} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgAdded{Version=[1],Text=[For @Chg{Version=[2],New=[an ],Old=[]}untagged derived @Chg{Version=[2],New=[type],Old=[types]}, the Write @Chg{Version=[2],New=[(resp.],Old=[and]} Read@Chg{Version=[2],New=[) attribute is],Old=[ attributes are]} inherited @Chg{Version=[2],New=[according to the rules given],Old=[as specified]} in @RefSecNum(Operational and Representation Items)@Chg{Version=[2], New=[ if the attribute is available for the parent type at the point where @i{T} is declared. For a tagged derived type, these attributes are not inherited, but rather],Old=[; otherwise,]} the default implementations @Chg{Version=[2],New=[],Old=[of these attributes ]}are used.@Chg{Version=[2],New=[],Old=[The default implementations of Write and Read attributes execute as follows:]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The default implementations of the Write and Read attributes, where available, execute as follows:]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01],ARef=[AI95-00251-01],ARef=[AI95-00270-01]} For elementary types, @Chg{Version=[2],New=[Read reads (and Write writes) the number of stream elements implied by the Stream_Size for the type @i<T>;], Old=[]} the representation @Chg{Version=[2],New=[],Old=[in terms ]}of@Chg{Version=[2], New=[ those],Old=[]} stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in @Chg{New=[],Old=[a ]}canonical order@Chg{New=[, which], Old=[. The canonical order of components]} is last dimension varying fastest for an array, and positional aggregate order for a record. Bounds are not included in the stream if @i(T) is an array type. If @i(T) is a discriminated type, discriminants are included only if they have defaults. If @i(T) is a tagged type, the tag is not included. @Chg{New=[For type extensions, the Write or Read attribute for the parent type is called, followed by the Write or Read attribute of each component of the extension part, in canonical order. For a limited type extension, if the attribute of @Chg{Version=[2],New=[the parent],Old=[any ancestor]} type @Chg{Version=[2],New=[or any progenitor type ],Old=[]}of @i(T) @Chg{Version=[2],New=[is available anywhere within the immediate scope of @i<T>,],Old=[has been directly specified]} and the attribute of @Chg{Version=[2],New=[the parent type or],Old=[any ancestor type of]} the type of any of the extension components @Chg{Version=[2],New=[is not available at the freezing point of @i<T>, then], Old=[which are of a limited type has not been specified,]} the attribute of @i(T) shall be directly specified.],Old=[]} @ChgImplDef{Version=[2],Kind=[Revised],Text=[The @Chg{Version=[2],New=[contents of the stream elements read and written],Old=[representation used]} by the Read and Write attributes of elementary types@Chg{Version=[2],New=[],Old=[ in terms of stream elements]}.]} @begin{Reason} A discriminant with a default value is treated simply as a component of the object. On the other hand, an array bound or a discriminant without a default value, is treated as @lquotes@;descriptor@rquotes@; or @lquotes@;dope@rquotes@; that must be provided in order to create the object and thus is logically separate from the regular components. Such @lquotes@;descriptor@rquotes@; data are written by 'Output and produced as part of the delivered result by the 'Input function, but they are not written by 'Write nor read by 'Read. A tag is like a discriminant without a default. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[For limited type extensions, we must have a definition of 'Read and 'Write if the parent type has one, as it is possible to make a dispatching call through the attributes. The rule is designed to automatically do the right thing in as many cases as possible.]} @ChgRef{Version=[1],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[1],Text=[Similarly, a type that has a progenitor with an available attribute must also have that attribute, for the same reason.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} For a composite object, the subprogram denoted by the Write or Read attribute of each component is called, whether it is the default or is user-specified.@Chg{Version=[2],New=[ Implementations are allowed to optimize these calls (see below), presuming the properties of the attributes are preserved.],Old=[]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[Constraint_Error is raised by the predefined Write attribute if the value of the elementary item is outside the range of values representable using Stream_Size bits. For a signed integer type, an enumeration type, or a fixed point type, the range is unsigned only if the integer code for the lower bound of the first subtype is nonnegative, and a (symmetric) signed range that covers all values of the first subtype would require more than Stream_Size bits; otherwise the range is signed.]} @Leading@;For @PrefixType{every subtype S'Class of a class-wide type @i(T)'Class}: @begin{Description} @AttributeLeading{Prefix=<S'Class>, AttrName=<Write>, Text=<S'Class'Write denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Write( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)'Class) @end{DescExample} @noprefix@;Dispatches to the subprogram denoted by the Write attribute of the specific type identified by the tag of Item.>} @AttributeLeading{Prefix=<S'Class>, AttrName=<Read>, Text=<S'Class'Read denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Read( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{out} @RI(T)'Class) @end{DescExample} @noprefix@;Dispatches to the subprogram denoted by the Read attribute of the specific type identified by the tag of Item.>} @begin{Reason} It is necessary to have class-wide versions of Read and Write in order to avoid generic contract model violations; in a generic, we don't necessarily know at compile time whether a given type is specific or class-wide. @end{Reason} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00270-01]} @ChgDeleted{Version=[2],Text=[If a stream element is the same size as a storage element, then the normal in-memory representation should be used by Read and Write for scalar objects. Otherwise, Read and Write should use the smallest number of stream elements needed to represent all values in the base range of the scalar type.]} @ChgNote{We don't add an Implementation Advice tag here, as we're deleting this.} @end{ImplAdvice} @begin{StaticSem} For @PrefixType{every subtype S of a specific type @i(T)}, the following attributes are defined. @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Output>, Text=<S'Output denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Output( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)) @end{DescExample} @noprefix@;S'Output writes the value of @i{Item} to @i{Stream}, including any bounds or discriminants.>} @begin{Ramification} Note that the bounds are included even for an array type whose first subtype is constrained. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Input>, Text=<S'Input denotes a function with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(function) S'Input( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class) @key(return) @RI(T) @end{DescExample} @noprefix@;S'Input reads and returns one value from @i{Stream}, using any bounds or discriminants written by a corresponding S'Output to determine how much to read.>} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00444-01]} @Chg{New=[For @Chg{Version=[2],New=[an ],Old=[]}untagged derived @Chg{Version=[2],New=[type],Old=[types]}, the Output @Chg{Version=[2],New=[(resp.],Old=[and]} Input@Chg{Version=[2],New=[) attribute is],Old=[attributes of the parent type are]} inherited @Chg{Version=[2],New=[according to the rules given], Old=[as specified]} in @RefSecNum(Operational and Representation Items)@Chg{Version=[2], New=[ if the attribute is available for the parent type at the point where @i{T} is declared. For a tagged derived type, these attributes are not inherited, but rather],Old=[; otherwise,]} the default implementations@Chg{Version=[2],New=[],Old=[ of these attributes]} are used.@Chg{Version=[2],New=[],Old=[ The default implementations of Output and Input attributes execute as follows:]}], Old=[Unless overridden by an @nt<attribute_definition_clause>, these subprograms execute as follows:]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The default implementations of the Output and Input attributes, where available, execute as follows:]} @begin(Itemize) If @i(T) is an array type, S'Output first writes the bounds, and S'Input first reads the bounds. If @i(T) has discriminants without defaults, S'Output first writes the discriminants (using S'Write for each), and S'Input first reads the discriminants (using S'Read for each). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} S'Output then calls S'Write to write the value of @i{Item} to the stream. S'Input then creates an object (with the bounds or discriminants, if any, taken from the stream), @Chg{Version=[2],New=[passes],Old=[initializes]} it @Chg{Version=[2],New=[to],Old=[with]} S'Read, and returns the value of the object.@Chg{Version=[2],New=[ Normal default initialization and finalization take place for this object (see @RefSecNum{Object Declarations}, @RefSecNum{User-Defined Assignment and Finalization}, and @RefSecNum{Completion and Finalization}).],Old=[]} @end(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If @i<T> is an abstract type, then S'Input is an abstract function.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For an abstract type @i<T>, S'Input can be called in a dispatching call, or passed to a abstract formal subprogram. But it cannot be used in non-dispatching contexts, because we don't allow objects of abstract types to exist. The designation of this function as abstract has no impact on descendants of @i<T>, as @i<T>'Input is not inherited for tagged types, but rather recreated (and the default implementation of @i<T>'Input calls @i<T>'Read, not the parent type's @i<T>'Input). Note that @i<T>'Input cannot be specified in this case, as any function with the proper profile is necessarily abstract, and specifying abstract subprograms in an @nt{attribute_definition_clause} is illegal.]} @end{Ramification} @Leading@;For @PrefixType{every subtype S'Class of a class-wide type @i(T)'Class}: @begin{Description} @AttributeLeading{Prefix=<S'Class>, AttrName=<Output>, Text=<S'Class'Output denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Output( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)'Class) @end{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @noprefix@;First writes the external tag of @i{Item} to @i{Stream} (by calling String'Output(@Chg{Version=[2],New=[@I{Stream}, ],Old=[]}Tags.@!External_Tag(@i{Item}'Tag)@Chg{Version=[2],New=[)],Old=[]} @em see @RefSecNum{Tagged Types and Type Extensions}) and then dispatches to the subprogram denoted by the Output attribute of the specific type identified by the tag.@Chg{Version=[2],New=[ Tag_Error is raised if the tag of Item identifies a type declared at an accessibility level deeper than that of S.],Old=[]}>}@Comment{End of S'Class'Output attribute} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[We raise Tag_Error here for nested types as such a type cannot be successfully read with S'Class'Input, and it doesn't make sense to allow writing a value that cannot be read.]} @end{Reason} @AttributeLeading{Prefix=<S'Class>, AttrName=<Input>, Text=<S'Class'Input denotes a function with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(function) S'Class'Input( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class) @key{return} @RI(T)'Class @end{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @noprefix@;First reads the external tag from @i{Stream} and determines the corresponding internal tag (by calling Tags.@Chg{Version=[2],New=[Descendant_Tag], Old=[Internal_Tag]}(String'Input(@i{Stream})@Chg{Version=[2],New=[, S'Tag],Old=[]}) @Chg{Version=[2],New=[which might raise Tag_Error ],Old=[]}@em see @RefSecNum{Tagged Types and Type Extensions}) and then dispatches to the subprogram denoted by the Input attribute of the specific type identified by the internal tag; returns that result.@Chg{Version=[2],New=[ If the specific type identified by the internal tag is not covered by @i<T>'Class or is abstract, Constraint_Error is raised.],Old=[]}>}@Comment{End S'Class'Input attribute} @end{Description} @EndPrefixType{} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} @IndexCheck{Range_Check} In the default implementation of Read and Input for a composite type, for each scalar component that is a discriminant or whose @nt{component_declaration} includes a @nt{default_expression}, a check is made that the value returned by Read for the component belongs to its subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. For other scalar components, no check is made. For each component that is of an access type, if the implementation can detect that the value returned by Read for the component is not a value of its subtype, Constraint_Error is raised. If the value is not a value of its subtype and this error is not detected, the component has an abnormal value, and erroneous execution can result (see @RefSecNum{Data Validity}).@Chg{Version=[2],New=[ In the default implementation of Read for a composite type with defaulted discriminants, if the actual parameter of Read is constrained, a check is made that the discriminants read from the stream are equal to those of the actual parameter. Constraint_Error is raised if this check fails.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[@PDefn{unspecified}It is unspecified at which point and in which order these checks are performed. In particular, if Constraint_Error is raised due to the failure of one of these checks, it is unspecified how many stream elements have been read from the stream.]} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0045],ARef=[AI95-00132-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[End_Error],Sec=(raised by failure of run-time check)} In the default implementation of Read and Input for a type, End_Error is raised if the end of the stream is reached before the reading of a value of the type is completed.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01],ARef=[AI95-00251-01]} @PDefn2{Term=[specifiable], Sec=(of Read for a type)} @PDefn2{Term=[specifiable], Sec=(of Write for a type)} @PDefn2{Term=[specifiable], Sec=(of Input for a type)} @PDefn2{Term=[specifiable], Sec=(of Output for a type)} @Defn{Read clause} @Defn{Write clause} @Defn{Input clause} @Defn{Output clause} The stream-oriented attributes may be specified for any type via an @nt{attribute_definition_clause}. @Chg{Version=[2],New=[The subprogram name given in such a clause shall not denote an abstract subprogram. Furthermore, if a stream-oriented attribute is specified for an interface type by an @nt{attribute_definition_clause}, the subprogram name given in the clause shall statically denote a null procedure.], Old=[All nonlimited types have default implementations for these operations. An @nt{attribute_reference} for one of these attributes is illegal if the type is limited, unless the attribute has been specified by an @nt{attribute_@!definition_@!clause}@Chg{New=[ or @Redundant[(for a type extension)] the attribute has been specified for an ancestor type],Old=[]}. For an @nt{attribute_@!definition_@!clause} specifying one of these attributes, the subtype of the Item parameter shall be the base subtype if scalar, and the first subtype otherwise. The same rule applies to the result of the Input function.]} @ChgNote{Most of the old text is moved down} @begin{Reason}@ChgNote{This belongs below} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00195-01]} @ChgDeleted{Version=[2],Text=[This is to simplify implementation.]} @end{Reason} @begin{Discussion}@ChgNote{This is junk} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00195-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[@lquotes@;Specified@rquotes includes inherited attributes, and default implementations are never inherited. So, for untagged limited types, the second part of the @nt{attribute_reference} rule has the same meaning as the first part. However, tagged types never inherit attributes, so the second rule is needed so that the default implementations for the attributes can be called when those are constructed from a directly specified ancestor.],Old=[]}]} @end{Discussion} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Stream attributes (other than Input) are always null procedures for interface types (they have no components). We need to allow explicit setting of the Read and Write attributes in order that the class-wide attributes like LI'Class'Input can be made available. (In that case, any descendant of the interface type would require available attributes.) But we don't allow any concrete implementation because these don't participate in extensions (unless the interface is the parent type). If we didn't ban concrete implementations, the order of declaration of a pair of interfaces would become significant. For example, if Int1 and Int2 are interfaces with concrete implementations of 'Read, then the following declarations would have different implementations for 'Read:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Con1 @key{is new} Int1 @key{and} Int2 @key{with null record}; @key{type} Con2 @key{is new} Int2 @key{and} Int1 @key{with null record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[This would violate our design principle that the order of the specification of the interfaces in a @nt{derived_type_definition} doesn't matter.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The Input attribute cannot be specified for an interface. As it is a function, a null procedure is impossible; a concrete function is not possible anyway as any function returning an abstract type must be abstract. And we don't allow specifying stream attributes to be abstract subprograms. This has no impact, as the availability of Int'Class'Input (where Int is a limited interface) depends on whether Int'Read (not Int'Input) is specified. There is no reason to allow Int'Output to be specified, either, but there is equally no reason to disallow it, so we don't have a special rule for that.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Limited types generally do not have default implementations of the stream-oriented attributes. The rules defining when a stream-oriented attribute is available (see below) determine when an attribute of a limited type is in fact well defined and usable. The rules are designed to maximize the number of cases in which the attributes are usable. For instance, when the language provides a default implementation of an attribute for a limited type based on a specified attribute for the parent type, we want to be able to call that attribute.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A stream-oriented attribute for a subtype of a specific type @i<T> is @i<available> at places where one of the following conditions is true: @Defn2{Term=[available],Sec=[stream attribute]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T> is nonlimited.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @nt{attribute_designator} is Read (resp. Write) and @i<T> is a limited record extension, and the attribute Read (resp. Write) is available for the parent type of @i<T> and for the types of all of the extension components.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, the language provides a well-defined default implementation, which we want to be able to call.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{T} is a limited untagged derived type, and the attribute was inherited for the type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Attributes are only inherited for untagged derived types, and surely we want to be able to call inherited attributes.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @nt{attribute_designator} is Input (resp. Output), and @i<T> is a limited type, and the attribute Read (resp. Write) is available for @i<T>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The default implementation of Input and Output are based on Read and Write; so if the implementation of Read or Write is good, so is the matching implementation of Input or Output.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The attribute has been specified via an @nt{attribute_definition_clause}, and the @nt{attribute_definition_clause} is visible.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We always want to allow calling a specified attribute. But we don't want availability to break privacy. Therefore, only attributes whose specification can be seen count. Yes, we defined the visibility of an @nt{attribute_definition_clause} (see @RefSecNum{Visibility}).]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A stream-oriented attribute for a subtype of a class-wide type @i<T>'Class is available at places where one of the following conditions is true:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T> is nonlimited;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the attribute has been specified via an @nt{attribute_definition_clause}, and the @nt{attribute_definition_clause} is visible; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the corresponding attribute of @i<T> is available, provided that if @i<T> has a partial view, the corresponding attribute is available at the end of the visible part where @i<T> is declared.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rules are stricter for class-wide attributes because (for the default implementation) we must ensure that any specific attribute that might ever be dispatched to is available. Because we require specification of attributes for extensions of limited parent types with available attributes, we can in fact know this. Otherwise, we would not be able to use default class-wide attributes with limited types, a significant limitation.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[An @nt{attribute_reference} for one of the stream-oriented attributes is illegal unless the attribute is available at the place of the @nt{attribute_reference}. Furthermore, an @nt{attribute_reference} for @i<T>'Input is illegal if @i<T> is an abstract type.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Stream attributes always exist. It is illegal to call them in some cases. Having the attributes not be defined for some limited types would seem to be a cleaner solution, but it would lead to contract model problems for limited private types.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T>'Input is available for abstract types so that @i<T>'Class'Input is available. But we certainly don't want to allow calls that could create an object of an abstract type. Remember that @i<T>'Class is never abstract, so the above legality rule doesn't apply to it. We don't have to discuss whether the attribute is specified, as it cannot be: any function returning the type would have to be abstract, and we do not allow specifying an attribute with an abstract subprogram.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[In the @nt{parameter_and_result_profile}s for the stream-oriented attributes, the subtype of the Item parameter is the base subtype of @i<T> if @i<T> is a scalar type, and the first subtype otherwise. The same rule applies to the result of the Input attribute.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[For an @nt{attribute_definition_clause} specifying one of these attributes, the subtype of the Item parameter shall be the base subtype if scalar, and the first subtype otherwise. The same rule applies to the result of the Input function.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is to simplify implementation.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The view of the type at the point of the @nt{attribute_definition_clause} determines whether the first subtype or base subtype is required. Thus, for a scalar type with a partial view (which is never scalar), whether the first subtype or the base subtype is required is determined by whether the @nt{attribute_definition_clause} occurs before or after the full definition of the scalar type.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{support external streaming} @Defn2{Term=[external streaming],Sec={type supports}} @Redundant[A type is said to @i{support external streaming} if Read and Write attributes are provided for sending values of such a type between active partitions, with Write marshalling the representation, and Read unmarshalling the representation.] A limited type supports external streaming only if it has available Read and Write attributes. A type with a part that is of an access type supports external streaming only if that access type or the type of some part that includes the access type component, has Read and Write attributes that have been specified via an @nt{attribute_definition_clause}, and that @nt{attribute_definition_clause} is visible. @Redundant[An anonymous access type does not support external streaming. ]All other types support external streaming.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A limited type with a part that is of an access type needs to satisfy both rules.]} @end{Ramification} @end{StaticSem} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the internal tag returned by Descendant_Tag to T'Class'Input identifies a type that is not library-level and whose tag has not been created, or does not exist in the partition at the time of the call, execution is erroneous.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The definition of Descendant_Tag prevents such a tag from being provided to T'Class'Input if T is a library-level type. However, this rule is needed for nested tagged types.]} @end{Ramification} @end{Erron} @begin{ImplReq} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[For every subtype @i<S> of a language-defined nonlimited specific type @i<T>, the output generated by S'Output or S'Write shall be readable by S'Input or S'Read, respectively. This rule applies across partitions if the implementation conforms to the Distributed Systems Annex.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[If Constraint_Error is raised during a call to Read because of failure of one the above checks, the implementation must ensure that the discriminants of the actual parameter of Read are not modified.]} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[The number of calls performed by the predefined implementation of the stream-oriented attributes on the Read and Write operations of the stream type is unspecified. An implementation may take advantage of this permission to perform internal buffering. However, all the calls on the Read and Write operations of the stream type needed to implement an explicit invocation of a stream-oriented attribute must take place before this invocation returns. An explicit invocation is one appearing explicitly in the program text, possibly through a generic instantiation (see @RefSecNum{Generic Instantiation}).]} @end{ImplPerm} @begin{Notes} For a definite subtype S of a type @i(T), only @i(T)'Write and @i(T)'Read are needed to pass an arbitrary value of the subtype through a stream. For an indefinite subtype S of a type @i(T), @i(T)'Output and @i(T)'Input will normally be needed, since @i(T)'Write and @i(T)'Read do not pass bounds, discriminants, or tags. User-specified attributes of S'Class are not inherited by other class-wide types descended from S. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of user-defined Write attribute:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key[procedure] My_Write( Stream : @key[@Chg{Version=[2],New=[not null ],Old=[]}access] Ada.Streams.Root_Stream_Type'Class;@Chg{Version=[2],New=[ ],Old=[]}Item@Chg{Version=[2],New=[ ],Old=[]} : My_Integer'Base); @key(for) My_Integer'Write @key(use) My_Write; @end{Example} @begin{Discussion} @leading@keepnext@i{Example of network input/output using input output attributes:} @begin{Example} @key(with) Ada.Streams; @key(use) Ada.Streams; @key(generic) @key(type) Msg_Type(<>) @key(is private); @key(package) Network_IO @key(is) --@RI[ Connect/Disconnect are used to establish the stream] @key(procedure) Connect(...); @key(procedure) Disconnect(...); --@RI[ Send/Receive transfer messages across the network] @key(procedure) Send(X : @key[in] Msg_Type); @key(function) Receive @key(return) Msg_Type; @key(private) @key(type) Network_Stream @key(is new) Root_Stream_Type @key(with) ... @key(procedure) Read(...); --@RI[ define Read/Write for Network_Stream] @key(procedure) Write(...); @key(end) Network_IO; @key(with) Ada.Streams; @key(use) Ada.Streams; @key(package body) Network_IO @key(is) Current_Stream : @key(aliased) Network_Stream; . . . @key(procedure) Connect(...) @key(is) ...; @key(procedure) Disconnect(...) @key(is) ...; @key(procedure) Send(X : @key[in] Msg_Type) @key(is) @key(begin) Msg_Type'Output(Current_Stream'Access, X); @key(end) Send; @key(function) Receive @key(return) Msg_Type @key(is) @key(begin) @key(return) Msg_Type'Input(Current_Stream'Access); @key(end) Receive; @key(end) Network_IO; @end{Example} @end{Discussion} @end{Examples} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b<Corrigendum:> Clarified how the default implementation for stream attributes is determined (eliminating conflicting language). The new wording provides that attributes for type extensions are created by composing the parent's attribute with those for the extension components if any. If a program was written assuming that the extension components were not included in the stream (as in original Ada 95), it would fail to work in the language as corrected by the Corrigendum.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Explicitly provided a permission that the number of calls to the underlying stream Read and Write operations may differ from the number determined by the canonical operations. If Ada 95 code somehow depended on the number of calls to Read or Write, it could fail with an Ada 2005 implementation. Such code is likely to be very rare; moreover, such code is really wrong, as the permission applies to Ada 95 as well.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Stream_Size attribute is new. It allows specifying the number of bits that will be streamed for a type. The @ImplAdviceTitle involving this also was changed; this is not incompatible because @ImplAdviceTitle does not have to be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01],ARef=[AI95-00195-01],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Limited types may have default constructed attributes if all of the parent and (for extensions) extension components have available attributes. Ada 2005 adds the notion of availability to patch up some holes in the Corrigendum model.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that these are operational attributes.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0045],ARef=[AI95-00132-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that End_Error is raised by the default implementation of Read and Input if the end of the stream is reached. (The result could have been abnormal without this clarification, thus this is not an inconsistency, as the programmer could not have depended on the previous behavior.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Clarified that the default implementation of S'Input does normal initialization on the object that it passes to S'Read.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Explicitly stated that what is read from a stream when a required check fails is unspecified.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Defined availability and default implementations for types with progenitors.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[Specified that Constraint_Error is raised if the internal tag retrieved for S'Class'Input is for some type not covered by S'Class or is abstract. We also explicitly state that the program is erroneous if the tag has not been created or does not currently exist in the partition. (Ada 95 did not specify what happened in these cases; it's very unlikely to have provided some useful result, so this is not considered an inconsistency.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added wording to support nested type extensions. S'Input and S'Output always raise Tag_Error for such extensions, and such extensions were not permitted in Ada 95, so this is neither an extension nor an incompatibility.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Defined @i<supports external streaming> to put all of the rules about @lquotes@;good@rquotes stream attributes in one place. This is used for distribution and for defining pragma Pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00441-01]} @ChgAdded{Version=[2],Text=[Added the @key[not null] qualifier to the first parameter of all of the stream attributes, so that the semantics doesn't change between Ada 95 and Ada 2005. This change is compatible, because mode conformance is required for subprograms specified as stream attributes, and @nt{null_exclusion}s are not considered for mode conformance.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[Improved the wording to make it clear that we don't define the default implementations of attributes that cannot be called (that is, aren't @lquotes@;available@rquotes@;). Also clarified when inheritance takes place.]} @end{DiffWord95} @LabeledClause{Freezing Rules} @begin{Intro} @redundant[This clause defines a place in the program text where each declared entity becomes @lquotes@;frozen.@rquotes@; A use of an entity, such as a reference to it by name, or (for a type) an expression of the type, causes freezing of the entity in some contexts, as described below. The @LegalityTitle forbid certain kinds of uses of an entity in the region of text where it is frozen.] @begin{Reason} This concept has two purposes: a compile-time one and a run-time one. The compile-time purpose of the freezing rules comes from the fact that the evaluation of static expressions depends on overload resolution, and overload resolution sometimes depends on the value of a static expression. (The dependence of static evaluation upon overload resolution is obvious. The dependence in the other direction is more subtle. There are three rules that require static expressions in contexts that can appear in declarative places: The expression in an @nt{attribute_designator} shall be static. In a record aggregate, variant-controlling discriminants shall be static. In an array aggregate with more than one named association, the choices shall be static. The compiler needs to know the value of these expressions in order to perform overload resolution and legality checking.) We wish to allow a compiler to evaluate static expressions when it sees them in a single pass over the @nt{compilation_unit}. The freezing rules ensure that. The run-time purpose of the freezing rules is called the @lquotes@;linear elaboration model.@rquotes@; This means that declarations are elaborated in the order in which they appear in the program text, and later elaborations can depend on the results of earlier ones. The elaboration of the declarations of certain entities requires run-time information about the implementation details of other entities. The freezing rules ensure that this information has been calculated by the time it is used. For example, suppose the initial value of a constant is the result of a function call that takes a parameter of type @i(T). In order to pass that parameter, the size of type @i(T) has to be known. If @i(T) is composite, that size might be known only at run time. (Note that in these discussions, words like @lquotes@;before@rquotes@; and @lquotes@;after@rquotes@; generally refer to places in the program text, as opposed to times at run time.) @end{Reason} @begin{Discussion} @leading@;The @lquotes@;implementation details@rquotes@; we're talking about above are: @begin{Itemize} For a tagged type, the implementations of all the primitive subprograms of the type @em that is (in the canonical implementation model), the contents of the type descriptor, which contains pointers to the code for each primitive subprogram. For a type, the full type declaration of any parts (including the type itself) that are private. For a deferred constant, the full constant declaration, which gives the constant's value. (Since this information necessarily comes after the constant's type and subtype are fully known, there's no need to worry about its type or subtype.) For any entity, representation information specified by the user via representation items. Most representation items are for types or subtypes; however, various other kinds of entities, such as objects and subprograms, are possible. @end{Itemize} Similar issues arise for incomplete types. However, we do not use freezing there; incomplete types have different, more severe, restrictions. Similar issues also arise for subprograms, protected operations, tasks and generic units. However, we do not use freezing there either; @RefSecNum{Declarative Parts} prevents problems with run-time Elaboration_Checks. @end{Discussion} @end{Intro} @begin{MetaRules} An evaluable construct should freeze anything that's needed to evaluate it. However, if the construct is not evaluated where it appears, let it cause freezing later, when it is evaluated. This is the case for @nt{default_expression}s and @nt{default_name}s. (Formal parameters, generic formal parameters, and components can have @nt{default_expression}s or @nt{default_name}s.) The compiler should be allowed to evaluate static expressions without knowledge of their context. (I.e. there should not be any special rules for static expressions that happen to occur in a context that requires a static expression.) Compilers should be allowed to evaluate static expressions (and record the results) using the run-time representation of the type. For example, suppose Color'Pos(Red) = 1, but the internal code for Red is 37. If the value of a static expression is Red, some compilers might store 1 in their symbol table, and other compilers might store 37. Either compiler design should be feasible. Compilers should never be required to detect erroneousness or exceptions at compile time (although it's very nice if they do). This implies that we should not require code-generation for a nonstatic expression of type @i(T) too early, even if we can prove that that expression will be erroneous, or will raise an exception. @Leading@;Here's an example (modified from AI83-00039, Example 3): @begin{example} @key[type] T @key[is] @key[record] ... @key[end] @key[record]; @key[function] F @key[return] T; @key[function] G(X : T) @key[return] Boolean; Y : Boolean := G(F); --@RI{ doesn't force T in Ada 83} @key[for] T @key[use] @key[record] ... @key[end] @key[record]; @end{example} @Leading@;AI83-00039 says this is legal. Of course, it raises Program_Error because the function bodies aren't elaborated yet. A one-pass compiler has to generate code for an expression of type T before it knows the representation of T. Here's a similar example, which AI83-00039 also says is legal: @begin{example} @key[package] P @key[is] @key[type] T @key[is] @key[private]; @key[function] F @key[return] T; @key[function] G(X : T) @key[return] Boolean; Y : Boolean := G(F); --@RI{ doesn't force T in Ada 83} @key[private] @key[type] T @key[is] @key[record] ... @key[end] @key[record]; @key[end] P; @end{example} If T's size were dynamic, that size would be stored in some compiler-generated dope; this dope would be initialized at the place of the full type declaration. However, the generated code for the function calls would most likely allocate a temp of the size specified by the dope @i{before} checking for Program_Error. That dope would contain uninitialized junk, resulting in disaster. To avoid doing that, the compiler would have to determine, at compile time, that the expression will raise Program_Error. This is silly. If we're going to require compilers to detect the exception at compile time, we might as well formulate the rule as a legality rule. Compilers should not be required to generate code to load the value of a variable before the address of the variable has been determined. After an entity has been frozen, no further requirements may be placed on its representation (such as by a representation item or a @nt{full_type_declaration}). @end{MetaRules} @begin{Intro} @RootDefn2{Term=[freezing], Sec=(entity)} @Defn2{Term=[freezing points], Sec=(entity)} The @i(freezing) of an entity occurs at one or more places (@i{freezing points}) in the program text where the representation for the entity has to be fully determined. Each entity is frozen from its first freezing point to the end of the program text (given the ordering of compilation units defined in @RefSecNum{The Compilation Process}). @begin{Ramification} The @lquotes@;representation@rquotes@; for a subprogram includes its calling convention and means for referencing the subprogram body, either a @lquotes@;link-name@rquotes@; or specified address. It does not include the code for the subprogram body itself, nor its address if a link-name is used to reference the body. @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014]} @Defn2{Term=[freezing], Sec=(entity caused by the end of an enclosing construct)} The end of a @nt{declarative_part}, @nt{protected_body}, or a declaration of a library package or generic library package, causes @i(freezing) of each entity declared within it, except for incomplete types. @Defn2{Term=[freezing], Sec=(entity caused by a body)} A noninstance body@Chg{New=[ other than a renames-as-body],Old=[]} causes freezing of each entity declared before it within the same @nt{declarative_part}. @begin{Discussion} This is worded carefully to handle nested packages and private types. Entities declared in a nested @nt{package_specification} will be frozen by some containing construct. An incomplete type declared in the private part of a library @nt{package_specification} can be completed in the body. @end{Discussion} @begin{Ramification} The part about bodies does not say @i{immediately} within. A renaming-as-body does not have this property. Nor does a @nt{pragma} Import. @end{Ramification} @begin{Reason} The reason bodies cause freezing is because we want @ntf{proper_bodies} and @nt{body_stub}s to be interchangeable @em one should be able to move a @nt{proper_body} to a @nt{subunit}, and vice-versa, without changing the semantics. Clearly, anything that should cause freezing should do so even if it's inside a @nt{proper_body}. However, if we make it a @nt{body_stub}, then the compiler can't see that thing that should cause freezing. So we make @nt{body_stub}s cause freezing, just in case they contain something that should cause freezing. But that means we need to do the same for @ntf{proper_bodies}. Another reason for bodies to cause freezing, there could be an added implementation burden if an entity declared in an enclosing @nt<declarative_part> is frozen within a nested body, since some compilers look at bodies after looking at the containing @nt{declarative_part}. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0046],ARef=[AI95-00106-01]} @Leading@RootDefn2{Term=[freezing], Sec=(entity caused by a construct)} A construct that (explicitly or implicitly) references an entity can cause the @i(freezing) of the entity, as defined by subsequent paragraphs. @PDefn2{Term=[freezing], Sec=(by a constituent of a construct)} At the place where a construct causes freezing, each @nt<name>, @Chg{New=[@nt<expression>, @nt<implicit_dereference>], Old=[expression]}@Redundant[, or @nt{range}] within the construct causes freezing: @begin{Ramification} Note that in the sense of this paragraph, a @nt{subtype_mark} @lquotes@;references@rquotes@; the denoted subtype, but not the type. @end{Ramification} @begin{Itemize} @Leading@PDefn2{Term=[freezing], Sec=(generic_instantiation)} The occurrence of a @nt{generic_instantiation} causes freezing; also, if a parameter of the instantiation is defaulted, the @nt{default_expression} or @nt{default_name} for that parameter causes freezing. @Leading@PDefn2{Term=[freezing], Sec=(object_declaration)} The occurrence of an @nt<object_declaration> that has no corresponding completion causes freezing. @begin{Ramification} Note that this does not include a @nt{formal_object_declaration}. @end{Ramification} @PDefn2{Term=[freezing], Sec=(subtype caused by a record extension)} The declaration of a record extension causes freezing of the parent subtype. @begin{Ramification} This combined with another rule specifying that primitive subprogram declarations shall precede freezing ensures that all descendants of a tagged type implement all of its dispatching operations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The declaration of a private extension does not cause freezing. The freezing is deferred until the full type declaration, which will necessarily be for a record extension@Chg{Version=[2],New=[, task, or protected type (the latter only for a limited private extension derived from an interface)], Old=[]}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The declaration of a record extension, interface type, task unit, or protected unit causes freezing of any progenitor types specified in the declaration.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This rule has the same purpose as the one above: ensuring that all descendants of an interface tagged type implement all of its dispatching operations. As with the previous rule, a private extension does not freeze its progenitors; the full type declaration (which must have the same progenitors) will do that.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[An interface type can be a parent as well as a progenitor; these rules are similar so that the location of an interface in a record extension does not have an effect on the freezing of the interface type.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0046],ARef=[AI95-00106-01]} @PDefn2{Term=[freezing], Sec=(by an expression)} A static expression causes freezing where it occurs. @Chg{New=[@PDefn2{Term=[freezing], Sec=(by an object name)} An object name or],Old=[A]} nonstatic expression causes freezing where it occurs, unless the @Chg{New=[name or ],Old=[]}expression is part of a @nt<default_expression>, a @nt<default_name>, or a per-object expression of a component's @nt<constraint>, in which case, the freezing occurs later as part of another construct. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=[freezing], Sec=(by an implicit call)} An implicit call freezes the same entities that would be frozen by an explicit call. This is true even if the implicit call is removed via implementation permissions.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=[freezing], Sec=(subtype caused by an implicit conversion)} If an expression is implicitly converted to a type or subtype @i(T), then at the place where the expression causes freezing, @i(T) is frozen.]} @Leading@;The following rules define which entities are frozen at the place where a construct causes freezing: @begin{Itemize} @Leading@PDefn2{Term=[freezing], Sec=(type caused by an expression)} At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used as a @nt{discrete_choice} of the @nt{array_@!aggregate} of an @nt{enumeration_@!representation_@!clause}. @begin{Reason} We considered making enumeration literals never cause freezing, which would be more upward compatible, but examples like the variant record aggregate (Discrim => Red, ...) caused us to change our mind. Furthermore, an enumeration literal is a static expression, so the implementation should be allowed to represent it using its representation. @end{Reason} @begin{Ramification} @Leading@;The following pathological example was legal in Ada 83, but is illegal in Ada 95: @begin{Example} @key[package] P1 @key[is] @key[type] T @key[is] @key[private]; @key[package] P2 @key[is] @key[type] Composite(D : Boolean) @key[is] @key[record] @key[case] D @key[is] @key[when] False => Cf : Integer; @key[when] True => Ct : T; @key[end] @key[case]; @key[end] @key[record]; @key[end] P2; X : Boolean := P2."="( (False,1), (False,1) ); @key[private] @key[type] T @key[is] @key[array](1..Func_Call) @key[of] Integer; @key[end]; @end{Example} In Ada 95, the declaration of X freezes Composite (because it contains an expression of that type), which in turn freezes T (even though Ct does not exist in this particular case). But type T is not completely defined at that point, violating the rule that a type shall be completely defined before it is frozen. In Ada 83, on the other hand, there is no occurrence of the name T, hence no forcing occurrence of T. @end{Ramification} @Leading@PDefn2{Term=[freezing], Sec=(entity caused by a name)} At the place where a @nt<name> causes freezing, the entity denoted by the @nt<name> is frozen, unless the @nt<name> is a @nt<prefix> of an expanded name; @PDefn2{Term=[freezing], Sec=(nominal subtype caused by a name)} at the place where an object @nt{name} causes freezing, the nominal subtype associated with the @nt<name> is frozen. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This only matters in the presence of deferred constants or access types; an @nt{object_declaration} other than a @Chg{Version=[2],New=[deferred constant declaration],Old=[@ntf{deferred_constant_declaration}]} causes freezing of the nominal subtype, plus all component junk. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgDeleted{Version=[1],Text=[@nt{Implicit_dereference}s are covered by @nt{expression}.]} @Comment{This statement is just plain wrong.} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[@PDefn2{Term=[freezing], Sec=(subtype caused by an implicit dereference)} At the place where an @nt{implicit_dereference} causes freezing, the nominal subtype associated with the @nt{implicit_dereference} is frozen.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule ensures that X.D freezes the same entities that X.@key{all}.D does. Note that an @nt{implicit_dereference} is neither a @nt{name} nor @nt{expression} by itself, so it isn't covered by other rules.]} @end{Discussion} @Leading@Redundant[@PDefn2{Term=[freezing], Sec=(type caused by a range)} At the place where a @nt{range} causes freezing, the type of the @nt<range> is frozen.] @begin{TheProof} This is consequence of the facts that expressions freeze their type, and the Range attribute is defined to be equivalent to a pair of expressions separated by @lquotes@;..@rquotes@;.} @end{TheProof} @Leading@PDefn2{Term=[freezing], Sec=(designated subtype caused by an allocator)} At the place where an @nt<allocator> causes freezing, the designated subtype of its type is frozen. If the type of the @nt<allocator> is a derived type, then all ancestor types are also frozen. @begin{Ramification} @nt{Allocator}s also freeze the named subtype, as a consequence of other rules. @Leading@;The ancestor types are frozen to prevent things like this: @begin{Example} @key[type] Pool_Ptr @key[is] @key[access] System.Storage_Pools.Root_Storage_Pool'Class; @key[function] F @key[return] Pool_Ptr; @key[package] P @key[is] @key[type] A1 @key[is] @key[access] Boolean; @key[type] A2 @key[is] @key[new] A1; @key[type] A3 @key[is] @key[new] A2; X : A3 := @key[new] Boolean; --@RI{ Don't know what pool yet!} @key[for] A1'Storage_Pool @key[use] F.all; @key[end] P; @end{Example} This is necessary because derived access types share their parent's pool. @end{Ramification} @Leading@PDefn2{Term=[freezing], Sec=(subtypes of the profile of a callable entity)} At the place where a callable entity is frozen, each subtype of its profile is frozen. If the callable entity is a member of an entry family, the index subtype of the family is frozen. @PDefn2{Term=[freezing], Sec=(function call)} At the place where a function call causes freezing, if a parameter of the call is defaulted, the @nt{default_@!expression} for that parameter causes freezing. @begin{Discussion} We don't worry about freezing for procedure calls or entry calls, since a body freezes everything that precedes it, and the end of a declarative part freezes everything in the declarative part. @end{Discussion} @Leading@PDefn2{Term=[freezing], Sec=[type caused by the freezing of a subtype]} At the place where a subtype is frozen, its type is frozen. @PDefn2{Term=[freezing], Sec=(constituents of a full type definition)} @PDefn2{Term=[freezing], Sec=(first subtype caused by the freezing of the type)} At the place where a type is frozen, any expressions or @nt<name>s within the full type definition cause freezing; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. @PDefn2{Term=[freezing], Sec=(class-wide type caused by the freezing of the specific type)} @PDefn2{Term=[freezing], Sec=(specific type caused by the freezing of the class-wide type)} For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well. @begin{Ramification} Freezing a type needs to freeze its first subtype in order to preserve the property that the subtype-specific aspects of statically matching subtypes are the same. Freezing an access type does not freeze its designated subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00341-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[At the place where a specific tagged type is frozen, the primitive subprograms of the type are frozen.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have a language design principle that all of the details of a specific tagged type are known at its freezing point. But that is only true if the primitive subprograms are frozen at this point as well. Late changes of Import and address clauses violate the principle.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule means that no implicit call to Initialize or Adjust can freeze a subprogram (the type and thus subprograms would have been frozen at worst at the same point).]} @end{ImplNote} @end{Itemize} @end{Intro} @begin{Legality} @Comment{"Leading" below is to get the last paragraph onto the page with everything else.} @Leading@Redundant[The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen (see @RefSecNum{Dispatching Operations of Tagged Types}).] @begin{Reason} This rule is needed because (1) we don't want people dispatching to things that haven't been declared yet, and (2) we want to allow tagged type descriptors to be static (allocated statically, and initialized to link-time-known symbols). Suppose T2 inherits primitive P from T1, and then overrides P. Suppose P is called @i{before} the declaration of the overriding P. What should it dispatch to? If the answer is the new P, we've violated the first principle above. If the answer is the old P, we've violated the second principle. (A call to the new one necessarily raises Program_Error, but that's beside the point.) Note that a call upon a dispatching operation of type @i(T) will freeze @i(T). We considered applying this rule to all derived types, for uniformity. However, that would be upward incompatible, so we rejected the idea. As in Ada 83, for an untagged type, the above call upon P will call the old P (which is arguably confusing). @end{Reason} @Leading@Redundant[A type shall be completely defined before it is frozen (see @RefSecNum{Completions of Declarations} and @RefSecNum{Private Types and Private Extensions}).] @Leading@Redundant[The completion of a deferred constant declaration shall occur before the constant is frozen (see @RefSecNum{Deferred Constants}).] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[The above @LegalityTitle are stated @lquotes@;officially@rquotes@; in the referenced clauses.]} @end{TheProof} @Leading@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[An operational or],Old=[A]} representation item that directly specifies an aspect of an entity shall appear before the entity is frozen (see @RefSecNum{Operational and Representation Items}). @ChgNote{A last minute change (requested by WG9) moved this rule to 13.1(9). However, the rule there only covers types and subtypes. So this rule is not redundant, and I removed the @Redundant for it. I don't have a way to mark that as a change, so it is just gone. RLB-29-08-00} @begin{Discussion} @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} From RM83-13.1(7). The wording here forbids freezing within the @Chg{New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]} itself, which was not true of the Ada 83 wording. The wording of this rule is carefully written to work properly for type-related representation items. For example, an @nt{enumeration_@!representation_@!clause} is illegal after the type is frozen, even though the @ntf{_clause} refers to the first subtype. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[The above @LegalityName is stated for types and subtypes in @RefSecNum{Operational and Representation Items}, but the rule here covers all other entities as well.]} @end{Discussion} @begin{TheProof} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[The above @LegalityTitle are stated @lquotes@;officially@rquotes@; in the referenced clauses]}. @end{TheProof} @begin{Discussion} @Leading@;Here's an example that illustrates when freezing occurs in the presence of defaults: @begin{Example} @key[type] T @key[is] ...; @key[function] F @key[return] T; @key[type] R @key[is] @key[record] C : T := F; D : Boolean := F = F; @key[end] @key[record]; X : R; @end{Example} Since the elaboration of R's declaration does not allocate component C, there is no need to freeze C's subtype at that place. Similarly, since the elaboration of R does not evaluate the @nt{default_expression} @lquotes@;F = F@rquotes@;, there is no need to freeze the types involved at that point. However, the declaration of X @i{does} need to freeze these things. Note that even if component C did not exist, the elaboration of the declaration of X would still need information about T @em even though D is not of type T, its @nt{default_expression} requires that information. @end{Discussion} @begin{Ramification} Although we define freezing in terms of the program text as a whole (i.e. after applying the rules of Section 10), the freezing rules actually have no effect beyond compilation unit boundaries. @end{Ramification} @begin{Reason} That is important, because Section 10 allows some implementation definedness in the order of things, and we don't want the freezing rules to be implementation defined. @end{Reason} @begin{Ramification} These rules also have no effect in @nt{statement}s @em they only apply within a single @nt{declarative_part}, @nt{package_specification}, @nt{task_definition}, @nt{protected_definition}, or @nt{protected_body}. @end{Ramification} @begin{ImplNote} An implementation may choose to generate code for @nt{default_expression}s and @nt{default_name}s in line at the place of use. @Defn{thunk} Alternatively, an implementation may choose to generate thunks (subprograms implicitly generated by the compiler) for evaluation of defaults. Thunk generation cannot, in general, be done at the place of the declaration that includes the default. Instead, they can be generated at the first freezing point of the type(s) involved. (It is impossible to write a purely one-pass Ada compiler, for various reasons. This is one of them @em the compiler needs to store a representation of defaults in its symbol table, and then walk that representation later, no earlier than the first freezing point.) In implementation terms, the linear elaboration model can be thought of as preventing uninitialized dope. For example, the implementation might generate dope to contain the size of a private type. This dope is initialized at the place where the type becomes completely defined. It cannot be initialized earlier, because of the order-of-elaboration rules. The freezing rules prevent elaboration of earlier declarations from accessing the size dope for a private type before it is initialized. @RefSecNum{Pragmas} overrides the freezing rules in the case of unrecognized @nt{pragma}s. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[An @nt{aspect_clause}],Old=[A @nt{representation_clause}]} for an entity should most certainly @i{not} be a freezing point for the entity. @end{ImplNote} @end{Legality} @begin{RunTime} @ChgNote{This is the last normative paragraph in the clause} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[The tag (see @RefSecNum{Tagged Types and Type Extensions}) of a tagged type T is created at the point where T is frozen.@PDefn2{Term=[creation],Sec=[of a tag]}]} @end{RunTime} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} RM83 defines a forcing occurrence of a type as follows: @lquotes@;A forcing occurrence is any occurrence [of the name of the type, subtypes of the type, or types or subtypes with subcomponents of the type] other than in a type or subtype declaration, a subprogram specification, an entry declaration, a deferred constant declaration, a @nt{pragma}, or a @ntf{representation_clause} for the type itself. In any case, an occurrence within an expression is always forcing.@rquotes@; @Leading@;It seems like the wording allows things like this: @begin{Example} @key[type] A @key[is] @key[array](Integer @key[range] 1..10) @key[of] Boolean; @key[subtype] S @key[is] Integer @key[range] A'Range; --@RI{ not forcing for A} @end{Example} Occurrences within @nt{pragma}s can cause freezing in Ada 95. (Since such @nt{pragma}s are ignored in Ada 83, this will probably fix more bugs than it causes.) @end{Incompatible83} @begin{Extend83} @Leading@;@Defn{extensions to Ada 83} In Ada 95, @nt{generic_formal_parameter_declaration}s do not normally freeze the entities from which they are defined. For example: @begin{example} @key[package] Outer @key[is] @key[type] T @key[is] @key[tagged] @key[limited] @key[private]; @key[generic] @key[type] T2 @key[is] @key[new] T @key[with] @key[private]; --@RI{ Does not freeze T} --@RI{ in Ada 95.} @key[package] Inner @key[is] ... @key[end] Inner; @key[private] @key[type] T @key[is] ...; @key[end] Outer; @end{example} This is important for the usability of generics. The above example uses the Ada 95 feature of formal derived types. Examples using the kinds of formal parameters already allowed in Ada 83 are well known. See, for example, comments 83-00627 and 83-00688. The extensive use expected for formal derived types makes this issue even more compelling than described by those comments. Unfortunately, we are unable to solve the problem that @nt{explicit_generic_actual_parameter}s cause freezing, even though a package equivalent to the instance would not cause freezing. This is primarily because such an equivalent package would have its body in the body of the containing program unit, whereas an instance has its body right there. @end{Extend83} @begin{DiffWord83} The concept of freezing is based on Ada 83's concept of @lquotes@;forcing occurrences.@rquotes@; The first freezing point of an entity corresponds roughly to the place of the first forcing occurrence, in Ada 83 terms. The reason for changing the terminology is that the new rules do not refer to any particular @lquotes@;occurrence@rquotes@; of a name of an entity. Instead, we refer to @lquotes@;uses@rquotes@; of an entity, which are sometimes implicit. In Ada 83, forcing occurrences were used only in rules about @ntf{representation_clause}s. We have expanded the concept to cover private types, because the rules stated in RM83-7.4.1(4) are almost identical to the forcing occurrence rules. @Leading@;The Ada 83 rules are changed in Ada 95 for the following reasons: @begin{Itemize} The Ada 83 rules do not work right for subtype-specific aspects. In an earlier version of Ada 9X, we considered allowing representation items to apply to subtypes other than the first subtype. This was part of the reason for changing the Ada 83 rules. However, now that we have dropped that functionality, we still need the rules to be different from the Ada 83 rules. The Ada 83 rules do not achieve the intended effect. In Ada 83, either with or without the AIs, it is possible to force the compiler to generate code that references uninitialized dope, or force it to detect erroneousness and exception raising at compile time. It was a goal of Ada 83 to avoid uninitialized access values. However, in the case of deferred constants, this goal was not achieved. The Ada 83 rules are not only too weak @em they are also too strong. They allow loopholes (as described above), but they also prevent certain kinds of @nt{default_expression}s that are harmless, and certain kinds of @nt{generic_declaration}s that are both harmless and very useful. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Ada 83 had a case where a @Chg{Version=[2],New=[@nt{aspect_clause}], Old=[@nt{representation_clause}]} had a strong effect on the semantics of the program @em 'Small. This caused certain semantic anomalies. There are more cases in Ada 95, because the @Chg{Version=[2],New=[@nt{attribute_definition_clause}], Old=[@ntf{attribute_representation_clause}]} has been generalized. @end{Itemize} @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0046],ARef=[AI95-00106-01],ARef=[AI95-00341-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b<Corrigendum:> Various freezing rules were added to fix holes in the rules. Most importantly, implicit calls are now freezing, which make some representation clauses illegal in Ada 2005 that were legal (but dubious) in Ada 95. @b[Amendment Correction:] Similarly, the primitive subprograms of a specific tagged type are frozen when the type is frozen, preventing dubious convention changes (and address clauses) after the freezing point. In both cases, the code is dubious and the workaround is easy.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that both operational and representation attributes must be specified before the type is frozen.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording that declaring a specific descendant of an interface type freezes the interface type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[Added wording that defines when a tag is created for a type (at the freezing point of the type). This is used to specify checking for uncreated tags (see @RefSecNum{Tagged Types and Type Extensions}).]} @end{DiffWord95} ������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/aarm.msm�������������������������������������������������������������0000755�0001752�0001001�00000013212�12273462240�017056� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the AARM} @Comment{Global properties} @ShowIndexEntries @Comment{To match the Ada 95 AARM} @ShowAnnotations @HideISO @NumberParagraphs @LinkNonTerminals @Title{Version=[0],Text=[Annotated Ada Reference Manual]}@Comment{Same title for all versions} @FilePrefix{AA} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @RTFHeaderPrefix{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @RTFHeaderPrefix{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]} @RTFPageSize{Letter} @RTFFonts{Serif=[Times],SansSerif=[Arial]} @Comment{HTML properties} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]}@Comment{Was "4Comp" for the Consolidated AARM} @HTMLNavBar{RefName=[AA-STDS.html],SrchName=[AA-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><B><SPAN Style="font-size:200%; color: rgb(0,51,153)">Annotated</SPAN><SPAN Style="font-size:200%; color: rgb(0,0,102)"> Ada Reference Manual</SPAN></B> — <A HREF="AA-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="font-size: 125%">Sponsored by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO requires skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO requires skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/ansi_cover.mss�������������������������������������������������������0000755�0001752�0001001�00000005020�12273462240�020272� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(ansicover, Root="ada.mss") @Define(I2Title, Copy TitlePage, Sink 8.5in, Font HeadingFont) @Define(I2TBox, Copy TitleBox, Fixed 2.5inches) @Define(I2Credit, Copy ResearchCredit, Fixed 9inches) @Define(I2CRNotice, Copy CopyrightNotice, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @Define(I2CR, Copy Copyright, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @comment{$Source: e:\\cvsroot/ARM/Source/ansi_cover.mss,v $} @comment{$Revision: 1.12 $ $Date: 2000/05/27 04:44:03 $} @begin(I2Title) @begin{FlushRight, Fixed 0.75inch} @Case{DocumentNickname, RM9X= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], ISO= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], else= [ISO/IEC JTC1/SC22 WG9 N 193]} @end{FlushRight} @begin(I2TBox) @String{OfficialPrefix="Proposed ANSI/ISO Standard" for Information Technology Programming Languages"} @Case{DocumentNickname, RM9X=[@Heading{@Value{OfficialPrefix}}], ISO=[@Heading{@Value{OfficialPrefix}}], else=[@Value{OfficialPrefix}]} @MajorHeading{Programming Language Ada} @Comment{We got the above mouthful in a mail message from Bob Mathis on 8 Sep 1993.} @Heading{Language and Standard Libraries} @Case{DocumentNickname, RM9X=[@i{Draft}], ISO=[@i{Draft}], AARM=[@i{Annotated Draft}], Syntax9X=[@i{Syntax Only Draft}]} Version @Value(Version) @Value(Date) @Value(IRno) @end(I2TBox) Ada 9X Mapping/Revision Team Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 (617) 661-1840 @end(I2Title) @PageHeading() @PageFooting() @comment{case statement: If draft/=2 then it's a public document and use the reprinting permitted copyright. Otherwise use the restricted copyright.} @Case{Draft, 2=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) @end(Center) FOR OFFICIAL USE ONLY in performance of Contract F08635-90-C-0066. This report has been produced under the sponsorship of the Ada 9X Project Office under contract F08635-90-C-0066.", else=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) Reprinting permitted if accompanied by this statement. This work is sponsored by the Ada 9X Project Office under contract F08635-90-C-0066. @end(Center) "}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/ansi_title.mss�������������������������������������������������������0000755�0001752�0001001�00000005036�12273462240�020304� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(ansititle, Root="ada.mss") @Define(I2Title, Copy TitlePage, Sink 8.5in, Font HeadingFont) @Define(I2TBox, Copy TitleBox, Fixed 2.5inches) @Define(I2Credit, Copy ResearchCredit, Fixed 9inches) @Define(I2CRNotice, Copy CopyrightNotice, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @Define(I2CR, Copy Copyright, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @comment{$Source: e:\\cvsroot/ARM/Source/ansi_title.mss,v $} @comment{$Revision: 1.12 $ $Date: 2000/05/27 04:44:03 $} @begin(I2Title) @begin{FlushRight, Fixed 0.75inch} @Case{DocumentNickname, RM9X= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], ISO= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], else= [ISO/IEC JTC1/SC22 WG9 N 193]} @end{FlushRight} @begin(I2TBox) @String{OfficialPrefix="@i(proposed) American National Standard for Information Technology - Programming Languages"} @Case{DocumentNickname, RM9X=[@Heading{@Value{OfficialPrefix}}], ISO=[@Heading{@Value{OfficialPrefix}}], else=[@Value{OfficialPrefix}]} @MajorHeading{Programming Language Ada} @Comment{We got the above mouthful in a mail message from Bob Mathis on 8 Sep 1993.} @Heading{Language and Standard Libraries} @Case{DocumentNickname, RM9X=[@i{Draft}], ISO=[@i{Draft}], AARM=[@i{Annotated Draft}], Syntax9X=[@i{Syntax Only Draft}]} Version @Value(Version) @Value(Date) @Value(IRno) @end(I2TBox) Ada 9X Mapping/Revision Team Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 (617) 661-1840 @end(I2Title) @PageHeading() @PageFooting() @comment{case statement: If draft/=2 then it's a public document and use the reprinting permitted copyright. Otherwise use the restricted copyright.} @Case{Draft, 2=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) @end(Center) FOR OFFICIAL USE ONLY in performance of Contract F08635-90-C-0066. This report has been produced under the sponsorship of the Ada 9X Project Office under contract F08635-90-C-0066.", else=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) Reprinting permitted if accompanied by this statement. This work is sponsored by the Ada 9X Project Office under contract F08635-90-C-0066. @end(Center) "}��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/attribs.mss����������������������������������������������������������0000755�0001752�0001001�00000000550�12273462240�017615� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(attribs, Root="ada.mss") @Comment{$Date: 2000/08/08 22:56:19 $} @LabeledInformativeAnnex{Language-Defined Attributes} @comment{$Source: e:\\cvsroot/ARM/Source/attribs.mss,v $} @comment{$Revision: 1.14 $} @begin{Intro} @Defn{attribute}This annex summarizes the definitions given elsewhere of the language-defined attributes. @AttributeList @end{Intro}��������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/ds.mss���������������������������������������������������������������0000755�0001752�0001001�00000237367�12273462240�016575� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/ds.mss,v $ } @comment{ $Revision: 1.47 $ $Date: 2006/10/14 06:05:20 $ $Author: Randy $ } @Part(dist, Root="ada.mss") @Comment{$Date: 2006/10/14 06:05:20 $} @LabeledNormativeAnnex{Distributed Systems} @begin{Intro} @redundant[This Annex defines facilities for supporting the implementation of distributed systems using multiple partitions working cooperatively as part of a single Ada program.] @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{LinkTime} @Defn{processing node} @Defn{storage node} @Defn{distributed system} A @i{distributed system} is an interconnection of one or more @i{processing nodes} (a system resource that has both computational and storage capabilities), and zero or more @i{storage nodes} (a system resource that has only storage capabilities, with the storage addressable by one or more processing nodes). @Defn{distributed program} A @i{distributed program} comprises one or more partitions that execute independently (except when they communicate) in a distributed system. @Defn2{Term=[configuration], Sec=(of the partitions of a program)} The process of mapping the partitions of a program to the nodes in a distributed system is called @i{configuring the partitions of the program}. @end{LinkTime} @begin{ImplReq} The implementation shall provide means for explicitly assigning library units to a partition and for the configuring and execution of a program consisting of multiple partitions on a distributed system; the means are implementation defined. @ImplDef{The means for creating and executing distributed programs.} @end{ImplReq} @begin{ImplPerm} An implementation may require that the set of processing nodes of a distributed system be homogeneous. @end{ImplPerm} @begin{Notes} The partitions comprising a program may be executed on differently configured distributed systems or on a non-distributed system without requiring recompilation. A distributed program may be partitioned differently from the same set of library units without recompilation. The resulting execution is semantically equivalent. A distributed program retains the same type safety as the equivalent single partition program. @end{Notes} @LabeledClause{Partitions} @begin{Intro} @redundant[The partitions of a distributed program are classified as either active or passive.] @end{Intro} @begin{LinkTime} @Defn{active partition} @Defn{passive partition} An @i{active partition} is a partition as defined in @RefSecNum{Program Execution}. A @i{passive partition} is a partition that has no thread of control of its own, whose library units are all preelaborated, and whose data and subprograms are accessible to one or more active partitions. @begin{Discussion} In most situations, a passive partition does not execute, and does not have a @lquotes@;real@rquotes@; environment task. Any execution involved in its elaboration and initialization occurs before it comes into existence in a distributed program (like most preelaborated entities). Likewise, there is no concrete meaning to passive partition termination. @end{Discussion} A passive partition shall include only @nt{library_item}s that either are declared pure or are shared passive (see @RefSecNum{Elaboration Control} and @RefSecNum{Shared Passive Library Units}). An active partition shall be configured on a processing node. A passive partition shall be configured either on a storage node or on a processing node. The configuration of the partitions of a program onto a distributed system shall be consistent with the possibility for data references or calls between the partitions implied by their semantic dependences. @Defn{remote access} Any reference to data or call of a subprogram across partitions is called a @i{remote access}. @begin{Discussion} For example, an active partition that includes a unit with a semantic dependence on the declaration of another RCI package of some other active partition has to be connected to that other partition by some sort of a message passing mechanism. A passive partition that is accessible to an active partition should have its storage addressable to the processor(s) of the active partition. The processor(s) should be able to read and write from/to that storage, as well as to perform @lquotes@;read-modify-write@rquotes@; operations (in order to support entry-less protected objects). @end{Discussion} @end{LinkTime} @begin{RunTime} @Defn2{Term=[elaboration], Sec=(partition)} A @nt{library_item} is elaborated as part of the elaboration of each partition that includes it. If a normal library unit (see @RefSecNum{Categorization of Library Units}) has state, then a separate copy of the state exists in each active partition that elaborates it. @Redundant[The state evolves independently in each such partition.] @begin{Ramification} Normal library units cannot be included in passive partitions. @end{Ramification} @Defn2{Term=[termination], Sec=(of a partition)} @Defn2{Term=[abort], Sec=(of a partition)} @Defn{inaccessible partition} @Defn{accessible partition} @Redundant[An active partition @i{terminates} when its environment task terminates.] A partition becomes @i{inaccessible} if it terminates or if it is @i{aborted}. An active partition is aborted when its environment task is aborted. In addition, if a partition fails during its elaboration, it becomes inaccessible to other partitions. Other implementation-defined events can also result in a partition becoming inaccessible. @ImplDef{Any events that can result in a partition becoming inaccessible.} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} D that denotes a library-level declaration, excepting a declaration of or within a declared-pure library unit]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<D>, AttrName=<Partition_Id>, Text=[Denotes a value of the type @i{universal_integer} that identifies the partition in which D was elaborated. If D denotes the declaration of a remote call interface library unit (see @RefSecNum{Remote Call Interface Library Units}) the given partition is the one where the body of D was elaborated.]} @end{Description} @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for there to be cyclic elaboration dependences between the active partitions of a single distributed program. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible effects@Chg{Version=[2],New=[, in each of the partitions involved,],Old=[]} are deadlock during elaboration, or the raising of @Chg{Version=[2],New=[Communication_Error or ],Old=[]}Program_Error@Chg{Version=[2], New=[],Old=[ in one or all of the active partitions involved]}. @end{Bounded} @begin{ImplPerm} An implementation may allow multiple active or passive partitions to be configured on a single processing node, and multiple passive partitions to be configured on a single storage node. In these cases, the scheduling policies, treatment of priorities, and management of shared resources between these partitions are implementation defined. @ImplDef{The scheduling policies, treatment of priorities, and management of shared resources between partitions in certain cases.} An implementation may allow separate copies of an active partition to be configured on different processing nodes, and to provide appropriate interactions between the copies to present a consistent state of the partition to other active partitions. @begin{Ramification} The language does not specify the nature of these interactions, nor the actual level of consistency preserved. @end{Ramification} In an implementation, the partitions of a distributed program need not be loaded and elaborated all at the same time; they may be loaded and elaborated one at a time over an extended period of time. An implementation may provide facilities to abort and reload a partition during the execution of a distributed program. An implementation may allow the state of some of the partitions of a distributed program to persist while other partitions of the program terminate and are later reinvoked. @end{ImplPerm} @begin{Notes} Library units are grouped into partitions after compile time, but before run time. At compile time, only the relevant library unit properties are identified using categorization pragmas. The value returned by the Partition_Id attribute can be used as a parameter to implementation-provided subprograms in order to query information about the partition. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00226-01]} @ChgAdded{Version=[2],Text=[Corrected wording so that a partition that has an elaboration problem will either deadlock or raise an exception. While an Ada 95 implementation could allow some partitions to continue to execute, they could be accessing unelaborated data, which is very bad (and erroneous in a practical sense). Therefore, this isn't listed as an inconsistency.]} @end{DiffWord95} @LabeledClause{Categorization of Library Units} @begin{Intro} @redundant[Library units can be categorized according to the role they play in a distributed program. Certain restrictions are associated with each category to ensure that the semantics of a distributed program remain close to the semantics for a nondistributed program.] @RootDefn{categorization pragma} @RootDefn{pragma, categorization} @PDefn2{Term=[library unit pragma], Sec=(categorization pragmas)} @PDefn2{Term=[pragma, library unit], Sec=(categorization pragmas)} @Defn{categorized library unit} A @i{categorization pragma} is a library unit pragma (see @RefSecNum{Pragmas and Program Units}) that restricts the declarations, child units, or semantic dependences of the library unit to which it applies. A @i{categorized library unit} is a library unit to which a categorization pragma applies. The pragmas Shared_Passive, Remote_Types, and Remote_Call_Interface are categorization pragmas. In addition, for the purposes of this Annex, the pragma Pure (see @RefSecNum{Elaboration Control}) is considered a categorization pragma. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @Defn{shared passive library unit} A library package or generic library package is called a @i{shared passive} library unit if a Shared_Passive pragma applies to it. @Defn{remote types library unit} A library package or generic library package is called a @i{remote types} library unit if a Remote_Types pragma applies to it. @Defn{remote call interface} A library @Chg{New=[unit],Old=[package or generic library package]} is called a @i{remote call interface} if a Remote_Call_Interface pragma applies to it. @Defn{normal library unit} A @i{normal library unit} is one to which no categorization pragma applies. @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[1],Text=[A library subprogram can be a remote call interface, but it cannot be a remote types or shared passive library unit.]} @end{Ramification} @redundant[The various categories of library units and the associated restrictions are described in this clause and its subclauses. The categories are related hierarchically in that the library units of one category can depend semantically only on library units of that category or an earlier one, except that the body of a remote types or remote call interface library unit is unrestricted. @Leading@;The overall hierarchy (including declared pure) is as follows: @begin{Description} Declared Pure @\Can depend only on other declared pure library units; Shared Passive @\Can depend only on other shared passive or declared pure library units; Remote Types @\The declaration of the library unit can depend only on other remote types library units, or one of the above; the body of the library unit is unrestricted; Remote Call Interface @\The declaration of the library unit can depend only on other remote call interfaces, or one of the above; the body of the library unit is unrestricted; Normal @\Unrestricted. @end{Description} Declared pure and shared passive library units are preelaborated. The declaration of a remote types or remote call interface library unit is required to be preelaborable. ] @end{Intro} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0079],ARef=[AI95-00208-01]} @ChgDeleted{Version=[1],Text=[For a given library-level type declared in a preelaborated library unit or in the declaration of a remote types or remote call interface library unit, the implementation shall choose the same representation for the type upon each elaboration of the type's declaration for different partitions of the same program.]} @end{ImplReq} @begin{ImplPerm} Implementations are allowed to define other categorization pragmas. @end{ImplPerm} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a library subprogram can be a remote call interface unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0079],ARef=[AI95-00208-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Removed the requirement that types be represented the same in all partitions, because it prevents the definition of heterogeneous distributed systems and goes much further than required.]} @end{DiffWord95} @LabeledSubClause{Shared Passive Library Units} @begin{Intro} @redundant[A shared passive library unit is used for managing global data shared between active partitions. The restrictions on shared passive library units prevent the data or tasks of one active partition from being accessible to another active partition through references implicit in objects declared in the shared passive library unit.] @end{Intro} @begin{MetaRules} The restrictions governing a shared passive library unit are designed to ensure that objects and subprograms declared in the package can be used safely from multiple active partitions, even though the active partitions live in different address spaces, and have separate run-time systems. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Shared_Passive)} @PDefn2{Term=[pragma, categorization], Sec=(Shared_Passive)} The form of a @nt{pragma} Shared_Passive is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Shared_Passive)[(@SynI{library_unit_}@Syn2{name})];' @end{Syntax} @begin{Legality} @Leading@Defn{shared passive library unit} A @i{shared passive library unit} is a library unit to which a Shared_Passive pragma applies. The following restrictions apply to such a library unit: @begin{itemize} @Redundant[it shall be preelaborable (see @RefSecNum{Elaboration Control});] @begin{Ramification} It cannot contain library-level declarations of protected objects with entries, nor of task objects. Task objects are disallowed because passive partitions don't have any threads of control of their own, nor any run-time system of their own. Protected objects with entries are disallowed because an entry queue contains references to calling tasks, and that would require in effect a pointer from a passive partition back to a task in some active partition. @end{Ramification} it shall depend semantically only upon declared pure or shared passive library units; @begin{reason} Shared passive packages cannot depend semantically upon remote types packages because the values of an access type declared in a remote types package refer to the local heap of the active partition including the remote types package. @end{reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0080],ARef=[AI95-00003-01]} it shall not contain a library-level declaration of an access type that designates a class-wide type, task type, or protected type with @nt{entry_declaration}s@Chg{New=[], Old=[; if the shared passive library unit is generic, it shall not contain a declaration for such an access type unless the declaration is nested within a body other than a @nt<package_body>]}. @begin{Reason} These kinds of access types are disallowed because the object designated by an access value of such a type could contain an implicit reference back to the active partition on whose behalf the designated object was created. @end{Reason} @end{itemize} @PDefn2{Term=[accessibility], Sec=(from shared passive library units)} @Defn{notwithstanding} Notwithstanding the definition of accessibility given in @RefSecNum(Operations of Access Types), the declaration of a library unit P1 is not accessible from within the declarative region of a shared passive library unit P2, unless the shared passive library unit P2 depends semantically on P1. @begin{Discussion} We considered a more complex rule, but dropped it. This is the simplest rule that recognizes that a shared passive package may outlive some other library package, unless it depends semantically on that package. In a nondistributed program, all library packages are presumed to have the same lifetime. Implementations may define additional pragmas that force two library packages to be in the same partition, or to have the same lifetime, which would allow this rule to be relaxed in the presence of such pragmas. @end{Discussion} @end{Legality} @begin{StaticSem} @PDefn{preelaborated} A shared passive library unit is preelaborated. @end{StaticSem} @begin{LinkTime} A shared passive library unit shall be assigned to at most one partition within a given program. @PDefn2{Term=[compilation units needed], Sec=(shared passive library unit)} @PDefn2{Term=[needed], Sec=(shared passive library unit)} @Defn{notwithstanding} Notwithstanding the rule given in @RefSecNum{Program Execution}, a compilation unit in a given partition does not @i{need} (in the sense of @RefSecNum{Program Execution}) the shared passive library units on which it depends semantically to be included in that same partition; they will typically reside in separate passive partitions. @end{LinkTime} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0080],ARef=[AI95-00003-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to allow access types in blocks in shared passive generic packages.]} @end{DiffWord95} @LabeledSubClause{Remote Types Library Units} @begin{Intro} @redundant[A remote types library unit supports the definition of types intended for use in communication between active partitions.] @end{Intro} @begin{MetaRules} The restrictions governing a remote types package are similar to those for a declared pure package. However, the restrictions are relaxed deliberately to allow such a package to contain declarations that violate the stateless property of pure packages, though it is presumed that any state-dependent properties are essentially invisible outside the package. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Remote_Types)} @PDefn2{Term=[pragma, categorization], Sec=(Remote_Types)} The form of a @nt{pragma} Remote_Types is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Remote_Types)[(@SynI{library_unit_}@Syn2{name})];' @end{Syntax} @begin{Legality} @Leading@Defn{remote types library unit} A @i{remote types library unit} is a library unit to which the pragma Remote_Types applies. The following restrictions apply to the declaration of such a library unit: @begin{itemize} @Redundant[it shall be preelaborable;] it shall depend semantically only on declared pure, shared passive, or other remote types library units; it shall not contain the declaration of any variable within the visible part of the library unit; @begin{Reason} This is essentially a @lquotes@;methodological@rquotes@; restriction. A separate copy of a remote types package is included in each partition that references it, just like a normal package. Nevertheless, a remote types package is thought of as an @lquotes@;essentially pure@rquotes@; package for defining types to be used for interpartition communication, and it could be misleading to declare visible objects when no remote data access is actually being provided. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} @Chg{Version=[2],New=[],Old=[if ]}the full view of @Chg{Version=[2],New=[each],Old=[a]} type declared in the visible part of the library unit @Chg{Version=[2],New=[that has any available stream attributes shall support external streaming (see @RefSecNum{Stream-Oriented Attributes})], Old=[has a part that is of a non-remote access type, then that access type, or the type of some part that includes the access type subcomponent, shall have user-specified Read and Write attributes]}. @begin{Reason} This is to prevent the use of the predefined Read and Write attributes of an access type as part of the Read and Write attributes of a visible type. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Types that do not have available stream attributes are excluded from this rule; that means that attributes do not need to be specified for most limited types. It is only necessary to specify attributes for nonlimited types that have a part that is of any access type, and for extensions of limited types with available stream attributes where the @nt{record_extension_part} includes a subcomponent of an access type, where the access type does not have specified attributes.]} @end{Ramification} @end{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0082],ARef=[AI95-00164-01]} @Chg{New=[@Leading],Old=[]}@Defn{remote access type} An access type declared in the visible part of a remote types or remote call interface library unit is called a @i{remote access type}. @Defn{remote access-to-subprogram type} @Defn{remote access-to-class-wide type} Such a type shall be@Chg{New=[:],Old=[ either an access-to-subprogram type or a general access type that designates a class-wide limited private type.]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgAdded{Version=[1],Text=[an access-to-subprogram type, or]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgAdded{Version=[1],Text=[a general access type that designates a class-wide limited private type or a class-wide private type extension all of whose ancestors are either private type extensions or limited private types.]} @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0081],ARef=[AI95-00004-01]} @ChgAdded{Version=[1],Text=[A type that is derived from a remote access type is also a remote access type.]} @Leading@;The following restrictions apply to the use of a remote access-to-subprogram type: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00431-01]} A value of a remote access-to-subprogram type shall be converted only to @Chg{Version=[2],New=[or from ],Old=[]}another (subtype-conformant) remote access-to-subprogram type; The @nt<prefix> of an Access @nt<attribute_reference> that yields a value of a remote access-to-subprogram type shall statically denote a (subtype-conformant) remote subprogram. @end{Itemize} @Leading@;The following restrictions apply to the use of a remote access-to-class-wide type: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0083],ARef=[AI95-00047-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} The primitive subprograms of the corresponding specific limited private type shall only have access parameters if they are controlling formal parameters; @Chg{New=[each non-controlling formal parameter],Old=[the types of all the non-controlling formal parameters]} shall @Chg{Version=[2],New=[support external streaming (see @RefSecNum{Stream-Oriented Attributes});], Old=[have @Chg{New=[either a nonlimited type or a type with],Old=[]} Read and Write attributes@Chg{New=[ specified via an @nt{attribute_definition_clause};],Old=[.]}]} A value of a remote access-to-class-wide type shall be explicitly converted only to another remote access-to-class-wide type; @ChgRef{Version=[1],Kind=[Revised]} A value of a remote access-to-class-wide type shall be dereferenced (or implicitly converted to an anonymous access type) only as part of a dispatching call where the value designates a controlling operand of the call (see @RefSec{Remote Subprogram Calls})@Chg{New=[.],Old=[;]} @ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} The Storage_Pool @Chg{Version=[2],New=[attribute is],Old=[and Storage_Size attributes are]} not defined for@Chg{Version=[2],New=[ a],Old=[]} remote access-to-class-wide @Chg{Version=[2],New=[type],Old=[types]}; the expected type for an @nt{allocator} shall not be a remote access-to-class-wide type@Chg{Version=[2],New=[. A],Old=[; a]} remote access-to-class-wide type shall not be an actual parameter for a generic formal access type@Chg{New=[.],Old=[;]}@Chg{Version=[2],New=[ The Storage_Size attribute of a remote access-to-class-wide type yields 0; it is not allowed in an @nt{attribute_definition_clause}.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised]} All three of these restrictions are because there is no storage pool associated with a remote access-to-class-wide type.@Chg{Version=[2],New=[ The Storage_Size is defined to be 0 so that there is no conflict with the rules for pure units.],Old=[]} @end{Reason} @end{Itemize} @end{Legality} @begin{Notes} A remote types library unit need not be pure, and the types it defines may include levels of indirection implemented by using access types. User-specified Read and Write attributes (see @RefSecNum{Stream-Oriented Attributes}) provide for sending values of such a type between active partitions, with Write marshalling the representation, and Read unmarshalling any levels of indirection. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00240-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The wording was changed from @lquotes@;user-specified@rquotes to @lquotes@;available@rquotes attributes. (This was then further changed, see below.) This means that an access type with the attributes specified in the private part would originally have been sufficient to allow the access type to be used in a remote type, but that is no longer allowed. Similarly, the attributes of a remote type that has access components have to be specified in the visible part. These changes were made so that the rules were consistent with the rules introduced for the Corrigendum for stream attributes; moreover, legality should not depend on the contents of the private part.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Remote types that cannot be streamed (that is, have no available stream attributes) do not require the specification of stream attributes. This is necessary so that most extensions of Limited_Controlled do not need stream attributes defined (otherwise there would be a signficant incompatibility, as Limited_Controlled would need stream attributes, and then all extensions of it also would need stream attributes).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0081],ARef=[AI95-00004-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added missing wording so that a type derived from a remote access type is also a remote access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0083],ARef=[AI95-00047-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that user-defined Read and Write attributes are required for the primitive subprograms corresponding to a remote access-to-class-wide type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added missing wording so that a remote access type can designate an appropriate private extension.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the newly defined term @i<type that supports external streaming>, so that various issues with access types in pure units and implicitly declared attributes for type extensions are properly handled.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Defined Storage_Size to be 0 for remote access-to-class-wide types, rather than having it undefined. This eliminates issues with pure units requiring a defined storage size.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00431-01]} @ChgAdded{Version=[2],Text=[Corrected the wording so that a value of a local access-to-subprogram type cannot be converted to a remote access-to-subprogram type, as intended (and required by the ACATS).]} @end{DiffWord95} @LabeledSubClause{Remote Call Interface Library Units} @begin{Intro} @redundant[A remote call interface library unit can be used as an interface for remote procedure calls (RPCs) (or remote function calls) between active partitions.] @end{Intro} @begin{MetaRules} The restrictions governing a remote call interface library unit are intended to ensure that the values of the actual parameters in a remote call can be meaningfully sent between two active partitions. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Remote_Call_Interface)} @PDefn2{Term=[pragma, categorization], Sec=(Remote_Call_Interface)} The form of a @nt{pragma} Remote_Call_Interface is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Remote_Call_Interface)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @Leading@;The form of a @nt{pragma} All_Calls_Remote is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(All_Calls_Remote)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(All_Calls_Remote)} @PDefn2{Term=[pragma, library unit], Sec=(All_Calls_Remote)} A @nt{pragma} All_Calls_Remote is a library unit pragma. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @Defn{remote call interface} @Defn2{Term=[RCI],Sec=(library unit)} @Defn2{Term=[RCI],Sec=(package)} @Defn2{Term=[RCI],Sec=(generic)} @Defn{remote subprogram} A @i{remote call interface (RCI)} is a library unit to which the pragma Remote_Call_Interface applies. A subprogram declared in the visible part of such a library unit@Chg{New=[, or declared by such a library unit,],Old=[]} is called a @i{remote subprogram}. The declaration of an RCI library unit shall be preelaborable (see @RefSecNum{Elaboration Control}), and shall depend semantically only upon declared pure, shared passive, remote types, or other remote call interface library units. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @Leading@;In addition, the following restrictions apply to @Chg{New=[],Old=[the visible part of ]}an RCI library unit: @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain the declaration of a variable; @begin{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} Remote call interface @Chg{New=[units],Old=[packages]} do not provide remote data access. A shared passive package has to be used for that. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain the declaration of a limited type; @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} We disallow the declaration of task and protected types, since calling an entry or a protected subprogram implicitly passes an object of a limited type (the target task or protected object). We disallow other limited types since we require that such types have @Chg{Version=[2],New=[available],Old=[user-defined]} Read and Write attributes, but we certainly don't want the Read and Write attributes themselves to involve remote calls (thereby defeating their purpose of marshalling the value for remote calls). @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain a nested @nt{generic_declaration}; @begin{Reason} This is disallowed because the body of the nested generic would presumably have access to data inside the body of the RCI package, and if instantiated in a different partition, remote data access might result, which is not supported. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it shall not @Chg{New=[be, nor shall its visible part],Old=[]} contain@Chg{New=[,],Old=[]} the declaration of a subprogram to which a pragma Inline applies; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} it shall not @Chg{New=[be, nor shall its visible part], Old=[]} contain@Chg{New=[,],Old=[]} a subprogram (or access-to-subprogram) declaration whose profile has @Chg{Version=[2],New=[@Redundant[an access parameter or] a parameter of a type that does not support external streaming (see @RefSecNum{Stream-Oriented Attributes})], Old=[an access parameter, or a formal parameter of a limited type unless that limited type has user-specified Read and Write attributes]}; any public child of the library unit shall be a remote call interface library unit. @begin{Reason} No restrictions apply to the private part of an RCI package, and since a public child can @lquotes@;see@rquotes@; the private part of its parent, such a child must itself have a Remote_Call_Interface pragma, and be assigned to the same partition (see below). @end{Reason} @begin{Discussion} We considered making the public child of an RCI package implicitly RCI, but it seemed better to require an explicit pragma to avoid any confusion. Note that there is no need for a private child to be an RCI package, since it can only be seen from the body of its parent or its siblings, all of which are required to be in the same active partition. @end{Discussion} @end{itemize} If a pragma All_Calls_Remote applies to a library unit, the library unit shall be a remote call interface. @end{Legality} @begin{LinkTime} A remote call interface library unit shall be assigned to at most one partition of a given program. A remote call interface library unit whose parent is also an RCI library unit shall be assigned only to the same partition as its parent. @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} The declaration of an RCI @Chg{New=[unit],Old=[package]}, with a calling-stub body, is automatically included in all active partitions with compilation units that depend on it. However the whole RCI library unit, including its (non-stub) body, will only be in one of the active partitions. @end{ImplNote} @PDefn2{Term=[compilation units needed], Sec=(remote call interface)} @PDefn2{Term=[needed], Sec=(remote call interface)} @Defn{notwithstanding} Notwithstanding the rule given in @RefSecNum{Program Execution}, a compilation unit in a given partition that semantically depends on the declaration of an RCI library unit, @i{needs} (in the sense of @RefSecNum{Program Execution}) only the declaration of the RCI library unit, not the body, to be included in that same partition. @Redundant[Therefore, the body of an RCI library unit is included only in the partition to which the RCI library unit is explicitly assigned.] @end{LinkTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} If a pragma All_Calls_Remote applies to a given RCI library @Chg{New=[unit],Old=[package]}, then the implementation shall route any call to a subprogram of the RCI @Chg{New=[unit],Old=[package]} from outside the declarative region of the @Chg{New=[unit],Old=[package]} through the Partition Communication Subsystem (PCS); see @RefSecNum{Partition Communication Subsystem}. Calls to such subprograms from within the declarative region of the @Chg{New=[unit],Old=[package]} are defined to be local and shall not go through the PCS. @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} Without this pragma, it is presumed that most implementations will make direct calls if the call originates in the same partition as that of the RCI @Chg{New=[unit],Old=[package]}. With this pragma, all calls from outside the subsystem rooted at the RCI @Chg{New=[unit],Old=[package]} are treated like calls from outside the partition, ensuring that the PCS is involved in all such calls (for debugging, redundancy, etc.). @end{Discussion} @begin{reason} There is no point to force local calls (or calls from children) to go through the PCS, since on the target system, these calls are always local, and all the units are in the same active partition. @end{Reason} @end{ImplReq} @begin{ImplPerm} An implementation need not support the Remote_Call_Interface pragma nor the All_Calls_Remote pragma. @Redundant[Explicit message-based communication between active partitions can be supported as an alternative to RPC.] @begin{Ramification} Of course, it is pointless to support the All_Calls_Remote pragma if the Remote_Call_Interface pragma (or some approximate equivalent) is not supported. @end{Ramification} @end{ImplPerm} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00240-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The wording was changed from @lquotes@;user-specified@rquotes to @lquotes@;available@rquotes attributes. (This was then further changed, see below.) This means that a type with the attributes specified in the private part would originally have been allowed as a formal parameter of an RCI subprogram, but that is no longer allowed. This change was made so that the rules were consistent with the rules introduced for the Corrigendum for stream attributes; moreover, legality should not depend on the contents of the private part.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed the wording to allow a library subprogram to be a remote call interface unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the newly defined term @i<type that supports external streaming>, so that various issues with access types in pure units and implicitly declared attributes for type extensions are properly handled.]} @end{DiffWord95} @LabeledClause{Consistency of a Distributed System} @begin{Intro} @redundant[This clause defines attributes and rules associated with verifying the consistency of a distributed program. ] @end{Intro} @begin{MetaRules} The rules guarantee that remote call interface and shared passive packages are consistent among all partitions prior to the execution of a distributed program, so that the semantics of the distributed program are well defined. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} P that statically denotes a program unit]}, the following attributes are defined: @begin{Description} @Attribute{Prefix=<P>, AttrName=<Version>, Text=[Yields a value of the predefined type String that identifies the version of the compilation unit that contains the declaration of the program unit.]} @Attribute{Prefix=<P>, AttrName=<Body_Version>, Text=[Yields a value of the predefined type String that identifies the version of the compilation unit that contains the body (but not any subunits) of the program unit.]} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0084],ARef=[AI95-00104-01]} @Defn2{Term=[version], Sec=(of a compilation unit)} The @i{version} of a compilation unit changes whenever the @Chg{New=[],Old=[version changes for any ]}compilation unit @Chg{New=[changes in a semantically significant way. This International Standard does not define the exact meaning of "semantically significant"], Old=[on which it depends semantically. The version also changes whenever the compilation unit itself changes in a semantically significant way]}. It is @Chg{New=[unspecified],Old=[implementation defined]} whether there are other events (such as recompilation) that result in the version of a compilation unit changing. @Chg{New=[@PDefn{unspecified}],Old=[]} @ChgImplDef{Version=[1],Kind=[Deleted],Text=[@Chg{New=[],Old=[Events that cause the version of a compilation unit to change.]}]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0084],ARef=[AI95-00104-01]} @ChgAdded{Version=[1],Text=[If P is not a library unit, and P has no completion, then P'Body_Version returns the Body_Version of the innermost program unit enclosing the declaration of P. If P is a library unit, and P has no completion, then P'Body_Version returns a value that is different from Body_Version of any version of P that has a completion.]} @end{StaticSem} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} @Defn{unit consistency} In a distributed program, a library unit is @i{consistent} if the same version of its declaration is used throughout. It is a bounded error to elaborate a partition of a distributed program that contains a compilation unit that depends on a different version of the declaration of a shared passive or RCI library unit than that included in the partition to which the shared passive or RCI library unit was assigned. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} As a result of this error, Program_Error can be raised in one or both partitions during elaboration; in any case, the partitions become inaccessible to one another. @begin{Ramification} Because a version changes if anything on which it depends undergoes a version change, requiring consistency for shared passive and remote call interface library units is sufficient to ensure consistency for the declared pure and remote types library units that define the types used for the objects and parameters through which interpartition communication takes place. Note that we do not require matching Body_Versions; it is irrelevant for shared passive and remote call interface packages, since only one copy of their body exists in a distributed program (in the absence of implicit replication), and we allow the bodies to differ for declared pure and remote types packages from partition to partition, presuming that the differences are due to required error corrections that took place during the execution of a long-running distributed program. The Body_Version attribute provides a means for performing stricter consistency checks. @end{Ramification} @end{Bounded} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0084],ARef=[AI95-00104-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of 'Version and 'Body_Version.]} @end{DiffWord95} @LabeledClause{Remote Subprogram Calls} @begin{Intro} @Defn{remote subprogram call} @RootDefn{asynchronous remote procedure call} @Defn{calling partition} @Defn{called partition} @Defn{remote subprogram binding} A @i{remote subprogram call} is a subprogram call that invokes the execution of a subprogram in another partition. The partition that originates the remote subprogram call is the @i{calling partition}, and the partition that executes the corresponding subprogram body is the @i{called partition}. Some remote procedure calls are allowed to return prior to the completion of subprogram execution. These are called @i{asynchronous remote procedure calls}. @Leading@;There are three different ways of performing a remote subprogram call: @begin{Itemize} As a direct call on a (remote) subprogram explicitly declared in a remote call interface; As an indirect call through a value of a remote access-to-subprogram type; As a dispatching call with a controlling operand designated by a value of a remote access-to-class-wide type. @end{Itemize} The first way of calling corresponds to a @i(static) binding between the calling and the called partition. The latter two ways correspond to a @i(dynamic) binding between the calling and the called partition. A remote call interface library unit (see @RefSecNum{Remote Call Interface Library Units}) defines the remote subprograms or remote access types used for remote subprogram calls. @end{Intro} @begin{MetaRules} Remote subprogram calls are standardized since the RPC paradigm is widely-used, and establishing an interface to it in the annex will increase the portability and reusability of distributed programs. @end{MetaRules} @begin{Legality} In a dispatching call with two or more controlling operands, if one controlling operand is designated by a value of a remote access-to-class-wide type, then all shall be. @end{Legality} @begin{RunTime} @Defn{marshalling} @Defn{unmarshalling} @PDefn2{Term=[execution], Sec=(remote subprogram call)} For the execution of a remote subprogram call, subprogram parameters (and later the results, if any) are passed using a stream-oriented representation (see @RefSecNum{The Package Streams}) @Redundant[which is suitable for transmission between partitions]. This action is called @i{marshalling}. @i{Unmarshalling} is the reverse action of reconstructing the parameters or results from the stream-oriented representation. @redundant[Marshalling is performed initially as part of the remote subprogram call in the calling partition; unmarshalling is done in the called partition. After the remote subprogram completes, marshalling is performed in the called partition, and finally unmarshalling is done in the calling partition.] @Defn{calling stub} @Defn{receiving stub} A @i{calling stub} is the sequence of code that replaces the subprogram body of a remotely called subprogram in the calling partition. A @i{receiving stub} is the sequence of code (the @lquotes@;wrapper@rquotes@;) that receives a remote subprogram call on the called partition and invokes the appropriate subprogram body. @begin{Discussion} The use of the term @i{stub} in this annex should not be confused with @nt{body_stub} as defined in @RefSecNum{Subunits of Compilation Units}. The term @i{stub} is used here because it is a commonly understood term when talking about the RPC paradigm. @end{Discussion} @Defn{at-most-once execution} Remote subprogram calls are executed at most once, that is, if the subprogram call returns normally, then the called subprogram's body was executed exactly once. The task executing a remote subprogram call blocks until the subprogram in the called partition returns, unless the call is asynchronous. For an asynchronous remote procedure call, the calling task can become ready before the procedure in the called partition returns. @Defn{cancellation of a remote subprogram call} If a construct containing a remote call is aborted, the remote subprogram call is @i{cancelled}. Whether the execution of the remote subprogram is immediately aborted as a result of the cancellation is implemen@!tation defined. @ImplDef{Whether the execution of the remote subprogram is immediately aborted as a result of cancellation.} If a remote subprogram call is received by a called partition before the partition has completed its elaboration, the call is kept pending until the called partition completes its elaboration (unless the call is cancelled by the calling partition prior to that). If an exception is propagated by a remotely called subprogram, and the call is not an asynchronous call, the corresponding exception is reraised at the point of the remote subprogram call. For an asynchronous call, if the remote procedure call returns prior to the completion of the remotely called subprogram, any exception is lost. The exception Communication_Error (see @RefSecNum{Partition Communication Subsystem}) is raised if a remote call cannot be completed due to difficulties in communicating with the called partition. @PDefn2{Term=[potentially blocking operation],Sec=(remote subprogram call)} @PDefn2{Term=[blocking, potentially],Sec=(remote subprogram call)} All forms of remote subprogram calls are potentially blocking operations (see @RefSecNum{Protected Subprograms and Protected Actions}). @begin{Reason} Asynchronous remote procedure calls are potentially blocking since the implementation may require waiting for the availability of shared resources to initiate the remote call. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0085],ARef=[AI95-00215-01]} @IndexCheck{Accessibility_Check} In a remote subprogram call with a formal parameter of a class-wide type, a check is made that the tag of the actual parameter identifies a tagged type declared in a declared-pure or shared passive library unit, or in the visible part of a remote types or remote call interface library unit. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if this check fails. @Chg{New=[In a remote function call which returns a class-wide type, the same check is made on the function result.],Old=[]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0085],ARef=[AI95-00215-01]} This check makes certain that the specific type passed@Chg{New=[ or returned], Old=[]} in an RPC satisfies the rules for a "communicable" type. Normally this is guaranteed by the compile-time restrictions on remote call interfaces. However, with class-wide types, it is possible to pass an object whose tag identifies a type declared outside the "safe" packages. This is considered an accessibility_check since only the types declared in "safe" packages are considered truly "global" (cross-partition). Other types are local to a single partition. This is analogous to the "accessibility" of global vs. local declarations in a single-partition program. This rule replaces a rule from an early version of Ada 9X which was given in the subclause on Remote Types Library Units (now @RefSec{Remote Types Library Units}). That rule tried to prevent "bad" types from being sent by arranging for their tags to mismatch between partitions. However, that interfered with other uses of tags. The new rule allows tags to agree in all partitions, even for those types which are not "safe" to pass in an RPC. @end{Discussion} @IndexCheck{Partition_Check} In a dispatching call with two or more controlling operands that are designated by values of a remote access-to-class-wide type, a check is made @Redundant[(in addition to the normal Tag_Check @em see @RefSecNum{Suppressing Checks})] that all the remote access-to-class-wide values originated from Access @nt<attribute_reference>s that were evaluated by tasks of the same active partition. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{ImplNote} When a remote access-to-class-wide value is created by an Access @nt<attribute_reference>, the identity of the active partition that evaluated the @nt<attribute_reference> should be recorded in the representation of the remote access value. @end{ImplNote} @end{RunTime} @begin{ImplReq} The implementation of remote subprogram calls shall conform to the PCS interface as defined by the specification of the language-defined package System.RPC (see @RefSecNum{Partition Communication Subsystem}). The calling stub shall use the Do_RPC procedure unless the remote procedure call is asynchronous in which case Do_APC shall be used. On the receiving side, the corresponding receiving stub shall be invoked by the RPC-receiver. @begin{ImplNote} One possible implementation model is as follows: The code for calls to subprograms declared in an RCI package is generated normally, that is, the call-site is the same as for a local subprogram call. The code for the remotely callable subprogram bodies is also generated normally. Subprogram's prologue and epilogue are the same as for a local call. When compiling the specification of an RCI package, the compiler generates calling stubs for each visible subprogram. Similarly, when compiling the body of an RCI package, the compiler generates receiving stubs for each visible subprogram together with the appropriate tables to allow the RPC-receiver to locate the correct receiving stub. For the statically bound remote calls, the identity of the remote partition is statically determined (it is resolved at configuration/link time). @Leading@;The calling stub operates as follows: @begin(Itemize) It allocates (or reuses) a stream of Params_Stream_Type of Initial_Size, and initializes it by repeatedly calling Write operations, first to identify which remote subprogram in the receiving partition is being called, and then to pass the incoming value of each of the @b(in) and @b(in out) parameters of the call. It allocates (or reuses) a stream for the Result, unless a pragma Asynchronous is applied to the procedure. It calls Do_RPC unless a pragma Asynchronous is applied to the procedure in which case it calls Do_APC. An access value designating the message stream allocated and initialized above is passed as the Params parameter. An access value designating the Result stream is passed as the Result parameter. If the pragma Asynchronous is not specified for the procedure, Do_RPC blocks until a reply message arrives, and then returns to the calling stub. The stub returns after extracting from the Result stream, using Read operations, the @b(in out) and @b(out) parameters or the function result. If the reply message indicates that the execution of the remote subprogram propagated an exception, the exception is propagated from Do_RPC to the calling stub, and thence to the point of the original remote subprogram call. If Do_RPC detects that communication with the remote partition has failed, it propagates Communication_Error. @end(Itemize) @Leading@;On the receiving side, the RPC-receiver procedure operates as follows: @begin(Itemize) It is called from the PCS when a remote-subprogram-call message is received. The call originates in some remote call receiver task executed and managed in the context of the PCS. It extracts information from the stream to identify the appropriate receiving stub. The receiving stub extracts the @b(in) and @b(in out) parameters using Read from the stream designated by the Params parameter. The receiving stub calls the actual subprogram body and, upon completion of the subprogram, uses Write to insert the results into the stream pointed to by the Result parameter. The receiving stub returns to the RPC-receiver procedure which in turn returns to the PCS. If the actual subprogram body propagates an exception, it is propagated by the RPC-receiver to the PCS, which handles the exception, and indicates in the reply message that the execution of the subprogram body propagated an exception. The exception occurrence can be represented in the reply message using the Write attribute of Ada.Exceptions.Exception_Occurrence. @end(Itemize) For remote access-to-subprogram types: A value of a remote access-to-subprogram type can be represented by the following components: a reference to the remote partition, an index to the package containing the remote subprogram, and an index to the subprogram within the package. The values of these components are determined at run time when the remote access value is created. These three components serve the same purpose when calling Do_APC/RPC, as in the statically bound remote calls; the only difference is that they are evaluated dynamically. For remote access-to-class-wide types: For each remote access-to-class-wide type, a calling stub is generated for each dispatching operation of the designated type. In addition, receiving stubs are generated to perform the remote dispatching operations in the called partition. The appropriate @nt{subprogram_body} is determined as for a local dispatching call once the receiving stub has been reached. A value of a remote access-to-class-wide type can be represented with the following components: a reference to the remote partition, an index to a table (created one per each such access type) containing addresses of all the dispatching operations of the designated type, and an access value designating the actual remote object. Alternatively, a remote access-to-class-wide value can be represented as a normal access value, pointing to a "stub" object which in turn contains the information mentioned above. A call on any dispatching operation of such a stub object does the remote call, if necessary, using the information in the stub object to locate the target partition, etc. This approach has the advantage that less special-casing is required in the compiler. All access values can remain just a simple address. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} For a call to Do_RPC or Do_APC: The partition ID of all controlling operands are checked for equality (a Constraint_Error is raised if this check fails). The partition ID value is used for the Partition parameter. An index into the @i{tagged-type-descriptor} is created. This index points to the receiving stub of the class-wide operation. This index and the index to the table (described above) are written to the stream. Then, the actual parameters are marshalled into the message stream. For a controlling operand, only the access value designating the remote object is required (the other two components are already present in the other parameters). On the called partition (after the RPC-receiver has transferred control to the appropriate receiving stub) the parameters are first unmarshalled. Then, the tags of the controlling operands (obtained by dereferencing the pointer to the object) are checked for equality. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the check fails Constraint_Error is raised and propagated back to the calling partition, unless it is a result of an asynchronous call. Finally, a dispatching call to the specific subprogram (based on the controlling object's tag) is made. Note that since this subprogram is not in an RCI package, no specific stub is generated for it, it is called normally from the @i{dispatching stub}. @end{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0086],ARef=[AI95-00159-01]} @ChgAdded{Version=[1],Text=[With respect to shared variables in shared passive library units, the execution of the corresponding subprogram body of a synchronous remote procedure call is considered to be part of the execution of the calling task. The execution of the corresponding subprogram body of an asynchronous remote procedure call proceeds in parallel with the calling task and does not signal the next action of the calling task (see @RefSecNum{Shared Variables}).]} @end{ImplReq} @begin{Notes} A given active partition can both make and receive remote subprogram calls. Thus, an active partition can act as both a client and a server. If a given exception is propagated by a remote subprogram call, but the exception does not exist in the calling partition, the exception can be handled by an @key(others) choice or be propagated to and handled by a third partition. @begin{Discussion} This situation can happen in a case of dynamically nested remote subprogram calls, where an intermediate call executes in a partition that does not include the library unit that defines the exception. @end{Discussion} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0086],ARef=[AI95-00159-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added rules so that tasks can safely access shared passive objects.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0085],ARef=[AI95-00215-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the check on class-wide types also applies to values returned from remote subprogram call functions.]} @end{DiffWord95} @LabeledSubClause{Pragma Asynchronous} @begin{Intro} @redundant[This subclause introduces the pragma Asynchronous which allows a remote subprogram call to return prior to completion of the execution of the corresponding remote subprogram body.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@;The form of a @nt{pragma} Asynchronous is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Asynchronous)(@Syn2{local_name});' @end{Syntax} @begin{Legality} @Leading@;The @nt<local_name> of a pragma Asynchronous shall denote either: @begin{Itemize} One or more remote procedures; the formal parameters of the procedure(s) shall all be of mode @key{in}; The first subtype of a remote access-to-procedure type; the formal parameters of the designated profile of the type shall all be of mode @key{in}; The first subtype of a remote access-to-class-wide type. @end{Itemize} @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Asynchronous)} @PDefn2{Term=[pragma, representation], Sec=(Asynchronous)} A pragma Asynchronous is a representation pragma. When applied to a type, it specifies the type-related @i{asynchronous} aspect of the type. @end{StaticSem} @begin{RunTime} @Defn2{Term=[remote procedure call],Sec=(asynchronous)} @Defn2{Term=[asynchronous], Sec=(remote procedure call)} A remote call is @i{asynchronous} if it is a call to a procedure, or a call through a value of an access-to-procedure type, to which a pragma Asynchronous applies. In addition, if a pragma Asynchronous applies to a remote access-to-class-wide type, then a dispatching call on a procedure with a controlling operand designated by a value of the type is asynchronous if the formal parameters of the procedure are all of mode @key{in}. @end{RunTime} @begin{ImplReq} Asynchronous remote procedure calls shall be implemented such that the corresponding body executes at most once as a result of the call. @begin{Honest} It is not clear that this rule can be tested or even defined formally. @end{Honest} @end{ImplReq} @LabeledSubClause{Example of Use of a Remote Access-to-Class-Wide Type} @begin{Examples} @Leading@i{Example of using a remote access-to-class-wide type to achieve dynamic binding across active partitions:} @begin{example} @key{package} Tapes @key{is} @key{pragma} Pure(Tapes); @key{type} Tape @key{is abstract tagged limited private}; @RI{-- Primitive dispatching operations where} @RI{-- Tape is controlling operand} @key{procedure} Copy (From, To : @key{access} Tape; Num_Recs : @key[in] Natural) @key{is} @key{abstract}; @key{procedure} Rewind (T : @key{access} Tape) @key{is} @key{abstract}; @RI{-- More operations} @key{private} @key{type} Tape @key{is} ... @key{end} Tapes; @key{with} Tapes; @key{package} Name_Server @key{is} @key{pragma} Remote_Call_Interface; @RI{-- Dynamic binding to remote operations is achieved} @RI{-- using the access-to-limited-class-wide type Tape_Ptr} @key{type} Tape_Ptr @key{is access all} Tapes.Tape'Class; @RI{-- The following statically bound remote operations} @RI{-- allow for a name-server capability in this example} @key{function} Find (Name : String) @key{return} Tape_Ptr; @key{procedure} Register (Name : @key[in] String; T : @key[in] Tape_Ptr); @key{procedure} Remove (T : @key[in] Tape_Ptr); @RI{-- More operations} @key{end} Name_Server; @key{package} Tape_Driver @key{is} @RI{-- Declarations are not shown, they are irrelevant here} @key{end} Tape_Driver; @key{with} Tapes, Name_Server; @key{package body} Tape_Driver @key{is} @key{type} New_Tape @key{is new} Tapes.Tape @key{with} ... @key{procedure} Copy (From, To : @key{access} New_Tape; Num_Recs: @key[in] Natural) @key{is} @key{begin} . . . @key{end} Copy; @key{procedure} Rewind (T : @key{access} New_Tape) @key{is} @key{begin} . . . @key{end} Rewind; @RI{-- Objects remotely accessible through use} @RI{-- of Name_Server operations} Tape1, Tape2 : @key[aliased] New_Tape; @key{begin} Name_Server.Register ("NINE-TRACK", Tape1'Access); Name_Server.Register ("SEVEN-TRACK", Tape2'Access); @key{end} Tape_Driver; @key{with} Tapes, Name_Server; @RI{-- Tape_Driver is not needed and thus not mentioned in the @nt{with_clause}} @key{procedure} Tape_Client @key{is} T1, T2 : Name_Server.Tape_Ptr; @key{begin} T1 := Name_Server.Find ("NINE-TRACK"); T2 := Name_Server.Find ("SEVEN-TRACK"); Tapes.Rewind (T1); Tapes.Rewind (T2); Tapes.Copy (T1, T2, 3); @key{end} Tape_Client; @end{example} @leading@keepnext@i{Notes on the example}: @begin{Discussion} The example does not show the case where tapes are removed from or added to the system. In the former case, an appropriate exception needs to be defined to instruct the client to use another tape. In the latter, the Name_Server should have a query function visible to the clients to inform them about the availability of the tapes in the system. @end{Discussion} @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{itemize} The package Tapes provides the necessary declarations of the type and its primitive operations. Name_Server is a remote call interface package and is elaborated in a separate active partition to provide the necessary naming services (such as Register and Find) to the entire distributed program through remote subprogram calls. Tape_Driver is a normal package that is elaborated in a partition configured on the processing node that is connected to the tape device(s). The abstract operations are overridden to support the locally declared tape devices (Tape1, Tape2). The package is not visible to its clients, but it exports the tape devices (as remote objects) through the services of the Name_Server. This allows for tape devices to be dynamically added, removed or replaced without requiring the modification of the clients' code. The Tape_Client procedure references only declarations in the Tapes and Name_Server packages. Before using a tape for the first time, it needs to query the Name_Server for a system-wide identity for that tape. From then on, it can use that identity to access the tape device. Values of remote access type Tape_Ptr include the necessary information to complete the remote dispatching operations that result from dereferencing the controlling operands T1 and T2. @end{itemize} @end{Examples} @LabeledClause{Partition Communication Subsystem} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00273-01]} @Defn{partition communication subsystem (PCS)} @Defn{PCS (partition communication subsystem)} @redundant[The @i{Partition Communication Subsystem} (PCS) provides facilities for supporting communication between the active partitions of a distributed program. The package System.RPC is a language-defined interface to the PCS.]@Chg{Version=[2],New=[],Old=[ An implementation conforming to this Annex shall use the RPC interface to implement remote subprogram calls.]} @begin{Reason} The prefix RPC is used rather than RSC because the term remote procedure call and its acronym are more familiar. @end{Reason} @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{example} @b(with) Ada.Streams; @RI{-- see @RefSecNum[The Package Streams]} @key(package) System.RPC @key(is)@ChildUnit{Parent=[System],Child=[RPC]} @key(type) @AdaTypeDefn{Partition_Id} @key(is range) 0 .. @RI(implementation-defined); @AdaExcDefn{Communication_Error} : @key(exception); @key(type) @AdaTypeDefn{Params_Stream_Type} ( Initial_Size : Ada.Streams.Stream_Element_Count) @key(is) @key(new) Ada.Streams.Root_Stream_Type @key(with) @key(private); @key(procedure) @AdaSubDefn{Read}( Stream : @key(in out) Params_Stream_Type; Item : @key(out) Ada.Streams.Stream_Element_Array; Last : @key(out) Ada.Streams.Stream_Element_Offset); @key(procedure) @AdaSubDefn{Write}( Stream : @key(in out) Params_Stream_Type; Item : @key(in) Ada.Streams.Stream_Element_Array); @RI(-- Synchronous call) @key(procedure) @AdaSubDefn{Do_RPC}( Partition : @key(in) Partition_Id; Params : @key(access) Params_Stream_Type; Result : @key(access) Params_Stream_Type); @RI(-- Asynchronous call) @key(procedure) @AdaSubDefn{Do_APC}( Partition : @key(in) Partition_Id; Params : @key(access) Params_Stream_Type); @RI(-- The handler for incoming RPCs) @key(type) @AdaTypeDefn{RPC_Receiver} @key(is access procedure)( Params : @key(access) Params_Stream_Type; Result : @key(access) Params_Stream_Type); @key(procedure) @AdaSubDefn{Establish_RPC_Receiver}( Partition : @key(in) Partition_Id; Receiver : @key(in) RPC_Receiver); @key[private] ... -- @RI{not specified by the language} @b(end) System.RPC; @end{example} A value of the type Partition_Id is used to identify a partition. @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The range of type System.RPC.Partition_Id.]}]} An object of the type Params_Stream_Type is used for identifying the particular remote subprogram that is being called, as well as marshalling and unmarshalling the parameters or result of a remote subprogram call, as part of sending them between partitions. @redundant[The Read and Write procedures override the corresponding abstract operations for the type Params_Stream_Type.] @end{StaticSem} @begin{RunTime} The Do_RPC and Do_APC procedures send a message to the active partition identified by the Partition parameter. @begin{ImplNote} It is assumed that the RPC interface is above the message-passing layer of the network protocol stack and is implemented in terms of it. @end{ImplNote} After sending the message, Do_RPC blocks the calling task until a reply message comes back from the called partition or some error is detected by the underlying communication system in which case Communication_Error is raised at the point of the call to Do_RPC. @begin{Reason} Only one exception is defined in System.RPC, although many sources of errors might exist. This is so because it is not always possible to distinguish among these errors. In particular, it is often impossible to tell the difference between a failing communication link and a failing processing node. Additional information might be associated with a particular Exception_Occurrence for a Communication_Error. @end{Reason} Do_APC operates in the same way as Do_RPC except that it is allowed to return immediately after sending the message. Upon normal return, the stream designated by the Result parameter of Do_RPC contains the reply message. @PDefn2{Term=[elaboration], Sec=(partition)} The procedure System.RPC.Establish_RPC_Receiver is called once, immediately after elaborating the library units of an active partition (that is, right after the @i{elaboration of the partition}) if the partition includes an RCI library unit, but prior to invoking the main subprogram, if any. The Partition parameter is the Partition_Id of the active partition being elaborated. @Defn{RPC-receiver} The Receiver parameter designates an implementation-provided procedure called the @i{RPC-receiver} which will handle all RPCs received by the partition from the PCS. Establish_RPC_Receiver saves a reference to the RPC-receiver; when a message is received at the called partition, the RPC-receiver is called with the Params stream containing the message. When the RPC-receiver returns, the contents of the stream designated by Result is placed in a message and sent back to the calling partition. @begin{ImplNote} It is defined by the PCS implementation whether one or more threads of control should be available to process incoming messages and to wait for their completion. @end{ImplNote} @begin{ImplNote} At link-time, the linker provides the RPC-receiver and the necessary tables to support it. A call on Establish_RPC_Receiver is inserted just before the call on the main subprogram. @end{ImplNote} @begin{Reason} The interface between the PCS (the System.RPC package) and the RPC-receiver is defined to be dynamic in order to allow the elaboration sequence to notify the PCS that all packages have been elaborated and that it is safe to call the receiving stubs. It is not guaranteed that the PCS units will be the last to be elaborated, so some other indication that elaboration is complete is needed. @end{Reason} If a call on Do_RPC is aborted, a cancellation message is sent to the called partition, to request that the execution of the remotely called subprogram be aborted. @begin{Honest} The full effects of this message are dependent on the implementation of the PCS. @end{Honest} @PDefn2{Term=[potentially blocking operation],Sec=(RPC operations)} @PDefn2{Term=[blocking, potentially],Sec=(RPC operations)} The subprograms declared in System.RPC are potentially blocking operations. @end{RunTime} @begin{ImplReq} The implementation of the RPC-receiver shall be reentrant@Redundant[, thereby allowing concurrent calls on it from the PCS to service concurrent remote subprogram calls into the partition]. @begin{Reason} There seems no reason to allow the implementation of RPC-receiver to be nonreentrant, even though we don't require that every implementation of the PCS actually perform concurrent calls on the RPC-receiver. @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[1],Text=[An implementation shall not restrict the replacement of the body of System.RPC. An implementation shall not restrict children of System.RPC. @Redundant[The related implementation permissions in the introduction to Annex A do not apply.]]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The point of System.RPC is to let the user tailor the communications mechanism without requiring changes to or other cooperation from the compiler. However, implementations can restrict the replacement of language-defined units. This requirement overrides that permission for System.RPC.]} @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[1],Text=[If the implementation of System.RPC is provided by the user, an implementation shall support remote subprogram calls as specified.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00273-01]} @ChgAdded{Version=[2],Text=[If the implementation takes advantage of the implementation permission to use a different specification for System.RPC, it still needs to use it for remote subprogram calls, and allow the user to replace the body of System.RPC. It just isn't guaranteed to be portable to do so in Ada 2005 - an advantage which was more theoretical than real anyway.]} @end{Discussion} @end{ImplReq} @begin{DocReq} The implementation of the PCS shall document whether the RPC-receiver is invoked from concurrent tasks. If there is an upper limit on the number of such tasks, this limit shall be documented as well, together with the mechanisms to configure it (if this is supported). @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of the PCS.]}]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Whether the RPC-receiver is invoked from concurrent tasks, and if so, the number of such tasks.]}]} @end{DocReq} @begin{ImplPerm} The PCS is allowed to contain implementation-defined interfaces for explicit message passing, broadcasting, etc. Similarly, it is allowed to provide additional interfaces to query the state of some remote partition (given its partition ID) or of the PCS itself, to set timeouts and retry parameters, to get more detailed error status, etc. These additional interfaces should be provided in child packages of System.RPC. @ImplDef{Implementation-defined interfaces in the PCS.} A body for the package System.RPC need not be supplied by the implementation. @begin{Reason} It is presumed that a body for the package System.RPC might be extremely environment specific. Therefore, we do not require that a body be provided by the (compiler) implementation. The user will have to write a body, or acquire one, appropriate for the target environment. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00273-01]} @ChgAdded{Version=[2],Text=[An alternative declaration is allowed for package System.RPC as long as it provides a set of operations that is substantially equivalent to the specification defined in this clause.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Experience has proved that the definition of System.RPC given here is inadequate for interfacing to existing distribution mechanisms (such as CORBA), especially on heterogeneous systems. Rather than mandate a change in the mechanism (which would break existing systems), require implementations to support multiple mechanisms (which is impractical), or prevent the use of Annex E facilities with existing systems (which would be silly), we simply make this facility optional.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[One of the purposes behind System.RPC was that knowledgeable users, rather than compiler vendors, could create this package tailored to their networks. Experience has shown that users get their RPC from vendors anyway; users have not taken advantage of the flexibility provided by this defined interface. Moreover, one could compare this defined interface to requiring Ada compilers to use a defined interface to implement tasking. No one thinks that the latter is a good idea, why should anyone believe that the former is?]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Therefore, this clause is made optional. We considered deleting the clause outright, but we still require that users may replace the package (whatever its interface). Also, it still provides a useful guide to the implementation of this feature.]} @end{Reason} @end{ImplPerm} @begin{ImplAdvice} Whenever possible, the PCS on the called partition should allow for multiple tasks to call the RPC-receiver with different messages and should allow them to block until the corresponding subprogram body returns. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The PCS should allow for multiple tasks to call the RPC-receiver.]}]} The Write operation on a stream of type Params_Stream_Type should raise Storage_Error if it runs out of space trying to write the Item into the stream. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The System.RPC.Write operation should raise Storage_Error if it runs out of space when writing an item.]}]} @begin{ImplNote} An implementation could also dynamically allocate more space as needed, only propagating Storage_Error if the @nt<allocator> it calls raises Storage_Error. This storage could be managed through a controlled component of the stream object, to ensure that it is reclaimed when the stream object is finalized. @end{ImplNote} @end{ImplAdvice} @begin{Notes} The package System.RPC is not designed for direct calls by user programs. It is instead designed for use in the implementation of remote subprograms calls, being called by the calling stubs generated for a remote call interface library unit to initiate a remote call, and in turn calling back to an RPC-receiver that dispatches to the receiving stubs generated for the body of a remote call interface, to handle a remote call received from elsewhere. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00273-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The specification of System.RPC can now be tailored for an implementation. If a program replaces the body of System.RPC with a user-defined body, it might not compile in a given implementation of Ada 2005 (if the specification of System.RPC has been changed).]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the user can replace System.RPC.]} @end{DiffWord95} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/front_matter.mss�����������������������������������������������������0000755�0001752�0001001�00000140245�12273462240�020657� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(frontmatter, root="ada.mss") @comment{$Source: e:\\cvsroot/ARM/Source/front_matter.mss,v $} @comment{$Revision: 1.57 $ $Date: 2006/11/09 06:29:49 $} @ChgNote{Following is a foreword for the consolidated edition of the RM/AARM.} @UnNumberedSection(Foreword to this version of the Ada Reference Manual) @ChgNote{The above has to be manually commented out if creating "original" RMs. We shouldn't need to do that again.} @ChgNote{We needed boilerplate like this to avoid objections from various outside parties. It seems unlikely that the same objections won't be raised again.} @begin{Intro} @begin{NotISO} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The International Standard for the programming language Ada is ISO/IEC 8652:1995(E).]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The Ada Working Group ISO/IEC JTC 1/SC 22/WG 9 is tasked by ISO with the work item to interpret and maintain the International Standard and to produce Technical Corrigenda, as appropriate. The technical work on the International Standard is performed by the Ada Rapporteur Group (ARG) of WG 9. In September 2000, WG 9 approved and forwarded Technical Corrigendum 1 to SC 22 for ISO approval, which was granted in February 2001. Technical Corrigendum 1 was published in June 2001.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[In October 2002, WG 9 approved a schedule and guidelines for the preparation of an Amendment to the International Standard. WG 9 approved the scope of the Amendment in June 2004. In April 2006, WG 9 approved and forwarded the Amendment to SC 22 for approval, which was granted in August 2006. Final ISO/IEC approval is expected by early 2007.]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The Technical Corrigendum lists the individual changes that need to be made to the text of the International Standard to correct errors, omissions or inconsistencies. The corrections specified in Technical Corrigendum 1 are part of the International Standard ISO/IEC 8652:1995(E).]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Similarly, Amendment 1 lists the individual changes that need to be made to the text of the International Standard to add new features as well as correct errors.]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[When ISO published Technical Corrigendum 1, it did not also publish a document that merges the @Chg{Version=[2],New=[changes from the ],Old=[]}Technical Corrigendum @Chg{Version=[2],New=[],Old=[changes ]}into the text of the International Standard.@Chg{Version=[2],New=[ It is not known whether ISO will publish a document that merges the changes from Technical Corrigendum and Amendment 1 into the text of the International Standard.],Old=[]} However, ISO rules require that the project editor for the @Chg{Version=[2],New=[International Standard], Old=[Technical Corrigendum]} be able to produce such a document on demand.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[This version of the Ada Reference Manual is what the project editor would provide to ISO in response to such a request. It incorporates the changes specified in the Technical Corrigendum @Chg{Version=[2],New=[and Amendment ],Old=[]}into the text of ISO/IEC 8652:1995(E). It should be understood that the publication of any ISO document involves changes in general format, boilerplate, headers, etc., as well as a review by professional editors that may introduce editorial changes to the text. This version of the Ada Reference Manual is therefore neither an official ISO document, nor a version guaranteed to be identical to an official ISO document, should ISO decide to reprint the International Standard incorporating an approved Technical Corrigendum@Chg{Version=[2],New=[ and Amendment],Old=[]}. It is nevertheless a best effort to be as close as possible to the technical content of such an updated document. In the case of a conflict between this document and @Chg{Version=[2],New=[Amendment],Old=[Technical Corrigendum]} 1 as approved by ISO (or between this document and @Chg{Version=[2],New=[Technical Corrigendum 1 in the case of paragraphs not changed by Amendment 1; or between this document and ],Old=[]}the original 8652:1995 in the case of paragraphs not changed by @Chg{Version=[2], New=[either Amendment 1 or ],Old=[]}Technical Corrigendum 1), the other documents contain the official text of the International Standard ISO/IEC 8652:1995(E)@Chg{Version=[2],New=[ and its Amendment],Old=[]}.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[As it is very inconvenient to have the Reference Manual for Ada specified in @Chg{Version=[2],New=[three],Old=[two]} documents, this consolidated version of the Ada Reference Manual is made available to the public.],Old=[]} @end{NotISO} @end{Intro} @UnNumberedSection(Foreword) @begin{Intro} ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work. In the field of information technology, ISO and IEC have established a joint technical committee, ISO/IEC JTC 1. Draft International Standards adopted by the joint technical committee are circulated to national bodies for voting. Publication as an International Standard requires approval by at least 75 % of the national bodies casting a vote. International Standard ISO/IEC 8652 was prepared by Joint Technical Committee ISO/IEC JTC 1, @i{Information Technology}. @ChgRef{Version=[2],Kind=[Revised]} This @Chg{Version=[2],New=[consolidated],Old=[second]} edition @Chg{Version=[2], New=[updates],Old=[cancels and replaces]} the @Chg{Version=[2],New=[second],Old=[first]} edition (ISO 8652:@Chg{Version=[2],New=[1995)],Old=[1987), of which it constitutes a technical revision]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above is unofficial wording added just to avoid confusion. If ISO decides to publish a new standard, the above would be replaced by @ldquote@;This third edition cancels and replaces the second edition (ISO 8652:1995), of which it constitutes a technical revision@rdquote. The first three paragraphs in this section also would be replaced by the current ISO boilerplate.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00440-01]} Annexes A to J form an integral part of this International Standard. Annexes K to @Chg{Version=[2],New=[Q],Old=[P]} are for information only. @begin{Discussion} This document is the Annotated Ada Reference Manual (AARM). It contains the entire text of the Ada 95 standard (ISO/IEC 8652:1995), plus various annotations. It is intended primarily for compiler writers, validation test writers, and other language lawyers. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. @end{Discussion} @end{Intro} @begin{Comment} (*Was Syntax9XOnly - We don't generate this document anymore*) This document lists the syntax rules of Ada 95. @end{Comment} @begin{Comment} (*Was Chg839XOnly - We don't generate this document anymore*) This document lists in detail the changes introduced in the second (Ada 95) edition of the Ada standard (ISO/IEC 8652:1995) with respect to the first (Ada 83) edition (ISO 8652:1987). @end{Comment} @UnNumberedSection{Introduction} @begin{Intro} @begin{AARMOnly} This is the Annotated Ada Reference Manual. @end{AARMOnly} @begin{RMOnly} This is the Ada Reference Manual. @end{RMOnly} @Leading@;Other available Ada documents include: @comment{We have to put the itemize inside of the AARMOnly, because otherwise the formatter thinks this is a nested bullet, making a mess. Since this is the only place this is used, it is easier to fix the text than the program. RLB - 2000-05-17} @begin{AARMOnly} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[Ada 95 Rationale. This],Old=[Rationale for the Ada Programming Language @em 1995 edition, which]} gives an introduction to the new features of Ada@Chg{Version=[2],New=[ incorporated in the 1995 edition of this Standard],Old=[]}, and explains the rationale behind them. Programmers @Chg{Version=[2],New=[unfamiliar with Ada 95 ], Old=[]}should read this first. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Text=[Ada 2005 Rationale. This gives an introduction to the changes and new features in Ada 2005 (compared with the 1995 edition), and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth.]} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Changes to Ada @em 1987 to 1995. This document lists in detail the changes made to the 1987 edition of the standard.]} The Ada Reference Manual (RM). This is the International Standard @em ISO/IEC 8652:1995. @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Technical Corrigendum 1 @em ISO/IEC 8652:1995:COR.1:2001. This document lists corrections to the International Standard.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Amendment 1 @em ISO/IEC 8652:1995:AMD.1:2007. This document outlines additional features and corrections to the International Standard.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The consolidated Ada Reference Manual. An @i{unofficial} document combining the above three documents into a single document.]} @end{Itemize} @end{AARMOnly} @begin{RMOnly} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[Ada 95 Rationale. This],Old=[Rationale for the Ada Programming Language @em 1995 edition, which]} gives an introduction to the new features of Ada@Chg{Version=[2],New=[ incorporated in the 1995 edition of this Standard],Old=[]}, and explains the rationale behind them. Programmers @Chg{Version=[2],New=[unfamiliar with Ada 95 ],Old=[]}should read this first. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Text=[Ada 2005 Rationale. This gives an introduction to the changes and new features in Ada 2005 (compared with the 1995 edition), and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth.]} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1], Text=[Changes to Ada @em 1987 to 1995. This document lists in detail the changes made to the 1987 edition of the standard.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} The Annotated Ada Reference Manual (AARM).@Defn{Annotated Ada Reference Manual} @Defn{AARM}The AARM contains all of the text in @Chg{Version=[2],New=[the consolidated Ada Reference Manual],Old=[the RM95]}, @ChgNote{John had "this International Standard", but it's really related to the unofficial document. Change it back if ISO decides to publish this consolidated RM.} plus various annotations. It is intended primarily for compiler writers, validation test writers, and others who wish to study the fine details. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. @end{Itemize} @end{RMOnly} @end{Intro} @SubHeading(Design Goals) @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} Ada was originally designed with three overriding concerns: program reliability and maintenance, programming as a human activity, and efficiency. @Chg{Version=[2],New=[The 1995],Old=[This]} revision to the language was designed to provide greater flexibility and extensibility, additional control over storage management and synchronization, and standardized packages oriented toward supporting important application areas, while at the same time retaining the original emphasis on reliability, maintainability, and efficiency.@Chg{Version=[2],New=[ This amended version provides further flexibility and adds more standardized packages within the framework provided by the 1995 revision.],Old=[]} The need for languages that promote reliability and simplify maintenance is well established. Hence emphasis was placed on program readability over ease of writing. For example, the rules of the language require that program variables be explicitly declared and that their type be specified. Since the type of a variable is invariant, compilers can ensure that operations on variables are compatible with the properties intended for objects of the type. Furthermore, error-prone notations have been avoided, and the syntax of the language avoids the use of encoded forms in favor of more English-like constructs. Finally, the language offers support for separate compilation of program units in a way that facilitates program development and maintenance, and which provides the same degree of checking between units as within a unit. Concern for the human programmer was also stressed during the design. Above all, an attempt was made to keep to a relatively small number of underlying concepts integrated in a consistent and systematic way while continuing to avoid the pitfalls of excessive involution. The design especially aims to provide language constructs that correspond intuitively to the normal expectations of users. Like many other human activities, the development of programs is becoming ever more decentralized and distributed. Consequently, the ability to assemble a program from independently produced software components continues to be a central idea in the design. The concepts of packages, of private types, and of generic units are directly related to this idea, which has ramifications in many other aspects of the language. An allied concern is the maintenance of programs to match changing requirements; type extension and the hierarchical library enable a program to be modified while minimizing disturbance to existing tested and trusted components. No language can avoid the problem of efficiency. Languages that require over-elaborate compilers, or that lead to the inefficient use of storage or execution time, force these inefficiencies on all machines and on all programs. Every construct of the language was examined in the light of present implementation techniques. Any proposed construct whose implementation was unclear or that required excessive machine resources was rejected. @end{Intro} @SubHeading{Language Summary} @begin{Intro} An Ada program is composed of one or more program units. Program units may be subprograms (which define executable algorithms), packages (which define collections of entities), task units (which define concurrent computations), protected units (which define operations for the coordinated sharing of data between tasks), or generic units (which define parameterized forms of packages and subprograms). Each program unit normally consists of two parts: a specification, containing the information that must be visible to other units, and a body, containing the implementation details, which need not be visible to other units. Most program units can be compiled separately. This distinction of the specification and body, and the ability to compile units separately, allows a program to be designed, written, and tested as a set of largely independent software components. An Ada program will normally make use of a library of program units of general utility. The language provides means whereby individual organizations can construct their own libraries. All libraries are structured in a hierarchical manner; this enables the logical decomposition of a subsystem into individual components. The text of a separately compiled program unit must name the library units it requires. @keepnext@i(Program Units) A subprogram is the basic unit for expressing an algorithm. There are two kinds of subprograms: procedures and functions. A procedure is the means of invoking a series of actions. For example, it may read data, update variables, or produce some output. It may have parameters, to provide a controlled means of passing information between the procedure and the point of call. A function is the means of invoking the computation of a value. It is similar to a procedure, but in addition will return a result. A package is the basic unit for defining a collection of logically related entities. For example, a package can be used to define a set of type declarations and associated operations. Portions of a package can be hidden from the user, thus allowing access only to the logical properties expressed by the package specification. Subprogram and package units may be compiled separately and arranged in hierarchies of parent and child units giving fine control over visibility of the logical properties and their detailed implementation. A task unit is the basic unit for defining a task whose sequence of actions may be executed concurrently with those of other tasks. Such tasks may be implemented on multicomputers, multiprocessors, or with interleaved execution on a single processor. A task unit may define either a single executing task or a task type permitting the creation of any number of similar tasks. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A protected unit is the basic unit for defining protected operations for the coordinated use of data shared between tasks. Simple mutual exclusion is provided automatically, and more elaborate sharing protocols can be defined. A protected operation can either be a subprogram or an entry. A protected entry specifies a Boolean expression (an entry barrier) that must be @Chg{Version=[2],New=[True],Old=[true]} before the body of the entry is executed. A protected unit may define a single protected object or a protected type permitting the creation of several similar objects. @keepnext@i(Declarations and Statements) The body of a program unit generally contains two parts: a declarative part, which defines the logical entities to be used in the program unit, and a sequence of statements, which defines the execution of the program unit. The declarative part associates names with declared entities. For example, a name may denote a type, a constant, a variable, or an exception. A declarative part also introduces the names and parameters of other nested subprograms, packages, task units, protected units, and generic units to be used in the program unit. The sequence of statements describes a sequence of actions that are to be performed. The statements are executed in succession (unless a transfer of control causes execution to continue from another place). An assignment statement changes the value of a variable. A procedure call invokes execution of a procedure after associating any actual parameters provided at the call with the corresponding formal parameters. Case statements and if statements allow the selection of an enclosed sequence of statements based on the value of an expression or on the value of a condition. The loop statement provides the basic iterative mechanism in the language. A loop statement specifies that a sequence of statements is to be executed repeatedly as directed by an iteration scheme, or until an exit statement is encountered. A block statement comprises a sequence of statements preceded by the declaration of local entities used by the statements. Certain statements are associated with concurrent execution. A delay statement delays the execution of a task for a specified duration or until a specified time. An entry call statement is written as a procedure call statement; it requests an operation on a task or on a protected object, blocking the caller until the operation can be performed. A called task may accept an entry call by executing a corresponding accept statement, which specifies the actions then to be performed as part of the rendezvous with the calling task. An entry call on a protected object is processed when the corresponding entry barrier evaluates to true, whereupon the body of the entry is executed. The requeue statement permits the provision of a service as a number of related activities with preference control. One form of the select statement allows a selective wait for one of several alternative rendezvous. Other forms of the select statement allow conditional or timed entry calls and the asynchronous transfer of control in response to some triggering event. Execution of a program unit may encounter error situations in which normal program execution cannot continue. For example, an arithmetic computation may exceed the maximum allowed value of a number, or an attempt may be made to access an array component by using an incorrect index value. To deal with such error situations, the statements of a program unit can be textually followed by exception handlers that specify the actions to be taken when the error situation arises. Exceptions can be raised explicitly by a raise statement. @keepnext@i(Data Types) Every object in the language has a type, which characterizes a set of values and a set of applicable operations. The main classes of types are elementary types (comprising enumeration, numeric, and access types) and composite types (including array and record types). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00387-01]} An enumeration type defines an ordered set of distinct enumeration literals, for example a list of states or an alphabet of characters. The enumeration types Boolean, Character, @Chg{Version=[2],New=[], Old=[and ]}Wide_Character@Chg{Version=[2],New=[, and Wide_Wide_Character], Old=[]} are predefined. Numeric types provide a means of performing exact or approximate numerical computations. Exact computations use integer types, which denote sets of consecutive integers. Approximate computations use either fixed point types, with absolute bounds on the error, or floating point types, with relative bounds on the error. The numeric types Integer, Float, and Duration are predefined. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00387-01]} Composite types allow definitions of structured objects with related components. The composite types in the language include arrays and records. An array is an object with indexed components of the same type. A record is an object with named components of possibly different types. Task and protected types are also forms of composite types. The array types String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2], New=[, and Wide_Wide_String],Old=[]} are predefined. Record, task, and protected types may have special components called discriminants which parameterize the type. Variant record structures that depend on the values of discriminants can be defined within a record type. Access types allow the construction of linked data structures. A value of an access type represents a reference to an object declared as aliased or to an object created by the evaluation of an allocator. Several variables of an access type may designate the same object, and components of one object may designate the same or other objects. Both the elements in such linked data structures and their relation to other elements can be altered during program execution. Access types also permit references to subprograms to be stored, passed as parameters, and ultimately dereferenced as part of an indirect call. Private types permit restricted views of a type. A private type can be defined in a package so that only the logically necessary properties are made visible to the users of the type. The full structural details that are externally irrelevant are then only available within the package and any child units. From any type a new type may be defined by derivation. A type, together with its derivatives (both direct and indirect) form a derivation class. Class-wide operations may be defined that accept as a parameter an operand of any type in a derivation class. For record and private types, the derivatives may be extensions of the parent type. Types that support these object-oriented capabilities of class-wide operations and type extension must be tagged, so that the specific type of an operand within a derivation class can be identified at run time. When an operation of a tagged type is applied to an operand whose specific type is not known until run time, implicit dispatching is performed based on the tag of the operand. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Text=[ Interface types provide abstract models from which other interfaces and types may be composed and derived. This provides a reliable form of multiple inheritance. Interface types may also be implemented by task types and protected types thereby enabling concurrent programming and inheritance to be merged.]} The concept of a type is further refined by the concept of a subtype, whereby a user can constrain the set of allowed values of a type. Subtypes can be used to define subranges of scalar types, arrays with a limited set of index values, and records and private types with particular discriminant values. @keepnext@i(Other Facilities) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[Aspect],Old=[Representation]} clauses can be used to specify the mapping between types and features of an underlying machine. For example, the user can specify that objects of a given type must be represented with a given number of bits, or that the components of a record are to be represented using a given storage layout. Other features allow the controlled use of low level, nonportable, or implementation-dependent aspects, including the direct insertion of machine code. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} The predefined environment of the language provides for input-output and other capabilities @Chg{Version=[2],New=[],Old=[(such as string manipulation and random number generation) ]}by means of standard library packages. Input-output is supported for values of user-defined as well as of predefined types. Standard means of representing values in display form are also provided.@Chg{Version=[2],New=[],Old=[ Other standard library packages are defined in annexes of the standard to support systems with specialized requirements.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[The predefined standard library packages provide facilities such as string manipulation, containers of various kinds (vectors, lists, maps, etc.), mathematical functions, random number generation, and access to the execution environment.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[The specialized annexes define further predefined library packages and facilities with emphasis on areas such as real-time scheduling, interrupt handling, distributed systems, numerical computation, and high-integrity systems.],Old=[]} Finally, the language provides a powerful means of parameterization of program units, called generic program units. The generic parameters can be types and subprograms (as well as objects and packages) and so allow general algorithms and data structures to be defined that are applicable to all types of a given class. @end{Intro} @SubHeading{Language Changes} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Leading@;This @Chg{Version=[2],New=[amended ],Old=[]}International Standard @Chg{Version=[2],New=[updates the edition of 1995 which replaced], Old=[International Standard replaces]} the first edition of 1987. In @Chg{Version=[2],New=[the 1995],Old=[this]} edition, the following major language changes @Chg{Version=[2],New=[were],Old=[have been]} incorporated: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} Support for standard 8-bit and 16-bit character@Chg{Version=[2],New=[s was added],Old=[ sets]}. See @Chg{Version=[2],New=[clauses @RefSecNum{Character Set}],Old=[Section 2]}, @RefSecNum{Character Types}, @RefSecNum{String Types}, @RefSecNum{The Package Standard}, @RefSecNum{Character Handling}, and @RefSecNum{String Handling}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[The type model was extended to include facilities for o],Old=[O]}bject-oriented programming with @Chg{Version=[2],New=[dynamic],Old=[run-time]} polymorphism. See the discussions of classes, derived types, tagged types, record extensions, and private extensions in clauses @RefSecNum{Derived Types and Classes}, @RefSecNum{Tagged Types and Type Extensions}, and @RefSecNum{Private Types and Private Extensions}. @Chg{Version=[2],New=[Additional],Old=[See also the new]} forms of generic formal parameters @Chg{Version=[2],New=[were],Old=[that are]} allowed @Chg{Version=[2],New=[as described in clauses @RefSecNum{Formal Private and Derived Types} and @RefSecNum{Formal Packages}], Old=[by @RefSec{Formal Private and Derived Types} and @RefSec{Formal Packages}]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} Access types @Chg{Version=[2],New=[were],Old=[have been]} extended to allow an access value to designate a subprogram or an object declared by an object declaration @Chg{Version=[2],New=[],Old=[(]}as opposed to just @Chg{Version=[2],New=[an object ],Old=[a heap-]}allocated @Chg{Version=[2],New=[on a heap],Old=[object)]}. See @Chg{Version=[2],New=[clause ],Old=[]}@RefSecNum{Access Types}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} Efficient data-oriented synchronization @Chg{Version=[2],New=[was], Old=[is]} provided @Chg{Version=[2],New=[by the introduction of], Old=[via]} protected types. See @Chg{Version=[2], New=[clause @RefSecNum{Protected Units and Protected Objects}],Old=[Section 9]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} The library @Chg{Version=[2],New=[structure was extended to allow library units to],Old=[units of a library may]} be organized into a hierarchy of parent and child units. See @Chg{Version=[2], New=[clause @RefSecNum{Separate Compilation}], Old=[Section 10]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} Additional support @Chg{Version=[2],New=[was],Old=[has been]} added for interfacing to other languages. See @RefSecNum{Interface to Other Languages}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @leading@;The Specialized Needs Annexes @Chg{Version=[2],New=[were],Old=[have been]} added to provide specific support for certain application areas: @begin{InnerItemize} @RefSec{Systems Programming} @RefSec{Real-Time Systems} @RefSec{Distributed Systems} @RefSec{Information Systems} @RefSec{Numerics} @RefSec{High Integrity Systems} @end{InnerItemize} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Text=[Amendment 1 modifies the 1995 International Standard by making changes and additions that improve the capability of the language and the reliability of programs written in the language. In particular the changes were designed to improve the portability of programs, interfacing to other languages, and both the object-oriented and real-time capabilities.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following significant changes with respect to the 1995 edition are incorporated:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[Support for program text is extended to cover the entire ISO/IEC 10646:2003 repertoire. Execution support now includes the 32-bit character set. See clauses @RefSecNum{Character Set}, @RefSecNum{Character Types}, @RefSecNum{String Types}, @RefSecNum{The Package Standard}, @RefSecNum{Character Handling}, and @RefSecNum{String Handling}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The object-oriented model has been improved by the addition of an interface facility which provides multiple inheritance and additional flexibility for type extensions. See clauses @RefSecNum{Derived Types and Classes}, @RefSecNum{Tagged Types and Type Extensions}, and @RefSecNum{Private Types and Private Extensions}. An alternative notation for calling operations more akin to that used in other languages has also been added. See clause @RefSecNum{Selected Components}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ Access types have been further extended to unify properties such as the ability to access constants and to exclude null values. See clause @RefSecNum{Access Types}. Anonymous access types are now permitted more freely and anonymous access-to-subprogram types are introduced. See clauses @RefSecNum{Objects and Named Numbers}, @RefSecNum{Array Types}, @RefSecNum{Access Types}, and @RefSecNum{Object Renaming Declarations}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The control of structure and visibility has been enhanced to permit mutually dependent references between units and finer control over access from the private part of a package. See clauses @RefSecNum{Incomplete Type Declarations} and @RefSecNum{Context Clauses - With Clauses}. In addition, limited types have been made more useful by the provision of aggregates, constants, and constructor functions. See clauses @RefSecNum{Aggregates}, @RefSecNum{Return Statements}, and @RefSecNum{Limited Types}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The predefined environment has been extended to include additional time and calendar operations, improved string handling, a comprehensive container library, file and directory management, and access to environment variables. See clauses @RefSecNum{Formatting, Time Zones, and other operations for Time}, @RefSecNum{String Handling}, @RefSecNum{The Package Directories}, @RefSecNum{The Package Environment_Variables}, and @RefSecNum{Containers}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ Two of the Specialized Needs Annexes have been considerably enhanced:],Old=[]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The Real-Time Systems Annex now includes the Ravenscar profile for high-integrity systems, further dispatching policies such as Round Robin and Earliest Deadline First, support for timing events, and support for control of CPU time utilization. See clauses @RefSecNum{Priority Scheduling}, @RefSecNum{Run-time Profiles}, @RefSecNum{Execution Time}, and @RefSecNum{Timing Events}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The Numerics Annex now includes support for real and complex vectors and matrices as previously defined in ISO/IEC 13813:1997 plus further basic operations for linear algebra. See clause @RefSecNum{Vector and Matrix Manipulation}.],Old=[]} @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The overall reliability of the language has been enhanced by a number of improvements. These include new syntax which detects accidental overloading, as well as pragmas for making assertions and giving better control over the suppression of checks. See clauses @RefSecNum{Subprogram Declarations}, @RefSecNum{Pragmas Assert and Assertion_Policy}, and @RefSecNum{Suppressing Checks}.],Old=[]} @end{Itemize} @end{Intro} @NewPage @SubHeading(Instructions for Comment Submission) @begin{Intro} @ChgRef{Version=[1],Kind=[Revised]} @Defn{instructions for comment submission} @Defn{comments, instructions for submission} Informal comments on this International Standard may be sent via e-mail to @Chg{New=[@b(ada-comment@@ada-auth.org)], Old=[@b(ada-comment@@sw-eng.falls-church.va.us)]}. If appropriate, the Project Editor will initiate the defect correction procedure. Comments should use the following format: @begin(display) @ChgRef{Version=[2],Kind=[Revised]} @TabSet(L6)@\@b(!topic) @i[Title summarizing comment] @\@b(!reference) @Chg{Version=[2],New=[Ada 2005 RM],Old=[RM95-]}@i{ss.ss(pp)} @\@b(!from) @i{Author Name yy-mm-dd} @\@b(!keywords) @i{keywords related to topic} @\@b(!discussion) @comment{Blank line} @\@i{text of discussion} @end(display) where @i(ss.ss) is the section, clause or subclause number, @i(pp) is the paragraph number where applicable, and @i(yy-mm-dd) is the date the comment was sent. The date is optional, as is the @b(!keywords) line. @ChgRef{Version=[1],Kind=[Revised]} @Chg{New=[], Old=[Multiple comments per e-mail message are acceptable.]} Please use a descriptive @lquotes@;Subject@rquotes@; in your e-mail message@Chg{New=[, and limit each message to a single comment.], Old=[.]} When correcting typographical errors or making minor wording suggestions, please put the correction directly as the topic of the comment; use square brackets [ ] to indicate text to be omitted and curly braces { } to indicate text to be added, and provide enough context to make the nature of the suggestion self-evident or put additional information in the body of the comment, for example: @begin{Display} @TabSet(L6)@\@b(!topic) [c]{C}haracter @\@b(!topic) it[']s meaning is not defined @end{Display} Formal requests for interpretations and for reporting defects in this International Standard may be made in accordance with the ISO/IEC JTC 1 Directives and the ISO/IEC JTC 1/SC 22 policy for interpretations. National Bodies may submit a Defect Report to ISO/IEC JTC 1/SC 22 for resolution under the JTC 1 procedures. A response will be provided and, if appropriate, a Technical Corrigendum will be issued in accordance with the procedures. @end{Intro} @begin{NotISO} @NewPage @SubHeading(Acknowledgements@Chg{Version=[2],New=[ for the Ada 95 edition of the Ada Reference Manual],Old=[]}) @begin{Intro} This International Standard was prepared by the Ada 9X Mapping/Revision Team based at Intermetrics, Inc., which has included: W. Carlson, Program Manager; T. Taft, Technical Director; J. Barnes (consultant); B. Brosgol (consultant); R. Duff (Oak Tree Software); M. Edwards; C. Garrity; R. Hilliard; O. Pazy (consultant); D. Rosenfeld; L. Shafer; W. White; M. Woodger. The following consultants to the Ada 9X Project contributed to the Specialized Needs Annexes: T. Baker (Real-Time/Systems Programming @em SEI, FSU); K. Dritz (Numerics @em Argonne National Laboratory); A. Gargaro (Distributed Systems @em Computer Sciences); J. Goodenough (Real-Time/Systems Programming @em SEI); J. McHugh (Secure Systems @em consultant); B. Wichmann (Safety-Critical Systems @em NPL: UK). This work was regularly reviewed by the Ada 9X Distinguished Reviewers and the members of the Ada 9X Rapporteur Group (XRG): E. Ploedereder, Chairman of DRs and XRG (University of Stuttgart: Germany); B. Bardin (Hughes); J. Barnes (consultant: UK); @Comment{XRG - UK} B. Brett (DEC); B. Brosgol (consultant); R. Brukardt (RR Software); N. Cohen (IBM); R. Dewar (NYU); G. Dismukes (TeleSoft); A. Evans (consultant); A. Gargaro (Computer Sciences); M. Gerhardt (ESL); J. Goodenough (SEI); @Comment{Also XRG - U.S.} S. Heilbrunner (University of Salzburg: Austria); @Comment{Also XRG - Belgium} P. Hilfinger (UC/Berkeley); @Comment{No longer a DR.} B. K@latin1(228)llberg (CelsiusTech: Sweden); @Comment{XRG - Sweden} M. Kamrad II (Unisys); J. van Katwijk (Delft University of Technology: The Netherlands); @Comment{XRG - The Netherlands} V. Kaufman (Russia); @Comment{XRG - Russia} P. Kruchten (Rational); @Comment{Also XRG - France} R. Landwehr (CCI: Germany); @Comment{Also XRG - Germany} C. Lester (Portsmouth Polytechnic: UK); L. M@latin1(229)nsson (TELIA Research: Sweden); @Comment{No longer a DR.} S. Michell (Multiprocessor Toolsmiths: Canada); @Comment{Also XRG - Canada} M. Mills (US Air Force); D. Pogge (US Navy); K. Power (Boeing); O. Roubine (Verdix: France); A. Strohmeier (Swiss Fed Inst of Technology: Switzerland); @Comment{XRG - Switzerland} W. Taylor (consultant: UK); J. Tokar (Tartan); E. Vasilescu (Grumman); J. Vladik (Prospeks s.r.o.: Czech Republic); @Comment{XRG - Czech Republic} S. Van Vlierberghe (OFFIS: Belgium). @Comment{XRG - Belgium} Other valuable feedback influencing the revision process was provided by the Ada 9X Language Precision Team (Odyssey Research Associates), the Ada 9X User/Implementer Teams (AETECH, Tartan, TeleSoft), the Ada 9X Implementation Analysis Team (New York University) and the Ada community-at-large. Special thanks go to R. Mathis, Convenor of ISO/IEC JTC 1/SC 22 Working Group 9. @Comment{Also XRG - U.S.} The Ada 9X Project was sponsored by the Ada Joint Program Office. Christine M. Anderson at the Air Force Phillips Laboratory (Kirtland AFB, NM) was the project manager. @AddedSubHeading{Version=[1],Acknowledgements for the Corrigendum version of the Ada Reference Manual} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=<The editor [R. Brukardt (USA)] would like to thank the many people whose hard work and assistance has made this revision possible.>,Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Thanks go out to all of the members of the ISO/IEC JTC 1/SC 22/WG 9 Ada Rapporteur Group, whose work on creating and editing the wording corrections was critical to the entire process. Especially valuable contributions came from the chairman of the ARG, E. Ploedereder (Germany), who kept the process moving; J. Barnes (UK) and K. Ishihata (Japan), whose extremely detailed reviews kept the editor on his toes; G. Dismukes (USA), M. Kamrad (USA), P. Leroy (France), S. Michell (Canada), T. Taft (USA), J. Tokar (USA), and other members too numerous to mention.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Special thanks go to R. Duff (USA) for his explanations of the previous system of formatting of these documents during the tedious conversion to more modern formats. Special thanks also go to the convener of ISO/IEC JTC 1/SC 22/WG 9, J. Moore (USA), without whose help and support the corrigendum and this consolidated reference manual would not have been possible.],Old=[]} @AddedSubHeading{Version=[2],Acknowledgements for the Amendment version of the Ada Reference Manual} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=<The editor [R. Brukardt (USA)] would like to thank the many people whose hard work and assistance has made this revision possible.>,Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Thanks go out to all of the members of the ISO/IEC JTC 1/SC 22/WG 9 Ada Rapporteur Group, whose work on creating and editing the wording corrections was critical to the entire process. Especially valuable contributions came from the chairman of the ARG, P. Leroy (France), who kept the process on schedule; J. Barnes (UK) whose careful reviews found many typographical errors; T. Taft (USA), who always seemed to have a suggestion when we were stuck, and who also was usually able to provide the valuable service of explaining why things were as they are; S. Baird (USA), who found many obscure problems with the proposals; and A. Burns (UK), who pushed many of the real-time proposals to completion. Other ARG members who contributed were: R. Dewar (USA), G. Dismukes (USA), R. Duff (USA), K. Ishihata (Japan), S. Michell (Canada), E. Ploedereder (Germany), J.P. Rosen (France), E. Schonberg (USA), J. Tokar (USA), and T. Vardanega (Italy).]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[Special thanks go to Ada-Europe and the Ada Resource Association, without whose help and support the Amendment and this consolidated reference manual would not have been possible. M. Heaney (USA) requires special thanks for his tireless work on the containers packages. Finally, special thanks go to the convener of ISO/IEC JTC 1/SC 22/WG 9, J. Moore (USA), who guided the document through the standardization process.],Old=[]} @end{Intro} @NewPage @SubHeading{Changes} @begin{Intro} @Leading@;The International Standard is the same as this version of the Reference Manual, except: @begin{Itemize} This list of Changes is not included in the International Standard. The @lquotes@;Acknowledgements@rquotes@; page is not included in the International Standard. The text in the running headers and footers on each page is slightly different in the International Standard. The title page(s) are different in the International Standard. This document is formatted for 8.5-by-11-inch paper, whereas the International Standard is formatted for A4 paper (210-by-297mm); thus, the page breaks are in different places. @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[The @lquotes@;Foreword to this version of the Ada Reference Manual@rquotes clause is not included in the International Standard.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[The @lquotes@;Using this version of the Ada Reference Manual@rquotes clause is not included in the International Standard.],Old=[]} @end{Itemize} @end{Intro} @end{NotISO} @begin{NotISO} @begin{Intro} @AddedSubHeading{Version=[1],Using this version of the Ada Reference Manual} @begin{RMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[This document has been revised with the corrections specified in Technical Corrigendum 1 (ISO/IEC 8652:1995/COR.1:2001)@Chg{Version=[2],New=[ and Amendment 1 (ISO/IEC 8652/AMD.1:2007)],Old=[]}. In addition, a variety of editorial errors have been corrected.],Old=[]} @end{RMOnly} @begin{AARMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[This document has been revised with the corrections specified in Technical Corrigendum 1 (ISO/IEC 8652:1995/COR.1:2001)@Chg{Version=[2],New=[ and Amendment 1 (ISO/IEC 8652/AMD.1:2007)],Old=[]}. In addition, additional annotations have been added and a variety of editorial errors have been corrected.],Old=[]} @end{AARMOnly} @begin{RMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[Changes to the original 8652:1995 can be identified by the version number @Chg{Version=[2],New=[],Old=[/1 ]}following the paragraph number.@Chg{Version=[2],New=[ Paragraphs with a version number of /1 were changed by Technical Corrigendum 1 or were editorial corrections at that time, while paragraphs with a version number of /2 were changed by Amendment 1 or were more recent editorial corrections.],Old=[]} Paragraphs not so marked are unchanged by @Chg{Version=[2],New=[Amendment 1, ],Old=[]}Technical Corrigendum 1@Chg{Version=[2],New=[,],Old=[]} or editorial corrections. Paragraph numbers of unchanged paragraphs are the same as in the original Ada Reference Manual. In addition, some versions of this document include revision bars near the paragraph numbers. Where paragraphs are inserted, the paragraph numbers are of the form pp.nn, where pp is the number of the preceding paragraph, and nn is an insertion number. For instance, the first paragraph inserted after paragraph 8 is numbered 8.1, the second paragraph inserted is numbered 8.2, and so on. Deleted paragraphs are indicated by the text @i{@shrink{This paragraph was deleted.}} Deleted paragraphs include empty paragraphs that were numbered in the original Ada Reference Manual.],Old=[]} @end{RMOnly} @begin{AARMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @Chg{New=[Changes to the original 8652:1995 can be identified by the version number @Chg{Version=[2],New=[],Old=[/1 ]}following the paragraph number.@Chg{Version=[2],New=[ Paragraphs with a version number of /1 were changed by Technical Corrigendum 1 or were editorial corrections at that time, while paragraphs with a version number of /2 were changed by Amendment 1 or were more recent editorial corrections.],Old=[]} Paragraphs not so marked are unchanged by @Chg{Version=[2],New=[Amendment 1, ],Old=[]}Technical Corrigendum 1@Chg{Version=[2],New=[,],Old=[]} or editorial corrections@Chg{Version=[2],New=[; that is, they are identical to the 1995 version],Old=[]}. Paragraph numbers of unchanged paragraphs are the same as in the original International Standard. Inserted text is indicated by underlining, and deleted text is indicated by strikethroughs. @Chg{Version=[2],New=[Some versions also use color to indicate the version of the change.],Old=[]}Where paragraphs are inserted, the paragraph numbers are of the form pp.nn, where pp is the number of the preceding paragraph, and nn is an insertion number. For instance, the first paragraph inserted after paragraph 8 is numbered 8.1, the second paragraph inserted is numbered 8.2, and so on. Deleted paragraphs are indicated by the text @i{@shrink{This paragraph was deleted.}} Deleted paragraphs include empty paragraphs that were numbered in the original Ada Reference Manual. Similar markings and numbering is used for changes to annotations.],Old=[]} @end{AARMOnly} @end{Intro} @end{NotISO} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/glossary.mss���������������������������������������������������������0000755�0001752�0001001�00000001211�12273462240�020003� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(glossary, Root="ada.mss") @Comment{$Date: 2005/11/24 02:15:07 $} @LabeledInformativeAnnex{Glossary} @comment{$Source: e:\\cvsroot/ARM/Source/glossary.mss,v $} @comment{$Revision: 1.16 $} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00437-01]} @Defn{Glossary} This Annex contains informal descriptions of some @Chg{Version=[2], New=[of the ],Old=[]}terms used in this International Standard. @Chg{Version=[2],New=[The index provides references to more formal definitions of all of the terms used in this International Standard], Old=[To find more formal definitions, look the term up in the index]}. @GlossaryList @end{Intro}���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/impldef.mss����������������������������������������������������������0000755�0001752�0001001�00000006062�12273462240�017571� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(impldef, Root="ada.mss") @Comment{$Date: 2005/05/07 05:18:29 $} @LabeledRevisedInformativeAnnex{Version=[2],New=[Summary of Documentation Requirements],Old=[Implementation-Defined Characteristics]} @comment{$Source: e:\\cvsroot/ARM/Source/impldef.mss,v $} @comment{$Revision: 1.16 $} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{documentation requirements} The Ada language allows for certain target machine dependences in a controlled manner. Each Ada implementation must document many characteristics and properties of the target system. This International Standard contains specific documentation requirements. In addition, many characteristics that require documentation are identified throughout this International Standard as being implementation defined. Finally, this International Standard requires documentation of whether implementation advice is followed. The following clauses provide summaries of these documentation requirements.]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Specific Documentation Requirements]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[documentation requirements], Sec=(summary of requirements)} @Defn{documentation (required of an implementation)} In addition to implementation-defined characteristics, each Ada implementation must document various properties of the implementation:]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Most of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes.]} @end{Ramification} @AddedDocReqList{Version=[2]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Implementation-Defined Characteristics]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised]} @Defn2{Term=[implementation defined], Sec=(summary of characteristics)} The Ada language allows for certain machine dependences in a controlled manner. @Defn{documentation (required of an implementation)} Each Ada implementation must document all implementation-defined characteristics: @begin{Ramification} @Defn{unspecified} @Defn{specified (not!)} It need not document unspecified characteristics. Some of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes. @end{Ramification} @ImplDefList @end{Intro} @LabeledAddedClause{Version=[2],Name=[Implementation Advice]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[implementation advice], Sec=(summary of advice)} @Defn{documentation (required of an implementation)} This International Standard sometimes gives advice about handling certain target machine dependences. Each Ada implementation must document whether that advice is followed:]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Some of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes.]} @end{Ramification} @AddedImplAdviceList{Version=[2]} @end{Intro} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/index.mss������������������������������������������������������������0000755�0001752�0001001�00000002101�12273462240�017246� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(index, Root="ada.mss") @Comment{$Date: 2006/01/17 07:20:58 $} @comment{$Source: e:\\cvsroot/ARM/Source/index.mss,v $} @comment{$Revision: 1.1 $} @UnnumberedSection{Index} @begin{ISOOnly} @noparanum@;Index entries are given by subclause.@Chg{Version=[2],New=[], Old=[ A list of all language-defined library units may be found under Language-Defined Library Units. A list of all language-defined types may be found under Language-Defined Types.@Chg{Version=[2],New=[ A list of all language-defined subprograms may be found under Language-Defined Subprograms.],Old=[]}]} @end{ISOOnly} @begin{NotISO} @noparanum@;Index entries are given by paragraph number.@Chg{Version=[2],New=[], Old=[ A list of all language-defined library units may be found under Language-Defined Library Units. A list of all language-defined types may be found under Language-Defined Types.@Chg{Version=[2],New=[ A list of all language-defined subprograms may be found under Language-Defined Subprograms.],Old=[]}]} @end{NotISO} @noparanum@ @*@Comment{Blank paragraph} @IndexList@Comment{Generate the index} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/infosys.mss����������������������������������������������������������0000755�0001752�0001001�00000152427�12273462240�017652� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/infosys.mss,v $ } @comment{ $Revision: 1.37 $ $Date: 2006/10/18 00:25:26 $ $Author: Randy $ } @Part(infosys, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:26 $} @LabeledNormativeAnnex{Information Systems} @begin{Intro} @Defn{information systems} @Leading@;This Annex provides a set of facilities relevant to Information Systems programming. These fall into several categories: @begin{itemize} an attribute definition clause specifying Machine_Radix for a decimal subtype; the package Decimal, which declares a set of constants defining the implementation's capacity for decimal types, and a generic procedure for decimal division; and @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} the child packages Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]}, which support formatted and localized output of decimal data, based on @lquotes@;picture String@rquotes@; values. @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} See also: @RefSec{Fixed Point Types}; @RefSec{Operations of Fixed Point Types}; @RefSec{Type Conversions}; @RefSec{Operational and Representation Attributes}; @RefSec(Input-Output for Real Types);@Chg{Version=[2], New=[],Old=[@RefSec{Interfacing with COBOL};]} @RefSec{Interfacing with C and C++};@Chg{Version=[2], New=[ @RefSec{Interfacing with COBOL};],Old=[]} @RefSec{Numerics}. The character and string handling packages in @RefSec{Predefined Language Environment} are also relevant for Information Systems. @end{Intro} @begin{ImplAdvice} If COBOL (respectively, C) is widely supported in the target environment, implementations supporting the Information Systems Annex should provide the child package Interfaces.COBOL (respectively, Interfaces.C) specified in @RefSecNum{Interface to Other Languages} and should support a @i{convention_}@nt{identifier} of COBOL (respectively, C) in the interfacing pragmas (see @RefSecNum{Interface to Other Languages}), thus allowing Ada programs to interface with programs written in that language. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If COBOL (respectively, C) is supported in the target environment, then interfacing to COBOL (respectively, C) should be supported as specified in @RefSecNum{Interface to Other Languages}.]}]} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Added a mention of Wide_Wide_Text_IO.Editing, part of the support for 32-bit characters.]} @end{DiffWord95} @LabeledClause{Machine_Radix Attribute Definition Clause} @begin{StaticSem} @PDefn2{Term=[specifiable], Sec=(of Machine_Radix for decimal first subtypes)} @Defn{Machine_Radix clause} Machine_Radix may be specified for a decimal first subtype (see @RefSecNum{Fixed Point Types}) via an @nt{attribute_definition_clause}; the expression of such a clause shall be static, and its value shall be 2 or 10. A value of 2 implies a binary base range; a value of 10 implies a decimal base range. @begin{Ramification} In the absence of a Machine_Radix clause, the choice of 2 versus 10 for S'Machine_Radix is not specified. @end{Ramification} @end{StaticSem} @begin{ImplAdvice} Packed decimal should be used as the internal representation for objects of subtype S when S'Machine_Radix = 10. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Packed decimal should be used as the internal representation for objects of subtype @i<S> when @i<S>'Machine_Radix = 10.]}]} @end{ImplAdvice} @begin{Discussion} The intent of a decimal Machine_Radix attribute definition clause is to allow the programmer to declare an Ada decimal data object whose representation matches a particular COBOL implementation's representation of packed decimal items. The Ada object may then be passed to an interfaced COBOL program that takes a packed decimal data item as a parameter, assuming that convention COBOL has been specified for the Ada object's type in a @nt[pragma] Convention. Additionally, the Ada compiler may choose to generate arithmetic instructions that exploit the packed decimal representation. @end{discussion} @begin{Examples} @Leading@Keepnext@i{Example of Machine_Radix attribute definition clause:} @begin{example} @key[type] Money @key[is] @key[delta] 0.01 @key[digits] 15; @key[for] Money'Machine_Radix @key[use] 10; @end{example} @end{Examples} @LabeledClause{The Package Decimal} @begin{StaticSem} @Leading@Keepnext@;The library package Decimal has the following declaration: @begin{Example} @key(package) Ada.Decimal @key(is)@ChildUnit{Parent=[Ada],Child=[Decimal]} @key(pragma) Pure(Decimal); @AdaObjDefn{Max_Scale} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Min_Scale} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Min_Delta} : @key(constant) := 10.0**(-Max_Scale); @AdaObjDefn{Max_Delta} : @key(constant) := 10.0**(-Min_Scale); @AdaObjDefn{Max_Decimal_Digits} : @key(constant) := @RI{implementation-defined}; @key(generic) @key(type) Dividend_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Divisor_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Quotient_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Remainder_Type @key(is) @key(delta) <> @key(digits) <>; @key(procedure) @AdaSubDefn{Divide} (Dividend : @key(in) Dividend_Type; Divisor : @key(in) Divisor_Type; Quotient : @key(out) Quotient_Type; Remainder : @key(out) Remainder_Type); @key[pragma] Convention(Intrinsic, Divide); @key(end) Ada.Decimal; @end{Example} @ImplDef{The values of named numbers in the package Decimal.} Max_Scale is the largest N such that 10.0**(@en@;N) is allowed as a decimal type's delta. Its type is @i{universal_integer}. Min_Scale is the smallest N such that 10.0**(@en@;N) is allowed as a decimal type's delta. Its type is @i{universal_integer}. Min_Delta is the smallest value allowed for @i{delta} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_real}. Max_Delta is the largest value allowed for @i{delta} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_real}. Max_Decimal_Digits is the largest value allowed for @i{digits} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_integer}. @begin{reason} The name is Max_Decimal_Digits versus Max_Digits, in order to avoid confusion with the named number System.Max_Digits relevant to floating point. @end{reason} @end{StaticSem} @begin{StaticSem} The effect of Divide is as follows. The value of Quotient is Quotient_Type(Dividend/Divisor). The value of Remainder is Remainder_Type(Intermediate), where Intermediate is the difference between Dividend and the product of Divisor and Quotient; this result is computed exactly. @end{StaticSem} @begin(ImplReq) Decimal.Max_Decimal_Digits shall be at least 18. Decimal.Max_Scale shall be at least 18. Decimal.Min_Scale shall be at most 0. @end{ImplReq} @begin(Notes) The effect of division yielding a quotient with control over rounding versus truncation is obtained by applying either the function attribute Quotient_Type'Round or the conversion Quotient_Type to the expression Dividend/Divisor. @end(Notes) @LabeledClause{Edited Output for Decimal Types} @begin{Intro} @Leading@; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The child packages Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]} provide localizable formatted text output, known as @i{edited output}@Defn{edited output}, for decimal types. An edited output string is a function of a numeric value, program-specifiable locale elements, and a format control value. The numeric value is of some decimal type. The locale elements are: @begin{itemize} the currency string; the digits group separator character; the radix mark character; and the fill character that replaces leading zeros of the numeric value. @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} For Text_IO.Editing the edited output and currency strings are of type String, and the locale characters are of type Character. For Wide_@!Text_IO.@!Editing their types are Wide_@!String and Wide_@!Character, respectively.@Chg{Version=[2],New=[ For Wide_Wide_@!Text_IO.@!Editing their types are Wide_Wide_@!String and Wide_Wide_@!Character, respectively.],Old=[]} Each of the locale elements has a default value that can be replaced or explicitly overridden. A format-control value is of the private type Picture; it determines the composition of the edited output string and controls the form and placement of the sign, the position of the locale elements and the decimal digits, the presence or absence of a radix mark, suppression of leading zeros, and insertion of particular character values. @Leading@;A Picture object is composed from a String value, known as a @i{picture String}, that serves as a template for the edited output string, and a Boolean value that controls whether a string of all space characters is produced when the number's value is zero. A picture String comprises a sequence of one- or two-Character symbols, each serving as a placeholder for a character or string at a corresponding position in the edited output string. The picture String symbols fall into several categories based on their effect on the edited output string: @TabClear() @begin{Display} @TabSet{3, 21, 27, 33, 39, 45, 51} @\Decimal Digit: @\'9' @\Radix Control: @\'.' @\'V' @\Sign Control: @\'+' @\'@en@;' @\'<' @\'>' @\"CR" @\"DB" @\Currency Control: @\'$' @\'#' @\Zero Suppression: @\'Z' @\'*' @\Simple Insertion: @\'_' @\'B' @\'0' @\'/' @end{Display} The entries are not case-sensitive. Mixed- or lower-case forms for "CR" and "DB", and lower-case forms for 'V', 'Z', and 'B', have the same effect as the upper-case symbols shown. An occurrence of a '9' Character in the picture String represents a decimal digit position in the edited output string. A radix control Character in the picture String indicates the position of the radix mark in the edited output string: an actual character position for '.', or an assumed position for 'V'. A sign control Character in the picture String affects the form of the sign in the edited output string. The '<' and '>' Character values indicate parentheses for negative values. A Character '+', '@en@;', or '<' appears either singly, signifying a fixed-position sign in the edited output, or repeated, signifying a floating-position sign that is preceded by zero or more space characters and that replaces a leading 0. A currency control Character in the picture String indicates an occurrence of the currency string in the edited output string. The '$' Character represents the complete currency string; the '#' Character represents one character of the currency string. A '$' Character appears either singly, indicating a fixed-position currency string in the edited output, or repeated, indicating a floating-position currency string that occurs in place of a leading 0. A sequence of '#' Character values indicates either a fixed- or floating-position currency string, depending on context. A zero suppression Character in the picture String allows a leading zero to be replaced by either the space character (for 'Z') or the fill character (for '*'). A simple insertion Character in the picture String represents, in general, either itself (if '/' or '0'), the space character (if 'B'), or the digits group separator character (if '_'). In some contexts it is treated as part of a floating sign, floating currency, or zero suppression string. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} An example of a picture String is "<###Z_ZZ9.99>". If the currency string is "@Chg{Version=[2],New=[kr],Old=[FF]}", the separator character is ',', and the radix mark is '.' then the edited output string values for the decimal values 32.10 and @en@;5432.10 are "bb@Chg{Version=[2],New=[kr],Old=[FF]}bbb32.10b" and "(b@Chg{Version=[2],New=[kr],Old=[FF]}5,432.10)", respectively, where 'b' indicates the space character. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The generic packages Text_IO.Decimal_IO@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Decimal_IO@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Decimal_IO],Old=[]} (see @RefSec(Input-Output for Real Types)) provide text input and non-edited text output for decimal types. @end{Intro} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} A picture String is of type Standard.String, @Chg{Version=[2],New=[for all of], Old=[both for]} Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Added descriptions of Wide_Wide_Text_IO.Editing; see @RefSecNum{The Package Wide_Wide_Text_IO.Editing}.]} @end{DiffWord95} @LabeledSubClause{Picture String Formation} @begin{Intro} @Defn2{term=[picture String],sec=[for edited output]} @Defn2{term=[well-formed picture String],sec=[for edited output]} A @i{well-formed picture String}, or simply @i{picture String}, is a String value that conforms to the syntactic rules, composition constraints, and character replication conventions specified in this clause. @end{Intro} @begin{RunTime} @TabClear() @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Display} @ntf{picture_string} ::= @ntf{fixed_$_picture_string} | @ntf{fixed_#_picture_string} | @ntf{floating_currency_picture_string} | @ntf{non_currency_picture_string} @comment{Blank Line} @end{Display} @begin{display} @ntf{fixed_$_picture_string} ::= [@ntf{fixed_LHS_sign}] @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{zero_suppression}] @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] [@ntf{zero_suppression}] @ntf{number} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{floating_LHS_sign} @ntf{number} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{fixed_$_char} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{all_sign_number} {@ntf{direct_insertion}} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_#_picture_string} ::= [@ntf{fixed_LHS_sign}] @ntf{single_#_currency} {@ntf{direct_insertion}} [@ntf{zero_suppression}] @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{multiple_#_currency} {@ntf{direct_insertion}} @ntf{zero_suppression} @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] [@ntf{zero_suppression}] @ntf{number} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{floating_LHS_sign} @ntf{number} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{single_#_currency} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{multiple_#_currency} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{all_sign_number} {@ntf{direct_insertion}} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{floating_currency_picture_string} ::= [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{floating_$_currency} @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{floating_#_currency} @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{all_currency_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{non_currency_picture_string} ::= [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{zero_suppression} @ntf{number} [@ntf{RHS_sign}] | [@ntf{floating_LHS_sign}] @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] | @ntf{all_sign_number} {@ntf{direct_insertion}} | @ntf{fixed_LHS_sign} @ntf{direct_insertion} {@ntf{direct_insertion}} @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_LHS_sign} ::= @ntf{LHS_Sign} @end{display} @begin{display} @ntf{LHS_Sign} ::= + | @en | < @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_$_char} ::= $ @comment{Blank Line} @end{display} @begin{display} @ntf{direct_insertion} ::= @ntf{simple_insertion} @end{display} @begin{display} @ntf{simple_insertion} ::= _ | B | 0 | / @comment{Blank Line} @end{display} @begin{display} @ntf{zero_suppression} ::= Z {Z | @ntf{context_sensitive_insertion}} | @ntf{fill_string} @end{display} @begin{display} @ntf{context_sensitive_insertion} ::= @ntf{simple_insertion} @comment{Blank Line} @end{display} @begin{display} @ntf{fill_string} ::= * {* | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{number} ::= @ntf{fore_digits} [@ntf{radix} [@ntf{aft_digits}] {@ntf{direct_insertion}}] | @ntf{radix} @ntf{aft_digits} {@ntf{direct_insertion}} @end{display} @begin{display} @ntf{fore_digits} ::= 9 {9 | @ntf{direct_insertion}} @end{display} @begin{display} @ntf{aft_digits} ::= {9 | @ntf{direct_insertion}} 9 @end{display} @begin{display} @ntf{radix} ::= . | V @comment{Blank Line} @end{display} @begin{display} @ntf{RHS_sign} ::= + | @en | > | CR | DB @comment{Blank Line} @end{display} @begin{display} @ntf{floating_LHS_sign} ::= @ntf{LHS_Sign} {@ntf{context_sensitive_insertion}} @ntf{LHS_Sign} {@ntf{LHS_Sign} | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{single_#_currency} ::= # @end{display} @begin{display} @ntf{multiple_#_currency} ::= ## {#} @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_#_currency} ::= @ntf{single_#_currency} | @ntf{multiple_#_currency} @comment{Blank Line} @end{display} @begin{display} @ntf{floating_$_currency} ::= $ {@ntf{context_sensitive_insertion}} $ {$ | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{floating_#_currency} ::= # {@ntf{context_sensitive_insertion}} # {# | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{all_sign_number} ::= @ntf{all_sign_fore} [@ntf{radix} [@ntf{all_sign_aft}]] [>] @end{display} @begin{display} @ntf{all_sign_fore} ::= @ntf{sign_char} {@ntf{context_sensitive_insertion}} @ntf{sign_char} {@ntf{sign_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_sign_aft} ::= {@ntf{all_sign_aft_char}} @ntf{sign_char} @comment{Blank Line} @ntf{all_sign_aft_char} ::= @ntf{sign_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @ntf{sign_char} ::= + | @en | < @comment{Blank Line} @end{display} @begin{display} @ntf{all_currency_number} ::= @ntf{all_currency_fore} [@ntf{radix} [@ntf{all_currency_aft}]] @end{display} @begin{display} @ntf{all_currency_fore} ::= @ntf{currency_char} {@ntf{context_sensitive_insertion}} @ntf{currency_char} {@ntf{currency_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_currency_aft} ::= {@ntf{all_currency_aft_char}} @ntf{currency_char} @comment{Blank Line} @ntf{all_currency_aft_char} ::= @ntf{currency_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @ntf{currency_char} ::= $ | # @comment{Blank Line} @end{display} @begin{display} @ntf{all_zero_suppression_number} ::= @ntf{all_zero_suppression_fore} [ @ntf{radix} [@ntf{all_zero_suppression_aft}]] @end{display} @begin{display} @ntf{all_zero_suppression_fore} ::= @ntf{zero_suppression_char} {@ntf{zero_suppression_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_zero_suppression_aft} ::= {@ntf{all_zero_suppression_aft_char}} @ntf{zero_suppression_char} @comment{Blank Line} @ntf{all_zero_suppression_aft_char} ::= @ntf{zero_suppression_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @trailing@ntf{zero_suppression_char} ::= Z | * @end{Display} @Leading@;The following composition constraints apply to a picture String: @begin{Itemize} A @ntf{floating_LHS_sign} does not have occurrences of different @ntf{LHS_Sign} Character values. If a picture String has '<' as @ntf{fixed_LHS_sign}, then it has '>' as @ntf{RHS_sign}. If a picture String has '<' in a @ntf{floating_LHS_sign} or in an @ntf{all_sign_number}, then it has an occurrence of '>'. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0088],ARef=[AI95-00153]} If a picture String has '+' or '@en@;' as @ntf{fixed_LHS_sign}, in a @ntf{floating_LHS_sign}, or in an @ntf{all_sign_number}, then it has no @ntf{RHS_sign}@Chg{New=[ or '>' character],Old=[]}. An instance of @ntf{all_sign_number} does not have occurrences of different @ntf{sign_char} Character values. An instance of @ntf{all_currency_number} does not have occurrences of different @ntf{currency_@!char} Character values. An instance of @ntf{all_zero_suppression_number} does not have occurrences of different @ntf{zero_@!suppression_@!char} Character values, except for possible case differences between 'Z' and 'z'. @end{Itemize} A @i{replicable Character} is a Character that, by the above rules, can occur in two consecutive positions in a picture String. @Leading@;A @i{Character replication} is a String @begin{example} @RI{char} & '(' & @RI{spaces} & @RI{count_string} & ')' @end{example} where @i{char} is a replicable Character, @i{spaces} is a String (possibly empty) comprising only space Character values, and @i{count_string} is a String of one or more decimal digit Character values. A Character replication in a picture String has the same effect as (and is said to be @i{equivalent to}) a String comprising @i[n] consecutive occurrences of @i{char}, where @i[n]=Integer'Value(@i{count_string}). An @i{expanded picture String} is a picture String containing no Character replications. @begin{Discussion} Since 'B' is not allowed after a RHS sign, there is no need for a special rule to disallow "9.99DB(2)" as an abbreviation for "9.99DBB" @end{discussion} @end{RunTime} @begin{Notes} Although a sign to the left of the number can float, a sign to the right of the number is in a fixed position. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0088],ARef=[AI95-00153-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The picture string rules for numbers were tightened.]} @end{DiffWord95} @LabeledSubClause{Edited Output Generation} @begin{RunTime} @Leading@;The contents of an edited output string are based on: @begin{Itemize} A value, Item, of some decimal type Num, An expanded picture String Pic_String, A Boolean value, Blank_When_Zero, A Currency string, A Fill character, A Separator character, and A Radix_Mark character. @end{Itemize} The combination of a True value for Blank_When_Zero and a '*' character in Pic_String is inconsistent; no edited output string is defined. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[Such a Pic_String is invalid, and any attempt to use such a string will raise Picture_Error.]} @end{Reason} A layout error is identified in the rules below if leading non-zero digits of Item, character values of the Currency string, or a negative sign would be truncated; in such cases no edited output string is defined. The edited output string has lower bound 1 and upper bound N where N = Pic_String'Length + Currency_Length_Adjustment @en Radix_Adjustment, and @begin{Itemize} Currency_Length_Adjustment = Currency'Length @en@; 1 if there is some occurrence of '$' in Pic_String, and 0 otherwise. Radix_Adjustment = 1 if there is an occurrence of 'V' or 'v' in Pic_Str, and 0 otherwise. @end{Itemize} @Leading@defn{displayed magnitude (of a decimal value)} Let the magnitude of Item be expressed as a base-10 number I@-(p)@Times@Times@Times@;I@-(1).F@-(1)@Times@Times@Times@;F@-(q), called the @i{displayed} @i{magnitude} of Item, where: @begin{Itemize} q = Min(Max(Num'Scale, 0), n) where n is 0 if Pic_String has no @ntf{radix} and is otherwise the number of digit positions following @ntf{radix} in Pic_String, where a digit position corresponds to an occurrence of '9', a @ntf{zero_suppression_char} (for an @ntf{all_zero_suppression_number}), a @ntf{currency_char} (for an @ntf{all_currency_number}), or a @ntf{sign_char} (for an @ntf{all_sign_number}). I@-(p) /= 0 if p>0. @end{Itemize} If n < Num'Scale, then the above number is the result of rounding (away from 0 if exactly midway between values). If Blank_When_Zero = True and the displayed magnitude of Item is zero, then the edited output string comprises all space character values. Otherwise, the picture String is treated as a sequence of instances of syntactic categories based on the rules in @RefSecNum[Picture String Formation], and the edited output string is the concatenation of string values derived from these categories according to the following mapping rules. Table F-1 shows the mapping from a sign control symbol to a corresponding character or string in the edited output. In the columns showing the edited output, a lower-case 'b' represents the space character. If there is no sign control symbol but the value of Item is negative, a layout error occurs and no edited output string is produced. @Table{Columns=<3>,Alignment=<AllCenter>,FirstColWidth=[1],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{Table F-1: Edited Output for Sign Control Symbols}>, Headers=<@b{Sign Control Symbol}@\@b{Edited Output for @*Non-Negative Number}@\@b{Edited Output for @*Negative Number}>, Body=['+'@\'+'@\'@en@;' '@en@;'@\'b'@\'@en@;' '<'@\'b'@\'(' '>'@\'b'@\')' "CR"@\"bb"@\"CR"@Last "DB"@\"bb"@\"DB"]} An instance of @ntf{fixed_LHS_sign} maps to a character as shown in Table F-1. An instance of @ntf{fixed_$_char} maps to Currency. An instance of @ntf{direct_insertion} maps to Separator if @ntf{direct_insertion} = '_', and to the @ntf{direct_insertion} Character otherwise. @Leading@;An instance of @ntf{number} maps to a string @i{integer_part} & @i{radix_part} & @i{fraction_part} where: @begin{Itemize} The string for @i{integer_part} is obtained as follows: @begin{Enumerate} Occurrences of '9' in @ntf{fore_digits} of @ntf{number} are replaced from right to left with the decimal digit character values for I@-(1), ..., I@-(p), respectively. Each occurrence of '9' in @ntf{fore_digits} to the left of the leftmost '9' replaced according to rule 1 is replaced with '0'. If p exceeds the number of occurrences of '9' in @ntf{fore_digits} of @ntf{number}, then the excess leftmost digits are eligible for use in the mapping of an instance of @ntf{zero_suppression}, @ntf{floating_LHS_sign}, @ntf{floating_$_currency}, or @ntf{floating_#_currency} to the left of @ntf{number}; if there is no such instance, then a layout error occurs and no edited output string is produced. @end{Enumerate} @leading@;The @i{radix_part} is: @begin{InnerItemize} "" if @ntf{number} does not include a @ntf{radix}, if @ntf{radix} = 'V', or if @ntf{radix} = 'v' Radix_Mark if @ntf{number} includes '.' as @ntf{radix} @end{InnerItemize} @leading@;The string for @i{fraction_part} is obtained as follows: @begin{Enumerate} Occurrences of '9' in @ntf{aft_digits} of @ntf{number} are replaced from left to right with the decimal digit character values for F@-(1), ... F@-(q). Each occurrence of '9' in @ntf{aft_digits} to the right of the rightmost '9' replaced according to rule 1 is replaced by '0'. @end{Enumerate} @end{Itemize} @leading@;An instance of @ntf{zero_suppression} maps to the string obtained as follows: @begin{Enumerate} The rightmost 'Z', 'z', or '*' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{zero_suppression} instance, A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of some 'Z', 'z', or '*' in @ntf{zero_suppression} that has been mapped to an excess digit, @leading@;Each Character to the left of the leftmost Character replaced according to rule 1 above is replaced by: @begin{InnerItemize} the space character if the zero suppression Character is 'Z' or 'z', or the Fill character if the zero suppression Character is '*'. @end{InnerItemize} A layout error occurs if some excess digits remain after all 'Z', 'z', and '*' Character values in @ntf{zero_suppression} have been replaced via rule 1; no edited output string is produced. @end{Enumerate} An instance of @ntf{RHS_sign} maps to a character or string as shown in Table F-1. An instance of @ntf{floating_LHS_sign} maps to the string obtained as follows. @begin{Enumerate} Up to all but one of the rightmost @ntf{LHS_Sign} Character values are replaced by the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_LHS_sign} instance. The next Character to the left is replaced with the character given by the entry in Table F-1 corresponding to the @ntf{LHS_Sign} Character. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost @ntf{LHS_Sign} character replaced according to rule 1. Any other Character is replaced by the space character.. A layout error occurs if some excess digits remain after replacement via rule 1; no edited output string is produced. @end{Enumerate} An instance of @ntf{fixed_#_currency} maps to the Currency string with n space character values concatenated on the left (if the instance does not follow a @ntf{radix}) or on the right (if the instance does follow a @ntf{radix}), where n is the difference between the length of the @ntf{fixed_#_currency} instance and Currency'Length. A layout error occurs if Currency'Length exceeds the length of the @ntf{fixed_#_currency} instance; no edited output string is produced. @Leading@;An instance of @ntf{floating_$_currency} maps to the string obtained as follows: @begin{Enumerate} Up to all but one of the rightmost '$' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_$_currency} instance. The next Character to the left is replaced by the Currency string. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost '$' Character replaced via rule 1. Each other Character is replaced by the space character. A layout error occurs if some excess digits remain after replacement by rule 1; no edited output string is produced. @end{Enumerate} @leading@;An instance of @ntf{floating_#_currency} maps to the string obtained as follows: @begin{Enumerate} Up to all but one of the rightmost '#' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_#_currency} instance. The substring whose last Character occurs at the position immediately preceding the leftmost Character replaced via rule 1, and whose length is Currency'Length, is replaced by the Currency string. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost '#' replaced via rule 1. Any other Character is replaced by the space character. A layout error occurs if some excess digits remain after replacement rule 1, or if there is no substring with the required length for replacement rule 2; no edited output string is produced. @end{Enumerate} @leading@;An instance of @ntf{all_zero_suppression_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero, the @ntf{zero_suppression_char} is 'Z' or 'z', and the instance of @ntf{all_zero_suppression_number} does not have a @ntf{radix} at its last character position; a string containing the Fill character in each position except for the character (if any) corresponding to @ntf{radix}, if @ntf{zero_suppression_char} = '*' and the displayed magnitude of Item is zero; otherwise, the same result as if each @ntf{zero_suppression_char} in @ntf{all_zero_suppression_aft} were '9', interpreting the instance of @ntf{all_zero_suppression_number} as either @ntf{zero_suppression} @ntf{number} (if a @ntf{radix} and @ntf{all_zero_suppression_aft} are present), or as @ntf{zero_suppression} otherwise. @end{Itemize} @leading@;An instance of @ntf{all_sign_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero and the instance of @ntf{all_sign_number} does not have a @ntf{radix} at its last character position; otherwise, the same result as if each @ntf{sign_char} in @ntf{all_sign_number_aft} were '9', interpreting the instance of @ntf{all_sign_number} as either @ntf{floating_LHS_sign} @ntf{number} (if a @ntf{radix} and @ntf{all_sign_number_aft} are present), or as @ntf{floating_LHS_sign} otherwise. @end{Itemize} @leading@;An instance of @ntf{all_currency_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero and the instance of @ntf{all_currency_number} does not have a @ntf{radix} at its last character position; otherwise, the same result as if each @ntf{currency_char} in @ntf{all_currency_number_aft} were '9', interpreting the instance of @ntf{all_currency_number} as @ntf{floating_$_currency} @ntf{number} or @ntf{floating_#_currency} @ntf{number} (if a @ntf{radix} and @ntf{all_currency_number_aft} are present), or as @ntf{floating_$_currency} or @ntf{floating_#_currency} otherwise. @end{Itemize} @end{RunTime} @begin{Examples} In the result string values shown below, 'b' represents the space character. @begin{Example} Item: Picture and Result Strings: 123456.78 Picture: "-###**_***_**9.99" "bbb$***123,456.78" "bbFF***123.456,78" (currency = "FF", separator = '.', radix mark = ',') @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0089],ARef=[AI95-00070]} 123456.78 Picture: "-@Chg{New=[],Old=[$$]}$**_***_**9.99" Result: "@Chg{New=[],Old=[bb]}b$***123,456.78" "b@Chg{New=[],Old=[bb]}FF***123.456,78" (currency = "FF", @Chg{New=[],Old=[ ]} separator = '.', @Chg{New=[],Old=[ ]} radix mark = ',') 0.0 Picture: "-$$$$$$.$$" Result: "bbbbbbbbbb" 0.20 Picture: "-$$$$$$.$$" Result: "bbbbbb$.20" -1234.565 Picture: "<<<<_<<<.<<###>" Result: "bb(1,234.57DMb)" (currency = "DM") 12345.67 Picture: "###_###_##9.99" Result: "bbCHF12,345.67" (currency = "CHF") @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0089],ARef=[AI95-00070-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the picture string example.]} @end{DiffWord95} @LabeledSubClause{The Package Text_IO.Editing} @begin{Intro} The package Text_IO.Editing provides a private type Picture with associated operations, and a generic package Decimal_Output. An object of type Picture is composed from a well-formed picture String (see @RefSecNum(Picture String Formation)) and a Boolean item indicating whether a zero numeric value will result in an edited output string of all space characters. The package Decimal_Output contains edited output subprograms implementing the effects defined in @RefSecNum(Edited Output Generation). @end{Intro} @begin{StaticSem} @leading@;The library package Text_IO.Editing has the following declaration: @begin{Example} @key(package) Ada.Text_IO.Editing @key(is)@ChildUnit{Parent=[Ada.Text_IO],Child=[Editing]} @key(type) @AdaTypeDefn{Picture} @key(is) @key(private); @key(function) @AdaSubDefn{Valid} (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Boolean; @key(function) @AdaSubDefn{To_Picture} (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Picture; @key(function) @AdaSubDefn{Pic_String} (Pic : @key(in) Picture) @key(return) String; @key(function) @AdaSubDefn{Blank_When_Zero} (Pic : @key(in) Picture) @key(return) Boolean; @AdaObjDefn{Max_Picture_Length} : @key(constant) := @RI{implementation_defined}; @AdaExcDefn{Picture_Error} : @key(exception); @AdaObjDefn{Default_Currency} : @key(constant) String := "$"; @AdaObjDefn{Default_Fill} : @key(constant) Character := '*'; @AdaObjDefn{Default_Separator} : @key(constant) Character := ','; @AdaObjDefn{Default_Radix_Mark} : @key(constant) Character := '.'; @key(generic) @key(type) Num @key(is) @key(delta) <> @key(digits) <>; Default_Currency : @key(in) String := Text_IO.Editing.Default_Currency; Default_Fill : @key(in) Character := Text_IO.Editing.Default_Fill; Default_Separator : @key(in) Character := Text_IO.Editing.Default_Separator; Default_Radix_Mark : @key(in) Character := Text_IO.Editing.Default_Radix_Mark; @key(package) @AdaPackDefn{Decimal_Output} @key(is) @key(function) @AdaSubDefn{Length} (Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Natural; @key(function) @AdaSubDefn{Valid} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Boolean; @key(function) @AdaSubDefn{Image} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark) @key(return) String; @key(procedure) @AdaSubDefn{Put} (File : @key(in) File_Type; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @key(procedure) @AdaSubDefn{Put} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @trailing@; @key(procedure) @AdaSubDefn{Put} (To : @key(out) String; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @key(end) Decimal_Output; @key(private) ... @RI{-- not specified by the language} @key(end) Ada.Text_IO.Editing; @end{Example} @ImplDef{The value of Max_Picture_Length in the package Text_IO.Editing} @Trailing@;The exception Constraint_Error is raised if the Image function or any of the Put procedures is invoked with a null string for Currency. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Valid (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Boolean; @end{Example} @Trailing@;Valid returns True if Pic_String is a well-formed picture String (see @RefSecNum(Picture String Formation)) the length of whose expansion does not exceed Max_Picture_Length, and if either Blank_When_Zero is False or Pic_String contains no '*'. @begin{Example}@Keepnext @key(function) To_Picture (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Picture; @end{Example} @Trailing@;To_Picture returns a result Picture such that the application of the function Pic_String to this result yields an expanded picture String equivalent to Pic_String, and such that Blank_When_Zero applied to the result Picture is the same value as the parameter Blank_When_Zero. Picture_Error is raised if not Valid(Pic_String, Blank_When_Zero). @begin{Example} @key(function) Pic_String (Pic : @key(in) Picture) @key(return) String; @Comment{Blank line} @key(function) Blank_When_Zero (Pic : @key(in) Picture) @key(return) Boolean; @end{Example} @Leading@;If Pic is To_Picture(String_Item, Boolean_Item) for some String_Item and Boolean_Item, then: @begin[itemize] Pic_String(Pic) returns an expanded picture String equivalent to String_Item and with any lower-case letter replaced with its corresponding upper-case form, and Blank_When_Zero(Pic) returns Boolean_Item. @end[Itemize] @Leading@;If Pic_1 and Pic_2 are objects of type Picture, then "="(Pic_1, Pic_2) is True when @begin[itemize] Pic_String(Pic_1) = Pic_String(Pic_2), and @Trailing@;Blank_When_Zero(Pic_1) = Blank_When_Zero(Pic_2). @end[Itemize] @begin{Example}@Keepnext @key(function) Length (Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Natural; @end{Example} @Leading@;Length returns Pic_String(Pic)'Length + Currency_Length_Adjustment @en Radix_Adjustment where @begin[itemize] @Leading@;Currency_Length_Adjustment = @begin[Inneritemize] Currency'Length @en@; 1 if there is some occurrence of '$' in Pic_String(Pic), and 0 otherwise. @end[Inneritemize] @Leading@;Radix_Adjustment = @begin[Inneritemize] 1 if there is an occurrence of 'V' or 'v' in Pic_Str(Pic), and @Trailing@;0 otherwise. @end[Inneritemize] @end[itemize] @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Boolean; @end{Example} @Trailing@;Valid returns True if Image(Item, Pic, Currency) does not raise Layout_Error, and returns False otherwise. @begin{Example} @key(function) Image (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark) @key(return) String; @end{Example} @Trailing@;Image returns the edited output String as defined in @RefSecNum(Edited Output Generation) for Item, Pic_String(Pic), Blank_When_Zero(Pic), Currency, Fill, Separator, and Radix_Mark. If these rules identify a layout error, then Image raises the exception Layout_Error. @begin{Example} @key(procedure) Put (File : @key(in) File_Type; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @Comment{Blank line} @key(procedure) Put (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @end{Example} @Trailing@;Each of these Put procedures outputs Image(Item, Pic, Currency, Fill, Separator, Radix_Mark) consistent with the conventions for Put for other real types in case of bounded line length (see @RefSec{Get and Put Procedures}). @begin{Example} @key(procedure) Put (To : @key(out) String; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @end{Example} Put copies Image(Item, Pic, Currency, Fill, Separator, Radix_Mark) to the given string, right justified. Otherwise unassigned Character values in To are assigned the space character. If To'Length is less than the length of the string resulting from Image, then Layout_Error is raised. @end{DescribeCode} @end{StaticSem} @begin{ImplReq} Max_Picture_Length shall be at least 30. The implementation shall support currency strings of length up to at least 10, both for Default_Currency in an instantiation of Decimal_Output, and for Currency in an invocation of Image or any of the Put procedures. @begin{Discussion} This implies that a picture string with character replications need not be supported (i.e., To_Picture will raise Picture_Error) if its expanded form exceeds 30 characters. @end{Discussion} @end{ImplReq} @begin{Notes} @Leading@;The rules for edited output are based on COBOL (ANSI X3.23:1985, endorsed by ISO as ISO 1989-1985), with the following differences: @begin{Itemize} The COBOL provisions for picture string localization and for 'P' format are absent from Ada. @Leading@;The following Ada facilities are not in COBOL: @begin{InnerItemize} currency symbol placement after the number, localization of edited output string for multi-character currency string values, including support for both length-preserving and length-expanding currency symbols in picture strings localization of the radix mark, digits separator, and fill character, and parenthesization of negative values. @end{InnerItemize} @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@NoPrefix @Chg{New=[],Old=[@Noparanum@;]}The value of 30 for Max_Picture_Length is the same limit as in COBOL. @end{Notes} @begin{Reason} There are several reasons we have not adopted the COBOL-style permission to provide a single-character replacement in the picture string for the `$' as currency symbol, or to interchange the roles of `.' and `,' in picture strings @begin{Itemize} It would have introduced considerable complexity into Ada, as well as confusion between run-time and compile-time character interpretation, since picture Strings are dynamically computable in Ada, in contrast with COBOL Ada's rules for real literals provide a natural interpretation of `_' as digits separator and `.' for radix mark; it is not essential to allow these to be localized in picture strings, since Ada does not allow them to be localized in real literals. The COBOL restriction for the currency symbol in a picture string to be replaced by a single character currency symbol is a compromise solution. For general international usage a mechanism is needed to localize the edited output to be a multi-character currency string. Allowing a single-Character localization for the picture Character, and a multiple-character localization for the currency string, would be an unnecessary complication. @end{Itemize} @end{Reason} @LabeledSubClause{The Package Wide_Text_IO.Editing} @begin{StaticSem} @Leading@;@Defn{Ada.Wide_@!Text_IO.Editing} @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Editing]} The child package Wide_Text_IO.Editing has the same contents as Text_IO.Editing, except that: @begin{Itemize} each occurrence of Character is replaced by Wide_Character, each occurrence of Text_IO is replaced by Wide_Text_IO, the subtype of Default_Currency is Wide_String rather than String, and each occurrence of String in the generic package Decimal_Output is replaced by Wide_String. @end{Itemize} @ImplDef{The value of Max_Picture_Length in the package Wide_Text_IO.Editing} @end{StaticSem} @begin{Notes} Each of the functions Wide_Text_IO.Editing.Valid, To_Picture, and Pic_String has String (versus Wide_String) as its parameter or result subtype, since a picture String is not localizable. @end{Notes} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Editing]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{Ada.Wide_@!Wide_@!Text_IO.Editing} @ChildUnit{Parent=[Ada.Wide_@!Wide_@!Text_IO],Child=[Editing]} The child package Wide_Wide_Text_IO.Editing has the same contents as Text_IO.Editing, except that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of Character is replaced by Wide_Wide_Character,]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of Text_IO is replaced by Wide_Wide_Text_IO,]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the subtype of Default_Currency is Wide_Wide_String rather than String, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of String in the generic package Decimal_Output is replaced by Wide_Wide_String.]} @end{Itemize} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The value of Max_Picture_Length in the package Wide_Wide_Text_IO.Editing],Old=[]}]} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Each of the functions Wide_Wide_Text_IO.Editing.Valid, To_Picture, and Pic_String has String (versus Wide_Wide_String) as its parameter or result subtype, since a picture String is not localizable.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Editing is new; it supports 32-bit character strings. (Shouldn't it have been @lquotes@;Widest_Text_IO.Editing@rquotes@;? :-)]} @end{Extend95} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/interface.mss��������������������������������������������������������0000755�0001752�0001001�00000400341�12273462240�020107� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/interface.mss,v $ } @comment{ $Revision: 1.48 $ $Date: 2006/10/18 00:25:28 $ $Author: Randy $ } @Part(interface, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:28 $} @LabeledNormativeAnnex{Interface to Other Languages} @begin{Intro} @Defn{interface to other languages} @Defn2{Term=[language], Sec=(interface to non-Ada)} @Defn{mixed-language programs} This Annex describes features for writing mixed-language programs. General interface support is presented first; then specific support for C, COBOL, and Fortran is defined, in terms of language interface packages for each of these languages. @begin{Ramification} This Annex is not a @lquotes@;Specialized Needs@rquotes@; annex. Every implementation must support all non-optional features defined here (mainly the package Interfaces). @end{Ramification} @end{Intro} @begin{MetaRules} Ada should have strong support for mixed-language programming. @end{MetaRules} @begin{Extend83} @Defn{extensions to Ada 83} Much of the functionality in this Annex is new to Ada 95. @end{Extend83} @begin{DiffWord83} This Annex contains what used to be RM83-13.8. @end{DiffWord83} @LabeledClause{Interfacing Pragmas} @begin{Intro} A @nt{pragma} Import is used to import an entity defined in a foreign language into an Ada program, thus allowing a foreign-language subprogram to be called from Ada, or a foreign-language variable to be accessed from Ada. In contrast, a @nt{pragma} Export is used to export an Ada entity to a foreign language, thus allowing an Ada subprogram to be called from a foreign language, or an Ada object to be accessed from a foreign language. The @nt[pragma]s Import and Export are intended primarily for objects and subprograms, although implementations are allowed to support other entities. A @nt{pragma} Convention is used to specify that an Ada entity should use the conventions of another language. It is intended primarily for types and @lquotes@;callback@rquotes@; subprograms. For example, @lquotes@;@key{pragma} Convention(Fortran, Matrix);@rquotes@; implies that Matrix should be represented according to the conventions of the supported Fortran implementation, namely column-major order. A @nt{pragma} Linker_Options is used to specify the system linker parameters needed when a given compilation unit is included in a partition. @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@RootDefn{interfacing pragma} @PDefn2{Term=[interfacing pragma], Sec=(Import)} @PDefn2{Term=[pragma, interfacing], Sec=(Import)} @PDefn2{Term=[interfacing pragma], Sec=(Export)} @PDefn2{Term=[pragma, interfacing], Sec=(Export)} @PDefn2{Term=[interfacing pragma], Sec=(Convention)} @PDefn2{Term=[pragma, interfacing], Sec=(Convention)} @PDefn2{Term=[pragma, interfacing], Sec=(Linker_Options)} An @i{interfacing pragma} is a representation @nt[pragma] that is one of the @nt{pragma}s Import, Export, or Convention. Their forms, together with that of the related @nt[pragma] Linker_Options, are as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Import)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{string_}@Syn2{expression}] [, [Link_Name =>] @SynI{string_}@Syn2{expression}]);' @PragmaSyn`@key{pragma} @prag(Export)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{string_}@Syn2{expression}] [, [Link_Name =>] @SynI{string_}@Syn2{expression}]);' @PragmaSyn`@key{pragma} @prag(Convention)([Convention =>] @SynI{convention_}@Syn2{identifier},[Entity =>] @Syn2{local_name});' @PragmaSyn`@key{pragma} @prag(Linker_Options)(@SynI{string_}@Syn2{expression});' @begin{SyntaxText} A @nt[pragma] Linker_Options is allowed only at the place of a @nt[declarative_item]. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0058],ARef=[AI95-00036-01]} @ChgAdded{Version=[1],Text=[For @nt{pragma}s Import and Export, the argument for Link_Name shall not be given without the @i{pragma_@!argument_}@!@nt{identifier} unless the argument for External_Name is given.]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(link name)} The expected type for a @SynI{string_}@Syn2{expression} in an interfacing pragma or in pragma Linker_Options is String. @begin{Ramification} There is no language-defined support for external or link names of type Wide_String, or of other string types. Implementations may, of course, have additional pragmas for that purpose. Note that allowing both String and Wide_String in the same @nt{pragma} would cause ambiguities. @end{Ramification} @end{Resolution} @begin{Legality} @Defn{convention} The @SynI{convention_}@nt{identifier} of an interfacing pragma shall be the name of a @i{convention}. The convention names are implementation defined, except for certain language-defined ones, such as Ada and Intrinsic, as explained in @RefSec{Conformance Rules}. @Redundant[Additional convention names generally represent the calling conventions of foreign languages, language implementations, or specific run-time models.] @Defn{calling convention} The convention of a callable entity is its @i{calling convention}. @ImplDef{Implementation-defined convention names.} @begin{Discussion} We considered representing the convention names using an enumeration type declared in System. Then, @SynI{convention_}@nt{identifier} would be changed to @SynI{convention_}@nt{name}, and we would make its expected type be the enumeration type. We didn't do this because it seems to introduce extra complexity, and because the list of available languages is better represented as the list of children of package Interfaces @em a more open-ended sort of list. @end{Discussion} @Leading@Defn2{Term=[compatible],Sec=[a type, with a convention]} If @i[L] is a @i[convention_]@nt[identifier] for a language, then a type T is said to be @i{compatible with convention L}, (alternatively, is said to be an @i[L-compatible type]) if any of the following conditions are met: @begin[itemize] T is declared in a language interface package corresponding to @i[L] and is defined to be @i[L]-compatible (see @refsecnum(Interfacing with C and C++), @refsecnum(The Package Interfaces.C.Strings), @refsecnum(The Generic Package Interfaces.C.Pointers), @refsecnum(Interfacing with COBOL), @refsecnum(Interfacing with Fortran)), @Leading@Defn2{Term=[eligible],Sec=[a type, for a convention]} Convention @i[L] has been specified for T in a @nt[pragma] Convention, and T is @i{eligible for convention @i[L]}; that is: @begin[inneritemize] T is an array type with either an unconstrained or statically-constrained first subtype, and its component type is @i[L]-compatible, T is a record type that has no discriminants and that only has components with statically-constrained subtypes, and each component type is @i[L]-compatible, T is an access-to-object type, and its designated type is @i[L]-compatible, T is an access-to-subprogram type, and its designated profile's parameter and result types are all @i[L]-compatible. @end[inneritemize] T is derived from an @i[L]-compatible type, The implementation permits T as an @i[L]-compatible type. @begin{discussion} For example, an implementation might permit Integer as a C-compatible type, though the C type to which it corresponds might be different in different environments.@end{discussion} @end[itemize] If @nt[pragma] Convention applies to a type, then the type shall either be compatible with or eligible for the convention specified in the pragma. @begin[ramification] If a type is derived from an @i[L]-compatible type, the derived type is by default @i[L]-compatible, but it is also permitted to specify pragma Convention for the derived type. It is permitted to specify pragma Convention for an incomplete type, but in the complete declaration each component must be @i[L]-compatible. If each component of a record type is @i[L]-compatible, then the record type itself is only @i[L]-compatible if it has a pragma Convention. @end[Ramification] A @nt{pragma} Import shall be the completion of a declaration. @Defn{notwithstanding} Notwithstanding any rule to the contrary, a @nt{pragma} Import may serve as the completion of any kind of (explicit) declaration if supported by an implementation for that kind of declaration. If a completion is a @nt{pragma} Import, then it shall appear in the same @nt{declarative_part}, @nt{package_specification}, @nt{task_definition} or @nt{protected_definition} as the declaration. For a library unit, it shall appear in the same @nt{compilation}, before any subsequent @nt{compilation_unit}s other than @nt{pragma}s. If the @nt{local_name} denotes more than one entity, then the @nt{pragma} Import is the completion of all of them. @begin(Discussion) For declarations of deferred constants and subprograms, we mention pragma Import explicitly as a possible completion. For other declarations that require completions, we ignore the possibility of pragma Import. Nevertheless, if an implementation chooses to allow a @nt{pragma} Import to complete the declaration of a task, protected type, incomplete type, private type, etc., it may do so, and the normal completion is then not allowed for that declaration. @end(Discussion) @Defn{imported entity} @Defn{exported entity} An entity specified as the Entity argument to a @nt[pragma] Import (or @nt[pragma] Export) is said to be @i{imported} (respectively, @i{exported}). The declaration of an imported object shall not include an explicit initialization expression. @Redundant[Default initializations are not performed.] @begin{TheProof} This follows from the @lquotes@;Notwithstanding ...@rquotes@; wording in the Dynamics Semantics paragraphs below. @end{TheProof} The type of an imported or exported object shall be compatible with the convention specified in the corresponding @nt[pragma]. @begin[Ramification] This implies, for example, that importing an Integer object might be illegal, whereas importing an object of type Interfaces.C.int would be permitted. @end[Ramification] For an imported or exported subprogram, the result and parameter types shall each be compatible with the convention specified in the corresponding pragma. The external name and link name @i{string}_@nt[expression]s of a @nt{pragma} Import or Export, and the @i[string]_@nt[expression] of a @nt[pragma] Linker_Options, shall be static. @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Import)} @PDefn2{Term=[pragma, representation], Sec=(Import)} @PDefn2{Term=[representation pragma], Sec=(Export)} @PDefn2{Term=[pragma, representation], Sec=(Export)} @PDefn2{Term=[representation pragma], Sec=(Convention)} @PDefn2{Term=[pragma, representation], Sec=(Convention)} @PDefn2{Term=[aspect of representation], Sec=(convention, calling convention)} @Defn2{Term=[convention], Sec=(aspect of representation)} Import, Export, and Convention @nt{pragma}s are representation pragmas that specify the @i{convention} aspect of representation. @PDefn2{Term=[aspect of representation], Sec=(imported)} @Defn2{Term=[imported], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(exported)} @Defn2{Term=[exported], Sec=(aspect of representation)} In addition, Import and Export @nt{pragma}s specify the @i{imported} and @i{exported} aspects of representation, respectively. @PDefn2{Term=[program unit pragma], Sec=(Import)} @PDefn2{Term=[pragma, program unit], Sec=(Import)} @PDefn2{Term=[program unit pragma], Sec=(Export)} @PDefn2{Term=[pragma, program unit], Sec=(Export)} @PDefn2{Term=[program unit pragma], Sec=(Convention)} @PDefn2{Term=[pragma, program unit], Sec=(Convention)} An interfacing pragma is a program unit pragma when applied to a program unit (see @RefSecNum{Pragmas and Program Units}). @Leading@;An interfacing pragma defines the convention of the entity denoted by the @nt{local_name}. The convention represents the calling convention or representation convention of the entity. For an access-to-subprogram type, it represents the calling convention of designated subprograms. In addition: @begin{Itemize} A @nt{pragma} Import specifies that the entity is defined externally (that is, outside the Ada program). A @nt{pragma} Export specifies that the entity is used externally. A @nt{pragma} Import or Export optionally specifies an entity's external name, link name, or both. @end{Itemize} @Defn{external name} An @i{external name} is a string value for the name used by a foreign language program either for an entity that an Ada program imports, or for referring to an entity that an Ada program exports. @Defn{link name} A @i[link name] is a string value for the name of an exported or imported entity, based on the conventions of the foreign language's compiler in interfacing with the system's linker tool. The meaning of link names is implementation defined. If neither a link name nor the Address attribute of an imported or exported entity is specified, then a link name is chosen in an implementation-defined manner, based on the external name if one is specified. @ImplDef{The meaning of link names.} @begin{Ramification} For example, an implementation might always prepend "_", and then pass it to the system linker. @end{Ramification} @ImplDef{The manner of choosing link names when neither the link name nor the address of an imported or exported entity is specified.} @begin{Ramification} Normally, this will be the entity's defining name, or some simple transformation thereof. @end{Ramification} Pragma Linker_Options has the effect of passing its string argument as a parameter to the system linker (if one exists), if the immediately enclosing compilation unit is included in the partition being linked. The interpretation of the string argument, and the way in which the string arguments from multiple Linker_Options pragmas are combined, is implementation defined. @ImplDef(The effect of pragma Linker_Options.) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(declaration named by a @nt{pragma} Import)} @Defn{notwithstanding} Notwithstanding what this International Standard says elsewhere, the elaboration of a declaration denoted by the @nt{local_name} of a @nt{pragma} Import does not create the entity. Such an elaboration has no other effect than to allow the defining name to denote the external entity. @begin{Ramification} This implies that default initializations are skipped. (Explicit initializations are illegal.) For example, an imported access object is @i{not} initialized to @key[null]. Note that the @nt{local_name} in a @nt{pragma} Import might denote more than one declaration; in that case, the entity of all of those declarations will be the external entity. @end{Ramification} @begin{Discussion} This @lquotes@;notwithstanding@rquotes@; wording is better than saying @lquotes@;unless named by a @nt{pragma} Import@rquotes@; on every definition of elaboration. It says we recognize the contradiction, and this rule takes precedence. @end{Discussion} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00320-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} It is the programmer's responsibility to ensure that the use of interfacing pragmas does not violate Ada semantics; otherwise, program execution is erroneous.]} @end{Erron} @begin{ImplAdvice} If an implementation supports pragma Export to a given language, then it should also allow the main subprogram to be written in that language. It should support some mechanism for invoking the elaboration of the Ada library units included in the system, and for invoking the finalization of the environment task. On typical systems, the recommended mechanism is to provide two subprograms whose link names are "adainit" and "adafinal". Adainit should contain the elaboration code for library units. Adafinal should contain the finalization code. These subprograms should have no effect the second and subsequent time they are called. @Chg{New=[@Defn{adainit}@Defn{adafinal}@Defn2{Term=[Elaboration], Sec=[of library units for a foreign language main subprogram]} @Defn2{Term=[Finalization], Sec=[of environment task for a foreign language main subprogram]}], Old=[]}@ChgNote{Presentation AI-00052. Index entries only; no real change, so no Chgref} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If @nt{pragma} Export is supported for a language, the main program should be able to be written in that language. Subprograms named "adainit" and "adafinal" should be provided for elaboration and finalization of the environment task.]}]} @begin{ramification} For example, if the main subprogram is written in C, it can call adainit before the first call to an Ada subprogram, and adafinal after the last.@end{ramification} Automatic elaboration of preelaborated packages should be provided when @nt[pragma] Export is supported. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Automatic elaboration of preelaborated packages should be provided when @nt[pragma] Export is supported.]}]} For each supported convention @i[L] other than Intrinsic, an implementation should support Import and Export @nt{pragma}s for objects of @i[L]-compatible types and for subprograms, and @nt(pragma) Convention for @i[L]-eligible types and for subprograms, presuming the other language has corresponding features. @nt(Pragma) Convention need not be supported for scalar types. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For each supported convention @i[L] other than Intrinsic, @nt{pragma}s Import and Export should be supported for objects of @i[L]-compatible types and for subprograms, and @nt(pragma) Convention should be supported for @i[L]-eligible types and for subprograms.]}]} @begin{reason} Pragma Convention is not necessary for scalar types, since the language interface packages declare scalar types corresponding to those provided by the respective foreign languages. @end[reason] @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} If an implementation supports interfacing to @Chg{Version=[2],New=[the ], Old=[]}C++@Chg{Version=[2],New=[ entities not supported by @RefSecNum{Interfacing with C and C++}],Old=[]}, it should do so via the convention identifier C_Plus_Plus (in additional to any C++-implementation-specific ones). @end{ImplNote} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The reason for giving the advice about C++ is to encourage uniformity among implementations, given that the name of the language is not syntactically legal as an @nt{identifier}.@Chg{Version=[2],New=[],Old=[ We place this advice in the AARM, rather than the RM95 proper, because (as of this writing) C++ is not an international standard, and we don't want to refer to a such a language from an international standard.]} @end{Reason} @end{ImplAdvice} @begin{Notes} Implementations may place restrictions on interfacing pragmas; for example, requiring each exported entity to be declared at the library level. @begin{TheProof} Arbitrary restrictions are allowed by @RefSecNum{Operational and Representation Items}. @end{TheProof} @begin{Ramification} Such a restriction might be to disallow them altogether. Alternatively, the implementation might allow them only for certain kinds of entities, or only for certain conventions. @end{Ramification} A @nt{pragma} Import specifies the conventions for accessing external entities. It is possible that the actual entity is written in assembly language, but reflects the conventions of a particular language. For example, @key{pragma} Import(Ada, ...) can be used to interface to an assembly language routine that obeys the Ada compiler's calling conventions. To obtain @lquotes@;call-back@rquotes@; to an Ada subprogram from a foreign language environment, @key(pragma) Convention should be specified both for the access-to-subprogram type and the specific subprogram(s) to which 'Access is applied. It is illegal to specify more than one of Import, Export, or Convention for a given entity. The @nt{local_name} in an interfacing pragma can denote more than one entity in the case of overloading. Such a @nt{pragma} applies to all of the denoted entities. See also @RefSec{Machine Code Insertions}. @begin{Ramification} The Intrinsic convention (see @refsecnum(Conformance Rules)) implies that the entity is somehow @lquotes@;built in@rquotes@; to the implementation. Thus, it generally does not make sense for users to specify Intrinsic in a @nt{pragma} Import. The intention is that only implementations will specify Intrinsic in a @nt{pragma} Import. The language also defines certain subprograms to be Intrinsic. @end{Ramification} @begin{Discussion} There are many imaginable interfacing pragmas that don't make any sense. For example, setting the Convention of a protected procedure to Ada is probably wrong. Rather than enumerating all such cases, however, we leave it up to implementations to decide what is sensible. @end{Discussion} If both External_Name and Link_Name are specified for an Import or Export pragma, then the External_Name is ignored. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00320-01]} @ChgDeleted{Version=[2],Text=[An interfacing pragma might result in an effect that violates Ada semantics.]} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of interfacing pragmas:} @begin{Example} @key[package] Fortran_Library @key[is] @key[function] Sqrt (X : Float) @key[return] Float; @key[function] Exp (X : Float) @key[return] Float; @key[private] @key[pragma] Import(Fortran, Sqrt); @key[pragma] Import(Fortran, Exp); @key[end] Fortran_Library; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Interfacing pragmas are new to Ada 95. Pragma Import replaces Ada 83's pragma Interface. Existing implementations can continue to support pragma Interface for upward compatibility. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0058],ARef=[AI95-00036-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that @nt{pragma}s Import and Export work like a subprogram call; parameters cannot be omitted unless named notation is used. (Reordering is still not permitted, however.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00320-01]} @ChgAdded{Version=[2],Text=[Added wording to say all bets are off if foreign code doesn't follow the semantics promised by the Ada specifications.]} @end{DiffWord95} @LabeledClause{The Package Interfaces} @begin{Intro} Package Interfaces is the parent of several library packages that declare types and other entities useful for interfacing to foreign languages. It also contains some implementation-defined types that are useful across more than one language (in particular for interfacing to assembly language). @ImplDef{The contents of the visible part of package Interfaces and its language-defined descendants.} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces has the following skeletal declaration: @begin{Example} @RootLibUnit{Interfaces} @key[package] Interfaces @key[is] @key[pragma] Pure(Interfaces); @key[type] Integer_@RI{n} @key[is] @key[range] -2**(@RI{n}-1) .. 2**(@RI{n}-1) - 1; --@RI{2's complement} @key[type] Unsigned_@RI{n} @key[is] @key[mod] 2**@RI{n}; @key[function] Shift_Left (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Shift_Right (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Shift_Right_Arithmetic (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Rotate_Left (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Rotate_Right (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; ... @key[end] Interfaces; @end{Example} @end{StaticSem} @begin{ImplReq} @Leading@;An implementation shall provide the following declarations in the visible part of package Interfaces: @begin{Itemize} Signed and modular integer types of @i{n} bits, if supported by the target architecture, for each @i{n} that is at least the size of a storage element and that is a factor of the word size. The names of these types are of the form Integer_@i{n} for the signed types, and Unsigned_@i{n} for the modular types; @begin{Ramification} For example, for a typical 32-bit machine the corresponding types might be Integer_8, Unsigned_8, Integer_16, Unsigned_16, Integer_32, and Unsigned_32. The wording above implies, for example, that Integer_16'Size = Unsigned_16'Size = 16. Unchecked conversions between same-Sized types will work as expected. @end{Ramification} @Defn{shift}@Defn{rotate} For each such modular type in Interfaces, shifting and rotating subprograms as specified in the declaration of Interfaces above. These subprograms are Intrinsic. They operate on a bit-by-bit basis, using the binary representation of the value of the operands to yield a binary representation for the result. The Amount parameter gives the number of bits by which to shift or rotate. For shifting, zero bits are shifted in, except in the case of Shift_Right_Arithmetic, where one bits are shifted in if Value is at least half the modulus. @begin{Reason} We considered making shifting and rotating be primitive operations of all modular types. However, it is a design principle of Ada that all predefined operations should be operators (not functions named by identifiers). (Note that an early version of Ada had "@key[abs]" as an identifier, but it was changed to a reserved word operator before standardization of Ada 83.) This is important because the implicit declarations would hide non-overloadable declarations with the same name, whereas operators are always overloadable. Therefore, we would have had to make shift and rotate into reserved words, which would have been upward incompatible, or else invent new operator symbols, which seemed like too much mechanism. @end{Reason} Floating point types corresponding to each floating point format fully supported by the hardware. @begin{ImplNote} The names for these floating point types are not specified. @Defn{IEEE floating point arithmetic} However, if IEEE arithmetic is supported, then the names should be IEEE_Float_32 and IEEE_Float_64 for single and double precision, respectively. @end{ImplNote} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00204-01]} @ChgAdded{Version=[2],Text=[Support for interfacing to any foreign language is optional. However, an implementation shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in the following clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intent is that the same rules apply for language interfacing as apply for Specialized Needs Annexes. See @RefSecNum{Conformity of an Implementation with the Standard} for a discussion of the purpose of these rules.]} @end{Discussion} @end{ImplReq} @begin{ImplPerm} An implementation may provide implementation-defined library units that are children of Interfaces, and may add declarations to the visible part of Interfaces in addition to the ones defined above. @ChgImplDef{Version=[2],Kind=[Revised],Text=[Implementation-defined children of package Interfaces.@Chg{Version=[2],New=[],Old=[ The contents of the visible part of package Interfaces.]}]} @ChgNote{The latter sentence is given previously!} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00204-01]} @ChgAdded{Version=[2],Text=[A child package of package Interfaces with the name of a convention may be provided independently of whether the convention is supported by the pragma Convention and vice versa. Such a child package should contain any declarations that would be useful for interfacing to the language (implementation) represented by the convention. Any declarations useful for interfacing to any language on the given hardware architecture should be provided directly in Interfaces.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]}@ChgNote{Moved from below} @ChgAdded{Version=[2],Text=[For example, package Interfaces.XYZ_Pascal might contain declarations of types that match the data types provided by the XYZ implementation of Pascal, so that it will be more convenient to pass parameters to a subprogram whose convention is XYZ_Pascal.]} @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00204-01]} @ChgDeleted{Version=[2],Text=[For each implementation-defined convention identifier, there should be a child package of package Interfaces with the corresponding name. This package should contain any declarations that would be useful for interfacing to the language (implementation) represented by the convention. Any declarations useful for interfacing to any language on the given hardware architecture should be provided directly in Interfaces.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[For example, package Interfaces.XYZ_Pascal might contain declarations of types that match the data types provided by the XYZ implementation of Pascal, so that it will be more convenient to pass parameters to a subprogram whose convention is XYZ_Pascal.]} @end{Ramification} An implementation supporting an interface to C, COBOL, or Fortran should provide the corresponding package or packages described in the following clauses. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If an interface to C, COBOL, or Fortran is provided, the corresponding package or packages described in @RefSec{Interface to Other Languages} should also be provided.]}]} @begin{ImplNote} @Leading@;The intention is that an implementation might support several implementations of the foreign language: Interfaces.This_Fortran and Interfaces.That_Fortran might both exist. The @lquotes@;default@rquotes@; implementation, overridable by the user, should be declared as a renaming: @begin{Example} @key[package] Interfaces.Fortran @key[renames] Interfaces.This_Fortran; @end{Example} @end{ImplNote} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00204-01]} @ChgAdded{Version=[2],Text=[Clarified that interfacing to foreign languages is optional and has the same restrictions as a Specialized Needs Annex.]} @end{DiffWord95} @LabeledRevisedClause{Version=[2],New=[Interfacing with C and C++], Old=[Interfacing with C]} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00376-01]} @Defn{interface to C} @Defn{C interface} The facilities relevant to interfacing with the C language @Chg{Version=[2],New=[and the corresponding subset of the C++ language ],Old=[]}are the package Interfaces.C and its children; @Chg{New=[],Old=[and ]}support for the Import, Export, and Convention pragmas with @i{convention}_@nt{identifier} C@Chg{New=[; and support for the Convention pragma with @i{convention}_@nt{identifier} C_Pass_By_Copy],Old=[]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00376-01]} The package Interfaces.C contains the basic types, constants and subprograms that allow an Ada program to pass scalars and strings to C @Chg{Version=[2],New=[and C++ ],Old=[]}functions.@Chg{Version=[2],New=[ When this clause mentions a C entity, the reference also applies to the corresponding entity in C++.],Old=[]} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.C has the following declaration: @begin{Example} @key(package) Interfaces.C @key(is)@ChildUnit{Parent=[Interfaces],Child=[C]} @key(pragma) Pure(C); @RI{-- Declarations based on C's <limits.h>} @AdaObjDefn{CHAR_BIT} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 8} @AdaObjDefn{SCHAR_MIN} : @key(constant) := @RI{implementation-defined}; @RI{-- typically @en@;128} @AdaObjDefn{SCHAR_MAX} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 127} @AdaObjDefn{UCHAR_MAX} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 255} @RI{-- Signed and Unsigned Integers} @key(type) @AdaTypeDefn{int} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{short} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{long} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{signed_char} @key(is) @key(range) SCHAR_MIN .. SCHAR_MAX; @key(for) signed_char'Size @key(use) CHAR_BIT; @key(type) @AdaTypeDefn{unsigned} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_short} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_long} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_char} @key(is) @key(mod) (UCHAR_MAX+1); @key(for) unsigned_char'Size @key(use) CHAR_BIT; @key(subtype) @AdaTypeDefn{plain_char} @key(is) @RI{implementation-defined}; @key(type) @AdaTypeDefn{ptrdiff_t} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{size_t} @key(is) @key(mod) @RI{implementation-defined}; @RI{-- Floating Point} @key(type) @AdaTypeDefn{C_float} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{double} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{long_double} @key(is) @key(digits) @RI{implementation-defined}; @RI{-- Characters and Strings } @key(type) @AdaTypeDefn{char} @key(is) @RI{<implementation-defined character type>}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @AdaObjDefn{nul} : @key(constant) char := @Chg{New=[@RI{implementation-defined}],Old=[char'First]}; @key[function] @AdaSubDefn{To_C} (Item : @key[in] Character) @key[return] char; @key[function] @AdaSubDefn{To_Ada} (Item : @key[in] char) @key[return] Character; @key(type) @AdaTypeDefn{char_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @key[aliased] char; @key[pragma] Pack(char_array); @key(for) char_array'Component_Size @key(use) CHAR_BIT; @key(function) @AdaSubDefn{Is_Nul_Terminated} (Item : @key(in) char_array) @key(return) Boolean; @key(function) @AdaSubDefn{To_C} (Item : @key(in) String; Append_Nul : @key(in) Boolean := True) @key(return) char_array; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) char_array; Trim_Nul : @key(in) Boolean := True) @key(return) String; @key(procedure) @AdaSubDefn{To_C} (Item : @key(in) String; Target : @key(out) char_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) char_array; Target : @key(out) String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @RI{-- Wide Character and Wide String} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @key(type) @AdaTypeDefn{wchar_t} @key(is) @Chg{New=[@RI{<implementation-defined character type>}], Old=[@RI{implementation-defined}]}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @AdaObjDefn{wide_nul} : @key(constant) wchar_t := @Chg{New=[@RI{implementation-defined}],Old=[wchar_t'First]}; @key(function) @AdaSubDefn{To_C} (Item : @key(in) Wide_Character) @key(return) wchar_t; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_t ) @key(return) Wide_Character; @key(type) @AdaTypeDefn{wchar_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @key(aliased) wchar_t; @key(pragma) Pack(wchar_array); @key(function) @AdaSubDefn{Is_Nul_Terminated} (Item : @key(in) wchar_array) @key(return) Boolean; @key(function) @AdaSubDefn{To_C} (Item : @key(in) Wide_String; Append_Nul : @key(in) Boolean := True) @key(return) wchar_array; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_array; Trim_Nul : @key(in) Boolean := True) @key(return) Wide_String; @key(procedure) @AdaSubDefn{To_C} (Item : @key(in) Wide_String; Target : @key(out) wchar_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_array; Target : @key(out) Wide_String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ -- @RI[ISO/IEC 10646:2003 compatible types defined by ISO/IEC TR 19769:2004.]]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char16_t} @key<is> @RI{<implementation-defined character type>};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{char16_nul} : @key<constant> char16_t := @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Character) @key<return> char16_t; @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char16_t) @key<return> Wide_Character;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char16_array} @key<is array> (size_t @key<range> <>) @key<of aliased> char16_t;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<pragma> Pack(char16_array);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Nul_Terminated} (Item : @key<in> char16_array) @key<return> Boolean; @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char16_array;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char16_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_String;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_C} (Item : @key<in> Wide_String; Target : @key<out> char16_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_Ada} (Item : @key<in> char16_array; Target : @key<out> Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char32_t} @key<is> @RI{<implementation-defined character type>};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{char32_nul} : @key<constant> char32_t := @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_Character) @key<return> char32_t; @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char32_t) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char32_array} @key<is array> (size_t @key<range> <>) @key<of aliased> char32_t;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<pragma> Pack(char32_array);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Nul_Terminated} (Item : @key<in> char32_array) @key<return> Boolean; @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char32_array;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char32_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_String; Target : @key<out> char32_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_Ada} (Item : @key<in> char32_array; Target : @key<out> Wide_Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @AdaExcDefn{Terminator_Error} : @key(exception); @key(end) Interfaces.C; @end{Example} @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{New=[The definitions of @Chg{Version=[2],New=[certain ],Old=[]}types and constants in Interfaces.C.],Old=[]}]} Each of the types declared in Interfaces.C is C-compatible. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The types int, short, long, unsigned, ptrdiff_t, size_t, double, char, @Chg{Version=[2],New=[],Old=[and ]}wchar_t@Chg{Version=[2],New=[, char16_t, and char32_t],Old=[]} correspond respectively to the C types having the same names. The types signed_char, unsigned_@!short, unsigned_@!long, unsigned_@!char, C_float, and long_@!double correspond respectively to the C types signed char, unsigned short, unsigned long, unsigned char, float, and long double. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The C types wchar_t and char16_t seem to be the same. However, wchar_t has an implementation-defined size, whereas char16_t is guaranteed to be an unsigned type of at least 16 bits. Also, char16_t and char32_t are encouraged to have UTF-16 and UTF-32 representations; that means that they are not directly the same as the Ada types, which most likely don't use any UTF encoding.]} @end{Discussion} @Trailing@;The type of the subtype plain_char is either signed_char or unsigned_char, depending on the C implementation. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) Character) @key(return) char; @key(function) To_Ada (Item : @key(in) char ) @key(return) Character; @end{Example} @Trailing@;The functions To_C and To_Ada map between the Ada type Character and the C type char. @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0114],ARef=[AI95-00038-01]} @ChgAdded{Version=[1],Text=[The To_C and To_Ada functions map between corresponding characters, not necessarily between characters with the same internal representation. Corresponding characters are characters defined by the same enumeration literal, if such exist; otherwise, the correspondence is unspecified.@PDefn{Unspecified}]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Type=[Leading],Text=[The following definition is equivalent to the above summary:]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@f{To_C (Latin_1_Char) = char'Value(Character'Image(Latin_1_Char))}@* provided that char'Value does not raise an exception; otherwise the result is unspecified.]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@f{To_Ada (Native_C_Char) = Character'Value(char'Image(Native_C_Char))}@* provided that Character'Value does not raise an exception; otherwise the result is unspecified.]} @end{ImplNote} @begin{Example}@Keepnext @key(function) Is_Nul_Terminated (Item : @key(in) char_array) @key(return) Boolean; @end{Example} @Trailing@;The result of Is_Nul_Terminated is True if Item contains nul, and is False otherwise. @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) String; Append_Nul : @key(in) Boolean := True) @key(return) char_array; @Comment{Blank line} @key(function) To_Ada (Item : @key(in) char_array; Trim_Nul : @key(in) Boolean := True) @key(return) String; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00258-01]} The result of To_C is a char_array value of length Item'Length (if Append_Nul is False) or Item'Length+1 (if Append_Nul is True). The lower bound is 0. For each component Item(I), the corresponding component in the result is To_C applied to Item(I). The value nul is appended if Append_Nul is True.@Chg{Version=[2],New=[ If Append_Nul is False and Item'Length is 0, then To_C propagates Constraint_Error.],Old=[]} @Trailing@;The result of To_Ada is a String whose length is Item'Length (if Trim_Nul is False) or the length of the slice of Item preceding the first nul (if Trim_Nul is True). The lower bound of the result is 1. If Trim_Nul is False, then for each component Item(I) the corresponding component in the result is To_Ada applied to Item(I). If Trim_Nul is True, then for each component Item(I) before the first nul the corresponding component in the result is To_Ada applied to Item(I). The function propagates Terminator_Error if Trim_Nul is True and Item does not contain nul. @begin{Example}@Keepnext @key(procedure) To_C (Item : @key(in) String; Target : @key(out) char_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @Comment{Blank line} @key(procedure) To_Ada (Item : @key(in) char_array; Target : @key(out) String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @end{Example} For procedure To_C, each element of Item is converted (via the To_C function) to a char, which is assigned to the corresponding element of Target. If Append_Nul is True, nul is then assigned to the next element of Target. In either case, Count is set to the number of Target elements assigned. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Target is not long enough, Constraint_Error is propagated. @Trailing@;For procedure To_Ada, each element of Item (if Trim_Nul is False) or each element of Item preceding the first nul (if Trim_Nul is True) is converted (via the To_Ada function) to a Character, which is assigned to the corresponding element of Target. Count is set to the number of Target elements assigned. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Target is not long enough, Constraint_Error is propagated. If Trim_Nul is True and Item does not contain nul, then Terminator_Error is propagated. @begin{Example}@Keepnext @key(function) Is_Nul_Terminated (Item : @key(in) wchar_array) @key(return) Boolean; @end{Example} @Trailing@;The result of Is_Nul_Terminated is True if Item contains wide_nul, and is False otherwise. @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) Wide_Character) @key(return) wchar_t; @key(function) To_Ada (Item : @key(in) wchar_t ) @key(return) Wide_Character; @end{Example} @Trailing@;To_C and To_Ada provide the mappings between the Ada and C wide character types. @begin{Example} @key(function) To_C (Item : @key(in) Wide_String; Append_Nul : @key(in) Boolean := True) @key(return) wchar_array; @Comment{Blank line} @key(function) To_Ada (Item : @key(in) wchar_array; Trim_Nul : @key(in) Boolean := True) @key(return) Wide_String; @Comment{Blank line} @key(procedure) To_C (Item : @key(in) Wide_String; Target : @key(out) wchar_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @Comment{Blank line} @key(procedure) To_Ada (Item : @key(in) wchar_array; Target : @key(out) Wide_String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @end{Example} The To_C and To_Ada subprograms that convert between Wide_String and wchar_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that wide_nul is used instead of nul. @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> Is_Nul_Terminated (Item : @key<in> char16_array) @key<return> Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> To_C (Item : @key<in> Wide_Character) @key<return> char16_t; @key<function> To_Ada (Item : @key<in> char16_t ) @key<return> Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[To_C and To_Ada provide mappings between the Ada and C 16-bit character types.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> To_C (Item : @key<in> Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char16_array; @Comment{Blank line} @key<function> To_Ada (Item : @key<in> char16_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_String; @Comment{Blank line} @key<procedure> To_C (Item : @key<in> Wide_String; Target : @key<out> char16_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True); @Comment{Blank line} @key<procedure> To_Ada (Item : @key<in> char16_array; Target : @key<out> Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The To_C and To_Ada subprograms that convert between Wide_String and char16_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char16_nul is used instead of nul.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> Is_Nul_Terminated (Item : @key<in> char32_array) @key<return> Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> To_C (Item : @key<in> Wide_Wide_Character) @key<return> char32_t; @key<function> To_Ada (Item : @key<in> char32_t ) @key<return> Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[To_C and To_Ada provide mappings between the Ada and C 32-bit character types.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> To_C (Item : @key<in> Wide_Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char32_array; @Comment{Blank line} @key<function> To_Ada (Item : @key<in> char32_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_Wide_String; @Comment{Blank line} @key<procedure> To_C (Item : @key<in> Wide_Wide_String; Target : @key<out> char32_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True); @Comment{Blank line} @key<procedure> To_Ada (Item : @key<in> char32_array; Target : @key<out> Wide_Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The To_C and To_Ada subprograms that convert between Wide_Wide_String and char32_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char32_nul is used instead of nul.]} @begin{Discussion} The Interfaces.C package provides an implementation-defined character type, char, designed to model the C run-time character set, and mappings between the types char and Character. @Leading@;One application of the C interface package is to compose a C string and pass it to a C function. One way to do this is for the programmer to declare an object that will hold the C array, and then pass this array to the C function. This is realized via the type char_array: @begin{Example} @key(type) char_array @key(is) @key(array) (size_t @key(range) <>) of Char; @end{Example} The programmer can declare an Ada String, convert it to a char_array, and pass the char_array as actual parameter to the C function that is expecting a char *. An alternative approach is for the programmer to obtain a C char pointer from an Ada String (or from a char_array) by invoking an allocation function. The package Interfaces.C.Strings (see below) supplies the needed facilities, including a private type chars_ptr that corresponds to C's char *, and two allocation functions. To avoid storage leakage, a Free procedure releases the storage that was allocated by one of these allocate functions. It is typical for a C function that deals with strings to adopt the convention that the string is delimited by a nul char. The C interface packages support this convention. A constant nul of type Char is declared, and the function Value(Chars_Ptr) in Interfaces.C.Strings returns a char_array up to and including the first nul in the array that the chars_ptr points to. The Allocate_Chars function allocates an array that is nul terminated. Some C functions that deal with strings take an explicit length as a parameter, thus allowing strings to be passed that contain nul as a data element. Other C functions take an explicit length that is an upper bound: the prefix of the string up to the char before nul, or the prefix of the given length, is used by the function, whichever is shorter. The C Interface packages support calling such functions. @end{Discussion} @end{DescribeCode} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgAdded{Version=[1],Text=[A Convention pragma with @i{convention}_@nt{identifier} C_Pass_By_Copy shall only be applied to a type.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00216-01]} @ChgAdded{Version=[1],Text=[The eligibility rules in @RefSecNum(Interfacing Pragmas) do not apply to convention C_Pass_By_Copy. Instead, a type T is eligible for convention C_Pass_By_Copy @Chg{Version=[2],New=[if T is an unchecked union type or ], Old=[]}if T is a record type that has no discriminants and that only has components with statically constrained subtypes, and each component is C-compatible.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgAdded{Version=[1],Text=[If a type is C_Pass_By_Copy-compatible then it is also C-compatible.]} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} An implementation shall support pragma Convention with a C @i{convention}_@nt{identifier} for a C-eligible type (see @refsecnum(Interfacing Pragmas))@Chg{New=[. An implementation shall support pragma Convention with a C_Pass_By_Copy @i{convention}_@nt{identifier} for a C_Pass_By_Copy-eligible type.],Old=[]} @end{ImplReq} @begin{ImplPerm} An implementation may provide additional declarations in the C interface packages. @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0060],ARef=[AI95-00037-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00285-01]} @ChgAdded{Version=[1],Text=[The constants nul@Chg{Version=[2],New=[,],Old=[ and]} wide_nul@Chg{Version=[2],New=[, char16_nul, and char32_nul],Old=[]} should have a representation of zero.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The constants nul, wide_nul, char16_nul, and char32_nul in package Interfaces.C should have a representation of zero.]}]} An implementation should support the following interface correspondences between Ada and C. @begin[itemize] An Ada procedure corresponds to a void-returning C function. @begin{discussion} The programmer can also choose an Ada procedure when the C function returns an int that is to be discarded.@end{discussion} An Ada function corresponds to a non-void C function. An Ada @key[in] scalar parameter is passed as a scalar argument to a C function. An Ada @key[in] parameter of an access-to-object type with designated type T is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. An Ada @key[access] T parameter, or an Ada @key[out] or @key[in out] parameter of an elementary type T, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. In the case of an elementary @key[out] or @key[in out] parameter, a pointer to a temporary copy is used to preserve by-copy semantics. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00343-01]} @ChgAdded{Version=[1],Text=[An Ada parameter of a @Chg{Version=[2], New=[(record) type T of convention ],Old=[]}C_Pass_By_Copy@Chg{Version=[2], New=[],Old=[-compatible (record) type T]}, of mode @key{in}, is passed as a t argument to a C function, where t is the C struct corresponding to the Ada type T.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00343-01]} An Ada parameter of a record type T, of any mode, @Chg{New=[other than an @key{in} parameter of a @Chg{Version=[2], New=[type of convention ],Old=[]}C_Pass_By_Copy@Chg{Version=[2], New=[],Old=[-compatible type]},],Old=[]} is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T. An Ada parameter of an array type with component type T, of any mode, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. An Ada parameter of an access-to-subprogram type is passed as a pointer to a C function whose prototype corresponds to the designated subprogram's specification. @end[itemize] @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00337-01]} @ChgAdded{Version=[2],Text=[An Ada parameter of a private type is passed as specified for the full view of the type.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If C interfacing is supported, the interface correspondences between Ada and C should be supported.]}]} @end{ImplAdvice} @begin{Notes} Values of type char_array are not implicitly terminated with nul. If a char_array is to be passed as a parameter to an imported C function requiring nul termination, it is the programmer's responsibility to obtain this effect. To obtain the effect of C's sizeof(item_type), where Item_Type is the corresponding Ada type, evaluate the expression: size_t(Item_Type'Size/CHAR_BIT). @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00216-01]} @ChgDeleted{Version=[2],Text=[There is no explicit support for C's union types. Unchecked conversions can be used to obtain the effect of C unions.]} A C function that takes a variable number of arguments can correspond to several Ada subprograms, taking various specific numbers and types of parameters. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of using the Interfaces.C package:} @begin{Example} @RI{--Calling the C Library Function strcpy} @key(with) Interfaces.C; @key(procedure) Test @key(is) @key(package) C @key(renames) Interfaces.C; @key(use) @key(type) C.char_array; @RI{-- Call <string.h>strcpy:} @RI{-- C definition of strcpy: char *strcpy(char *s1, const char *s2);} @RI{-- This function copies the string pointed to by s2 (including the terminating null character)} @RI{-- into the array pointed to by s1. If copying takes place between objects that overlap, } @RI{-- the behavior is undefined. The strcpy function returns the value of s1.} @RI{-- Note: since the C function's return value is of no interest, the Ada interface is a procedure} @key(procedure) Strcpy (Target : @key(out) C.char_array; Source : @key(in) C.char_array); @key(pragma) Import(C, Strcpy, "strcpy"); Chars1 : C.char_array(1..20); Chars2 : C.char_array(1..20); @key(begin) Chars2(1..6) := "qwert" & C.nul; Strcpy(Chars1, Chars2); @RI{-- Now Chars1(1..6) = "qwert" & C.Nul} @key(end) Test; @end{Example} @end{Examples} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Types char16_t and char32_t and their related types and operations are newly added to Interfaces.C. If Interfaces.C is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Interfaces.C is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b<Corrigendum:> Convention C_Pass_By_Copy is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0060],ARef=[AI95-00037-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the intent for Nul and Wide_Nul.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Specified that an unchecked union type (see @RefSecNum{Pragma Unchecked_Union}) is eligible for convention C_Pass_By_Copy.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00258-01]} @ChgAdded{Version=[2],Text=[Specified what happens if the To_C function tries to return a null string.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00337-01]} @ChgAdded{Version=[2],Text=[Clarified that the interface correspondences also apply to private types whose full types have the specified characteristics.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00343-01]} @ChgAdded{Version=[2],Text=[Clarified that a type must have convention C_Pass_By_Copy in order to be passed by copy (not just a type that could have that convention).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00376-01]} @ChgAdded{Version=[2],Text=[Added wording to make it clear that these facilities can also be used with C++.]} @end{DiffWord95} @LabeledSubClause{The Package Interfaces.C.Strings} @begin{Intro} The package Interfaces.C.Strings declares types and subprograms allowing an Ada program to allocate, reference, update, and free C-style strings. In particular, the private type chars_ptr corresponds to a common use of @lquotes@;char *@rquotes@; in C programs, and an object of this type can be passed to a subprogram to which @nt(pragma) Import(C,...) has been applied, and for which @lquotes@;char *@rquotes@; is the type of the argument of the C function. @end{Intro} @begin{StaticSem} @Leading@;The library package Interfaces.C.Strings has the following declaration: @begin{example} @key(package) Interfaces.C.Strings @key(is)@ChildUnit{Parent=[Interfaces.C],Child=[Strings]} @key[pragma] Preelaborate(Strings); @key(type) @AdaTypeDefn{char_array_access} @key(is) @key(access) @key(all) char_array; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key(type) @AdaTypeDefn{chars_ptr} @key(is) @key(private);@Chg{Version=[2],New=[ @key(pragma) Preelaborable_Initialization(chars_ptr);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00276-01]} @key(type) @AdaTypeDefn{chars_ptr_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @Chg{Version=[2],New=[@key(aliased) ],Old=[]}chars_ptr; @AdaObjDefn{Null_Ptr} : @key(constant) chars_ptr; @key(function) @AdaSubDefn{To_Chars_Ptr} (Item : @key(in) char_array_access; Nul_Check : @key(in) Boolean := False) @key(return) chars_ptr; @key(function) @AdaSubDefn{New_Char_Array} (Chars : @key(in) char_array) @key(return) chars_ptr; @key(function) @AdaSubDefn{New_String} (Str : @key(in) String) @key(return) chars_ptr; @key(procedure) @AdaSubDefn{Free} (Item : @key(in) @key(out) chars_ptr); @AdaSubDefn{Dereference_Error} : @key(exception); @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr) @key(return) char_array; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) char_array; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr) @key(return) String; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) String; @key(function) @AdaSubDefn{Strlen} (Item : @key(in) chars_ptr) @key(return) size_t; @key(procedure) @AdaSubDefn{Update} (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Chars : @key(in) char_array; Check : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{Update} (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Str : @key(in) String; Check : @key(in) Boolean := True); @AdaSubDefn{Update_Error} : @key(exception); @key(private) ... -- @RI{not specified by the language} @key(end) Interfaces.C.Strings; @end{Example} @begin{discussion} The string manipulation types and subprograms appear in a child of Interfaces.C versus being there directly, since it is useful to have Interfaces.C specified as @nt(pragma) Pure. Differently named functions New_String and New_Char_Array are declared, since if there were a single overloaded function a call with a string literal as actual parameter would be ambiguous. @end{discussion} The type chars_ptr is C-compatible and corresponds to the use of C's @lquotes@;char *@rquotes@; for a pointer to the first char in a char array terminated by nul. When an object of type chars_ptr is declared, its value is by default set to Null_Ptr, unless the object is imported (see @RefSecNum(Interfacing Pragmas)). @begin{discussion} The type char_array_access is not necessarily C-compatible, since an object of this type may carry @lquotes@;dope@rquotes@; information. The programmer should convert from char_array_access to chars_ptr for objects imported from, exported to, or passed to C.@end{discussion} @begin{DescribeCode} @begin{Example}@Keepnext @key(function) To_Chars_Ptr (Item : @key(in) char_array_access; Nul_Check : @key(in) Boolean := False) @key(return) chars_ptr; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0061],ARef=[AI95-00140-01]} @Trailing@;If Item is @key(null), then To_Chars_Ptr returns Null_Ptr. @Chg{New=[If Item is not @key(null),], Old=[Otherwise, if]} Nul_Check is True@Chg{New=[,],Old=[]} and Item.@key(all) does not contain nul, then the function propagates Terminator_Error; @Chg{New=[otherwise], Old=[if Nul_Check is True and Item.@key(all) does contain nul,]} To_Chars_Ptr performs a pointer conversion with no allocation of memory. @begin{Example}@Keepnext @key(function) New_Char_Array (Chars : @key(in) char_array) @key(return) chars_ptr; @end{Example} This function returns a pointer to an allocated object initialized to Chars(Chars'First .. Index) & nul, where @begin{itemize} Index = Chars'Last if Chars does not contain nul, or Index is the smallest size_t value I such that Chars(I+1) = nul. @end{itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@Trailing @Chg{New=[],Old=[@Noparanum@;]}Storage_Error is propagated if the allocation fails. @begin{Example}@Keepnext @key(function) New_String (Str : @key(in) String) @key(return) chars_ptr; @end{Example} @Trailing@;This function is equivalent to New_Char_Array(To_C(Str)). @begin{Example}@Keepnext @key(procedure) Free (Item : @key(in) @key(out) chars_ptr); @end{Example} @Trailing@;If Item is Null_Ptr, then Free has no effect. Otherwise, Free releases the storage occupied by Value(Item), and resets Item to Null_Ptr. @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr) @key(return) char_array; @end{Example} @Trailing@;If Item = Null_Ptr then Value propagates Dereference_Error. Otherwise Value returns the prefix of the array of chars pointed to by Item, up to and including the first nul. The lower bound of the result is 0. If Item does not point to a nul-terminated string, then execution of Value is erroneous. @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) char_array; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0062],ARef=[AI95-00139-01]} @Trailing@;If Item = Null_Ptr then Value@Chg{New=[],Old=[(Item)]} propagates Dereference_Error. Otherwise Value returns the shorter of two arrays@Chg{New=[, either],Old=[:]} the first Length chars pointed to by Item, @Chg{New=[or],Old=[and]} Value(Item). The lower bound of the result is 0. @Chg{New=[If Length is 0, then Value propagates Constraint_Error.],Old=[]} @begin{Ramification} Value(New_Char_Array(Chars)) = Chars if Chars does not contain nul; else Value(New_Char_Array( Chars)) is the prefix of Chars up to and including the first nul. @end{Ramification} @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr) @key(return) String; @end{Example} @Trailing@;Equivalent to To_Ada(Value(Item), Trim_Nul=>True). @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0063],ARef=[AI95-00177-01]} @Trailing@;Equivalent to To_Ada(Value(Item, Length)@Chg{New=[ & nul],Old=[]}, Trim_Nul=>True). @begin{Example}@Keepnext @key(function) Strlen (Item : @key(in) chars_ptr) @key(return) size_t; @end{Example} @Trailing@;Returns @i[Val]'Length@en@;1 where @i[Val] = Value(Item); propagates Dereference_Error if Item = Null_Ptr. @begin{ramification} Strlen returns the number of chars in the array pointed to by Item, up to and including the char immediately before the first nul. Strlen has the same possibility for erroneous execution as Value, in cases where the string has not been nul-terminated. Strlen has the effect of C's strlen function. @end{Ramification} @begin{Example}@Keepnext @key(procedure) Update (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Chars : @key(in) char_array; Check : Boolean := True); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0064],ARef=[AI95-00039-01]} @Leading@;@Chg{New=[If Item = Null_Ptr, then Update propagates Dereference_Error. Otherwise, t],Old=[T]}his procedure updates the value pointed to by Item, starting at position Offset, using Chars as the data to be copied into the array. Overwriting the nul terminator, and skipping with the Offset past the nul terminator, are both prevented if Check is True, as follows: @begin[itemize] Let N = Strlen(Item). If Check is True, then: @begin{inneritemize} If Offset+Chars'Length>N, propagate Update_Error. Otherwise, overwrite the data in the array pointed to by Item, starting at the char at position Offset, with the data in Chars. @end{inneritemize} @Trailing@;If Check is False, then processing is as above, but with no check that Offset+Chars'Length>N. @begin{Ramification} If Chars contains nul, Update's effect may be to @lquotes@;shorten@rquotes@; the pointed-to char array.@end{ramification} @end[itemize] @begin{Example}@Keepnext @key(procedure) Update (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Str : @key(in) String; Check : @key(in) Boolean := True); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00242-01]} Equivalent to Update(Item, Offset, To_C(Str@Chg{Version=[2], New=[, Append_Nul => False],Old=[]}), Check). @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00242-01]} @ChgAdded{Version=[2],Text=[To truncate the Item to the length of Str, use Update(Item, Offset, To_C(Str), Check) instead of Update(Item, Offset, Str, Check). Note that when truncating Item, Item must be longer than Str.]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of any of the following is erroneous if the Item parameter is not null_ptr and Item does not point to a nul-terminated array of chars. @begin[itemize] a Value function not taking a Length parameter, the Free procedure, the Strlen function. @end[itemize] @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Free(X) is also erroneous if the chars_ptr X was not returned by New_Char_Array or New_String. @PDefn2{Term=(erroneous execution),Sec=(cause)} Reading or updating a freed char_array is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Update is erroneous if Check is False and a call with Check equal to True would have propagated Update_Error. @end{erron} @begin{Notes} New_Char_Array and New_String might be implemented either through the allocation function from the C environment (@lquotes@;malloc@rquotes@;) or through Ada dynamic memory allocation (@lquotes@;new@rquotes@;). The key points are @begin{itemize} the returned value (a chars_ptr) is represented as a C @lquotes@;char *@rquotes@; so that it may be passed to C functions; the allocated object should be freed by the programmer via a call of Free, not by a called C function. @end{itemize} @end{Notes} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00242-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Update for a String parameter is now defined to not add a nul character. It did add a nul in Ada 95. This means that programs that used this behavior of Update to truncate a string will no longer work (the string will not be truncated). This change makes Update for a string consistent with Update for a char_array (no implicit nul is added to the end of a char_array).]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type chars_ptr, so that it can be used in preelaborated units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00276-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] The components of chars_ptr_array are aliased so that it can be used to instantiate Interfaces.C.Pointers (that is its intended purpose, which is otherwise mysterious as it has no operations).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0061],ARef=[AI95-00140-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of To_Char_Ptr when Nul_Check is False.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0062],ARef=[AI95-00139-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of Value when the Length is 0.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0063],ARef=[AI95-00177-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of Value to avoid raising Terminator_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0064],ARef=[AI95-00039-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of Update when Item is Null_Ptr.]} @end{DiffWord95} @LabeledSubClause{The Generic Package Interfaces.C.Pointers} @begin{Intro} The generic package Interfaces.C.Pointers allows the Ada programmer to perform C-style operations on pointers. It includes an access type Pointer, Value functions that dereference a Pointer and deliver the designated array, several pointer arithmetic operations, and @lquotes@;copy@rquotes@; procedures that copy the contents of a source pointer into the array designated by a destination pointer. As in C, it treats an object Ptr of type Pointer as a pointer to the first element of an array, so that for example, adding 1 to Ptr yields a pointer to the second element of the array. The generic allows two styles of usage: one in which the array is terminated by a special terminator element; and another in which the programmer needs to keep track of the length. @end{Intro} @begin{StaticSem} @Leading@;The generic library package Interfaces.C.Pointers has the following declaration: @begin{Example} @key(generic) @key(type) Index @key(is) (<>); @key(type) Element @key(is) @key(private); @key(type) Element_Array @key(is) @key(array) (Index @key(range) <>) @key(of) @key(aliased) Element; Default_Terminator : Element; @key(package) Interfaces.C.Pointers @key(is)@ChildUnit{Parent=[Interfaces.C],Child=[Pointers]} @key[pragma] Preelaborate(Pointers); @key(type) @AdaTypeDefn{Pointer} @key(is) @key(access) @key(all) Element; @key(function) @AdaSubDefn{Value}(Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) Element_Array; @key(function) @AdaSubDefn{Value}(Ref : @key(in) Pointer; Length : @key(in) ptrdiff_t) @key(return) Element_Array; @AdaExcDefn{Pointer_Error} : @key(exception); @RI{-- C-style Pointer arithmetic} @key(function) "+" (Left : @key(in) Pointer; Right : @key(in) ptrdiff_t) @key(return) Pointer; @key(function) "+" (Left : @key(in) ptrdiff_t; Right : @key(in) Pointer) @key(return) Pointer; @key(function) "-" (Left : @key(in) Pointer; Right : @key(in) ptrdiff_t) @key(return) Pointer; @key(function) "-" (Left : @key(in) Pointer; Right : @key(in) Pointer) @key(return) ptrdiff_t; @key(procedure) @AdaSubDefn{Increment} (Ref : @key(in) @key(out) Pointer); @key(procedure) @AdaSubDefn{Decrement} (Ref : @key(in) @key(out) Pointer); @key(pragma) Convention (Intrinsic, "+"); @key(pragma) Convention (Intrinsic, "-"); @key(pragma) Convention (Intrinsic, Increment); @key(pragma) Convention (Intrinsic, Decrement); @key(function) @AdaSubDefn{Virtual_Length} (Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) ptrdiff_t; @key(procedure) @AdaSubDefn{Copy_Terminated_Array} (Source : @key(in) Pointer; Target : @key(in) Pointer; Limit : @key(in) ptrdiff_t := ptrdiff_t'Last; Terminator : @key(in) Element := Default_Terminator); @key(procedure) @AdaSubDefn{Copy_Array} (Source : @key(in) Pointer; Target : @key(in) Pointer; Length : @key(in) ptrdiff_t); @key(end) Interfaces.C.Pointers; @end{Example} @Leading@;The type Pointer is C-compatible and corresponds to one use of C's @lquotes@;Element *@rquotes@;. An object of type Pointer is interpreted as a pointer to the initial Element in an Element_Array. Two styles are supported: @begin{Itemize} Explicit termination of an array value with Default_Terminator (a special terminator value); @Trailing@;Programmer-managed length, with Default_Terminator treated simply as a data element. @end{Itemize} @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Value(Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) Element_Array; @end{Example} @Trailing@;This function returns an Element_Array whose value is the array pointed to by Ref, up to and including the first Terminator; the lower bound of the array is Index'First. Interfaces.C.Strings.Dereference_Error is propagated if Ref is @key(null). @begin{Example}@Keepnext @key(function) Value(Ref : @key(in) Pointer; Length : @key(in) ptrdiff_t) @key(return) Element_Array; @end{Example} @Trailing@;This function returns an Element_Array comprising the first Length elements pointed to by Ref. The exception Interfaces.C.Strings.Dereference_Error is propagated if Ref is @key(null). @end{DescribeCode} @Trailing@;The "+" and "@en@;" functions perform arithmetic on Pointer values, based on the Size of the array elements. In each of these functions, Pointer_Error is propagated if a Pointer parameter is @key(null). @begin{DescribeCode} @begin{Example}@Keepnext @key(procedure) Increment (Ref : @key(in) @key(out) Pointer); @end{Example} @Trailing@;Equivalent to Ref := Ref+1. @begin{Example}@Keepnext @key(procedure) Decrement (Ref : @key(in) @key(out) Pointer); @end{Example} @Trailing@;Equivalent to Ref := Ref@en@;1. @begin{Example}@Keepnext @key(function) Virtual_Length (Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) ptrdiff_t; @end{Example} @Trailing@;Returns the number of Elements, up to the one just before the first Terminator, in Value(Ref, Terminator). @begin{Example}@Keepnext @key(procedure) Copy_Terminated_Array (Source : @key(in) Pointer; Target : @key(in) Pointer; Limit : @key(in) ptrdiff_t := ptrdiff_t'Last; Terminator : @key(in) Element := Default_Terminator); @end{Example} @Trailing@;This procedure copies Value(Source, Terminator) into the array pointed to by Target; it stops either after Terminator has been copied, or the number of elements copied is Limit, whichever occurs first. Dereference_Error is propagated if either Source or Target is @key(null). @begin{ramification} It is the programmer's responsibility to ensure that elements are not copied beyond the logical length of the target array. @end{ramification} @begin{ImplNote} The implementation has to take care to check the Limit first. @end{ImplNote} @begin{Example}@Keepnext @key(procedure) Copy_Array (Source : @key(in) Pointer; Target : @key(in) Pointer; Length : @key(in) ptrdiff_t); @end{Example} This procedure copies the first Length elements from the array pointed to by Source, into the array pointed to by Target. Dereference_Error is propagated if either Source or Target is @key(null). @end{DescribeCode} @end{StaticSem} @begin{erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to dereference a Pointer that does not designate an aliased Element. @begin{Discussion} Such a Pointer could arise via "+", "@en@;", Increment, or Decrement.@end{discussion} @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Value(Ref, Terminator) is erroneous if Ref does not designate an aliased Element in an Element_Array terminated by Terminator. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Value(Ref, Length) is erroneous if Ref does not designate an aliased Element in an Element_Array containing at least Length Elements between the designated Element and the end of the array, inclusive. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Virtual_Length(Ref, Terminator) is erroneous if Ref does not designate an aliased Element in an Element_Array terminated by Terminator. @Leading@PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Copy_Terminated_Array(Source, Target, Limit, Terminator) is erroneous in either of the following situations: @begin[itemize] Execution of both Value(Source, Terminator) and Value(Source, Limit) are erroneous, or Copying writes past the end of the array containing the Element designated by Target. @end[Itemize] @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Copy_Array(Source, Target, Length) is erroneous if either Value(Source, Length) is erroneous, or copying writes past the end of the array containing the Element designated by Target. @end{erron} @begin{Notes} @Leading@;To compose a Pointer from an Element_Array, use 'Access on the first element. For example (assuming appropriate instantiations): @begin{example} Some_Array : Element_Array(0..5) ; Some_Pointer : Pointer := Some_Array(0)'Access; @end{example} @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of Interfaces.C.Pointers:} @begin{Example} @key(with) Interfaces.C.Pointers; @key(with) Interfaces.C.Strings; @key(procedure) Test_Pointers @key(is) @key(package) C @key(renames) Interfaces.C; @key(package) Char_Ptrs @key(is) @key(new) C.Pointers (Index => C.size_t, Element => C.char, Element_Array => C.char_array, Default_Terminator => C.nul); @key(use) @key(type) Char_Ptrs.Pointer; @key(subtype) Char_Star @key(is) Char_Ptrs.Pointer; @key(procedure) Strcpy (Target_Ptr, Source_Ptr : Char_Star) @key(is) Target_Temp_Ptr : Char_Star := Target_Ptr; Source_Temp_Ptr : Char_Star := Source_Ptr; Element : C.char; @key(begin) @key(if) Target_Temp_Ptr = @key(null) @key(or) Source_Temp_Ptr = @key(null) @key(then) @key(raise) C.Strings.Dereference_Error; @key(end if); @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0065],ARef=[AI95-00142-01]} @key(loop) Element := Source_Temp_Ptr.@key(all); Target_Temp_Ptr.@key(all) := Element; @key(exit) @key(when) @Chg{New=[C."="(Element, C.nul)],Old=[Element = C.nul]}; Char_Ptrs.Increment(Target_Temp_Ptr); Char_Ptrs.Increment(Source_Temp_Ptr); @key(end) @key(loop); @key(end) Strcpy; @key(begin) ... @key(end) Test_Pointers; @end{Example} @end{Examples} @LabeledAddedSubClause{Version=[2],Name=[Pragma Unchecked_Union]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[union],Sec=[C]} @Redundant[A pragma Unchecked_Union specifies an interface correspondence between a given discriminated type and some C union. The pragma specifies that the associated type shall be given a representation that leaves no space for its discriminant(s).]]} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[The form of a pragma Unchecked_Union is as follows:]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag{Unchecked_Union} (@Syni<first_subtype_>@Syn2<local_name>);''} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Unchecked_Union is a representation pragma, specifying the unchecked union aspect of representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[The @SynI{first_subtype_}@nt{local_name} of a @nt{pragma} Unchecked_Union shall denote an unconstrained discriminated record subtype having a @nt{variant_part}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[@Defn{unchecked union type} @Defn{unchecked union subtype} @Defn{unchecked union object} A type to which a pragma Unchecked_Union applies is called an @i<unchecked union type>. A subtype of an unchecked union type is defined to be an @i<unchecked union subtype>. An object of an unchecked union type is defined to be an @i<unchecked union object>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[All component subtypes of an unchecked union type shall be C-compatible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[If a component subtype of an unchecked union type is subject to a per-object constraint, then the component subtype shall be an unchecked union subtype.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[A component declared in a @nt{variant_part} of an unchecked union type shall not have a controlled, protected, or task part.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[The completion of an incomplete or private type declaration having a @nt{known_discriminant_part} shall not be an unchecked union type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An unchecked union subtype shall only be passed as a generic actual parameter if the corresponding formal type has no known discriminants or is an unchecked union type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This includes formal private types without a @nt{known_discriminant_part}, formal derived types that do not inherit any discriminants (formal derived types do not have @nt{known_discriminant_part}s), and formal derived types that are unchecked union types.]} @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An unchecked union type is eligible for convention C.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[All objects of an unchecked union type have the same size.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Discriminants of objects of an unchecked union type are of size zero.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[Any check which would require reading a discriminant of an unchecked union object is suppressed (see @RefSecNum{Suppressing Checks}). These checks include:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check performed when addressing a variant component (i.e., a component that was declared in a variant part) of an unchecked union object that the object has this component (see @RefSecNum{Selected Components}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any checks associated with a type or subtype conversion of a value of an unchecked union type (see @RefSecNum{Type Conversions}). This includes, for example, the check associated with the implicit subtype conversion of an assignment statement.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The subtype membership check associated with the evaluation of a qualified expression (see @RefSecNum{Qualified Expressions}) or an uninitialized allocator (see @RefSecNum{Allocators}).]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a suppressed check would have failed, execution is erroneous (see @RefSecNum{Suppressing Checks}). An implementation is always allowed to make a suppressed check if it can somehow determine the discriminant value.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[A view of an unchecked union object (including a type conversion or function call) has @i<inferable discriminants> if it has a constrained nominal subtype, unless the object is a component of an enclosing unchecked union object that is subject to a per-object constraint and the enclosing object lacks inferable discriminants.@Defn{inferable discriminants}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An expression of an unchecked union type has inferable discriminants if it is either a name of an object with inferable discriminants or a qualified expression whose @nt{subtype_mark} denotes a constrained subtype.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[Program_Error is raised in the following cases:@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of the predefined equality operator for a type which has a subcomponent of an unchecked union type whose nominal subtype is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of a membership test if the @nt{subtype_mark} denotes a constrained unchecked union subtype and the expression lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Conversion from a derived unchecked union type to an unconstrained non-unchecked-union type if the operand of the conversion lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Write or Read attribute of an unchecked union type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Output or Input attribute of an unchecked union type if the type lacks default discriminant values.]} @end{Itemize} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An implementation may require that @nt{pragma} Controlled be specified for the type of an access subcomponent of an unchecked union type.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[The use of an unchecked union to obtain the effect of an unchecked conversion results in erroneous execution (see @RefSecNum{Suppressing Checks}). Execution of the following example is erroneous even if Float'Size = Integer'Size:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<type> T (Flag : Boolean := False) @key<is> @key<record> @key<case> Flag @key<is> @key<when> False => F1 : Float := 0.0; @key<when> True => F2 : Integer := 0; @key<end case>; @key<end record>; @key<pragma> Unchecked_Union (T);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[X : T; Y : Integer := X.F2; -- @RI[erroneous]]} @end{Example} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Unchecked_Union is new.]} @end{Extend95} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{Interfacing with COBOL} @begin{Intro} @Defn{interface to COBOL} @Defn{COBOL interface} The facilities relevant to interfacing with the COBOL language are the package Interfaces.COBOL and support for the Import, Export and Convention pragmas with @i{convention}_@nt{identifier} COBOL. @Leading@;The COBOL interface package supplies several sets of facilities: @begin{itemize} A set of types corresponding to the native COBOL types of the supported COBOL implementation (so-called @lquotes@;internal COBOL representations@rquotes@;), allowing Ada data to be passed as parameters to COBOL programs A set of types and constants reflecting external data representations such as might be found in files or databases, allowing COBOL-generated data to be read by an Ada program, and Ada-generated data to be read by COBOL programs A generic package for converting between an Ada decimal type value and either an internal or external COBOL representation @end{itemize} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.COBOL has the following declaration: @begin{Example} @key(package) Interfaces.COBOL @key(is)@ChildUnit{Parent=[Interfaces],Child=[COBOL]} @key[pragma] Preelaborate(COBOL); @RI{-- Types and operations for internal data representations} @key(type) @AdaTypeDefn{Floating} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Long_Floating} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Binary} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Long_Binary} @key(is) @key(range) @RI{implementation-defined}; @AdaObjDefn{Max_Digits_Binary} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Max_Digits_Long_Binary} : @key(constant) := @RI{implementation-defined}; @key(type) @AdaTypeDefn{Decimal_Element} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Packed_Decimal} @key(is) @key(array) (Positive @key(range) <>) @key(of) Decimal_Element; @key(pragma) Pack(Packed_Decimal); @key(type) @AdaTypeDefn{COBOL_Character} @key(is) @RI{implementation-defined character type}; @AdaObjDefn{Ada_To_COBOL} : @key(array) (Character) @key(of) COBOL_Character := @RI{implementation-defined}; @AdaObjDefn{COBOL_To_Ada} : @key(array) (COBOL_Character) @key(of) Character := @RI{implementation-defined}; @key(type) @AdaTypeDefn{Alphanumeric} @key(is) @key(array) (Positive range <>) @key(of) COBOL_Character; @key(pragma) Pack(Alphanumeric); @key(function) @AdaSubDefn{To_COBOL} (Item : @key(in) String) @key(return) Alphanumeric; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) Alphanumeric) @key(return) String; @key(procedure) @AdaSubDefn{To_COBOL} (Item : @key(in) String; Target : @key(out) Alphanumeric; Last : @key(out) Natural); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) Alphanumeric; Target : @key(out) String; Last : @key(out) Natural); @key(type) @AdaTypeDefn{Numeric} @key(is) @key(array) (Positive @key[range] <>) @key(of) COBOL_Character; @key(pragma) Pack(Numeric); @RI{-- Formats for COBOL data representations} @key(type) @AdaTypeDefn{Display_Format} @key(is) @key(private); @AdaObjDefn{Unsigned} : @key(constant) Display_Format; @AdaObjDefn{Leading_Separate} : @key(constant) Display_Format; @AdaObjDefn{Trailing_Separate} : @key(constant) Display_Format; @AdaObjDefn{Leading_Nonseparate} : @key(constant) Display_Format; @AdaObjDefn{Trailing_Nonseparate} : @key(constant) Display_Format; @key(type) @AdaTypeDefn{Binary_Format} @key(is) @key(private); @AdaObjDefn{High_Order_First} : @key(constant) Binary_Format; @AdaObjDefn{Low_Order_First} : @key(constant) Binary_Format; @AdaObjDefn{Native_Binary} : @key(constant) Binary_Format; @key(type) @AdaTypeDefn{Packed_Format} @key(is) @key(private); @AdaObjDefn{Packed_Unsigned} : @key(constant) Packed_Format; @AdaObjDefn{Packed_Signed} : @key(constant) Packed_Format; @RI{-- Types for external representation of COBOL binary data} @key(type) @AdaTypeDefn{Byte} @key(is) @key(mod) 2**COBOL_Character'Size; @key(type) @AdaTypeDefn{Byte_Array} @key(is) @key(array) (Positive @key(range) <>) @key(of) Byte; @key(pragma) Pack (Byte_Array); @AdaExcDefn{Conversion_Error} : @key(exception); @key(generic) @key(type) Num @key(is) @key(delta) <> @key(digits) <>; @key(package) @AdaPackDefn{Decimal_Conversions} @key(is) @RI{-- Display Formats: data values are represented as Numeric} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Display_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Display} (Item : @key(in) Num; Format : @key(in) Display_Format) @key(return) Numeric; @RI{-- Packed Formats: data values are represented as Packed_Decimal} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Packed_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Packed} (Item : @key(in) Num; Format : @key(in) Packed_Format) @key(return) Packed_Decimal; @RI{-- Binary Formats: external data values are represented as Byte_Array} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Binary_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Binary} (Item : @key(in) Num; Format : @key(in) Binary_Format) @key(return) Byte_Array; @RI{-- Internal Binary formats: data values are of type Binary or Long_Binary} @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Binary) @key(return) Num; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Long_Binary) @key(return) Num; @key(function) @AdaSubDefn{To_Binary} (Item : @key(in) Num) @key(return) Binary; @key(function) @AdaSubDefn{To_Long_Binary} (Item : @key(in) Num) @key(return) Long_Binary; @key(end) Decimal_Conversions; @key(private) ... -- @RI{not specified by the language} @key(end) Interfaces.COBOL; @end{Example} @ChgImplDef{Version=[1],Kind=[Revised],Text=[The types Floating, Long_Floating, Binary, Long_Binary, Decimal_Element, and COBOL_Character; and the initializations of the variables Ada_To_COBOL and COBOL_To_Ada, in Interfaces.COBOL@Chg{New=[.],Old=[]}]} Each of the types in Interfaces.COBOL is COBOL-compatible. The types Floating and Long_Floating correspond to the native types in COBOL for data items with computational usage implemented by floating point. The types Binary and Long_Binary correspond to the native types in COBOL for data items with binary usage, or with computational usage implemented by binary. Max_Digits_Binary is the largest number of decimal digits in a numeric value that is represented as Binary. Max_Digits_Long_Binary is the largest number of decimal digits in a numeric value that is represented as Long_Binary. The type Packed_Decimal corresponds to COBOL's packed-decimal usage. The type COBOL_Character defines the run-time character set used in the COBOL implementation. Ada_To_COBOL and COBOL_To_Ada are the mappings between the Ada and COBOL run-time character sets. @begin{reason} The character mappings are visible variables, since the user needs the ability to modify them at run time. @end{reason} Type Alphanumeric corresponds to COBOL's alphanumeric data category. Each of the functions To_COBOL and To_Ada converts its parameter based on the mappings Ada_To_COBOL and COBOL_To_Ada, respectively. The length of the result for each is the length of the parameter, and the lower bound of the result is 1. Each component of the result is obtained by applying the relevant mapping to the corresponding component of the parameter. Each of the procedures To_COBOL and To_Ada copies converted elements from Item to Target, using the appropriate mapping (Ada_To_COBOL or COBOL_To_Ada, respectively). The index in Target of the last element assigned is returned in Last (0 if Item is a null array). @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Item'Length exceeds Target'Length, Constraint_Error is propagated. Type Numeric corresponds to COBOL's numeric data category with display usage. @Trailing@;The types Display_Format, Binary_Format, and Packed_Format are used in conversions between Ada decimal type values and COBOL internal or external data representations. The value of the constant Native_Binary is either High_Order_First or Low_Order_First, depending on the implementation. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Boolean; @end{Example} @Leading@;The function Valid checks that the Item parameter has a value consistent with the value of Format. If the value of Format is other than Unsigned, Leading_Separate, and Trailing_Separate, the effect is implementation defined. If Format does have one of these values, the following rules apply: @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} Format=Unsigned: if Item comprises @Chg{New=[],Old=[zero or more leading space characters followed by ]}one or more decimal digit characters then Valid returns True, else it returns False. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} Format=Leading_Separate: if Item comprises @Chg{New=[],Old=[zero or more leading space characters, followed by ]}a single occurrence of the plus or minus sign character, and then one or more decimal digit characters, then Valid returns True, else it returns False. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} @Trailing@;Format=Trailing_Separate: if Item comprises @Chg{New=[],Old=[zero or more leading space characters, followed by ]}one or more decimal digit characters and finally a plus or minus sign character, then Valid returns True, else it returns False. @end{itemize} @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Display_Format) @key(return) Natural; @end{Example} @Trailing@;The Length function returns the minimal length of a Numeric value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. The number of digits after the assumed radix point in Item is Num'Scale. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{discussion} There is no issue of truncation versus rounding, since the number of decimal places is established by Num'Scale.@end{discussion} @begin{Example}@Keepnext @key(function) To_Display (Item : @key(in) Num; Format : @key(in) Display_Format) @key(return) Numeric; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Numeric value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1. ],Old=[]}Conversion_Error is propagated if Num is negative and Format is Unsigned. @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Boolean; @end{Example} @Trailing@;This function returns True if Item has a value consistent with Format, and False otherwise. The rules for the formation of Packed_Decimal values are implementation defined. @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Packed_Format) @key(return) Natural; @end{Example} @Trailing@;This function returns the minimal length of a Packed_Decimal value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. Num'Scale is the number of digits after the assumed radix point in Item. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{Example}@Keepnext @key(function) To_Packed (Item : @key(in) Num; Format : @key(in) Packed_Format) @key(return) Packed_Decimal; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Packed_Decimal value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1. ],Old=[]}Conversion_Error is propagated if Num is negative and Format is Packed_Unsigned. @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Boolean; @end{Example} @Trailing@;This function returns True if Item has a value consistent with Format, and False otherwise. @begin{ramification} This function returns False only when the represented value is outside the range of Num.@end{ramification} @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Binary_Format) @key(return) Natural; @end{Example} @Trailing@;This function returns the minimal length of a Byte_Array value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. Num'Scale is the number of digits after the assumed radix point in Item. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{Example}@Keepnext @key(function) To_Binary (Item : @key(in) Num; Format : @key(in) Binary_Format) @key(return) Byte_Array; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Byte_Array value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1.],Old=[]} @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Binary) @key(return) Num; @comment{Blank line} @key(function) To_Decimal (Item : @key(in) Long_Binary) @key(return) Num; @end{Example} @Trailing@;These functions convert from COBOL binary format to a corresponding value of the decimal type Num. Conversion_Error is propagated if Item is too large for Num. @begin{Ramification} There is no rescaling performed on the conversion. That is, the returned value in each case is a @lquotes@;bit copy@rquotes@; if Num has a binary radix. The programmer is responsible for maintaining the correct scale. @end{ramification} @begin{Example}@Keepnext @key(function) To_Binary (Item : @key(in) Num) @key(return) Binary; @comment{Blank line} @key(function) To_Long_Binary (Item : @key(in) Num) @key(return) Long_Binary; @end{Example} These functions convert from Ada decimal to COBOL binary format. Conversion_Error is propagated if the value of Item is too large to be represented in the result type. @begin{discussion} One style of interface supported for COBOL, similar to what is provided for C, is the ability to call and pass parameters to an existing COBOL program. Thus the interface package supplies types that can be used in an Ada program as parameters to subprograms whose bodies will be in COBOL. These types map to COBOL's alphanumeric and numeric data categories. Several types are provided for support of alphanumeric data. Since COBOL's run-time character set is not necessarily the same as Ada's, Interfaces.COBOL declares an implementation-defined character type COBOL_Character, and mappings between Character and COBOL_Character. These mappings are visible variables (rather than, say, functions or constant arrays), since in the situation where COBOL_Character is EBCDIC, the flexibility of dynamically modifying the mappings is needed. Corresponding to COBOL's alphanumeric data is the string type Alphanumeric. Numeric data may have either a @lquotes@;display@rquotes@; or @lquotes@;computational@rquotes@; representation in COBOL. On the Ada side, the data is of a decimal fixed point type. Passing an Ada decimal data item to a COBOL program requires conversion from the Ada decimal type to some type that reflects the representation expected on the COBOL side. @begin{Itemize} Computational Representation @NoPrefix@;Floating point representation is modeled by Ada floating point types, Floating and Long_Floating. Conversion between these types and Ada decimal types is obtained directly, since the type name serves as a conversion function. @NoPrefix@;Binary representation is modeled by an Ada integer type, Binary, and possibly other types such as Long_Binary. Conversion between, say, Binary and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. @NoPrefix@;Packed decimal representation is modeled by the Ada array type Packed_Decimal. Conversion between packed decimal and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. Display Representation @NoPrefix@;Display representation for numeric data is modeled by the array type Numeric. Conversion between display representation and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. A parameter to the conversion function indicates the desired interpretation of the data (e.g., signed leading separate, etc.) @end{Itemize} Pragma Convention(COBOL, T) may be applied to a record type T to direct the compiler to choose a COBOL-compatible representation for objects of the type. The package Interfaces.COBOL allows the Ada programmer to deal with data from files (or databases) created by a COBOL program. For data that is alphanumeric, or in display or packed decimal format, the approach is the same as for passing parameters (instantiate Decimal_Conversions to obtain the needed conversion functions). For binary data, the external representation is treated as a Byte array, and an instantiation of Decimal_IO produces a package that declares the needed conversion functions. A parameter to the conversion function indicates the desired interpretation of the data (e.g., high- versus low-order byte first). @end{discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} An implementation shall support pragma Convention with a COBOL @i[convention]_@nt[identifier] for a COBOL-eligible type (see @RefSecNum(Interfacing Pragmas)). @begin{ramification} An implementation supporting this package shall ensure that if the bounds of a Packed_Decimal, Alphanumeric, or Numeric variable are static, then the representation of the object comprises solely the array components (that is, there is no implicit run-time @lquotes@;descriptor@rquotes@; that is part of the object). @end{ramification} @end{ImplReq} @begin{ImplPerm} An implementation may provide additional constants of the private types Display_Format, Binary_Format, or Packed_Format. @begin{Reason} This is to allow exploitation of other external formats that may be available in the COBOL implementation.@end{reason} An implementation may provide further floating point and integer types in Interfaces.COBOL to match additional native COBOL types, and may also supply corresponding conversion functions in the generic package Decimal_Conversions. @end{ImplPerm} @begin{ImplAdvice} An Ada implementation should support the following interface correspondences between Ada and COBOL. @begin[itemize] An Ada @key[access] T parameter is passed as a @lquotes@;BY REFERENCE@rquotes@; data item of the COBOL type corresponding to T. An Ada @key[in] scalar parameter is passed as a @lquotes@;BY CONTENT@rquotes@; data item of the corresponding COBOL type. Any other Ada parameter is passed as a @lquotes@;BY REFERENCE@rquotes@; data item of the COBOL type corresponding to the Ada parameter type; for scalars, a local copy is used if necessary to ensure by-copy semantics. @end[itemize] @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If COBOL interfacing is supported, the interface correspondences between Ada and COBOL should be supported.]}]} @end{ImplAdvice} @begin[Notes] An implementation is not required to support pragma Convention for access types, nor is it required to support pragma Import, Export or Convention for functions. @begin{reason} COBOL does not have a pointer facility, and a COBOL program does not return a value.@end{reason} If an Ada subprogram is exported to COBOL, then a call from COBOL call may specify either @lquotes@;BY CONTENT@rquotes@; or @lquotes@;BY REFERENCE@rquotes@;. @end[Notes] @begin{Examples} @Leading@Keepnext@i{Examples of Interfaces.COBOL:} @begin{Example} @key(with) Interfaces.COBOL; @key(procedure) Test_Call @key(is) @RI{-- Calling a foreign COBOL program} @RI{-- Assume that a COBOL program PROG has the following declaration} @RI{-- in its LINKAGE section:} @RI{-- 01 Parameter-Area} @RI{-- 05 NAME PIC X(20).} @RI{-- 05 SSN PIC X(9).} @RI{-- 05 SALARY PIC 99999V99 USAGE COMP.} @RI{-- The effect of PROG is to update SALARY based on some algorithm} @key(package) COBOL @key(renames) Interfaces.COBOL; @key(type) Salary_Type @key(is) @key(delta) 0.01 @key(digits) 7; @key(type) COBOL_Record @key(is) @key(record) Name : COBOL.Numeric(1..20); SSN : COBOL.Numeric(1..9); Salary : COBOL.Binary; @RI{-- Assume Binary = 32 bits} @key(end) @key(record); @key(pragma) Convention (COBOL, COBOL_Record); @key(procedure) Prog (Item : @key(in) @key(out) COBOL_Record); @key(pragma) Import (COBOL, Prog, "PROG"); @key(package) Salary_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Salary_Type); Some_Salary : Salary_Type := 12_345.67; Some_Record : COBOL_Record := (Name => "Johnson, John ", SSN => "111223333", Salary => Salary_Conversions.To_Binary(Some_Salary)); @key(begin) Prog (Some_Record); ... @key(end) Test_Call; @end{Example} @begin{Example} @key(with) Interfaces.COBOL; @key(with) COBOL_Sequential_IO; @RI{-- Assumed to be supplied by implementation} @key(procedure) Test_External_Formats @key(is) @RI{-- Using data created by a COBOL program} @RI{-- Assume that a COBOL program has created a sequential file with} @RI{-- the following record structure, and that we need to} @RI{-- process the records in an Ada program} @RI{-- 01 EMPLOYEE-RECORD} @RI{-- 05 NAME PIC X(20).} @RI{-- 05 SSN PIC X(9).} @RI{-- 05 SALARY PIC 99999V99 USAGE COMP.} @RI{-- 05 ADJUST PIC S999V999 SIGN LEADING SEPARATE.} @RI{-- The COMP data is binary (32 bits), high-order byte first} @key(package) COBOL @key(renames) Interfaces.COBOL; @key(type) Salary_Type @key(is) @key(delta) 0.01 @key(digits) 7; @key(type) Adjustments_Type @key(is) @key(delta) 0.001 @key(digits) 6; @key(type) COBOL_Employee_Record_Type @key(is) @RI{-- External representation} @key(record) Name : COBOL.Alphanumeric(1..20); SSN : COBOL.Alphanumeric(1..9); Salary : COBOL.Byte_Array(1..4); Adjust : COBOL.Numeric(1..7); @RI{-- Sign and 6 digits} @key(end) @key(record); @key(pragma) Convention (COBOL, COBOL_Employee_Record_Type); @key(package) COBOL_Employee_IO @key(is) @key(new) COBOL_Sequential_IO(COBOL_Employee_Record_Type); @key(use) COBOL_Employee_IO; COBOL_File : File_Type; @key(type) Ada_Employee_Record_Type @key(is) @RI{-- Internal representation} @key(record) Name : String(1..20); SSN : String(1..9); Salary : Salary_Type; Adjust : Adjustments_Type; @key(end) @key(record); COBOL_Record : COBOL_Employee_Record_Type; Ada_Record : Ada_Employee_Record_Type; @key(package) Salary_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Salary_Type); @key(use) Salary_Conversions; @key(package) Adjustments_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Adjustments_Type); @key(use) Adjustments_Conversions; @key(begin) Open (COBOL_File, Name => "Some_File"); @key(loop) Read (COBOL_File, COBOL_Record); Ada_Record.Name := To_Ada(COBOL_Record.Name); Ada_Record.SSN := To_Ada(COBOL_Record.SSN); Ada_Record.Salary := To_Decimal(COBOL_Record.Salary, COBOL.High_Order_First); Ada_Record.Adjust := To_Decimal(COBOL_Record.Adjust, COBOL.Leading_Separate); ... @RI{-- Process Ada_Record} @key(end) @key(loop); @key(exception) @key[when] End_Error => ... @key(end) Test_External_Formats; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0066],ARef=[AI95-00071-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of Valid to match COBOL.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0067],ARef=[AI95-00072-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Specified the bounds of the results of To_Display, To_Packed, and To_Binary.]} @end{DiffWord95} @LabeledClause{Interfacing with Fortran} @begin{Intro} @Defn{interface to Fortran} @Defn{Fortran interface} The facilities relevant to interfacing with the Fortran language are the package Interfaces.Fortran and support for the Import, Export and Convention pragmas with @i{convention}_@nt{identifier} Fortran. The package Interfaces.Fortran defines Ada types whose representations are identical to the default representations of the Fortran intrinsic types Integer, Real, Double Precision, Complex, Logical, and Character in a supported Fortran implementation. These Ada types can therefore be used to pass objects between Ada and Fortran programs. @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.Fortran has the following declaration: @begin{Example} @key[with] Ada.Numerics.Generic_Complex_Types; @RI{-- see @RefSecNum{Complex Types}} @key[pragma] Elaborate_All(Ada.Numerics.Generic_Complex_Types); @key[package] Interfaces.Fortran @key[is]@ChildUnit{Parent=[Interfaces],Child=[Fortran]} @key[pragma] Pure(Fortran); @key[type] @AdaTypeDefn{Fortran_Integer} @key[is] @key[range] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Real} @key[is] @key[digits] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Double_Precision} @key[is] @key[digits] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Logical} @key[is] @key[new] Boolean; @key[package] @AdaPackDefn{Single_Precision_Complex_Types} @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (Real); @key[type] @AdaTypeDefn{Complex} @key[is] @key[new] Single_Precision_Complex_Types.Complex; @key[subtype] @AdaSubtypeDefn{Name=[Imaginary],Of=[Imaginary]} @key[is] Single_Precision_Complex_Types.Imaginary; @AdaObjDefn{i} : Imaginary @key[renames] Single_Precision_Complex_Types.i; @AdaObjDefn{j} : Imaginary @key[renames] Single_Precision_Complex_Types.j; @key[type] @AdaTypeDefn{Character_Set} @key[is] @RI{implementation-defined character type}; @key[type] @AdaTypeDefn{Fortran_Character} @key[is] @key[array] (Positive @key[range] <>) @key[of] Character_Set; @key[pragma] Pack (Fortran_Character); @key[function] @AdaSubDefn{To_Fortran} (Item : @key[in] Character) @key[return] Character_Set; @key[function] @AdaSubDefn{To_Ada} (Item : @key[in] Character_Set) @key[return] Character; @key(function) @AdaSubDefn{To_Fortran} (Item : @key(in) String) @key(return) Fortran_Character; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) Fortran_Character) @key(return) String; @key(procedure) @AdaSubDefn{To_Fortran} (Item : @key(in) String; Target : @key(out) Fortran_Character; Last : @key(out) Natural); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) Fortran_Character; Target : @key(out) String; Last : @key(out) Natural); @key[end] Interfaces.Fortran; @end{Example} @ChgImplDef{Version=[1],Kind=[Added],Text=[@Chg{New=[The types Fortran_Integer, Real, Double_Precision, and Character_Set in Interfaces.Fortran.],Old=[]}]} @begin{Ramification} The means by which the Complex type is provided in Interfaces.Fortran creates a dependence of Interfaces.Fortran on Numerics.Generic_Complex_Types (see @RefSecNum{Complex Types}). This dependence is intentional and unavoidable, if the Fortran-compatible Complex type is to be useful in Ada code without duplicating facilities defined elsewhere. @end{Ramification} The types Fortran_Integer, Real, Double_Precision, Logical, Complex, and Fortran_Character are Fortran-compatible. The To_Fortran and To_Ada functions map between the Ada type Character and the Fortran type Character_Set, and also between the Ada type String and the Fortran type Fortran_Character. The To_Fortran and To_Ada procedures have analogous effects to the string conversion subprograms found in Interfaces.COBOL. @end{StaticSem} @begin[ImplReq] An implementation shall support @nt[pragma] Convention with a Fortran @i[convention]_@nt[identifier] for a Fortran-eligible type (see @RefSecNum(Interfacing Pragmas)). @end[ImplReq] @begin{ImplPerm} An implementation may add additional declarations to the Fortran interface packages. For example, the Fortran interface package for an implementation of Fortran 77 (ANSI X3.9-1978) that defines types like Integer*@i{n}, Real*@i{n}, Logical*@i{n}, and Complex*@i{n} may contain the declarations of types named Integer_@!Star_@i{n}, Real_@!Star_@i{n}, Logical_@!Star_@i{n}, and Complex_@!Star_@i{n}. (This convention should not apply to Character*@i{n}, for which the Ada analog is the constrained array subtype Fortran_Character (1..@i{n}).) Similarly, the Fortran interface package for an implementation of Fortran 90 that provides multiple @i{kinds} of intrinsic types, e.g. Integer (Kind=@i{n}), Real (Kind=@i{n}), Logical (Kind=@i{n}), Complex (Kind=@i{n}), and Character (Kind=@i{n}), may contain the declarations of types with the recommended names Integer_Kind_@i{n}, Real_Kind_@i{n}, Logical_Kind_@i{n}, Complex_Kind_@i{n}, and Character_Kind_@i{n}. @begin[discussion] Implementations may add auxiliary declarations as needed to assist in the declarations of additional Fortran-compatible types. For example, if a double precision complex type is defined, then Numerics.@!Generic_@!Complex_@!Types may be instantiated for the double precision type. Similarly, if a wide character type is defined to match a Fortran 90 wide character type (accessible in Fortran 90 with the Kind modifier), then an auxiliary character set may be declared to serve as its component type. @end[discussion] @end{ImplPerm} @begin{ImplAdvice} @Leading@;An Ada implementation should support the following interface correspondences between Ada and Fortran: @begin[itemize] An Ada procedure corresponds to a Fortran subroutine. An Ada function corresponds to a Fortran function. An Ada parameter of an elementary, array, or record type T is passed as a T@-(F) argument to a Fortran procedure, where T@-(F) is the Fortran type corresponding to the Ada type T, and where the INTENT attribute of the corresponding dummy argument matches the Ada formal parameter mode; the Fortran implementation's parameter passing conventions are used. For elementary types, a local copy is used if necessary to ensure by-copy semantics. An Ada parameter of an access-to-subprogram type is passed as a reference to a Fortran procedure whose interface corresponds to the designated subprogram's specification. @end[itemize] @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If Fortran interfacing is supported, the interface correspondences between Ada and Fortran should be supported.]}]} @end{ImplAdvice} @begin[Notes] An object of a Fortran-compatible record type, declared in a library package or subprogram, can correspond to a Fortran common block; the type also corresponds to a Fortran @lquotes@;derived type@rquotes@;. @end[Notes] @begin{Examples} @Leading@Keepnext@i{Example of Interfaces.Fortran:} @begin{Example} @key[with] Interfaces.Fortran; @key[use] Interfaces.Fortran; @key[procedure] Ada_Application @key[is] @key[type] Fortran_Matrix @key[is] @key[array] (Integer @key[range] <>, Integer @key[range] <>) @key[of] Double_Precision; @key[pragma] Convention (Fortran, Fortran_Matrix); @RI{-- stored in Fortran's} @RI{-- column-major order} @key[procedure] Invert (Rank : @key[in] Fortran_Integer; X : @key[in] @key[out] Fortran_Matrix); @key[pragma] Import (Fortran, Invert); @RI{-- a Fortran subroutine} Rank : @key[constant] Fortran_Integer := 100; My_Matrix : Fortran_Matrix (1 .. Rank, 1 .. Rank); @key[begin] ... My_Matrix := ...; ... Invert (Rank, My_Matrix); ... @key[end] Ada_Application; @end{Example} @end{Examples}�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/iso-rm.msm�����������������������������������������������������������0000755�0001752�0001001�00000013221�12273462240�017344� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the RM (ISO version)} @Comment{Global properties} @HideIndexEntries @HideAnnotations @ShowISO @Comment{Paragraphs are not numbered here} @Title{Version=[0],Text=[Ada Reference Manual]}@Comment{Same title for all versions} @FilePrefix{8652} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @RTFHeaderPrefix{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @RTFHeaderPrefix{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]} @RTFPageSize{A4} @RTFFonts{Serif=[Times],SansSerif=[Helvetica]}@Command{ISO requires the latter} @Comment{HTML properties - generally, no HTML version is made of the ISO version, so these settings aren't important} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]} @HTMLNavBar{RefName=[8652-STDS.html],SrchName=[8652-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><SPAN Style="font-size:200%; color: rgb(0,0,153)"><B>Ada Reference Manual</B></SPAN> — <A HREF="8652-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="vertical-align: middle">Sponsored by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO requires skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO requires skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/langdef.mss����������������������������������������������������������0000755�0001752�0001001�00000004150�12273462240�017545� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(glossary, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:32 $} @LabeledAddedInformativeAnnex{Version=[2],Name=[Language-Defined Entities]} @comment{$Source: e:\\cvsroot/ARM/Source/langdef.mss,v $} @comment{$Revision: 1.3 $} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This annex lists the language-defined entities of the language. A list of language-defined library units can be found in @RefSec{Predefined Language Environment}.]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Language-Defined Packages]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This clause lists all language-defined packages.]} @end{Intro} @PackageList @LabeledAddedClause{Version=[2],Name=[Language-Defined Types and Subtypes]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This clause lists all language-defined types and subtypes.]} @end{Intro} @TypeList @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledAddedClause{Version=[2],Name=[Language-Defined Subprograms]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This clause lists all language-defined subprograms.]} @end{Intro} @SubprogramList @LabeledAddedClause{Version=[2],Name=[Language-Defined Exceptions]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This clause lists all language-defined exceptions.]} @end{Intro} @ExceptionList @LabeledAddedClause{Version=[2],Name=[Language-Defined Objects]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This clause lists all language-defined constants, variables, named numbers, and enumeration literals.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Formally, named numbers and enumeration literals aren't objects, but it was thought to be too weird to say @lquotes@;Language-Defined Objects and Values@rquotes.]} @end{Honest} @end{Intro} @ObjectList ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/library.mss����������������������������������������������������������0000755�0001752�0001001�00000000377�12273462240�017620� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(library, Root="ada.mss") @Comment{$Date: 2000/05/27 04:44:03 $} @comment{$Source: e:\\cvsroot/ARM/Source/library.mss,v $} @comment{$Revision: 1.2 $} @comment{$RLB: This is the library separator page. $} @UnnumberedSection{The Standard Libraries} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/numerics.mss���������������������������������������������������������0000755�0001752�0001001�00000634421�12273462240�020004� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/numerics.mss,v $ } @comment{ $Revision: 1.54 $ $Date: 2006/10/19 06:40:29 $ $Author: Randy $ } @Part(numerics, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:29 $} @LabeledNormativeAnnex{Numerics} @begin{Intro} @Defn{numerics} The Numerics Annex specifies @begin{itemize} features for complex arithmetic, including complex I/O; a mode (@lquotes@;strict mode@rquotes@;), in which the predefined arithmetic operations of floating point and fixed point types and the functions and operations of various predefined packages have to provide guaranteed accuracy or conform to other numeric performance requirements, which the Numerics Annex also specifies; a mode (@lquotes@;relaxed mode@rquotes@;), in which no accuracy or other numeric performance requirements need be satisfied, as for implementations not conforming to the Numerics Annex; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00296-01]} models of floating point and fixed point arithmetic on which the accuracy requirements of strict mode are based;@Chg{Version=[2],New=[],Old=[ and]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00296-01]} the definitions of the model-oriented attributes of floating point types that apply in the strict mode@Chg{Version=[2],New=[; and],Old=[.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00296-01]}@ChgAdded{Version=[2], Text=[features for the manipulation of real and complex vectors and matrices.]} @end{itemize} @end{Intro} @begin{ImplAdvice} If Fortran (respectively, C) is widely supported in the target environment, implementations supporting the Numerics Annex should provide the child package Interfaces.Fortran (respectively, Interfaces.C) specified in @RefSecNum{Interface to Other Languages} and should support a @i{convention_}@nt{identifier} of Fortran (respectively, C) in the interfacing pragmas (see @RefSecNum{Interface to Other Languages}), thus allowing Ada programs to interface with programs written in that language. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If Fortran (respectively, C) is supported in the target environment, then interfacing to Fortran (respectively, C) should be supported as specified in @RefSecNum{Interface to Other Languages}.]}]} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Complex Arithmetic} @begin{Intro} Types and arithmetic operations for complex arithmetic are provided in Generic_Complex_Types, which is defined in @RefSecNum{Complex Types}. Implementation-defined approximations to the complex analogs of the mathematical functions known as the @lquotes@;elementary functions@rquotes@; are provided by the subprograms in Generic_@!Complex_@!Elementary_@!Functions, which is defined in @RefSecNum{Complex Elementary Functions}. Both of these library units are generic children of the predefined package Numerics (see @RefSecNum{The Numerics Packages}). Nongeneric equivalents of these generic packages for each of the predefined floating point types are also provided as children of Numerics. @ImplDef{The accuracy actually achieved by the complex elementary functions and by other complex arithmetic operations.} @begin{Discussion} Complex arithmetic is defined in the Numerics Annex, rather than in the core, because it is considered to be a specialized need of (some) numeric applications. @end{Discussion} @end{Intro} @LabeledSubClause{Complex Types} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Complex_Types has the following declaration: @begin{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @key{generic}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Types]} @key{type} Real @key{is} @key{digits} <>; @key{package} Ada.Numerics.Generic_Complex_Types @key{is} @Chg{New=[@key{pragma}],Old=[pragma]} Pure(Generic_Complex_Types); @key{type} @AdaTypeDefn{Complex} @key{is} @key{record} Re, Im : Real'Base; @key{end} @key{record}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key{type} @AdaTypeDefn{Imaginary} @key{is} @key{private};@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Imaginary);],Old=[]} @AdaObjDefn{i} : @key{constant} Imaginary; @AdaObjDefn{j} : @key{constant} Imaginary; @key{function} @AdaSubDefn{Re} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Im} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Im} (X : Imaginary) @key{return} Real'Base; @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in} @key{out} Complex; Re : @key{in} Real'Base); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in} @key{out} Complex; Im : @key{in} Real'Base); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{out} Imaginary; Im : @key{in} Real'Base); @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Im : Imaginary) @key{return} Complex; @key{function} @AdaSubDefn{Modulus} (X : Complex) @key{return} Real'Base; @key{function} "@key{abs}" (Right : Complex) @key{return} Real'Base @key{renames} Modulus; @key{function} @AdaSubDefn{Argument} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Argument} (X : Complex; Cycle : Real'Base) @key{return} Real'Base; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument, Cycle : Real'Base) @key{return} Complex; @key{function} "+" (Right : Complex) @key{return} Complex; @key{function} "-" (Right : Complex) @key{return} Complex; @key{function} @AdaSubDefn{Conjugate} (X : Complex) @key{return} Complex; @key{function} "+" (Left, Right : Complex) @key{return} Complex; @key{function} "-" (Left, Right : Complex) @key{return} Complex; @key{function} "*" (Left, Right : Complex) @key{return} Complex; @key{function} "/" (Left, Right : Complex) @key{return} Complex; @key{function} "**" (Left : Complex; Right : Integer) @key{return} Complex; @key{function} "+" (Right : Imaginary) @key{return} Imaginary; @key{function} "-" (Right : Imaginary) @key{return} Imaginary; @key{function} @AdaSubDefn{Conjugate} (X : Imaginary) @key{return} Imaginary @key{renames} "-"; @key{function} "@key{abs}" (Right : Imaginary) @key{return} Real'Base; @key{function} "+" (Left, Right : Imaginary) @key{return} Imaginary; @key{function} "-" (Left, Right : Imaginary) @key{return} Imaginary; @key{function} "*" (Left, Right : Imaginary) @key{return} Real'Base; @key{function} "/" (Left, Right : Imaginary) @key{return} Real'Base; @key{function} "**" (Left : Imaginary; Right : Integer) @key{return} Complex; @key{function} "<" (Left, Right : Imaginary) @key{return} Boolean; @key{function} "<=" (Left, Right : Imaginary) @key{return} Boolean; @key{function} ">" (Left, Right : Imaginary) @key{return} Boolean; @key{function} ">=" (Left, Right : Imaginary) @key{return} Boolean; @key{function} "+" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "+" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "-" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "-" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "*" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "*" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "/" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "/" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "+" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "+" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "-" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "-" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "*" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "*" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "/" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "/" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "+" (Left : Imaginary; Right : Real'Base) @key{return} Complex; @key{function} "+" (Left : Real'Base; Right : Imaginary) @key{return} Complex; @key{function} "-" (Left : Imaginary; Right : Real'Base) @key{return} Complex; @key{function} "-" (Left : Real'Base; Right : Imaginary) @key{return} Complex; @key{function} "*" (Left : Imaginary; Right : Real'Base) @key{return} Imaginary; @key{function} "*" (Left : Real'Base; Right : Imaginary) @key{return} Imaginary; @key{function} "/" (Left : Imaginary; Right : Real'Base) @key{return} Imaginary; @key{function} "/" (Left : Real'Base; Right : Imaginary) @key{return} Imaginary; @key[private] @key{type} Imaginary @key{is} @key{new} Real'Base; i : @key{constant} Imaginary := 1.0; j : @key{constant} Imaginary := 1.0; @key{end} Ada.Numerics.Generic_Complex_Types; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Types]} The library package Numerics.Complex_Types @Chg{New=[is declared pure and ],Old=[]}defines the same types, constants, and subprograms as Numerics.Generic_Complex_Types, except that the predefined type Float is systematically substituted for Real'Base throughout. Nongeneric equivalents of Numerics.Generic_Complex_Types for each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Complex_@!Types, Numerics.@!Long_@!Complex_@!Types, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} @begin{Reason} The nongeneric equivalents all export the types Complex and Imaginary and the constants i and j (rather than uniquely named types and constants, such as Short_Complex, Long_Complex, etc.) to preserve their equivalence to actual instantiations of the generic package and to allow the programmer to change the precision of an application globally by changing a single context clause. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Redundant{Complex is a visible type with @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} components.} @begin{Reason} The @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} representation is far more common than the polar representation, in practice. The accuracy of the results of the complex arithmetic operations and of the complex elementary functions is dependent on the representation; thus, implementers need to know that representation. The type is visible so that complex @lquotes@;literals@rquotes@; can be written in aggregate notation, if desired. @end{Reason} @Redundant{Imaginary is a private type; its full type is derived from Real'Base.} @begin{Reason} @Leading@;The Imaginary type and the constants i and j are provided for two reasons: @begin{itemize} They allow complex @lquotes@;literals@rquotes@; to be written in the alternate form of @RI{a} + @RI{b}*i (or @RI{a} + @RI{b}*j), if desired. Of course, in some contexts the sum will need to be parenthesized. When an Ada binding to IEC 559:1989 that provides (signed) infinities as the result of operations that overflow becomes available, it will be important to allow arithmetic between pure-imaginary and complex operands without requiring the former to be represented as (or promoted to) complex values with a real component of zero. For example, the multiplication of @RI{a} + @RI{b}*i by @RI{d}*i should yield @en@RI{b}@Times @RI{d} + @RI{a}@Times @RI{d}*i, but if one cannot avoid representing the pure-imaginary value @RI{d}*i as the complex value 0.0 + @RI{d}*i, then a NaN ("Not-a-Number") could be produced as the result of multiplying @RI{a} by 0.0 (e.g., when @RI{a} is infinite); the NaN could later trigger an exception. Providing the Imaginary type and overloadings of the arithmetic operators for mixtures of Imaginary and Complex operands gives the programmer the same control over avoiding premature coercion of pure-imaginary values to complex as is already provided for pure-real values. @end{itemize} @end{Reason} @begin{Reason} @Leading@;The Imaginary type is private, rather than being visibly derived from Real'Base, for two reasons: @begin{itemize} to preclude implicit conversions of real literals to the Imaginary type (such implicit conversions would make many common arithmetic expressions ambiguous); and to suppress the implicit derivation of the multiplication, division, and absolute value operators with Imaginary operands and an Imaginary result (the result type would be incorrect). @end{itemize} @end{Reason} @begin{Reason} The base subtype Real'Base is used for the component type of Complex, the parent type of Imaginary, and the parameter and result types of some of the subprograms to maximize the chances of being able to pass meaningful values into the subprograms and receive meaningful results back. The generic formal parameter Real therefore plays only one role, that of providing the precision to be maintained in complex arithmetic calculations. Thus, the subprograms in Numerics.Generic_Complex_Types share with those in Numerics.Generic_Elementary_Functions, and indeed even with the predefined arithmetic operations (see @RefSecNum{Operators and Expression Evaluation}), the property of being free of range checks on input and output, i.e., of being able to exploit the base range of the relevant floating point type fully. As a result, the user loses the ability to impose application-oriented bounds on the range of values that the components of a complex variable can acquire; however, it can be argued that few, if any, applications have a naturally square domain (as opposed to a circular domain) anyway. @end{Reason} @Leading@;The arithmetic operations and the Re, Im, Modulus, Argument, and Conjugate functions have their usual mathematical meanings. When applied to a parameter of pure-imaginary type, the @lquotes@;imaginary-part@rquotes@; function Im yields the value of its parameter, as the corresponding real value. The remaining subprograms have the following meanings: @begin{Reason} The middle case can be understood by considering the parameter of pure-imaginary type to represent a complex value with a zero real part. @end{Reason} @begin{Itemize} The Set_Re and Set_Im procedures replace the designated component of a complex parameter with the given real value; applied to a parameter of pure-imaginary type, the Set_Im procedure replaces the value of that parameter with the imaginary value corresponding to the given real value. The Compose_From_Cartesian function constructs a complex value from the given real and imaginary components. If only one component is given, the other component is implicitly zero. The Compose_From_Polar function constructs a complex value from the given modulus (radius) and argument (angle). When the value of the parameter Modulus is positive (resp., negative), the result is the complex value represented by the point in the complex plane lying at a distance from the origin given by the absolute value of Modulus and forming an angle measured counterclockwise from the positive (resp., negative) real axis given by the value of the parameter Argument. @end(Itemize) When the Cycle parameter is specified, the result of the Argument function and the parameter Argument of the Compose_From_Polar function are measured in units such that a full cycle of revolution has the given value; otherwise, they are measured in radians. @Leading@;The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply the principal branch: @begin{Itemize} The result of the Modulus function is nonnegative. The result of the Argument function is in the quadrant containing the point in the complex plane represented by the parameter X. This may be any quadrant (I through IV); thus, the range of the Argument function is approximately @en@Pi to @Pi (@en@R[Cycle]/2.0 to @R[Cycle]/2.0, if the parameter Cycle is specified). When the point represented by the parameter X lies on the negative real axis, the result approximates @begin{InnerItemize} @Pi (resp., @en@Pi) when the sign of the imaginary component of X is positive (resp., negative), if Real'Signed_Zeros is True; @Pi, if Real'Signed_Zeros is False. @end{InnerItemize} Because a result lying on or near one of the axes may not be exactly representable, the approximation inherent in computing the result may place it in an adjacent quadrant, close to but on the wrong side of the axis. @end{Itemize} @end{StaticSem} @begin{RunTime} The exception Numerics.Argument_Error is raised by the Argument and Compose_From_Polar functions with specified cycle, signaling a parameter value outside the domain of the corresponding mathematical function, when the value of the parameter Cycle is zero or negative. @IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised by the division operator when the value of the right operand is zero, and by the exponentiation operator when the value of the left operand is zero and the value of the exponent is negative, provided that Real'Machine_Overflows is True; when Real'Machine_Overflows is False, the result is unspecified. @PDefn{unspecified} @Redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for Complex Arithmetic}).] @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit implementations of the complex arithmetic operations to deliver results with an infinite component (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the complex arithmetic operations to deliver results with infinite components (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error in the situations defined above, when traps are disabled. Finally, such a binding should also specify the behavior of the complex arithmetic operations, when sensible, given operands with infinite components. @end{Discussion} @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Complex_Types, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Real. @begin{ImplNote} Implementations of Numerics.Generic_Complex_Types written in Ada should therefore avoid declaring local variables of subtype Real; the subtype Real'Base should be used instead. @end{ImplNote} @Leading @Defn2{Term=[prescribed result], Sec=[for the evaluation of a complex arithmetic operation]} In the following cases, evaluation of a complex arithmetic operation shall yield the @i{prescribed result}, provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} The results of the Re, Im, and Compose_From_Cartesian functions are exact. The real (resp., imaginary) component of the result of a binary addition operator that yields a result of complex type is exact when either of its operands is of pure-imaginary (resp., real) type. @begin{Ramification} The result of the addition operator is exact when one of its operands is of real type and the other is of pure-imaginary type. In this particular case, the operator is analogous to the Compose_From_Cartesian function; it performs no arithmetic. @end{Ramification} The real (resp., imaginary) component of the result of a binary subtraction operator that yields a result of complex type is exact when its right operand is of pure-imaginary (resp., real) type. The real component of the result of the Conjugate function for the complex type is exact. When the point in the complex plane represented by the parameter X lies on the nonnegative real axis, the Argument function yields a result of zero. @begin{Discussion} Argument(X + i*Y) is analogous to @i{EF}.Arctan(Y, X), where @i{EF} is an appropriate instance of Numerics.Generic_Elementary_Functions, except when X and Y are both zero, in which case the former yields the value zero while the latter raises Numerics.Argument_Error. @end{Discussion} When the value of the parameter Modulus is zero, the Compose_From_Polar function yields a result of zero. When the value of the parameter Argument is equal to a multiple of the quarter cycle, the result of the Compose_From_Polar function with specified cycle lies on one of the axes. In this case, one of its components is zero, and the other has the magnitude of the parameter Modulus. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand. Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero, provided that the exponent is nonzero. When the left operand is of pure-imaginary type, one component of the result of the exponentiation operator is zero. @end{Itemize} When the result, or a result component, of any operator of Numerics.Generic_Complex_Types has a mathematical definition in terms of a single arithmetic or relational operation, that result or result component exhibits the accuracy of the corresponding operation of the type Real. Other accuracy requirements for the Modulus, Argument, and Compose_From_Polar functions, and accuracy requirements for the multiplication of a pair of complex operands or for division by a complex operand, all of which apply only in the strict mode, are given in @RefSecNum{Accuracy Requirements for Complex Arithmetic}. The sign of a zero result or zero result component yielded by a complex arithmetic operation or function is implementation defined when Real'Signed_Zeros is True. @ImplDef{The sign of a zero result (or a component thereof) from any operator or function in Numerics.Generic_Complex_Types, when Real'Signed_Zeros is True.} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0091]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Implementations may obtain the result of exponentiation of a complex or pure-imaginary operand by repeated complex multiplication, with arbitrary association of the factors and with a possible final complex reciprocation (when the exponent is negative). Implementations are also permitted to obtain the result of exponentiation of a complex operand, but not of a pure-imaginary operand, by converting the left operand to a polar representation; exponentiating the modulus by the given exponent; multiplying the argument by the given exponent@Chg{New=[],Old=[, when the exponent is positive, or dividing the argument by the absolute value of the given exponent, when the exponent is negative]}; and reconverting to a @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} representation. Because of this implementation freedom, no accuracy requirement is imposed on complex exponentiation (except for the prescribed results given above, which apply regardless of the implementation method chosen). @end{ImplPerm} @begin{ImplAdvice} Because the usual mathematical meaning of multiplication of a complex operand and a real operand is that of the scaling of both components of the former by the latter, an implementation should not perform this operation by first promoting the real operand to complex type and then performing a full complex multiplication. In systems that, in the future, support an Ada binding to IEC 559:1989, the latter technique will not generate the required result when one of the components of the complex operand is infinite. (Explicit multiplication of the infinite component by the zero component obtained during promotion yields a NaN that propagates into the final result.) Analogous advice applies in the case of multiplication of a complex operand and a pure-imaginary operand, and in the case of division of a complex operand by a real or pure-imaginary operand. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Mixed real and complex operations (as well as pure-imaginary and complex operations) should not be performed by converting the real (resp. pure-imaginary) operand to complex.]}]} Likewise, because the usual mathematical meaning of addition of a complex operand and a real operand is that the imaginary operand remains unchanged, an implementation should not perform this operation by first promoting the real operand to complex type and then performing a full complex addition. In implementations in which the Signed_Zeros attribute of the component type is True (and which therefore conform to IEC 559:1989 in regard to the handling of the sign of zero in predefined arithmetic operations), the latter technique will not generate the required result when the imaginary component of the complex operand is a negatively signed zero. (Explicit addition of the negative zero to the zero obtained during promotion yields a positive zero.) Analogous advice applies in the case of addition of a complex operand and a pure-imaginary operand, and in the case of subtraction of a complex operand and a real or pure-imaginary operand. Implementations in which Real'Signed_Zeros is True should attempt to provide a rational treatment of the signs of zero results and result components. As one example, the result of the Argument function should have the sign of the imaginary component of the parameter X when the point represented by that parameter lies on the positive real axis; as another, the sign of the imaginary component of the Compose_@!From_@!Polar function should be the same as (resp., the opposite of) that of the Argument parameter when that parameter has a value of zero and the Modulus parameter has a nonnegative (resp., negative) value. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If Real'Signed_Zeros is true for Numerics.@!Generic_@!Complex_@!Types, a rational treatment of the signs of zero results and result components should be provided.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Complex_Types differs from Generic_Complex_Types as defined in ISO/IEC CD 13813 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child of the package defining the Argument_Error exception. The nongeneric equivalents export types and constants with the same names as those exported by the generic package, rather than with names unique to the package. Implementations are not allowed to impose an optional restriction that the generic actual parameter associated with Real be unconstrained. (In view of the ability to declare variables of subtype Real'Base in implementations of Numerics.Generic_Complex_Types, this flexibility is no longer needed.) The dependence of the Argument function on the sign of a zero parameter component is tied to the value of Real'Signed_Zeros. Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added a @nt{pragma} Preelaborable_Initialization to type Imaginary, so that it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Complex_Types are pure.]} @end{DiffWord95} @LabeledSubClause{Complex Elementary Functions} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Complex_Elementary_Functions has the following declaration: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @key[with] Ada.Numerics.Generic_Complex_Types; @key[generic]@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Elementary_@!Functions]} @key[with] @key[package] Complex_Types @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (<>); @key[use] Complex_Types; @key[package] Ada.Numerics.Generic_Complex_Elementary_Functions @key[is] @Chg{Version=[2],New=[@key{pragma}],Old=[pragma]} Pure(Generic_Complex_Elementary_Functions); @key[function] @AdaSubDefn{Sqrt} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Log} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Exp} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Exp} (X : Imaginary) @key[return] Complex; @key[function] "**" (Left : Complex; Right : Complex) @key[return] Complex; @key[function] "**" (Left : Complex; Right : Real'Base) @key[return] Complex; @key[function] "**" (Left : Real'Base; Right : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Sin} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cos} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Tan} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cot} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arcsin} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccos} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arctan} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccot} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Sinh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cosh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Tanh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Coth} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arcsinh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccosh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arctanh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccoth} (X : Complex) @key[return] Complex; @key[end] Ada.Numerics.Generic_Complex_Elementary_Functions; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Elementary_@!Functions]} The library package Numerics.Complex_Elementary_Functions @Chg{New=[is declared pure and ],Old=[]}defines the same subprograms as Numerics.@!Generic_@!Complex_@!Elementary_@!Functions, except that the predefined type Float is systematically substituted for Real'Base, and the Complex and Imaginary types exported by Numerics.@!Complex_@!Types are systematically substituted for Complex and Imaginary, throughout. Nongeneric equivalents of Numerics.@!Generic_@!Complex_@!Elementary_@!Functions corresponding to each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Complex_@!Elementary_@!Functions, Numerics.@!Long_@!Complex_@!Elementary_@!Functions, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} The overloading of the Exp function for the pure-imaginary type is provided to give the user an alternate way to compose a complex value from a given modulus and argument. In addition to Compose_@!From_@!Polar(Rho, Theta) (see @RefSecNum{Complex Types}), the programmer may write Rho * Exp(i * Theta). The imaginary (resp., real) component of the parameter X of the forward hyperbolic (resp., trigonometric) functions and of the Exp function (and the parameter X, itself, in the case of the overloading of the Exp function for the pure-imaginary type) represents an angle measured in radians, as does the imaginary (resp., real) component of the result of the Log and inverse hyperbolic (resp., trigonometric) functions. @Leading@;The functions have their usual mathematical meanings. However, the arbitrariness inherent in the placement of branch cuts, across which some of the complex elementary functions exhibit discontinuities, is eliminated by the following conventions: @begin{Itemize} The imaginary component of the result of the Sqrt and Log functions is discontinuous as the parameter X crosses the negative real axis. The result of the exponentiation operator when the left operand is of complex type is discontinuous as that operand crosses the negative real axis. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The @Chg{Version=[2],New=[],Old=[real (resp., ]}imaginary@Chg{Version=[2], New=[],Old=[)]} component of the result of the Arcsin@Chg{Version=[2], New=[,],Old=[ and]} Arccos@Chg{Version=[2],New=[],Old=[(resp.]}, @Chg{Version=[2],New=[and ],Old=[]}Arctanh@Chg{Version=[2], New=[],Old=[)]} functions is discontinuous as the parameter X crosses the real axis to the left of @en@;1.0 or the right of 1.0. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The real @Chg{Version=[2],New=[],Old=[(resp., imaginary) ]}component of the result of the Arctan @Chg{Version=[2],New=[and],Old=[(resp.,]} Arcsinh@Chg{Version=[2], New=[ functions],Old=[) function]} is discontinuous as the parameter X crosses the imaginary axis below @en@RI{i} or above @RI{i}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The real component of the result of the Arccot function is discontinuous as the parameter X crosses the imaginary axis @Chg{Version=[2],New=[below], Old=[between]} @en@RI{i} @Chg{Version=[2],New=[or above],Old=[and]} @RI{i}. The imaginary component of the Arccosh function is discontinuous as the parameter X crosses the real axis to the left of 1.0. The imaginary component of the result of the Arccoth function is discontinuous as the parameter X crosses the real axis between @en@;1.0 and 1.0. @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00185-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The branch cuts come from the fact that the functions in question are really multi-valued in the complex domain, and that we have to pick one @i{principal value} to be the result of the function. Evidently we have much freedom in choosing where the branch cuts lie. However, we are adhering to the following principles which seem to lead to the more @i{natural} definitions:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A branch cut should not intersect the real axis at a place where the corresponding real function is well-defined (in other words, the complex function should be an extension of the corresponding real function).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Because all the functions in question are analytic, to ensure power series validity for the principal value, the branch cuts should be invariant by complex conjugation.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For odd functions, to ensure that the principal value remains an odd function, the branch cuts should be invariant by reflection in the origin.]} @end{Itemize} @end{Discussion} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]}The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply @Chg{Version=[2],New=[that ],Old=[]}the principal branch@Chg{Version=[2],New=[ is an analytic continuation of the corresponding real-valued function in Numerics.Generic_Elementary_Functions. (For Arctan and Arccot, the single-argument function in question is that obtained from the two-argument version by fixing the second argument to be its default value.)],Old=[:]} @begin{Itemize} The real component of the result of the Sqrt and Arccosh functions is nonnegative. The same convention applies to the imaginary component of the result of the Log function as applies to the result of the natural-cycle version of the Argument function of Numerics.Generic_Complex_Types (see @RefSecNum{Complex Types}). The range of the real (resp., imaginary) component of the result of the Arcsin and Arctan (resp., Arcsinh and Arctanh) functions is approximately @en@Pi/2.0 to @Pi/2.0. The real (resp., imaginary) component of the result of the Arccos and Arccot (resp., Arccoth) functions ranges from 0.0 to approximately @Pi. The range of the imaginary component of the result of the Arccosh function is approximately @en@Pi to @Pi. @end{Itemize} In addition, the exponentiation operator inherits the single-valuedness of the Log function. @end{StaticSem} @begin{RunTime} The exception Numerics.Argument_Error is raised by the exponentiation operator, signaling a parameter value outside the domain of the corresponding mathematical function, when the value of the left operand is zero and the real component of the exponent (or the exponent itself, when it is of real type) is zero. @Leading@IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised, signaling a pole of the mathematical function (analogous to dividing by zero), in the following cases, provided that Complex_Types.Real'Machine_Overflows is True: @begin{Itemize} by the Log, Cot, and Coth functions, when the value of the parameter X is zero; by the exponentiation operator, when the value of the left operand is zero and the real component of the exponent (or the exponent itself, when it is of real type) is negative; by the Arctan and Arccot functions, when the value of the parameter X is @PorM @RI{i}; by the Arctanh and Arccoth functions, when the value of the parameter X is @PorM 1.0. @end{Itemize} @redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for Complex Arithmetic}); this may occur for parameter values sufficiently @i{near} poles, and, in the case of some of the functions, for parameter values having components of sufficiently large magnitude.] @PDefn{unspecified} When Complex_Types.Real'Machine_Overflows is False, the result at poles is unspecified. @begin{Reason} The purpose of raising Constraint_Error (rather than Numerics.Argument_Error) at the poles of a function, when Float_Type'Machine_Overflows is True, is to provide continuous behavior as the actual parameters of the function approach the pole and finally reach it. @end{Reason} @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit implementations of the complex elementary functions to deliver results with an infinite component (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the complex elementary functions to deliver results with an infinite component (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error at poles, when traps are disabled. Finally, such a binding should also specify the behavior of the complex elementary functions, when sensible, given parameters with infinite components. @end{Discussion} @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Complex_Elementary_Functions, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Complex_Types.Real. @begin{ImplNote} Implementations of Numerics.Generic_Complex_Elementary_Functions written in Ada should therefore avoid declaring local variables of subtype Complex_Types.Real; the subtype Complex_Types.Real'Base should be used instead. @end{ImplNote} @Leading @Defn2{Term=[prescribed result], Sec=[for the evaluation of a complex elementary function]} In the following cases, evaluation of a complex elementary function shall yield the @i{prescribed result} (or a result having the prescribed component), provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} When the parameter X has the value zero, the Sqrt, Sin, Arcsin, Tan, Arctan, Sinh, Arcsinh, Tanh, and Arctanh functions yield a result of zero; the Exp, Cos, and Cosh functions yield a result of one; the Arccos and Arccot functions yield a real result; and the Arccoth function yields an imaginary result. When the parameter X has the value one, the Sqrt function yields a result of one; the Log, Arccos, and Arccosh functions yield a result of zero; and the Arcsin function yields a real result. When the parameter X has the value @en@;1.0, the Sqrt function yields the result @begin{InnerItemize} @RI{i} (resp., @en@RI{i}), when the sign of the imaginary component of X is positive (resp., negative), if Complex_Types.Real'Signed_Zeros is True; @RI{i}, if Complex_Types.Real'Signed_Zeros is False; @end{InnerItemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Chg{Version=[2],New=[When the parameter X has the value @en@;1.0, ], Old=[]}the Log function yields an imaginary result; and the Arcsin and Arccos functions yield a real result. When the parameter X has the value @PorM @RI{i}, the Log function yields an imaginary result. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand (as a complex value). Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero. @end{Itemize} @begin{Discussion} It is possible to give many other prescribed results restricting the result to the real or imaginary axis when the parameter X is appropriately restricted to easily testable portions of the domain. We follow the proposed ISO/IEC standard for Generic_Complex_Elementary_Functions (for Ada 83), CD 13813, in not doing so, however. @end{Discussion} Other accuracy requirements for the complex elementary functions, which apply only in the strict mode, are given in @RefSecNum{Accuracy Requirements for Complex Arithmetic}. The sign of a zero result or zero result component yielded by a complex elementary function is implementation defined when Complex_Types.Real'Signed_Zeros is True. @ImplDef{The sign of a zero result (or a component thereof) from any operator or function in Numerics.Generic_Complex_Elementary_Functions, when Complex_Types.Real'Signed_Zeros is True.} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package with the appropriate predefined nongeneric equivalent of Numerics.Generic_Complex_Types; if they are, then the latter shall have been obtained by actual instantiation of Numerics.Generic_Complex_Types. The exponentiation operator may be implemented in terms of the Exp and Log functions. Because this implementation yields poor accuracy in some parts of the domain, no accuracy requirement is imposed on complex exponentiation. @PDefn{unspecified} The implementation of the Exp function of a complex parameter X is allowed to raise the exception Constraint_Error, signaling overflow, when the real component of X exceeds an unspecified threshold that is approximately @Log(@R[Complex_Types.Real'Safe_Last]). This permission recognizes the impracticality of avoiding overflow in the marginal case that the exponential of the real component of X exceeds the safe range of Complex_Types.Real but both components of the final result do not. Similarly, the Sin and Cos (resp., Sinh and Cosh) functions are allowed to raise the exception Constraint_Error, signaling overflow, when the absolute value of the imaginary (resp., real) component of the parameter X exceeds an unspecified threshold that is approximately @Log(@R[Complex_Types.Real'Safe_Last]) + @Log(2.0). @PDefn{unspecified} This permission recognizes the impracticality of avoiding overflow in the marginal case that the hyperbolic sine or cosine of the imaginary (resp., real) component of X exceeds the safe range of Complex_Types.Real but both components of the final result do not. @end{ImplPerm} @begin{ImplAdvice} Implementations in which Complex_Types.Real'Signed_Zeros is True should attempt to provide a rational treatment of the signs of zero results and result components. For example, many of the complex elementary functions have components that are odd functions of one of the parameter components; in these cases, the result component should have the sign of the parameter component at the origin. Other complex elementary functions have zero components whose sign is opposite that of a parameter component at the origin, or is always positive or always negative. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If Complex_Types.Real'Signed_Zeros is true for Numerics.@!Generic_@!Complex_@!Elementary_@!Functions, a rational treatment of the signs of zero results and result components should be provided.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.@!Generic_@!Complex_@!Elementary_@!Functions differs from Generic_@!Complex_@!Elementary_@!Functions as defined in ISO/IEC CD 13814 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child unit of the package defining the Argument_Error exception. The proposed Generic_Complex_Elementary_Functions standard (for Ada 83) specified names for the nongeneric equivalents, if provided. Here, those nongeneric equivalents are required. The generic package imports an instance of Numerics.Generic_Complex_Types rather than a long list of individual types and operations exported by such an instance. The dependence of the imaginary component of the Sqrt and Log functions on the sign of a zero parameter component is tied to the value of Complex_Types.Real'Signed_Zeros. Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Complex_Elementary_Functions are pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00185-01]} @ChgAdded{Version=[2],Text=[Corrected various inconsistencies in the definition of the branch cuts.]} @end{DiffWord95} @LabeledSubClause{Complex Input-Output} @begin{Intro} The generic package Text_IO.Complex_IO defines procedures for the formatted input and output of complex values. The generic actual parameter in an instantiation of Text_IO.Complex_IO is an instance of Numerics.Generic_Complex_Types for some floating point subtype. Exceptional conditions are reported by raising the appropriate exception defined in Text_IO. @begin{ImplNote} An implementation of Text_IO.Complex_IO can be built around an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, where Complex_Types is the generic formal package parameter of Text_IO.Complex_IO. There is no need for an implementation of Text_IO.Complex_IO to parse real values. @end{ImplNote} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Text_IO.Complex_IO has the following declaration: @begin{Ramification} Because this is a child of Text_IO, the declarations of the visible part of Text_IO are directly visible within it. @end{Ramification} @begin{Example} @key[with] Ada.Numerics.Generic_Complex_Types; @key[generic]@ChildUnit{Parent=[Ada.Text_IO],Child=[Complex_IO]} @key[with] @key[package] Complex_Types @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (<>); @key[package] Ada.Text_IO.Complex_IO @key[is] @key[use] Complex_Types; @AdaObjDefn{Default_Fore} : Field := 2; @AdaObjDefn{Default_Aft} : Field := Real'Digits - 1; @AdaObjDefn{Default_Exp} : Field := 3; @key[procedure] @AdaSubDefn{Get} (File : @key[in] File_Type; Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get} (Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put} (File : @key[in] File_Type; Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put} (Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @trailing@; @key[procedure] @AdaSubDefn{Get} (From : @key[in] String; Item : @key[out] Complex; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put} (To : @key[out] String; Item : @key[in] Complex; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Ada.Text_IO.Complex_IO; @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00328-01]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada],Child=[Complex_@!Text_IO]} The library package Complex_Text_IO defines the same subprograms as Text_IO.Complex_IO, except that the predefined type Float is systematically substituted for Real, and the type Numerics.Complex_Types.Complex is systematically substituted for Complex throughout. Non-generic equivalents of Text_IO.Complex_IO corresponding to each of the other predefined floating point types are defined similarly, with the names Short_Complex_Text_IO, Long_Complex_Text_IO, etc.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics.]} @end{Reason} The semantics of the Get and Put procedures are as follows: @begin{DescribeCode} @begin{Example} @key[procedure] Get (File : @key[in] File_Type; Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] Get (Item : @key[out] Complex; Width : @key[in] Field := 0); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0092],ARef=[AI95-00029-01]} @Leading@;The input sequence is a pair of optionally signed real literals representing the real and imaginary components of a complex value@Chg{New=[ These components have the format defined for the corresponding Get procedure of an instance of Text_IO.Float_IO (see @RefSecNum{Input-Output for Real Types}) for the base subtype of Complex_Types.Real. T],Old=[; optionally, t]}he pair of components may be separated by a comma @Chg{New=[],Old=[and/]}or surrounded by a pair of parentheses@Chg{New=[ or both],Old=[]}. Blanks are freely allowed before each of the components and before the parentheses and comma, if either is used. If the value of the parameter Width is zero, then @begin{Itemize} line and page terminators are also allowed in these places; the components shall be separated by at least one blank or line terminator if the comma is omitted; and reading stops when the right parenthesis has been read, if the input sequence includes a left parenthesis, or when the imaginary component has been read, otherwise. @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@Leading @Chg{New=[],Old=[@Noparanum@;]}If a nonzero value of Width is supplied, then @begin{Itemize} the components shall be separated by at least one blank if the comma is omitted; and exactly Width characters are read, or the characters (possibly none) up to a line terminator, whichever comes first (blanks are included in the count). @end{Itemize} @begin{Reason} The parenthesized and comma-separated form is the form produced by Put on output (see below), and also by list-directed output in Fortran. The other allowed forms match several common styles of edit-directed output in Fortran, allowing most preexisting Fortran data files containing complex data to be read easily. When such files contain complex values with no separation between the real and imaginary components, the user will have to read those components separately, using an instance of Text_IO.Float_IO. @end{Reason} Returns, in the parameter Item, the value of type Complex that corresponds to the input sequence. @Trailing@;The exception Text_IO.Data_Error is raised if the input sequence does not have the required syntax or if the components of the complex value obtained are not of the base subtype of Complex_Types.Real. @begin{Example} @key[procedure] Put (File : @key[in] File_Type; Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] Put (Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item as a pair of decimal literals representing the real and imaginary components of the complex value, using the syntax of an aggregate. More specifically, @begin{itemize} outputs a left parenthesis; outputs the value of the real component of the parameter Item with the format defined by the corresponding Put procedure of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using the given values of Fore, Aft, and Exp; outputs a comma; outputs the value of the imaginary component of the parameter Item with the format defined by the corresponding Put procedure of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using the given values of Fore, Aft, and Exp; @Trailing@;outputs a right parenthesis. @end{itemize} @begin{Discussion} If the file has a bounded line length, a line terminator may be output implicitly before any element of the sequence itemized above. @end{Discussion} @begin{Discussion} The option of outputting the complex value as a pair of reals without additional punctuation is not provided, since it can be accomplished by outputting the real and imaginary components of the complex value separately. @end{Discussion} @begin{Example} @key[procedure] Get (From : @key[in] String; Item : @key[out] Complex; Last : @key[out] Positive); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Reads a complex value from the beginning of the given string, following the same rule as the Get procedure that reads a complex value from a file, but treating the end of the string as a @Chg{Version=[2],New=[file],Old=[line]} terminator. Returns, in the parameter Item, the value of type Complex that corresponds to the input sequence. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Text_IO.Data_Error is raised if the input sequence does not have the required syntax or if the components of the complex value obtained are not of the base subtype of Complex_Types.Real. @begin{Example} @key[procedure] Put (To : @key[out] String; Item : @key[in] Complex; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item to the given string as a pair of decimal literals representing the real and imaginary components of the complex value, using the syntax of an aggregate. More specifically, @begin{itemize} a left parenthesis, the real component, and a comma are left justified in the given string, with the real component having the format defined by the Put procedure (for output to a file) of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using a value of zero for Fore and the given values of Aft and Exp; the imaginary component and a right parenthesis are right justified in the given string, with the imaginary component having the format defined by the Put procedure (for output to a file) of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using a value for Fore that completely fills the remainder of the string, together with the given values of Aft and Exp. @end{itemize} @begin{Reason} This rule is the one proposed in LSN-1051. Other rules were considered, including one that would have read @lquotes@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using a value for Fore such that the sequence of characters output exactly fills, or comes closest to filling, the string; in the latter case, the string is filled by inserting one extra blank immediately after the comma.@rquotes@; While this latter rule might be considered the closest analogue to the rule for output to a string in Text_IO.Float_IO, it requires a more difficult and inefficient implementation involving special cases when the integer part of one component is substantially longer than that of the other and the string is too short to allow both to be preceded by blanks. Unless such a special case applies, the latter rule might produce better columnar output if several such strings are ultimately output to a file, but very nearly the same output can be produced by outputting to the file directly, with the appropriate value of Fore; in any case, it might validly be assumed that output to a string is intended for further computation rather than for display, so that the precise formatting of the string to achieve a particular appearance is not the major concern. @end{Reason} The exception Text_IO.Layout_Error is raised if the given string is too short to hold the formatted output. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} Other exceptions declared (by renaming) in Text_IO may be raised by the preceding procedures in the appropriate circumstances, as for the corresponding procedures of Text_IO.Float_IO. @end{ImplPerm} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00328-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Nongeneric equivalents for Text_IO.Complex_IO are added, to be consistent with all other language-defined Numerics generic packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0092],ARef=[AI95-00029-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the syntax of values read by Complex_IO is the same as that read by Text_IO.Float_IO.]} @end{DiffWord95} @LabeledSubClause{The Package Wide_Text_IO.Complex_IO} @begin{StaticSem} @Defn{Ada.Wide_@!Text_IO.Complex_IO} @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Complex_IO]} Implementations shall also provide the generic library package Wide_Text_IO.Complex_IO. Its declaration is obtained from that of Text_IO.Complex_IO by systematically replacing Text_IO by Wide_Text_IO and String by Wide_String; the description of its behavior is obtained by additionally replacing references to particular characters (commas, parentheses, etc.) by those for the corresponding wide characters. @end{StaticSem} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Complex_IO]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{Ada.Wide_Wide_@!Text_IO.Complex_IO} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Complex_IO]} Implementations shall also provide the generic library package Wide_Wide_Text_IO.Complex_IO. Its declaration is obtained from that of Text_IO.Complex_IO by systematically replacing Text_IO by Wide_Wide_Text_IO and String by Wide_Wide_String; the description of its behavior is obtained by additionally replacing references to particular characters (commas, parentheses, etc.) by those for the corresponding wide wide characters.]} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Complex_IO is new. (At least it wasn't called Incredibly_Wide_Text_IO.Complex_IO; maybe next time.)]} @end{Extend95} @LabeledClause{Numeric Performance Requirements} @begin{ImplReq} @Defn{accuracy} @Defn{strict mode} Implementations shall provide a user-selectable mode in which the accuracy and other numeric performance requirements detailed in the following subclauses are observed. This mode, referred to as the @i{strict mode}, may or may not be the default mode; it directly affects the results of the predefined arithmetic operations of real types and the results of the subprograms in children of the Numerics package, and indirectly affects the operations in other language defined packages. @Defn{relaxed mode} Implementations shall also provide the opposing mode, which is known as the @i{relaxed mode}. @begin{Reason} On the assumption that the users of an implementation that does not support the Numerics Annex have no particular need for numerical performance, such an implementation has no obligation to meet any particular requirements in this area. On the other hand, users of an implementation that does support the Numerics Annex are provided with a way of ensuring that their programs achieve a known level of numerical performance and that the performance is portable to other such implementations. The relaxed mode is provided to allow implementers to offer an efficient but not fully accurate alternative in the case that the strict mode entails a time overhead that some users may find excessive. In some of its areas of impact, the relaxed mode may be fully equivalent to the strict mode. @end{Reason} @begin{ImplNote} The relaxed mode may, for example, be used to exploit the implementation of (some of) the elementary functions in hardware, when available. Such implementations often do not meet the accuracy requirements of the strict mode, or do not meet them over the specified range of parameter values, but compensate in other ways that may be important to the user, such as their extreme speed. @end{ImplNote} @begin{Ramification} For implementations supporting the Numerics Annex, the choice of mode has no effect on the selection of a representation for a real type or on the values of attributes of a real type. @end{Ramification} @end{ImplReq} @begin{ImplPerm} Either mode may be the default mode. @ImplDef{Whether the strict mode or the relaxed mode is the default.} The two modes need not actually be different. @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} The choice between strict and relaxed numeric performance was not available in Ada 83. @end{Extend83} @RMNewPage@Comment{For printed version of Ada 2007 RM} @LabeledSubClause{Model of Floating Point Arithmetic} @begin{Intro} In the strict mode, the predefined operations of a floating point type shall satisfy the accuracy requirements specified here and shall avoid or signal overflow in the situations described. This behavior is presented in terms of a model of floating point arithmetic that builds on the concept of the canonical form (see @RefSecNum{Attributes of Floating Point Types}). @end{Intro} @begin{StaticSem} Associated with each floating point type is an infinite set of model numbers. The model numbers of a type are used to define the accuracy requirements that have to be satisfied by certain predefined operations of the type; through certain attributes of the model numbers, they are also used to explain the meaning of a user-declared floating point type declaration. The model numbers of a derived type are those of the parent type; the model numbers of a subtype are those of its type. @Defn{model number} The @i{model numbers} of a floating point type T are zero and all the values expressible in the canonical form (for the type T), in which @i{mantissa} has T'Model_Mantissa digits and @i{exponent} has a value greater than or equal to T'Model_Emin. (These attributes are defined in @RefSecNum{Model-Oriented Attributes of Floating Point Types}.) @begin{Discussion} The model is capable of describing the behavior of most existing hardware that has a mantissa-exponent representation. As applied to a type T, it is parameterized by the values of T'Machine_Radix, T'Model_Mantissa, T'Model_Emin, T'Safe_First, and T'Safe_Last. The values of these attributes are determined by how, and how well, the hardware behaves. They in turn determine the set of model numbers and the safe range of the type, which figure in the accuracy and range (overflow avoidance) requirements. In hardware that is free of arithmetic anomalies, T'Model_Mantissa, T'Model_Emin, T'Safe_First, and T'Safe_Last will yield the same values as T'Machine_Mantissa, T'Machine_Emin, T'Base'First, and T'Base'Last, respectively, and the model numbers in the safe range of the type T will coincide with the machine numbers of the type T. In less perfect hardware, it is not possible for the model-oriented attributes to have these optimal values, since the hardware, by definition, and therefore the implementation, cannot conform to the stringencies of the resulting model; in this case, the values yielded by the model-oriented parameters have to be made more conservative (i.e., have to be penalized), with the result that the model numbers are more widely separated than the machine numbers, and the safe range is a subrange of the base range. The implementation will then be able to conform to the requirements of the weaker model defined by the sparser set of model numbers and the smaller safe range. @end{Discussion} @Defn{model interval} A @i(model interval) of a floating point type is any interval whose bounds are model numbers of the type. @Defn2{Term=[model interval], Sec=[associated with a value]} The @i{model interval} of a type T @i{associated with a value} @i{v} is the smallest model interval of T that includes @i{v}. (The model interval associated with a model number of a type consists of that number only.) @end{StaticSem} @begin{ImplReq} The accuracy requirements for the evaluation of certain predefined operations of floating point types are as follows. @begin{Discussion} This subclause does not cover the accuracy of an operation of a static expression; such operations have to be evaluated exactly (see @RefSecNum(Static Expressions and Static Subtypes)). It also does not cover the accuracy of the predefined attributes of a floating point subtype that yield a value of the type; such operations also yield exact results (see @RefSecNum(Operations of Floating Point Types) and @RefSecNum(Attributes of Floating Point Types)). @end{Discussion} @Defn{operand interval} An @i(operand interval) is the model interval, of the type specified for the operand of an operation, associated with the value of the operand. @Leading@;For any predefined arithmetic operation that yields a result of a floating point type T, the required bounds on the result are given by a model interval of T (called the @i(result interval)) defined in terms of the operand values as follows: @begin(Itemize) @Defn2{Term=[result interval], Sec=[for the evaluation of a predefined arithmetic operation]} The result interval is the smallest model interval of T that includes the minimum and the maximum of all the values obtained by applying the (exact) mathematical operation to values arbitrarily selected from the respective operand intervals. @end(Itemize) The result interval of an exponentiation is obtained by applying the above rule to the sequence of multiplications defined by the exponent, assuming arbitrary association of the factors, and to the final division in the case of a negative exponent. The result interval of a conversion of a numeric value to a floating point type T is the model interval of T associated with the operand value, except when the source expression is of a fixed point type with a @i(small) that is not a power of T'Machine_Radix or is a fixed point multiplication or division either of whose operands has a @i(small) that is not a power of T'Machine_Radix; in these cases, the result interval is implementation defined. @ImplDef{The result interval in certain cases of fixed-to-float conversion.} @IndexCheck{Overflow_Check} For any of the foregoing operations, the implementation shall deliver a value that belongs to the result interval when both bounds of the result interval are in the safe range of the result type T, as determined by the values of T'Safe_First and T'Safe_Last; otherwise, @begin(itemize) @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if T'Machine_Overflows is True, the implementation shall either deliver a value that belongs to the result interval or raise Constraint_Error; if T'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a floating point arithmetic operation in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end(itemize) For any predefined relation on operands of a floating point type T, the implementation may deliver any value (i.e., either True or False) obtained by applying the (exact) mathematical comparison to values arbitrarily chosen from the respective operand intervals. The result of a membership test is defined in terms of comparisons of the operand value with the lower and upper bounds of the given range or type mark (the usual rules apply to these comparisons). @end{ImplReq} @begin{ImplPerm} If the underlying floating point hardware implements division as multiplication by a reciprocal, the result interval for division (and exponentiation by a negative exponent) is implementation defined. @ImplDef{The result interval for division (or exponentiation by a negative exponent), when the floating point hardware implements division as multiplication by a reciprocal.} @end{ImplPerm} @begin{DiffWord83} The Ada 95 model numbers of a floating point type that are in the safe range of the type are comparable to the Ada 83 safe numbers of the type. There is no analog of the Ada 83 model numbers. The Ada 95 model numbers, when not restricted to the safe range, are an infinite set. @end{DiffWord83} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Giving the model numbers the hardware radix, instead of always a radix of two, allows (in conjunction with other changes) some borderline declared types to be represented with less precision than in Ada 83 (i.e., with single precision, whereas Ada 83 would have used double precision). Because the lower precision satisfies the requirements of the model (and did so in Ada 83 as well), this change is viewed as a desirable correction of an anomaly, rather than a worrisome inconsistency. (Of course, the wider representation chosen in Ada 83 also remains eligible for selection in Ada 95.) As an example of this phenomenon, assume that Float is represented in single precision and that a double precision type is also available. Also assume hexadecimal hardware with clean properties, for example certain IBM hardware. Then, @begin{Example} @key[type] T @key[is] @key[digits] Float'Digits @key[range] -Float'Last .. Float'Last; @end{Example} results in T being represented in double precision in Ada 83 and in single precision in Ada 95. The latter is intuitively correct; the former is counterintuitive. The reason why the double precision type is used in Ada 83 is that Float has model and safe numbers (in Ada 83) with 21 binary digits in their mantissas, as is required to model the hypothesized hexadecimal hardware using a binary radix; thus Float'Last, which is not a model number, is slightly outside the range of safe numbers of the single precision type, making that type ineligible for selection as the representation of T even though it provides adequate precision. In Ada 95, Float'Last (the same value as before) is a model number and is in the safe range of Float on the hypothesized hardware, making Float eligible for the representation of T. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Giving the model numbers the hardware radix allows for practical implementations on decimal hardware. @end{Extend83} @begin{DiffWord83} The wording of the model of floating point arithmetic has been simplified to a large extent. @end{DiffWord83} @LabeledSubClause{Model-Oriented Attributes of Floating Point Types} @begin{Intro} In implementations that support the Numerics Annex, the model-oriented attributes of floating point types shall yield the values defined here, in both the strict and the relaxed modes. These definitions add conditions to those in @RefSecNum{Attributes of Floating Point Types}. @end{Intro} @begin{StaticSem} @Leading@keepnext@;For every subtype S of a floating point type @i{T}: @begin{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} S'@Attr{Model_Mantissa} @\Yields the number of digits in the mantissa of the canonical form of the model numbers of @i{T} (see @RefSecNum{Attributes of Floating Point Types}). The value of this attribute shall be greater than or equal to@Chg{Version=[2],New=[], Old=[ @Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + 1, where @RI{d} is the requested decimal precision of @i{T}. In addition, it shall be less than or equal to the value of @i{T}'Machine_Mantissa. This attribute yields a value of the type @i{universal_integer}.]} @begin{Display} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + @RI{g}]} @end{Display} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[where @RI{d} is the requested decimal precision of @i{T}, and @RI{g} is 0 if @i{T}'Machine_Radix is a positive power of 10 and 1 otherwise. In addition, @i{T}'Model_Mantissa shall be less than or equal to the value of @i{T}'Machine_Mantissa. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} S'Model_Epsilon, which is defined in terms of S'Model_Mantissa (see @RefSecNum{Attributes of Floating Point Types}), yields the absolute value of the difference between one and the next model number of the type @i{T} above one. It is equal to or larger than the absolute value of the difference between one and the next machine number of the type @i{T} above one. @end{Ramification} S'@Attr{Model_Emin} @\Yields the minimum exponent of the canonical form of the model numbers of @i{T} (see @RefSecNum{Attributes of Floating Point Types}). The value of this attribute shall be greater than or equal to the value of @i{T}'Machine_Emin. This attribute yields a value of the type @i{universal_integer}. @begin{Ramification} S'Model_Small, which is defined in terms of S'Model_Emin (see @RefSecNum{Attributes of Floating Point Types}), yields the smallest positive (nonzero) model number of the type @i{T}. @end{Ramification} S'@Attr{Safe_First} @\Yields the lower bound of the safe range of @i{T}. The value of this attribute shall be a model number of @i{T} and greater than or equal to the lower bound of the base range of @i{T}. In addition, if @i{T} is declared by a @nt{floating_point_definition} or is derived from such a type, and the @nt{floating_point_definition} includes a @nt{real_range_specification} specifying a lower bound of @RI{lb}, then the value of this attribute shall be less than or equal to @RI{lb}; otherwise, it shall be less than or equal to @en@;10.0 @+[4 @Times @RI{d}], where @RI{d} is the requested decimal precision of @i{T}. This attribute yields a value of the type @i{universal_real}. S'@Attr{Safe_Last} @\Yields the upper bound of the safe range of @i{T}. The value of this attribute shall be a model number of @i{T} and less than or equal to the upper bound of the base range of @i{T}. In addition, if @i{T} is declared by a @nt{floating_point_definition} or is derived from such a type, and the @nt{floating_point_definition} includes a @nt{real_range_specification} specifying an upper bound of @RI{ub}, then the value of this attribute shall be greater than or equal to @RI{ub}; otherwise, it shall be greater than or equal to 10.0 @+[4 @Times @RI{d}], where d is the requested decimal precision of @i{T}. This attribute yields a value of the type @i{universal_real}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)}S'@Attr{Model} @\Denotes a function (of a parameter @i{X}) whose specification is given in @RefSecNum{Attributes of Floating Point Types}. If @i{X} is a model number of @i{T}, the function yields @i{X}; otherwise, it yields the value obtained by rounding or truncating @i{X} to either one of the adjacent model numbers of @i{T}. @IndexCheck{Overflow_Check}Constraint_Error is raised if the resulting model number is outside the safe range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True. @end{Description} @Leading@;Subject to the constraints given above, the values of S'Model_Mantissa and S'Safe_Last are to be maximized, and the values of S'Model_Emin and S'Safe_First minimized, by the implementation as follows: @begin{Itemize} First, S'Model_Mantissa is set to the largest value for which values of S'Model_Emin, S'Safe_First, and S'Safe_Last can be chosen so that the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes. Next, S'Model_Emin is set to the smallest value for which values of S'Safe_First and S'Safe_Last can be chosen so that the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes and the previously determined value of S'Model_Mantissa. Finally, S'Safe_First and S'Safe_last are set (in either order) to the smallest and largest values, respectively, for which the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes and the previously determined values of S'Model_Mantissa and S'Model_Emin. @end{Itemize} @begin{Ramification} @Defn{IEEE floating point arithmetic} @Defn{IEC 559:1989} The following table shows appropriate attribute values for IEEE basic single and double precision types (ANSI/IEEE Std 754-1985, IEC 559:1989). Here, we use the names IEEE_Float_32 and IEEE_Float_64, the names that would typically be declared in package Interfaces, in an implementation that supports IEEE arithmetic. In such an implementation, the attributes would typically be the same for Standard.Float and Long_Float, respectively. @begin{Example} Attribute IEEE_Float_32 IEEE_Float_64 'Machine_Radix 2 2 'Machine_Mantissa 24 53 'Machine_Emin -125 -1021 'Machine_Emax 128 1024 'Denorm True True 'Machine_Rounds True True 'Machine_Overflows True/False True/False 'Signed_Zeros should be True should be True 'Model_Mantissa (same as 'Machine_Mantissa) (same as 'Machine_Mantissa) 'Model_Emin (same as 'Machine_Emin) (same as 'Machine_Emin) 'Model_Epsilon 2.0**(-23) 2.0**(-52) 'Model_Small 2.0**(-126) 2.0**(-1022) 'Safe_First -2.0**128*(1.0-2.0**(-24)) -2.0**1024*(1.0-2.0**(-53)) 'Safe_Last 2.0**128*(1.0-2.0**(-24)) 2.0**1024*(1.0-2.0**(-53)) 'Digits 6 15 'Base'Digits (same as 'Digits) (same as 'Digits) 'First (same as 'Safe_First) (same as 'Safe_First) 'Last (same as 'Safe_Last) (same as 'Safe_Last) 'Size 32 64 @end{Example} Note: 'Machine_Overflows can be True or False, depending on whether the Ada implementation raises Constraint_Error or delivers a signed infinity in overflow and zerodivide situations (and at poles of the elementary functions). @end{Ramification} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Corrected the definition of Model_Mantissa to match that given in @RefSecNum{Operations of Floating Point Types}.]} @end{DiffWord95} @LabeledSubClause{Model of Fixed Point Arithmetic} @begin{Intro} In the strict mode, the predefined arithmetic operations of a fixed point type shall satisfy the accuracy requirements specified here and shall avoid or signal overflow in the situations described. @end{Intro} @begin{ImplReq} The accuracy requirements for the predefined fixed point arithmetic operations and conversions, and the results of relations on fixed point operands, are given below. @begin{Discussion} This subclause does not cover the accuracy of an operation of a static expression; such operations have to be evaluated exactly (see @RefSecNum(Static Expressions and Static Subtypes)). @end{Discussion} The operands of the fixed point adding operators, absolute value, and comparisons have the same type. These operations are required to yield exact results, unless they overflow. Multiplications and divisions are allowed between operands of any two fixed point types; the result has to be (implicitly or explicitly) converted to some other numeric type. For purposes of defining the accuracy rules, the multiplication or division and the conversion are treated as a single operation whose accuracy depends on three types (those of the operands and the result). For decimal fixed point types, the attribute T'Round may be used to imply explicit conversion with rounding (see @RefSecNum(Operations of Fixed Point Types)). When the result type is a floating point type, the accuracy is as given in @RefSecNum(Model of Floating Point Arithmetic). @Defn{perfect result set} For some combinations of the operand and result types in the remaining cases, the result is required to belong to a small set of values called the @i(perfect result set); @Defn{close result set} for other combinations, it is required merely to belong to a generally larger and implementation-defined set of values called the @i(close result set). When the result type is a decimal fixed point type, the perfect result set contains a single value; thus, operations on decimal types are always fully specified. @ImplDef{The definition of @i{close result set}, which determines the accuracy of certain fixed point multiplications and divisions.} When one operand of a fixed-fixed multiplication or division is of type @i(universal_real), that operand is not implicitly converted in the usual sense, since the context does not determine a unique target type, but the accuracy of the result of the multiplication or division (i.e., whether the result has to belong to the perfect result set or merely the close result set) depends on the value of the operand of type @i(universal_real) and on the types of the other operand and of the result. @begin{Discussion} We need not consider here the multiplication or division of two such operands, since in that case either the operation is evaluated exactly (i.e., it is an operation of a static expression all of whose operators are of a root numeric type) or it is considered to be an operation of a floating point type. @end{Discussion} @Leading@;For a fixed point multiplication or division whose (exact) mathematical result is @RI{v}, and for the conversion of a value @RI{v} to a fixed point type, the perfect result set and close result set are defined as follows: @begin(itemize) @Leading@Keepnext@;If the result type is an ordinary fixed point type with a @i(small) of @RI{s}, @begin(InnerItemize) if @RI{v} is an integer multiple of @RI{s}, then the perfect result set contains only the value @RI{v}; otherwise, it contains the integer multiple of @RI{s} just below @RI{v} and the integer multiple of @RI{s} just above @RI{v}. @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integer multiples of @RI{s} containing the perfect result set as a subset. @Leading@Keepnext@;If the result type is a decimal type with a @i(small) of @RI{s}, @begin(InnerItemize) if @RI{v} is an integer multiple of @RI{s}, then the perfect result set contains only the value @RI{v}; otherwise, if truncation applies then it contains only the integer multiple of @RI{s} in the direction toward zero, whereas if rounding applies then it contains only the nearest integer multiple of @RI{s} (with ties broken by rounding away from zero). @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integer multiples of @RI{s} containing the perfect result set as a subset. @begin{Ramification} As a consequence of subsequent rules, this case does not arise when the operand types are also decimal types. @end{Ramification} @Leading@Keepnext@;If the result type is an integer type, @begin(InnerItemize) if @RI{v} is an integer, then the perfect result set contains only the value @RI{v}; otherwise, it contains the integer nearest to the value @RI{v} (if @RI{v} lies equally distant from two consecutive integers, the perfect result set contains the one that is further from zero). @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integers containing the perfect result set as a subset. @end(itemize) The result of a fixed point multiplication or division shall belong either to the perfect result set or to the close result set, as described below, if overflow does not occur. In the following cases, if the result type is a fixed point type, let @RI{s} be its @i(small); otherwise, i.e. when the result type is an integer type, let @RI{s} be 1.0. @begin(itemize) For a multiplication or division neither of whose operands is of type @i(universal_real), let @RI{l} and @RI{r} be the @i(smalls) of the left and right operands. For a multiplication, if (@RI{l} @Times @RI{r}) / @RI{s} is an integer or the reciprocal of an integer (the @i(smalls) are said to be @lquotes@;compatible@rquotes@; in this case), the result shall belong to the perfect result set; otherwise, it belongs to the close result set. For a division, if @RI{l} / (@RI{r} @Times @RI{s}) is an integer or the reciprocal of an integer (i.e., the @i(smalls) are compatible), the result shall belong to the perfect result set; otherwise, it belongs to the close result set. @begin{Ramification} When the operand and result types are all decimal types, their @i(smalls) are necessarily compatible; the same is true when they are all ordinary fixed point types with binary @i(smalls). @end{Ramification} For a multiplication or division having one @i(universal_real) operand with a value of @RI{v}, note that it is always possible to factor @RI{v} as an integer multiple of a @lquotes@;compatible@rquotes@; @i(small), but the integer multiple may be @lquotes@;too big.@rquotes@; If there exists a factorization in which that multiple is less than some implementation-defined limit, the result shall belong to the perfect result set; otherwise, it belongs to the close result set. @ImplDef{Conditions on a @i{universal_real} operand of a fixed point multiplication or division for which the result shall be in the @i{perfect result set}.} @end(itemize) A multiplication P * Q of an operand of a fixed point type F by an operand of an integer type I, or vice-versa, and a division P / Q of an operand of a fixed point type F by an operand of an integer type I, are also allowed. In these cases, the result has a type of F; explicit conversion of the result is never required. The accuracy required in these cases is the same as that required for a multiplication F(P * Q) or a division F(P / Q) obtained by interpreting the operand of the integer type to have a fixed point type with a @i(small) of 1.0. The accuracy of the result of a conversion from an integer or fixed point type to a fixed point type, or from a fixed point type to an integer type, is the same as that of a fixed point multiplication of the source value by a fixed point operand having a @i(small) of 1.0 and a value of 1.0, as given by the foregoing rules. The result of a conversion from a floating point type to a fixed point type shall belong to the close result set. The result of a conversion of a @i(universal_real) operand to a fixed point type shall belong to the perfect result set. The possibility of overflow in the result of a predefined arithmetic operation or conversion yielding a result of a fixed point type T is analogous to that for floating point types, except for being related to the base range instead of the safe range. @IndexCheck{Overflow_Check} If all of the permitted results belong to the base range of T, then the implementation shall deliver one of the permitted results; otherwise, @begin(itemize) @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if T'Machine_Overflows is True, the implementation shall either deliver one of the permitted results or raise Constraint_Error; if T'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a fixed point arithmetic operation in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end(itemize) @end{ImplReq} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Since the values of a fixed point type are now just the integer multiples of its @i{small}, the possibility of using extra bits available in the chosen representation for extra accuracy rather than for increasing the base range would appear to be removed, raising the possibility that some fixed point expressions will yield less accurate results than in Ada 83. However, this is partially offset by the ability of an implementation to choose a smaller default @i{small} than before. Of course, if it does so for a type T then T'Small will have a different value than it previously had. The accuracy requirements in the case of incompatible @i{smalls} are relaxed to foster wider support for non-binary @i{smalls}. If this relaxation is exploited for a type that was previously supported, lower accuracy could result; however, there is no particular incentive to exploit the relaxation in such a case. @end{Inconsistent83} @begin{DiffWord83} @Leading@;The fixed point accuracy requirements are now expressed without reference to model or safe numbers, largely because the full generality of the former model was never exploited in the case of fixed point types (particularly in regard to operand perturbation). Although the new formulation in terms of perfect result sets and close result sets is still verbose, it can be seen to distill down to two cases: @begin{Itemize} a case where the result must be the exact result, if the exact result is representable, or, if not, then either one of the adjacent values of the type (in some subcases only one of those adjacent values is allowed); a case where the accuracy is not specified by the language. @end{Itemize} @end{DiffWord83} @LabeledSubClause{Accuracy Requirements for the Elementary Functions} @begin{Intro} In the strict mode, the performance of Numerics.Generic_Elementary_Functions shall be as specified here. @end{Intro} @begin{ImplReq} @Defn2{Term=[result interval], Sec=[for the evaluation of an elementary function]} @Defn2{Term=[maximum relative error], Sec=[for the evaluation of an elementary function]} When an exception is not raised, the result of evaluating a function in an instance @i{EF} of Numerics.Generic_Elementary_Functions belongs to a @i{result interval}, defined as the smallest model interval of @i{EF}.Float_Type that contains all the values of the form @RI{f} @Times (1.0 + @RI{d}), where @RI{f} is the exact value of the corresponding mathematical function at the given parameter values, @RI{d} is a real number, and @Abs[@RI{d}] is less than or equal to the function's @i{maximum relative error}. @IndexCheck{Overflow_Check} The function delivers a value that belongs to the result interval when both of its bounds belong to the safe range of @i{EF}.Float_Type; otherwise, @begin{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if @i{EF}.Float_Type'Machine_Overflows is True, the function either delivers a value that belongs to the result interval or raises Constraint_Error, signaling overflow; @Trailing@;if @i{EF}.Float_Type'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of an elementary function reference in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end{Itemize} @Leading@;The maximum relative error exhibited by each function is as follows: @begin{Itemize} 2.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the Sqrt, Sin, and Cos functions; 4.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the Log, Exp, Tan, Cot, and inverse trigonometric functions; and 8.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the forward and inverse hyperbolic functions. @end{Itemize} The maximum relative error exhibited by the exponentiation operator, which depends on the values of the operands, is (4.0 + @Abs{@R[Right] @Times @Log(@R[Left])} / 32.0) @Times @RI{EF}@R[.Float_Type'Model_Epsilon]. The maximum relative error given above applies throughout the domain of the forward trigonometric functions when the Cycle parameter is specified. @Defn{angle threshold} When the Cycle parameter is omitted, the maximum relative error given above applies only when the absolute value of the angle parameter X is less than or equal to some implementation-defined @i{angle threshold}, which shall be at least @RI{EF}@R[.Float_@!Type'Machine_@!Radix] @+<@Floor(@RI{EF}@R[.Float_@!Type'Machine_@!Mantissa]/2)>. Beyond the angle threshold, the accuracy of the forward trigonometric functions is implementation defined. @ImplDef{The value of the @i{angle threshold}, within which certain elementary functions, complex arithmetic operations, and complex elementary functions yield results conforming to a maximum relative error bound.} @ImplDef{The accuracy of certain elementary functions for parameters beyond the angle threshold.} @begin{ImplNote} The angle threshold indirectly determines the amount of precision that the implementation has to maintain during argument reduction. @end{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The prescribed results specified in @RefSecNum{Elementary Functions} for certain functions at particular parameter values take precedence over the maximum relative error bounds; effectively, they narrow to a single value the result interval allowed by the maximum relative error bounds. Additional rules with a similar effect are given by @Chg{Version=[2],New=[],Old=[the ]}table @Chg{Version=[2],New=[G-1],Old=[below]} for the inverse trigonometric functions, at particular parameter values for which the mathematical result is possibly not a model number of @i{EF}.Float_Type (or is, indeed, even transcendental). In each table entry, the values of the parameters are such that the result lies on the axis between two quadrants; the corresponding accuracy rule, which takes precedence over the maximum relative error bounds, is that the result interval is the model interval of @i{EF}.Float_Type associated with the exact mathematical result given in the table. @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number (12) from original RM}>] The last line of the table is meant to apply when @i{EF}.Float_Type'Signed_Zeros is False; the two lines just above it, when @i{EF}.Float_Type'Signed_Zeros is True and the parameter Y has a zero value with the indicated sign. @Table[Columns=<5>,Alignment=<AllCenter>,FirstColWidth=[2],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{@Chg{Version=[2],New=[Table G-1: ],Old=[]}Tightly Approximated Elementary Function Results}>, Headers=<@b{Function}@\@b{Value of X}@\@b{Value of Y}@\@b{Exact Result @*when Cycle @*Specified}@\@b{Exact Result @*when Cycle @*Omitted}>, Body=<Arcsin@\1.0@\n.a.@\Cycle/4.0@\@Pi/2.0 Arcsin@\@en@;1.0@\n.a.@\@en@R[Cycle]/4.0@\@en@Pi/2.0 Arccos@\0.0@\n.a.@\Cycle/4.0@\@Pi/2.0 Arccos@\@en@;1.0@\n.a.@\Cycle/2.0@\@Pi Arctan and Arccot@\0.0@\positive@\Cycle/4.0@\@Pi/2.0 Arctan and Arccot@\0.0@\negative@\@en@R[Cycle]/4.0@\@en@Pi/2.0 Arctan and Arccot@\negative@\+0.0@\Cycle/2.0@\@Pi Arctan and Arccot@\negative@\@en@;0.0@\@en@R[Cycle]/2.0@\@en@Pi@Last Arctan and Arccot@\negative@\0.0@\Cycle/2.0@\@Pi>] The amount by which the result of an inverse trigonometric function is allowed to spill over into a quadrant adjacent to the one corresponding to the principal branch, as given in @RefSecNum{Elementary Functions}, is limited. The rule is that the result belongs to the smallest model interval of @i{EF}.Float_Type that contains both boundaries of the quadrant corresponding to the principal branch. This rule also takes precedence over the maximum relative error bounds, effectively narrowing the result interval allowed by them. @Comment{For Ada 95 with Corr, table G-1 appears here} @Leading@;Finally, the following specifications also take precedence over the maximum relative error bounds: @begin{Itemize} The absolute value of the result of the Sin, Cos, and Tanh functions never exceeds one. The absolute value of the result of the Coth function is never less than one. The result of the Cosh function is never less than one. @end{Itemize} @end{ImplReq} @begin{ImplAdvice} The versions of the forward trigonometric functions without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter of 2.0*Numerics.Pi, since this will not provide the required accuracy in some portions of the domain. For the same reason, the version of Log without a Base parameter should not be implemented by calling the corresponding version with a Base parameter of Numerics.e. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For elementary functions, the forward trigonometric functions without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter. Log without a Base parameter should not be implemented by calling Log with a Base parameter.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Elementary_Functions differs from Generic_Elementary_Functions as defined in ISO/IEC DIS 11430 (for Ada 83) in the following ways related to the accuracy specified for strict mode: @begin{Itemize} The maximum relative error bounds use the Model_Epsilon attribute instead of the Base'Epsilon attribute. The accuracy requirements are expressed in terms of result intervals that are model intervals. On the one hand, this facilitates the description of the required results in the presence of underflow; on the other hand, it slightly relaxes the requirements expressed in ISO/IEC DIS 11430. @end{Itemize} @end{DiffWord83} @LabeledSubClause{Performance Requirements for Random Number Generation} @begin{Intro} In the strict mode, the performance of Numerics.Float_Random and Numerics.Discrete_Random shall be as specified here. @end{Intro} @begin{ImplReq} Two different calls to the time-dependent Reset procedure shall reset the generator to different states, provided that the calls are separated in time by at least one second and not more than fifty years. The implementation's representations of generator states and its algorithms for generating random numbers shall yield a period of at least 2@+{31}@en@;2; much longer periods are desirable but not required. The implementations of Numerics.Float_Random.Random and Numerics.Discrete_Random.Random shall pass at least 85% of the individual trials in a suite of statistical tests. For Numerics.Float_Random, the tests are applied directly to the floating point values generated (i.e., they are not converted to integers first), while for Numerics.Discrete_Random they are applied to the generated values of various discrete types. Each test suite performs 6 different tests, with each test repeated 10 times, yielding a total of 60 individual trials. An individual trial is deemed to pass if the chi-square value (or other statistic) calculated for the observed counts or distribution falls within the range of values corresponding to the 2.5 and 97.5 percentage points for the relevant degrees of freedom (i.e., it shall be neither too high nor too low). For the purpose of determining the degrees of freedom, measurement categories are combined whenever the expected counts are fewer than 5. @begin{ImplNote} In the floating point random number test suite, the generator is reset to a time-dependent state at the beginning of the run. The test suite incorporates the following tests, adapted from D. E. Knuth, @i{The Art of Computer Programming, vol. 2: Seminumerical Algorithms.} In the descriptions below, the given number of degrees of freedom is the number before reduction due to any necessary combination of measurement categories with small expected counts; it is one less than the number of measurement categories. @begin{itemize} Proportional Distribution Test (a variant of the Equidistribution Test). The interval 0.0 .. 1.0 is partitioned into @RI{K} subintervals. @RI{K} is chosen randomly between 4 and 25 for each repetition of the test, along with the boundaries of the subintervals (subject to the constraint that at least 2 of the subintervals have a width of 0.001 or more). 5000 random floating point numbers are generated. The counts of random numbers falling into each subinterval are tallied and compared with the expected counts, which are proportional to the widths of the subintervals. The number of degrees of freedom for the chi-square test is @RI{K}@en@;1. Gap Test. The bounds of a range @RI{A} .. @RI{B}, with 0.0 @leq @RI{A} @Lt @RI{B} @leq 1.0, are chosen randomly for each repetition of the test, subject to the constraint that 0.2 @leq @RI{B}@en@RI{A} @leq 0.6. Random floating point numbers are generated until 5000 falling into the range @RI{A} .. @RI{B} have been encountered. Each of these 5000 is preceded by a @lquotes@;gap@rquotes@; (of length greater than or equal to 0) of consecutive random numbers not falling into the range @RI{A} .. @RI{B}. The counts of gaps of each length from 0 to 15, and of all lengths greater than 15 lumped together, are tallied and compared with the expected counts. Let @RI{P} = @RI{B}@en@RI{A}. The probability that a gap has a length of @RI{L} is (1@en@RI{P}) @+[@RI{L}] @Times @RI{P} for @RI{L} @leq 15, while the probability that a gap has a length of 16 or more is (1@en@RI{P}) @+[16]. The number of degrees of freedom for the chi-square test is 16. Permutation Test. 5000 tuples of 4 different random floating point numbers are generated. (An entire 4-tuple is discarded in the unlikely event that it contains any two exactly equal components.) The counts of each of the 4! = 24 possible relative orderings of the components of the 4-tuples are tallied and compared with the expected counts. Each of the possible relative orderings has an equal probability. The number of degrees of freedom for the chi-square test is 23. Increasing-Runs Test. Random floating point numbers are generated until 5000 increasing runs have been observed. An @lquotes@;increasing run@rquotes@; is a sequence of random numbers in strictly increasing order; it is followed by a random number that is strictly smaller than the preceding random number. (A run under construction is entirely discarded in the unlikely event that one random number is followed immediately by an exactly equal random number.) The decreasing random number that follows an increasing run is discarded and not included with the next increasing run. The counts of increasing runs of each length from 1 to 4, and of all lengths greater than 4 lumped together, are tallied and compared with the expected counts. The probability that an increasing run has a length of @RI{L} is 1/@RI{L}! @en 1/(@RI{L}+1)! for @RI{L} @leq 4, while the probability that an increasing run has a length of 5 or more is 1/5!. The number of degrees of freedom for the chi-square test is 4. Decreasing-Runs Test. The test is similar to the Increasing Runs Test, but with decreasing runs. Maximum-of-@RI{t} Test (with @RI{t} = 5). 5000 tuples of 5 random floating point numbers are generated. The maximum of the components of each 5-tuple is determined and raised to the 5th power. The uniformity of the resulting values over the range 0.0 .. 1.0 is tested as in the Proportional Distribution Test. @end{itemize} @end{ImplNote} @begin{ImplNote} In the discrete random number test suite, Numerics.Discrete_Random is instantiated as described below. The generator is reset to a time-dependent state after each instantiation. The test suite incorporates the following tests, adapted from D. E. Knuth (@i{op. cit.}) and other sources. The given number of degrees of freedom for the chi-square test is reduced by any necessary combination of measurement categories with small expected counts, as described above. @begin{Itemize} Equidistribution Test. In each repetition of the test, a number @RI{R} between 2 and 30 is chosen randomly, and Numerics.Discrete_Random is instantiated with an integer subtype whose range is 1 .. @RI{R}. 5000 integers are generated randomly from this range. The counts of occurrences of each integer in the range are tallied and compared with the expected counts, which have equal probabilities. The number of degrees of freedom for the chi-square test is @RI{R}@en@;1. Simplified Poker Test. Numerics.Discrete_Random is instantiated once with an enumeration subtype representing the 13 denominations (Two through Ten, Jack, Queen, King, and Ace) of an infinite deck of playing cards. 2000 @lquotes@;poker@rquotes@; hands (5-tuples of values of this subtype) are generated randomly. The counts of hands containing exactly @RI{K} different denominations (1 @leq @RI{K} @leq 5) are tallied and compared with the expected counts. The probability that a hand contains exactly @RI{K} different denominations is given by a formula in Knuth. The number of degrees of freedom for the chi-square test is 4. Coupon Collector's Test. Numerics.Discrete_Random is instantiated in each repetition of the test with an integer subtype whose range is 1 .. @RI{R}, where @RI{R} varies systematically from 2 to 11. Integers are generated randomly from this range until each value in the range has occurred, and the number @RI{K} of integers generated is recorded. This constitutes a @lquotes@;coupon collector's segment@rquotes@; of length @RI{K}. 2000 such segments are generated. The counts of segments of each length from @RI{R} to @RI{R}+29, and of all lengths greater than @RI{R}+29 lumped together, are tallied and compared with the expected counts. The probability that a segment has any given length is given by formulas in Knuth. The number of degrees of freedom for the chi-square test is 30. Craps Test (Lengths of Games). Numerics.Discrete_Random is instantiated once with an integer subtype whose range is 1 .. 6 (representing the six numbers on a die). 5000 craps games are played, and their lengths are recorded. (The length of a craps game is the number of rolls of the pair of dice required to produce a win or a loss. A game is won on the first roll if the dice show 7 or 11; it is lost if they show 2, 3, or 12. If the dice show some other sum on the first roll, it is called the @i{point}, and the game is won if and only if the point is rolled again before a 7 is rolled.) The counts of games of each length from 1 to 18, and of all lengths greater than 18 lumped together, are tallied and compared with the expected counts. For 2 @leq @RI{S} @leq 12, let @RI{D} @-{@RI{S}} be the probability that a roll of a pair of dice shows the sum @RI{S}, and let @RI{Q} @-[@RI{S}](@RI{L}) = @RI{D} @-[@RI{S}] @Times (1 @en (@RI{D} @-[@RI{S}] + @RI{D} @-[7])) @+[@RI{L}@en@;2] @Times (@RI{D} @-[@RI{S}] + @RI{D} @-[7]). Then, the probability that a game has a length of 1 is @RI{D} @-[7] + @RI{D} @-[11] + @RI{D} @-[2] + @RI{D} @-[3] + @RI{D} @-[12] and, for @RI{L} @Gt 1, the probability that a game has a length of @RI{L} is @RI{Q} @-[4](@RI{L}) + @RI{Q} @-[5](@RI{L}) + @RI{Q} @-[6](@RI{L}) + @RI{Q} @-[8](@RI{L}) + @RI{Q} @-[9](@RI{L}) + @RI{Q} @-[10](@RI{L}). The number of degrees of freedom for the chi-square test is 18. Craps Test (Lengths of Passes). This test is similar to the last, but enough craps games are played for 3000 losses to occur. A string of wins followed by a loss is called a @i{pass}, and its length is the number of wins preceding the loss. The counts of passes of each length from 0 to 7, and of all lengths greater than 7 lumped together, are tallied and compared with the expected counts. For @RI{L} @geq 0, the probability that a pass has a length of @RI{L} is @RI{W} @+[@RI{L}] @Times (1@en@RI{W}), where @RI{W}, the probability that a game ends in a win, is 244.0/495.0. The number of degrees of freedom for the chi-square test is 8. Collision Test. Numerics.Discrete_Random is instantiated once with an integer or enumeration type representing binary bits. 15 successive calls on the Random function are used to obtain the bits of a 15-bit binary integer between 0 and 32767. 3000 such integers are generated, and the number of collisions (integers previously generated) is counted and compared with the expected count. A chi-square test is not used to assess the number of collisions; rather, the limits on the number of collisions, corresponding to the 2.5 and 97.5 percentage points, are (from formulas in Knuth) 112 and 154. The test passes if and only if the number of collisions is in this range. @end{Itemize} @end{ImplNote} @end{ImplReq} @LabeledSubClause{Accuracy Requirements for Complex Arithmetic} @begin{Intro} In the strict mode, the performance of Numerics.Generic_@!Complex_Types and Numerics.Generic_@!Complex_@!Elementary_@!Functions shall be as specified here. @end{Intro} @begin{ImplReq} When an exception is not raised, the result of evaluating a real function of an instance @i{CT} of Numerics.Generic_Complex_Types (i.e., a function that yields a value of subtype @i{CT}.Real'Base or @i{CT}.Imaginary) belongs to a result interval defined as for a real elementary function (see @RefSecNum{Accuracy Requirements for the Elementary Functions}). @Defn2{Term=[result interval], Sec=[for a component of the result of evaluating a complex function]} When an exception is not raised, each component of the result of evaluating a complex function of such an instance, or of an instance of Numerics.Generic_Complex_Elementary_Functions obtained by instantiating the latter with @i{CT} (i.e., a function that yields a value of subtype @i{CT}.Complex), also belongs to a @i{result interval}. The result intervals for the components of the result are either defined by a @i{maximum relative error} bound or by a @i{maximum box error} bound. @Defn2{Term=[maximum relative error], Sec=[for a component of the result of evaluating a complex function]} When the result interval for the real (resp., imaginary) component is defined by maximum relative error, it is defined as for that of a real function, relative to the exact value of the real (resp., imaginary) part of the result of the corresponding mathematical function. @Defn2{Term=[maximum box error], Sec=[for a component of the result of evaluating a complex function]} When defined by maximum box error, the result interval for a component of the result is the smallest model interval of @i{CT}.Real that contains all the values of the corresponding part of @RI{f} @Times (1.0 + @RI{d}), where @RI{f} is the exact complex value of the corresponding mathematical function at the given parameter values, @RI{d} is complex, and @Abs{@RI{d}} is less than or equal to the given maximum box error. @IndexCheck{Overflow_Check} The function delivers a value that belongs to the result interval (or a value both of whose components belong to their respective result intervals) when both bounds of the result interval(s) belong to the safe range of @i{CT}.Real; otherwise, @begin{Discussion} The maximum relative error could be specified separately for each component, but we do not take advantage of that freedom here. @end{Discussion} @begin{Discussion} Note that @RI{f} @Times (1.0 + @RI{d}) defines a small circular region of the complex plane centered at @RI{f}, and the result intervals for the real and imaginary components of the result define a small rectangular box containing that circle. @end{Discussion} @begin{Reason} Box error is used when the computation of the result risks loss of significance in a component due to cancellation. @end{Reason} @begin{Ramification} The components of a complex function that exhibits bounded relative error in each component have to have the correct sign. In contrast, one of the components of a complex function that exhibits bounded box error may have the wrong sign, since the dimensions of the box containing the result are proportional to the modulus of the mathematical result and not to either component of the mathematical result individually. Thus, for example, the box containing the computed result of a complex function whose mathematical result has a large modulus but lies very close to the imaginary axis might well straddle that axis, allowing the real component of the computed result to have the wrong sign. In this case, the distance between the computed result and the mathematical result is, nevertheless, a small fraction of the modulus of the mathematical result. @end{Ramification} @begin{itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if @i{CT}.Real'Machine_Overflows is True, the function either delivers a value that belongs to the result interval (or a value both of whose components belong to their respective result intervals) or raises Constraint_Error, signaling overflow; if @i{CT}.Real'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a complex arithmetic operation or complex elementary function reference in overflow situations, when the Machine_Overflows attribute of the corresponding real type is False.} @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The error bounds for particular complex functions are tabulated @Chg{Version=[2],New=[in table G-2],Old=[below]}. In the table, the error bound is given as the coefficient of @i{CT}.Real'Model_Epsilon. @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number (7) from original RM}>] @Table[Columns=<4>,Alignment=<AllCenter>,FirstColWidth=[2],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{@Chg{Version=[2],New=[Table G-2: ],Old=[]}Error Bounds for Particular Complex Functions}>, Headers=<@b{Function or Operator}@\@b{Nature of @*Result}@\@b{Nature of @*Bound}@\@b{Error Bound}>, Body=<Modulus@\real@\max. rel. error@\3.0 Argument@\real@\max. rel. error@\4.0 Compose_From_Polar@\complex@\max. rel. error@\3.0 "*" (both operands complex)@\complex@\max. box error@\5.0 "/" (right operand complex)@\complex@\max. box error@\13.0 Sqrt@\complex@\max. rel. error@\6.0 Log@\complex@\max. box error@\13.0 Exp (complex parameter)@\complex@\max. rel. error@\7.0 Exp (imaginary parameter)@\complex@\max. rel. error@\2.0 Sin, Cos, Sinh, and Cosh@\complex@\max. rel. error@\11.0 Tan, Cot, Tanh, and Coth@\complex@\max. rel. error@\35.0 inverse trigonometric@\complex@\max. rel. error@\14.0@Last inverse hyperbolic@\complex@\max. rel. error@\14.0>] The maximum relative error given above applies throughout the domain of the Compose_From_Polar function when the Cycle parameter is specified. When the Cycle parameter is omitted, the maximum relative error applies only when the absolute value of the parameter Argument is less than or equal to the angle threshold (see @RefSecNum{Accuracy Requirements for the Elementary Functions}). For the Exp function, and for the forward hyperbolic (resp., trigonometric) functions, the maximum relative error given above likewise applies only when the absolute value of the imaginary (resp., real) component of the parameter X (or the absolute value of the parameter itself, in the case of the Exp function with a parameter of pure-imaginary type) is less than or equal to the angle threshold. For larger angles, the accuracy is implementation defined. @ImplDef{The accuracy of certain complex arithmetic operations and certain complex elementary functions for parameters (or components thereof) beyond the angle threshold.} @Comment{For Ada 95 with Corr, table G-2 appears here} @Leading@;The prescribed results specified in @RefSecNum{Complex Elementary Functions} for certain functions at particular parameter values take precedence over the error bounds; effectively, they narrow to a single value the result interval allowed by the error bounds for a component of the result. Additional rules with a similar effect are given below for certain inverse trigonometric and inverse hyperbolic functions, at particular parameter values for which a component of the mathematical result is transcendental. In each case, the accuracy rule, which takes precedence over the error bounds, is that the result interval for the stated result component is the model interval of @i{CT}.Real associated with the component's exact mathematical value. The cases in question are as follows: @begin{Itemize} When the parameter X has the value zero, the real (resp., imaginary) component of the result of the Arccot (resp., Arccoth) function is in the model interval of @i{CT}.Real associated with the value @Pi/2.0. When the parameter X has the value one, the real component of the result of the Arcsin function is in the model interval of @i{CT}.Real associated with the value @Pi/2.0. When the parameter X has the value @en@;1.0, the real component of the result of the Arcsin (resp., Arccos) function is in the model interval of @i{CT}.Real associated with the value @en@Pi/2.0 (resp., @Pi). @end{Itemize} @begin{Discussion} It is possible to give many other prescribed results in which a component of the parameter is restricted to a similar model interval when the parameter X is appropriately restricted to an easily testable portion of the domain. We follow the proposed ISO/IEC standard for Generic_Complex_Elementary_Functions (for Ada 83) in not doing so, however. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The amount by which a component of the result of an inverse trigonometric or inverse hyperbolic function is allowed to spill over into a quadrant adjacent to the one corresponding to the principal branch, as given in @RefSecNum{Complex Elementary Functions}, is limited. The rule is that the result belongs to the smallest model interval of @i{CT}.Real that contains both boundaries of the quadrant corresponding to the principal branch. This rule also takes precedence @Chg{Version=[2],New=[over],Old=[to]} the maximum error bounds, effectively narrowing the result interval allowed by them. Finally, the results allowed by the error bounds are narrowed by one further rule: The absolute value of each component of the result of the Exp function, for a pure-imaginary parameter, never exceeds one. @end{ImplReq} @begin{ImplAdvice} The version of the Compose_From_Polar function without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter of 2.0*Numerics.Pi, since this will not provide the required accuracy in some portions of the domain. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For complex arithmetic, the Compose_From_Polar function without a Cycle parameter should not be implemented by calling Compose_From_Polar with a Cycle parameter.]}]} @end{ImplAdvice} @begin{DiffWord83} The semantics of Numerics.Generic_Complex_Types and Numerics.Generic_Complex_Elementary_Functions differs from Generic_Complex_Types and Generic_Complex_Elementary_Functions as defined in ISO/IEC CDs 13813 and 13814 (for Ada 83) in ways analogous to those identified for the elementary functions in @RefSecNum{Accuracy Requirements for the Elementary Functions}. In addition, we do not generally specify the signs of zero results (or result components), although those proposed standards do. @end{DiffWord83} @LabeledAddedClause{Version=[2],Name=[Vector and Matrix Manipulation]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Types and operations for the manipulation of real vectors and matrices are provided in Generic_Real_Arrays, which is defined in @RefSecNum[Real Vectors and Matrices]. Types and operations for the manipulation of complex vectors and matrices are provided in Generic_Complex_Arrays, which is defined in @RefSecNum[Complex Vectors and Matrices]. Both of these library units are generic children of the predefined package Numerics (see @RefSecNum[The Numerics Packages]). Nongeneric equivalents of these packages for each of the predefined floating point types are also provided as children of Numerics.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Vector and matrix manipulation is defined in the Numerics Annex, rather than in the core, because it is considered to be a specialized need of (some) numeric applications.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These packages provide facilities that are similar to and replace those found in ISO/IEC 13813:1998 @i{Information technology @em Programming languages @em Generic packages of real and complex type declarations and basic operations for Ada (including vector and matrix types)}. (The other facilities provided by that Standard were already provided in Ada 95.) In addition to the main facilities of that Standard, these packages also include subprograms for the solution of linear equations, matrix inversion, determinants, and the determination of the eigenvalues and eigenvectors of real symmetric matrices and Hermitian matrices.]} @end{Discussion} @end{Intro} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} This clause is new. It just provides an introduction to the following subclauses.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Real Vectors and Matrices]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Numerics.Generic_Real_Arrays has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Real @key{is digits} <>; @key{package} Ada.Numerics.Generic_Real_Arrays @key{is}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_Real_Arrays]} @key{pragma} Pure(Generic_Real_Arrays);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Real_Vector} @key{is array} (Integer @key{range} <>) @key{of} Real'Base; @key{type} @AdaTypeDefn{Real_Matrix} @key{is array} (Integer @key{range} <>, Integer @key{range} <>) @key{of} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Real_Vector types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Real_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Left, Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Real_Vector) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Vector scaling operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Real_Vector) @key{return} Real_Vector; @key{function} "*" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector; @key{function} "/" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Other Real_Vector operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Vector} (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Subprograms for Real_Matrix types]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix arithmetic operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Transpose} (X : Real_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "*" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Real_Vector) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Real_Matrix) @key{return} Real_Vector; @key{function} "*" (Left : Real_Matrix; Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix scaling operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "*" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix; @key{function} "/" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix inversion and related operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Solve} (A : Real_Matrix; X : Real_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Solve} (A, X : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Inverse} (A : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Determinant} (A : Real_Matrix) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Eigenvalues and vectors of a real symmetric matrix]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Eigenvalues} (A : Real_Matrix) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Eigensystem} (A : @key{in} Real_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Real_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Other Real_Matrix operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Matrix} (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Numerics.Generic_Real_Arrays;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Numerics],Child=[Real_@!Arrays]} The library package Numerics.Real_Arrays is declared pure and defines the same types and subprograms as Numerics.Generic_Real_Arrays, except that the predefined type Float is systematically substituted for Real'Base throughout. Nongeneric equivalents for each of the other predefined floating point types are defined similarly, with the names Numerics.Short_Real_Arrays, Numerics.Long_Real_Arrays, etc.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics, and to be consistent with other Numerics packages.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Two types are defined and exported by Numerics.Generic_Real_Arrays. The composite type Real_Vector is provided to represent a vector with components of type Real; it is defined as an unconstrained, one-dimensional array with an index of type Integer. The composite type Real_Matrix is provided to represent a matrix with components of type Real; it is defined as an unconstrained, two-dimensional array with indices of type Integer.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The effect of the various subprograms is as described below. In most cases the subprograms are described in terms of corresponding scalar operations of the type Real; any exception raised by those operations is propagated by the array operation. Moreover, the accuracy of the result for each individual component is as defined for the scalar operation unless stated otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[In the case of those operations which are defined to @i{involve an inner product}, Constraint_Error may be raised if an intermediate result is outside the range of Real'Base even though the mathematical final result would not be.@Defn2{Term=[involve an inner product],Sec=[real]}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Right. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Left, Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Vector) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. This operation involves an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[This operation returns the L2-norm of Right (the square root of the inner product of the vector with itself).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Normalization of vectors is a frequent enough operation that it is useful to provide the norm as a basic operation. Furthermore, implementing the norm is not entirely straightforward, because the inner product might overflow while the final norm does not. An implementation cannot merely return Sqrt (X * X), it has to cope with a possible overflow of the inner product.]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While the definition is given in terms of an inner product, the norm doesn't @lquotes@;involve an inner product@rquotes@; in the technical sense. The reason is that it has accuracy requirements substantially different from those applicable to inner products; and that cancellations cannot occur, because all the terms are positive, so there is no possibility of intermediate overflow.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the scalar Left using the "*" operation of the type Real. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector; @key{function} "/" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and to the scalar Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a @i<unit vector>@Defn2{Term=[unit vector],Sec=[real vector]} with Order components and a lower bound of First. All components are set to 0.0 except for the Index component which is set to 1.0. Constraint_Error is raised if Index < First, Index > First + Order @en 1 or if First + Order @en 1 > Integer'Last.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Right. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Transpose (X : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the transpose of a matrix X. The first and second index ranges of the result are X'Range(2) and X'Range(1) respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Vector) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the outer product of a (column) vector Left by a (row) vector Right using the operation "*" of the type Real for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Real_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the scalar Left using the "*" operation of the type Real. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix; @key{function} "/" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and to the scalar Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A : Real_Matrix; X : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a vector Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving a single set of linear equations. The index range of the result is A'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The text says that Y is such that @lquotes@;X is (nearly) equal to A * Y@rquotes rather than @lquotes@;X is equal to A * Y@rquotes because rounding errors may mean that there is no value of Y such that X is exactly equal to A * Y. On the other hand it does not mean that any old rough value will do. The algorithm given under @ImplAdviceTitle should be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The requirement to raise Constraint_Error if the matrix is ill-conditioned is really a reflection of what will happen if the matrix is ill-conditioned. See @ImplAdviceTitle. We do not make any attempt to define ill-conditioned formally.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These remarks apply to all versions of Solve and Inverse.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A, X : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving several sets of linear equations. The index ranges of the result are A'Range(2) and X'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length(1) are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Inverse (A : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix B such that A * B is (nearly) equal to the unit matrix. The index ranges of the result are A'Range(2) and A'Range(1). Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Determinant (A : Real_Matrix) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the determinant of the matrix A. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Eigenvalues(A : Real_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the eigenvalues of the symmetric matrix A as a vector sorted into order with the largest first. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index range of the result is A'Range(1). Argument_Error is raised if the matrix A is not symmetric.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Eigensystem(A : @key{in} Real_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Real_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This procedure computes both the eigenvalues and eigenvectors of the symmetric matrix A. The out parameter Values is the same as that obtained by calling the function Eigenvalues. The out parameter Vectors is a matrix whose columns are the eigenvectors of the matrix A. The order of the columns corresponds to the order of the eigenvalues. The eigenvectors are normalized and mutually orthogonal (they are orthonormal), including when there are repeated eigenvalues. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index ranges of the parameter Vectors are those of A. Argument_Error is raised if the matrix A is not symmetric.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Matrix (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a square @i{unit matrix}@Defn2{Term=[unit matrix],Sec=[real matrix]} with Order**2 components and lower bounds of First_1 and First_2 (for the first and second index ranges respectively). All components are set to 0.0 except for the main diagonal, whose components are set to 1.0. Constraint_Error is raised if First_1 + Order @en 1 > Integer'Last or First_2 + Order @en 1 > Integer'Last.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem for type Real_Matrix.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For operations not involving an inner product, the accuracy requirements are those of the corresponding operations of the type Real in both the strict mode and the relaxed mode (see @RefSecNum{Numeric Performance Requirements}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For operations involving an inner product, no requirements are specified in the relaxed mode. In the strict mode the modulus of the absolute error of the inner product @i<X>*@i<Y> shall not exceed @i<g>*@b<abs>(@i<X>)*@b<abs>(@i<Y>) where @i<g> is defined as]} @begin{Display} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<g> = @i<X>'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa)]} @end{Display} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[For the L2-norm, no accuracy requirements are specified in the relaxed mode. In the strict mode the relative error on the norm shall not exceed @i<g> / 2.0 + 3.0 * Real'Model_Epsilon where @i<g> is defined as above.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is simply the combination of the error on the inner product with the error on Sqrt. A first order computation would lead to 2.0 * Real'Model_Epsilon above, but we are adding an extra Real'Model_Epsilon to account for higher order effects.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations shall document any techniques used to reduce cancellation errors such as extended precision arithmetic.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Any techniques used to reduce cancellation errors in Numerics.Generic_Real_Arrays shall be documented.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above accuracy requirement is met by the canonical implementation of the inner product by multiplication and addition using the corresponding operations of type Real'Base and performing the cumulative addition using ascending indices. Note however, that some hardware provides special operations for the computation of the inner product and although these may be fast they may not meet the accuracy requirement specified. See Accuracy and Stability of Numerical Algorithms By N J Higham (ISBN 0-89871-355-2), Section 3.1.]} @end{ImplNote} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations should implement the Solve and Inverse functions using established techniques such as LU decomposition with row interchanges followed by back and forward substitution. Implementations are recommended to refine the result by performing an iteration on the residuals; if this is done then it should be documented.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Solve and Inverse for Numerics.Generic_Real_Arrays should be implemented using established techniques such as LU decomposition and the result should be refined by an iteration on the residuals.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is not the intention that any special provision should be made to determine whether a matrix is ill-conditioned or not. The naturally occurring overflow (including division by zero) which will result from executing these functions with an ill-conditioned matrix and thus raise Constraint_Error is sufficient.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There isn't any advice for the implementation to document with this paragraph.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The test that a matrix is symmetric should be performed by using the equality operator to compare the relevant components.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The equality operator should be used to test that a matrix in Numerics.Generic_Real_Matrix is symmetric.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Numerics.Generic_Real_Arrays and its nongeneric equivalents are new.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Complex Vectors and Matrices]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Numerics.Generic_Complex_Arrays has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Numerics.Generic_Real_Arrays, Ada.Numerics.Generic_Complex_Types; @key{generic} @key{with package} Real_Arrays @key{is new} Ada.Numerics.Generic_Real_Arrays (<>); @key{use} Real_Arrays; @key{with package} Complex_Types @key{is new} Ada.Numerics.Generic_Complex_Types (Real); @key{use} Complex_Types; @key{package} Ada.Numerics.Generic_Complex_Arrays @key{is}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Arrays]} @key{pragma} Pure(Generic_Complex_Arrays);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Complex_Vector} @key{is array} (Integer @key{range} <>) @key{of} Complex; @key{type} @AdaTypeDefn{Complex_Matrix} @key{is array} (Integer @key{range} <>, Integer @key{range} <>) @key{of} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Complex_Vector types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector selection, conversion and composition operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Re} (X : Complex_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Im} (X : Complex_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in out} Complex_Vector; Re : @key{in} Real_Vector); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in out} Complex_Vector; Im : @key{in} Real_Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modulus} (X : Complex_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Real_Vector @key{renames} Modulus; @key{function} @AdaSubDefn{Argument} (X : Complex_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Argument} (X : Complex_Vector; Cycle : Real'Base) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Vector; Cycle : Real'Base) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Conjugate} (X : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left, Right : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Mixed Real_Vector and Complex_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "+" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector scaling operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Other Complex_Vector operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Vector} (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Complex_Matrix types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix selection, conversion and composition operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Re} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Im} (X : Complex_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in out} Complex_Matrix; Re : @key{in} Real_Matrix); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in out} Complex_Matrix; Im : @key{in} Real_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modulus} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Complex_Matrix) @key{return} Real_Matrix @key{renames} Modulus;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Argument} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Argument} (X : Complex_Matrix; Cycle : Real'Base) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Matrix; Cycle : Real'Base) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Conjugate} (X : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Transpose} (X : Complex_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Mixed Real_Matrix and Complex_Matrix arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "+" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Real_Matrix; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix scaling operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix inversion and related operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Solve} (A : Complex_Matrix; X : Complex_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Solve} (A, X : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Inverse} (A : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Determinant} (A : Complex_Matrix) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Eigenvalues and vectors of a Hermitian matrix}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Eigenvalues}(A : Complex_Matrix) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Eigensystem}(A : @key{in} Complex_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Complex_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Other Complex_Matrix operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Matrix} (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Numerics.Generic_Complex_Arrays;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Arrays]} The library package Numerics.Complex_Arrays is declared pure and defines the same types and subprograms as Numerics.Generic_Complex_Arrays, except that the predefined type Float is systematically substituted for Real'Base, and the Real_Vector and Real_Matrix types exported by Numerics.Real_Arrays are systematically substituted for Real_Vector and Real_Matrix, and the Complex type exported by Numerics.Complex_Types is systematically substituted for Complex, throughout. Nongeneric equivalents for each of the other predefined floating point types are defined similarly, with the names Numerics.Short_Complex_Arrays, Numerics.Long_Complex_Arrays, etc.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Two types are defined and exported by Numerics.Generic_Complex_Arrays. The composite type Complex_Vector is provided to represent a vector with components of type Complex; it is defined as an unconstrained one-dimensional array with an index of type Integer. The composite type Complex_Matrix is provided to represent a matrix with components of type Complex; it is defined as an unconstrained, two-dimensional array with indices of type Integer.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The effect of the various subprograms is as described below. In many cases they are described in terms of corresponding scalar operations in Numerics.Generic_Complex_Types. Any exception raised by those operations is propagated by the array subprogram. Moreover, any constraints on the parameters and the accuracy of the result for each individual component are as defined for the scalar operation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[In the case of those operations which are defined to @i{involve an inner product}, Constraint_Error may be raised if an intermediate result has a component outside the range of Real'Base even though the final mathematical result would not.@Defn2{Term=[involve an inner product],Sec=[complex]}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Re (X : Complex_Vector) @key{return} Real_Vector; @key{function} Im (X : Complex_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function returns a vector of the specified Cartesian components of X. The index range of the result is X'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Re (X : @key{in out} Complex_Vector; Re : @key{in} Real_Vector); @key{procedure} Set_Im (X : @key{in out} Complex_Vector; Im : @key{in} Real_Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each procedure replaces the specified (Cartesian) component of each of the components of X by the value of the matching component of Re or Im; the other (Cartesian) component of each of the components is unchanged. Constraint_Error is raised if X'Length is not equal to Re'Length or Im'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Cartesian (Re : Real_Vector) @key{return} Complex_Vector; @key{function} Compose_From_Cartesian (Re, Im : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a vector of Complex results (in Cartesian representation) formed from given vectors of Cartesian components; when only the real components are given, imaginary components of zero are assumed. The index range of the result is Re'Range. Constraint_Error is raised if Re'Length is not equal to Im'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Modulus (X : Complex_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Real_Vector @key{renames} Modulus; @key{function} Argument (X : Complex_Vector) @key{return} Real_Vector; @key{function} Argument (X : Complex_Vector; Cycle : Real'Base) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function calculates and returns a vector of the specified polar components of X or Right using the corresponding function in numerics.@!generic_complex_types. The index range of the result is X'Range or Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Polar (Modulus, Argument : Real_Vector) @key{return} Complex_Vector; @key{function} Compose_From_Polar (Modulus, Argument : Real_Vector; Cycle : Real'Base) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a vector of Complex results (in Cartesian representation) formed from given vectors of polar components using the corresponding function in numerics.@!generic_complex_types on matching components of Modulus and Argument. The index range of the result is Modulus'Range. Constraint_Error is raised if Modulus'Length is not equal to Argument'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Right. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Conjugate (X : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the result of applying the appropriate function Conjugate in numerics.@!generic_complex_types to each component of X. The index range of the result is X'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left, Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. This operation involves an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[This operation returns the Hermitian L2-norm of Right (the square root of the inner product of the vector with its conjugate).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While the definition is given in terms of an inner product, the norm doesn't @lquotes@;involve an inner product@rquotes in the technical sense. The reason is that it has accuracy requirements substantially different from those applicable to inner products; and that cancellations cannot occur, because all the terms are positive, so there is no possibility of intermediate overflow.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "+" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. These operations involve an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the complex number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the vector Left and the complex number Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the real number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the vector Left and the real number Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a @i{unit vector}@Defn2{Term=[unit vector],Sec=[complex vector]} with Order components and a lower bound of First. All components are set to (0.0, 0.0) except for the Index component which is set to (1.0, 0.0). Constraint_Error is raised if Index < First, Index > First + Order @en 1, or if First + Order @en 1 > Integer'Last.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Re (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} Im (X : Complex_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function returns a matrix of the specified Cartesian components of X. The index ranges of the result are those of X.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Re (X : @key{in out} Complex_Matrix; Re : @key{in} Real_Matrix); @key{procedure} Set_Im (X : @key{in out} Complex_Matrix; Im : @key{in} Real_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each procedure replaces the specified (Cartesian) component of each of the components of X by the value of the matching component of Re or Im; the other (Cartesian) component of each of the components is unchanged. Constraint_Error is raised if X'Length(1) is not equal to Re'Length(1) or Im'Length(1) or if X'Length(2) is not equal to Re'Length(2) or Im'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Cartesian (Re : Real_Matrix) @key{return} Complex_Matrix; @key{function} Compose_From_Cartesian (Re, Im : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a matrix of Complex results (in Cartesian representation) formed from given matrices of Cartesian components; when only the real components are given, imaginary components of zero are assumed. The index ranges of the result are those of Re. Constraint_Error is raised if Re'Length(1) is not equal to Im'Length(1) or Re'Length(2) is not equal to Im'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Modulus (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Complex_Matrix) @key{return} Real_Matrix @key{renames} Modulus; @key{function} Argument (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} Argument (X : Complex_Matrix; Cycle : Real'Base) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function calculates and returns a matrix of the specified polar components of X or Right using the corresponding function in numerics.@!generic_complex_types. The index ranges of the result are those of X or Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Polar (Modulus, Argument : Real_Matrix) @key{return} Complex_Matrix; @key{function} Compose_From_Polar (Modulus, Argument : Real_Matrix; Cycle : Real'Base) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a matrix of Complex results (in Cartesian representation) formed from given matrices of polar components using the corresponding function in numerics.@!generic_complex_types on matching components of Modulus and Argument. The index ranges of the result are those of Modulus. Constraint_Error is raised if Modulus'Length(1) is not equal to Argument'Length(1) or Modulus'Length(2) is not equal to Argument'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Right. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Conjugate (X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the result of applying the appropriate function Conjugate in numerics.@!generic_complex_types to each component of X. The index ranges of the result are those of X.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Transpose (X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the transpose of a matrix X. The first and second index ranges of the result are X'Range(2) and X'Range(1) respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the outer product of a (column) vector Left by a (row) vector Right using the appropriate operation "*" in numerics.@!generic_complex_types for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Complex_Matrix) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "+" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the outer product of a (column) vector Left by a (row) vector Right using the appropriate operation "*" in numerics.@!generic_complex_types for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real_Matrix) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex; Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the complex number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the matrix Left and the complex number Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the real number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the matrix Left and the real number Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A : Complex_Matrix; X : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a vector Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving a single set of linear equations. The index range of the result is A'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The text says that Y is such that @lquotes@;X is (nearly) equal to A * Y@rquotes rather than @lquotes@;X is equal to A * Y@rquotes because rounding errors may mean that there is no value of Y such that X is exactly equal to A * Y. On the other hand it does not mean that any old rough value will do. The algorithm given under @ImplAdviceTitle should be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The requirement to raise Constraint_Error if the matrix is ill-conditioned is really a reflection of what will happen if the matrix is ill-conditioned. See @ImplAdviceTitle. We do not make any attempt to define ill-conditioned formally.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These remarks apply to all versions of Solve and Inverse.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A, X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving several sets of linear equations. The index ranges of the result are A'Range(2) and X'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length(1) are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Inverse (A : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix B such that A * B is (nearly) equal to the unit matrix. The index ranges of the result are A'Range(2) and A'Range(1). Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Determinant (A : Complex_Matrix) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the determinant of the matrix A. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Eigenvalues(A : Complex_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the eigenvalues of the Hermitian matrix A as a vector sorted into order with the largest first. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index range of the result is A'Range(1). Argument_Error is raised if the matrix A is not Hermitian.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A Hermitian matrix is one whose transpose is equal to its complex conjugate. The eigenvalues of a Hermitian matrix are always real. We only support this case because algorithms for solving the general case are inherently unstable.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Eigensystem(A : @key{in} Complex_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Complex_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This procedure computes both the eigenvalues and eigenvectors of the Hermitian matrix A. The out parameter Values is the same as that obtained by calling the function Eigenvalues. The out parameter Vectors is a matrix whose columns are the eigenvectors of the matrix A. The order of the columns corresponds to the order of the eigenvalues. The eigenvectors are mutually orthonormal, including when there are repeated eigenvalues. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index ranges of the parameter Vectors are those of A. Argument_Error is raised if the matrix A is not Hermitian.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Matrix (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a square @i{unit matrix}@Defn2{Term=[unit matrix],Sec=[complex matrix]} with Order**2 components and lower bounds of First_1 and First_2 (for the first and second index ranges respectively). All components are set to (0.0, 0.0) except for the main diagonal, whose components are set to (1.0, 0.0). Constraint_Error is raised if First_1 + Order @en 1 > Integer'Last or First_2 + Order @en 1 > Integer'Last.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[For operations not involving an inner product, the accuracy requirements are those of the corresponding operations of the type Real'Base and Complex in both the strict mode and the relaxed mode (see @RefSecNum{Numeric Performance Requirements}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[For operations involving an inner product, no requirements are specified in the relaxed mode. In the strict mode the modulus of the absolute error of the inner product @i{X}*@i{Y} shall not exceed @i{g}*@key{abs}(@i{X})*@key{abs}(@i{Y}) where @i{g} is defined as]} @begin{Display} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{g} = @i{X}'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa) for mixed complex and real operands]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{g} = sqrt(2.0) * @i{X}'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa) for two complex operands]} @end{Display} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[For the L2-norm, no accuracy requirements are specified in the relaxed mode. In the strict mode the relative error on the norm shall not exceed @i<g> / 2.0 + 3.0 * Real'Model_Epsilon where @i<g> has the definition appropriate for two complex operands.]} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations shall document any techniques used to reduce cancellation errors such as extended precision arithmetic.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Any techniques used to reduce cancellation errors in Numerics.Generic_Complex_Arrays shall be documented.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above accuracy requirement is met by the canonical implementation of the inner product by multiplication and addition using the corresponding operations of type Complex and performing the cumulative addition using ascending indices. Note however, that some hardware provides special operations for the computation of the inner product and although these may be fast they may not meet the accuracy requirement specified. See Accuracy and Stability of Numerical Algorithms by N J Higham (ISBN 0-89871-355-2), Sections 3.1 and 3.6.]} @end{ImplNote} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Although many operations are defined in terms of operations from numerics.@!generic_complex_types, they need not be implemented by calling those operations provided that the effect is the same.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations should implement the Solve and Inverse functions using established techniques. Implementations are recommended to refine the result by performing an iteration on the residuals; if this is done then it should be documented.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Solve and Inverse for Numerics.Generic_Complex_Arrays should be implemented using established techniques and the result should be refined by an iteration on the residuals.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[It is not the intention that any special provision should be made to determine whether a matrix is ill-conditioned or not. The naturally occurring overflow (including division by zero) which will result from executing these functions with an ill-conditioned matrix and thus raise Constraint_Error is sufficient.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There isn't any advice for the implementation to document with this paragraph.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The test that a matrix is Hermitian should use the equality operator to compare the real components and negation followed by equality to compare the imaginary components (see @RefSecNum{Model of Floating Point Arithmetic}).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The equality and negation operators should be used to test that a matrix is Hermitian.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations should not perform operations on mixed complex and real operands by first converting the real operand to complex. See @RefSecNum{Complex Types}.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Mixed real and complex operations should not be performed by converting the real operand to complex.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Numerics.Generic_Complex_Arrays and its nongeneric equivalents are new.@Comment{ It would be better if this was called "Ada.Numerics.Generic_Imitation_Arrays", 'cause that's the opposite of Real. :-) Just checking if anyone reads this stuff.}]} @end{Extend95} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/obsolescent.mss������������������������������������������������������0000755�0001752�0001001�00000106253�12273462240�020474� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(obsolescent, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:32 $} @LabeledNormativeAnnex{Obsolescent Features} @Comment{$Source: e:\\cvsroot/ARM/Source/obsolescent.mss,v $} @Comment{$Revision: 1.40 $} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00368-01]} @Redundant[@Defn{obsolescent feature} This Annex contains descriptions of features of the language whose functionality is largely redundant with other features defined by this International Standard. Use of these features is not recommended in newly written programs. @Chg{Version=[2],New=[Use of these features can be prevented by using pragma Restrictions (No_Obsolescent_Features), see @RefSecNum{Language-Defined Restrictions}.], Old=[]}] @begin{Ramification} These features are still part of the language, and have to be implemented by conforming implementations. The primary reason for putting these descriptions here is to get redundant features out of the way of most readers. The designers of the next version of Ada@Chg{Version=[2],New=[], Old=[ after Ada 95]} will have to assess whether or not it makes sense to drop these features from the language. @end{Ramification} @end{Intro} @begin{DiffWord83} @Leading@;The following features have been removed from the language, rather than declared to be obsolescent: @begin{Itemize} The package Low_Level_IO (see @RefSecNum{Input-Output}). The Epsilon, Mantissa, Emax, Small, Large, Safe_Emax, Safe_Small, and Safe_Large attributes of floating point types (see @RefSecNum{Attributes of Floating Point Types}). @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00284-02]} @ChgDeleted{Version=[2],Text=[The pragma Interface (see @RefSecNum{Interfacing Pragmas}).]} The pragmas System_Name, Storage_Unit, and Memory_Size (see @RefSecNum{The Package System}). The pragma Shared (see @RefSecNum{Shared Variable Control}). @end{Itemize} Implementations can continue to support the above features for upward compatibility. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00368-01]} @ChgAdded{Version=[2],Text=[A mention of the No_Obsolescent_Features restriction was added.]} @end{DiffWord95} @LabeledClause{Renamings of Ada 83 Library Units} @begin{StaticSem} The following @nt{library_unit_renaming_declaration}s exist: @begin{Example} @key[with] Ada.Unchecked_Conversion; @key[generic] @key[function] Unchecked_Conversion @key[renames] Ada.Unchecked_Conversion; @key[with] Ada.Unchecked_Deallocation; @key[generic] @key[procedure] Unchecked_Deallocation @key[renames] Ada.Unchecked_Deallocation; @key[with] Ada.Sequential_IO; @key[generic] @key[package] Sequential_IO @key[renames] Ada.Sequential_IO; @key[with] Ada.Direct_IO; @key[generic] @key[package] Direct_IO @key[renames] Ada.Direct_IO; @key[with] Ada.Text_IO; @key[package] Text_IO @key[renames] Ada.Text_IO; @key[with] Ada.IO_Exceptions; @key[package] IO_Exceptions @key[renames] Ada.IO_Exceptions; @key[with] Ada.Calendar; @key[package] Calendar @key[renames] Ada.Calendar; @key[with] System.Machine_Code; @key[package] Machine_Code @key[renames] System.Machine_Code; --@RI{ If supported.} @end{Example} @end{StaticSem} @begin{ImplReq} The implementation shall allow the user to replace these renamings. @end{ImplReq} @LabeledClause{Allowed Replacements of Characters} @begin{Syntax} @begin{SyntaxText} @Leading@;The following replacements are allowed for the vertical line, number sign, and quotation mark characters: @begin{Itemize} A vertical line character (|) can be replaced by an exclamation mark (!) where used as a delimiter. The number sign characters (#) of a @nt{based_literal} can be replaced by colons (:) provided that the replacement is done for both occurrences. @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The intent is that such a replacement works in the Value@Chg{Version=[2],New=[,],Old=[ and]} Wide_Value@Chg{Version=[2],New=[, and Wide_Wide_Value],Old=[]} attributes, and in the Get procedures of Text_IO@Chg{Version=[2],New=[ (and Wide_Text_IO and Wide_Wide_Text_IO as well)],Old=[]}}, so that things like @lquotes@;16:.123:@rquotes@; is acceptable. @end{Honest} The quotation marks (") used as string brackets at both ends of a string literal can be replaced by percent signs (%) provided that the enclosed sequence of characters contains no quotation mark, and provided that both string brackets are replaced. Any percent sign within the sequence of characters shall then be doubled and each such doubled percent sign is interpreted as a single percent sign character value. @end{Itemize} These replacements do not change the meaning of the program. @begin{Reason} The original purpose of this feature was to support hardware (for example, teletype machines) that has long been obsolete. The feature is no longer necessary for that reason. Another use of the feature has been to replace the vertical line character (|) when using certain hardware that treats that character as a (non-English) letter. The feature is no longer necessary for that reason, either, since Ada 95 has full support for international character sets. Therefore, we believe this feature is no longer necessary. Users of equipment that still uses | to represent a letter will continue to do so. Perhaps by next the time Ada is revised, such equipment will no longer be in use. @Leading@;Note that it was never legal to use this feature as a convenient method of including double quotes in a string without doubling them @em the string literal: @begin{Example} %"This is quoted."% @end{Example} @Leading@;is not legal in Ada 83, nor will it be in Ada 95. One has to write: @begin{Example} """This is quoted.""" @end{Example} @end{Reason} @end{SyntaxText} @end{Syntax} @LabeledClause{Reduced Accuracy Subtypes} @begin{Intro} A @nt<digits_constraint> may be used to define a floating point subtype with a new value for its requested decimal precision, as reflected by its Digits attribute. Similarly, a @nt<delta_constraint> may be used to define an ordinary fixed point subtype with a new value for its @i(delta), as reflected by its Delta attribute. @begin(Discussion) It might be more direct to make these attributes specifiable via an @nt<attribute_definition_clause>, and eliminate the syntax for these @ntf<_constraint>s. @end(Discussion) @end{Intro} @begin{Syntax} @Syn{lhs=<delta_constraint>, rhs="@key{delta} @SynI{static_}@Syn2{expression} [@Syn2{range_constraint}]"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(delta_constraint expression)} The @nt<expression> of a @nt<delta_constraint> is expected to be of any real type. @end{Resolution} @begin{Legality} The @nt<expression> of a @nt<delta_constraint> shall be static. For a @nt<subtype_indication> with a @nt<delta_constraint>, the @nt<subtype_mark> shall denote an ordinary fixed point subtype. @Defn{notwithstanding} For a @nt<subtype_indication> with a @nt<digits_constraint>, the @nt<subtype_mark> shall denote either a decimal fixed point subtype or a floating point subtype (notwithstanding the rule given in @RefSecNum(Fixed Point Types) that only allows a decimal fixed point subtype). @begin(Discussion) @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[We may need a better way to deal with obsolescent features with rules that contradict those of the non-obsolescent parts of the standard.]} @end(Discussion) @end{Legality} @begin{StaticSem} A @nt<subtype_indication> with a @nt<subtype_mark> that denotes an ordinary fixed point subtype and a @nt<delta_constraint> defines an ordinary fixed point subtype with a @i(delta) given by the value of the @nt<expression> of the @nt<delta_constraint>. If the @nt<delta_constraint> includes a @nt<range_@!constraint>, then the ordinary fixed point subtype is constrained by the @nt<range_@!constraint>. A @nt<subtype_indication> with a @nt<subtype_mark> that denotes a floating point subtype and a @nt<digits_constraint> defines a floating point subtype with a requested decimal precision (as reflected by its Digits attribute) given by the value of the @nt<expression> of the @nt<digits_constraint>. If the @nt<digits_constraint> includes a @nt<range_@!constraint>, then the floating point subtype is constrained by the @nt<range_@!constraint>. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(delta_constraint with an ordinary fixed point subtype)} A @nt<delta_constraint> is @i(compatible) with an ordinary fixed point subtype if the value of the @nt<expression> is no less than the @i(delta) of the subtype, and the @nt<range_constraint>, if any, is compatible with the subtype. @PDefn2{Term=[compatibility], Sec=(digits_constraint with a floating point subtype)} A @nt<digits_constraint> is @i(compatible) with a floating point subtype if the value of the @nt<expression> is no greater than the requested decimal precision of the subtype, and the @nt<range_constraint>, if any, is compatible with the subtype. @PDefn2{Term=[elaboration], Sec=(delta_constraint)} The elaboration of a @nt<delta_constraint> consists of the elaboration of the @nt<range_constraint>, if any. @begin{Reason} A numeric subtype is considered @lquotes@;constrained@rquotes@; only if a range constraint applies to it. The only effect of a @nt<digits_constraint> or a @nt<delta_constraint> without a @nt<range_constraint> is to specify the value of the corresponding Digits or Delta attribute in the new subtype. The set of values of the subtype is not @lquotes@;constrained@rquotes@; in any way by such @ntf<_constraint>s. @end{Reason} @end{RunTime} @begin{DiffWord83} In Ada 83, a @nt<delta_constraint> is called a fixed_point_constraint, and a @nt<digits_constraint> is called a floating_point_constraint. We have adopted other terms because @nt<digits_constraint>s apply primarily to decimal fixed point types now (they apply to floating point types only as an obsolescent feature). @end{DiffWord83} @RMNewPage@Comment{For printed Ada 2007 RM} @LabeledClause{The Constrained Attribute} @begin{StaticSem} @Leading@;For every private subtype S, the following attribute is defined: @begin{Discussion} This includes generic formal private subtypes. @end{Discussion} @begin{Description} S'@attr{Constrained}@\Yields the value False if S denotes an unconstrained nonformal private subtype with discriminants; also yields the value False if S denotes a generic formal private subtype, and the associated actual subtype is either an unconstrained subtype with discriminants or an unconstrained array subtype; yields the value True otherwise. The value of this attribute is of the predefined subtype Boolean. @begin{Reason} Because Ada 95 has @nt{unknown_discriminant_part}s, the Constrained attribute of private subtypes is obsolete. This is fortunate, since its Ada 83 definition was confusing, as explained below. Because this attribute is obsolete, we do not bother to extend its definition to private extensions. The Constrained attribute of an object is @i(not) obsolete. Note well: S'Constrained matches the Ada 95 definition of @lquotes@;constrained@rquotes@; only for composite subtypes. For elementary subtypes, S'Constrained is always true, whether or not S is constrained. (The Constrained attribute of an object does not have this problem, as it is only defined for objects of a discriminated type.) So one should think of its designator as being 'Constrained_Or_Elementary. @end{Reason} @end{Description} @end{StaticSem} @LabeledClause{ASCII} @begin{StaticSem} @Leading@;The following declaration exists in the declaration of package Standard: @begin{example} @key[package] ASCII @key[is] --@RI{ Control characters:} @tabclear()@tabset(P47) NUL : @key[constant] Character := @RI{nul}; @\SOH : @key[constant] Character := @RI{soh}; STX : @key[constant] Character := @RI{stx}; @\ETX : @key[constant] Character := @RI{etx}; EOT : @key[constant] Character := @RI{eot}; @\ENQ : @key[constant] Character := @RI{enq}; ACK : @key[constant] Character := @RI{ack}; @\BEL : @key[constant] Character := @RI{bel}; BS : @key[constant] Character := @RI{bs}; @\HT : @key[constant] Character := @RI{ht}; LF : @key[constant] Character := @RI{lf}; @\VT : @key[constant] Character := @RI{vt}; FF : @key[constant] Character := @RI{ff}; @\CR : @key[constant] Character := @RI{cr}; SO : @key[constant] Character := @RI{so}; @\SI : @key[constant] Character := @RI{si}; DLE : @key[constant] Character := @RI{dle}; @\DC1 : @key[constant] Character := @RI{dc1}; DC2 : @key[constant] Character := @RI{dc2}; @\DC3 : @key[constant] Character := @RI{dc3}; DC4 : @key[constant] Character := @RI{dc4}; @\NAK : @key[constant] Character := @RI{nak}; SYN : @key[constant] Character := @RI{syn}; @\ETB : @key[constant] Character := @RI{etb}; CAN : @key[constant] Character := @RI{can}; @\EM : @key[constant] Character := @RI{em}; SUB : @key[constant] Character := @RI{sub}; @\ESC : @key[constant] Character := @RI{esc}; FS : @key[constant] Character := @RI{fs}; @\GS : @key[constant] Character := @RI{gs}; RS : @key[constant] Character := @RI{rs}; @\US : @key[constant] Character := @RI{us}; DEL : @key[constant] Character := @RI{del}; --@RI{ Other characters:} Exclam : @key[constant] Character:= '!';@\Quotation : @key[constant] Character:= '"'; Sharp : @key[constant] Character:= '#';@\Dollar : @key[constant] Character:= '$'; Percent : @key[constant] Character:= '%';@\Ampersand : @key[constant] Character:= '&'; Colon : @key[constant] Character:= ':';@\Semicolon : @key[constant] Character:= ';'; Query : @key[constant] Character:= '?';@\At_Sign : @key[constant] Character:= '@@'; L_Bracket: @key[constant] Character:= '[';@\Back_Slash: @key[constant] Character:= '\'; R_Bracket: @key[constant] Character:= ']';@\Circumflex: @key[constant] Character:= '^'; Underline: @key[constant] Character:= '_';@\Grave : @key[constant] Character:= '`'; L_Brace : @key[constant] Character:= '{';@\Bar : @key[constant] Character:= '|'; R_Brace : @key[constant] Character:= '}';@\Tilde : @key[constant] Character:= '~'; --@RI{ Lower case letters:} LC_A: @key[constant] Character:= 'a'; ... LC_Z: @key[constant] Character:= 'z'; @key[end] ASCII; @end{example} @end{StaticSem} @LabeledClause{Numeric_Error} @begin{StaticSem} @Leading@;The following declaration exists in the declaration of package Standard: @begin{Example} Numeric_Error : @key[exception] @key[renames] Constraint_Error; @end{Example} @begin{Discussion} This is true even though it is not shown in @RefSecNum{The Package Standard}. @end{Discussion} @begin{Reason} In Ada 83, it was unclear which situations should raise Numeric_Error, and which should raise Constraint_Error. The permissions of RM83-11.6 could often be used to allow the implementation to raise Constraint_Error in a situation where one would normally expect Numeric_Error. To avoid this confusion, all situations that raise Numeric_Error in Ada 83 are changed to raise Constraint_Error in Ada 95. Numeric_Error is changed to be a renaming of Constraint_Error to avoid most of the upward compatibilities associated with this change. In new code, Constraint_Error should be used instead of Numeric_Error. @end{Reason} @end{StaticSem} @LabeledClause{At Clauses} @begin{Syntax} @Syn{lhs=<at_clause>,rhs="@key{for} @Syn2{direct_name} @key{use} @key{at} @Syn2{expression};"} @end{Syntax} @begin{StaticSem} An @nt{at_clause} of the form @lquotes@;for @i{x} use at @i{y};@rquotes@; is equivalent to an @nt{attribute_definition_clause} of the form @lquotes@;for @i{x}'Address use @i{y};@rquotes@;. @begin{Reason} The preferred syntax for specifying the address of an entity is an @nt{attribute_definition_clause} specifying the Address attribute. Therefore, the special-purpose @nt{at_clause} syntax is now obsolete. The above equivalence implies, for example, that only one @nt{at_clause} is allowed for a given entity. Similarly, it is illegal to give both an @nt{at_clause} and an @nt{attribute_definition_clause} specifying the Address attribute. @end{Reason} @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} We now allow to define the address of an entity using an @nt{attribute_definition_clause}. This is because Ada 83's @nt{at_clause} is so hard to remember: programmers often tend to write @lquotes@;for X'Address use...;@rquotes@;. @end{Extend83} @begin{DiffWord83} Ada 83's @ntf{address_clause} is now called an @nt{at_clause} to avoid confusion with the new term @lquotes@;Address clause@rquotes@; (that is, an @nt{attribute_definition_clause} for the Address attribute). @end{DiffWord83} @LabeledSubClause{Interrupt Entries} @begin{Intro} @redundant[Implementations are permitted to allow the attachment of task entries to interrupts via the address clause. Such an entry is referred to as an @i{interrupt entry}. The address of the task entry corresponds to a hardware interrupt in an implementation-defined manner. (See Ada.Interrupts.Reference in @RefSecNum{The Package Interrupts}.)] @end{Intro} @begin{StaticSem} @Leading@;The following attribute is defined: @Leading@;For any task entry X: @begin{Description} @Defn{interrupt entry} X'@attr{Address} @\For a task entry whose address is specified (an @i{interrupt entry}), the value refers to the corresponding hardware interrupt. For such an entry, as for any other task entry, the meaning of this value is implementation defined. The value of this attribute is of the type of the subtype System.Address. @NoPrefix@;@PDefn2{Term=[specifiable], Sec=(of Address for entries)} Address may be specified for single entries via an @nt{attribute_definition_clause}. @begin{Reason} Because of the equivalence of @nt{at_clause}s and @nt{attribute_definition_clause}s, an interrupt entry may be specified via either notation. @end{Reason} @end{Description} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[initialization], Sec=[of a task object]} As part of the initialization of a task object, the address clause for an interrupt entry is elaborated@Redundant[, which evaluates the @nt<expression> of the address clause]. A check is made that the address specified is associated with some interrupt to which a task entry may be attached. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If this check fails, Program_Error is raised. Otherwise, the interrupt entry is attached to the interrupt associated with the specified address. @PDefn2{Term=[finalization], Sec=[of a task object]} Upon finalization of the task object, the interrupt entry, if any, is detached from the corresponding interrupt and the default treatment is restored. While an interrupt entry is attached to an interrupt, the interrupt is reserved (see @RefSecNum{Interrupt Support}). An interrupt delivered to a task entry acts as a call to the entry issued by a hardware task whose priority is in the System.Interrupt_Priority range. It is implementation defined whether the call is performed as an ordinary entry call, a timed entry call, or a conditional entry call; which kind of call is performed can depend on the specific interrupt. @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to evaluate E'Caller (see @RefSecNum(The Package Task_Identification)) in an @nt{accept_statement} for an interrupt entry. The possible effects are the same as for calling Current_Task from an entry body. @end{Bounded} @begin{DocReq} The implementation shall document to which interrupts a task entry may be attached. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The interrupts to which a task entry may be attached.]}]} The implementation shall document whether the invocation of an interrupt entry has the effect of an ordinary entry call, conditional call, or a timed call, and whether the effect varies in the presence of pending interrupts. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The type of entry call invoked for an interrupt entry.]}]} @end{DocReq} @begin{ImplPerm} The support for this subclause is optional. Interrupts to which the implementation allows a task entry to be attached may be designated as reserved for the entire duration of program execution@Redundant[; that is, not just when they have an interrupt entry attached to them]. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} Interrupt entry calls may be implemented by having the hardware execute directly the appropriate @Chg{New=[@nt{accept_statement}],Old=[accept body]}. Alternatively, the implementation is allowed to provide an internal interrupt handler to simulate the effect of a normal task calling the entry. The implementation is allowed to impose restrictions on the specifications and bodies of tasks that have interrupt entries. It is implementation defined whether direct calls (from the program) to interrupt entries are allowed. If a @nt{select_statement} contains both a @nt{terminate_alternative} and an @nt{accept_alternative} for an interrupt entry, then an implementation is allowed to impose further requirements for the selection of the @nt{terminate_alternative} in addition to those given in @RefSecNum{Task Dependence - Termination of Tasks}. @end{ImplPerm} @begin{Notes} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} Queued interrupts correspond to ordinary entry calls. Interrupts that are lost if not immediately processed correspond to conditional entry calls. It is a consequence of the priority rules that an @Chg{New=[@nt{accept_statement}], Old=[accept body]} executed in response to an interrupt can be executed with the active priority at which the hardware generates the interrupt, taking precedence over lower priority tasks, without a scheduling action. Control information that is supplied upon an interrupt can be passed to an associated interrupt entry as one or more parameters of mode @key[in]. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of an interrupt entry:} @begin{example} @key[task] Interrupt_Handler @key[is] @key[entry] Done; @key[for] Done'Address @key[use] Ada.Interrupts.Reference(Ada.Interrupts.Names.Device_Done); @key[end] Interrupt_Handler; @end{example} @end{Examples} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} RM83-13.5.1 did not adequately address the problems @Chg{Version=[2],New=[associated],Old=[associate]} with interrupts. This feature is now obsolescent and is replaced by the Ada 95 interrupt model as specified in the Systems Programming Annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0077],ARef=[AI95-00111-01]} @Chg{Version=[2],New=[@b<Corrigendum:> The undefined term @i{accept body} was replaced by @nt{accept_statement}.], Old=[]} @end{DiffWord95} @RMNewPage@Comment{For printed RM Ada 2007} @LabeledClause{Mod Clauses} @begin{Syntax} @Syn{lhs=<mod_clause>,rhs="@key{at} @key{mod} @SynI{static_}@Syn2{expression};"} @end{Syntax} @begin{StaticSem} @leading@keepnext@;A @nt{record_representation_clause} of the form: @begin{example} @key[for] @RI{r} @key[use] @key[record] @key[at] @key[mod] @RI{a} ... @key[end] @key[record]; @end{example} @leading@keepnext@;is equivalent to: @begin{example} @key[for] @RI{r}'Alignment @key[use] @RI{a}; @key[for] @RI{r} @key[use] @key[record] ... @key[end] @key[record]; @end{example} @begin{Reason} The preferred syntax for specifying the alignment of an entity is an @nt{attribute_definition_clause} specifying the Alignment attribute. Therefore, the special-purpose @nt{mod_clause} syntax is now obsolete. The above equivalence implies, for example, that it is illegal to give both a @nt{mod_clause} and an @nt{attribute_definition_clause} specifying the Alignment attribute for the same type. @end{Reason} @end{StaticSem} @begin{DiffWord83} Ada 83's @ntf{alignment_clause} is now called a @nt{mod_clause} to avoid confusion with the new term @lquotes@;Alignment clause@rquotes@; (that is, an @nt{attribute_definition_clause} for the Alignment attribute). @end{DiffWord83} @LabeledClause{The Storage_Size Attribute} @begin{StaticSem} @Leading@;For any task subtype T, the following attribute is defined: @begin{Description} T'@attr{Storage_Size} @\Denotes an implementation-defined value of type @i{universal_integer} representing the number of storage elements reserved for a task of the subtype T. @begin{Honest} T'Storage_Size cannot be particularly meaningful in the presence of a @nt{pragma} Storage_Size, especially when the expression is dynamic, or depends on a discriminant of the task, because the Storage_Size will be different for different objects of the type. Even without such a @nt{pragma}, the Storage_Size can be different for different objects of the type, and in any case, the value is implementation defined. Hence, it is always implementation defined. @end{Honest} @NoPrefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[specifiable], Sec=(of Storage_Size for a task first subtype)} @NoPrefix@;Storage_Size may be specified for a task first subtype @Chg{Version=[2],New=[that is not an interface ],Old=[]}via an @nt{attribute_definition_clause}. @end{Description} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[We don't allow specifying Storage_Size on task interfaces. We don't need to mention class-wide task types, because these cannot be a first subtype.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Specific Suppression of Checks]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[Pragma Suppress can be used to suppress checks on specific entities.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The form of a specific Suppress @nt{pragma} is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2], New=`@ @ @key{pragma} @prag{Suppress}(@Syn2{identifier}, [On =>] @Syn2{name});', Old=<>} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The @nt{identifier} shall be the name of a check (see @RefSecNum{Suppressing Checks}). The @nt{name} shall statically denote some entity.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[For a specific Suppress @nt{pragma} that is immediately within a @nt{package_specification}, the @nt{name} shall denote an entity (or several overloaded subprograms) declared immediately within the @nt{package_@!specification}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A specific Suppress @nt{pragma} applies to the named check from the place of the @nt{pragma} to the end of the innermost enclosing declarative region, or, if the @nt{pragma} is given in a @nt{package_specification}, to the end of the scope of the named entity. The @nt{pragma} applies only to the named entity, or, for a subtype, on objects and values of its type. A specific Suppress @nt{pragma} suppresses the named check for any entities to which it applies (see @RefSecNum{Suppressing Checks}). Which checks are associated with a specific entity is not defined by this International Standard.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @begin{Discussion} @ChgAdded{Version=[2],Text=[The language doesn't specify exactly which entities control whether a check is performed. For example, in]} @begin{Example} @Chg{Version=[2],New=[@key{pragma} Suppress (Range_Check, On => A); A := B;],Old=[]} @end{Example} @ChgAdded{Version=[2],Text=[whether or not the range check is performed is not specified. The compiler may require that checks are suppressed on B or on the type of A in order to omit the range check.]} @end{Discussion} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation is allowed to place restrictions on specific Suppress @nt{pragma}s.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation may support a similar On parameter on @nt{pragma} Unsuppress (see @RefSecNum{Suppressing Checks}).]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[This clause is new. This feature was moved here because it is important for pragma Unsuppress that there be an unambiguous meaning for each checking pragma. For instance, in the example]} @begin{Example} @ChgAdded{Version=[2],Text=[@key{pragma} Suppress (Range_Check); @key{pragma} Unsuppress (Range_Check, On => A); A := B;]} @end{Example} @ChgAdded{Version=[2],Text=[the user needs to be able to depend on the range check being made on the assignment. But a compiler survey showed that the interpretation of this feature varied widely; trying to define this carefully was likely to cause a lot of user and implementer pain. Thus the feature was moved here, to emphasize that its use is not portable.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[The Class Attribute of Untagged Incomplete Types]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For the first subtype S of a type @i<T> declared by an @nt<incomplete_type_declaration> that is not tagged, the following attribute is defined:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[S'@attr{Class} @\Denotes the first subtype of the incomplete class-wide type rooted at @i<T>. The completion of @i<T> shall declare a tagged type. Such an attribute reference shall occur in the same library unit as the @nt<incomplete_type_declaration>.],Old=[]} @end{Description} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[This must occur in the same unit to prevent children from imposing requirements on their ancestor library units for deferred incomplete types.]} @end{reason} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[This clause is new. This feature was moved here because the tagged incomplete type provides a better way to provide this capability (it doesn't put requirements on the completion based on uses that could be anywhere). Pity we didn't think of it in 1994.],Old=[]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Pragma Interface]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[In addition to an identifier, the reserved word @key{interface} is allowed as a pragma name, to provide compatibility with a prior edition of this International Standard.]} @end{SyntaxText} @end{Syntax} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[All implementations need to at least recognize and ignore this pragma. A syntax error is not an acceptable implementation of this pragma.]} @end{ImplNote} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[This clause is new. This is necessary as @key{interface} is now a reserved word, which would prevent pragma Interface from being an implementation-defined pragma. We don't define any semantics for this pragma, as we expect that implementations will continue to use whatever they currently implement - requiring any changes would be counter-productive.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Dependence Restriction Identifiers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[The following restrictions involve dependence on specific language-defined units. The more general restriction No_Dependence (see @RefSecNum{Language-Defined Restrictions}) should be used for this purpose.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following @Syni<restriction_>@nt<identifier>s exist:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Asynchronous_Control)}No_Asynchronous_Control @\Semantic dependence on the predefined package Asynchronous_Task_Control is not allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Conversion)}No_Unchecked_Conversion @\Semantic dependence on the predefined generic function Unchecked_Conversion is not allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Deallocation)}No_Unchecked_Deallocation @\Semantic dependence on the predefined generic procedure Unchecked_Deallocation is not allowed.]} @end{Description} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[This clause is new. These restrictions are replaced by the more general No_Dependence (see @RefSecNum{Language-Defined Restrictions}).]} @end{DiffWord95} @RMNewPage @LabeledAddedClause{Version=[2],Name=[Character and Wide_Character Conversion Functions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following declarations exist in the declaration of package Ada.Characters.Handling:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character (Item : @key{in} Wide_Character) @key{return} Boolean @key{renames} Conversions.Is_Character; @key{function} Is_String (Item : @key{in} Wide_String) @key{return} Boolean @key{renames} Conversions.Is_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Character (Item : @key{in} Wide_Character; Substitute : @key{in} Character := ' ') @key{return} Character @key{renames} Conversions.To_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_String (Item : @key{in} Wide_String; Substitute : @key{in} Character := ' ') @key{return} String @key{renames} Conversions.To_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Wide_Character (Item : @key{in} Character) @key{return} Wide_Character @key{renames} Conversions.To_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Wide_String (Item : @key{in} String) @key{return} Wide_String @key{renames} Conversions.To_Wide_String;]} @end{Example} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[This clause is new. These subprograms were moved to Characters.Conversions (see @RefSecNum{The Package Characters.Conversions}).]} @end{DiffWord95} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pragmas.mss����������������������������������������������������������0000755�0001752�0001001�00000000723�12273462240�017601� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(pragmas, Root="ada.mss") @Comment{$Date: 2000/08/12 00:40:17 $} @LabeledInformativeAnnex{Language-Defined Pragmas} @comment{$Source: e:\\cvsroot/ARM/Source/pragmas.mss,v $} @comment{$Revision: 1.14 $} @begin{Intro} @Defn{pragma} This Annex summarizes the definitions given elsewhere of the language-defined pragmas. @PragmaList @end{Intro} @begin{DiffWord83} Pragmas List, Page, and Optimize are now officially defined in @RefSec{Pragmas}. @end{DiffWord83}���������������������������������������������org.adaic.arm_form/source_2005/pre.mss��������������������������������������������������������������0000755�0001752�0001001�00000034332�12273462240�016740� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(predef, Root="ada.mss") @Comment{$Date: 2006/03/21 22:47:18 $} @LabeledNormativeAnnex{Predefined Language Environment} @comment{$Source: e:\\cvsroot/ARM/Source/pre.mss,v $} @comment{$Revision: 1.32 $} @comment{$RLB: Eliminated includes. $} @begin{Intro} @Leading@keepnext @redundant[@Defn{Language-Defined Library Units} @Defn{predefined environment} This Annex contains the specifications of library units that shall be provided by every implementation. There are three root library units: Ada, Interfaces, and System; other library units are children of these:] @Leading@Keepnext @ChgRef{Version=(1),Kind=(Revised),Ref=(8652/0047),ARef=(AI95-00081-01)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00424-01]} @ @*@ @;@comment{paragraph number here, paragraph numbers seem to intrude on the RHS column, misaligning it. Thus we have two lines, as small as possible.} @begin{Display} @TabClear{}@TabSet{L2, L4, L6, L8, L10, L12, L14, L16} @begin{TwoCol} @Noparanum@redundant[@shrink<Standard @em @RefSecNum{The Package Standard} @\Ada @em @RefSecNum{The Package Ada} @Chg{Version=[2],New=(@\@\Assertions @em @RefSecNum{Pragmas Assert and Assertion_Policy} ), Old=()}@\@\Asynchronous_Task_Control @em @RefSecNum{Asynchronous Task Control} @\@\Calendar @em @RefSecNum{Delay Statements, Duration, and Time} @Chg{Version=[2],New=(@\@\@\Arithmetic @em @RefSecNum{Formatting, Time Zones, and other operations for Time} @\@\@\Formatting @em @RefSecNum{Formatting, Time Zones, and other operations for Time} @\@\@\Time_Zones @em @RefSecNum{Formatting, Time Zones, and other operations for Time} ), Old=()}@\@\Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} @Chg{Version=[2],New=(@\@\@\Conversions @em @RefSecNum{The Package Characters.Conversions} ), Old=()}@\@\@\Handling @em @RefSecNum{The Package Characters.Handling} @\@\@\Latin_1 @em @RefSecNum{The Package Characters.Latin_1} @\@\Command_Line @em @RefSecNum{The Package Command_Line} @Chg{Version=[2],New=(@\@\Complex_Text_IO @em @RefSecNum{Complex Input-Output} @\@\Containers @em @RefSecNum{The Package Containers} @\@\@\Doubly_Linked_Lists @em @RefSecNum{The Package Containers.Doubly_Linked_Lists} @\@\@\Generic_Array_Sort @em @RefSecNum{Array Sorting} @\@\@\Generic_Constrained_Array_Sort @\@\@\@\@\@\@em @RefSecNum{Array Sorting} @\@\@\Hashed_Maps @em @RefSecNum{The Package Containers.Hashed_Maps} @\@\@\Hashed_Sets @em @RefSecNum{The Package Containers.Hashed_Sets} @\@\@\Indefinite_Doubly_Linked_Lists @\@\@\@\@\@\@em @RefSecNum{The Package Containers.Indefinite_Doubly_Linked_Lists} @\@\@\Indefinite_Hashed_Maps @em @RefSecNum{The Package Containers.Indefinite_Hashed_Maps} @\@\@\Indefinite_Hashed_Sets @em @RefSecNum{The Package Containers.Indefinite_Hashed_Sets} @\@\@\Indefinite_Ordered_Maps @em @RefSecNum{The Package Containers.Indefinite_Ordered_Maps} @\@\@\Indefinite_Ordered_Sets @em @RefSecNum{The Package Containers.Indefinite_Ordered_Sets} @\@\@\Indefinite_Vectors @em @RefSecNum{The Package Containers.Indefinite_Vectors} @\@\@\Ordered_Maps @em @RefSecNum{The Package Containers.Ordered_Maps} @\@\@\Ordered_Sets @em @RefSecNum{The Package Containers.Ordered_Sets} @\@\@\Vectors @em @RefSecNum{The Package Containers.Vectors} ), Old=()}@\@\Decimal @em @RefSecNum{The Package Decimal} @\@\Direct_IO @em @RefSecNum{The Generic Package Direct_IO} @Chg{Version=[2],New=(@\@\Directories @em @RefSecNum{The Package Directories} @\@\@\Information @em @RefSecNum{The Package Directories} @\@\Dispatching @em @RefSecNum{The Task Dispatching Model} @\@\@\EDF @em @RefSecNum{Earliest Deadline First Dispatching} @\@\@\Round_Robin @em @RefSecNum{Round Robin Dispatching} ), Old=()}@\@\Dynamic_Priorities @em @RefSecNum{Dynamic Priorities}> @NewColumn@Comment{This should be conditional for version 2, but not with the current generator} @Noparanum@shrink<@Chg{Version=[2],New=[Standard (@i{...continued}) @\Ada (@i{...continued}) @\@\Environment_Variables @em @RefSecNum{The Package Environment_Variables} ], Old=()}@\@\Exceptions @em @RefSecNum{The Package Exceptions} @Chg{Version=[2],New=(@\@\Execution_Time @em @RefSecNum{Execution Time} @\@\@\Group_Budgets @em @RefSecNum{Group Execution Time Budgets} @\@\@\Timers @em @RefSecNum{Execution Time Timers} ), Old=()}@\@\Finalization @em @RefSecNum{User-Defined Assignment and Finalization} @Chg{New=(@\@\Float_Text_IO @em @RefSecNum{Input-Output for Real Types} @\@\Float_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @Chg{Version=[2],New=(@\@\Float_Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} ), Old=()}@\@\Integer_Text_IO @em @RefSecNum{Input-Output for Integer Types} @\@\Integer_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @Chg{Version=[2],New=(@\@\Integer_Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} ), Old=()}), Old=()}@\@\Interrupts @em @RefSecNum{The Package Interrupts} @\@\@\Names @em @RefSecNum{The Package Interrupts} @\@\IO_Exceptions @em @RefSecNum{Exceptions in Input-Output} @\@\Numerics @em @RefSecNum{The Numerics Packages} @Chg{Version=[2],New=(@\@\@\Complex_Arrays @em @RefSecNum{Complex Vectors and Matrices} ), Old=()}@\@\@\Complex_Elementary_Functions @em @RefSecNum{Complex Elementary Functions} @\@\@\Complex_Types @em @RefSecNum{Complex Types} @\@\@\Discrete_Random @em @RefSecNum{Random Number Generation} @\@\@\Elementary_Functions @em @RefSecNum{Elementary Functions} @\@\@\Float_Random @em @RefSecNum{Random Number Generation} @Chg{Version=[2],New=(@\@\@\Generic_Complex_Arrays @em @RefSecNum{Complex Vectors and Matrices} ), Old=()}@\@\@\Generic_Complex_Elementary_Functions @\@\@\@\@\@\@em @RefSecNum{Complex Elementary Functions} @\@\@\Generic_Complex_Types @em @RefSecNum{Complex Types} @\@\@\Generic_Elementary_Functions @em @RefSecNum{Elementary Functions} @Chg{Version=[2],New=(@\@\@\Generic_Real_Arrays @em @RefSecNum{Real Vectors and Matrices} @\@\@\Real_Arrays @em @RefSecNum{Real Vectors and Matrices} ), Old=()}@\@\Real_Time @em @RefSecNum{Monotonic Time} @Chg{Version=[2],New=(@\@\@\Timing_Events @em @RefSecNum{Timing Events} ), Old=()}@\@\Sequential_IO @em @RefSecNum{The Generic Package Sequential_IO} @\@\Storage_IO @em @RefSecNum{The Generic Package Storage_IO} @\@\Streams @em @RefSecNum{The Package Streams} @\@\@\Stream_IO @em @RefSecNum{The Package Streams.Stream_IO}> @NewColumn @Noparanum@shrink<Standard (@i{...continued}) @\Ada (@i{...continued}) @\@\Strings @em @RefSecNum{The Package Strings} @\@\@\Bounded @em @RefSecNum{Bounded-Length String Handling} @Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} ), Old=()}@\@\@\Fixed @em @RefSecNum{Fixed-Length String Handling} @Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} @\@\@\Hash @em @RefSecNum{String Hashing} ), Old=()}@\@\@\Maps @em @RefSecNum{The Package Strings.Maps} @\@\@\@\Constants @em @RefSecNum{String-Handling Sets and Mappings} @\@\@\Unbounded @em @RefSecNum{Unbounded-Length String Handling} @Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} ), Old=()}@\@\@\Wide_Bounded @em @RefSecNum{Wide_String Handling} @Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} ), Old=()}@\@\@\Wide_Fixed @em @RefSecNum{Wide_String Handling} @Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} ), Old=()}@\@\@\Wide_Maps @em @RefSecNum{Wide_String Handling} @\@\@\@\Wide_Constants @em @RefSecNum{Wide_String Handling} @\@\@\Wide_Unbounded @em @RefSecNum{Wide_String Handling} @Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @\@\@\Wide_Wide_Bounded @em @RefSecNum{Wide_Wide_String Handling} @\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Fixed @em @RefSecNum{Wide_Wide_String Handling} @\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Maps @em @RefSecNum{Wide_Wide_String Handling} @\@\@\@\Wide_Wide_Constants @em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Unbounded @em @RefSecNum{Wide_Wide_String Handling} @\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} ), Old=()}@\@\Synchronous_Task_Control @em @RefSecNum{Synchronous Task Control} @\@\Tags @em @RefSecNum{Tagged Types and Type Extensions} @Chg{Version=[2],New=(@\@\@\Generic_Dispatching_Constructor @em @RefSecNum{Tagged Types and Type Extensions} ), Old=()}@\@\Task_Attributes @em @RefSecNum{The Package Task_Attributes} @\@\Task_Identification @em @RefSecNum{The Package Task_Identification} @Chg{Version=[2],New=(@\@\Task_Termination @em @RefSecNum{The Package Task_Termination}), Old=()}> @NewColumn@Comment{This should be conditional for version 2, but not with the current generator} @Noparanum@shrink<@Chg{Version=[2],New=[Standard (@i{...continued}) @\Ada (@i{...continued}) ], Old=()}@\@\Text_IO @em @RefSecNum{The Package Text_IO} @Chg{Version=[2],New=(@\@\@\Bounded_IO @em @RefSecNum{Input-Output for Bounded Strings} ),Old=()}@\@\@\Complex_IO @em @RefSecNum{Complex Input-Output} @\@\@\Editing @em @RefSecNum{The Package Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Text_IO.Text_Streams} @Chg{Version=[2],New=(@\@\@\Unbounded_IO @em @RefSecNum{Input-Output for Unbounded Strings} ), Old=()}@\@\Unchecked_Conversion @em @RefSecNum{Unchecked Type Conversions} @\@\Unchecked_Deallocation @em @RefSecNum{Unchecked Storage Deallocation} @Chg{Version=[2],New=(@\@\Wide_Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} ),Old=()}@\@\Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Complex_IO @em @RefSecNum{The Package Wide_Text_IO.Complex_IO} @\@\@\Editing @em @RefSecNum{The Package Wide_Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Wide_Text_IO.Text_Streams} @Chg{Version=[2],New=(@\@\@\Wide_Bounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Wide_Unbounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\Wide_Wide_Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} @\@\Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Complex_IO @em @RefSecNum{The Package Wide_Wide_Text_IO.Complex_IO} @\@\@\Editing @em @RefSecNum{The Package Wide_Wide_Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Wide_Wide_Text_IO.Text_Streams} @\@\@\Wide_Wide_Bounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Wide_Wide_Unbounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output}), Old=()}> @Noparanum@shrink<@\Interfaces @em @RefSecNum{The Package Interfaces} @\@\C @em @RefSecNum{Interfacing with C and C++} @\@\@\Pointers @em @RefSecNum{The Generic Package Interfaces.C.Pointers} @\@\@\Strings @em @RefSecNum{The Package Interfaces.C.Strings} @\@\COBOL @em @RefSecNum{Interfacing with COBOL} @\@\Fortran @em @RefSecNum{Interfacing with Fortran}> @Noparanum@shrink<@\System @em @RefSecNum{The Package System} @\@\Address_To_Access_Conversions @em @RefSecNum{The Package System.Address_To_Access_Conversions} @\@\Machine_Code @em @RefSecNum{Machine Code Insertions} @\@\RPC @em @RefSecNum{Partition Communication Subsystem} @\@\Storage_Elements @em @RefSecNum{The Package System.Storage_Elements} @\@\Storage_Pools @em @RefSecNum{Storage Management}>] @end{TwoCol} @end{Display} @begin{Discussion} In running text, we generally leave out the @lquotes@;Ada.@rquotes@; when referring to a child of Ada. @end{Discussion} @begin{Reason} We had no strict rule for which of Ada, Interfaces, or System should be the parent of a given library unit. However, we have tried to place as many things as possible under Ada, except that interfacing is a separate category, and we have tried to place library units whose use is highly non-portable under System. @end{Reason} @end{Intro} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The implementation shall ensure that each language@Chg{Version=[2],New=[-],Old=[]}defined subprogram is reentrant@Chg{Version=[2],New=[@Defn{reentrant}],Old=[]}@ChgNote{Suggested by Gary Dismukes} in the sense that concurrent calls on the same subprogram perform as specified, so long as all parameters that could be passed by reference denote nonoverlapping objects. @begin{Ramification} For example, simultaneous calls to Text_IO.Put will work properly, so long as they are going to two different files. On the other hand, simultaneous output to the same file constitutes erroneous use of shared variables. @end{Ramification} @begin{Honest} Here, @lquotes@;language defined subprogram@rquotes@; means a language defined library subprogram, a subprogram declared in the visible part of a language defined library package, an instance of a language defined generic library subprogram, or a subprogram declared in the visible part of an instance of a language defined generic library package. @end{Honest} @begin{Ramification} The rule implies that any data local to the private part or body of the package has to be somehow protected against simultaneous access. @end{Ramification} @end{ImplReq} @begin{ImplPerm} The implementation may restrict the replacement of language-defined compilation units. The implementation may restrict children of language-defined library units (other than Standard). @begin{Ramification} For example, the implementation may say, @lquotes@;you cannot compile a library unit called System@rquotes@; or @lquotes@;you cannot compile a child of package System@rquotes@; or @lquotes@;if you compile a library unit called System, it has to be a package, and it has to contain at least the following declarations: ...@rquotes@;. @end{Ramification} @end{ImplPerm} @begin{DiffWord83} Many of Ada 83's language-defined library units are now children of Ada or System. For upward compatibility, these are renamed as root library units (see @RefSecNum{Renamings of Ada 83 Library Units}). The order and lettering of the annexes has been changed. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0047],ARef=[AI95-00081-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Units missing from the list of predefined units were added.]} @end{DiffWord95} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_ada.mss����������������������������������������������������������0000755�0001752�0001001�00000003326�12273462240�017544� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_ada.mss,v $ } @comment{ $Revision: 1.15 $ $Date: 00/03/08 Created by RLB to avoid Includes } @Part(predefstandard, Root="ada.mss") @Comment{$Date: 2000/08/31 04:56:06 $} @LabeledClause{The Package Ada} @begin{StaticSem} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @RootLibUnit{Ada}@key[package] Ada @key[is] @key[pragma] Pure(Ada); @key[end] Ada; @end{Example} Ada serves as the parent of most of the other language-defined library units; its declaration is empty (except for the @nt{pragma} Pure). @end{StaticSem} @begin{Legality} In the standard mode, it is illegal to compile a child of package Ada. @begin{Reason} The intention is that mentioning, say, Ada.Text_IO in a @nt{with_clause} is guaranteed (at least in the standard mode) to refer to the standard version of Ada.Text_IO. The user can compile a root library unit Text_IO that has no relation to the standard version of Text_IO. @end{Reason} @begin{Ramification} Note that Ada can have non-language-defined grandchildren, assuming the implementation allows it. Also, packages System and Interfaces can have children, assuming the implementation allows it. @end{Ramification} @begin{ImplNote} An implementation will typically support a nonstandard mode in which compiling the language defined library units is allowed. Whether or not this mode is made available to users is up to the implementer. An implementation could theoretically have private children of Ada, since that would be semantically neutral. However, a programmer cannot compile such a library unit. @end{ImplNote} @end{Legality} @begin{Extend83} @Defn{extensions to Ada 83} This clause is new to Ada 95. @end{Extend83} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_chars.mss��������������������������������������������������������0000755�0001752�0001001�00000151120�12273462240�020113� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_chars.mss,v $ } @comment{ $Revision: 1.30 $ $Date: 2006/10/19 06:40:32 $ $Author: Randy $ } @Part(predefchars, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:32 $} @LabeledClause{Character Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} This clause presents the packages related to character processing: an empty pure package Characters and child packages Characters.Handling and Characters.Latin_1. The package Characters.Handling provides classification and conversion functions for Character data, and some simple functions for dealing with Wide_Character @Chg{Version=[2],New=[and Wide_Wide_Character ], Old=[]}data. The child package Characters.Latin_1 declares a set of constants initialized to values of type Character. @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This clause is new to Ada 95. @end{Extend83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included Wide_Wide_Character in this description; the individual changes are documented as extensions as needed.]} @end{Diffword95} @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledRevisedSubClause{Version=[2],New=[The Packages Characters, Wide_Characters, and Wide_Wide_Characters],Old=[The Package Characters]} @begin{StaticSem} @leading@keepnext@;The library package Characters has the following declaration: @begin{example} @ChildUnit{Parent=[Ada],Child=[Characters]}@key(package) Ada.Characters @key[is] @key[pragma] Pure(Characters); @key(end) Ada.Characters; @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Wide_Characters has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Wide_Characters]}@key(package) Ada.Wide_Characters @key[is] @key[pragma] Pure(Wide_Characters); @key[end] Ada.Wide_Characters;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Wide_Wide_Characters has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Wide_Wide_Characters]}@key(package) Ada.Wide_Wide_Characters @key[is] @key[pragma] Pure(Wide_Wide_Characters); @key[end] Ada.Wide_Wide_Characters;]} @end{example} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[If an implementation chooses to provide implementation-defined operations on Wide_Character or Wide_String (such as case mapping, classification, collating and sorting, etc.) it should do so by providing child units of Wide_Characters. Similarly if it chooses to provide implementation-defined operations on Wide_Wide_Character or Wide_Wide_String it should do so by providing child units of Wide_Wide_Characters.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined operations on Wide_Character, Wide_String, Wide_Wide_Character, and Wide_Wide_String should be child units of Wide_Characters or Wide_Wide_Characters.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The packages Wide_Characters and Wide_Wide_Characters are new.]} @end{Extend95} @LabeledSubClause{The Package Characters.Handling} @begin{StaticSem} @leading@keepnext@;The library package Characters.Handling has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01],ARef=[AI95-00395-01]} @Chg{Version=[2],New=[@key[with] Ada.Characters.Conversions; ],Old=[]}@key[package] Ada.Characters.Handling @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Handling]} @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Handling); @keepnext--@RI{Character classification functions} @key[function] @AdaSubDefn{Is_Control} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Graphic} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Letter} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Lower} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Upper} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Basic} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Digit} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Decimal_Digit} (Item : @key[in] Character) @key[return] Boolean @key[renames] Is_Digit; @key[function] @AdaSubDefn{Is_Hexadecimal_Digit} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Alphanumeric} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Special} (Item : @key[in] Character) @key[return] Boolean; @keepnext--@RI{Conversion functions for Character and String} @key[function] @AdaSubDefn{To_Lower} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Upper} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Basic} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Lower} (Item : @key[in] String) @key[return] String; @key[function] @AdaSubDefn{To_Upper} (Item : @key[in] String) @key[return] String; @key[function] @AdaSubDefn{To_Basic} (Item : @key[in] String) @key[return] String; @keepnext--@RI{Classifications of and conversions between Character and ISO 646} @key[subtype] @AdaSubtypeDefn{Name=[ISO_646],Of=[Character]} @key[is] Character @key[range] Character'Val(0) .. Character'Val(127); @key[function] @AdaSubDefn{Is_ISO_646} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_ISO_646} (Item : @key[in] String) @key[return] Boolean; @key[function] @AdaSubDefn{To_ISO_646} (Item : @key[in] Character; Substitute : @key[in] ISO_646 := ' ') @key[return] ISO_646; @key[function] @AdaSubDefn{To_ISO_646} (Item : @key[in] String; Substitute : @key[in] ISO_646 := ' ') @key[return] String; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Keepnext--@RI{@Chg{Version=[2],New=[ The functions Is_Character, Is_String, To_Character, To_String, To_Wide_Character,],Old=[Classifications of and conversions between Wide_Character and Character.]}}@Chg{Version=[2],New=[ --@RI{ and To_Wide_String are obsolescent; see @RefSecnum{Character and Wide_Character Conversion Functions}.}],Old=[]} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@roman{@Shrink{@i<Paragraphs 14 through 18 were deleted.>}}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_String) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Character;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] String) @key[return] Wide_String;]} @key[end] Ada.Characters.Handling; @end{Example} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The @nt{with_clause} for Ada.Characters.Conversions is needed for the definition of the obsolescent functions (see @RefSecnum{Character and Wide_Character Conversion Functions}). It would be odd to put this clause into @RefSecnum{Character and Wide_Character Conversion Functions} as it was not present in Ada 95, and @nt{with_clause}s are semantically neutral to clients anyway.]} @end{Discussion} In the description below for each function that returns a Boolean result, the effect is described in terms of the conditions under which the value True is returned. If these conditions are not met, then the function returns False. Each of the following classification functions has a formal Character parameter, Item, and returns a Boolean result. @begin{description} @Defn2{term=[control character], sec=[a category of Character]}Is_Control @\True if Item is a control character. A @i{control character} is a character whose position is in one of the ranges 0..31 or 127..159. @Defn2{term=[graphic character], sec=[a category of Character]}Is_Graphic @\True if Item is a graphic character. A @i[graphic character] is a character whose position is in one of the ranges 32..126 or 160..255. @Defn2{term=[letter], sec=[a category of Character]}Is_Letter @\True if Item is a letter. A @i[letter] is a character that is in one of the ranges 'A'..'Z' or 'a'..'z', or whose position is in one of the ranges 192..214, 216..246, or 248..255. @Defn2{term=[lower-case letter], sec=[a category of Character]}Is_Lower @\True if Item is a lower-case letter. A @i[lower-case letter] is a character that is in the range 'a'..'z', or whose position is in one of the ranges 223..246 or 248..255. @Defn2{term=[upper-case letter], sec=[a category of Character]}Is_Upper@\True if Item is an upper-case letter. An @i[upper-case letter] is a character that is in the range 'A'..'Z' or whose position is in one of the ranges 192..214 or 216.. 222. @Defn2{term=[basic letter], sec=[a category of Character]}Is_Basic @\True if Item is a basic letter. A @i[basic letter] is a character that is in one of the ranges 'A'..'Z' and 'a'..'z', or that is one of the following: '@latin1(198)', '@latin1(230)', '@latin1(208)', '@latin1(240)', '@latin1(222)', '@latin1(254)', or '@latin1(223)'. @comment[These characters are at the positions 198 and 230, 208 and 240, 222 and 254, and 223.] @Defn2{term=[decimal digit], sec=[a category of Character]}Is_Digit @\True if Item is a decimal digit. A @i[decimal digit] is a character in the range '0'..'9'. Is_Decimal_Digit @\A renaming of Is_Digit. @Defn2{term=[hexadecimal digit], sec=[a category of Character]}Is_Hexadecimal_Digit @\True if Item is a hexadecimal digit. A @i[hexadecimal digit] is a character that is either a decimal digit or that is in one of the ranges 'A' .. 'F' or 'a' .. 'f'. @Defn2{term=[alphanumeric character], sec=[a category of Character]}Is_Alphanumeric @\True if Item is an alphanumeric character. An @i[alphanumeric character] is a character that is either a letter or a decimal digit. @Defn2{term=[special graphic character], sec=[a category of Character]}Is_Special @\True if Item is a special graphic character. A @i[special graphic character] is a graphic character that is not alphanumeric. @end{description} Each of the names To_Lower, To_Upper, and To_Basic refers to two functions: one that converts from Character to Character, and the other that converts from String to String. The result of each Character-to-Character function is described below, in terms of the conversion applied to Item, its formal Character parameter. The result of each String-to-String conversion is obtained by applying to each element of the function's String parameter the corresponding Character-to-Character conversion; the result is the null String if the value of the formal parameter is the null String. The lower bound of the result String is 1. @begin{description} To_Lower@\Returns the corresponding lower-case value for Item if Is_Upper(Item), and returns Item otherwise. To_Upper@\Returns the corresponding upper-case value for Item if Is_Lower(Item) and Item has an upper-case form, and returns Item otherwise. The lower case letters '@latin1(223)' and '@latin1(255)' @comment{These are at positions 223 and 255} do not have upper case forms. To_Basic@\Returns the letter corresponding to Item but with no diacritical mark, if Item is a letter but not a basic letter; returns Item otherwise. @end{Description} The following set of functions test for membership in the ISO 646 character range, or convert between ISO 646 and Character. @begin{description} Is_ISO_646@\The function whose formal parameter, Item, is of type Character returns True if Item is in the subtype ISO_646. Is_ISO_646@\The function whose formal parameter, Item, is of type String returns True if Is_ISO_646(Item(I)) is True for each I in Item'Range. To_ISO_646@\The function whose first formal parameter, Item, is of type Character returns Item if Is_ISO_646(Item), and returns the Substitute ISO_646 character otherwise. To_ISO_646@\The function whose first formal parameter, Item, is of type String returns the String whose Range is 1..Item'Length and each of whose elements is given by To_ISO_646 of the corresponding element in Item. @end{description} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@roman{@Shrink{@i<Paragraphs 42 through 48 were deleted.>}}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[The following set of functions test Wide_Character values for membership in Character, or convert between corresponding characters of Wide_Character and Character.]} @begin{description} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Is_Character@\Returns True if Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Is_String@\Returns True if Is_Character(Item(I)) is True for each I in Item'Range.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Character@\Returns the Character corresponding to Item if Is_Character(Item), and returns the Substitute Character otherwise.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_String@\Returns the String whose range is 1..Item'Length and each of whose elements is given by To_Character of the corresponding element in Item.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Wide_Character@\Returns the Wide_Character X such that Character'Pos(Item) = Wide_Character'Pos(X).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Wide_String@\Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item.]} @end{description} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[If an implementation provides a localized definition of Character or Wide_Character, then the effects of the subprograms in Characters.Handling should reflect the localizations. See also @RefSecNum(Character Types).]} @ChgNote{No @ChgImplAdvice here, because we'd have to insert and delete the item in the same version.} @end{ImplAdvice} @begin{Notes} A basic letter is a letter without a diacritical mark. @Leading@;Except for the hexadecimal digits, basic letters, and ISO_646 characters, the categories identified in the classification functions form a strict hierarchy: @begin{Display} @TabClear{}@Comment{We use "Leading" below to make this list closely packed} @TabSet{4, 8, 12, 16} @Leading@em Control characters @Leading@em Graphic characters @Leading@\@em Alphanumeric characters @Leading@\@\@em Letters @Leading@\@\@\@em Upper-case letters @Leading@\@\@\@em Lower-case letters @Leading@\@\@em Decimal digits @Leading@\@em Special graphic characters @end{Display} @begin{Ramification} Thus each Character value is either a control character or a graphic character but not both; each graphic character is either an alphanumeric or special graphic but not both; each alphanumeric is either a letter or decimal digit but not both; each letter is either upper case or lower case but not both.@end{ramification} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Characters.Handling is now Pure, so it can be used in pure units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The conversion functions are made obsolescent; a more complete set is available in Characters.Conversions @em see @RefSecNum{The Package Characters.Conversions}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We no longer talk about localized character sets; these are a non-standard mode, which is none of our business.]} @end{DiffWord95} @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledSubClause{The Package Characters.Latin_1} @begin{Intro} The package Characters.Latin_1 declares constants for characters in ISO 8859-1. @begin{reason} The constants for the ISO 646 characters could have been declared as renamings of objects declared in package ASCII, as opposed to explicit constants. The main reason for explicit constants was for consistency of style with the upper-half constants, and to avoid emphasizing the package ASCII.@end{reason} @end{Intro} @begin{StaticSem} @leading@keepnext@;The library package Characters.Latin_1 has the following declaration: @begin{Example} @key[package] Ada.Characters.Latin_1 @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Latin_1]} @key[pragma] Pure(Latin_1); @keepnext--@RI{ Control characters:}@PDefn2{term=[control character], sec=[a category of Character]} @AdaObjDefn{NUL} : @key[constant] Character := Character'Val(0); @AdaObjDefn{SOH} : @key[constant] Character := Character'Val(1); @AdaObjDefn{STX} : @key[constant] Character := Character'Val(2); @AdaObjDefn{ETX} : @key[constant] Character := Character'Val(3); @AdaObjDefn{EOT} : @key[constant] Character := Character'Val(4); @AdaObjDefn{ENQ} : @key[constant] Character := Character'Val(5); @AdaObjDefn{ACK} : @key[constant] Character := Character'Val(6); @AdaObjDefn{BEL} : @key[constant] Character := Character'Val(7); @AdaObjDefn{BS} : @key[constant] Character := Character'Val(8); @AdaObjDefn{HT} : @key[constant] Character := Character'Val(9); @AdaObjDefn{LF} : @key[constant] Character := Character'Val(10); @AdaObjDefn{VT} : @key[constant] Character := Character'Val(11); @AdaObjDefn{FF} : @key[constant] Character := Character'Val(12); @AdaObjDefn{CR} : @key[constant] Character := Character'Val(13); @AdaObjDefn{SO} : @key[constant] Character := Character'Val(14); @AdaObjDefn{SI} : @key[constant] Character := Character'Val(15); @AdaObjDefn{DLE} : @key[constant] Character := Character'Val(16); @AdaObjDefn{DC1} : @key[constant] Character := Character'Val(17); @AdaObjDefn{DC2} : @key[constant] Character := Character'Val(18); @AdaObjDefn{DC3} : @key[constant] Character := Character'Val(19); @AdaObjDefn{DC4} : @key[constant] Character := Character'Val(20); @AdaObjDefn{NAK} : @key[constant] Character := Character'Val(21); @AdaObjDefn{SYN} : @key[constant] Character := Character'Val(22); @AdaObjDefn{ETB} : @key[constant] Character := Character'Val(23); @AdaObjDefn{CAN} : @key[constant] Character := Character'Val(24); @AdaObjDefn{EM} : @key[constant] Character := Character'Val(25); @AdaObjDefn{SUB} : @key[constant] Character := Character'Val(26); @AdaObjDefn{ESC} : @key[constant] Character := Character'Val(27); @AdaObjDefn{FS} : @key[constant] Character := Character'Val(28); @AdaObjDefn{GS} : @key[constant] Character := Character'Val(29); @AdaObjDefn{RS} : @key[constant] Character := Character'Val(30); @AdaObjDefn{US} : @key[constant] Character := Character'Val(31); @keepnext--@RI{ ISO 646 graphic characters:} @AdaObjDefn{Space} : @key[constant] Character := ' '; --@RI{ Character'Val(32)} @AdaObjDefn{Exclamation} : @key[constant] Character := '!'; --@RI{ Character'Val(33)} @AdaObjDefn{Quotation} : @key[constant] Character := '"'; --@RI{ Character'Val(34)} @AdaObjDefn{Number_Sign} : @key[constant] Character := '#'; --@RI{ Character'Val(35)} @AdaObjDefn{Dollar_Sign} : @key[constant] Character := '$'; --@RI{ Character'Val(36)} @AdaObjDefn{Percent_Sign} : @key[constant] Character := '%'; --@RI{ Character'Val(37)} @AdaObjDefn{Ampersand} : @key[constant] Character := '&'; --@RI{ Character'Val(38)} @AdaObjDefn{Apostrophe} : @key[constant] Character := '''; --@RI{ Character'Val(39)} @AdaObjDefn{Left_Parenthesis} : @key[constant] Character := '('; --@RI{ Character'Val(40)} @AdaObjDefn{Right_Parenthesis} : @key[constant] Character := ')'; --@RI{ Character'Val(41)} @AdaObjDefn{Asterisk} : @key[constant] Character := '*'; --@RI{ Character'Val(42)} @AdaObjDefn{Plus_Sign} : @key[constant] Character := '+'; --@RI{ Character'Val(43)} @AdaObjDefn{Comma} : @key[constant] Character := ','; --@RI{ Character'Val(44)} @AdaObjDefn{Hyphen} : @key[constant] Character := '-'; --@RI{ Character'Val(45)} @AdaObjDefn{Minus_Sign} : Character @key[renames] Hyphen; @AdaObjDefn{Full_Stop} : @key[constant] Character := '.'; --@RI{ Character'Val(46)} @AdaObjDefn{Solidus} : @key[constant] Character := '/'; --@RI{ Character'Val(47)} @keepnext --@RI{ Decimal digits '0' though '9' are at positions 48 through 57} @AdaObjDefn{Colon} : @key[constant] Character := ':'; --@RI{ Character'Val(58)} @AdaObjDefn{Semicolon} : @key[constant] Character := ';'; --@RI{ Character'Val(59)} @AdaObjDefn{Less_Than_Sign} : @key[constant] Character := '<'; --@RI{ Character'Val(60)} @AdaObjDefn{Equals_Sign} : @key[constant] Character := '='; --@RI{ Character'Val(61)} @AdaObjDefn{Greater_Than_Sign} : @key[constant] Character := '>'; --@RI{ Character'Val(62)} @AdaObjDefn{Question} : @key[constant] Character := '?'; --@RI{ Character'Val(63)} @AdaObjDefn{Commercial_At} : @key[constant] Character := '@@'; --@RI{ Character'Val(64)} @keepnext --@RI{ Letters 'A' through 'Z' are at positions 65 through 90} @AdaObjDefn{Left_Square_Bracket} : @key[constant] Character := '['; --@RI{ Character'Val(91)} @AdaObjDefn{Reverse_Solidus} : @key[constant] Character := '\'; --@RI{ Character'Val(92)} @AdaObjDefn{Right_Square_Bracket} : @key[constant] Character := ']'; --@RI{ Character'Val(93)} @AdaObjDefn{Circumflex} : @key[constant] Character := '^'; --@RI{ Character'Val(94)} @AdaObjDefn{Low_Line} : @key[constant] Character := '_'; --@RI{ Character'Val(95)} @AdaObjDefn{Grave} : @key[constant] Character := '`'; --@RI{ Character'Val(96)} @AdaObjDefn{LC_A} : @key[constant] Character := 'a'; --@RI{ Character'Val(97)} @AdaObjDefn{LC_B} : @key[constant] Character := 'b'; --@RI{ Character'Val(98)} @AdaObjDefn{LC_C} : @key[constant] Character := 'c'; --@RI{ Character'Val(99)} @AdaObjDefn{LC_D} : @key[constant] Character := 'd'; --@RI{ Character'Val(100)} @AdaObjDefn{LC_E} : @key[constant] Character := 'e'; --@RI{ Character'Val(101)} @AdaObjDefn{LC_F} : @key[constant] Character := 'f'; --@RI{ Character'Val(102)} @AdaObjDefn{LC_G} : @key[constant] Character := 'g'; --@RI{ Character'Val(103)} @AdaObjDefn{LC_H} : @key[constant] Character := 'h'; --@RI{ Character'Val(104)} @AdaObjDefn{LC_I} : @key[constant] Character := 'i'; --@RI{ Character'Val(105)} @AdaObjDefn{LC_J} : @key[constant] Character := 'j'; --@RI{ Character'Val(106)} @AdaObjDefn{LC_K} : @key[constant] Character := 'k'; --@RI{ Character'Val(107)} @AdaObjDefn{LC_L} : @key[constant] Character := 'l'; --@RI{ Character'Val(108)} @AdaObjDefn{LC_M} : @key[constant] Character := 'm'; --@RI{ Character'Val(109)} @AdaObjDefn{LC_N} : @key[constant] Character := 'n'; --@RI{ Character'Val(110)} @AdaObjDefn{LC_O} : @key[constant] Character := 'o'; --@RI{ Character'Val(111)} @AdaObjDefn{LC_P} : @key[constant] Character := 'p'; --@RI{ Character'Val(112)} @AdaObjDefn{LC_Q} : @key[constant] Character := 'q'; --@RI{ Character'Val(113)} @AdaObjDefn{LC_R} : @key[constant] Character := 'r'; --@RI{ Character'Val(114)} @AdaObjDefn{LC_S} : @key[constant] Character := 's'; --@RI{ Character'Val(115)} @AdaObjDefn{LC_T} : @key[constant] Character := 't'; --@RI{ Character'Val(116)} @AdaObjDefn{LC_U} : @key[constant] Character := 'u'; --@RI{ Character'Val(117)} @AdaObjDefn{LC_V} : @key[constant] Character := 'v'; --@RI{ Character'Val(118)} @AdaObjDefn{LC_W} : @key[constant] Character := 'w'; --@RI{ Character'Val(119)} @AdaObjDefn{LC_X} : @key[constant] Character := 'x'; --@RI{ Character'Val(120)} @AdaObjDefn{LC_Y} : @key[constant] Character := 'y'; --@RI{ Character'Val(121)} @AdaObjDefn{LC_Z} : @key[constant] Character := 'z'; --@RI{ Character'Val(122)} @AdaObjDefn{Left_Curly_Bracket} : @key[constant] Character := '{'; --@RI{ Character'Val(123)} @AdaObjDefn{Vertical_Line} : @key[constant] Character := '|'; --@RI{ Character'Val(124)} @AdaObjDefn{Right_Curly_Bracket} : @key[constant] Character := '}'; --@RI{ Character'Val(125)} @AdaObjDefn{Tilde} : @key[constant] Character := '~'; --@RI{ Character'Val(126)} @AdaObjDefn{DEL} : @key[constant] Character := Character'Val(127); @keepnext--@RI{ ISO 6429 control characters:}@PDefn2{term=[control character], sec=[a category of Character]} @AdaObjDefn{IS4} : Character @key[renames] FS; @AdaObjDefn{IS3} : Character @key[renames] GS; @AdaObjDefn{IS2} : Character @key[renames] RS; @AdaObjDefn{IS1} : Character @key[renames] US; @AdaObjDefn{Reserved_128} : @key[constant] Character := Character'Val(128); @AdaObjDefn{Reserved_129} : @key[constant] Character := Character'Val(129); @AdaObjDefn{BPH} : @key[constant] Character := Character'Val(130); @AdaObjDefn{NBH} : @key[constant] Character := Character'Val(131); @AdaObjDefn{Reserved_132} : @key[constant] Character := Character'Val(132); @AdaObjDefn{NEL} : @key[constant] Character := Character'Val(133); @AdaObjDefn{SSA} : @key[constant] Character := Character'Val(134); @AdaObjDefn{ESA} : @key[constant] Character := Character'Val(135); @AdaObjDefn{HTS} : @key[constant] Character := Character'Val(136); @AdaObjDefn{HTJ} : @key[constant] Character := Character'Val(137); @AdaObjDefn{VTS} : @key[constant] Character := Character'Val(138); @AdaObjDefn{PLD} : @key[constant] Character := Character'Val(139); @AdaObjDefn{PLU} : @key[constant] Character := Character'Val(140); @AdaObjDefn{RI} : @key[constant] Character := Character'Val(141); @AdaObjDefn{SS2} : @key[constant] Character := Character'Val(142); @AdaObjDefn{SS3} : @key[constant] Character := Character'Val(143); @AdaObjDefn{DCS} : @key[constant] Character := Character'Val(144); @AdaObjDefn{PU1} : @key[constant] Character := Character'Val(145); @AdaObjDefn{PU2} : @key[constant] Character := Character'Val(146); @AdaObjDefn{STS} : @key[constant] Character := Character'Val(147); @AdaObjDefn{CCH} : @key[constant] Character := Character'Val(148); @AdaObjDefn{MW} : @key[constant] Character := Character'Val(149); @AdaObjDefn{SPA} : @key[constant] Character := Character'Val(150); @AdaObjDefn{EPA} : @key[constant] Character := Character'Val(151); @AdaObjDefn{SOS} : @key[constant] Character := Character'Val(152); @AdaObjDefn{Reserved_153} : @key[constant] Character := Character'Val(153); @AdaObjDefn{SCI} : @key[constant] Character := Character'Val(154); @AdaObjDefn{CSI} : @key[constant] Character := Character'Val(155); @AdaObjDefn{ST} : @key[constant] Character := Character'Val(156); @AdaObjDefn{OSC} : @key[constant] Character := Character'Val(157); @AdaObjDefn{PM} : @key[constant] Character := Character'Val(158); @AdaObjDefn{APC} : @key[constant] Character := Character'Val(159); @keepnext--@RI{ Other graphic characters:} --@RI{ Character positions 160 (16#A0#) .. 175 (16#AF#):} @AdaObjDefn{No_Break_Space} : @key[constant] Character := ' '; --@RI{Character'Val(160)} @AdaObjDefn{NBSP} : Character @key[renames] No_Break_Space; @AdaObjDefn{Inverted_Exclamation} : @key[constant] Character := '@latin1(161)'; --@RI{Character'Val(161)} @AdaObjDefn{Cent_Sign} : @key[constant] Character := '@latin1(162)'; --@RI{Character'Val(162)} @AdaObjDefn{Pound_Sign} : @key[constant] Character := '@latin1(163)'; --@RI{Character'Val(163)} @AdaObjDefn{Currency_Sign} : @key[constant] Character := '@latin1(164)'; --@RI{Character'Val(164)} @AdaObjDefn{Yen_Sign} : @key[constant] Character := '@latin1(165)'; --@RI{Character'Val(165)} @AdaObjDefn{Broken_Bar} : @key[constant] Character := '@latin1(166)'; --@RI{Character'Val(166)} @AdaObjDefn{Section_Sign} : @key[constant] Character := '@latin1(167)'; --@RI{Character'Val(167)} @AdaObjDefn{Diaeresis} : @key[constant] Character := '@latin1(168)'; --@RI{Character'Val(168)} @AdaObjDefn{Copyright_Sign} : @key[constant] Character := '@latin1(169)'; --@RI{Character'Val(169)} @AdaObjDefn{Feminine_Ordinal_Indicator} : @key[constant] Character := '@latin1(170)'; --@RI{Character'Val(170)} @AdaObjDefn{Left_Angle_Quotation} : @key[constant] Character := '@latin1(171)'; --@RI{Character'Val(171)} @AdaObjDefn{Not_Sign} : @key[constant] Character := '@latin1(172)'; --@RI{Character'Val(172)} @AdaObjDefn{Soft_Hyphen} : @key[constant] Character := '@latin1(173)'; --@RI{Character'Val(173)} @AdaObjDefn{Registered_Trade_Mark_Sign} : @key[constant] Character := '@latin1(174)'; --@RI{Character'Val(174)} @AdaObjDefn{Macron} : @key[constant] Character := '@latin1(175)'; --@RI{Character'Val(175)} --@RI{ Character positions 176 (16#B0#) .. 191 (16#BF#):} @AdaObjDefn{Degree_Sign} : @key[constant] Character := '@latin1(176)'; --@RI{Character'Val(176)} @AdaObjDefn{Ring_Above} : Character @key[renames] Degree_Sign; @AdaObjDefn{Plus_Minus_Sign} : @key[constant] Character := '@latin1(177)'; --@RI{Character'Val(177)} @AdaObjDefn{Superscript_Two} : @key[constant] Character := '@latin1(178)'; --@RI{Character'Val(178)} @AdaObjDefn{Superscript_Three} : @key[constant] Character := '@latin1(179)'; --@RI{Character'Val(179)} @AdaObjDefn{Acute} : @key[constant] Character := '@latin1(180)'; --@RI{Character'Val(180)} @AdaObjDefn{Micro_Sign} : @key[constant] Character := '@latin1(181)'; --@RI{Character'Val(181)} @AdaObjDefn{Pilcrow_Sign} : @key[constant] Character := '@latin1(182)'; --@RI{Character'Val(182)} @AdaObjDefn{Paragraph_Sign} : Character @key[renames] Pilcrow_Sign; @AdaObjDefn{Middle_Dot} : @key[constant] Character := '@latin1(183)'; --@RI{Character'Val(183)} @AdaObjDefn{Cedilla} : @key[constant] Character := '@latin1(184)'; --@RI{Character'Val(184)} @AdaObjDefn{Superscript_One} : @key[constant] Character := '@latin1(185)'; --@RI{Character'Val(185)} @AdaObjDefn{Masculine_Ordinal_Indicator}: @key[constant] Character := '@latin1(186)'; --@RI{Character'Val(186)} @AdaObjDefn{Right_Angle_Quotation} : @key[constant] Character := '@latin1(187)'; --@RI{Character'Val(187)} @AdaObjDefn{Fraction_One_Quarter} : @key[constant] Character := '@latin1(188)'; --@RI{Character'Val(188)} @AdaObjDefn{Fraction_One_Half} : @key[constant] Character := '@latin1(189)'; --@RI{Character'Val(189)} @AdaObjDefn{Fraction_Three_Quarters} : @key[constant] Character := '@latin1(190)'; --@RI{Character'Val(190)} @AdaObjDefn{Inverted_Question} : @key[constant] Character := '@latin1(191)'; --@RI{Character'Val(191)} --@RI{ Character positions 192 (16#C0#) .. 207 (16#CF#):} @AdaObjDefn{UC_A_Grave} : @key[constant] Character := '@latin1(192)'; --@RI{Character'Val(192)} @AdaObjDefn{UC_A_Acute} : @key[constant] Character := '@latin1(193)'; --@RI{Character'Val(193)} @AdaObjDefn{UC_A_Circumflex} : @key[constant] Character := '@latin1(194)'; --@RI{Character'Val(194)} @AdaObjDefn{UC_A_Tilde} : @key[constant] Character := '@latin1(195)'; --@RI{Character'Val(195)} @AdaObjDefn{UC_A_Diaeresis} : @key[constant] Character := '@latin1(196)'; --@RI{Character'Val(196)} @AdaObjDefn{UC_A_Ring} : @key[constant] Character := '@latin1(197)'; --@RI{Character'Val(197)} @AdaObjDefn{UC_AE_Diphthong} : @key[constant] Character := '@latin1(198)'; --@RI{Character'Val(198)} @AdaObjDefn{UC_C_Cedilla} : @key[constant] Character := '@latin1(199)'; --@RI{Character'Val(199)} @AdaObjDefn{UC_E_Grave} : @key[constant] Character := '@latin1(200)'; --@RI{Character'Val(200)} @AdaObjDefn{UC_E_Acute} : @key[constant] Character := '@latin1(201)'; --@RI{Character'Val(201)} @AdaObjDefn{UC_E_Circumflex} : @key[constant] Character := '@latin1(202)'; --@RI{Character'Val(202)} @AdaObjDefn{UC_E_Diaeresis} : @key[constant] Character := '@latin1(203)'; --@RI{Character'Val(203)} @AdaObjDefn{UC_I_Grave} : @key[constant] Character := '@latin1(204)'; --@RI{Character'Val(204)} @AdaObjDefn{UC_I_Acute} : @key[constant] Character := '@latin1(205)'; --@RI{Character'Val(205)} @AdaObjDefn{UC_I_Circumflex} : @key[constant] Character := '@latin1(206)'; --@RI{Character'Val(206)} @AdaObjDefn{UC_I_Diaeresis} : @key[constant] Character := '@latin1(207)'; --@RI{Character'Val(207)} --@RI{ Character positions 208 (16#D0#) .. 223 (16#DF#):} @AdaObjDefn{UC_Icelandic_Eth} : @key[constant] Character := '@latin1(208)'; --@RI{Character'Val(208)} @AdaObjDefn{UC_N_Tilde} : @key[constant] Character := '@latin1(209)'; --@RI{Character'Val(209)} @AdaObjDefn{UC_O_Grave} : @key[constant] Character := '@latin1(210)'; --@RI{Character'Val(210)} @AdaObjDefn{UC_O_Acute} : @key[constant] Character := '@latin1(211)'; --@RI{Character'Val(211)} @AdaObjDefn{UC_O_Circumflex} : @key[constant] Character := '@latin1(212)'; --@RI{Character'Val(212)} @AdaObjDefn{UC_O_Tilde} : @key[constant] Character := '@latin1(213)'; --@RI{Character'Val(213)} @AdaObjDefn{UC_O_Diaeresis} : @key[constant] Character := '@latin1(214)'; --@RI{Character'Val(214)} @AdaObjDefn{Multiplication_Sign} : @key[constant] Character := '@latin1(215)'; --@RI{Character'Val(215)} @AdaObjDefn{UC_O_Oblique_Stroke} : @key[constant] Character := '@latin1(216)'; --@RI{Character'Val(216)} @AdaObjDefn{UC_U_Grave} : @key[constant] Character := '@latin1(217)'; --@RI{Character'Val(217)} @AdaObjDefn{UC_U_Acute} : @key[constant] Character := '@latin1(218)'; --@RI{Character'Val(218)} @AdaObjDefn{UC_U_Circumflex} : @key[constant] Character := '@latin1(219)'; --@RI{Character'Val(219)} @AdaObjDefn{UC_U_Diaeresis} : @key[constant] Character := '@latin1(220)'; --@RI{Character'Val(220)} @AdaObjDefn{UC_Y_Acute} : @key[constant] Character := '@latin1(221)'; --@RI{Character'Val(221)} @AdaObjDefn{UC_Icelandic_Thorn} : @key[constant] Character := '@latin1(222)'; --@RI{Character'Val(222)} @AdaObjDefn{LC_German_Sharp_S} : @key[constant] Character := '@latin1(223)'; --@RI{Character'Val(223)} --@RI{ Character positions 224 (16#E0#) .. 239 (16#EF#):} @AdaObjDefn{LC_A_Grave} : @key[constant] Character := '@latin1(224)'; --@RI{Character'Val(224)} @AdaObjDefn{LC_A_Acute} : @key[constant] Character := '@latin1(225)'; --@RI{Character'Val(225)} @AdaObjDefn{LC_A_Circumflex} : @key[constant] Character := '@latin1(226)'; --@RI{Character'Val(226)} @AdaObjDefn{LC_A_Tilde} : @key[constant] Character := '@latin1(227)'; --@RI{Character'Val(227)} @AdaObjDefn{LC_A_Diaeresis} : @key[constant] Character := '@latin1(228)'; --@RI{Character'Val(228)} @AdaObjDefn{LC_A_Ring} : @key[constant] Character := '@latin1(229)'; --@RI{Character'Val(229)} @AdaObjDefn{LC_AE_Diphthong} : @key[constant] Character := '@latin1(230)'; --@RI{Character'Val(230)} @AdaObjDefn{LC_C_Cedilla} : @key[constant] Character := '@latin1(231)'; --@RI{Character'Val(231)} @AdaObjDefn{LC_E_Grave} : @key[constant] Character := '@latin1(232)'; --@RI{Character'Val(232)} @AdaObjDefn{LC_E_Acute} : @key[constant] Character := '@latin1(233)'; --@RI{Character'Val(233)} @AdaObjDefn{LC_E_Circumflex} : @key[constant] Character := '@latin1(234)'; --@RI{Character'Val(234)} @AdaObjDefn{LC_E_Diaeresis} : @key[constant] Character := '@latin1(235)'; --@RI{Character'Val(235)} @AdaObjDefn{LC_I_Grave} : @key[constant] Character := '@latin1(236)'; --@RI{Character'Val(236)} @AdaObjDefn{LC_I_Acute} : @key[constant] Character := '@latin1(237)'; --@RI{Character'Val(237)} @AdaObjDefn{LC_I_Circumflex} : @key[constant] Character := '@latin1(238)'; --@RI{Character'Val(238)} @AdaObjDefn{LC_I_Diaeresis} : @key[constant] Character := '@latin1(239)'; --@RI{Character'Val(239)} --@RI{ Character positions 240 (16#F0#) .. 255 (16#FF#):} @AdaObjDefn{LC_Icelandic_Eth} : @key[constant] Character := '@latin1(240)'; --@RI{Character'Val(240)} @AdaObjDefn{LC_N_Tilde} : @key[constant] Character := '@latin1(241)'; --@RI{Character'Val(241)} @AdaObjDefn{LC_O_Grave} : @key[constant] Character := '@latin1(242)'; --@RI{Character'Val(242)} @AdaObjDefn{LC_O_Acute} : @key[constant] Character := '@latin1(243)'; --@RI{Character'Val(243)} @AdaObjDefn{LC_O_Circumflex} : @key[constant] Character := '@latin1(244)'; --@RI{Character'Val(244)} @AdaObjDefn{LC_O_Tilde} : @key[constant] Character := '@latin1(245)'; --@RI{Character'Val(245)} @AdaObjDefn{LC_O_Diaeresis} : @key[constant] Character := '@latin1(246)'; --@RI{Character'Val(246)} @AdaObjDefn{Division_Sign} : @key[constant] Character := '@latin1(247)'; --@RI{Character'Val(247)} @AdaObjDefn{LC_O_Oblique_Stroke} : @key[constant] Character := '@latin1(248)'; --@RI{Character'Val(248)} @AdaObjDefn{LC_U_Grave} : @key[constant] Character := '@latin1(249)'; --@RI{Character'Val(249)} @AdaObjDefn{LC_U_Acute} : @key[constant] Character := '@latin1(250)'; --@RI{Character'Val(250)} @AdaObjDefn{LC_U_Circumflex} : @key[constant] Character := '@latin1(251)'; --@RI{Character'Val(251)} @AdaObjDefn{LC_U_Diaeresis} : @key[constant] Character := '@latin1(252)'; --@RI{Character'Val(252)} @AdaObjDefn{LC_Y_Acute} : @key[constant] Character := '@latin1(253)'; --@RI{Character'Val(253)} @AdaObjDefn{LC_Icelandic_Thorn} : @key[constant] Character := '@latin1(254)'; --@RI{Character'Val(254)} @AdaObjDefn{LC_Y_Diaeresis} : @key[constant] Character := '@latin1(255)'; --@RI{Character'Val(255)} @key[end] Ada.Characters.Latin_1; @end{Example} @end{StaticSem} @begin{ImplPerm} An implementation may provide additional packages as children of Ada.Characters, to declare names for the symbols of the local character set or other character sets. @end{ImplPerm} @RMNewPage@LabeledAddedSubClause{Version=[2],Name=[The Package Characters.Conversions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Characters.Conversions has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[package] Ada.Characters.Conversions @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Conversions]} @key[pragma] Pure(Conversions);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_String) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_Wide_String) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Wide_Character} (Item : @key[in] Wide_Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Wide_String} (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Character; @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] String) @key[return] Wide_String; @key[function] @AdaSubDefn{To_Wide_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Wide_Character; @key[function] @AdaSubDefn{To_Wide_Wide_String} (Item : @key[in] String) @key[return] Wide_Wide_String; @key[function] @AdaSubDefn{To_Wide_Wide_Character} (Item : @key[in] Wide_Character) @key[return] Wide_Wide_Character; @key[function] @AdaSubDefn{To_Wide_Wide_String} (Item : @key[in] Wide_String) @key[return] Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_Character; @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[end] Ada.Characters.Conversions;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The functions in package Characters.Conversions test Wide_Wide_Character or Wide_Character values for membership in Wide_Character or Character, or convert between corresponding characters of Wide_Wide_Character, Wide_Character, and Character.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Character (Item : @key[in] Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Character (Item : @key[in] Wide_Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Wide_Character (Item : @key[in] Wide_Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Wide_Character'Pos(Item) <= Wide_Character'Pos(Wide_Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_String (Item : @key[in] Wide_String) @key[return] Boolean; @key[function] Is_String (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Is_Character(Item(I)) is True for each I in Item'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Wide_String (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Is_Wide_Character(Item(I)) is True for each I in Item'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Character (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] To_Character (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Character corresponding to Item if Is_Character(Item), and returns the Substitute Character otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Character (Item : @key[in] Character) @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Character X such that Character'Pos(Item) = Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Character (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Character corresponding to Item if Is_Wide_Character(Item), and returns the Substitute Wide_Character otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Wide_Character (Item : @key[in] Character) @key[return] Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_Character X such that Character'Pos(Item) = Wide_Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Wide_Character (Item : @key[in] Wide_Character) @key[return] Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_Character X such that Wide_Character'Pos(Item) = Wide_Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_String (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] To_String (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Character := ' ') @key[return] String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the String whose range is 1..Item'Length and each of whose elements is given by To_Character of the corresponding element in Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_String (Item : @key[in] String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_String (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item with the given Substitute Wide_Character.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key[function] To_Wide_Wide_String (Item : @key[in] String) @key[return] Wide_Wide_String; @key[function] To_Wide_Wide_String (Item : @key[in] Wide_String) @key[return] Wide_Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Wide_Character of the corresponding element in Item.]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Characters.Conversions is new, replacing functions previously found in Characters.Handling.]} @end{Extend95} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_cmdln.mss��������������������������������������������������������0000755�0001752�0001001�00000011360�12273462240�020111� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_cmdln.mss,v $ } @comment{ $Revision: 1.24 $ $Date: 2005/10/31 17:34:29 $ $Author: Randy $ } @Part(predefcmdln, Root="ada.mss") @Comment{$Date: 2005/10/31 17:34:29 $} @LabeledClause{The Package Command_Line} @begin{Intro} The package Command_Line allows a program to obtain the values of its arguments and to set the exit status code to be returned on normal termination. @ChgImplDef{Version=[2],Kind=[Revised],Text=[The meaning of Argument_Count, Argument, and Command_Name@Chg{Version=[2],New=[ for package Command_Line. The bounds of type Command_Line.Exit_Status],Old=[]}.]} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Ada.Command_Line has the following declaration: @begin{Example} @key[package] Ada.Command_Line @key[is]@ChildUnit{Parent=[Ada],Child=[Command_Line]} @key[pragma] Preelaborate(Command_Line); @key[function] @AdaSubDefn{Argument_Count} @key[return] Natural; @key[function] @AdaSubDefn{Argument} (Number : @key[in] Positive) @key[return] String; @key[function] @AdaSubDefn{Command_Name} @key[return] String; @key[type] @AdaTypeDefn{Exit_Status} @key[is] @RI{implementation-defined integer type}; @AdaObjDefn{Success} : @key[constant] Exit_Status; @AdaObjDefn{Failure} : @key[constant] Exit_Status; @key[procedure] @AdaSubDefn{Set_Exit_Status} (Code : @key[in] Exit_Status); @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Command_Line; @comment{Blank line} @end{example} @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Argument_Count @key[return] Natural; @end{Example} @Trailing@;If the external execution environment supports passing arguments to a program, then Argument_Count returns the number of arguments passed to the program invoking the function. Otherwise it returns 0. The meaning of @lquotes@;number of arguments@rquotes@; is implementation defined. @begin{Example}@Keepnext @key[function] Argument (Number : @key[in] Positive) @key[return] String; @end{Example} @Trailing@;If the external execution environment supports passing arguments to a program, then Argument returns an implementation-defined value corresponding to the argument at relative position Number. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Number is outside the range 1..Argument_Count, then Constraint_Error is propagated. @begin{Ramification} If the external execution environment does not support passing arguments to a program, then Argument(N) for any N will raise Constraint_Error, since Argument_Count is 0.@end{ramification} @begin{Example}@Keepnext @key[function] Command_Name @key[return] String; @end{Example} @Trailing@;If the external execution environment supports passing arguments to a program, then Command_Name returns an implementation-defined value corresponding to the name of the command invoking the program; otherwise Command_Name returns the null string. @Comment{This is missing; leading the following paragraph glued to "Command_Name"} @begin{Example}@Keepnext @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[type] Exit_Status @key[is] @RI{implementation-defined integer type};],Old=[]} @end{Example} @Trailing@; The type Exit_Status represents the range of exit status values supported by the external execution environment. The constants Success and Failure correspond to success and failure, respectively. @begin{Example}@Keepnext @key[procedure] Set_Exit_Status (Code : @key[in] Exit_Status); @end{Example} If the external execution environment supports returning an exit status from a program, then Set_Exit_Status sets Code as the status. Normal termination of a program returns as the exit status the value most recently set by Set_Exit_Status, or, if no such value has been set, then the value Success. If a program terminates abnormally, the status set by Set_Exit_Status is ignored, and an implementation-defined exit status value is set. @ChgNote{An incorrect index entry; presentation AI-00005} @Chg{New=[],Old=[@PDefn{unspecified}]} If the external execution environment does not support returning an exit value from a program, then Set_Exit_Status does nothing. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} An alternative declaration is allowed for package Command_Line if different functionality is appropriate for the external execution environment. @end{ImplPerm} @begin{Notes} Argument_Count, Argument, and Command_Name correspond to the C language's argc, argv[n] (for n>0) and argv[0], respectively. @begin{Honest} The correspondence of Argument_Count to argc is not direct @em argc would be one more than Argument_Count, since the argc count includes the command name, whereas Argument_Count does not. @end{Honest} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} This clause is new in Ada 95. @end{Extend83}��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_containers.mss���������������������������������������������������0000755�0001752�0001001�00001232625�12273462240�021173� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� @comment{ $Source: e:\\cvsroot/ARM/Source/pre_containers.mss,v $ } @comment{ $Revision: 1.59 $ $Date: 2006/10/19 20:44:19 $ $Author: Randy $ } @Part(precontainers, Root="ada.mss") @Comment{$Date: 2006/10/19 20:44:19 $} @RMNewPage @LabeledAddedClause{Version=[2],Name=[Containers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This clause presents the specifications of the package Containers and several child packages, which provide facilities for storing collections of elements.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A variety of sequence and associative containers are provided. Each container includes a @i{cursor} type. A cursor is a reference to an element within a container. Many operations on cursors are common to all of the containers. A cursor referencing an element in a container is considered to be overlapping with the container object itself.@PDefn2{Term=[cursor],Sec=[for a container]} @Defn2{Term=[container],Sec=[cursor]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The last sentence is intended to clarify that operations that just use a cursor are on the same footing as operations that use a container in terms of the reentrancy rules of Annex A.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Within this clause we provide Implementation Advice for the desired average or worst case time complexity of certain operations on a container. This advice is expressed using the Landau symbol @i{O}(X). Presuming f is some function of a length parameter N and t(N) is the time the operation takes (on average or worst case, as specified) for the length N, a complexity of @i{O}(f(N)) means that there exists a finite A such that for any N, t(N)/f(N) < A. @Defn{Landau symbol @i{O}(X)}@Defn{@i{O}(f(N))}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Of course, an implementation can do better than a specified @i{O}(f(N)): for example, @i{O}(1) meets the requirements for @i{O}(log N).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This concept seems to have as many names as there are authors. We used @lquotes@;Landau symbol@rquotes because that's what our reference does. But we'd also seen this referred as big-O notation@Defn{big-O notation} (sometimes written as @i<big-oh>), and as Bachmann notation. Whatever the name, it always has the above definition.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the advice suggests that the complexity should be less than @i{O}(f(N)), then for any arbitrarily small positive real D, there should exist a positive integer M such that for all N > M, t(N)/f(N) < D.]} @end{Intro} @begin{Metarules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This clause provides a number of useful containers for Ada. Only the most useful containers are provided. Ones that are relatively easy to code, redundant, or rarely used are omitted from this set, even if they are generally included in containers libraries.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The containers packages are modeled on the Standard Template Library (STL), an algorithms and data structure library popularized by Alexander Stepanov, and included in the C++ standard library. The structure and terminology differ from the STL where that better maps to common Ada usage. For instance, what the STL calls @lquotes@;iterators@rquotes@; are called @lquotes@;cursors@rquotes@; here.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following major nonlimited containers are provided:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[(Expandable) Vectors of any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Doubly-linked Lists of any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Hashed Maps keyed by any nonlimited hashable type, and containing any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Ordered Maps keyed by any nonlimited ordered type, and containing any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Hashed Sets of any nonlimited hashable type; and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Ordered Sets of any nonlimited ordered type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Separate versions for definite and indefinite element types are provided, as those for definite types can be implemented more efficiently.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each container includes a cursor, which is a reference to an element within a container. Cursors generally remain valid as long as the container exists and the element referenced is not deleted. Many operations on cursors are common to all of the containers. This makes it possible to write generic algorithms that work on any kind of container.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The containers packages are structured so that additional packages can be added in the future. Indeed, we hope that these packages provide the basis for a more extensive secondary standard for containers.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If containers with similar functionality (but different performance characteristics) are provided (by the implementation or by a secondary standard), we suggest that a prefix be used to identify the class of the functionality: "Ada.Containers.Bounded_Sets" (for a set with a maximum number of elements); "Ada.Containers.Protected_Maps" (for a map which can be accessed by multiple tasks at one time); "Ada.Containers.Persistent_Vectors" (for a persistent vector which continues to exist between executions of a program) and so on.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Note that the language already includes several requirements that are important to the use of containers. These include:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Library packages must be reentrant @en multiple tasks can use the packages as long as they operate on separate containers. Thus, it is only necessary for a user to protect a container if a single container needs to be used by multiple tasks.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Language-defined types must stream "properly". That means that the stream attributes can be used to implement persistence of containers when necessary, and containers can be passed between partitions of a program.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Equality of language-defined types must compose @lquotes@;properly@rquotes@;. This means that the version of "=" directly used by users is the same one that will be used in generics and in predefined equality operators of types with components of the containers and/or cursors. This prevents the abstraction from breaking unexpectedly.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a container's element type is controlled, the point at which the element is finalized will depend on the implementation of the container. We do not specify precisely where this will happen (it will happen no later than the finalization of the container, of course) in order to give implementation's flexibility to cache, block, or split the nodes of the container. In particular, Delete does not necessarily finalize the element; the implementation may (or may not) hold the space for reuse.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not likely to be a hardship, as the element type has to be nonlimited. Types used to manage scarce resources generally need to be limited. Otherwise, the amount of resources needed is hard to control, as the language allows a lot of variation in the number or order of adjusts/finalizations. For common uses of nonlimited controlled types such as managing storage, the types already have to manage arbitrary copies.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The use of controlled type also brings up the possibility of failure of finalization (and thus deallocation) of an element. This is a @lquotes@;serious bug@rquotes@;, as AI-179 puts it, so we don't try to specify what happens in that case. The implementation should propagate the exception.]} @end{Metarules} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is expected that exceptions propagated from these operations do not damage containers. That is, if Storage_Error is propagated because of an allocation failure, or Constraint_Error is propagated by the assignment of elements, the container can continue to be used without further exceptions. The intent is that it should be possible to recover from errors without losing data. We don't try to state this formally in most cases, because it is hard to define precisely what is and is not allowed behavior.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When this clause says that the behavior of something is unspecified@PDefn{unspecified}, we really mean that any result of executing Ada code short of erroneous execution is allowed. We do not mean that memory not belonging to the parameters of the operation can be trashed. When we mean to allow erroneous behavior, we specifically say that execution is erroneous. All this means if the containers are written in Ada is that checks should not be suppressed or removed assuming some behavior of other code, and that the implementation should take care to avoid creating internal dangling accesses by assuming behavior from generic formals that can't be guaranteed. We don't try to say this normatively because it would be fairly complex, and implementers are unlikely to increase their support costs by fielding implementations that are unstable if given buggy hash functions, et al.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} This clause is new. It just provides an introduction to the following subclauses.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The package Containers is the root of the containers subsystem.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Containers has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Containers @key{is}@ChildUnit{Parent=[Ada],Child=[Containers]} @key{pragma} Pure(Containers);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Hash_Type} @key{is mod} @i<implementation-defined>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Count_Type @key{is range} 0 .. @i<implementation-defined>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Hash_Type represents the range of the result of a hash function. Count_Type represents the (potential or actual) number of elements of a container.]} @ChgImpldef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The value of Containers.Hash_Type'Modulus. The value of Containers.Count_Type'Last.]}]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Hash_Type'Modulus should be at least 2**32. Count_Type'Last should be at least 2**31@en@;1.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Hash_Type'Modulus should be at least 2**32. Containers.Count_Type'Last should be at least 2**31@en@;1.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not a requirement so that these types can be declared properly on machines with native sizes that are not 32 bits. For instance, a 24-bit target could use 2**24 for Hash_Type'Modulus.]} @end{Discussion} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Containers is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Vectors]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Vectors provides private types Vector and Cursor, and a set of operations for each type. A vector container allows insertion and deletion at any position, but it is specifically optimized for insertion and deletion at the high end (the end with the higher index) of the container. A vector container also provides random access to its elements.@Defn{vector container} @Defn2{Term=[container],Sec=[vector]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Pdefn2{Term=[length], Sec=(of a vector container)} @Pdefn2{Term=[capacity], Sec=(of a vector)} A vector container behaves conceptually as an array that expands as necessary as items are inserted. The @i{length} of a vector is the number of elements that the vector contains. The @i{capacity} of a vector is the maximum number of elements that can be inserted into the vector prior to it being automatically expanded.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Elements in a vector container can be referred to by an index value of a generic formal type. The first element of a vector always has its index value equal to the lower bound of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Pdefn2{Term=[empty element], Sec=(of a vector)} A vector container may contain @i{empty elements}. Empty elements do not have a specified value.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Vectors are not intended to be sparse (that is, there are elements at all defined positions). Users are expected to use other containers (like a Map) when they need sparse structures (there is a Note to this effect at the end of this subclause).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The internal array is a conceptual model of a vector. There is no requirement for an implementation to be a single contiguous array.]} @end{Implnote} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Vectors has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Index_Type @key{is range} <>; @key{type} Element_Type @key{is private}; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Vectors @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Vectors]} @key{pragma} Preelaborate(Vectors);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{subtype} @AdaSubtypeDefn{Name=[Extended_Index],Of=[Index_Type'Base]} @key{is} Index_Type'Base @key{range} Index_Type'First-1 .. Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1; @AdaObjDefn{No_Index} : @key{constant} Extended_Index := Extended_Index'First;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Vector} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Vector} : @key{constant} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Vector} (Length : Count_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Vector} (New_Item : Element_Type; Length : Count_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left, Right : Vector) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left : Vector; Right : Element_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left : Element_Type; Right : Vector) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left, Right : Element_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Vector) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Vector; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Vector) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Length} (Container : @key{in out} Vector; Length : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Cursor} (Container : Vector; Index : Extended_Index) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Index} (Position : Cursor) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Vector; Index : Index_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Vector; Index : @key{in} Index_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Vector; Position : @key{in} Cursor; New_item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Container : @key{in} Vector; Index : @key{in} Index_Type; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Vector; Index : @key{in} Index_Type; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Vector; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector; Position : @key{out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert_Space} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert_Space} (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Vector; Index : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Vector; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Elements} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} Vector; I, J : @key{in} Index_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} Vector; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Index} (Container : Vector) @key{return} Index_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Vector) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Vector) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Index} (Container : Vector) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Vector) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Vector) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find_Index} (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'First) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find_Index} (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'Last) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find} (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Vector; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Vector; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Vector; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean is <>; @key{package} @AdaPackDefn{Generic_Sorting} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Sorted} (Container : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Sort} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Merge} (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Sorting;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Vectors;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the functions defined to use it return an unspecified value. The exact arguments and number of calls of this generic formal function by the functions defined to use it are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;functions defined to use it@rquotes are Find, Find_Index, Reverse_Find, Reverse_Find_Index, and "=" for Vectors. This list is a bit too long to give explicitly.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by any of the functions defined to use "=" cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the results of the functions defined to use "=" are unspecified; other subprograms are not allowed to break if "=" is bad.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Vector is used to represent vectors. The type Vector needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Vector represents the empty vector object. It has a length of 0. If an object of type Vector is not otherwise initialized, it is initialized to the same value as Empty_Vector.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Index represents a position that does not correspond to any element. The subtype Extended_Index includes the indices covered by Index_Type plus the value No_Index and, if it exists, the successor to the Index_Type'Last.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require the existence of Index_Type'First @en 1, so that No_Index and Last_Index of an empty vector is well-defined. We don't require the existence of Index_Type'Last + 1, as it is only used as the position of insertions (and needs to be allowed only when inserting an empty vector).]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a vector]} A subprogram is said to @i{tamper with cursors} of a vector object @i<V> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<V>, that is, it calls the Insert, Insert_Space, Clear, Delete, or Set_Length procedures with @i<V> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<V>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<V> as a parameter.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Swap, Sort, and Merge copy elements rather than reordering them, so they don't tamper with cursors.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a vector]} A subprogram is said to @i{tamper with elements} of a vector object @i<V> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<V>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<V>, that is, it calls the Replace_Element, Reverse_Elements, or Swap procedures or the Sort or Merge procedures of an instance of Generic_Sorting with @i<V> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same vector object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, it compares each element in Left to the corresponding element in Right using the generic formal equality operator. If any such comparison returns False, the function returns False; otherwise it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Vector (Length : Count_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector with a length of Length, filled with empty elements.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Vector (New_Item : Element_Type; Length : Count_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector with a length of Length, filled with elements initialized to the value New_Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left, Right : Vector) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the elements of Left followed by the elements of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left : Vector; Right : Element_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the elements of Left followed by the element Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left : Element_Type; Right : Vector) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the element Left followed by the elements of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left, Right : Element_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the element Left followed by the element Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Vector) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Vector; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity allocates new internal data structures such that the length of the resulting vector can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then copies the elements into the new data structures and deallocates the old data structures. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Expanding the internal array can be done by allocating a new, longer array, copying the elements, and deallocating the original array. This may raise Storage_Error, or cause an exception from a controlled subprogram. We require that a failed Reserve_Capacity does not lose any elements if an exception occurs, but we do not require a specific order of evaluations or copying.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine is used to preallocate the internal array to the specified capacity such that future Inserts do not require memory allocation overhead. Therefore, the implementation should allocate the needed memory to make that true at this point, even though the visible semantics could be preserved by waiting until the memory is needed. This doesn't apply to the indefinite element container, because elements will have to be allocated individually.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation does not have to contract the internal array if the capacity is reduced, as any capacity greater than or equal to the specified capacity is allowed.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Vector) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Length (Container : @key{in out} Vector; Length : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length is larger than the capacity of Container, Set_Length calls Reserve_Capacity (Container, Length), then sets the length of the Container to Length. If Length is greater than the original length of Container, empty elements are added to Container; otherwise elements are removed from Container.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[No elements are moved by this operation; any new empty elements are added at the end. This follows from the rules that a cursor continues to designate the same element unless the routine is defined to make the cursor ambiguous or invalid; this operation does not do that.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container. The capacity of Container does not change.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Cursor (Container : Vector; Index : Extended_Index) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then No_Element is returned. Otherwise, a cursor designating the element at position Index in Container is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Index (Position : Cursor) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element, No_Index is returned. Otherwise, the index (within its containing vector) of the element designated by Position is returned.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies that the index is determinable from a bare cursor alone. The basic model is that a vector cursor is implemented as a record containing an access to the vector container and an index value. This does constrain implementations, but it also allows all of the cursor operations to be defined in terms of the corresponding index operation (which should be primary for a vector).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Container : Vector; Index : Index_Type) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Element returns the element at position Index.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Vector; Index : @key{in} Index_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise Replace_Element assigns the value New_Item to the element at position Index. Any exception raised during the assignment is propagated. The element at position Index is not an empty element after successful call to Replace_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Vector; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Replace_Element assigns New_Item to the element designated by Position. Any exception raised during the assignment is propagated. The element at Position is not an empty element after successful call to Replace_Element.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Replace_Element and Update_Element are the only ways that an element can change from empty to non-empty. Also see the note following Update_Element.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Container : @key{in} Vector; Index : @key{in} Index_Type; Process : @key{not null access} @key{procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element at position Index as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with the elements@rquotes@; check is intended to prevent the Element parameter of Process from being modified or deleted outside of Process. The check prevents data loss (if Element_Type is passed by copy) or erroneous execution (if Element_Type is an unconstrained type in an indefinite container).]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access} @key{procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Vector; Index : @key{in} Index_Type; Process : @key{not null access} @key{procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Update_Element calls Process.@key{all} with the element at position Index as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The element at position Index is not an empty element after successful completion of this operation.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since reading an empty element is a bounded error, attempting to use this procedure to replace empty elements may fail. Use Replace_Element to do that reliably.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Vector; Position : @key{in} Cursor; Process : @key{not null access} @key{procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Update_Element calls Process.@key{all} with the element designated by Position as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The element designated by Position is not an empty element after successful completion of this operation.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first calls Clear (Target); then, each element from Source is removed from Source and inserted into Target in the original order. The length of Source is 0 after a successful call to Move.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The idea is that the internal array is removed from Source and moved to Target. (See the @ImplAdviceName for Move). If Capacity (Target) /= 0, the previous internal array may need to be deallocated. We don't mention this explicitly, because it is covered by the "no memory loss" @ImplReqName@;.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Length(New_Item) is 0, then Insert does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Length (New_Item); if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert slides the elements in the range Before .. Last_Index (Container) up by Length(New_Item) positions, and then copies the elements of New_Item to the positions starting at Before. Any exception raised during the copying is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Moving the elements does not necessarily involve copying. Similarly, since Reserve_Capacity does not require the copying of elements, it does not need to be explicitly called (the implementation can combine the operations if it wishes to).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, if Length(New_Item) is 0, then Insert does nothing. If Before is No_Element, then the call is equivalent to Insert (Container, Last_Index (Container) + 1, New_Item); otherwise the call is equivalent to Insert (Container, To_Index (Before), New_Item);]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Before checks that the cursor does not belong to some other Container. This check implies that a reference to the container is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector; Position : @key{out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert (Container, @i<T>, New_Item) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The messy wording is needed because Before is invalidated by Insert, and we don't want Position to be invalid after this call. An implementation probably only needs to copy Before to Position.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count), Position);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, then Insert does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Count; if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert slides the elements in the range Before .. Last_Index (Container) up by Count positions, and then inserts elements that are initialized by default (see @RefSecNum{Object Declarations}) in the positions starting at Before.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert (Container, @i<T>, Count) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine exists mainly to ease conversion between Vector and List containers. Unlike Insert_Space, this routine default initializes the elements it inserts, which can be more expensive for some element types.]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} Vector; New_Item : @key{in} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First_Index (Container), New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First_Index (Container), New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert_Space (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, then Insert_Space does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Count; if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert_Space slides the elements in the range Before .. Last_Index (Container) up by Count positions, and then inserts empty elements in the positions starting at Before.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert_Space (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert_Space (Container, @i<T>, Count) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Vector; Index : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, Delete has no effect. Otherwise Delete slides the elements (if any) starting at position Index + Count down to Index. Any exception raised during element assignment is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Index + Count >= Last_Index(Container), this effectively truncates the vector (setting Last_Index to Index @en 1 and consequently sets Length to Index @en Index_Type'First).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Vector; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete (Container, To_Index (Position), Count) is called, and then Position is set to No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Delete (Container, First_Index (Container), Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) <= Count then Delete_Last is equivalent to Clear (Container). Otherwise it is equivalent to Delete (Container, Index_Type'Val(Index_Type'Pos(Last_Index (Container)) @en Count + 1), Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Elements (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container in reverse order.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This can copy the elements of the vector @em all cursors referencing the vector are ambiguous afterwards and may designate different elements afterwards.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} Vector; I, J : @key{in} Index_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Swap exchanges the values of the elements at positions I and J.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} Vector; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap exchanges the values of the elements designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[After a call to Swap, I designates the element value previously designated by J, and J designates the element value previously designated by I. The cursors do not become ambiguous from this operation.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Index (Container : Vector) @key{return} Index_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the value Index_Type'First.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We'd rather call this @lquotes@;First@rquotes@;, but then calling most routines in here with First (Some_Vect) would be ambiguous.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Vector) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, First returns No_Element. Otherwise, it returns a cursor that designates the first element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Vector) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Container, First_Index (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Index (Container : Vector) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last_Index returns No_Index. Otherwise, it returns the position of the last element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Vector) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last returns No_Element. Otherwise, it returns a cursor that designates the last element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Vector) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Container, Last_Index (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the last element of the container, then Next returns the value No_Element. Otherwise, it returns a cursor that designates the element with index To_Index (Position) + 1 in the same vector as Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the first element of the container, then Previous returns the value No_Element. Otherwise, it returns a cursor that designates the element with index To_Index (Position) @en 1 in the same vector as Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find_Index (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'First) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at position Index and proceeds towards Last_Index (Container). If no equal element is found, then Find_Index returns No_Index. Otherwise, it returns the index of the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the first element if Position equals No_Element, and at the element designated by Position otherwise. It proceeds towards the last element of Container. If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find_Index (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'Last) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at position Index or, if Index is greater than Last_Index (Container), at position Last_Index (Container). It proceeds towards First_Index (Container). If no equal element is found, then Reverse_Find_Index returns No_Index. Otherwise, it returns the index of the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise Reverse_Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the last element if Position equals No_Element, and at the element designated by Position otherwise. It proceeds towards the first element of Container. If no equal element is found, then Reverse_Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Vector; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Has_Element (Find (Container, Item)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Vector; Process : @key{not null access} @key{procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Invokes Process.@key{all} with a cursor that designates each element in Container, in index order. Program_Error is propagated if Process.@key{all} tampers with the cursors of Container. Any exception raised by Process is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The purpose of the @lquotes@;tamper with the cursors@rquotes@; check is to prevent erroneous execution from the Position parameter of Process.@key{all} becoming invalid. This check takes place when the operations that tamper with the cursors of the container are called. The check cannot be made later (say in the body of Iterate), because that could cause the Position cursor to be invalid and potentially cause execution to become erroneous -- defeating the purpose of the check.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ There is no check needed if an attempt is made to insert or delete nothing (that is, Count = 0 or Length(Item) = 0).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check is easy to implement: each container needs a counter. The counter is incremented when Iterate is called, and decremented when Iterate completes. If the counter is nonzero when an operation that inserts or deletes is called, Finalize is called, or one of the other operations in the list occurs, Program_Error is raised.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Vector; Process : @key{not null access} @key{procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the elements in Container as per Iterate, except that elements are traversed in reverse index order.]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. How many times the subprograms of Generic_Sorting call "<" is unspecified.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Sorted (Container : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if the elements are sorted smallest first as determined by the generic formal "<" operator; otherwise, Is_Sorted returns False. Any exception raised during evaluation of "<" is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Sort (Container : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies swapping the elements, usually including an intermediate copy. This means that the elements will usually be copied. (As with Swap, if the implementation can do this some other way, it is allowed to.) Since the elements are nonlimited, this usually will not be a problem. Note that there is @ImplAdviceName below that the implementation should use a sort that minimizes copying of elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The sort is not required to be stable (and the fast algorithm required will not be stable). If a stable sort is needed, the user can include the original location of the element as an extra "sort key". We considered requiring the implementation to do that, but it is mostly extra overhead -- usually there is something already in the element that provides the needed stability.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Merge (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Merge removes elements from Source and inserts them into Target; afterwards, Target contains the union of the elements that were initially in Source and Target; Source is left empty. If Target and Source are initially sorted smallest first, then Target is ordered smallest first as determined by the generic formal "<" operator; otherwise, the order of elements in Target is unspecified. Any exception raised during evaluation of "<" is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is a bounded error if either of the vectors is unsorted, see below. The bounded error can be recovered by sorting Target after the merge call, or the vectors can be pretested with Is_Sorted.]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Merge operation will usually require copying almost all of the elements. One implementation strategy would be to extend Target to the appropriate length, then copying elements from the back of the vectors working towards the front. An alternative approach would be to allocate a new internal data array of the appropriate length, copy the elements into it in an appropriate order, and then replacing the data array in Target with the temporary.]} @end{ImplNote} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Reading the value of an empty element by calling Element, Query_Element, Update_Element, Swap, Is_Sorted, Sort, Merge, "=", Find, or Reverse_Find is a bounded error. The implementation may treat the element as having any normal value (see @RefSecNum{Data Validity}) of the element type, or raise Constraint_Error or Program_Error before modifying the vector.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For instance, a default initialized element could be returned. Or some previous value of an element. But returning random junk is not allowed if the type has default initial value(s).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Assignment and streaming of empty elements are @b<not> bounded errors. This is consistent with regular composite types, for which assignment and streaming of uninitialized components do not cause a bounded error, but reading the uninitialized component does cause a bounded error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are other operations which are defined in terms of the operations listed above.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Calling Merge in an instance of Generic_Sorting with either Source or Target not ordered smallest first using the provided generic formal "<" operator is a bounded error. Either Program_Error is raised after Target is updated as described for Merge, or the operation works as defined.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[ambiguous cursor],Sec=[of a vector]} @Defn2{Term=[cursor],Sec=[ambiguous]} A Cursor value is @i{ambiguous} if any of the following have occurred since it was created:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Insert, Insert_Space, or Delete has been called on the vector that contains the element the cursor designates with an index value (or a cursor designating an element at such an index value) less than or equal to the index value of the element designated by the cursor; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The vector that contains the element it designates has been passed to the Sort or Merge procedures of an instance of Generic_Sorting, or to the Reverse_Elements procedure.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram other than "=" or Has_Element declared in Containers.Vectors with an ambiguous (but not invalid, see below) cursor parameter. Possible results are:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor may be treated as if it were No_Element;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor may designate some element in the vector (but not necessarily the element that it originally designated);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Constraint_Error may be raised; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Program_Error may be raised.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Cursors are made ambiguous if an Insert or Delete occurs that moves the elements in the internal array including the designated ones. After such an operation, the cursor probably still designates an element (although it might not after a deletion), but it is a @i<different> element. That violates the definition of cursor @em it designates a particular element.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For "=" or Has_Element, the cursor works normally (it would not be No_Element). We don't want to trigger an exception simply for comparing a bad cursor.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases or ensure that cursors survive such operations, in many cases the overhead necessary to make the check (or ensure cursors continue to designate the same element) is substantial in time or space.]} @end{Reason} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i{invalid} if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a vector]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The vector that contains the element it designates has been finalized;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The vector that contains the element it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The element it designates has been deleted.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if it is called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Vectors is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution), Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above (combined with the bounded error cases) is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the appending of new elements.]} @end{Discussion} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a vector object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a vector shall have the effect of copying the elements from the source vector object to the target vector object.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An assignment of a Vector is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Vectors should be implemented similarly to an array. In particular, if the length of a vector is @i{N}, then]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Element should be @i{O}(log @i{N});]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element for Containers.Vector should be @i{O}(log @i{N}).]}]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Append with Count=1 when @i{N} is less than the capacity of the vector should be @i{O}(log @i{N}); and]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Append with Count = 1 when @i{N} is less than the capacity for Containers.Vector should be @i{O}(log @i{N}).]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Prepend with Count=1 and Delete_First with Count=1 should be @i{O}(@i{N} log @i{N}).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Prepend with Count = 1 and Delete_First with Count=1 for Containers.Vectors should be @i{O}(@i{N} log @i{N}).]}]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i{N}) time to access elements, that program could be unusable when the vectors are large. We allow @i{O}(log @i{N}) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Vectors.Generic_Sorting should be @i{O}(@i{N}**2), and the average time complexity should be better than @i{O}(@i{N}**2).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Vectors.Generic_Sorting should be @i{O}(@i{N}**2), and the average time complexity should be better than @i{O}(@i{N}**2).]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a better than @i{O}(@i{N}**2) sorting algorithm, such as Quicksort. No bubble sorts allowed!]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Vectors.Generic_Sorting.Sort and Containers.Vectors.Generic_Sorting.Merge should minimize copying of elements.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Vectors.Generic_Sorting.Sort and Containers.Vectors.Generic_Sorting.Merge should minimize copying of elements.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean @lquotes@;absolutely minimize@rquotes here; we're not intending to require a single copy for each element. Rather, we want to suggest that the sorting algorithm chosen is one that does not copy items unnecessarily. Bubble sort would not meet this advice, for instance.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Vectors.Move should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source vector to the Target vector.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a vector operation, no storage should be lost, nor any elements removed from a vector unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a vector operation, no storage should be lost, nor any elements removed from a vector unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[All elements of a vector occupy locations in the internal array. If a sparse container is required, a Hashed_Map should be used rather than a vector.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Index_Type'Base'First = Index_Type'First an instance of Ada.Containers.Vectors will raise Constraint_Error. A value below Index_Type'First is required so that an empty vector has a meaningful value of Last_Index.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This property is the main reason why only integer types (as opposed to any discrete type) are allowed as the index type of a vector. An enumeration or modular type would require a subtype in order to meet this requirement.]} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Containers.Vectors is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2], Name=[The Package Containers.Doubly_Linked_Lists]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Doubly_Linked_Lists provides private types List and Cursor, and a set of operations for each type. A list container is optimized for insertion and deletion at any position. @Defn{list container}@Defn2{Term=[container],Sec=[list]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[node],Sec=[of a list]}A doubly-linked list container object manages a linked list of internal @i{nodes}, each of which contains an element and pointers to the next (successor) and previous (predecessor) internal nodes. A cursor designates a particular node within a list (and by extension the element contained in that node). A cursor keeps designating the same node (and element) as long as the node is part of the container, even if the node is moved in the container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The @i{length} of a list is the number of elements it contains.@Defn2{Term=[length],Sec=(of a list container)}]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Doubly_Linked_Lists has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Element_Type @key{is private}; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Doubly_Linked_Lists @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Doubly_@!Linked_@!Lists]} @key{pragma} Preelaborate(Doubly_Linked_Lists);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{List} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_List} : @key{constant} List;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : List) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} List; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} List; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} List; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} List; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Elements} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} List; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap_Links} (Container : @key{in out} List; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Container: @key{in out} List; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : List) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : List) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : List) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : List) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find} (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : List; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean is <>; @key{package} @AdaPackDefn{Generic_Sorting} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Sorted} (Container : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Sort} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Merge} (Target : @key{in out} List; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Sorting;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Doubly_Linked_Lists;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the functions Find, Reverse_Find, and "=" on list values return an unspecified value. The exact arguments and number of calls of this generic formal function by the functions Find, Reverse_Find, and "=" on list values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by the listed functions cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the results of Find, Reverse_Find, and List "=" are unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type List is used to represent lists. The type List needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_List represents the empty List object. It has a length of 0. If an object of type List is not otherwise initialized, it is initialized to the same value as Empty_List.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a list]} A subprogram is said to @i{tamper with cursors} of a list object @i<L> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<L>, that is, it calls the Insert, Clear, Delete, or Delete_Last procedures with @i<L> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it reorders the elements of @i<L>, that is, it calls the Splice, Swap_Links, or Reverse_Elements procedures or the Sort or Merge procedures of an instance of Generic_Sorting with @i<L> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<L>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<L> as a parameter.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Swap copies elements rather than reordering them, so it doesn't tamper with cursors.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a list]} A subprogram is said to @i{tamper with elements} of a list object @i<L> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<L>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<L>, that is, it calls the Replace_Element or Swap procedures with @i<L> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same list object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, it compares each element in Left to the corresponding element in Right using the generic formal equality operator. If any such comparison returns False, the function returns False; otherwise it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : List) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} List; Position : @b{in} Cursor; New_Item : @b{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Replace_Element assigns the value New_Item to the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} List; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Update_Element calls Process.@key{all} with the element designated by Position as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} List; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first calls Clear (Target). Then, the nodes in Source are moved to Target (in the original order). The length of Target is set to the length of Source, and the length of Source is set to 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert inserts Count copies of New_Item prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last node (if any). Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Before checks that the cursor does not belong to some other Container. This check implies that a reference to the container is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert allocates Count copies of New_Item, and inserts them prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last element (if any). Position designates the first newly-inserted element. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert inserts Count new elements prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last node (if any). The new elements are initialized by default (see @RefSecNum{Object Declarations}). Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First (Container), New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, No_Element, New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} List; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise Delete removes (from Container) Count elements starting at the element designated by Position (or all of the elements starting at Position if there are fewer than Count elements starting at Position). Finally, Position is set to No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Delete (Container, First (Container), Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) <= Count then Delete_Last is equivalent to Clear (Container). Otherwise it removes the last Count nodes from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Elements (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container in reverse order.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike the similar routine for a vector, elements should not be copied; rather, the nodes should be exchanged. Cursors are expected to reference the same elements afterwards.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} List; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap exchanges the values of the elements designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[After a call to Swap, I designates the element value previously designated by J, and J designates the element value previously designated by I. The cursors do not become ambiguous from this operation.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap_Links (Container : @key{in out} List; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap_Links exchanges the nodes designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike Swap, this exchanges the nodes, not the elements. No copying is performed. I and J designate the same elements after this call as they did before it. This operation can provide better performance than Swap if the element size is large.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Target, then Program_Error is propagated. Otherwise, if Source denotes the same object as Target, the operation has no effect. Otherwise, Splice reorders elements such that they are removed from Source and moved to Target, immediately prior to Before. If Before equals No_Element, the nodes of Source are spliced after the last node of Target. The length of Target is incremented by the number of nodes in Source, and the length of Source is set to 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element then Constraint_Error is propagated. If Before does not equal No_Element, and does not designate an element in Target, then Program_Error is propagated. If Position does not equal No_Element, and does not designate a node in Source, then Program_Error is propagated. If Source denotes the same object as Target, then there is no effect if Position equals Before, else the element designated by Position is moved immediately prior to Before, or, if Before equals No_Element, after the last element. In both cases, Position and the length of Target are unchanged. Otherwise the element designated by Position is removed from Source and moved to Target, immediately prior to Before, or, if Before equals No_Element, after the last element of Target. The length of Target is incremented, the length of Source is decremented, and Position is updated to represent an element in Target.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Source is the same as Target, and Position = Before, or Next(Position} = Before, Splice has no effect, as the element does not have to move to meet the postcondition.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Container: @key{in out} List; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element then Constraint_Error is propagated. If Before does not equal No_Element, and does not designate an element in Container, then Program_Error is propagated. If Position does not equal No_Element, and does not designate a node in Container, then Program_Error is propagated. If Position equals Before there is no effect. Otherwise, the element designated by Position is moved immediately prior to Before, or, if Before equals No_Element, after the last element. The length of Container is unchanged.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : List) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, First returns the value No_Element. Otherwise it returns a cursor that designates the first node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : List) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : List) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last returns the value No_Element. Otherwise it returns a cursor that designates the last node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : List) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the last element of the container, then Next returns the value No_Element. Otherwise, it returns a cursor that designates the successor of the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the first element of the container, then Previous returns the value No_Element. Otherwise, it returns a cursor that designates the predecessor of the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the element designated by Position, or at the first element if Position equals No_Element. It proceeds towards Last (Container). If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the element designated by Position, or at the last element if Position equals No_Element. It proceeds towards First (Container). If no equal element is found, then Reverse_Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : List; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Find (Container, Item) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of Has_Element for an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each node in Container, starting with the first node and moving the cursor as per the Next function. Program_Error is propagated if Process.@key{all} tampers with the cursors of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The purpose of the tamper with cursors check is to prevent erroneous execution from the Position parameter of Process.@key{all} becoming invalid. This check takes place when the operations that tamper with the cursors of the container are called. The check cannot be made later (say in the body of Iterate), because that could cause the Position cursor to be invalid and potentially cause execution to become erroneous -- defeating the purpose of the check.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the nodes in Container as per Iterate, except that elements are traversed in reverse order, starting with the last node and moving the cursor as per the Previous function.]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. How many times the subprograms of Generic_Sorting call "<" is unspecified.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Sorted (Container : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if the elements are sorted smallest first as determined by the generic formal "<" operator; otherwise, Is_Sorted returns False. Any exception raised during evaluation of "<" is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Sort (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the nodes of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. The sort is stable. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike array sorts, we do require stable sorts here. That's because algorithms in the merge sort family (as described by Knuth) can be both fast and stable. Such sorts use the extra memory as offered by the links to provide better performance.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that list sorts never copy elements; it is the nodes, not the elements, that are reordered.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Merge (Target : @key{in out} List; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Merge removes elements from Source and inserts them into Target; afterwards, Target contains the union of the elements that were initially in Source and Target; Source is left empty. If Target and Source are initially sorted smallest first, then Target is ordered smallest first as determined by the generic formal "<" operator; otherwise, the order of elements in Target is unspecified. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is a bounded error if either of the lists is unsorted, see below. The bounded error can be recovered by sorting Target after the merge call, or the lists can be pretested with Is_Sorted.]} @end{Ramification} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Calling Merge in an instance of Generic_Sorting with either Source or Target not ordered smallest first using the provided generic formal "<" operator is a bounded error. Either Program_Error is raised after Target is updated as described for Merge, or the operation works as defined.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[A Cursor value is @i<invalid> if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a list container]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list that contains the element it designates has been finalized;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list that contains the element it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The element it designates has been deleted.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if it is called with an invalid cursor parameter. Execution is erroneous if any other subprogram declared in Containers.Doubly_Linked_Lists is called with an invalid cursor parameter. @PDefn{unspecified}@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other nodes.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a doubly-linked List object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a list shall have the effect of copying the elements from the source list object to the target list object.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An assignment of a List is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Doubly_Linked_Lists should be implemented similarly to a linked list. In particular, if @i<N> is the length of a list, then the worst-case time complexity of Element, Insert with Count=1, and Delete with Count=1 should be @i{O}(log @i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element, Insert with Count=1, and Delete with Count=1 for Containers.Doubly_Linked_Lists should be @i{O}(log @i<N>).]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i<N>) time to access elements, that program could be unusable when the lists are large. We allow @i{O}(log @i<N>) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Doubly_Linked_Lists.Generic_Sorting should be @i{O}(@i<N>**2), and the average time complexity should be better than @i{O}(@i<N>**2).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[a call on procedure Sort of an instance of Containers.Doubly_Linked_Lists.Generic_Sorting should have an average time complexity better than @i{O}(@i{N}**2) and worst case no worse than @i{O}(@i{N}**2).]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a better than @i{O}(@i{N}**2) sorting algorithm, such as Quicksort. No bubble sorts allowed!]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Doubly_Link_Lists.Move should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a list operation, no storage should be lost, nor any elements removed from a list unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a list operation, no storage should be lost, nor any elements removed from a list unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Sorting a list never copies elements, and is a stable sort (equal elements remain in the original order). This is different than sorting an array or vector, which may need to copy elements, and is probably not a stable sort.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Doubly_Linked_Lists is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic packages Containers.Hashed_Maps and Containers.Ordered_Maps provide private types Map and Cursor, and a set of operations for each type. A map container allows an arbitrary type to be used as a key to find the element associated with that key. A hashed map uses a hash function to organize the keys, while an ordered map orders the keys per a specified relation. @Defn{map container}@Defn2{Term=[container],Sec=[map]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This section describes the declarations that are common to both kinds of maps. See @RefSecNum{The Package Containers.Hashed_Maps} for a description of the semantics specific to Containers.Hashed_Maps and @RefSecNum{The Package Containers.Ordered_Maps} for a description of the semantics specific to Containers.Ordered_Maps.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the function "=" on map values returns an unspecified value. The exact arguments and number of calls of this generic formal function by the function "=" on map values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by "=" for Map objects cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the result of "=" for Map objects is unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Map is used to represent maps. The type Map needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[node],Sec=[of a map]}A map contains pairs of keys and elements, called @i{nodes}. Map cursors designate nodes, but also can be thought of as designating an element (the element contained in the node) for consistency with the other containers. There exists an equivalence relation on keys, whose definition is different for hashed maps and ordered maps. A map never contains two or more nodes with equivalent keys. The @i{length} of a map is the number of nodes it contains.@Defn2{Term=[length],Sec=[of a map]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of a map]} @Defn2{Term=[last node],Sec=[of a map]} @Defn2{Term=[successor node],Sec=[of a map]}Each nonempty map has two particular nodes called the @i{first node} and the @i{last node} (which may be the same). Each node except for the last node has a @i{successor node}. If there are no other intervening operations, starting with the first node and repeatedly going to the successor node will visit each node in the map exactly once until the last node is reached. The exact definition of these terms is different for hashed maps and ordered maps.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of these generic packages have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[tamper with cursors],Sec=[of a map]} A subprogram is said to @i{tamper with cursors} of a map object @i<M> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<M>, that is, it calls the Insert, Include, Clear, Delete, or Exclude procedures with @i<M> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<M>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<M> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls one of the operations defined to tamper with the cursors of @i<M>.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Replace only modifies a key and element rather than rehashing, so it does not tamper with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[tamper with elements],Sec=[of a map]} A subprogram is said to @i{tamper with elements} of a map object @i<M> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<M>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<M>, that is, it calls the Replace or Replace_Element procedures with @i<M> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Map represents the empty Map object. It has a length of 0. If an object of type Map is not otherwise initialized, it is initialized to the same value as Empty_Map.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no node. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[If Left and Right denote the same map object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each key @i<K> in Left, the function returns False if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a key equivalent to @i<K> is not present in Right; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the element associated with @i<K> in Left is not equal to the element associated with @i<K> in Right (using the generic formal equality operator for elements).]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the function has not returned a result after checking all of the keys, it returns True. Any exception raised during evaluation of key equivalence or element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Map) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of nodes in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Map) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the nodes from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Key (Position : Cursor) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Key returns the key component of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element component of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Replace_Element assigns New_Item to the element of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the key and element from the node designated by Position as the arguments. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise Update_Element calls Process.@key{all} with the key and element from the node designated by Position as the arguments. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Map; Source : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first calls Clear (Target). Then, each node from Source is removed from Source and inserted into Target. The length of Source is 0 after a successful call to Move.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert checks if a node with a key equivalent to Key is already present in Container. If a match is found, Inserted is set to False and Position designates the element with the matching key. Otherwise, Insert allocates a new node, initializes it to Key and New_Item, and adds it to Container; Inserted is set to True and Position designates the newly-inserted node. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts Key into Container as per the five-parameter Insert, with the difference that an element initialized by default (see @RefSecNum{Object Declarations}) is inserted.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts Key and New_Item into Container as per the five-parameter Insert, with the difference that if a node with a key equivalent to Key is already in the map, then Constraint_Error is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} Inserted : Boolean; C : Cursor; @key{begin} Insert (Container, Key, New_Item, C, Inserted); @key{if not} Inserted @key{then} @key{raise} Constraint_Error; @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but doesn't require the hassle of @key{out} parameters.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Include (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Include inserts Key and New_Item into Container as per the five-parameter Insert, with the difference that if a node with a key equivalent to Key is already in the map, then this operation assigns Key and New_Item to the matching node. Any exception raised during assignment is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} C : Cursor := Find (Container, Key); @key{begin} @key{if} C = No_Element @key{then} Insert (Container, Key, New_Item); @key{else} Replace (Container, Key, New_Item); @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but this avoids doing the search twice.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Replace checks if a node with a key equivalent to Key is present in Container. If a match is found, Replace assigns Key and New_Item to the matching node; otherwise, Constraint_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We update the key as well as the element, as the key might include additional information that does not participate in equivalence. If only the element needs to be updated, use Replace_Element (Find (Container, Key), New_Element).]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Exclude checks if a node with a key equivalent to Key is present in Container. If a match is found, Exclude removes the node from the map.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Exclude should work on an empty map; nothing happens in that case.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Delete checks if a node with a key equivalent to Key is present in Container. If a match is found, Delete removes the node from the map; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete removes the node designated by Position from the map. Position is set to No_Element on return.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Position checks that the cursor does not belong to some other map. This check implies that a reference to the map is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the successor of the node designated by Position. If Position designates the last node, then No_Element is returned. If Position equals No_Element, then No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) equals 0, then Find returns No_Element. Otherwise, Find checks if a node with a key equivalent to Key is present in Container. If a match is found, a cursor designating the matching node is returned; otherwise, No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Find (Container, Key)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Map; Key : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Find (Container, Key) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Position designates a node, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below); the result of Has_Element for invalid cursors is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each node in Container, starting with the first node and moving the cursor according to the successor relation. Program_Error is propagated if Process.@key{all} tampers with the cursors of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with cursors@rquotes@; check takes place when the operations that insert or delete elements, and so on, are called.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @end{DescribeCode} @end{StaticSem} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i{invalid} if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a map]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The map that contains the node it designates has been finalized;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The map that contains the node it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The node it designates has been deleted from the map.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if these functions are called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Hashed_Maps or Containers.Ordered_Maps is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other nodes.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a Map object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a map shall have the effect of copying the elements from the source map object to the target map object.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An assignment of a Map is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Move for a map should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a map operation, no storage should be lost, nor any elements removed from a map unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a map operation, no storage should be lost, nor any elements removed from a map unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This description of maps is new; the extensions are documented with the specific packages.]} @end{DiffWord95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Hashed_Maps]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Hashed_Maps has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Key_Type @key{is private}; @key{type} Element_Type @key{is private}; @key{with function} Hash (Key : Key_Type) @key{return} Hash_Type; @key{with function} Equivalent_Keys (Left, Right : Key_Type) @key{return} Boolean; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean is <>; @key{package} Ada.Containers.Hashed_Maps @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Hashed_Maps]} @key{pragma} Preelaborate(Hashed_Maps);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Map} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Map} : @key{constant} Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Map; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Map; Source : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Map; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Hashed_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[An object of type Map contains an expandable hash table, which is used to provide direct access to nodes. The @i<capacity> of an object of type Map is the maximum number of nodes that can be inserted into the hash table prior to it being automatically expanded.@Defn2{Term=[capacity],Sec=[of a hashed map]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The expected implementation for a Map uses a hash table which is grown when it is too small, with linked lists hanging off of each bucket. Note that in that implementation a cursor needs a back pointer to the Map object to implement iteration; that could either be in the nodes, or in the cursor object. To provide an average @i{O}(1) access time, capacity would typically equal the number of buckets in such an implementation, so that the average bucket linked list length would be no more than 1.0.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no defined relationship between elements in a hashed map. Typically, iteration will return elements in the order that they are hashed in.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term={equivalent key},Sec={of a hashed map}} Two keys @i<K1> and @i<K2> are defined to be @i<equivalent> if Equivalent_Keys (@i<K1>, @i<K2>) returns True.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Hash is expected to return the same value each time it is called with a particular key value. For any two equivalent key values, the actual for Hash is expected to return the same value. If the actual for Hash behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against Hash raising an exception, or returning random numbers, or any other @lquotes@;bad@rquotes behavior. It's not practical to do so, and a broken Hash function makes the container unusable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation can call Hash whenever it is needed; we don't want to specify how often that happens. The result must remain the same (this is logically a pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Equivalent_Keys on Key_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define an equivalence relationship, that is, be reflexive, symmetric, and transitive. If the actual for Equivalent_Keys behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Equivalent_Keys, and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As with Hash, the implementation is not required to protect against Equivalent_Keys raising an exception or returning random results. Similarly, the implementation can call this operation whenever it is needed. The result must remain the same (this is a logically pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of a key stored in a node of a map is changed other than by an operation in this package such that at least one of Hash or Equivalent_Keys give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against changes to key values other than via the operations declared in the Hashed_Maps package.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[To see how this could happen, imagine an instance of Hashed_Maps where the key type is an access-to-variable type and Hash returns a value derived from the components of the designated object. Then, any operation that has a key value could modify those components and change the hash value:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Key (Map).Some_Component := New_Value;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is really a design error on the part of the user of the map; it shouldn't be possible to modify keys stored in a map. But we can't prevent this error anymore than we can prevent someone passing as Hash a random number generator.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of a hashed map]} @Defn2{Term=[last node],Sec=[of a hashed map]} @Defn2{Term=[successor node],Sec=[of a hashed map]}Which nodes are the first node and the last node of a map, and which node is the successor of a given node, are unspecified, other than the general semantics described in @RefSecNum{Maps}.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Typically the first node will be the first node in the first bucket, the last node will be the last node in the last bucket, and the successor will be obtained by following the collision list, and going to the next bucket at the end of each bucket.]} @end{ImplNote} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Map) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Map; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Reserve_Capacity allocates a new hash table such that the length of the resulting map can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then rehashes the nodes in Container onto the new hash table. It replaces the old hash table with the new hash table, and then deallocates the old hash table. Any exception raised during allocation is propagated and Container is not modified.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors of Container.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine is used to preallocate the internal hash table to the specified capacity such that future Inserts do not require expansion of the hash table. Therefore, the implementation should allocate the needed memory to make that true at this point, even though the visible semantics could be preserved by waiting until enough elements are inserted.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While Reserve_Capacity can be used to reduce the capacity of a map, we do not specify whether an implementation actually supports reduction of the capacity. Since the actual capacity can be anything greater than or equal to Count, an implementation never has to reduce the capacity.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reserve_Capacity tampers with the cursors, as rehashing probably will change the order that elements are stored in the map.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Maps}, Clear does not affect the capacity of Container.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Map; Source : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intended implementation is that the internal hash table of Target is first deallocated; then the internal hash table is removed from Source and moved to Target.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Maps}, if Length (Container) equals Capacity (Container), then Insert first calls Reserve_Capacity to increase the capacity of Container to some larger value.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Insert should only compare keys that hash to the same bucket in the hash table.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We specify when Reserve_Capacity is called to bound the overhead of capacity expansion operations (which are potentially expensive). Moreover, expansion can be predicted by comparing Capacity(Map) to Length(Map). Since we don't specify by how much the hash table is expanded, this only can be used to predict the next expansion, not later ones.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Exclude should only compare keys that hash to the same bucket in the hash table.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Delete should only compare keys that hash to the same bucket in the hash table. The node containing the element may be deallocated now, or it may be saved and reused later.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In a typical implementation, this will be the first node in the lowest numbered hash bucket that contains a node.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In a typical implementation, this will return the next node in a bucket; if Position is the last node in a bucket, this will return the first node in the next non-empty bucket.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A typical implementation will need to a keep a pointer at the map container in the cursor in order to implement this function.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Find should only compare keys that hash to the same bucket in the hash table.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Key (Left), Key (Right)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Key (Left), Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Left, Key (Right)).]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a map, the average time complexity of the subprograms Element, Insert, Include, Replace, Delete, Exclude and Find that take a key parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms that take a cursor parameter should be @i{O}(1). The average time complexity of Reserve_Capacity should be @i{O}(@i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The average time complexity of Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter for Containers.Hashed_Maps should be @i{O}(log @i<N>). The average time complexity of the subprograms of Containers.Hashed_Maps that take a cursor parameter should be @i{O}(1).]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation for which Find is @i{O}(@i<N>), that program could be unusable when the maps are large. We allow @i{O}(log @i<N>) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Hashed_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Ordered_Maps]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Ordered_Maps has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Key_Type @key{is private}; @key{type} Element_Type @key{is private}; @key{with function} "<" (Left, Right : Key_Type) @key{return} Boolean @key{is} <>; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Ordered_Maps @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Ordered_Maps]} @key{pragma} Preelaborate(Ordered_Maps);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Map} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Map} : @key{constant} Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Map; Source : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Map) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Key} (Container : Map) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Map) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Key} (Container : Map) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Map; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Ordered_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term={equivalent key},Sec={of an ordered map}} Two keys @i<K1> and @i<K2> are @i<equivalent> if both @i<K1> < @i<K2> and @i<K2> < @i<K1> return False, using the generic formal "<" operator for keys. Function Equivalent_Keys returns True if Left and Right are equivalent, and False otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" on Key_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive. If the actual for "<" behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call "<" and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against "<" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. It's not practical to do so, and a broken "<" function makes the container unusable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation can call "<" whenever it is needed; we don't want to specify how often that happens. The result must remain the same (this is a logically pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of a key stored in a map is changed other than by an operation in this package such that at least one of "<" or "=" give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against changes to key values other than via the operations declared in the Ordered_Maps package.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[To see how this could happen, imagine an instance of Ordered_Maps package where the key type is an access-to-variable type and "<" returns a value derived from comparing the components of the designated objects. Then, any operation that has a key value (even if the key value is constant) could modify those components and change the result of "<":]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Key (Map).Some_Component := New_Value;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is really a design error on the part of the user of the map; it shouldn't be possible to modify keys stored in a map such that "<" changes. But we can't prevent this error anymore than we can prevent someone passing as "<" a routine that produces random answers.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of an ordered map]} @Defn2{Term=[last node],Sec=[of an ordered map]} @Defn2{Term=[successor node],Sec=[of an ordered map]} The first node of a nonempty map is the one whose key is less than the key of all the other nodes in the map. The last node of a nonempty map is the one whose key is greater than the key of all the other elements in the map. The successor of a node is the node with the smallest key that is larger than the key of the given node. The predecessor of a node is the node with the largest key that is smaller than the key of the given node. All comparisons are done using the generic formal "<" operator for keys.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_First has no effect. Otherwise the node designated by First (Container) is removed from Container. Delete_First tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_Last has no effect. Otherwise the node designated by Last (Container) is removed from Container. Delete_Last tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Map) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Key (Container : Map) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the last node in Container. If Container is empty, returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Map) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Key (Container : Map) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Previous returns No_Element. Otherwise Previous returns a cursor designating the node that precedes the one designated by Position. If Position designates the first element, then Previous returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Floor (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Floor searches for the last node whose key is not greater than Key, using the generic formal "<" operator for keys. If such a node is found, a cursor that designates it is returned. Otherwise No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Ceiling (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ceiling searches for the first node whose key is not less than Key, using the generic formal "<" operator for keys. If such a node is found, a cursor that designates it is returned. Otherwise No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Left) < Key (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Right) < Key (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Left) < Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Right < Key (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Left < Key (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Right) < Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the nodes in Container as per Iterate, with the difference that the nodes are traversed in predecessor order, starting with the last node.]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a map, then the worst-case time complexity of the Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms that take a cursor parameter should be @i{O}(1).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter for Containers.Ordered_Maps should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms of Containers.Ordered_Maps that take a cursor parameter should be @i{O}(1).]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A balanced (red-black) tree for keys has @i{O}(log @i<N>) worst-case performance. Note that a @i{O}(@i<N>) worst-case implementation (like a list) would be wrong.]} @end{ImplNote} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i<N>) to find elements, that program could be unusable when the maps are large. We allow the extra log @i<N> factors because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Ordered_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic packages Containers.Hashed_Sets and Containers.Ordered_Sets provide private types Set and Cursor, and a set of operations for each type. A set container allows elements of an arbitrary type to be stored without duplication. A hashed set uses a hash function to organize elements, while an ordered set orders its element per a specified relation.@Defn{set container} @Defn2{Term=[container],Sec=[set]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This section describes the declarations that are common to both kinds of sets. See @RefSecNum{The Package Containers.Hashed_Sets} for a description of the semantics specific to Containers.Hashed_Sets and @RefSecNum{The Package Containers.Ordered_Sets} for a description of the semantics specific to Containers.Ordered_Sets.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the function "=" on set values returns an unspecified value. The exact arguments and number of calls of this generic formal function by the function "=" on set values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by the "=" for Set objects cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the result of "=" for Set objects is unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Set is used to represent sets. The type Set needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A set contains elements. Set cursors designate elements. There exists an equivalence relation on elements, whose definition is different for hashed sets and ordered sets. A set never contains two or more equivalent elements. The @i{length} of a set is the number of elements it contains.@Defn2{Term={length},Sec={of a set}}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of a set]} @Defn2{Term=[last element],Sec=[of a set]} @Defn2{Term=[successor element],Sec=[of a set]} Each nonempty set has two particular elements called the @i{first element} and the @i{last element} (which may be the same). Each element except for the last element has a @i{successor element}. If there are no other intervening operations, starting with the first element and repeatedly going to the successor element will visit each element in the set exactly once until the last element is reached. The exact definition of these terms is different for hashed sets and ordered sets.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of these generic packages have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a set]} A subprogram is said to @i{tamper with cursors} of a set object @i{S} if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i{S}, that is, it calls the Insert, Include, Clear, Delete, Exclude, or Replace_Element procedures with @i{S} as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to include Replace_Element here because it might delete and reinsert the element if it moves in the set. That could change the order of iteration, which is what this check is designed to prevent. Replace is also included, as it is defined in terms of Replace_Element.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<S>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<S> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls one of the operations defined to tamper with cursors of @i<S>.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a set]} A subprogram is said to @i{tamper with elements} of a set object @i<S> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<S>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_@!Element_@!Preserving_@!Key does not cause a problem.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't need to list Replace and Replace_Element here because they are covered by @lquotes@;tamper with cursors@rquotes. For Set, @lquotes@;tamper with cursors@rquotes@; and @lquotes@;tamper with elements@rquotes are the same. We leave both terms so that the rules for routines like Iterate and Query_Element are consistent across all containers.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Set represents the empty Set object. It has a length of 0. If an object of type Set is not otherwise initialized, it is initialized to the same value as Empty_Set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same set object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each element @i<E> in Left, the function returns False if an element equal to @i<E> (using the generic formal equality operator) is not present in Right. If the function has not returned a result after checking all of the elements, it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Sets (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same set object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each element @i<E> in Left, the function returns False if an element equivalent to @i<E> is not present in Right. If the function has not returned a result after checking all of the elements, it returns True. Any exception raised during evaluation of element equivalence is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Set (New_Item : Element_Type) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set containing the single element New_Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Set) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. If an element equivalent to New_Item is already present in Container at a position other than Position, Program_Error is propagated. Otherwise, Replace_Element assigns New_Item to the element designated by Position. Any exception raised by the assignment is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The final assignment may require that the node of the element be moved in the Set's data structures. That could mean that implementing this operation exactly as worded above could require the overhead of searching twice. Implementations are encouraged to avoid this extra overhead when possible, by prechecking if the old element is equivalent to the new one, by inserting a placeholder node while checking for an equivalent element, and similar optimizations.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor still designates the same element after this operation; only the value of that element has changed. Cursors cannot include information about the relative position of an element in a Set (as they must survive insertions and deletions of other elements), so this should not pose an implementation hardship.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Set; Source : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first clears Target. Then, each element from Source is removed from Source and inserted into Target. The length of Source is 0 after a successful call to Move.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert checks if an element equivalent to New_Item is already present in Container. If a match is found, Inserted is set to False and Position designates the matching element. Otherwise, Insert adds New_Item to Container; Inserted is set to True and Position designates the newly-inserted element. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts New_Item into Container as per the four-parameter Insert, with the difference that if an element equivalent to New_Item is already in the set, then Constraint_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} Inserted : Boolean; C : Cursor; @key{begin} Insert (Container, New_Item, C, Inserted); @key{if not} Inserted @key{then} @key{raise} Constraint_Error; @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but doesn't require the hassle of @key{out} parameters.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Include (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Include inserts New_Item into Container as per the four-parameter Insert, with the difference that if an element equivalent to New_Item is already in the set, then it is replaced. Any exception raised during assignment is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Replace checks if an element equivalent to New_Item is already in the set. If a match is found, that element is replaced with New_Item; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Exclude checks if an element equivalent to Item is present in Container. If a match is found, Exclude removes the element from the set.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Delete checks if an element equivalent to Item is present in Container. If a match is found, Delete removes the element from the set; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete removes the element designated by Position from the set. Position is set to No_Element on return.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Position checks that the cursor does not belong to some other set. This check implies that a reference to the set is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Union (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Union inserts into Target the elements of Source that are not equivalent to some element already in Target.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the objects are the same, the result is the same as the original object. The implementation needs to take care so that aliasing effects do not make the result trash; Union (S, S); must work.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Union (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising all of the elements of Left, and the elements of Right that are not equivalent to some element of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Intersection (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Union deletes from Target the elements of Target that are not equivalent to some element of Source.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the objects are the same, the result is the same as the original object. The implementation needs to take care so that aliasing effects do not make the result trash; Intersection (S, S); must work.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Intersection (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising all the elements of Left that are equivalent to the some element of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Difference (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Difference clears Target. Otherwise, it deletes from Target the elements that are equivalent to some element of Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Difference (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising the elements of Left that are not equivalent to some element of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Symmetric_Difference (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Symmetric_Difference clears Target. Otherwise, it deletes from Target the elements that are equivalent to some element of Source, and inserts into Target the elements of Source that are not equivalent to some element of Target.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Symmetric_Difference (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising the elements of Left that are not equivalent to some element of Right, and the elements of Right that are not equivalent to some element of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Overlap (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If an element of Left is equivalent to some element of Right, then Overlap returns True. Otherwise it returns False.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is commutative. If Overlap returns False, the two sets are disjoint.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Subset (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If an element of Subset is not equivalent to some element of Of_Set, then Is_Subset returns False. Otherwise it returns True.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is not commutative, so we use parameter names that make it clear in named notation which set is which.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the successor of the element designated by Position. If Position designates the last element, then No_Element is returned. If Position equals No_Element, then No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Find (Container, Item) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) equals 0, then Find returns No_Element. Otherwise, Find checks if an element equivalent to Item is present in Container. If a match is found, a cursor designating the matching element is returned; otherwise, No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Set; Item : Element_Type) @key{return} Boolean;]} @end{Example} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below); the result of Has_Element for invalid cursors is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each element in Container, starting with the first element and moving the cursor according to the successor relation. Program_Error is propagated if Process.@key{all} tampers with the cursors of Container. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with cursors@rquotes@; check takes place when the operations that insert or delete elements, and so on are called.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Both Containers.Hashed_Set and Containers.Ordered_Set declare a nested generic package Generic_Keys, which provides operations that allow set manipulation in terms of a key (typically, a portion of an element) instead of a complete element. The formal function Key of Generic_Keys extracts a key value from an element. It is expected to return the same value each time it is called with a particular element. The behavior of Generic_Keys is unspecified if Key behaves in some other manner.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A key is expected to unambiguously determine a single equivalence class for elements. The behavior of Generic_Keys is unspecified if the formal parameters of this package behave in some other manner.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Key (Position : Cursor) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Element (Position)).]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The subprograms in package Generic_Keys named Contains, Find, Element, Delete, and Exclude, are equivalent to the corresponding subprograms in the parent package, with the difference that the Key parameter is used to locate an element in the set.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Replace_Element (Container, Find (Container, Key), New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element_Preserving_Key (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Update_@!Element_@!Preserving_Key uses Key to save the key value @i<K> of the element designated by Position. Update_@!Element_@!Preserving_Key then calls Process.@key{all} with that element as the argument. Program_Error is propagated if Process.@key{all} tampers with the elements of Container. Any exception raised by Process.@key{all} is propagated. After Process.@key{all} returns, Update_@!Element_@!Preserving_Key checks if @i<K> determines the same equivalence class as that for the new element; if not, the element is removed from the set and Program_Error is propagated.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The key check ensures that the invariants of the set are preserved by the modification. The @lquotes@;tampers with the elements@rquotes@; check prevents data loss (if Element_Type is by-copy) or erroneous execution (if element type is unconstrained and indefinite).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @end{DescribeCode} @end{StaticSem} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i<invalid> if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a set]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The set that contains the element it designates has been finalized;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The set that contains the element it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The element it designates has been deleted from the set.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if these functions are called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Hashed_Sets or Containers.Ordered_Sets is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a Set object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a set shall have the effect of copying the elements from the source set object to the target set object.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An assignment of a Set is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Move for sets should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a set operation, no storage should be lost, nor any elements removed from a set unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a set operation, no storage should be lost, nor any elements removed from a set unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This description of sets is new; the extensions are documented with the specific packages.]} @end{DiffWord95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Hashed_Sets]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Hashed_Sets has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Element_Type @key{is private}; @key{with function} Hash (Element : Element_Type) @key{return} Hash_Type; @key{with function} Equivalent_Elements (Left, Right : Element_Type) @key{return} Boolean; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Hashed_Sets @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Hashed_Sets]} @key{pragma} Preelaborate(Hashed_Sets);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Set} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Set} : @key{constant} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Sets} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Set} (New_Item : Element_Type) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Set; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Set; Source : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Union} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Union} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{or}" (Left, Right : Set) @key{return} Set @key{renames} Union;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Intersection} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Intersection} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{and}" (Left, Right : Set) @key{return} Set @key{renames} Intersection;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "-" (Left, Right : Set) @key{return} Set @key{renames} Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Symmetric_Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Symmetric_Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{xor}" (Left, Right : Set) @key{return} Set @key{renames} Symmetric_Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Overlap} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Subset} (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{type} Key_Type (<>) @key{is private}; @key{with function} Key (Element : Element_Type) @key{return} Key_Type; @key{with function} Hash (Key : Key_Type) @key{return} Hash_Type; @key{with function} Equivalent_Keys (Left, Right : Key_Type) @key{return} Boolean; @key{package} @AdaPackDefn{Generic_Keys} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Set; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element_Preserving_Key} (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Keys;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Hashed_Sets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[capacity],Sec=[of a hashed set]} An object of type Set contains an expandable hash table, which is used to provide direct access to elements. The @i<capacity> of an object of type Set is the maximum number of elements that can be inserted into the hash table prior to it being automatically expanded.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[equivalent element],Sec=[of a hashed set]} Two elements @i<E1> and @i<E2> are defined to be @i<equivalent> if Equivalent_Elements (@i<E1>, @i<E2>) returns True.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Hash is expected to return the same value each time it is called with a particular element value. For any two equivalent elements, the actual for Hash is expected to return the same value. If the actual for Hash behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Equivalent_Elements is expected to return the same value each time it is called with a particular pair of Element values. It should define an equivalence relationship, that is, be reflexive, symmetric, and transitive. If the actual for Equivalent_Elements behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Equivalent_Elements, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of an element stored in a set is changed other than by an operation in this package such that at least one of Hash or Equivalent_Elements give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See @RefSec{The Package Containers.Hashed_Maps} for a suggested implementation, and for justification of the restrictions regarding Hash and Equivalent_Elements. Note that sets only need to store elements, not key/element pairs.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of a hashed set]} @Defn2{Term=[last element],Sec=[of a hashed set]} @Defn2{Term=[successor element],Sec=[of a hashed set]} Which elements are the first element and the last element of a set, and which element is the successor of a given element, are unspecified, other than the general semantics described in @RefSecNum{Sets}.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Set) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Set; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Reserve_Capacity allocates a new hash table such that the length of the resulting set can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then rehashes the elements in Container onto the new hash table. It replaces the old hash table with the new hash table, and then deallocates the old hash table. Any exception raised during allocation is propagated and Container is not modified.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors of Container.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors, as rehashing probably will change the relationships of the elements in Container.]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Sets}, Clear does not affect the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Sets}, if Length (Container) equals Capacity (Container), then Insert first calls Reserve_Capacity to increase the capacity of Container to some larger value.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first hashed element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Element (Left), Element (Right)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Element (Left), Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Left, Element (Right)).]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any element @i{E}, the actual function for the generic formal function Generic_Keys.Hash is expected to be such that Hash (@i{E}) = Generic_Keys.Hash (Key (@i{E})). If the actuals for Key or Generic_Keys.Hash behave in some other manner, the behavior of Generic_Keys is unspecified. Which subprograms of Generic_Keys call Generic_Keys.Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any two elements @i{E1} and @i{E2}, the boolean values Equivalent_Elements (@i{E1}, @i{E2}) and Equivalent_Keys (Key (@i{E1}), Key (@i{E2})) are expected to be equal. If the actuals for Key or Equivalent_Keys behave in some other manner, the behavior of Generic_Keys is unspecified. Which subprograms of Generic_Keys call Equivalent_Keys, and how many times they call it, is unspecified.@PDefn{unspecified}]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a set, the average time complexity of the subprograms Insert, Include, Replace, Delete, Exclude and Find that take an element parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms that take a cursor parameter should be @i{O}(1). The average time complexity of Reserve_Capacity should be @i{O}(@i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The average time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations of Containers.Hashed_Sets that take an element parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms of Containers.Hashed_Sets that take a cursor parameter should be @i{O}(1). The average time complexity of Containers.@!Hashed_Sets.@!Reserve_Capacity should be @i{O}(@i<N>).]}]} @end{ImplAdvice} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[See @RefSec{The Package Containers.Hashed_Maps} for implementation notes regarding some of the operations of this package.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Hashed_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Ordered_Sets]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Ordered_Sets has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Element_Type @key{is private}; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Ordered_Sets @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Ordered_Sets]} @key{pragma} Preelaborate(Ordered_Sets);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left, Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Set} @key{is tagged private}; @key{pragma} Preelaborable_Initialization(Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Set} : @key{constant} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Sets} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Set} (New_Item : Element_Type) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Set; Source : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Union} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Union} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{or}" (Left, Right : Set) @key{return} Set @key{renames} Union;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Intersection} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Intersection} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{and}" (Left, Right : Set) @key{return} Set @key{renames} Intersection;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "-" (Left, Right : Set) @key{return} Set @key{renames} Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Symmetric_Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Symmetric_Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{xor}" (Left, Right : Set) @key{return} Set @key{renames} Symmetric_Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Overlap} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Subset} (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Set) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Set) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{type} Key_Type (<>) @key{is private}; @key{with function} Key (Element : Element_Type) @key{return} Key_Type; @key{with function} "<" (Left, Right : Key_Type) @key{return} Boolean @key{is} <>; @key{package} @AdaPackDefn{Generic_Keys} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Set; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element_Preserving_Key} (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Keys;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Ordered_Sets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Two elements @i<E1> and @i<E2> are @i<equivalent> if both @i<E1> < @i<E2> and @i<E2> < @i<E1> return False, using the generic formal "<" operator for elements.@Defn2{Term=[equivalent element],Sec=[of a ordered set]} Function Equivalent_Elements returns True if Left and Right are equivalent, and False otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" on Element_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive. If the actual for "<" behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call "<" and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of an element stored in a set is changed other than by an operation in this package such that at least one of "<" or "=" give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See @RefSec{The Package Containers.Ordered_Maps} for a suggested implementation, and for justification of the restrictions regarding "<" and "=". Note that sets only need to store elements, not key/element pairs.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of a ordered set]} @Defn2{Term=[last element],Sec=[of a ordered set]} @Defn2{Term=[successor element],Sec=[of a ordered set]} The first element of a nonempty set is the one which is less than all the other elements in the set. The last element of a nonempty set is the one which is greater than all the other elements in the set. The successor of an element is the smallest element that is larger than the given element. The predecessor of an element is the largest element that is smaller than the given element. All comparisons are done using the generic formal "<" operator for elements.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_First has no effect. Otherwise the element designated by First (Container) is removed from Container. Delete_First tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_Last has no effect. Otherwise the element designated by Last (Container) is removed from Container. Delete_Last tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Set) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the last element in Container. If Container is empty, returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Set) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Previous returns No_Element. Otherwise Previous returns a cursor designating the element that precedes the one designated by Position. If Position designates the first element, then Previous returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Floor (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Floor searches for the last element which is not greater than Item. If such an element is found, a cursor that designates it is returned. Otherwise No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Ceiling (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ceiling searches for the first element which is not less than Item. If such an element is found, a cursor that designates it is returned. Otherwise No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Left) < Element (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Right) < Element (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Left) < Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Right < Element (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Left < Element (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Right) < Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the elements in Container as per Iterate, with the difference that the elements are traversed in predecessor order, starting with the last element.]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any two elements @i<E1> and @i<E2>, the boolean values (@i<E1> < @i<E2>) and (Key(@i<E1>) < Key(@i<E2>)) are expected to be equal. If the actuals for Key or Generic_Keys."<" behave in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Key and Generic_Keys."<", and how many times the functions are called, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[In addition to the semantics described in @RefSecNum{Sets}, the subprograms in package Generic_Keys named Floor and Ceiling, are equivalent to the corresponding subprograms in the parent package, with the difference that the Key subprogram parameter is compared to elements in the container using the Key and "<" generic formal functions. The function named Equivalent_Keys in package Generic_Keys returns True if both Left < Right and Right < Left return False using the generic formal "<" operator, and returns True otherwise.]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a set, then the worst-case time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations that take an element parameter should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms that take a cursor parameter should be @i{O}(1).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations of Containers.Ordered_Sets that take an element parameter should be @i{O}((log @i<N>)**2). The worst-case time complexity of the subprograms of Containers.Ordered_Sets that take a cursor parameter should be @i{O}(1).]}]} @end{ImplAdvice} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[See @RefSec{The Package Containers.Ordered_Maps} for implementation notes regarding some of the operations of this package.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Ordered_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Vectors]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Vectors provides a private type Vector and a set of operations. It provides the same operations as the package Containers.Vectors (see @RefSecNum{The Package Containers.Vectors}), with the difference that the generic formal Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Vectors@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Vectors]} has the same contents as Containers.Vectors except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedures with the profiles:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[F],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[are omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These procedures are omitted because there is no way to create a default-initialized object of an indefinite type. Note that Insert_Space can be used instead of this routine in most cases. Omitting the routine completely allows any problems to be diagnosed by the compiler when converting from a definite to indefinite vector.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Vectors is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Doubly_Linked_Lists]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Doubly_Linked_Lists provides private types List and Cursor, and a set of operations for each type. It provides the same operations as the package Containers.Doubly_Linked_Lists (see @RefSecNum{The Package Containers.Doubly_Linked_Lists}), with the difference that the generic formal Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.@!Indefinite_@!Doubly_@!Linked_@!Lists@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Doubly_Linked_Lists]} has the same contents as Containers.@!Doubly_@!Linked_@!Lists except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Doubly_Linked_Lists is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Hashed_Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Hashed_Maps provides a map with the same operations as the package Containers.Hashed_Maps (see @RefSecNum{The Package Containers.Hashed_Maps}), with the difference that the generic formal types Key_Type and Element_Type are indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Hashed_Maps@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Hashed_Maps]} has the same contents as Containers.Hashed_Maps except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Key_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Hashed_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Ordered_Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Ordered_Maps provides a map with the same operations as the package Containers.Ordered_Maps (see @RefSecNum{The Package Containers.Ordered_Maps}), with the difference that the generic formal types Key_Type and Element_Type are indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Ordered_Maps@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Ordered_Maps]} has the same contents as Containers.Ordered_Maps except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Key_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Ordered_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Hashed_Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Hashed_Sets provides a set with the same operations as the package Containers.Hashed_Sets (see @RefSecNum{The Package Containers.Hashed_Sets}), with the difference that the generic formal type Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Hashed_Sets@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Hashed_Sets]} has the same contents as Containers.Hashed_Sets except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_@!Element_@!Preserving_Key may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Hashed_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers.Indefinite_Ordered_Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Ordered_Sets provides a set with the same operations as the package Containers.Ordered_Sets (see @RefSecNum{The Package Containers.Ordered_Sets}), with the difference that the generic formal type Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Ordered_Sets@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Ordered_Sets]} has the same contents as Containers.Ordered_Sets except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_@!Element_@!Preserving_Key may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Ordered_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[Array Sorting]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic procedures Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort provide sorting on arbitrary array types.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library procedure Containers.Generic_Array_Sort has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Index_Type @key{is} (<>); @key{type} Element_Type @key{is private}; @key{type} Array_Type @key{is array} (Index_Type @key{range} <>) @key{of} Element_Type; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{procedure} Ada.Containers.Generic_Array_Sort (Container : @key{in out} Array_Type);@SubChildUnit{Parent=[Ada.Containers],Child=[Generic_Array_Sort]} @key{pragma} Pure(Ada.Containers.Generic_Array_Sort);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Array_Sort is unspecified. How many times Generic_Array_Sort calls "<" is unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies swapping the elements, usually including an intermediate copy. This of course means that the elements will be copied. Since the elements are nonlimited, this usually will not be a problem. Note that there is Implementation Advice below that the implementation should use a sort that minimizes copying of elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The sort is not required to be stable (and the fast algorithm required will not be stable). If a stable sort is needed, the user can include the original location of the element as an extra "sort key". We considered requiring the implementation to do that, but it is mostly extra overhead -- usually there is something already in the element that provides the needed stability.]} @end{Ramification} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library procedure Containers.@!Generic_@!Constrained_@!Array_Sort has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Index_Type @key{is} (<>); @key{type} Element_Type @key{is private}; @key{type} Array_Type @key{is array} (Index_Type) @key{of} Element_Type; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{procedure} Ada.Containers.Generic_Constrained_Array_Sort@SubChildUnit{Parent=[Ada.Containers],Child=[Generic_Constrained_Array_Sort]} (Container : @key{in out} Array_Type); @key{pragma} Pure(Ada.Containers.Generic_Constrained_Array_Sort);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Constrained_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Constrained_Array_Sort is unspecified. How many times Generic_Constrained_Array_Sort calls "<" is unspecified.@PDefn{unspecified}]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[ The worst-case time complexity of a call on an instance of Containers.Generic_Array_Sort or Containers.Generic_Constrained_Array_Sort should be @i{O}(@i<N>**2) or better, and the average time complexity should be better than @i{O}(@i<N>**2), where @i<N> is the length of the Container parameter.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should have an average time complexity better than @i{O}(@i{N}**2) and worst case no worse than @i{O}(@i{N}**2).]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a sorting algorithm better than @i{O}(@i<N>**2), such as Quicksort. No bubble sorts allowed!]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[ Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should minimize copying of elements.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should minimize copying of elements.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean @lquotes@;absolutely minimize@rquotes@; here; we're not intending to require a single copy for each element. Rather, we want to suggest that the sorting algorithm chosen is one that does not copy items unnecessarily. Bubble sort would not meet this advice, for instance.]} @end{Honest} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic packages Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort are new.]} @end{Extend95} �����������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_dirs.mss���������������������������������������������������������0000755�0001752�0001001�00000162141�12273462240�017761� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_dirs.mss,v $ } @comment{ $Revision: 1.28 $ $Date: 2006/10/19 06:40:30 $ $Author: Randy $ } @Part(predefdirs, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:30 $} @RMNewPage@Comment{For printed RM Ada 2007} @LabeledAddedClause{Version=[2],Name=[The Package Directories]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The package Directories provides operations for manipulating files and directories, and their names.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The notes for this clause contain the expected interpretations of some of the operations on various target systems. @lquotes@;Unix@rquotes@; refers to the UNIX@latin1(174) operating system, and in most cases also covers Unix-like systems such as Linux and POSIX. @lquotes@;Windows@latin1(174)@rquotes@; refers to the Microsoft@latin1(174) Windows@latin1(174) 2000 operating system and usually also covers most other versions that use the Win32 API.]} @end{Discussion} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Directories has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.IO_Exceptions; @key{with} Ada.Calendar; @key{package} Ada.Directories @key{is}@ChildUnit{Parent=[Ada],Child=[Directories]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Directory and file operations:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Current_Directory} @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Directory} (Directory : in String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Create_Directory} (New_Directory : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Directory} (Directory : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Create_Path} (New_Directory : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Tree} (Directory : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_File} (Name : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Rename} (Old_Name, New_Name : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Copy_File} (Source_Name, Target_Name : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[File and directory name operations:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Full_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Simple_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Containing_Directory} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Extension} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Base_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose} (Containing_Directory : @key{in} String := ""; Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{File and directory queries:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{File_Kind} @key{is} (Directory, Ordinary_File, Special_File);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{File_Size} @key{is range} 0 .. @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Exists} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Kind} (Name : @key{in} String) @key{return} File_Kind;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Size} (Name : @key{in} String) @key{return} File_Size;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modification_Time} (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Directory searching:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Directory_Entry_Type} @key{is limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Filter_Type} @key{is array} (File_Kind) @key{of} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Search_Type} @key{is limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Start_Search} (Search : @key{in out} Search_Type; Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{End_Search} (Search : @key{in out} Search_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{More_Entries} (Search : @key{in} Search_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Next_Entry} (Search : @key{in out} Search_Type; Directory_Entry : @key{out} Directory_Entry_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Search ( Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True); Process : @key{not null access procedure} ( Directory_Entry : @key{in} Directory_Entry_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Operations on Directory Entries:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Simple_Name} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Full_Name} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Kind} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Kind;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Size} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Size;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modification_Time} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Status_Error} : @key{exception renames} Ada.IO_Exceptions.Status_Error; @AdaExcDefn{Name_Error} : @key{exception renames} Ada.IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key{exception renames} Ada.IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key{exception renames} Ada.IO_Exceptions.Device_Error;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} -- @RI{Not specified by the language.} @key{end} Ada.Directories;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[External files may be classified as directories, special files, or ordinary files. A @i<directory> is an external file that is a container for files on the target system. A @i<special file> is an external file that cannot be created or read by a predefined Ada input-output package. External files that are not special files or directories are called @i<ordinary files>. @Defn{directory} @Defn{special file} @Defn{ordinary file}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A directory is an external file, although it may not have a name on some targets. A directory is not a special file, as it can be created and read by Directories.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Devices and soft links are examples of special files on Windows@latin1(174) and Unix.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Even if an implementation provides a package to create and read soft links, such links are still special files.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[A @i<file name> is a string identifying an external file. Similarly, a @i<directory name> is a string identifying a directory. The interpretation of file names and directory names is implementation-defined. @Defn{directory name} @Defn{file name}]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The interpretation of file names and directory names.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The @i<full name> of an external file is a full specification of the name of the file. If the external environment allows alternative specifications of the name (for example, abbreviations), the full name should not use such alternatives. A full name typically will include the names of all of the directories that contain the item. The @i<simple name> of an external file is the name of the item, not including any containing directory names. Unless otherwise specified, a file name or directory name parameter in a call to a predefined Ada input-output subprogram can be a full name, a simple name, or any other form of name supported by the implementation. @Defn2{Term=[full name],Sec=[of a file]} @Defn2{Term=[simple name],Sec=[of a file]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The full name on Unix is a complete path to the root. For Windows@latin1(174), the full name includes a complete path, as well as a disk name ("C:") or network share name. For both systems, the simple name is the part of the name following the last '/' (or '\' for Windows@latin1(174)). For example, in the name "/usr/randy/ada-directories.ads", "ada-directories.ads" is the simple name.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is possible for a file or directory name to be neither a full name nor a simple name. For instance, the Unix name "../parent/myfile" is neither a full name nor a simple name.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The @i<default directory> is the directory that is used if a directory or file name is not a full name (that is, when the name does not fully identify all of the containing directories). @Defn{default directory}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The default directory is the one maintained by the familiar @lquotes@;cd@rquotes@; command on Unix and Windows@latin1(174). Note that Windows@latin1(174) maintains separate default directories for each disk drive; implementations should use the natural implementation.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[A @i<directory entry> is a single item in a directory, identifying a single external file (including directories and special files). @Defn{directory entry}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[For each function that returns a string, the lower bound of the returned value is 1.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following file and directory operations are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Current_Directory @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full directory name for the current default directory. The name returned shall be suitable for a future call to Set_Directory. The exception Use_Error is propagated if a default directory is not supported by the external environment.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Set_Directory (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Sets the current default directory. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the external environment does not support making Directory (in the absence of Name_Error) a default directory.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Create_Directory (New_Directory : @key{in} String; Form : @key{in} String := "");]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Creates a directory with name New_Directory. The Form parameter can be used to give system-dependent characteristics of the directory; the interpretation of the Form parameter is implementation-defined. A null string for Form specifies the use of the default options of the implementation of the new directory. The exception Name_Error is propagated if the string given as New_Directory does not allow the identification of a directory. The exception Use_Error is propagated if the external environment does not support the creation of a directory with the given name (in the absence of Name_Error) and form.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_Directory (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing empty directory with name Directory. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the external environment does not support the deletion of the directory (or some portion of its contents) with the given name (in the absence of Name_Error).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Create_Path (New_Directory : @key{in} String; Form : @key{in} String := "");]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Creates zero or more directories with name New_Directory. Each non-existent directory named by New_Directory is created.@Redundant[ For example, on a typical Unix system, Create_Path ("/usr/me/my"); would create directory "me" in directory "usr", then create directory "my" in directory "me".] The Form parameter can be used to give system-dependent characteristics of the directory; the interpretation of the Form parameter is implementation-defined. A null string for Form specifies the use of the default options of the implementation of the new directory. The exception Name_Error is propagated if the string given as New_Directory does not allow the identification of any directory. The exception Use_Error is propagated if the external environment does not support the creation of any directories with the given name (in the absence of Name_Error) and form.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_Tree (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing directory with name Directory. The directory and all of its contents (possibly including other directories) are deleted. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the external environment does not support the deletion of the directory or some portion of its contents with the given name (in the absence of Name_Error). If Use_Error is propagated, it is unspecified whether a portion of the contents of the directory is deleted.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_File (Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing ordinary or special file with name Name. The exception Name_Error is propagated if the string given as Name does not identify an existing ordinary or special external file. The exception Use_Error is propagated if the external environment does not support the deletion of the file with the given name (in the absence of Name_Error).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Rename (Old_Name, New_Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Renames an existing external file (including directories) with name Old_Name to New_Name. The exception Name_Error is propagated if the string given as Old_Name does not identify an existing external file. The exception Use_Error is propagated if the external environment does not support the renaming of the file with the given name (in the absence of Name_Error). In particular, Use_Error is propagated if a file or directory already exists with name New_Name.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is expected to work within a a single directory, and implementers are encouraged to support it across directories on a single device. Copying files from one device to another is discouraged (that's what Copy_File is for). However, there is no requirement to detect file copying by the target system. If the target system has an API that gives that for @lquotes@;free@rquotes, it can be used. For Windows@latin1(174), for instance, MoveFile can be used to implement Rename.]} @end{ImplNote} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Copy_File (Source_Name, Target_Name : @key{in} String; Form : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Copies the contents of the existing external file with name Source_Name to an external file with name Target_Name. The resulting external file is a duplicate of the source external file. The Form parameter can be used to give system-dependent characteristics of the resulting external file; the interpretation of the Form parameter is implementation-defined. Exception Name_Error is propagated if the string given as Source_Name does not identify an existing external ordinary or special file, or if the string given as Target_Name does not allow the identification of an external file. The exception Use_Error is propagated if the external environment does not support creating the file with the name given by Target_Name and form given by Form, or copying of the file with the name given by Source_Name (in the absence of Name_Error).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Name_Error is always raised if Source_Name identifies a directory. It is up to the implementation whether special files can be copied, or if Use_Error will be raised.]} @end{Ramification} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following file and directory name operations are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Full_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full name corresponding to the file name specified by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Full name means that no abbreviations are used in the returned name, and that it is a full specification of the name. Thus, for Unix and Windows@latin1(174), the result should be a full path that does not contain any "." or ".." directories. Typically, the default directory is used to fill in any missing information.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Simple_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the simple name portion of the file name specified by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Containing_Directory (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the name of the containing directory of the external file (including directories) identified by Name. (If more than one directory can contain Name, the directory name returned is implementation-defined.) The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file. The exception Use_Error is propagated if the external file does not have a containing directory.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is purely a string manipulation function. If Name is not given as a full name, the containing directory probably won't be one, either. For example, if Containing_Directory ("..\AARM\RM-A-8") is called on Windows@latin1(174), the result should be "..\AARM". If there is no path at all on the name, the result should be "." (which represents the current directory). Use Full_Name on the result of Containing_Directory if the full name is needed.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Extension (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the extension name corresponding to Name. The extension name is a portion of a simple name (not including any separator characters), typically used to identify the file class. If the external environment does not have extension names, then the null string is returned. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Unix and Windows@latin1(174), the extension is the portion of the simple name following the rightmost period. For example, in the simple name "RM-A-8.html", the extension is "html".]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Base_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the base name corresponding to Name. The base name is the remainder of a simple name after removing any extension and extension separators. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Unix and Windows@latin1(174), the base name is the portion of the simple name preceding the rightmost period (except for the special directory names "." and "..", whose Base_Name is "." and ".."). For example, in the simple name "RM-A-8.html", the base name is "RM-A-8".]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Compose (Containing_Directory : @key{in} String := ""; Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the name of the external file with the specified Containing_Directory, Name, and Extension. If Extension is the null string, then Name is interpreted as a simple name; otherwise Name is interpreted as a base name. The exception Name_Error is propagated if the string given as Containing_Directory is not null and does not allow the identification of a directory, or if the string given as Extension is not null and is not a possible extension, or if the string given as Name is not a possible simple name (if Extension is null) or base name (if Extension is non-null).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above definition implies that if the Extension is null, for Unix and Windows@latin1(174) no '.' is added to Name.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Name is null, Name_Error should be raised, as nothing is not a possible simple name or base name.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Generally, Compose(Containing_Directory(F), Base_Name(F),Extension(F)) = F. However, this is not true on Unix or Windows@latin1(174) for file names that end with a '.'; Compose(Base_Name("Fooey."),Extension("Fooey.")) = "Fooey". This is not a problem for Windows@latin1(174), as the names have the same meaning with or without the '.', but these are different names for Unix. Thus, care needs to be taken on Unix; if Extension is null, Base_Name should be avoided. (That's not usually a problem with file names generated by a program.)]} @end{Discussion} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following file and directory queries and types are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} File_Kind @key{is} (Directory, Ordinary_File, Special_File);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type File_Kind represents the kind of file represented by an external file or directory.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} File_Size @key{is range} 0 .. @RI<implementation-defined>;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type File_Size represents the size of an external file.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The maximum value for a file size in Directories.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Exists (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if an external file represented by Name exists, and False otherwise. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Kind (Name : @key{in} String) @key{return} File_Kind;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the kind of external file represented by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Size (Name : @key{in} String) @key{return} File_Size;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the size of the external file represented by Name. The size of an external file is the number of stream elements contained in the file. If the external file is not an ordinary file, the result is implementation-defined. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file. The exception Constraint_Error is propagated if the file size is not a value of type File_Size.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The result for Directories.Size for a directory or special file],Old=[]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[We allow raising Constraint_Error, so that an implementation for a system with 64-bit file sizes does not need to support full numerics on 64-bit integers just to implement this package. Of course, if 64-bit integers are available on such a system, they should be used when defining type File_Size.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Modification_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the time that the external file represented by Name was most recently modified. If the external file is not an ordinary file, the result is implementation-defined. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file. The exception Use_Error is propagated if the external environment does not support reading the modification time of the file with the name given by Name (in the absence of Name_Error).]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The result for Directories.Modification_Time for a directory or special file.], Old=[]}]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following directory searching operations and types are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Directory_Entry_Type @key{is limited private};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Directory_Entry_Type represents a single item in a directory. These items can only be created by the Get_Next_Entry procedure in this package. Information about the item can be obtained from the functions declared in this package. A default-initialized object of this type is invalid; objects returned from Get_Next_Entry are valid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Filter_Type @key{is array} (File_Kind) @key{of} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Filter_Type specifies which directory entries are provided from a search operation. If the Directory component is True, directory entries representing directories are provided. If the Ordinary_File component is True, directory entries representing ordinary files are provided. If the Special_File component is True, directory entries representing special files are provided.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Search_Type @key{is limited private};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Search_Type contains the state of a directory search. A default-initialized Search_Type object has no entries available (function More_Entries returns False). Type Search_Type needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Start_Search (Search : @key{in out} Search_Type; Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Starts a search in the directory named by Directory for entries matching Pattern. Pattern represents a pattern for matching file names. If Pattern is null, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. After a successful call on Start_Search, the object Search may have entries available, but it may have no entries available if no files or directories match Pattern and Filter. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error). When Start_Search propagates Name_Error or Use_Error, the object Search will have no entries available.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The interpretation of a non-null search pattern in Directories.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} End_Search (Search : @key{in out} Search_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ends the search represented by Search. After a successful call on End_Search, the object Search will have no entries available.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The only way that a call to End_Search could be unsuccessful if Device_Error (see @RefSecNum{Exceptions in Input-Output}) is raised because of an underlying failure (or bug).]} @end{Ramification} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} More_Entries (Search : @key{in} Search_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if more entries are available to be returned by a call to Get_Next_Entry for the specified search object, and False otherwise.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Get_Next_Entry (Search : @key{in out} Search_Type; Directory_Entry : @key{out} Directory_Entry_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the next Directory_Entry for the search described by Search that matches the pattern and filter. If no further matches are available, Status_Error is raised. It is implementation-defined as to whether the results returned by this routine are altered if the contents of the directory are altered while the Search object is valid (for example, by another program). The exception Use_Error is propagated if the external environment does not support continued searching of the directory represented by Search.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The results of a Directories search if the contents of the directory are altered while a search is in progress.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Search ( Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (others => True); Process : @key{not null access procedure} ( Directory_Entry : @key{in} Directory_Entry_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches in the directory named by Directory for entries matching Pattern. The subprogram designated by Process is called with each matching entry in turn. Pattern represents a pattern for matching file names. If Pattern is null, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error).]} @Comment{The implementation-defined case is handled above.} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@lquotes@;In turn@rquotes means that the calls to the subprogram designated by Process are not made in parallel; they can be made in any order but must be in sequence.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Simple_Name (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the simple external name of the external file (including directories) represented by Directory_Entry. The format of the name returned is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Full_Name (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full external name of the external file (including directories) represented by Directory_Entry. The format of the name returned is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Kind (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Kind;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the kind of external file represented by Directory_Entry. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Size (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Size;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the size of the external file represented by Directory_Entry. The size of an external file is the number of stream elements contained in the file. If the external file represented by Directory_Entry is not an ordinary file, the result is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid. The exception Constraint_Error is propagated if the file size is not a value of type File_Size.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Modification_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the time that the external file represented by Directory_Entry was most recently modified. If the external file represented by Directory_Entry is not an ordinary file, the result is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid. The exception Use_Error is propagated if the external environment does not support reading the modification time of the file represented by Directory_Entry.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Copy_File, if Source_Name identifies an existing external ordinary file created by a predefined Ada input-output package, and Target_Name and Form can be used in the Create operation of that input-output package with mode Out_File without raising an exception, then Copy_File shall not propagate Use_Error.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that Copy_File will copy any file that the Ada programmer could copy (by writing some possibly complicated Ada code).]} @end{Discussion} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If other information about a file (such as the owner or creation date) is available in a directory entry, the implementation should provide functions in a child package Directories.Information to retrieve it.@ChildUnit{Parent=[Ada.Directories],Child=[Information]}]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Package Directories.Information should be provided to retrieve other information about a file.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Windows@latin1(174), Directories.Information should contain at least the following routines:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Directories.Information @key{is} -- @RI[System-specific directory information.] -- @RI[Version for the Microsoft@latin1(174) Windows@latin1(174) operating system.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Creation_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Read_Only (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Needs_Archiving (Name : @key{in} String) @key{return} Boolean; -- @RI[This generally means that the file needs to be backed up.] -- @RI[The flag is only cleared by backup programs.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Compressed (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Encrypted (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Hidden (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_System (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Offline (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Temporary (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Sparse (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Not_Indexed (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Creation_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Read_Only (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Needs_Archiving (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean; -- @RI[This generally means that the file needs to be backed up.] -- @RI[The flag is only cleared by backup programs.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Compressed (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Encrypted (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Hidden (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_System (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Offline (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Temporary (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Sparse (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Not_Indexed (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Additional implementation-defined subprograms allowed here.] @key{end} Ada.Directories.Information;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Unix-like systems (Unix, POSIX, Linux, etc.), Directories.Information should contain at least the following routines:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Directories.Information @key{is} -- @RI[System-specific directory information.] -- @RI[Unix and similar systems version.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Status_Change_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Permission @key{is} (Others_Execute, Others_Write, Others_Read, Group_Execute, Group_Write, Group_Read, Owner_Execute, Owner_Write, Owner_Read, Set_Group_ID, Set_User_ID);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Permission_Set_Type @key{is array} (Permission) @key{of} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Permission_Set (Name : @key{in} String) @key{return} Permission_Set_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Owner (Name : @key{in} String) @key{return} String; -- @RI[Returns the image of the User_Id. If a definition of User_Id] -- @RI[is available, an implementation-defined version of Owner] -- @RI[returning User_Id should also be defined.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Group (Name : @key{in} String) @key{return} String; -- @RI[Returns the image of the User_Id. If a definition of Group_Id] -- @RI[is available, an implementation-defined version of Group] -- @RI[returning Group_Id should also be defined.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Block_Special_File (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character_Special_File (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_FIFO (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Symbolic_Link (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Socket (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Status_Change_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Permission_Set (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Permission_Set_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Owner (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String; -- @RI[See Owner above.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Group (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String; -- @RI[See Group above.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Block_Special_File (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character_Special_File (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_FIFO (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Symbolic_Link (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Socket (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Additional implementation-defined subprograms allowed here.] @key{end} Ada.Directories.Information;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We give these definitions to give guidance so that every implementation for a given target is not unnecessarily different. Implementers are encouraged to make packages for other targets as similar to these as possible.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Start_Search and Search should raise Use_Error if Pattern is malformed, but not if it could represent a file in the directory but does not actually do so.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Directories.Start_Search and Directories.Search should raise Use_Error for malformed patterns.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Rename should be supported at least when both New_Name and Old_Name are simple names and New_Name does not identify an existing external file.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Directories.Rename should be supported at least when both New_Name and Old_Name are simple names and New_Name does not identify an existing external file.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Lquotes@;Supported@rquotes@; includes raising an exception if either name is malformed, the file to rename doesn't exist, insufficient permission for the operation exists, or similar problems. But this advice requires implementations to document what they do, and tells implementers that simply raising Use_Error isn't acceptable.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The operations Containing_Directory, Full_Name, Simple_Name, Base_Name, Extension, and Compose operate on file names, not external files. The files identified by these operations do not need to exist. Name_Error is raised only if the file name is malformed and cannot possibly identify a file. Of these operations, only the result of Full_Name depends on the current default directory; the result of the others depends only on their parameters.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Using access types, values of Search_Type and Directory_Entry_Type can be saved and queried later. However, another task or application can modify or delete the file represented by a Directory_Entry_Type value or the directory represented by a Search_Type value; such a value can only give the information valid at the time it is created. Therefore, long-term storage of these values is not recommended.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target system does not support directories inside of directories, then Kind will never return Directory and Containing_Directory will always raise Use_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target system does not support creation or deletion of directories, then Create_Directory, Create_Path, Delete_Directory, and Delete_Tree will always propagate Use_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To move a file or directory to a different location, use Rename. Most target systems will allow renaming of files from one directory to another. If the target file or directory might already exist, it should be deleted first.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[While Rename is only guaranteed to work for name changes within a single directory, its unlikely that implementers would purposely prevent functionality present in the underlying system from working. To move a file totally portably, it's necessary to handle failure of the Rename and fall back to Copy_File and Delete:]} @begin{Example} @ChgAdded{Version=[2],Text=[@key[begin] Rename (Source, Target); @key[exception] @key[when] Use_Error => Copy_File (Source, Target); Delete (Source); @key[end];]} @end{Example} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Ada.Directories is new.]} @end{Extend95} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_environ.mss������������������������������������������������������0000755�0001752�0001001�00000023431�12273462240�020476� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_environ.mss,v $ } @comment{ $Revision: 1.8 $ $Date: 2005/12/06 06:34:05 $ $Author: Randy $ } @Part(predefenviron, Root="ada.mss") @Comment{$Date: 2005/12/06 06:34:05 $} @LabeledAddedClause{Version=[2],Name=[The Package Environment_Variables]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@Defn{environment variable} The package Environment_Variables allows a program to read or modify environment variables. Environment variables are name-value pairs, where both the name and value are strings. The definition of what constitutes an @i{environment variable}, and the meaning of the name and value, are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The definition and meaning of an environment variable.],Old=[]}]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Environment_Variables has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Environment_Variables @key{is}@ChildUnit{Parent=[Ada],Child=[Environment_Variables]} @key{pragma} Preelaborate(Environment_Variables);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Value} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Exists} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set} (Name : @key{in} String; Value : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Name : @key{in} String); @key{procedure} @AdaSubDefn{Clear};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} ( Process : @key{not null access procedure} (Name, Value : @key{in} String));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@key{end} Ada.Environment_Variables;]} @end{Example} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Value (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Value returns the value of the environment variable with the given name. If no environment variable with the given name exists, then Constraint_Error is propagated. If the execution environment does not support environment variables, then Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Exists (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables and an environment variable with the given name currently exists, then Exists returns True; otherwise it returns False.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set (Name : @key{in} String; Value : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[If the external execution environment supports environment variables, then Set first clears any existing environment variable with the given name, and then defines a single new environment variable with the given name and value. Otherwise Program_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If implementation-defined circumstances prohibit the definition of an environment variable with the given name and value, then Constraint_Error is propagated.]} @ChgImplDef{Version=[2],Kind=[AddedNormal], Text=[@Chg{Version=[2],New=[The circumstances where an environment variable cannot be defined.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[It is implementation defined whether there exist values for which the call Set(Name, Value) has the same effect as Clear (Name).]} @ChgImplDef{Version=[2],Kind=[AddedNormal], Text=[@Chg{Version=[2],New=[Environment names for which Set has the effect of Clear.],Old=[]}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Clear deletes all existing environment variable with the given name. Otherwise Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Clear deletes all existing environment variables. Otherwise Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate ( Process : @key{not null access procedure} (Name, Value : @key{in} String));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[If the external execution environment supports environment variables, then Iterate calls the subprogram designated by Process for each existing environment variable, passing the name and value of that environment variable. Otherwise Program_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If several environment variables exist that have the same name, Process is called once for each such variable.]} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call Value if more than one environment variable exists with the given name; the possible outcomes are that:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[one of the values is returned, and that same value is returned in subsequent calls in the absence of changes to the environment; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Program_Error is propagated.]} @end{Itemize} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} Making calls to the procedures Set or Clear concurrently with calls to any subprogram of package Environment_Variables, or to any instantiation of Iterate, results in erroneous execution.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Making calls to the procedures Set or Clear in the actual subprogram corresponding to the Process parameter of Iterate results in erroneous execution.]} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[An implementation shall document how the operations of this package behave if environment variables are changed by external mechanisms (for instance, calling operating system services).]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The behavior of package Environment_Variables when environment variables are changed by external mechanisms.]}]} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[An implementation running on a system that does not support environment variables is permitted to define the operations of package Environment_Variables with the semantics corresponding to the case where the external execution environment does support environment variables. In this case, it shall provide a mechanism to initialize a nonempty set of environment variables prior to the execution of a partition.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[If the execution environment supports subprocesses, the currently defined environment variables should be used to initialize the environment variables of a subprocess.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the execution environment supports subprocesses, the current environment variables should be used to initialize the environment variables of a subprocess.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Changes to the environment variables made outside the control of this package should be reflected immediately in the effect of the operations of this package. Changes to the environment variables made using this package should be reflected immediately in the external execution environment. This package should not perform any buffering of the environment variables.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Changes to the environment variables made outside the control of Environment_Variables should be reflected immediately.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Environment_Variables is new.]} @end{Extend95} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_io.mss�����������������������������������������������������������0000755�0001752�0001001�00000515557�12273462240�017444� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(predefio, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:26 $} @Comment{$Source: e:\\cvsroot/ARM/Source/pre_io.mss,v $} @Comment{$Revision: 1.48 $} @LabeledClause{Input-Output} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Redundant[@Defn{input}@Defn{output} Input-output is provided through language-defined packages, each of which is a child of the root package Ada. The generic packages Sequential_IO and Direct_IO define input-output operations applicable to files containing elements of a given type. The generic package Storage_IO supports reading from and writing to an in-memory buffer. Additional operations for text input-output are supplied in the packages Text_IO@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO@Chg{Version=[2],New=[, and Wide_Wide_Text_IO],Old=[]}. Heterogeneous input-output is provided through the child packages Streams.@!Stream_IO and Text_IO.@!Text_@!Streams (see also @RefSecNum{Streams}). The package IO_Exceptions defines the exceptions needed by the predefined input-output packages.] @end{Intro} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The introduction of Append_File as a new element of the enumeration type File_Mode in Sequential_IO and Text_IO, and the introduction of several new declarations in Text_IO, may result in name clashes in the presence of @key[use] clauses. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Text_IO enhancements (Get_Immediate, Look_Ahead, Standard_Error, Modular_IO, Decimal_IO), Wide_Text_IO, and the stream input-output facilities are new in Ada 95. @end{Extend83} @begin{DiffWord83} RM83-14.6, "Low Level Input-Output," is removed. This has no semantic effect, since the package was entirely implementation defined, nobody actually implemented it, and if they did, they can always provide it as a vendor-supplied package. @end{DiffWord83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO in this description.]} @end{Diffword95} @LabeledClause{External Files and File Objects} @begin{StaticSem} @Defn{external file} @Defn2{Term=[name], Sec=(of an external file)} @Defn2{Term=[form], Sec=(of an external file)} Values input from the external environment of the program, or output to the external environment, are considered to occupy @i{external files}. An external file can be anything external to the program that can produce a value to be read or receive a value to be written. An external file is identified by a string (the @i{name}). A second string (the @i{form}) gives further system-dependent characteristics that may be associated with the file, such as the physical organization or access rights. The conventions governing the interpretation of such strings shall be documented. @Defn2{Term=[file], Sec=(as file object)} Input and output operations are expressed as operations on objects of some @i{file type}, rather than directly in terms of the external files. In the remainder of this section, the term @i{file} is always used to refer to a file object; the term @i{external file} is used otherwise. Input-output for sequential files of values of a single element type is defined by means of the generic package Sequential_IO. In order to define sequential input-output for a given element type, an instantiation of this generic unit, with the given type as actual parameter, has to be declared. The resulting package contains the declaration of a file type (called File_Type) for files of such elements, as well as the operations applicable to these files, such as the Open, Read, and Write procedures. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Input-output for direct access files is likewise defined by a generic package called Direct_IO. Input-output in human-readable form is defined by the (nongeneric) packages Text_IO for Character and String data, @Chg{Version=[2],New=[],Old=[and ]}Wide_Text_IO for Wide_Character and Wide_String data@Chg{Version=[2],New=[, and Wide_Wide_Text_IO for Wide_Wide_Character and Wide_Wide_String data],Old=[]}. Input-output for files containing streams of elements representing values of possibly different types is defined by means of the (nongeneric) package Streams.Stream_IO. Before input or output operations can be performed on a file, the file first has to be associated with an external file. While such an association is in effect, the file is said to be @i{open}, and otherwise the file is said to be @i{closed}. The language does not define what happens to external files after the completion of the main program and all the library tasks (in particular, if corresponding files have not been closed). @Defn2{Term=[access types], Sec=(input-output unspecified)} @Defn2{Term=[input-output], Sec=(unspecified for access types)} @PDefn{unspecified} The effect of input-output for access types is unspecified. @Leading@Keepnext@Defn2{Term=[current mode], Sec=(of an open file)} An open file has a @i{current mode}, which is a value of one of the following enumeration types: @begin{DescribeCode} @begin{Example} @key[type] File_Mode @key[is] (In_File, Inout_File, Out_File); --@RI{ for Direct_IO} @end{Example} These values correspond respectively to the cases where only reading, both reading and writing, or only writing are to be performed. @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @key[type] File_Mode @key[is] (In_File, Out_File, Append_File); --@RI{ for Sequential_IO, Text_IO, Wide_Text_IO, @Chg{Version=[2],New=[Wide_Wide_Text_IO, ], Old=[]}and Stream_IO} @end{Example} These values correspond respectively to the cases where only reading, only writing, or only appending are to be performed. @Trailing@;The mode of a file can be changed. @end{DescribeCode} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Several file management operations are common to Sequential_IO, Direct_IO, Text_IO, @Chg{Version=[2],New=[],Old=[and ]}Wide_Text_IO@Chg{Version=[2], New=[, and Wide_Wide_Text_IO],Old=[]}. These operations are described in subclause @RefSecNum{File Management} for sequential and direct files. Any additional effects concerning text input-output are described in subclause @RefSecNum{Text File Management}. The exceptions that can be propagated by the execution of an input-output subprogram are defined in the package IO_Exceptions; the situations in which they can be propagated are described following the description of the subprogram (and in clause @RefSecNum{Exceptions in Input-Output}). @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exceptions Storage_Error and Program_Error may be propagated. (Program_Error can only be propagated due to errors made by the caller of the subprogram.) Finally, exceptions can be propagated in certain implementation-defined situations. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Any implementation-defined characteristics of the input-output packages.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The last sentence here is referring to the documentation requirements in @RefSec{Exceptions in Input-Output}, and the documentation summary item is provided there.]} @end{Discussion} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Each instantiation of the generic packages Sequential_IO and Direct_IO declares a different type File_Type. In the case of Text_IO, Wide_Text_IO, @Chg{Version=[2],New=[Wide_Wide_Text_IO, ],Old=[]}and Streams.Stream_IO, the corresponding type File_Type is unique. A bidirectional device can often be modeled as two sequential files associated with the device, one of mode In_File, and one of mode Out_File. An implementation may restrict the number of files that may be associated with a given external file. @end{Notes} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO in this description.]} @end{Diffword95} @Comment{@RMNewPage Break here so printed Ada 95 w/ corrigendum RM looks better.} @LabeledClause{Sequential and Direct Files} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} @Defn{sequential file} @Defn{direct file}@Chg{Version=[2],New=[@Defn{stream file}],Old=[]} Two kinds of access to external files are defined in this subclause: @i{sequential access} and @i{direct access}. The corresponding file types and the associated operations are provided by the generic packages Sequential_IO and Direct_IO. A file object to be used for sequential access is called a @i{sequential file}, and one to be used for direct access is called a @i{direct file}. Access to @Chg{Version=[2],New=[@i{stream file}s],Old=[stream files]} is described in @RefSecNum(The Package Streams.Stream_IO). @Defn{sequential access} For sequential access, the file is viewed as a sequence of values that are transferred in the order of their appearance (as produced by the program or by the external environment). When the file is opened with mode In_File or Out_File, transfer starts respectively from or to the beginning of the file. When the file is opened with mode Append_File, transfer to the file starts after the last element of the file. @begin{Discussion} Adding stream I/O necessitates a review of the terminology. In Ada 83, `sequential' implies both the access method (purely sequential @em that is, no indexing or positional access) and homogeneity. Direct access includes purely sequential access and indexed access, as well as homogeneity. In Ada 95, streams allow purely sequential access but also positional access to an individual element, and are heterogeneous. We considered generalizing the notion of `sequential file' to include both Sequential_IO and Stream_IO files, but since streams allow positional access it seems misleading to call them sequential files. Or, looked at differently, if the criterion for calling something a sequential file is whether it permits (versus requires) purely sequential access, then one could just as soon regard a Direct_IO file as a sequential file. It seems better to regard `sequential file' as meaning `only permitting purely sequential access'; hence we have decided to supplement `sequential access' and `direct access' with a third category, informally called `access to streams'. (We decided against the term `stream access' because of possible confusion with the Stream_Access type declared in one of the stream packages.)@end{discussion} @Defn{direct access} @Defn2{Term=[index], Sec=(of an element of an open direct file)} @Defn2{Term=[current size], Sec=(of an external file)} For direct access, the file is viewed as a set of elements occupying consecutive positions in linear order; a value can be transferred to or from an element of the file at any selected position. The position of an element is specified by its @i{index}, which is a number, greater than zero, of the implementation-defined integer type Count. The first element, if any, has index one; the index of the last element, if any, is called the @i{current size}; the current size is zero if there are no elements. The current size is a property of the external file. @Defn2{Term=[current index], Sec=(of an open direct file)} An open direct file has a @i{current index}, which is the index that will be used by the next read or write operation. When a direct file is opened, the current index is set to one. The current index of a direct file is a property of a file object, not of an external file. @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Text=[Italicized @lquotes@;stream file@rquotes@; to clarify that this is another kind of file.]} @end{DiffWord95} @LabeledSubClause{The Generic Package Sequential_IO} @begin{StaticSem} @Leading@;The generic library package Sequential_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[generic] @key[type] Element_Type(<>) @key[is] @key[private]; @key[package] Ada.Sequential_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Sequential_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Out_File, Append_File); @RI{-- File management} @key[procedure] @AdaSubDefn{Create}(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Out_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete}(File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write} (File : @key[in] File_Type; Item : @key[in] Element_Type); @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @keepnext --@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Sequential_IO; @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}) in every instantiation of Sequential_IO.]} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The new enumeration element Append_File may introduce upward incompatibilities. It is possible that a program based on the assumption that File_Mode'Last = Out_File will be illegal (e.g., case statement choice coverage) or execute with a different effect in Ada 95. @end{Incompatible83} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[File_Type cannot be implemented as a (directly) controlled type, as Ada.Sequential_IO can be instantiated at any nesting depth. File_Type could have a component of a controlled type, as long as that type is declared in some other (non-generic) package.],Old=[]}]}@ChgNote{AI-344 allows controlled types to be declared at any nesting depth, so this note is obsolete.} @end{ImplNote} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] File_Type in an instance of Sequential_IO is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @LabeledSubClause{File Management} @begin{StaticSem} The procedures and functions described in this subclause provide for the control of external files; their declarations are repeated in each of the packages for sequential, direct, text, and stream input-output. For text input-output, the procedures Create, Open, and Reset have additional effects described in subclause @RefSecNum{Text File Management}. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Create(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := @RI{default_mode}; Name : @key[in] String := ""; Form : @key[in] String := ""); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} Establishes a new external file, with the given name and form, and associates this external file with the given file. The given file is left open. The current mode of the given file is set to the given access mode. The default access mode is the mode Out_File for sequential@Chg{Version=[2],New=[, stream,],Old=[]} and text input-output; it is the mode Inout_File for direct input-output. For direct access, the size of the created file is implementation defined. A null string for Name specifies an external file that is not accessible after the completion of the main program (a temporary file). A null string for Form specifies the use of the default options of the implementation for the external file. @Trailing@;The exception Status_Error is propagated if the given file is already open. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file. The exception Use_Error is propagated if, for the specified mode, the external environment does not support creation of an external file with the given name (in the absence of Name_Error) and form. @begin{Example}@Keepnext @key[procedure] Open(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @end{Example} Associates the given file with an existing external file having the given name and form, and sets the current mode of the given file to the given mode. The given file is left open. @Trailing@;The exception Status_Error is propagated if the given file is already open. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file; in particular, this exception is propagated if no external file with the given name exists. The exception Use_Error is propagated if, for the specified mode, the external environment does not support opening for an external file with the given name (in the absence of Name_Error) and form. @begin{Example}@Keepnext @key[procedure] Close(File : @key[in] @key[out] File_Type); @end{Example} Severs the association between the given file and its associated external file. The given file is left closed. In addition, for sequential files, if the file being closed has mode Out_File or Append_File, then the last element written since the most recent open or reset is the last element that can be read from the file. If no elements have been written and the file mode is Out_File, then the closed file is empty. If no elements have been written and the file mode is Append_File, then the closed file is unchanged. @Trailing@;The exception Status_Error is propagated if the given file is not open. @begin{Example}@Keepnext @key[procedure] Delete(File : @key[in] @key[out] File_Type); @end{Example} Deletes the external file associated with the given file. The given file is closed, and the external file ceases to exist. @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Use_Error is propagated if deletion of the external file is not supported by the external environment. @begin{Example}@Keepnext @key[procedure] Reset(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] Reset(File : @key[in] @key[out] File_Type); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00085-01]} Resets the given file so that reading from its elements can be restarted from the beginning of the @Chg{Version=[2],New=[external ],Old=[]}file (for modes In_File and Inout_File), and so that writing to its elements can be restarted at the beginning of the @Chg{Version=[2],New=[external ],Old=[]}file (for modes Out_File and Inout_File) or after the last element of the @Chg{Version=[2],New=[external ],Old=[]}file (for mode Append_File). In particular, for direct access this means that the current index is set to one. If a Mode parameter is supplied, the current mode of the given file is set to the given mode. In addition, for sequential files, if the given file has mode Out_File or Append_File when Reset is called, the last element written since the most recent open or reset is the last element that can be read from the @Chg{Version=[2],New=[external ],Old=[]}file. If no elements have been written and the file mode is Out_File, the reset file is empty. If no elements have been written and the file mode is Append_File, then the reset file is unchanged. @Trailing@;The exception Status_Error is propagated if the file is not open. The exception Use_Error is propagated if the external environment does not support resetting for the external file and, also, if the external environment does not support resetting to the specified mode for the external file. @begin{Example}@Keepnext @key[function] Mode(File : @key[in] File_Type) @key[return] File_Mode; @end{Example} Returns the current mode of the given file. @Trailing@;The exception Status_Error is propagated if the file is not open. @begin{Example}@Keepnext @key[function] Name(File : @key[in] File_Type) @key[return] String; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00248-01]} Returns a string which uniquely identifies the external file currently associated with the given file (and may thus be used in an Open operation).@Chg{Version=[2],New=[],Old=[ If an external environment allows alternative specifications of the name (for example, abbreviations), the string returned by the function should correspond to a full specification of the name.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[Retrieving the full path can be accomplished by passing the result of Name to Directories.Full_Name (see @RefSecNum{The Package Directories}). It is important to drop the requirement on Name, as the only way to accomplish this requirement given that the current directory can be changed with package Directories is to store the full path when the file is opened. That's expensive, and it's better for users that need the full path to explicitly request it.]} @end{Discussion} @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Use_Error is propagated if the associated external file is a temporary file that cannot be opened by any name. @begin{Example}@Keepnext @key[function] Form(File : @key[in] File_Type) @key[return] String; @end{Example} Returns the form string for the external file currently associated with the given file. If an external environment allows alternative specifications of the form (for example, abbreviations using default options), the string returned by the function should correspond to a full specification (that is, it should indicate explicitly all options selected, including default options). @Trailing@;The exception Status_Error is propagated if the given file is not open. @begin{Example}@Keepnext @key[function] Is_Open(File : @key[in] File_Type) @key[return] Boolean; @end{Example} Returns True if the file is open (that is, if it is associated with an external file), otherwise returns False. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} An implementation may propagate Name_Error or Use_Error if an attempt is made to use an I/O feature that cannot be supported by the implementation due to limitations in the external environment. Any such restriction should be documented. @end{ImplPerm} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[Clarified that Reset affects and depends on the external file.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[Removed the requirement for Name to return a full path; this is now accomplished by Directories.Full_Name(Name(File)) (see @RefSecNum{The Package Directories}). This is not documented as an inconsistency, because there is no requirement for implementations to change @em the Ada 95 behavior is still allowed, it just is no longer required.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Text=[Added text to specify the default mode for a stream file.]} @end{DiffWord95} @LabeledSubClause{Sequential Input-Output Operations} @begin{StaticSem} The operations available for sequential input and output are described in this subclause. The exception Status_Error is propagated if any of these operations is attempted for a file that is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type); @end{Example} Operates on a file of mode In_File. Reads an element from the given file, and returns the value of this element in the Item parameter. @begin{Discussion} We considered basing Sequential_IO.Read on Element_Type'Read from an implicit stream associated with the sequential file. However, Element_Type'Read is a type-related attribute, whereas Sequential_IO should take advantage of the particular constraints of the actual subtype corresponding to Element_Type to minimize the size of the external file. Furthermore, forcing the implementation of Sequential_IO to be based on Element_Type'Read would create an upward incompatibility since existing data files written by an Ada 83 program using Sequential_IO might not be readable by the identical program built with an Ada 95 implementation of Sequential_IO. An Ada 95 implementation might still use an implementation-defined attribute analogous to 'Read to implement the procedure Read, but that attribute will likely have to be subtype-specific rather than type-related, and it need not be user-specifiable. Such an attribute will presumably be needed to implement the generic package Storage_IO (see @RefSecNum{The Generic Package Storage_IO}). @end{Discussion} @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if no more elements can be read from the given file. The exception Data_Error can be propagated if the element read cannot be interpreted as a value of the subtype Element_Type (see @RefSec{Exceptions in Input-Output}). @begin{Discussion} Data_Error need not be propagated if the check is too complex. See @RefSec{Exceptions in Input-Output}. @end{Discussion} @begin{Example}@Keepnext @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type); @end{Example} Operates on a file of mode Out_File or Append_File. Writes the value of Item to the given file. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. The exception Use_Error is propagated if the capacity of the external file is exceeded. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @end{Example} Operates on a file of mode In_File. Returns True if no more elements can be read from the given file; otherwise returns False. The exception Mode_Error is propagated if the mode is not In_File. @end{DescribeCode} @end{StaticSem} @LabeledSubClause{The Generic Package Direct_IO} @begin{StaticSem} @Leading@;The generic library package Direct_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[generic] @key[type] Element_Type @key[is] @key[private]; @key[package] Ada.Direct_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Direct_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Inout_File, Out_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; --@RI{ File management} @key[procedure] @AdaSubDefn{Create}(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Inout_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete}(File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type; From : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write}(File : @key[in] File_Type; Item : @key[in] Element_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Write}(File : @key[in] File_Type; Item : @key[in] Element_Type); @key[procedure] @AdaSubDefn{Set_Index}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Index}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Size} (File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @keepnext --@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Direct_IO; @end{Example} @begin{Reason} The Element_Type formal of Direct_IO does not have an @nt{unknown_discriminant_part} (unlike Sequential_IO) so that the implementation can make use of the ability to declare uninitialized variables of the type. @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}) in every instantiation of Direct_IO.]} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[File_Type cannot be implemented as a (directly) controlled type, as Ada.Direct_IO can be instantiated at any nesting depth. File_Type could have a component of a controlled type, as long as that type is declared in some other (non-generic) package.],Old=[]}]} @end{ImplNote} @end{StaticSem} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] File_Type in an instance of Direct_IO is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @LabeledSubClause{Direct Input-Output Operations} @begin{StaticSem} The operations available for direct input and output are described in this subclause. The exception Status_Error is propagated if any of these operations is attempted for a file that is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type; From : @key[in] Positive_Count); @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type); @end{Example} Operates on a file of mode In_File or Inout_File. In the case of the first form, sets the current index of the given file to the index value given by the parameter From. Then (for both forms) returns, in the parameter Item, the value of the element whose position in the given file is specified by the current index of the file; finally, increases the current index by one. @Trailing@;The exception Mode_Error is propagated if the mode of the given file is Out_File. The exception End_Error is propagated if the index to be used exceeds the size of the external file. The exception Data_Error can be propagated if the element read cannot be interpreted as a value of the subtype Element_Type (see @RefSecNum{Exceptions in Input-Output}). @begin{Example}@Keepnext @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type; To : @key[in] Positive_Count); @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type); @end{Example} Operates on a file of mode Inout_File or Out_File. In the case of the first form, sets the index of the given file to the index value given by the parameter To. Then (for both forms) gives the value of the parameter Item to the element whose position in the given file is specified by the current index of the file; finally, increases the current index by one. @Trailing@;The exception Mode_Error is propagated if the mode of the given file is In_File. The exception Use_Error is propagated if the capacity of the external file is exceeded. @begin{Example}@Keepnext @key[procedure] Set_Index(File : @key[in] File_Type; To : @key[in] Positive_Count); @end{Example} @Trailing@;Operates on a file of any mode. Sets the current index of the given file to the given index value (which may exceed the current size of the file). @begin{Example}@Keepnext @key[function] Index(File : @key[in] File_Type) @key[return] Positive_Count; @end{Example} @Trailing@;Operates on a file of any mode. Returns the current index of the given file. @begin{Example}@Keepnext @key[function] Size(File : @key[in] File_Type) @key[return] Count; @end{Example} @Trailing@;Operates on a file of any mode. Returns the current size of the external file that is associated with the given file. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @end{Example} Operates on a file of mode In_File or Inout_File. Returns True if the current index exceeds the size of the external file; otherwise returns False. The exception Mode_Error is propagated if the mode of the given file is Out_File. @end{DescribeCode} @end{StaticSem} @begin{Notes} Append_File mode is not supported for the generic package Direct_IO. @end{Notes} @LabeledClause{The Generic Package Storage_IO} @begin{Intro} The generic package Storage_IO provides for reading from and writing to an in-memory buffer. This generic package supports the construction of user-defined input-output packages. @begin{Reason} This package exists to allow the portable construction of user-defined direct-access-oriented input-output packages. The Write procedure writes a value of type Element_Type into a Storage_Array of size Buffer_Size, flattening out any implicit levels of indirection used in the representation of the type. The Read procedure reads a value of type Element_Type from the buffer, reconstructing any implicit levels of indirection used in the representation of the type. It also properly initializes any type tags that appear within the value, presuming that the buffer was written by a different program and that tag values for the@lquotes@;same@rquotes@; type might vary from one executable to another. @end{Reason} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Storage_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[with] System.Storage_Elements; @key[generic] @key[type] Element_Type @key[is] @key[private]; @key[package] Ada.Storage_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Storage_IO]} @key[pragma] Preelaborate(Storage_IO); @AdaObjDefn{Buffer_Size} : @key(constant) System.Storage_Elements.Storage_Count := @RI(implementation-defined); @key(subtype) @AdaSubtypeDefn{Name=[Buffer_Type],Of=[Storage_Array]} @key(is) System.Storage_Elements.Storage_Array(1..Buffer_Size); --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (Buffer : @key[in] Buffer_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write}(Buffer : @key[out] Buffer_Type; Item : @key[in] Element_Type); @keepnext --@RI{ Exceptions} @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[end] Ada.Storage_IO; @end{Example} In each instance, the constant Buffer_Size has a value that is the size (in storage elements) of the buffer required to represent the content of an object of subtype Element_Type, including any implicit levels of indirection used by the implementation. The Read and Write procedures of Storage_IO correspond to the Read and Write procedures of Direct_IO (see @RefSecNum{The Generic Package Direct_IO}), but with the content of the Item parameter being read from or written into the specified Buffer, rather than an external file. @begin{Reason} @Leading@;As with Direct_IO, the Element_Type formal of Storage_IO does not have an @nt{unknown_discriminant_part} so that there is a well-defined upper bound on the size of the buffer needed to hold the content of an object of the formal subtype (i.e. Buffer_Size). If there are no implicit levels of indirection, Buffer_Size will typically equal: @begin{Example} (Element_Type'Size + System.Storage_Unit - 1) / System.Storage_Unit @end{Example} @end{Reason} @ImplDef{The value of Buffer_Size in Storage_IO.} @end{StaticSem} @begin{Notes} A buffer used for Storage_IO holds only one element at a time; an external file used for Direct_IO holds a sequence of elements. @end{Notes} @LabeledClause{Text Input-Output} @begin{StaticSem} This clause describes the package Text_IO, which provides facilities for input and output in human-readable form. Each file is read or written sequentially, as a sequence of characters grouped into lines, and as a sequence of lines grouped into pages. The specification of the package is given below in subclause @RefSecNum{The Package Text_IO}. The facilities for file management given above, in subclauses @RefSecNum{File Management} and @RefSecNum{Sequential Input-Output Operations}, are available for text input-output. In place of Read and Write, however, there are procedures Get and Put that input values of suitable types from text files, and output values to them. These values are provided to the Put procedures, and returned by the Get procedures, in a parameter Item. Several overloaded procedures of these names exist, for different types of Item. These Get procedures analyze the input sequences of characters based on lexical elements (see Section 2) and return the corresponding values; the Put procedures output the given values as appropriate lexical elements. Procedures Get and Put are also available that input and output individual characters treated as character values rather than as lexical elements. Related to character input are procedures to look ahead at the next character without reading it, and to read a character @lquotes@;immediately@rquotes@; without waiting for an end-of-line to signal availability. In addition to the procedures Get and Put for numeric and enumeration types of Item that operate on text files, analogous procedures are provided that read from and write to a parameter of type String. These procedures perform the same analysis and composition of character sequences as their counterparts which have a file parameter. For all Get and Put procedures that operate on text files, and for many other subprograms, there are forms with and without a file parameter. Each such Get procedure operates on an input file, and each such Put procedure operates on an output file. If no file is specified, a default input file or a default output file is used. @Defn{standard input file} @Defn{standard output file} At the beginning of program execution the default input and output files are the so-called standard input file and standard output file. These files are open, have respectively the current modes In_File and Out_File, and are associated with two implementation-defined external files. Procedures are provided to change the current default input file and the current default output file. @ChgNote{The following was poorly formatted.} @ChgImplDef{Version=[2],Kind=[Revised],Text=[@Chg{Version=[2],New=[The ], Old=[]}external files @Chg{Version=[2],New=[associated with the],Old=[for]} standard input, standard output, and standard error@Chg{Version=[2],New=[ files.],Old=[]}]} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0113],ARef=[AI95-00087-01]} @ChgAdded{Version=[1],Text=[The default input file and default output file are not the names of distinct file objects, but rather the @i<role> played by one or more (other) file object(s). Thus, they generally will be implemented as accesses to another file object. An implementation that implements them by copying them is incorrect.]} @end{ImplNote} @Defn{standard error file} At the beginning of program execution a default file for program-dependent error-related text output is the so-called standard error file. This file is open, has the current mode Out_File, and is associated with an implementation-defined external file. A procedure is provided to change the current default error file. @Defn{line terminator} @Defn{page terminator} @Defn{file terminator} From a logical point of view, a text file is a sequence of pages, a page is a sequence of lines, and a line is a sequence of characters; the end of a line is marked by a @i{line terminator}; the end of a page is marked by the combination of a line terminator immediately followed by a @i{page terminator}; and the end of a file is marked by the combination of a line terminator immediately followed by a page terminator and then a @i{file terminator}. Terminators are generated during output; either by calls of procedures provided expressly for that purpose; or implicitly as part of other operations, for example, when a bounded line length, a bounded page length, or both, have been specified for a file. The actual nature of terminators is not defined by the language and hence depends on the implementation. Although terminators are recognized or generated by certain of the procedures that follow, they are not necessarily implemented as characters or as sequences of characters. Whether they are characters (and if so which ones) in any particular implementation need not concern a user who neither explicitly outputs nor explicitly inputs control characters. The effect of input (Get) or output (Put) of control characters (other than horizontal tabulation) is not specified by the language. @PDefn{unspecified} @Defn{column number} @Defn{current column number} @Defn{current line number} @Defn{current page number} The characters of a line are numbered, starting from one; the number of a character is called its @i{column number}. For a line terminator, a column number is also defined: it is one more than the number of characters in the line. The lines of a page, and the pages of a file, are similarly numbered. The current column number is the column number of the next character or line terminator to be transferred. The current line number is the number of the current line. The current page number is the number of the current page. These numbers are values of the subtype Positive_Count of the type Count (by convention, the value zero of the type Count is used to indicate special conditions). @begin{Example} @Trailing@key[type] Count @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] Positive_Count @key[is] Count @key[range] 1 .. Count'Last; @end{Example} @Defn{maximum line length} @Defn{maximum page length} For an output file or an append file, a @i{maximum line length} can be specified and a @i{maximum page length} can be specified. If a value to be output cannot fit on the current line, for a specified maximum line length, then a new line is automatically started before the value is output; if, further, this new line cannot fit on the current page, for a specified maximum page length, then a new page is automatically started before the value is output. Functions are provided to determine the maximum line length and the maximum page length. When a file is opened with mode Out_File or Append_File, both values are zero: by convention, this means that the line lengths and page lengths are unbounded. (Consequently, output consists of a single line if the subprograms for explicit control of line and page structure are not used.) The constant Unbounded is provided for this purpose. @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} Append_File is new in Ada 95. @end{Extend83} @LabeledSubClause{The Package Text_IO} @begin{StaticSem} @Leading@;The library package Text_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[package] Ada.Text_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Text_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Out_File, Append_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; @AdaObjDefn{Unbounded} : @key[constant] Count := 0; --@RI{ line and page length} @key[subtype] @AdaSubtypeDefn{Name=[Field],Of=[Integer]} @key[is] Integer @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Number_Base],Of=[Integer]} @key[is] Integer @key[range] 2 .. 16; @key[type] @AdaTypeDefn{Type_Set} @key[is] (Lower_Case, Upper_Case); --@RI{ File Management} @key[procedure] @AdaSubDefn{Create} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Out_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Control of default input and output files} @key[procedure] @AdaSubDefn{Set_Input} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Set_Output}(File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Set_Error} (File : @key[in] File_Type); @key[function] @AdaSubDefn{Standard_Input} @key[return] File_Type; @key[function] @AdaSubDefn{Standard_Output} @key[return] File_Type; @key[function] @AdaSubDefn{Standard_Error} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Input} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Output} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Error} @key[return] File_Type; @key[type] @AdaTypeDefn{File_Access} @key[is] @key[access] @key[constant] File_Type; @key[function] @AdaSubDefn{Standard_Input} @key[return] File_Access; @key[function] @AdaSubDefn{Standard_Output} @key[return] File_Access; @key[function] @AdaSubDefn{Standard_Error} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Input} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Output} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Error} @key[return] File_Access; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]} --@RI{Buffer control} @key[procedure] @AdaSubDefn{Flush} (File : @key[in] @Chg{New=[],Old=[@key[out] ]}File_Type); @key[procedure] @AdaSubDefn{Flush}; --@RI{ Specification of line and page lengths} @key[procedure] @AdaSubDefn{Set_Line_Length}(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Line_Length}(To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Page_Length}(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Page_Length}(To : @key[in] Count); @key[function] @AdaSubDefn{Line_Length}(File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{Line_Length} @key[return] Count; @key[function] @AdaSubDefn{Page_Length}(File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{Page_Length} @key[return] Count; --@RI{ Column, Line, and Page Control} @key[procedure] @AdaSubDefn{New_Line} (File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{New_Line} (Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{Skip_Line} (File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{Skip_Line} (Spacing : @key[in] Positive_Count := 1); @key[function] @AdaSubDefn{End_Of_Line}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_Line} @key[return] Boolean; @key[procedure] @AdaSubDefn{New_Page} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{New_Page}; @key[procedure] @AdaSubDefn{Skip_Page} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Skip_Page}; @key[function] @AdaSubDefn{End_Of_Page}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_Page} @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_File} @key[return] Boolean; @key[procedure] @AdaSubDefn{Set_Col} (File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Col} (To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Line}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Line}(To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Col} (File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Col} @key[return] Positive_Count; @key[function] @AdaSubDefn{Line}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Line} @key[return] Positive_Count; @key[function] @AdaSubDefn{Page}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Page} @key[return] Positive_Count; --@RI{ Character Input-Output} @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Character); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Character); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Character); @key[procedure] @AdaSubDefn{Look_Ahead} (File : @key[in] File_Type; Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] @AdaSubDefn{Look_Ahead} (Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] @AdaSubDefn{Get_Immediate}(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get_Immediate}(Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get_Immediate}(File : @key[in] File_Type; Item : @key[out] Character; Available : @key[out] Boolean); @key[procedure] @AdaSubDefn{Get_Immediate}(Item : @key[out] Character; Available : @key[out] Boolean); --@RI{ String Input-Output} @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] String); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] String); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] String); @key[procedure] @AdaSubDefn{Get_Line}(File : @key[in] File_Type; Item : @key[out] String; Last : @key[out] Natural); @key[procedure] @AdaSubDefn{Get_Line}(Item : @key[out] String; Last : @key[out] Natural); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Get_Line}(File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Get_Line} @key[return] String;]} @key[procedure] @AdaSubDefn{Put_Line}(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] @AdaSubDefn{Put_Line}(Item : @key[in] String); --@RI{ Generic packages for Input-Output of Integer Types} @key[generic] @key[type] Num @key[is] @key[range] <>; @key[package] @AdaPackDefn{Integer_IO} @key[is] @AdaObjDefn{Default_Width} : Field := Num'Width; @AdaObjDefn{Default_Base} : Number_Base := 10; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @key[end] Integer_IO; @key[generic] @key[type] Num @key[is] @key[mod] <>; @key[package] @AdaPackDefn{Modular_IO} @key[is] @AdaObjDefn{Default_Width} : Field := Num'Width; @AdaObjDefn{Default_Base} : Number_Base := 10; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @key[end] Modular_IO; --@RI{ Generic packages for Input-Output of Real Types} @key[generic] @key[type] Num @key[is] @key[digits] <>; @key[package] @AdaPackDefn{Float_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := 2; @AdaObjDefn{Default_Aft} : Field := Num'Digits-1; @AdaObjDefn{Default_Exp} : Field := 3; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Float_IO; @key[generic] @key[type] Num @key[is] @key[delta] <>; @key[package] @AdaPackDefn{Fixed_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := Num'Fore; @AdaObjDefn{Default_Aft} : Field := Num'Aft; @AdaObjDefn{Default_Exp} : Field := 0; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Fixed_IO; @key[generic] @key[type] Num @key[is] @key[delta] <> @key[digits] <>; @key[package] @AdaPackDefn{Decimal_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := Num'Fore; @AdaObjDefn{Default_Aft} : Field := Num'Aft; @AdaObjDefn{Default_Exp} : Field := 0; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Decimal_IO; --@RI{ Generic package for Input-Output of Enumeration Types} @key[generic] @key[type] Enum @key[is] (<>); @key[package] @AdaPackDefn{Enumeration_IO} @key[is] @AdaObjDefn{Default_Width} : Field := 0; @AdaObjDefn{Default_Setting} : Type_Set := Upper_Case; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Enum); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Enum); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Enum; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Enum; Set : @key[in] Type_Set := Default_Setting); @key[end] Enumeration_IO; @keepnext@;--@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @AdaExcDefn{Layout_Error} : @key[exception] @key[renames] IO_Exceptions.Layout_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Text_IO; @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Append_File is a new element of enumeration type File_Mode. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Get_Immediate, Look_Ahead, the subprograms for dealing with standard error, the type File_Access and its associated subprograms, and the generic packages Modular_IO and Decimal_IO are new in Ada 95. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] Text_IO.File_Type is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The Text_IO.Get_Line functions are new; they are described in @RefSec{Input-Output of Characters and Strings}.]} @end{DiffWord95} @LabeledSubClause{Text File Management} @begin{StaticSem} @Leading@;The only allowed file modes for text files are the modes In_File, Out_File, and Append_File. The subprograms given in subclause @RefSecNum{File Management} for the control of external files, and the function End_Of_File given in subclause @RefSecNum{Sequential Input-Output Operations} for sequential input-output, are also available for text files. There is also a version of End_Of_File that refers to the current default input file. For text files, the procedures have the following additional effects: @begin{Itemize} For the procedures Create and Open: After a file with mode Out_File or Append_File is opened, the page length and line length are unbounded (both have the conventional value zero). After a file (of any mode) is opened, the current column, current line, and current page numbers are set to one. If the mode is Append_File, it is implementation defined whether a page terminator will separate preexisting text in the file from the new text to be written. @begin{Reason} For a file with mode Append_File, although it may seem more sensible for Open to set the current column, line, and page number based on the number of pages in the file, the number of lines on the last page, and the number of columns in the last line, we rejected this approach because of implementation costs; it would require the implementation to scan the file before doing the append, or to do processing that would be equivalent in effect. For similar reasons, there is no requirement to erase the last page terminator of the file, nor to insert an explicit page terminator in the case when the final page terminator of a file is represented implicitly by the implementation. @end{Reason} For the procedure Close: If the file has the current mode Out_File or Append_File, has the effect of calling New_Page, unless the current page is already terminated; then outputs a file terminator. For the procedure Reset: If the file has the current mode Out_File or Append_File, has the effect of calling New_Page, unless the current page is already terminated; then outputs a file terminator. The current column, line, and page numbers are set to one, and the line and page lengths to Unbounded. If the new mode is Append_File, it is implementation defined whether a page terminator will separate preexisting text in the file from the new text to be written. @begin{Reason} The behavior of Reset should be similar to closing a file and reopening it with the given mode@end{reason} @end{Itemize} The exception Mode_Error is propagated by the procedure Reset upon an attempt to change the mode of a file that is the current default input file, the current default output file, or the current default error file. @end{StaticSem} @begin{Notes} @Leading@;An implementation can define the Form parameter of Create and Open to control effects including the following: @begin{itemize} the interpretation of line and column numbers for an interactive file, and the interpretation of text formats in a file created by a foreign program. @end{itemize} @end{Notes} @LabeledSubClause{Default Input, Output, and Error Files} @begin{StaticSem} The following subprograms provide for the control of the particular default files that are used when a file parameter is omitted from a Get, Put, or other operation of text input-output described below, or when application-dependent error-related text is to be output. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Input(File : @key[in] File_Type); @end{Example} Operates on a file of mode In_File. Sets the current default input file to File. @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Mode_Error is propagated if the mode of the given file is not In_File. @begin{Example}@Keepnext @key[procedure] Set_Output(File : @key[in] File_Type); @key[procedure] Set_Error (File : @key[in] File_Type); @end{Example} @Trailing@;Each operates on a file of mode Out_File or Append_File. Set_Output sets the current default output file to File. Set_Error sets the current default error file to File. The exception Status_Error is propagated if the given file is not open. The exception Mode_Error is propagated if the mode of the given file is not Out_File or Append_File. @begin{Example}@Keepnext @key[function] Standard_Input @key[return] File_Type; @key[function] Standard_Input @key[return] File_Access; @end{Example} @Trailing@;Returns the standard input file (see @RefSecNum{Text Input-Output}), or an access value designating the standard input file, respectively. @begin{Example}@Keepnext @key[function] Standard_Output @key[return] File_Type; @key[function] Standard_Output @key[return] File_Access; @end{Example} @Trailing@;Returns the standard output file (see @RefSecNum{Text Input-Output}) or an access value designating the standard output file, respectively. @begin{Example}@Keepnext @key[function] Standard_Error @key[return] File_Type; @key[function] Standard_Error @key[return] File_Access; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0052],ARef=[AI95-00194-01]} @Trailing@;Returns the standard error file (see @RefSecNum{Text Input-Output}), or an access value designating the standard @Chg{New=[error],Old=[output]} file, respectively. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} @Trailing@;The Form strings implicitly associated with the opening of Standard_Input, Standard_Output, and Standard_Error at the start of program execution are implementation defined. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Current_Input @key[return] File_Type; @key[function] Current_Input @key[return] File_Access; @end{Example} @Trailing@;Returns the current default input file, or an access value designating the current default input file, respectively. @begin{Example}@Keepnext @key[function] Current_Output @key[return] File_Type; @key[function] Current_Output @key[return] File_Access; @end{Example} @Trailing@;Returns the current default output file, or an access value designating the current default output file, respectively. @begin{Example}@Keepnext @key[function] Current_Error @key[return] File_Type; @key[function] Current_Error @key[return] File_Access; @end{Example} @Trailing@;Returns the current default error file, or an access value designating the current default error file, respectively. @begin{Example}@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]}@Keepnext @key[procedure] Flush (File : @key[in] @Chg{New=[],Old=[@key[out] ]}File_Type); @key[procedure] Flush; @end{Example} The effect of Flush is the same as the corresponding subprogram in Streams.Stream_IO (see @RefSecNum[The Package Streams.Stream_IO]). If File is not explicitly specified, Current_Output is used. @end{DescribeCode} @end{StaticSem} @begin{Erron} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0053],ARef=[AI95-00063-01]} @PDefn2{Term=(erroneous execution),Sec=(cause)} The execution of a program is erroneous if it @Chg{New=[invokes an operation on], Old=[attempts to use]} a current default input, default output, or default error file@Chg{New=[, and if the corresponding file object is closed or],Old=[ that]} no longer exists. @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgAdded{Version=[1],Text=[Closing a default file, then setting the default file to another open file before accessing it is not erroneous.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgDeleted{Version=[1],Text=[If the Close operation is applied to a file object that is also serving as the default input, default output, or default error file, then subsequent operations on such a default file are erroneous.]} @end{Erron} @begin{Notes} The standard input, standard output, and standard error files cannot be opened, closed, reset, or deleted, because the parameter File of the corresponding procedures has the mode @key[in] @key[out]. The standard input, standard output, and standard error files are different file objects, but not necessarily different external files. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0052],ARef=[AI95-00194-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected Standard_Error so it refers to the correct file.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that execution is erroneous only when a closed default file is accessed.]} @end{DiffWord95} @LabeledSubClause{Specification of Line and Page Lengths} @begin{StaticSem} The subprograms described in this subclause are concerned with the line and page structure of a file of mode Out_File or Append_File. They operate either on the file given as the first parameter, or, in the absence of such a file parameter, on the current default output file. They provide for output of text with a specified maximum line length or page length. In these cases, line and page terminators are output implicitly and automatically when needed. When line and page lengths are unbounded (that is, when they have the conventional value zero), as in the case of a newly opened file, new lines and new pages are only started when explicitly called for. In all cases, the exception Status_Error is propagated if the file to be used is not open; the exception Mode_Error is propagated if the mode of the file is not Out_File or Append_File. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Line_Length(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] Set_Line_Length(To : @key[in] Count); @end{Example} Sets the maximum line length of the specified output or append file to the number of characters specified by To. The value zero for To specifies an unbounded line length. @begin{Ramification} The setting does not affect the lengths of lines in the existing file, rather it only influences subsequent output operations.@end{ramification} @Trailing@;The exception Use_Error is propagated if the specified line length is inappropriate for the associated external file. @begin{Example}@Keepnext @key[procedure] Set_Page_Length(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] Set_Page_Length(To : @key[in] Count); @end{Example} Sets the maximum page length of the specified output or append file to the number of lines specified by To. The value zero for To specifies an unbounded page length. @Trailing@;The exception Use_Error is propagated if the specified page length is inappropriate for the associated external file. @begin{Example}@Keepnext @key[function] Line_Length(File : @key[in] File_Type) @key[return] Count; @key[function] Line_Length @key[return] Count; @end{Example} @Trailing@;Returns the maximum line length currently set for the specified output or append file, or zero if the line length is unbounded. @begin{Example}@Keepnext @key[function] Page_Length(File : @key[in] File_Type) @key[return] Count; @key[function] Page_Length @key[return] Count; @end{Example} Returns the maximum page length currently set for the specified output or append file, or zero if the page length is unbounded. @end{DescribeCode} @end{StaticSem} @LabeledSubClause{Operations on Columns, Lines, and Pages} @begin{StaticSem} The subprograms described in this subclause provide for explicit control of line and page structure; they operate either on the file given as the first parameter, or, in the absence of such a file parameter, on the appropriate (input or output) current default file. The exception Status_Error is propagated by any of these subprograms if the file to be used is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] New_Line(File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] New_Line(Spacing : @key[in] Positive_Count := 1); @end{Example} Operates on a file of mode Out_File or Append_File. For a Spacing of one: Outputs a line terminator and sets the current column number to one. Then increments the current line number by one, except in the case that the current line number is already greater than or equal to the maximum page length, for a bounded page length; in that case a page terminator is output, the current page number is incremented by one, and the current line number is set to one. For a Spacing greater than one, the above actions are performed Spacing times. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. @begin{Example}@Keepnext @key[procedure] Skip_Line(File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] Skip_Line(Spacing : @key[in] Positive_Count := 1); @end{Example} Operates on a file of mode In_File. For a Spacing of one: Reads and discards all characters until a line terminator has been read, and then sets the current column number to one. If the line terminator is not immediately followed by a page terminator, the current line number is incremented by one. Otherwise, if the line terminator is immediately followed by a page terminator, then the page terminator is skipped, the current page number is incremented by one, and the current line number is set to one. For a Spacing greater than one, the above actions are performed Spacing times. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if an attempt is made to read a file terminator. @begin{Example}@Keepnext @key[function] End_Of_Line(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_Line @key[return] Boolean; @end{Example} Operates on a file of mode In_File. Returns True if a line terminator or a file terminator is next; otherwise returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @begin{Example}@Keepnext @key[procedure] New_Page(File : @key[in] File_Type); @key[procedure] New_Page; @end{Example} Operates on a file of mode Out_File or Append_File. Outputs a line terminator if the current line is not terminated, or if the current page is empty (that is, if the current column and line numbers are both equal to one). Then outputs a page terminator, which terminates the current page. Adds one to the current page number and sets the current column and line numbers to one. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. @begin{Example}@Keepnext @key[procedure] Skip_Page(File : @key[in] File_Type); @key[procedure] Skip_Page; @end{Example} Operates on a file of mode In_File. Reads and discards all characters and line terminators until a page terminator has been read. Then adds one to the current page number, and sets the current column and line numbers to one. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if an attempt is made to read a file terminator. @begin{Example}@Keepnext @key[function] End_Of_Page(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_Page @key[return] Boolean; @end{Example} Operates on a file of mode In_File. Returns True if the combination of a line terminator and a page terminator is next, or if a file terminator is next; otherwise returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_File @key[return] Boolean; @end{Example} Operates on a file of mode In_File. Returns True if a file terminator is next, or if the combination of a line, a page, and a file terminator is next; otherwise returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} The following subprograms provide for the control of the current position of reading or writing in a file. In all cases, the default file is the current output file. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Col(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] Set_Col(To : @key[in] Positive_Count); @end{Example} @Leading@;If the file mode is Out_File or Append_File: @begin{itemize} If the value specified by To is greater than the current column number, outputs spaces, adding one to the current column number after each space, until the current column number equals the specified value. If the value specified by To is equal to the current column number, there is no effect. If the value specified by To is less than the current column number, has the effect of calling New_Line (with a spacing of one), then outputs (To @en 1) spaces, and sets the current column number to the specified value. The exception Layout_Error is propagated if the value specified by To exceeds Line_Length when the line length is bounded (that is, when it does not have the conventional value zero). @end{itemize} @Leading@;If the file mode is In_File: @begin{itemize} Reads (and discards) individual characters, line terminators, and page terminators, until the next character to be read has a column number that equals the value specified by To; there is no effect if the current column number already equals this value. Each transfer of a character or terminator maintains the current column, line, and page numbers in the same way as a Get procedure (see @RefSecNum{Get and Put Procedures}). (Short lines will be skipped until a line is reached that has a character at the specified column position.) @Trailing@;The exception End_Error is propagated if an attempt is made to read a file terminator. @end{itemize} @begin{Example}@Keepnext @key[procedure] Set_Line(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] Set_Line(To : @key[in] Positive_Count); @end{Example} @Leading@;If the file mode is Out_File or Append_File: @begin{itemize} If the value specified by To is greater than the current line number, has the effect of repeatedly calling New_Line (with a spacing of one), until the current line number equals the specified value. If the value specified by To is equal to the current line number, there is no effect. If the value specified by To is less than the current line number, has the effect of calling New_Page followed by a call of New_Line with a spacing equal to (To @en 1). The exception Layout_Error is propagated if the value specified by To exceeds Page_Length when the page length is bounded (that is, when it does not have the conventional value zero). @end{itemize} @Leading@;If the mode is In_File: @begin{itemize} Has the effect of repeatedly calling Skip_Line (with a spacing of one), until the current line number equals the value specified by To; there is no effect if the current line number already equals this value. (Short pages will be skipped until a page is reached that has a line at the specified line position.) @Trailing@;The exception End_Error is propagated if an attempt is made to read a file terminator. @end{itemize} @begin{Example}@Keepnext @key[function] Col(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Col @key[return] Positive_Count; @end{Example} Returns the current column number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @begin{Example}@Keepnext @key[function] Line(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Line @key[return] Positive_Count; @end{Example} Returns the current line number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @begin{Example}@Keepnext @key[function] Page(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Page @key[return] Positive_Count; @end{Example} Returns the current page number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @end{DescribeCode} The column number, line number, or page number are allowed to exceed Count'Last (as a consequence of the input or output of sufficiently many characters, lines, or pages). These events do not cause any exception to be propagated. However, a call of Col, Line, or Page propagates the exception Layout_Error if the corresponding number exceeds Count'Last. @end{StaticSem} @begin{Notes} A page terminator is always skipped whenever the preceding line terminator is skipped. An implementation may represent the combination of these terminators by a single character, provided that it is properly recognized on input. @end{Notes} @LabeledSubClause{Get and Put Procedures} @begin{StaticSem} The procedures Get and Put for items of the type Character, String, numeric types, and enumeration types are described in subsequent subclauses. Features of these procedures that are common to most of these types are described in this subclause. The Get and Put procedures for items of type Character and String deal with individual character values; the Get and Put procedures for numeric and enumeration types treat the items as lexical elements. All procedures Get and Put have forms with a file parameter, written first. Where this parameter is omitted, the appropriate (input or output) current default file is understood to be specified. Each procedure Get operates on a file of mode In_File. Each procedure Put operates on a file of mode Out_File or Append_File. All procedures Get and Put maintain the current column, line, and page numbers of the specified file: the effect of each of these procedures upon these numbers is the result of the effects of individual transfers of characters and of individual output or skipping of terminators. Each transfer of a character adds one to the current column number. Each output of a line terminator sets the current column number to one and adds one to the current line number. Each output of a page terminator sets the current column and line numbers to one and adds one to the current page number. For input, each skipping of a line terminator sets the current column number to one and adds one to the current line number; each skipping of a page terminator sets the current column and line numbers to one and adds one to the current page number. Similar considerations apply to the procedures Get_Line, Put_Line, and Set_Col. Several Get and Put procedures, for numeric and enumeration types, have @i{format} parameters which specify field lengths; these parameters are of the nonnegative subtype Field of the type Integer. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00223-01]} @Defn2{Term=[blank], Sec=(in text input for enumeration and numeric types)} Input-output of enumeration values uses the syntax of the corresponding lexical elements. Any Get procedure for an enumeration type begins by skipping any leading blanks, or line or page terminators. @Chg{Version=[2], New=[A],Old=[Get procedures for numeric or enumeration types start by skipping leading blanks, where a]} @i{blank} is defined as a space or a horizontal tabulation character. Next, characters are input only so long as the sequence input is an initial sequence of an identifier or of a character literal (in particular, input ceases when a line terminator is encountered). The character or line terminator that causes input to cease remains available for subsequent input. For a numeric type, the Get procedures have a format parameter called Width. If the value given for this parameter is zero, the Get procedure proceeds in the same manner as for enumeration types, but using the syntax of numeric literals instead of that of enumeration literals. If a nonzero value is given, then exactly Width characters are input, or the characters up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. The syntax used for numeric literals is an extended syntax that allows a leading sign (but no intervening blanks, or line or page terminators) and that also allows (for real types) an integer literal as well as forms that have digits only before the point or only after the point. Any Put procedure, for an item of a numeric or an enumeration type, outputs the value of the item as a numeric literal, identifier, or character literal, as appropriate. This is preceded by leading spaces if required by the format parameters Width or Fore (as described in later subclauses), and then a minus sign for a negative value; for an enumeration type, the spaces follow instead of leading. The format given for a Put procedure is overridden if it is insufficiently wide, by using the minimum needed width. Two further cases arise for Put procedures for numeric and enumeration types, if the line length of the specified output file is bounded (that is, if it does not have the conventional value zero). If the number of characters to be output does not exceed the maximum line length, but is such that they cannot fit on the current line, starting from the current column, then (in effect) New_Line is called (with a spacing of one) before output of the item. Otherwise, if the number of characters exceeds the maximum line length, then the exception Layout_Error is propagated and nothing is output. The exception Status_Error is propagated by any of the procedures Get, Get_Line, Put, and Put_Line if the file to be used is not open. The exception Mode_Error is propagated by the procedures Get and Get_Line if the mode of the file to be used is not In_File; and by the procedures Put and Put_Line, if the mode is not Out_File or Append_File. The exception End_Error is propagated by a Get procedure if an attempt is made to skip a file terminator. The exception Data_Error is propagated by a Get procedure if the sequence finally input is not a lexical element corresponding to the type, in particular if no characters were input; for this test, leading blanks are ignored; for an item of a numeric type, when a sign is input, this rule applies to the succeeding numeric literal. The exception Layout_Error is propagated by a Put procedure that outputs to a parameter of type String, if the length of the actual string is insufficient for the output of the item. @end{StaticSem} @begin{Examples} In the examples, here and in subclauses @RefSecNum{Input-Output for Integer Types} and @RefSecNum{Input-Output for Real Types}, the string quotes and the lower case letter b are not transferred: they are shown only to reveal the layout and spaces. @begin{Example} N : Integer; ... Get(N); @tabclear()@tabset(P4, P22, P38) @RI[-- @\Characters at input @\Sequence input @\Value of N] @Comment{Blank line.} @RI[-- @\bb@en@|12535b @\@en@|12535 @\@en@|12535] @RI[-- @\bb12_535e1b @\12_535e1 @\125350] @RI[-- @\bb12_535e; @\12_535e @\(none) Data_Error raised] @end{Example} @begin{Wide} @Leading@;Example of overridden width parameter: @end{Wide} @begin{Example} Put(Item => -23, Width => 2); --@RI{ "@en@|23"} @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00223-01]} @ChgAdded{Version=[2],Text=[Removed conflicting text describing the skipping of blanks for a Get procedure.]} @end{DiffWord95} @LabeledSubClause{Input-Output of Characters and Strings} @begin{StaticSem} @Leading@Keepnext@;For an item of type Character the following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] Get(Item : @key[out] Character); @end{Example} After skipping any line terminators and any page terminators, reads the next character from the specified input file and returns the value of this character in the out parameter Item. @Trailing@;The exception End_Error is propagated if an attempt is made to skip a file terminator. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Character); @key[procedure] Put(Item : @key[in] Character); @end{Example} @Trailing@;If the line length of the specified output file is bounded (that is, does not have the conventional value zero), and the current column number exceeds it, has the effect of calling New_Line with a spacing of one. Then, or otherwise, outputs the given character to the file. @begin{Example}@Keepnext @key[procedure] Look_Ahead (File : @key[in] File_Type; Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] Look_Ahead (Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @end{Example} @Trailing@ChgRef{Version=[1],Kind=[Revised]}Mode_Error is propagated if the mode of the file is not In_File. Sets End_Of_Line to True if at end of line, including if at end of page or at end of file; in each of these cases the value of Item is not specified. @PDefn{unspecified} Otherwise End_Of_Line is set to False and Item is set to @Chg{New=[],Old=[the ]}the next character (without consuming it) from the file. @begin{Example}@Keepnext @key[procedure] Get_Immediate(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] Get_Immediate(Item : @key[out] Character); @end{Example} @Trailing@;Reads the next character, either control or graphic, from the specified File or the default input file. Mode_Error is propagated if the mode of the file is not In_File. End_Error is propagated if at the end of the file. The current column, line and page numbers for the file are not affected. @begin{Example}@Keepnext @key[procedure] Get_Immediate(File : @key[in] File_Type; Item : @key[out] Character; Available : @key[out] Boolean); @key[procedure] Get_Immediate(Item : @key[out] Character; Available : @key[out] Boolean); @end{Example} @Trailing@;If a character, either control or graphic, is available from the specified File or the default input file, then the character is read; Available is True and Item contains the value of this character. If a character is not available, then Available is False and the value of Item is not specified. @PDefn{unspecified} Mode_Error is propagated if the mode of the file is not In_File. End_Error is propagated if at the end of the file. The current column, line and page numbers for the file are not affected. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} @Leading@; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} For an item of type String the following @Chg{Version=[2],New=[subprograms], Old=[procedures]} are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] String); @key[procedure] Get(Item : @key[out] String); @end{Example} @Trailing@;Determines the length of the given string and attempts that number of Get operations for successive characters of the string (in particular, no operation is performed if the string is null). @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] Put(Item : @key[in] String); @end{Example} @Trailing@;Determines the length of the given string and attempts that number of Put operations for successive characters of the string (in particular, no operation is performed if the string is null). @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Get_Line(File : @key{in} File_Type) @key{return} String; @key{function} Get_Line @b<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a result string constructed by reading successive characters from the specified input file, and assigning them to successive characters of the result string. The result string has a lower bound of 1 and an upper bound of the number of characters read. Reading stops when the end of the line is met; Skip_Line is then (in effect) called with a spacing of 1.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Constraint_Error is raised if the length of the line exceeds Positive'Last; in this case, the line number and page number are unchanged, and the column number is unspecified but no less than it was before the call.@PDefn{unspecified} The exception End_Error is propagated if an attempt is made to skip a file terminator.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Precisely what is left in the file is unspecified if Constraint_Error is raised because the line doesn't fit in a String; it should be consistent with column number. This allows implementers to use whatever buffering scheme makes sense. But the line terminator is not skipped in this case.]} @end{Ramification} @begin{Example}@Keepnext @key[procedure] Get_Line(File : @key[in] File_Type; Item : @key[out] String; Last : @key[out] Natural); @key[procedure] Get_Line(Item : @key[out] String; Last : @key[out] Natural); @end{Example} Reads successive characters from the specified input file and assigns them to successive characters of the specified string. Reading stops if the end of the string is met. Reading also stops if the end of the line is met before meeting the end of the string; in this case Skip_Line is (in effect) called with a spacing of 1. @PDefn{unspecified} The values of characters not assigned are not specified. @Trailing@;If characters are read, returns in Last the index value such that Item(Last) is the last character assigned (the index of the first character assigned is Item'First). If no characters are read, returns in Last an index value that is one less than Item'First. The exception End_Error is propagated if an attempt is made to skip a file terminator. @begin{Example}@Keepnext @key[procedure] Put_Line(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] Put_Line(Item : @key[in] String); @end{Example} Calls the procedure Put for the given string, and then the procedure New_Line with a spacing of one. @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} The Get_Immediate procedures should be implemented with unbuffered input. For a device such as a keyboard, input should be @lquotes@;available@rquotes@; if a key has already been typed, whereas for a disk file, input should always be available except at end of file. For a file associated with a keyboard-like device, any line-editing features of the underlying operating system should be disabled during the execution of Get_Immediate. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Get_Immediate should be implemented with unbuffered input; input should be available immediately; line-editing should be disabled.]}]} @end{ImplAdvice} @begin{Notes} Get_Immediate can be used to read a single key from the keyboard @lquotes@;immediately@rquotes@;; that is, without waiting for an end of line. In a call of Get_Immediate without the parameter Available, the caller will wait until a character is available. In a literal string parameter of Put, the enclosing string bracket characters are not output. Each doubled string bracket character in the enclosed string is output as a single string bracket character, as a consequence of the rule for string literals (see @RefSecNum{String Literals}). A string read by Get or written by Put can extend over several lines. An implementation is allowed to assume that certain external files do not contain page terminators, in which case Get_Line and Skip_Line can return as soon as a line terminator is read. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The Get_Line functions are newly added to Ada.Text_IO. If Ada.Text_IO is referenced in a @nt{use_clause}, and a function Get_Line is defined in a package that is also referenced in a @nt{use_clause}, the user-defined Get_Line may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Text_IO.Get_Line functions are new.]} @end{Extend95} @LabeledSubClause{Input-Output for Integer Types} @begin{StaticSem} The following procedures are defined in the generic packages Integer_IO and Modular_IO, which have to be instantiated for the appropriate signed integer or modular type respectively (indicated by Num in the specifications). @Leading@;Values are output as decimal or based literals, without low line characters or exponent, and, for Integer_IO, preceded by a minus sign if negative. The format (which includes any leading spaces and minus sign) can be specified by an optional field width parameter. Values of widths of fields in output formats are of the nonnegative integer subtype Field. Values of bases are of the integer subtype Number_Base. @begin{Example} @Trailing@key[subtype] Number_Base @key[is] Integer @key[range] 2 .. 16; @end{Example} @Leading@;The default field width and base to be used by output procedures are defined by the following variables that are declared in the generic packages Integer_IO and Modular_IO: @begin{Example} @Trailing@;Default_Width : Field := Num'Width; Default_Base : Number_Base := 10; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] Get(Item : @key[out] Num; Width : @key[in] Field := 0); @end{Example} If the value of the parameter Width is zero, skips any leading blanks, line terminators, or page terminators, then reads a plus sign if present or (for a signed type only) a minus sign if present, then reads the longest possible sequence of characters matching the syntax of a numeric literal without a point. If a nonzero value of Width is supplied, then exactly Width characters are input, or the characters (possibly none) up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. @Trailing@;The exception Data_Error is propagated if the sequence of characters read does not form a legal integer literal or if the value obtained is not of the subtype Num (for Integer_IO) or is not in the base range of Num (for Modular_IO). @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @end{Example} Outputs the value of the parameter Item as an integer literal, with no low lines, no exponent, and no leading zeros (but a single zero for the value zero), and a preceding minus sign for a negative value. If the resulting sequence of characters to be output has fewer than Width characters, then leading spaces are first output to make up the difference. @Trailing@;Uses the syntax for decimal literal if the parameter Base has the value ten (either explicitly or through Default_Base); otherwise, uses the syntax for based literal, with any letters in upper case. @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @end{Example} Reads an integer value from the beginning of the given string, following the same rules as the Get procedure that reads an integer value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using the length of the given string as the value for Width. @end{DescribeCode} @Leading@;Integer_Text_IO is a library package that is a nongeneric equivalent to Text_IO.Integer_IO for the predefined type Integer: @begin{Example} @key[with] Ada.Text_IO;@ChildUnit{Parent=[Ada],Child=[Integer_@!Text_IO]} @key[package] Ada.Integer_Text_IO @key[is] @key[new] Ada.Text_IO.Integer_IO(Integer); @end{Example} For each predefined signed integer type, a nongeneric equivalent to Text_IO.Integer_IO is provided, with names such as Ada.Long_Integer_Text_IO. @end{StaticSem} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{Notes} For Modular_IO, execution of Get propagates Data_Error if the sequence of characters read forms an integer literal outside the range 0..Num'Last. @end{Notes} @begin{Examples} @begin{Example} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[package] Int_IO @key[is] @key[new] Integer_IO(Small_Int); @key[use] Int_IO; --@RI{ default format used at instantiation,} --@RI{ Default_Width = 4, Default_Base = 10} Put(126); --@RI{ "b126"} Put(-126, 7); --@RI{ "bbb@en@|126"} Put(126, Width => 13, Base => 2); --@RI{ "bbb2#1111110#"} @end{Example} @end{Examples} @LabeledSubClause{Input-Output for Real Types} @begin{StaticSem} The following procedures are defined in the generic packages Float_IO, Fixed_IO, and Decimal_IO, which have to be instantiated for the appropriate floating point, ordinary fixed point, or decimal fixed point type respectively (indicated by Num in the specifications). @Leading@;Values are output as decimal literals without low line characters. The format of each value output consists of a Fore field, a decimal point, an Aft field, and (if a nonzero Exp parameter is supplied) the letter E and an Exp field. The two possible formats thus correspond to: @begin{Example} Fore . Aft @end{Example} @Leading@;and to: @begin{Example} Fore . Aft E Exp @end{Example} without any spaces between these fields. The Fore field may include leading spaces, and a minus sign for negative values. The Aft field includes only decimal digits (possibly with trailing zeros). The Exp field includes the sign (plus or minus) and the exponent (possibly with leading zeros). @Leading@;For floating point types, the default lengths of these fields are defined by the following variables that are declared in the generic package Float_IO: @begin{Example} @Trailing@;Default_Fore : Field := 2; Default_Aft : Field := Num'Digits-1; Default_Exp : Field := 3; @end{Example} @Leading@;For ordinary or decimal fixed point types, the default lengths of these fields are defined by the following variables that are declared in the generic packages Fixed_IO and Decimal_IO, respectively: @begin{Example} @Trailing@;Default_Fore : Field := Num'Fore; Default_Aft : Field := Num'Aft; Default_Exp : Field := 0; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] Get(Item : @key[out] Num; Width : @key[in] Field := 0); @end{Example} @Leading@;If the value of the parameter Width is zero, skips any leading blanks, line terminators, or page terminators, then reads the longest possible sequence of characters matching the syntax of any of the following (see @RefSecNum(Numeric Literals)): @begin[itemize] [+|@en]@nt[numeric_literal] [+|@en]@nt[numeral].[@nt[exponent]] [+|@en].@nt[numeral][@nt[exponent]] [+|@en]@nt[base]#@nt[based_numeral].#[@nt[exponent]] [+|@en]@nt[base]#.@nt[based_numeral]#[@nt[exponent]] @end{Itemize} If a nonzero value of Width is supplied, then exactly Width characters are input, or the characters (possibly none) up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. Returns in the parameter Item the value of type Num that corresponds to the sequence input, preserving the sign (positive if none has been specified) of a zero value if Num is a floating point type and Num'Signed_Zeros is True. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item as a decimal literal with the format defined by Fore, Aft and Exp. If the value is negative, or if Num is a floating point type where Num'Signed_Zeros is True and the value is a negatively signed zero, then a minus sign is included in the integer part. If Exp has the value zero, then the integer part to be output has as many digits as are needed to represent the integer part of the value of Item, overriding Fore if necessary, or consists of the digit zero if the value of Item has no integer part. If Exp has a value greater than zero, then the integer part to be output has a single digit, which is nonzero except for the value 0.0 of Item. In both cases, however, if the integer part to be output has fewer than Fore characters, including any minus sign, then leading spaces are first output to make up the difference. The number of digits of the fractional part is given by Aft, or is one if Aft equals zero. The value is rounded; a value of exactly one half in the last place is rounded away from zero. @Trailing@;If Exp has the value zero, there is no exponent part. If Exp has a value greater than zero, then the exponent part to be output has as many digits as are needed to represent the exponent part of the value of Item (for which a single digit integer part is used), and includes an initial sign (plus or minus). If the exponent part to be output has fewer than Exp characters, including the sign, then leading zeros precede the digits, to make up the difference. For the value 0.0 of Item, the exponent has the value zero. @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @end{Example} Reads a real value from the beginning of the given string, following the same rule as the Get procedure that reads a real value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using a value for Fore such that the sequence of characters output exactly fills the string, including any leading spaces. @end{DescribeCode} @Leading@;Float_Text_IO is a library package that is a nongeneric equivalent to Text_IO.Float_IO for the predefined type Float: @begin{Example} @key[with] Ada.Text_IO;@ChildUnit{Parent=[Ada],Child=[Float_@!Text_IO]} @key[package] Ada.Float_Text_IO @key[is] @key[new] Ada.Text_IO.Float_IO(Float); @end{Example} For each predefined floating point type, a nongeneric equivalent to Text_IO.Float_IO is provided, with names such as Ada.Long_Float_Text_IO. @end{StaticSem} @begin{ImplPerm} An implementation may extend Get @Redundant[and Put] for floating point types to support special values such as infinities and NaNs. @begin{Discussion} See also the similar permission for the Wide_Value attribute in @RefSecNum{Scalar Types}. @end{Discussion} The implementation of Put need not produce an output value with greater accuracy than is supported for the base subtype. The additional accuracy, if any, of the value produced by Put when the number of requested digits in the integer and fractional parts exceeds the required accuracy is implementation defined. @begin{Discussion} The required accuracy is thus Num'Base'Digits digits if Num is a floating point subtype. For a fixed point subtype the required accuracy is a function of the subtype's Fore, Aft, and Delta attributes. @end{Discussion} @ImplDef{The accuracy of the value produced by Put.} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{Notes} For an item with a positive value, if output to a string exactly fills the string without leading spaces, then output of the corresponding negative value will propagate Layout_Error. The rules for the Value attribute (see @RefSecNum(Scalar Types)) and the rules for Get are based on the same set of formats. @end{Notes} @begin{Examples} @begin{Example} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[package] Real_IO @key[is] @key[new] Float_IO(Real); @key[use] Real_IO; --@RI{ default format used at instantiation, Default_Exp = 3} X : Real := -123.4567; --@RI{ digits 8 (see @RefSecNum{Floating Point Types})} @tabclear()@tabset(P50) Put(X); @RI[-- default format] @\@RI["@en@|1.2345670E+02"] Put(X, Fore => 5, Aft => 3, Exp => 2); @\@RI[-- "bbb@en@|1.235E+2"] Put(X, 5, 3, 0); @\@RI[-- "b@en@|123.457"] @end{Example} @end{Examples} @LabeledSubClause{Input-Output for Enumeration Types} @begin{StaticSem} The following procedures are defined in the generic package Enumeration_IO, which has to be instantiated for the appropriate enumeration type (indicated by Enum in the specification). Values are output using either upper or lower case letters for identifiers. This is specified by the parameter Set, which is of the enumeration type Type_Set. @begin{Example} @Trailing@key[type] Type_Set @key[is] (Lower_Case, Upper_Case); @end{Example} @Leading@;The format (which includes any trailing spaces) can be specified by an optional field width parameter. The default field width and letter case are defined by the following variables that are declared in the generic package Enumeration_IO: @begin{Example} @Trailing@;Default_Width : Field := 0; Default_Setting : Type_Set := Upper_Case; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Enum); @key[procedure] Get(Item : @key[out] Enum); @end{Example} After skipping any leading blanks, line terminators, or page terminators, reads an identifier according to the syntax of this lexical element (lower and upper case being considered equivalent), or a character literal according to the syntax of this lexical element (including the apostrophes). Returns, in the parameter Item, the value of type Enum that corresponds to the sequence input. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the identifier or character literal does not correspond to a value of the subtype Enum. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @end{Example} @Trailing@;Outputs the value of the parameter Item as an enumeration literal (either an identifier or a character literal). The optional parameter Set indicates whether lower case or upper case is used for identifiers; it has no effect for character literals. If the sequence of characters produced has fewer than Width characters, then trailing spaces are finally output to make up the difference. If Enum is a character type, the sequence of characters produced is as for Enum'Image(Item), as modified by the Width and Set parameters. @begin{Discussion} For a character type, the literal might be a Wide_Character or a control character. Whatever Image does for these things is appropriate here, too. @end{Discussion} @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Enum; Last : @key[out] Positive); @end{Example} Reads an enumeration value from the beginning of the given string, following the same rule as the Get procedure that reads an enumeration value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Enum that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the identifier or character literal does not correspond to a value of the subtype Enum. @begin{Honest} For a character type, it is permissible for the implementation to make Get do the inverse of what Put does, in the case of wide @nt{character_literal}s and control characters. @end{Honest} @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Enum; Set : @key[in] Type_Set := Default_Setting); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using the length of the given string as the value for Width. @end{DescribeCode} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0054],ARef=[AI95-00007-01]} Although the specification of the generic package Enumeration_IO would allow instantiation for an @Chg{New=[integer],Old=[float]} type, this is not the intended purpose of this generic package, and the effect of such instantiations is not defined by the language. @end{StaticSem} @begin{Notes} There is a difference between Put defined for characters, and for enumeration values. Thus @begin{Example} Ada.Text_IO.Put('A'); --@RI{ outputs the character A} @key[package] Char_IO @key[is] @key[new] Ada.Text_IO.Enumeration_IO(Character); Char_IO.Put('A'); --@RI{ outputs the character 'A', between apostrophes} @end{Example} The type Boolean is an enumeration type, hence Enumeration_IO can be instantiated for this type. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0054],ARef=[AI95-00007-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to say Enumeration_IO can be instantiated with an integer type, not a float type.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Input-Output for Bounded Strings]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[The package Text_IO.Bounded_IO provides input-output in human-readable form for Bounded_Strings.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Text_IO.Bounded_IO has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Strings.Bounded; @key{generic} @key{with package} Bounded @key{is} @key{new} Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key{package} Ada.Text_IO.Bounded_IO @key{is}@ChildUnit{Parent=[Ada.Text_IO],Child=[Bounded_IO]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} (File : @key{in} File_Type) @key{return} Bounded.Bounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} @key{return} Bounded.Bounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (File : @key{in} File_Type; Item : @key{out} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (Item : @key{out} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Text_IO.Bounded_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an item of type Bounded_String, the following subprograms are provided:]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (File, Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (File, Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line (File : @key{in} File_Type) @key{return} Bounded.Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Returns Bounded.To_Bounded_String(Text_IO.Get_Line(File));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line @key{return} Bounded.Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Returns Bounded.To_Bounded_String(Text_IO.Get_Line);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (File : @key{in} File_Type; Item : @key{out} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line (File);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (Item : @key{out} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line;]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Text_IO.Bounded_IO is new.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Input-Output for Unbounded Strings]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The package Text_IO.Unbounded_IO provides input-output in human-readable form for Unbounded_Strings.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Text_IO.Unbounded_IO has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Strings.Unbounded; @key{package} Ada.Text_IO.Unbounded_IO @key{is}@ChildUnit{Parent=[Ada.Text_IO],Child=[Unbounded_IO]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} (File : @key{in} File_Type) @key{return} Strings.Unbounded.Unbounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} @key{return} Strings.Unbounded.Unbounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (File : @key{in} File_Type; Item : @key{out} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (Item : @key{out} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Text_IO.Unbounded_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an item of type Unbounded_String, the following subprograms are provided:]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (File, Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (File, Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line (File : @key{in} File_Type) @key{return} Strings.Unbounded.Unbounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Returns Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line(File));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line @key{return} Strings.Unbounded.Unbounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Returns Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (File : @key{in} File_Type; Item : @key{out} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line (File);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (Item : @key{out} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line;]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Text_IO.Unbounded_IO is new.]} @end{Extend95} @LabeledRevisedClause{Version=[1],New=[Wide Text Input-Output and Wide Wide Text Input-Output],Old=[Wide Text Input-Output]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The @Chg{Version=[2],New=[packages],Old=[package]} Wide_Text_IO @Chg{Version=[2],New=[and Wide_Wide_Text_IO provide],Old=[provides]} facilities for input and output in human-readable form. Each file is read or written sequentially, as a sequence of wide characters @Chg{Version=[2],New=[(or wide wide characters) ],Old=[]}grouped into lines, and as a sequence of lines grouped into pages. @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @ChildUnit{Parent=[Ada],Child=[Wide_@!Text_IO]} The specification of package Wide_Text_IO is the same as that for Text_IO, except that in each Get, Look_Ahead, Get_Immediate, Get_Line, Put, and Put_Line @Chg{Version=[2],New=[subprogram],Old=[procedure]}, any occurrence of Character is replaced by Wide_Character, and any occurrence of String is replaced by Wide_String.@Chg{Version=[2],New=[ @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_@!Text_IO]} Nongeneric equivalents of Wide_Text_IO.Integer_IO and Wide_Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Text_IO, Ada.Long_@!Integer_@!Wide_Text_IO, Ada.Float_@!Wide_Text_IO, Ada.Long_@!Float_@!Wide_Text_IO.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @Chg{Version=[2],New=[ @ChildUnit{Parent=[Ada],Child=[Wide_Wide_@!Text_IO]} The specification of package Wide_Wide_Text_IO is the same as that for Text_IO, except that in each Get, Look_Ahead, Get_Immediate, Get_Line, Put, and Put_Line subprogram, any occurrence of Character is replaced by Wide_Wide_Character, and any occurrence of String is replaced by Wide_Wide_String. @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_Wide_@!Text_IO]} Nongeneric equivalents of Wide_Wide_Text_IO.Integer_IO and Wide_Wide_@!Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Wide_@!Text_IO, Ada.Long_@!Integer_@!Wide_Wide_@!Text_IO, Ada.Float_@!Wide_Wide_@!Text_IO, Ada.Long_@!Float_@!Wide_Wide_@!Text_IO.], Old=[ @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_@!Text_IO]} Nongeneric equivalents of Wide_Text_IO.Integer_IO and Wide_Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Text_IO, Ada.Long_@!Integer_@!Wide_Text_IO, Ada.Float_@!Wide_Text_IO, Ada.Long_@!Float_@!Wide_Text_IO.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Bounded_IO]} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Bounded_IO]} The specification of package Wide_Text_IO.Wide_@!Bounded_IO is the same as that for Text_IO.Bounded_IO, except that any occurrence of Bounded_String is replaced by Wide_@!Bounded_@!String, and any occurrence of package Bounded is replaced by Wide_Bounded. The specification of package Wide_Wide_@!Text_IO.Wide_Wide_@!Bounded_IO is the same as that for Text_IO.@!Bounded_IO, except that any occurrence of Bounded_@!String is replaced by Wide_Wide_@!Bounded_String, and any occurrence of package Bounded is replaced by Wide_Wide_@!Bounded.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Unbounded_IO]} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Unbounded_IO]} The specification of package Wide_Text_IO.@!Wide_Unbounded_IO is the same as that for Text_IO.@!Unbounded_IO, except that any occurrence of Unbounded_@!String is replaced by Wide_@!Unbounded_@!String, and any occurrence of package Unbounded is replaced by Wide_@!Unbounded. The specification of package Wide_Wide_Text_IO.Wide_Wide_@!Unbounded_IO is the same as that for Text_IO.Unbounded_IO, except that any occurrence of Unbounded_String is replaced by Wide_Wide_@!Unbounded_@!String, and any occurrence of package Unbounded is replaced by Wide_Wide_@!Unbounded.]} @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} Support for Wide_Character and Wide_String I/O is new in Ada 95. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO is new. Be glad it wasn't called Double_Wide_Text_IO (for use in trailer parks) or Really_Wide_Text_IO.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Packages Wide_Text_IO.Wide_Unbounded_IO and Wide_Wide_Text_IO.Wide_Wide_Unbounded_IO are also new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Packages Wide_Text_IO.Wide_Bounded_IO and Wide_Wide_Text_IO.Wide_Wide_Bounded_IO are new as well.]} @end{Extend95} @LabeledClause{Stream Input-Output} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} The packages Streams.Stream_IO, Text_IO.Text_Streams, @Chg{Version=[2], New=[],Old=[and ]}Wide_Text_IO.Text_Streams@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Text_Streams],Old=[]} provide stream-oriented operations on files. @end{Intro} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO.Text_Streams in this description.]} @end{Diffword95} @LabeledSubClause{The Package Streams.Stream_IO} @begin{Intro} @Defn{heterogeneous input-output} @Redundant[The subprograms in the child package Streams.Stream_IO provide control over stream files. Access to a stream file is either sequential, via a call on Read or Write to transfer an array of stream elements, or positional (if supported by the implementation for the given file), by specifying a relative index for an element. Since a stream file can be converted to a Stream_Access value, calling stream-oriented attribute subprograms of different element types with the same Stream_Access value provides heterogeneous input-output.] See @RefSecNum{Streams} for a general discussion of streams. @end{Intro} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The elements of a stream file are stream elements. If positioning is supported for the specified external file, a current index and current size are maintained for the file as described in @RefSecNum(Sequential and Direct Files). If positioning is not supported, a current index is not maintained, and the current size is implementation defined.@Defn2{Term=(Current index), Sec=(of an open stream file)}@Defn2{Term=(Current size),Sec=(of a stream file)}]} @ChgImpldef{Version=[1],Kind=[Added],Text=[@ChgAdded{Version=[1], Text=[Current size for a stream file for which positioning is not supported.]}]} @Leading@;The library package Streams.Stream_IO has the following declaration: @begin(example) @key(with) Ada.IO_Exceptions;@ChildUnit{Parent=[Ada.Streams],Child=[Stream_@!IO]} @key(package) Ada.Streams.Stream_IO @key(is) @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Root_Stream_Type'Class; @key(type) @AdaTypeDefn{File_Type} @key(is) @key(limited) @key(private;) @key(type) @AdaTypeDefn{File_Mode} @key(is) (In_File, Out_File, Append_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; -- @RI(Index into file, in stream elements.) @key(procedure) @AdaSubDefn{Create} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode := Out_File; Name : @key(in) String := ""; Form : @key(in) String := ""); @key(procedure) @AdaSubDefn{Open} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode; Name : @key(in) String; Form : @key(in) String := ""); @key(procedure) @AdaSubDefn{Close} (File : @key(in) @key(out) File_Type); @key(procedure) @AdaSubDefn{Delete} (File : @key(in) @key(out) File_Type); @key(procedure) @AdaSubDefn{Reset} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode); @key(procedure) @AdaSubDefn{Reset} (File : @key(in) @key(out) File_Type); @key(function) @AdaSubDefn{Mode} (File : @key(in) File_Type) @key(return) File_Mode; @key(function) @AdaSubDefn{Name} (File : @key(in) File_Type) @key(return) String; @key(function) @AdaSubDefn{Form} (File : @key(in) File_Type) @key(return) String; @key(function) @AdaSubDefn{Is_Open} (File : @key(in) File_Type) @key(return) Boolean; @key(function) @AdaSubDefn{End_Of_File} (File : @key(in) File_Type) @key(return) Boolean; @key(function) @AdaSubDefn{Stream} (File : @key(in) File_Type) @key(return) Stream_Access; -- @RI(Return stream access for use with T'Input and T'Output) @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Read array of stream elements from file) @key(procedure) @AdaSubDefn{Read} (File : @key(in) File_Type; Item : @key(out) Stream_Element_Array; Last : @key(out) Stream_Element_Offset; From : @key(in) Positive_Count); @key(procedure) @AdaSubDefn{Read} (File : @key(in) File_Type; Item : @key(out) Stream_Element_Array; Last : @key(out) Stream_Element_Offset); @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Write array of stream elements into file) @key(procedure) @AdaSubDefn{Write} (File : @key(in) File_Type; Item : @key(in) Stream_Element_Array; To : @key(in) Positive_Count); @key(procedure) @AdaSubDefn{Write} (File : @key(in) File_Type; Item : @key(in) Stream_Element_Array); @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Operations on position within file) @key[procedure] @AdaSubDefn{Set_Index}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Index}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Size} (File : @key[in] File_Type) @key[return] Count; @key(procedure) @AdaSubDefn{Set_Mode}(File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode); @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]} @key(procedure) @AdaSubDefn{Flush}(File : @key(in) @Chg{New=[],Old=[@key(out) ]}File_Type); -- @RI(exceptions) @AdaExcDefn{Status_Error} : @key(exception) @key(renames) IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key(exception) @key(renames) IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key(exception) @key(renames) IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key(exception) @key(renames) IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key(exception) @key(renames) IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key(exception) @key(renames) IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key(exception) @key(renames) IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key(end) Ada.Streams.Stream_IO; @end(example) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} The subprograms @Chg{Version=[2],New=[given in subclause @RefSecNum(File Management) for the control of external files (],Old=[]}Create, Open, Close, Delete, Reset, Mode, Name, Form,@Chg{Version=[2],New=[ and],Old=[]} Is_Open@Chg{Version=[2],New=[) are available for stream files], Old=[, and End_of_File have the same effect as the corresponding subprograms in Sequential_IO (see @RefSecNum(File Management))]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The End_Of_File function:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Propagates Mode_Error if the mode of the file is not In_File;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If positioning is supported for the given external file, the function returns True if the current index exceeds the size of the external file; otherwise it returns False;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If positioning is not supported for the given external file, the function returns True if no more elements can be read from the given file; otherwise it returns False.]} @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00085-01]} @ChgAdded{Version=[1],Text=[The Set_Mode procedure @Chg{Version=[2],New=[sets],Old=[changes]} the mode of the file. If the new mode is Append_File, the file is positioned to its end; otherwise, the position in the file is unchanged.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The Flush procedure synchronizes the external file with the internal file (by flushing any internal buffers) without closing the file or changing the position. Mode_Error is propagated if the mode of the file is In_File.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0056],ARef=[AI95-00001-01]} The Stream function returns a Stream_Access result from a File_Type object, thus allowing the stream-oriented attributes Read, Write, Input, and Output to be used on the same file for multiple types. @Chg{New=[Stream propagates Status_Error if File is not open.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} The procedures Read and Write are equivalent to the corresponding operations in the package Streams. Read propagates Mode_Error if the mode of File is not In_File. Write propagates Mode_Error if the mode of File is not Out_File or Append_File. The Read procedure with a Positive_Count parameter starts reading at the specified index. The Write procedure with a Positive_Count parameter starts writing at the specified index.@Chg{Version=[2],New=[ For a file that supports positioning, Read without a Positive_Count parameter starts reading at the current index, and Write without a Positive_Count parameter starts writing at the current index.],Old=[]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The Size function returns the current size of the file.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0055],ARef=[AI95-00026-01]} The Index function returns the current @Chg{New=[],Old=[file ]}index@Chg{New=[], Old=[, as a count (in stream elements) from the beginning of the file. The position of the first element in the file is 1]}. @begin{Ramification} @ChgRef{Version=[1],Kind=[Deleted]} @ChgNote{This ramification is now part of the official wording.} @ChgDeleted{Version=[1],Text=[The notion of Index for Stream_IO is analogous to that of Index in Direct_IO, except that the former is measured in Stream_Element units, whereas the latter is in terms of Element_Type values.]} @end{Ramification} The Set_Index procedure sets the current index to the specified value. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[If positioning is supported for the external file, the current index is maintained as follows:]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Open and Create, if the Mode parameter is Append_File, the current index is set to the current size of the file plus one; otherwise, the current index is set to one.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Reset, if the Mode parameter is Append_File, or no Mode parameter is given and the current mode is Append_File, the current index is set to the current size of the file plus one; otherwise, the current index is set to one.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Set_Mode, if the new mode is Append_File, the current index is set to current size plus one; otherwise, the current index is unchanged.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Read and Write without a Positive_Count parameter, the current index is incremented by the number of stream elements read or written.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Read and Write with a Positive_Count parameter, the value of the current index is set to the value of the Positive_Count parameter plus the number of stream elements read or written.]} @end{Itemize} If positioning is not supported for the given file, then a call of Index or Set_Index propagates Use_Error. Similarly, a call of Read or Write with a Positive_Count parameter propagates Use_Error. @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[It is permissible for an implementation to implement mode Append_File using the Unix append mode (the O_APPEND bit). Such an implementation does not support positioning when the mode is Append_File, and therefore the operations listed above must raise Use_Error. This is acceptable as there is no requirement that any particular file support positioning; therefore it is acceptable that a file support positioning when opened with mode Out_File, and the same file not support positioning when opened with mode Append_File. But it is not acceptable for a file to support positioning (by allowing the above operations), but to do something other than the defined semantics (that is, always write at the end, even when explicitly commanded to write somewhere else).]} @end{ImplNote} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 34 through 36 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Size function returns the current size of the file, in stream elements.]} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Set_Mode procedure changes the mode of the file. If the new mode is Append_File, the file is positioned to its end; otherwise, the position in the file is unchanged.]} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Flush procedure synchronizes the external file with the internal file (by flushing any internal buffers) without closing the file or changing the position. Mode_Error is propagated if the mode of the file is In_File.]} @end{StaticSem} @begin{Erron} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0056],ARef=[AI95-00001-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the File_Type object passed to the Stream function is later closed or finalized, and the stream-oriented attributes are subsequently called (explicitly or implicitly) on the Stream_Access value returned by Stream, execution is erroneous. This rule applies even if the File_Type object was opened again after it had been closed.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[These rules are analogous to the rule for the result of the Current_Input, Current_Output, and Current_Error functions. These rules make it possible to represent a value of (some descendant of) Root_Stream_Type which represents a file as an access value, with a null value corresponding to a closed file.]} @end{Reason} @end{Erron} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] The description of the subprograms for managing files was corrected so that they do not require truncation of the external file @em a stream file is not a sequential file. An Ada 95 program that expects truncation of the stream file may not work under Ada 2005. Note that the Ada 95 standard was ambiguous on this point (the normative wording seemed to require truncation, but didn't explain where; the AARM notes seemed to expect behavior like Direct_IO), and implementations varied widely. Therefore, as a practical matter, code that depends on stream truncation may not work even in Ada 95; deleting the file before opening it provides truncation that works in both Ada 95 and Ada 2005.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] Stream_IO.File_Type is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0055],ARef=[AI95-00026-01],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to describe the effects of the various operations on the current index. The Amendment adds an explanation of the use of current index for Read and Write.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0056],ARef=[AI95-00001-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Stream can raise Status_Error, and clarified that using a Stream_Access whose file has been closed is erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[Clarified that Set_Mode can be called with the current mode.]} @end{DiffWord95} @LabeledSubClause{The Package Text_IO.Text_Streams} @begin{Intro} The package Text_IO.Text_Streams provides a function for treating a text file as a stream. @end{Intro} @begin{StaticSem} @Leading@;The library package Text_IO.Text_Streams has the following declaration: @begin{example} @key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class; @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Text_IO.Text_Streams; @end{example} The Stream function has the same effect as the corresponding function in Streams.Stream_IO. @end{StaticSem} @begin[Notes] The ability to obtain a stream for a text file allows Current_Input, Current_Output, and Current_Error to be processed with the functionality of streams, including the mixing of text and binary input-output, and the mixing of binary input-output for different types. Performing operations on the stream associated with a text file does not affect the column, line, or page counts. @end[Notes] @LabeledSubClause{The Package Wide_Text_IO.Text_Streams} @begin{Intro} The package Wide_Text_IO.Text_Streams provides a function for treating a wide text file as a stream. @end{Intro} @begin{StaticSem} @Leading@;The library package Wide_Text_IO.Text_Streams has the following declaration: @begin{example} @key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Wide_Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class; @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Wide_Text_IO.Text_Streams; @end{example} The Stream function has the same effect as the corresponding function in Streams.Stream_IO. @end{StaticSem} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Text_Streams]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The package Wide_Wide_Text_IO.Text_Streams provides a function for treating a wide wide text file as a stream.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Leading@;The library package Wide_Wide_Text_IO.Text_Streams has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Wide_Wide_Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Wide_Wide_Text_IO.Text_Streams;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The Stream function has the same effect as the corresponding function in Streams.Stream_IO.]} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Text_Streams is new.]} @end{Extend95} @LabeledClause{Exceptions in Input-Output} @begin{Intro} The package IO_Exceptions defines the exceptions needed by the predefined input-output packages. @end{Intro} @begin{StaticSem} @Leading@;The library package IO_Exceptions has the following declaration: @begin{Example} @key[package] Ada.IO_Exceptions @key[is]@ChildUnit{Parent=[Ada],Child=[IO_Exceptions]} @key[pragma] Pure(IO_Exceptions); @AdaExcDefn{Status_Error} : @key[exception]; @AdaExcDefn{Mode_Error} : @key[exception]; @AdaExcDefn{Name_Error} : @key[exception]; @AdaExcDefn{Use_Error} : @key[exception]; @AdaExcDefn{Device_Error} : @key[exception]; @AdaExcDefn{End_Error} : @key[exception]; @AdaExcDefn{Data_Error} : @key[exception]; @AdaExcDefn{Layout_Error} : @key[exception]; @key[end] Ada.IO_Exceptions; @end{Example} If more than one error condition exists, the corresponding exception that appears earliest in the following list is the one that is propagated. The exception Status_Error is propagated by an attempt to operate upon a file that is not open, and by an attempt to open a file that is already open. The exception Mode_Error is propagated by an attempt to read from, or test for the end of, a file whose current mode is Out_File or Append_File, and also by an attempt to write to a file whose current mode is In_File. In the case of Text_IO, the exception Mode_Error is also propagated by specifying a file whose current mode is Out_File or Append_File in a call of Set_Input, Skip_Line, End_Of_Line, Skip_Page, or End_Of_Page; and by specifying a file whose current mode is In_File in a call of Set_Output, Set_Line_Length, Set_Page_Length, Line_Length, Page_Length, New_Line, or New_Page. The exception Name_Error is propagated by a call of Create or Open if the string given for the parameter Name does not allow the identification of an external file. For example, this exception is propagated if the string is improper, or, alternatively, if either none or more than one external file corresponds to the string. The exception Use_Error is propagated if an operation is attempted that is not possible for reasons that depend on characteristics of the external file. For example, this exception is propagated by the procedure Create, among other circumstances, if the given mode is Out_File but the form specifies an input only device, if the parameter Form specifies invalid access rights, or if an external file with the given name already exists and overwriting is not allowed. The exception Device_Error is propagated if an input-output operation cannot be completed because of a malfunction of the underlying system. The exception End_Error is propagated by an attempt to skip (read past) the end of a file. The exception Data_Error can be propagated by the procedure Read (or by the Read attribute) if the element read cannot be interpreted as a value of the required subtype. This exception is also propagated by a procedure Get (defined in the package Text_IO) if the input character sequence fails to satisfy the required syntax, or if the value input does not belong to the range of the required subtype. The exception Layout_Error is propagated (in text input-output) by Col, Line, or Page if the value returned exceeds Count'Last. The exception Layout_Error is also propagated on output by an attempt to set column or line numbers in excess of specified maximum line or page lengths, respectively (excluding the unbounded cases). It is also propagated by an attempt to Put too many characters to a string. @end{StaticSem} @begin{DocReq} The implementation shall document the conditions under which Name_Error, Use_Error and Device_Error are propagated. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The conditions under which Io_Exceptions.Name_Error, Io_Exceptions.Use_Error, and Io_Exceptions.Device_Error are propagated.]}]} @end{DocReq} @begin{ImplPerm} If the associated check is too complex, an implementation need not propagate Data_Error as part of a procedure Read (or the Read attribute) if the value read cannot be interpreted as a value of the required subtype. @begin{Ramification} An example where the implementation may choose not to perform the check is an enumeration type with a representation clause with @lquotes@;holes@rquotes@; in the range of internal codes.@end{ramification} @end{ImplPerm} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)}@Redundant[If the element read by the procedure Read (or by the Read attribute) cannot be interpreted as a value of the required subtype, but this is not detected and Data_Error is not propagated, then the resulting value can be abnormal, and subsequent references to the value can lead to erroneous execution, as explained in @RefSecNum{Data Validity}. @PDefn{normal state of an object} @PDefn{abnormal state of an object}] @end{Erron} @LabeledClause{File Sharing} @begin{RunTime} @PDefn{unspecified} @Leading@;It is not specified by the language whether the same external file can be associated with more than one file object. If such sharing is supported by the implementation, the following effects are defined: @begin{itemize} Operations on one text file object do not affect the column, line, and page numbers of any other file object. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0057],ARef=[AI95-00050-01]} @ChgDeleted{Version=[1],Text=[Standard_Input and Standard_Output are associated with distinct external files, so operations on one of these files cannot affect operations on the other file. In particular, reading from Standard_Input does not affect the current page, line, and column numbers for Standard_Output, nor does writing to Standard_Output affect the current page, line, and column numbers for Standard_Input.]} For direct and stream files, the current index is a property of each file object; an operation on one file object does not affect the current index of any other file object. For direct and stream files, the current size of the file is a property of the external file. @end{itemize} All other effects are identical. @end{RunTime} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0057],ARef=[AI95-00050-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Removed the incorrect statement that the external files associated with the standard input, standard output, and standard error files are distinct.]} @end{DiffWord95} �������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_math.mss���������������������������������������������������������0000755�0001752�0001001�00000121377�12273462240�017757� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_math.mss,v $ } @comment{ $Revision: 1.37 $ $Date: 2006/02/16 06:49:06 $ $Author: Randy $ } @Part(predefmath, Root="ada.mss") @Comment{$Date: 2006/02/16 06:49:06 $} @LabeledClause{The Numerics Packages} @begin{Intro} The library package Numerics is the parent of several child units that provide facilities for mathematical computation. One child, the generic package Generic_Elementary_Functions, is defined in @RefSecNum{Elementary Functions}, together with nongeneric equivalents; two others, the package Float_Random and the generic package Discrete_Random, are defined in @RefSecNum{Random Number Generation}. Additional (optional) children are defined in @RefSec{Numerics}. @end{Intro} @begin{StaticSem} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00388-01]} @key[package] Ada.Numerics @key[is]@ChildUnit{Parent=[Ada],Child=[Numerics]} @key[pragma] Pure(Numerics); @AdaExcDefn{Argument_Error} : @key[exception]; @AdaObjDefn{Pi} : @key[constant] := 3.14159_26535_89793_23846_26433_83279_50288_41971_69399_37511;@Chg{Version=[2],New=[ @pi : @key[constant] := Pi;],Old=[]} @AdaObjDefn{e} : @key[constant] := 2.71828_18284_59045_23536_02874_71352_66249_77572_47093_69996; @key[end] Ada.Numerics; @end{Example} The Argument_Error exception is raised by a subprogram in a child unit of Numerics to signal that one or more of the actual subprogram parameters are outside the domain of the corresponding mathematical function. @end{StaticSem} @begin{ImplPerm} The implementation may specify the values of Pi and e to a larger number of significant digits. @begin{Reason} 51 digits seem more than adequate for all present computers; converted to binary, the values given above are accurate to more than 160 bits. Nevertheless, the permission allows implementations to accommodate unforeseen hardware advances. @end{Reason} @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} Numerics and its children were not predefined in Ada 83. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00388-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The alternative declaration of @pi is new.]} @end{Extend95} @LabeledSubClause{Elementary Functions} @begin{Intro} Implementation-defined approximations to the mathematical functions known as the @lquotes@;elementary functions@rquotes@; are provided by the subprograms in Numerics.@!Generic_@!Elementary_@!Functions. Nongeneric equivalents of this generic package for each of the predefined floating point types are also provided as children of Numerics. @ImplDef{The accuracy actually achieved by the elementary functions.} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Elementary_Functions has the following declaration: @begin{Example} @key{generic} @key{type} Float_Type @key{is} @key{digits} <>; @ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Elementary_@!Functions]} @key{package} Ada.Numerics.Generic_Elementary_Functions @key{is} @key[pragma] Pure(Generic_Elementary_Functions); @key{function} @AdaSubDefn{Sqrt} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Log} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Log} (X, Base : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Exp} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} "**" (Left, Right : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sin} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sin} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cos} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cos} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tan} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tan} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cot} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cot} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsin} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsin} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccos} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccos} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctan} (Y : Float_Type'Base; X : Float_Type'Base := 1.0) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctan} (Y : Float_Type'Base; X : Float_Type'Base := 1.0; Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccot} (X : Float_Type'Base; Y : Float_Type'Base := 1.0) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccot} (X : Float_Type'Base; Y : Float_Type'Base := 1.0; Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sinh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cosh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tanh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Coth} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsinh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccosh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctanh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccoth} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{end} Ada.Numerics.Generic_Elementary_Functions; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Elementary_@!Functions]} The library package Numerics.Elementary_Functions @Chg{New=[is declared pure and ],Old=[]}defines the same subprograms as Numerics.@!Generic_@!Elementary_@!Functions, except that the predefined type Float is systematically substituted for Float_Type'Base throughout. Nongeneric equivalents of Numerics.@!Generic_@!Elementary_@!Functions for each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Elementary_@!Functions, Numerics.@!Long_@!Elementary_@!Functions, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} The functions have their usual mathematical meanings. When the Base parameter is specified, the Log function computes the logarithm to the given base; otherwise, it computes the natural logarithm. When the Cycle parameter is specified, the parameter X of the forward trigonometric functions (Sin, Cos, Tan, and Cot) and the results of the inverse trigonometric functions (Arcsin, Arccos, Arctan, and Arccot) are measured in units such that a full cycle of revolution has the given value; otherwise, they are measured in radians. @Leading@;The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply the principal branch: @begin{Itemize} The results of the Sqrt and Arccosh functions and that of the exponentiation operator are nonnegative. The result of the Arcsin function is in the quadrant containing the point (1.0, @i[x]), where @i[x] is the value of the parameter X. This quadrant is I or IV; thus, the range of the Arcsin function is approximately @en@Pi/2.0 to @Pi/2.0 (@en@R[Cycle]/4.0 to @R[Cycle]/4.0, if the parameter Cycle is specified). The result of the Arccos function is in the quadrant containing the point (@i{x}, 1.0), where @i[x] is the value of the parameter X. This quadrant is I or II; thus, the Arccos function ranges from 0.0 to approximately @Pi (@R[Cycle]/2.0, if the parameter Cycle is specified). The results of the Arctan and Arccot functions are in the quadrant containing the point (@i[x], @i[y]), where @i[x] and @i[y] are the values of the parameters X and Y, respectively. This may be any quadrant (I through IV) when the parameter X (resp., Y) of Arctan (resp., Arccot) is specified, but it is restricted to quadrants I and IV (resp., I and II) when that parameter is omitted. Thus, the range when that parameter is specified is approximately @en@Pi to @Pi (@en@R[Cycle]/2.0 to @R[Cycle]/2.0, if the parameter Cycle is specified); when omitted, the range of Arctan (resp., Arccot) is that of Arcsin (resp., Arccos), as given above. When the point (@i[x], @i[y]) lies on the negative x-axis, the result approximates @begin{Itemize} @Pi (resp., @en@Pi) when the sign of the parameter Y is positive (resp., negative), if Float_Type'Signed_Zeros is True; @Pi, if Float_Type'Signed_Zeros is False. @end{Itemize} @end{Itemize} (In the case of the inverse trigonometric functions, in which a result lying on or near one of the axes may not be exactly representable, the approximation inherent in computing the result may place it in an adjacent quadrant, close to but on the wrong side of the axis.) @end{StaticSem} @begin{RunTime} @Leading@;The exception Numerics.Argument_Error is raised, signaling a parameter value outside the domain of the corresponding mathematical function, in the following cases: @begin{Itemize} by any forward or inverse trigonometric function with specified cycle, when the value of the parameter Cycle is zero or negative; by the Log function with specified base, when the value of the parameter Base is zero, one, or negative; by the Sqrt and Log functions, when the value of the parameter X is negative; by the exponentiation operator, when the value of the left operand is negative or when both operands have the value zero; by the Arcsin, Arccos, and Arctanh functions, when the absolute value of the parameter X exceeds one; by the Arctan and Arccot functions, when the parameters X and Y both have the value zero; by the Arccosh function, when the value of the parameter X is less than one; and by the Arccoth function, when the absolute value of the parameter X is less than one. @end{Itemize} @Leading@IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised, signaling a pole of the mathematical function (analogous to dividing by zero), in the following cases, provided that Float_Type'Machine_Overflows is True: @begin{Itemize} by the Log, Cot, and Coth functions, when the value of the parameter X is zero; by the exponentiation operator, when the value of the left operand is zero and the value of the exponent is negative; by the Tan function with specified cycle, when the value of the parameter X is an odd multiple of the quarter cycle; by the Cot function with specified cycle, when the value of the parameter X is zero or a multiple of the half cycle; and by the Arctanh and Arccoth functions, when the absolute value of the parameter X is one. @end{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for the Elementary Functions}); this may occur for parameter values sufficiently @i{near} poles, and, in the case of some of the functions, for parameter values with sufficiently large magnitudes.]@PDefn{unspecified} When Float_Type'Machine_Overflows is False, the result at poles is unspecified. @begin{Reason} The purpose of raising Constraint_Error (rather than Numerics.Argument_Error) at the poles of a function, when Float_Type'Machine_Overflows is True, is to provide continuous behavior as the actual parameters of the function approach the pole and finally reach it. @end{Reason} @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit both the predefined arithmetic operations and implementations of the elementary functions to deliver signed infinities (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the elementary functions to deliver signed infinities (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error at poles, when traps are disabled. Finally, such a binding should also specify the behavior of the elementary functions, when sensible, given parameters with infinite values. @end{Discussion} When one parameter of a function with multiple parameters represents a pole and another is outside the function's domain, the latter takes precedence (i.e., Numerics.Argument_Error is raised). @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Elementary_Functions, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Float_Type. @begin{ImplNote} Implementations of Numerics.Generic_Elementary_Functions written in Ada should therefore avoid declaring local variables of subtype Float_Type; the subtype Float_Type'Base should be used instead. @end{ImplNote} @Leading@Defn2{Term=[prescribed result], Sec=[for the evaluation of an elementary function]} In the following cases, evaluation of an elementary function shall yield the @i{prescribed result}, provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} When the parameter X has the value zero, the Sqrt, Sin, Arcsin, Tan, Sinh, Arcsinh, Tanh, and Arctanh functions yield a result of zero, and the Exp, Cos, and Cosh functions yield a result of one. When the parameter X has the value one, the Sqrt function yields a result of one, and the Log, Arccos, and Arccosh functions yield a result of zero. When the parameter Y has the value zero and the parameter X has a positive value, the Arctan and Arccot functions yield a result of zero. The results of the Sin, Cos, Tan, and Cot functions with specified cycle are exact when the mathematical result is zero; those of the first two are also exact when the mathematical result is @PorM 1.0. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand. Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero. @end{Itemize} Other accuracy requirements for the elementary functions, which apply only in implementations conforming to the Numerics Annex, and then only in the @lquotes@;strict@rquotes@; mode defined there (see @RefSecNum{Numeric Performance Requirements}), are given in @RefSecNum{Accuracy Requirements for the Elementary Functions}. @Leading@;When Float_Type'Signed_Zeros is True, the sign of a zero result shall be as follows: @begin{itemize} A prescribed zero result delivered @i{at the origin} by one of the odd functions (Sin, Arcsin, Sinh, Arcsinh, Tan, Arctan or Arccot as a function of Y when X is fixed and positive, Tanh, and Arctanh) has the sign of the parameter X (Y, in the case of Arctan or Arccot). A prescribed zero result delivered by one of the odd functions @i{away from the origin}, or by some other elementary function, has an implementation-defined sign. @ImplDef{The sign of a zero result from some of the operators or functions in Numerics.Generic_Elementary_Functions, when Float_Type'Signed_Zeros is True.} @redundant[A zero result that is not a prescribed result (i.e., one that results from rounding or underflow) has the correct mathematical sign.] @begin{Reason} This is a consequence of the rules specified in IEC 559:1989 as they apply to underflow situations with traps disabled. @end{Reason} @end{itemize} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Elementary_Functions differs from Generic_Elementary_Functions as defined in ISO/IEC DIS 11430 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child unit of the package defining the Argument_Error exception. DIS 11430 specified names for the nongeneric equivalents, if provided. Here, those nongeneric equivalents are required. Implementations are not allowed to impose an optional restriction that the generic actual parameter associated with Float_Type be unconstrained. (In view of the ability to declare variables of subtype Float_Type'Base in implementations of Numerics.Generic_Elementary_Functions, this flexibility is no longer needed.) The sign of a prescribed zero result at the origin of the odd functions is specified, when Float_Type'Signed_Zeros is True. This conforms with recommendations of Kahan and other numerical analysts. The dependence of Arctan and Arccot on the sign of a parameter value of zero is tied to the value of Float_Type'Signed_Zeros. Sqrt is prescribed to yield a result of one when its parameter has the value one. This guarantee makes it easier to achieve certain prescribed results of the complex elementary functions (see @RefSec{Complex Elementary Functions}). Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Elementary_Functions are pure.]} @end{DiffWord95} @LabeledSubClause{Random Number Generation} @begin{Intro} @redundant[Facilities for the generation of pseudo-random floating point numbers are provided in the package Numerics.Float_Random; the generic package Numerics.Discrete_Random provides similar facilities for the generation of pseudo-random integers and pseudo-random values of enumeration types. @Defn{random number} For brevity, pseudo-random values of any of these types are called @i{random numbers}. Some of the facilities provided are basic to all applications of random numbers. These include a limited private type each of whose objects serves as the generator of a (possibly distinct) sequence of random numbers; a function to obtain the @lquotes@;next@rquotes@; random number from a given sequence of random numbers (that is, from its generator); and subprograms to initialize or reinitialize a given generator to a time-dependent state or a state denoted by a single integer. Other facilities are provided specifically for advanced applications. These include subprograms to save and restore the state of a given generator; a private type whose objects can be used to hold the saved state of a generator; and subprograms to obtain a string representation of a given generator state, or, given such a string representation, the corresponding state.] @begin{Discussion} These facilities support a variety of requirements ranging from repeatable sequences (for debugging) to unique sequences in each execution of a program. @end{Discussion} @end{Intro} @begin{StaticSem} @Leading@;The library package Numerics.Float_Random has the following declaration: @begin{Example} @key[package] Ada.Numerics.Float_Random @key[is]@ChildUnit{Parent=[Ada.Numerics],Child=[Float_@!Random]} -- @RI{Basic facilities} @key[type] @AdaTypeDefn{Generator} @key[is] @key[limited] @key[private]; @key[subtype] @AdaSubtypeDefn{Name=[Uniformly_Distributed],Of=[Float]} @key[is] Float @key[range] 0.0 .. 1.0; @key[function] @AdaSubDefn{Random} (Gen : Generator) @key[return] Uniformly_Distributed; @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator); -- @RI{Advanced facilities} @key[type] @AdaTypeDefn{State} @key[is] @key[private]; @key[procedure] @AdaSubDefn{Save} (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; From_State : @key[in] State); @AdaObjDefn{Max_Image_Width} : @key[constant] := @RI{implementation-defined integer value}; @key[function] @AdaSubDefn{Image} (Of_State : State) @key[return] String; @key[function] @AdaSubDefn{Value} (Coded_State : String) @key[return] State; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Numerics.Float_Random; @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Generator needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} The generic library package Numerics.Discrete_Random has the following declaration: @begin{Example} @ChildUnit{Parent=[Ada.Numerics],Child=[Discrete_@!Random]} @key[generic] @key[type] Result_Subtype @key[is] (<>); @key[package] Ada.Numerics.Discrete_Random @key[is] -- @RI{Basic facilities} @key[type] @AdaTypeDefn{Generator} @key[is] @key[limited] @key[private]; @key[function] @AdaSubDefn{Random} (Gen : Generator) @key[return] Result_Subtype; @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator); -- @RI{Advanced facilities} @key[type] @AdaTypeDefn{State} @key[is] @key[private]; @key[procedure] @AdaSubDefn{Save} (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; From_State : @key[in] State); @AdaObjDefn{Max_Image_Width} : @key[constant] := @RI{implementation-defined integer value}; @key[function] @AdaSubDefn{Image} (Of_State : State) @key[return] String; @key[function] @AdaSubDefn{Value} (Coded_State : String) @key[return] State; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Numerics.Discrete_Random; @end{Example} @ImplDef{The value of Numerics.Float_Random.Max_Image_Width.} @ImplDef{The value of Numerics.Discrete_Random.Max_Image_Width.} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0097],ARef=[AI95-00115-01]} @Leading@; The following is a possible implementation of the private part of @Chg{New=[Numerics.Float_Random], Old=[each package]} (assuming the presence of @lquotes@;@key[with] Ada.Finalization;@rquotes@; as a context clause): @begin{example} @key[type] State @key[is] ...; @key[type] Access_State @key[is] @key[access] State; @key[type] Generator @key[is] @key[new] Finalization.Limited_Controlled @key[with] @key[record] S : Access_State := @key[new] State'(...); @key[end] @key[record]; @key[procedure] Finalize (G : @key[in] @key[out] Generator); @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00344-01]} @ChgAdded{Version=[1],Text=[@Chg{Version=[2],New=[], Old=[Unfortunately, ]}Numerics.Discrete_Random.Generator @Chg{Version=[2],New=[also can],Old=[cannot]} be implemented this way@Chg{Version=[2],New=[],Old=[, as Numerics.Discrete_Random can be instantiated at any nesting depth. However, Generator could have a component of a controlled type, as long as that type is declared in some other (non-generic) package. One possible solution would be to implement Numerics.@!Discrete_@!Random in terms of Numerics.@!Float_@!Random, using a component of Numerics.@!Float_@!Random.Generator to implement Numerics.@!Float_@!Random.@!Generator]}.]} Clearly some level of indirection is required in the implementation of a Generator, since the parameter mode is @key(in) for all operations on a Generator. For this reason, Numerics.Float_Random and Numerics.Discrete_Random cannot be declared pure. @end{ImplNote} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Generator needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}) in every instantiation of Numerics.Discrete_Random.]} An object of the limited private type Generator is associated with a sequence of random numbers. Each generator has a hidden (internal) state, which the operations on generators use to determine the position in the associated sequence. @PDefn{unspecified} All generators are implicitly initialized to an unspecified state that does not vary from one program execution to another; they may also be explicitly initialized, or reinitialized, to a time-dependent state, to a previously saved state, or to a state uniquely denoted by an integer value. @begin{Discussion} The repeatability provided by the implicit initialization may be exploited for testing or debugging purposes. @end{Discussion} An object of the private type State can be used to hold the internal state of a generator. Such objects are only needed if the application is designed to save and restore generator states or to examine or manufacture them. @Trailing@;The operations on generators affect the state and therefore the future values of the associated sequence. The semantics of the operations on generators and states are defined below. @begin{DescribeCode} @begin{Example} @key[function] Random (Gen : Generator) @key[return] Uniformly_Distributed; @key[function] Random (Gen : Generator) @key[return] Result_Subtype; @end{Example} @Trailing@;Obtains the @lquotes@;next@rquotes@; random number from the given generator, relative to its current state, according to an implementation-defined algorithm. The result of the function in Numerics.Float_Random is delivered as a value of the subtype Uniformly_Distributed, which is a subtype of the predefined type Float having a range of 0.0 .. 1.0. The result of the function in an instantiation of Numerics.Discrete_Random is delivered as a value of the generic formal subtype Result_Subtype. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2],Text=[The algorithms for random number generation.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The algorithm is the subject of a @DocReqName@;, so we don't separately summarize this implementation-defined item.]} @end{Discussion} @begin{Reason} The requirement for a level of indirection in accessing the internal state of a generator arises from the desire to make Random a function, rather than a procedure. @end{Reason} @begin{Example} @key[procedure] Reset (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] Reset (Gen : @key[in] Generator); @end{Example} @Trailing@PDefn{unspecified} Sets the state of the specified generator to one that is an unspecified function of the value of the parameter Initiator (or to a time-dependent state, if only a generator parameter is specified). @Defn2{Term=[Time-dependent Reset procedure],Sec=(of the random number generator)} The latter form of the procedure is known as the @i{time-dependent Reset procedure}. @begin{ImplNote} The time-dependent Reset procedure can be implemented by mapping the current time and date as determined by the system clock into a state, but other implementations are possible. For example, a white-noise generator or a radioactive source can be used to generate time-dependent states. @end{ImplNote} @begin{Example} @key[procedure] Save (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] Reset (Gen : @key[in] Generator; From_State : @key[in] State); @end{Example} @Trailing@;Save obtains the current state of a generator. Reset gives a generator the specified state. A generator that is reset to a state previously obtained by invoking Save is restored to the state it had when Save was invoked. @begin{Example} @key[function] Image (Of_State : State) @key[return] String; @key[function] Value (Coded_State : String) @key[return] State; @end{Example} Image provides a representation of a state coded (in an implementation-defined way) as a string whose length is bounded by the value of Max_Image_Width. Value is the inverse of Image: Value(Image(S)) = S for each state S that can be obtained from a generator by invoking Save. @ImplDef{The string representation of a random number generator's state.} @end{DescribeCode} @end{StaticSem} @begin{RunTime} @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Instantiation of Numerics.Discrete_Random with a subtype having a null range raises Constraint_Error. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0050],ARef=[AI95-00089]} @ChgDeleted{Version=[1],Text=[@IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Invoking Value with a string that is not the image of any generator state raises Constraint_Error.]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0050],ARef=[AI95-00089]} @ChgAdded{Version=[1],Text=[It is a bounded error to invoke Value with a string that is not the image of any generator state. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the error is detected, Constraint_Error or Program_Error is raised. Otherwise, a call to Reset with the resulting state will produce a generator such that calls to Random with this generator will produce a sequence of values of the appropriate subtype, but which might not be random in character. That is, the sequence of values might not fulfill the implementation requirements of this subclause.]} @end{Bounded} @begin{ImplReq} A sufficiently long sequence of random numbers obtained by successive calls to Random is approximately uniformly distributed over the range of the result subtype. The Random function in an instantiation of Numerics.Discrete_Random is guaranteed to yield each value in its result subtype in a finite number of calls, provided that the number of such values does not exceed 2 @+[15]. Other performance requirements for the random number generator, which apply only in implementations conforming to the Numerics Annex, and then only in the @lquotes@;strict@rquotes@; mode defined there (see @RefSecNum{Numeric Performance Requirements}), are given in @RefSecNum{Performance Requirements for Random Number Generation}. @end{ImplReq} @begin{DocReq} No one algorithm for random number generation is best for all applications. To enable the user to determine the suitability of the random number generators for the intended application, the implementation shall describe the algorithm used and shall give its period, if known exactly, or a lower bound on the period, if the exact period is unknown. Periods that are so long that the periodicity is unobservable in practice can be described in such terms, without giving a numerical bound. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The algorithm used for random number generation, including a description of its period.]}]} The implementation also shall document the minimum time interval between calls to the time-dependent Reset procedure that are guaranteed to initiate different sequences, and it shall document the nature of the strings that Value will accept without raising Constraint_Error. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2],Text=[The minimum time interval between calls to the time-dependent Reset procedure that are guaranteed to initiate different random number sequences.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The minimum time interval between calls to the time-dependent Reset procedure that is guaranteed to initiate different random number sequences.]}]} @end{DocReq} @begin{ImplAdvice} Any storage associated with an object of type Generator should be reclaimed on exit from the scope of the object. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2],Text=[Any storage associated with an object of type Generator of the random number packages should be reclaimed on exit from the scope of the object.]}]} @begin{Ramification} A level of indirection is implicit in the semantics of the operations, given that they all take parameters of mode @key(in). This implies that the full type of Generator probably should be a controlled type, with appropriate finalization to reclaim any heap-allocated storage. @end{Ramification} If the generator period is sufficiently long in relation to the number of distinct initiator values, then each possible value of Initiator passed to Reset should initiate a sequence of random numbers that does not, in a practical sense, overlap the sequence initiated by any other value. If this is not possible, then the mapping between initiator values and generator states should be a rapidly varying function of the initiator value. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Each value of Initiator passed to Reset for the random number packages should initiate a distinct sequence of random numbers, or, if that is not possible, be at least a rapidly varying function of the initiator value.]}]} @end{ImplAdvice} @begin{Notes} If two or more tasks are to share the same generator, then the tasks have to synchronize their access to the generator as for any shared variable (see @RefSecNum(Shared Variables)). Within a given implementation, a repeatable random number sequence can be obtained by relying on the implicit initialization of generators or by explicitly initializing a generator with a repeatable initiator value. Different sequences of random numbers can be obtained from a given generator in different program executions by explicitly initializing the generator to a time-dependent state. A given implementation of the Random function in Numerics.Float_Random may or may not be capable of delivering the values 0.0 or 1.0. Portable applications should assume that these values, or values sufficiently close to them to behave indistinguishably from them, can occur. If a sequence of random integers from some fixed range is needed, the application should use the Random function in an appropriate instantiation of Numerics.Discrete_Random, rather than transforming the result of the Random function in Numerics.Float_Random. However, some applications with unusual requirements, such as for a sequence of random integers each drawn from a different range, will find it more convenient to transform the result of the floating point Random function. For @R[M] @geq 1, the expression @begin{Example} Integer(Float(M) * Random(G)) mod M @end{Example} @NoPrefix@;transforms the result of Random(G) to an integer uniformly distributed over the range 0 .. @R[M]@en@;1; it is valid even if Random delivers 0.0 or 1.0. Each value of the result range is possible, provided that M is not too large. Exponentially distributed (floating point) random numbers with mean and standard deviation 1.0 can be obtained by the transformation @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} -Log(Random(G) + Float'Model_Small)@Chg{Version=[2],New=[],Old=[)]} @end{Example} @NoPrefix@;where Log comes from Numerics.Elementary_Functions (see @RefSecNum{Elementary Functions}); in this expression, the addition of Float'Model_Small avoids the exception that would be raised were Log to be given the value zero, without affecting the result (in most implementations) when Random returns a nonzero value. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of a program that plays a simulated dice game:} @begin{Example}@Trailing @key[with] Ada.Numerics.Discrete_Random; @key[procedure] Dice_Game @key[is]@Softpage @key[subtype] Die @key[is] Integer @key[range] 1 .. 6; @key[subtype] Dice @key[is] Integer @key[range] 2*Die'First .. 2*Die'Last; @key[package] Random_Die @key[is] @key[new] Ada.Numerics.Discrete_Random (Die); @key[use] Random_Die; G : Generator; D : Dice;@Softpage @key[begin]@Softpage Reset (G); -- @RI{Start the generator in a unique state in each run} @key[loop] -- @RI{Roll a pair of dice; sum and process the results} D := Random(G) + Random(G); ... @key[end] @key[loop];@Softpage @key[end] Dice_Game; @end{Example} @Leading@Keepnext@i{Example of a program that simulates coin tosses:} @begin{Example}@Trailing @key[with] Ada.Numerics.Discrete_Random; @key[procedure] Flip_A_Coin @key[is]@Softpage @key[type] Coin @key[is] (Heads, Tails); @key[package] Random_Coin @key[is] @key[new] Ada.Numerics.Discrete_Random (Coin); @key[use] Random_Coin; G : Generator;@Softpage @key[begin]@Softpage Reset (G); -- @RI{Start the generator in a unique state in each run} @key[loop] -- @RI{Toss a coin and process the result} @key[case] Random(G) @key[is] @key[when] Heads => ... @key[when] Tails => ... @key[end] @key[case]; ... @key[end] @key[loop];@Softpage @key[end] Flip_A_Coin; @end{Example} @Leading@Keepnext@i{Example of a parallel simulation of a physical system, with a separate generator of event probabilities in each task:} @begin{Example} @key[with] Ada.Numerics.Float_Random; @key[procedure] Parallel_Simulation @key[is]@Softpage @key[use] Ada.Numerics.Float_Random; @key[task] @key[type] Worker @key[is] @key[entry] Initialize_Generator (Initiator : @key[in] Integer); ... @key[end] Worker; W : @key[array] (1 .. 10) @key[of] Worker;@Softpage @key[task] @key[body] Worker @key[is] G : Generator; Probability_Of_Event : Uniformly_Distributed; @key[begin]@Softpage @key[accept] Initialize_Generator (Initiator : @key[in] Integer) @key[do] Reset (G, Initiator); @key[end] Initialize_Generator; @key[loop] ... Probability_Of_Event := Random(G); ... @key[end] @key[loop]; @key[end] Worker;@Softpage @key[begin]@Softpage -- @RI{Initialize the generators in the Worker tasks to different states} @key[for] I @key[in] W'Range @key[loop] W(I).Initialize_Generator (I); @key[end] @key[loop]; ... -- @RI{Wait for the Worker tasks to terminate}@Softpage @key[end] Parallel_Simulation; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the last example:} Although each Worker task initializes its generator to a different state, those states will be the same in every execution of the program. The generator states can be initialized uniquely in each program execution by instantiating Ada.Numerics.Discrete_Random for the type Integer in the main procedure, resetting the generator obtained from that instance to a time-dependent state, and then using random integers obtained from that generator to initialize the generators in each Worker task. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Type Generator in Numerics.Float_Random and in an instance of Numerics.Discrete_Random is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and Generator does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in Generator, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0050],ARef=[AI95-00089-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Made the passing of an incorrect Image of a generator a bounded error, as it may not be practical to check for problems (if a generator consists of several related values).]} @end{DiffWord95} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_standard.mss�����������������������������������������������������0000755�0001752�0001001�00000056672�12273462240�020633� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_standard.mss,v $ } @comment{ $Revision: 1.33 $ $Date: 2006/10/18 00:25:28 $ $Author: Randy $ } @Part(predefstandard, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:28 $} @RMNewPage@Comment{For printed RM Ada 2005} @LabeledClause{The Package Standard} @begin{Intro} This clause outlines the specification of the package Standard containing all predefined identifiers in the language. @PDefn{unspecified} The corresponding package body is not specified by the language. The operators that are predefined for the types declared in the package Standard are given in comments since they are implicitly declared. @Defn2{Term=[italics],Sec=(pseudo-names of anonymous types)} Italics are used for pseudo-names of anonymous types (such as @i{root_real}) and for undefined information (such as @i{implementation-defined}). @begin{Ramification} All of the predefined operators are of convention Intrinsic. @end{Ramification} @end{Intro} @begin{StaticSem} @Leading@;The library package Standard has the following declaration: @ImplDef{The names and characteristics of the numeric subtypes declared in the visible part of package Standard.} @begin{Example} @RootLibUnit{Standard}@key[package] Standard @key[is] @key[pragma] Pure(Standard); @key[type] @AdaTypeDefn{Boolean} @key[is] (False, True); @Keepnext --@RI{ The predefined relational operators for this type are as follows:} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "<" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] ">" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; @Keepnext --@RI{ The predefined logical operators and the predefined logical} --@RI{ negation operator are as follows:} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "@key[and]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; -- @key[function] "@key[or]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; -- @key[function] "@key[xor]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "@key[not]" (Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} --@RI{ The integer type root_integer @Chg{Version=[2],New=[and the],Old=[is predefined.]}} --@RI{ @Chg{Version=[2],New=[],Old=[The ]}corresponding universal type @Chg{Version=[2],New=[],Old=[is ]}universal_integer@Chg{Version=[2],New=[ are predefined],Old=[]}.} @key[type] @AdaTypeDefn{Integer} @key[is] @key{range} @RI{implementation-defined}; @key[subtype] @AdaSubtypeDefn{Name=[Natural],Of=[Integer]} @key[is] Integer @key[range] 0 .. Integer'Last; @key[subtype] @AdaSubtypeDefn{Name=[Positive],Of=[Integer]} @key[is] Integer @key[range] 1 .. Integer'Last; @Keepnext --@RI{ The predefined operators for type Integer are as follows:} -- @key[function] "=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "<" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] ">" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "+" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "-" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[abs]" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "+" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "-" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "*" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "/" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[rem]" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[mod]" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "**" (Left : Integer'Base; Right : Natural) -- @key[return] Integer'Base; --@RI{ The specification of each operator for the type} --@RI{ root_integer, or for any additional predefined integer} --@RI{ type, is obtained by replacing Integer by the name of the type} --@RI{ in the specification of the corresponding operator of the type} --@RI{ Integer. The right operand of the exponentiation operator} --@RI{ remains as subtype Natural.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} --@RI{ The floating point type root_real @Chg{Version=[2],New=[and the],Old=[is predefined.]}} --@RI{ @Chg{Version=[2],New=[],Old=[The ]}corresponding universal type @Chg{Version=[2],New=[],Old=[is ]}universal_real@Chg{Version=[2],New=[ are predefined],Old=[]}.} @key[type] @AdaTypeDefn{Float} @key[is] @key{digits} @RI{implementation-defined}; @Keepnext --@RI{ The predefined operators for this type are as follows:} -- @key[function] "=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "<" (Left, Right : Float) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Float) @key[return] Boolean; -- @key[function] ">" (Left, Right : Float) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "+" (Right : Float) @key[return] Float; -- @key[function] "-" (Right : Float) @key[return] Float; -- @key[function] "@key[abs]" (Right : Float) @key[return] Float; -- @key[function] "+" (Left, Right : Float) @key[return] Float; -- @key[function] "-" (Left, Right : Float) @key[return] Float; -- @key[function] "*" (Left, Right : Float) @key[return] Float; -- @key[function] "/" (Left, Right : Float) @key[return] Float; -- @key[function] "**" (Left : Float; Right : Integer'Base) @key[return] Float; --@RI{ The specification of each operator for the type root_real, or for} --@RI{ any additional predefined floating point type, is obtained by} --@RI{ replacing Float by the name of the type in the specification of the} --@RI{ corresponding operator of the type Float.} @Keepnext --@RI{ In addition, the following operators are predefined for the root} --@RI{ numeric types:} @key[function] "*" (Left : @RI{root_integer}; Right : @RI{root_real}) @key[return] @RI{root_real}; @key[function] "*" (Left : @RI{root_real}; Right : @RI{root_integer}) @key[return] @RI{root_real}; @key[function] "/" (Left : @RI{root_real}; Right : @RI{root_integer}) @key[return] @RI{root_real}; --@RI{ The type universal_fixed is predefined.} --@RI{ The only multiplying operators defined between} --@RI{ fixed point types are} @key[function] "*" (Left : @RI[universal_fixed]; Right : @RI[universal_fixed]) @key[return] @RI[universal_fixed]; @key[function] "/" (Left : @RI[universal_fixed]; Right : @RI[universal_fixed]) @key[return] @RI[universal_fixed]; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[ --@RI{ The type universal_access is predefined.} --@RI{ The following equality operators are predefined:}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[ @key[function] "=" (Left, Right: @RI[universal_access]) @key[return] Boolean; @key[function] "/=" (Left, Right: @RI[universal_access]) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @tabclear()@tabset(P7, P14, P21, P28, P37, P44, P51, P58, P64) @comment{blank line} --@RI{ The declaration of type Character is based on the standard ISO 8859-1 character set.} @comment{blank line} --@RI{ There are no character literals corresponding to the positions for control characters.} --@RI{ They are indicated in italics in this definition. See @refsecnum[Character Types].} @comment[blank line] @key[type] @AdaTypeDefn{Character} @key[is] (@RI[nul],@\@RI[soh],@\@RI[stx],@\@RI[etx],@\@RI[eot],@\@RI[enq],@\@RI[ack],@\@RI[bel],@\--@RI{0 (16#00#) .. 7 (16#07#)} @RI[bs],@\@RI[ht],@\@RI[lf],@\@RI[vt],@\@RI[ff],@\@RI[cr],@\@RI[so],@\@RI[si],@\--@RI{8 (16#08#) .. 15 (16#0F#)} @comment{blank line} @RI[dle],@\@RI[dc1],@\@RI[dc2],@\@RI[dc3],@\@RI[dc4],@\@RI[nak],@\@RI[syn],@\@RI[etb],@\--@RI{16 (16#10#) .. 23 (16#17#)} @RI[can],@\@RI[em],@\@RI[sub],@\@RI[esc],@\@RI[fs],@\@RI[gs],@\@RI[rs],@\@RI[us],@\--@RI{24 (16#18#) .. 31 (16#1F#)} @comment{blank line} ' ',@\'!',@\'"',@\'#',@\'$',@\'%',@\'&',@\''',@\--@RI{32 (16#20#) .. 39 (16#27#)} '(',@\')',@\'*',@\'+',@\',',@\'-',@\'.',@\'/',@\--@RI{40 (16#28#) .. 47 (16#2F#)} @comment{blank line} '0',@\'1',@\'2',@\'3',@\'4',@\'5',@\'6',@\'7',@\--@RI{48 (16#30#) .. 55 (16#37#)} '8',@\'9',@\':',@\';',@\'<',@\'=',@\'>',@\'?',@\--@RI{56 (16#38#) .. 63 (16#3F#)} @comment{blank line} '@@',@\'A',@\'B',@\'C',@\'D',@\'E',@\'F',@\'G',@\--@RI{64 (16#40#) .. 71 (16#47#)} 'H',@\'I',@\'J',@\'K',@\'L',@\'M',@\'N',@\'O',@\--@RI{72 (16#48#) .. 79 (16#4F#)} @comment{blank line} 'P',@\'Q',@\'R',@\'S',@\'T',@\'U',@\'V',@\'W',@\--@RI{80 (16#50#) .. 87 (16#57#)} 'X',@\'Y',@\'Z',@\'[',@\'\',@\']',@\'^',@\'_',@\--@RI{88 (16#58#) .. 95 (16#5F#)} @comment{blank line} '`',@\'a',@\'b',@\'c',@\'d',@\'e',@\'f',@\'g',@\--@RI{96 (16#60#) .. 103 (16#67#)} 'h',@\'i',@\'j',@\'k',@\'l',@\'m',@\'n',@\'o',@\--@RI{104 (16#68#) .. 111 (16#6F#)} @comment{blank line} 'p',@\'q',@\'r',@\'s',@\'t',@\'u',@\'v',@\'w',@\--@RI{112 (16#70#) .. 119 (16#77#)} 'x',@\'y',@\'z',@\'{',@\'|',@\'}',@\'~',@\@RI[del],@\--@RI{120 (16#78#) .. 127 (16#7F#)} @Comment{Blank line} @RI[reserved_128],@\@RI[reserved_129],@\@RI[bph],@\@RI[nbh],@\@\@\--@RI{128 (16#80#) .. 131 (16#83#)} @RI[reserved_132],@\@RI[nel],@\@RI[ssa],@\@RI[esa],@\@\@\@\--@RI{132 (16#84#) .. 135 (16#87#)} @RI[hts],@\@RI[htj],@\@RI[vts],@\@RI[pld],@\@RI[plu],@\@RI[ri],@\@RI[ss2],@\@RI[ss3],@\--@RI{136 (16#88#) .. 143 (16#8F#)} @comment{blank line} @RI[dcs],@\@RI[pu1],@\@RI[pu2],@\@RI[sts],@\@RI[cch],@\@RI[mw],@\@RI[spa],@\@RI[epa],@\--@RI{144 (16#90#) .. 151 (16#97#)} @RI[sos],@\@RI[reserved_153],@\@RI[sci],@\@RI[csi],@\@\@\@\--@RI{152 (16#98#) .. 155 (16#9B#)} @RI[st],@\@RI[osc],@\@RI[pm],@\@RI[apc],@\@\@\@\@\--@RI{156 (16#9C#) .. 159 (16#9F#)} @comment{blank line} ' ',@\'@latin1(161)',@\'@latin1(162)',@\'@latin1(163)',@\'@latin1(164)',@\'@latin1(165)',@\'@latin1(166)',@\'@latin1(167)',@\--@RI{160 (16#A0#) .. 167 (16#A7#)} '@latin1(168)',@\'@latin1(169)',@\'@latin1(170)',@\'@latin1(171)',@\'@latin1(172)',@\'@latin1(173)',@\'@latin1(174)',@\'@latin1(175)',@\--@RI{168 (16#A8#) .. 175 (16#AF#)} @comment{blank line} '@latin1(176)',@\'@latin1(177)',@\'@latin1(178)',@\'@latin1(179)',@\'@latin1(180)',@\'@latin1(181)',@\'@latin1(182)',@\'@latin1(183)',@\--@RI{176 (16#B0#) .. 183 (16#B7#)} '@latin1(184)',@\'@latin1(185)',@\'@latin1(186)',@\'@latin1(187)',@\'@latin1(188)',@\'@latin1(189)',@\'@latin1(190)',@\'@latin1(191)',@\--@RI{184 (16#B8#) .. 191 (16#BF#)} @comment{blank line} '@latin1(192)',@\'@latin1(193)',@\'@latin1(194)',@\'@latin1(195)',@\'@latin1(196)',@\'@latin1(197)',@\'@latin1(198)',@\'@latin1(199)',@\--@RI{192 (16#C0#) .. 199 (16#C7#)} '@latin1(200)',@\'@latin1(201)',@\'@latin1(202)',@\'@latin1(203)',@\'@latin1(204)',@\'@latin1(205)',@\'@latin1(206)',@\'@latin1(207)',@\--@RI{200 (16#C8#) .. 207 (16#CF#)} @comment{blank line} '@latin1(208)',@\'@latin1(209)',@\'@latin1(210)',@\'@latin1(211)',@\'@latin1(212)',@\'@latin1(213)',@\'@latin1(214)',@\'@latin1(215)',@\--@RI{208 (16#D0#) .. 215 (16#D7#)} '@latin1(216)',@\'@latin1(217)',@\'@latin1(218)',@\'@latin1(219)',@\'@latin1(220)',@\'@latin1(221)',@\'@latin1(222)',@\'@latin1(223)',@\--@RI{216 (16#D8#) .. 223 (16#DF#)} @comment{blank line} '@latin1(224)',@\'@latin1(225)',@\'@latin1(226)',@\'@latin1(227)',@\'@latin1(228)',@\'@latin1(229)',@\'@latin1(230)',@\'@latin1(231)',@\--@RI{224 (16#E0#) .. 231 (16#E7#)} '@latin1(232)',@\'@latin1(233)',@\'@latin1(234)',@\'@latin1(235)',@\'@latin1(236)',@\'@latin1(237)',@\'@latin1(238)',@\'@latin1(239)',@\--@RI{232 (16#E8#) .. 239 (16#EF#)} @comment{blank line} '@latin1(240)',@\'@latin1(241)',@\'@latin1(242)',@\'@latin1(243)',@\'@latin1(244)',@\'@latin1(245)',@\'@latin1(246)',@\'@latin1(247)',@\--@RI{240 (16#F0#) .. 247 (16#F7#)} '@latin1(248)',@\'@latin1(249)',@\'@latin1(250)',@\'@latin1(251)',@\'@latin1(252)',@\'@latin1(253)',@\'@latin1(254)',@\'@latin1(255)'@Chg{Version=[2],New=[);],Old=[,@\]}--@RI{248 (16#F8#) .. 255 (16#FF#)} --@RI{ The predefined operators for the type Character are the same as for} --@RI{ any enumeration type.} @Softpage@; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]}@Comment{Odd missing paragraph number here} @Chg{Version=[2],New=[],Old=[@noparanum@;]} --@RI{ The declaration of type Wide_Character is based on the standard @Chg{Version=[2],New=[ISO/IEC],Old=[ISO]} 10646@Chg{Version=[2],New=[:2003],Old=[]} BMP character@Chg{Version=[2],New=[],Old=[ set.]}} --@RI{ @Chg{Version=[2],New=[set. ],Old=[]}The first 256 positions have the same contents as type Character. See @refsecnum[Character types].} @comment[blank line] @key[type] @AdaTypeDefn{Wide_Character} @key[is] (@RI[nul], @RI[soh] ... @RI[@Chg{Version=[2],New=[Hex_0000FFFE],Old=[FFFE]}], @RI[@Chg{Version=[2],New=[Hex_0000FFFF],Old=[FFFF]}]); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[ --@RI[ The declaration of type Wide_Wide_Character is based on the full] --@RI[ ISO/IEC 10646:2003 character set. The first 65536 positions have the] --@RI[ same contents as type Wide_Character. See @refsecnum[Character types].] @comment[blank line] @key[type] @AdaTypeDefn{Wide_Wide_Character} @key[is] (@RI[nul], @RI[soh] ... @RI[Hex_7FFFFFFE], @RI[Hex_7FFFFFFF]); @key[for] Wide_Wide_Character'Size @key[use] 32;]} @ChgRef{Version=[2],Kind=[Added]}@Comment{Odd missing paragraph number here} @Chg{Version=[2],New=[],Old=[@noparanum@;]} @key[package] @AdaPackDefn{ASCII} @key[is] ... @key[end] ASCII; --@RI{Obsolescent; see @RefSecNum[ASCII]} @Defn2{Term=[ASCII], Sec=(package physically nested within the declaration of Standard)} @comment[blank line] --@RI{ Predefined string types:} @comment[blank line] @key[type] @AdaTypeDefn{String} @key[is] @key[array](Positive @key[range] <>) @key[of] Character; @key[pragma] Pack(String); @Keepnext --@RI{ The predefined operators for this type are as follows:} -- @key[function] "=" (Left, Right: String) @key[return] Boolean; -- @key[function] "/=" (Left, Right: String) @key[return] Boolean;@Softpage -- @key[function] "<" (Left, Right: String) @key[return] Boolean; -- @key[function] "<=" (Left, Right: String) @key[return] Boolean; -- @key[function] ">" (Left, Right: String) @key[return] Boolean; -- @key[function] ">=" (Left, Right: String) @key[return] Boolean; -- @key[function] "&" (Left: String; Right: String) @key[return] String; -- @key[function] "&" (Left: Character; Right: String) @key[return] String; -- @key[function] "&" (Left: String; Right: Character) @key[return] String; -- @key[function] "&" (Left: Character; Right: Character) @key[return] String; @key[type] @AdaTypeDefn{Wide_String} @key[is] @key[array](Positive @key[range] <>) @key[of] Wide_Character; @key[pragma] Pack(Wide_String); --@RI{ The predefined operators for this type correspond to those for String.} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ @key[type] @AdaTypeDefn{Wide_Wide_String} @key[is array] (Positive @key[range] <>) @key[of] Wide_Wide_Character; @key[pragma] Pack (Wide_Wide_String);]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ --@RI[ The predefined operators for this type correspond to those for String.]]} @key[type] @AdaTypeDefn{Duration} @key[is] @key[delta] @RI{implementation-defined} @key[range] @RI{implementation-defined}; --@RI{ The predefined operators for the type Duration are the same as for} --@RI{ any fixed point type.} @Keepnext --@RI{ The predefined exceptions:} @AdaExcDefn{Constraint_Error}: @key[exception]; @AdaExcDefn{Program_Error} : @key[exception]; @AdaExcDefn{Storage_Error} : @key[exception]; @AdaExcDefn{Tasking_Error} : @key[exception]; @key[end] Standard; @end{Example} Standard has no private part. @begin{Reason} This is important for portability. All library packages are children of Standard, and if Standard had a private part then it would be visible to all of them. @end{reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} In each of the types Character@Chg{Version=[2],New=[,],Old=[ and]} Wide_Character@Chg{Version=[2],New=[, and Wide_Wide_Character],Old=[]}, the character literals for the space character (position 32) and the non-breaking space character (position 160) correspond to different values. Unless indicated otherwise, each occurrence of the character literal ' ' in this International Standard refers to the space character. Similarly, the character literals for hyphen (position 45) and soft hyphen (position 173) correspond to different values. Unless indicated otherwise, each occurrence of the character literal '@en@;' in this International Standard refers to the hyphen character. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(package_body of Standard)} Elaboration of the body of Standard has no effect. @begin{Discussion} Note that the language does not define where this body appears in the environment @nt{declarative_part} @em see @RefSec{Program Structure and Compilation Issues}. @end{Discussion} @end{RunTime} @begin{ImplPerm} An implementation may provide additional predefined integer types and additional predefined floating point types. Not all of these types need have names. @begin{Honest} An implementation may add representation items to package Standard, for example to specify the internal codes of type Boolean, or the Small of type Duration. @end{Honest} @end{ImplPerm} @begin{ImplAdvice} If an implementation provides additional named predefined integer types, then the names should end with @lquotes@;Integer@rquotes@; as in @lquotes@;Long_Integer@rquotes@;. If an implementation provides additional named predefined floating point types, then the names should end with @lquotes@;Float@rquotes@; as in @lquotes@;Long_Float@rquotes@;. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an implementation provides additional named predefined integer types, then the names should end with @lquotes@;Integer@rquotes@;. If an implementation provides additional named predefined floating point types, then the names should end with @lquotes@;Float@rquotes@;.]}]} @end{ImplAdvice} @begin{Notes} Certain aspects of the predefined entities cannot be completely described in the language itself. For example, although the enumeration type Boolean can be written showing the two enumeration literals False and True, the short-circuit control forms cannot be expressed in the language. As explained in @RefSec{Declarative Region} and @RefSec{The Compilation Process}, the declarative region of the package Standard encloses every library unit and consequently the main subprogram; the declaration of every library unit is assumed to occur within this declarative region. @nt{Library_item}s are assumed to be ordered in such a way that there are no forward semantic dependences. However, as explained in @RefSec{Visibility}, the only library units that are visible within a given compilation unit are the library units named by all @nt{with_clause}s that apply to the given unit, and moreover, within the declarative region of a given library unit, that library unit itself. If all @nt{block_statement}s of a program are named, then the name of each program unit can always be written as an expanded name starting with Standard (unless Standard is itself hidden). The name of a library unit cannot be a homograph of a name (such as Integer) that is already declared in Standard. The exception Standard.Numeric_Error is defined in @RefSecNum{Numeric_Error}. @begin{Discussion} The declaration of Natural needs to appear between the declaration of Integer and the (implicit) declaration of the "**" operator for Integer, because a formal parameter of "**" is of subtype Natural. This would be impossible in normal code, because the implicit declarations for a type occur immediately after the type declaration, with no possibility of intervening explicit declarations. But we're in Standard, and Standard is somewhat magic anyway. Using Natural as the subtype of the formal of "**" seems natural; it would be silly to have a textual rule about Constraint_Error being raised when there is a perfectly good subtype that means just that. Furthermore, by not using Integer for that formal, it helps remind the reader that the exponent remains Natural even when the left operand is replaced with the derivative of Integer. It doesn't logically imply that, but it's still useful as a reminder. In any case, declaring these general-purpose subtypes of Integer close to Integer seems more readable than declaring them much later. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Package Standard is declared to be pure. @begin{discussion} The introduction of the types Wide_Character and Wide_String is not an Ada 95 extension to Ada 83, since ISO WG9 has approved these as an authorized extension of the original Ada 83 standard that is part of that standard. @end{discussion} @end{Extend83} @begin{DiffWord83} Numeric_Error is made obsolescent. The declarations of Natural and Positive are moved to just after the declaration of Integer, so that "**" can refer to Natural without a forward reference. There's no real need to move Positive, too @em it just came along for the ride. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Types Wide_Wide_Character and Wide_Wide_String are new.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inconsistencies associated with these types are documented in @RefSecNum{Character Types} and @RefSecNum{String Types}.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Type @i<universal_access> and the equality operations for it are new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0028],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter type for the Boolean operators declared in Standard..]} @end{DiffWord95} ����������������������������������������������������������������������org.adaic.arm_form/source_2005/pre_strings.mss������������������������������������������������������0000755�0001752�0001001�00000371043�12273462240�020514� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_strings.mss,v $ } @comment{ $Revision: 1.52 $ $Date: 2006/10/19 06:40:33 $ $Author: Randy $ } @Part(predefstrings, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:33 $} @LabeledClause{String Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} This clause presents the specifications of the package Strings and several child packages, which provide facilities for dealing with string data. Fixed-length, bounded-length, and unbounded-length strings are supported, for @Chg{Version=[2],New=[],Old=[both]} String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2],New=[, and Wide_Wide_String],Old=[]}. The string-handling subprograms include searches for pattern strings and for characters in program-specified sets, translation (via a character-to-character mapping), and transformation (replacing, inserting, overwriting, and deleting of substrings). @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This clause is new to Ada 95. @end{Extend83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included Wide_Wide_String in this description; the individual changes are documented as extensions as needed.]} @end{Diffword95} @LabeledSubClause{The Package Strings} @begin{Intro} The package Strings provides declarations common to the string handling packages. @end{Intro} @begin{StaticSem} @Leading@;The library package Strings has the following declaration: @begin{example} @ChildUnit{Parent=[Ada],Child=[Strings]}@key[package] Ada.Strings @key[is] @key[pragma] Pure(Strings); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @AdaObjDefn{Space} : @key[constant] Character := ' '; @AdaObjDefn{Wide_Space} : @key[constant] Wide_Character := ' ';@Chg{Version=[2],New=[ @AdaObjDefn{Wide_Wide_Space} : @key[constant] Wide_Wide_Character := ' ';],Old=[]} @AdaExcDefn{Length_Error}, @AdaExcDefn{Pattern_Error}, @AdaExcDefn{Index_Error}, @AdaExcDefn{Translation_Error} : @key[exception]; @key[type] @AdaTypeDefn{Alignment} @key[is] (Left, Right, Center); @key[type] @AdaTypeDefn{Truncation} @key[is] (Left, Right, Error); @key[type] @AdaTypeDefn{Membership} @key[is] (Inside, Outside); @key[type] @AdaTypeDefn{Direction} @key[is] (Forward, Backward); @key[type] @AdaTypeDefn{Trim_End} @key[is] (Left, Right, Both); @key[end] Ada.Strings; @end{example} @end{StaticSem} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Constant Wide_Wide_Space is newly added to Ada.Strings. If Ada.Strings is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Wide_Wide_Space is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @Comment{@RmNewPage Insert page break so printed Ada 95 w/ Corr RM looks better.} @LabeledSubClause{The Package Strings.Maps} @begin{Intro} The package Strings.Maps defines the types, operations, and other entities needed for character sets and character-to-character mappings. @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Maps has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada.Strings],Child=[Maps]}@key[package] Ada.Strings.Maps @key[is] @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Maps); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@RI{ Representation for a set of character values:} @key[type] @AdaTypeDefn{Character_Set} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Character_Set);],Old=[]} @AdaObjDefn{Null_Set} : @key[constant] Character_Set; @key[type] @AdaTypeDefn{Character_Range} @key[is] @Key[record] Low : Character; High : Character; @key[end] @key[record]; -- @RI[Represents Character range Low..High] @key[type] @AdaTypeDefn{Character_Ranges} @key[is] @key[array] (Positive @key[range] <>) @key[of] Character_Range; @key[function] @AdaSubDefn{To_Set} (Ranges : @key[in] Character_Ranges)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Set} (Span : @key[in] Character_Range)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Ranges} (Set : @key[in] Character_Set) @key[return] Character_Ranges; @key[function] "=" (Left, Right : @key[in] Character_Set) @key[return] Boolean; @key[function] "@key[not]" (Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[and]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[or]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[xor]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "-" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] @AdaSubDefn{Is_In} (Element : @key[in] Character; Set : @key[in] Character_Set) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Subset} (Elements : @key[in] Character_Set; Set : @key[in] Character_Set) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Character_Set; Right : @key[in] Character_Set) @key[return] Boolean @key[renames] Is_Subset; --@RI{ Alternative representation for a set of character values:} @key[subtype] @AdaSubtypeDefn{Name=[Character_Sequence],Of=[String]} @key[is] String; @key[function] @AdaSubDefn{To_Set} (Sequence : @key[in] Character_Sequence)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Set} (Singleton : @key[in] Character) @key[return] Character_Set; @key[function] @AdaSubDefn{To_Sequence} (Set : @key[in] Character_Set) @key[return] Character_Sequence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@RI{ Representation for a character to character mapping:} @key[type] @AdaTypeDefn{Character_Mapping} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Character_Mapping);],Old=[]} @key[function] @AdaSubDefn{Value} (Map : @key[in] Character_Mapping; Element : @key[in] Character) @key[return] Character; @AdaObjDefn{Identity} : @key[constant] Character_Mapping; @key[function] @AdaSubDefn{To_Mapping} (From, To : @key[in] Character_Sequence) @key[return] Character_Mapping; @key[function] @AdaSubDefn{To_Domain} (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @key[function] @AdaSubDefn{To_Range} (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @key{type} @AdaTypeDefn{Character_Mapping_Function} @key{is} @key{access} @key{function} (From : @key{in} Character) @key{return} Character; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Strings.Maps; @end{example} An object of type Character_Set represents a set of characters. Null_Set represents the set containing no characters. An object Obj of type Character_Range represents the set of characters in the range Obj.Low .. Obj.High. An object Obj of type Character_Ranges represents the union of the sets corresponding to Obj(I) for I in Obj'Range. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] To_Set (Ranges : @key[in] Character_Ranges) @key[return] Character_Set; @end{Example} @Trailing@;If Ranges'Length=0 then Null_Set is returned; otherwise the returned value represents the set corresponding to Ranges. @begin{Example}@Keepnext @key[function] To_Set (Span : @key[in] Character_Range) @key[return] Character_Set; @end{Example} The returned value represents the set containing each character in Span. @begin{Example}@Keepnext @key[function] To_Ranges (Set : @key[in] Character_Set) @key[return] Character_Ranges; @end{Example} @Trailing@;If Set = Null_Set then an empty Character_Ranges array is returned; otherwise the shortest array of contiguous ranges of Character values in Set, in increasing order of Low, is returned. @begin{Example}@Keepnext @key[function] "=" (Left, Right : @key[in] Character_Set) @key[return] Boolean; @end{Example} @Trailing@;The function "=" returns True if Left and Right represent identical sets, and False otherwise. @end{DescribeCode} @Trailing@;Each of the logical operators "@key[not]", "@key[and]", "@key[or]", and "@key[xor]" returns a Character_Set value that represents the set obtained by applying the corresponding operation to the set(s) represented by the parameter(s) of the operator. "@en"(Left, Right) is equivalent to "and"(Left, "not"(Right)). @begin{reason} The set minus operator is provided for efficiency.@end{reason} @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Is_In (Element : @key[in] Character; Set : @key[in] Character_Set); @key[return] Boolean; @end{Example} @Trailing@;Is_In returns True if Element is in Set, and False otherwise. @begin{Example}@Keepnext @key[function] Is_Subset (Elements : @key[in] Character_Set; Set : @key[in] Character_Set) @key[return] Boolean; @end{Example} @Trailing@;Is_Subset returns True if Elements is a subset of Set, and False otherwise. @begin{Example}@Keepnext @key[subtype] Character_Sequence @key[is] String; @end{Example} @Trailing@;The Character_Sequence subtype is used to portray a set of character values and also to identify the domain and range of a character mapping. @begin{reason} Although a named subtype is redundant @em the predefined type String could have been used for the parameter to To_Set and To_Mapping below @em the use of a differently named subtype identifies the intended purpose of the parameter. @end{reason} @begin{Example}@Keepnext @key[function] To_Set (Sequence : @key[in] Character_Sequence) @key[return] Character_Set;@* @key[function] To_Set (Singleton : @key[in] Character) @key[return] Character_Set; @end{Example} @Trailing@;Sequence portrays the set of character values that it explicitly contains (ignoring duplicates). Singleton portrays the set comprising a single Character. Each of the To_Set functions returns a Character_Set value that represents the set portrayed by Sequence or Singleton. @begin{Example}@Keepnext @key[function] To_Sequence (Set : @key[in] Character_Set) @key[return] Character_Sequence; @end{Example} @Trailing@;The function To_Sequence returns a Character_Sequence value containing each of the characters in the set represented by Set, in ascending order with no duplicates. @begin{Example}@Keepnext @key[type] Character_Mapping @key[is] @key[private]; @end{Example} @Trailing@;An object of type Character_Mapping represents a Character-to-Character mapping. @begin{Example}@Keepnext @key[function] Value (Map : @key[in] Character_Mapping; Element : @key[in] Character) @key[return] Character; @end{Example} @Trailing@;The function Value returns the Character value to which Element maps with respect to the mapping represented by Map. @end{DescribeCode} @Defn2{Term=[match], Sec=(a character to a pattern character)} A character C @i{matches} a pattern character P with respect to a given Character_Mapping value Map if Value(Map, C) = P. @Defn2{Term=[match], Sec=(a string to a pattern string)} A string S @i{matches} a pattern string P with respect to a given Character_Mapping if their lengths are the same and if each character in S matches its corresponding character in the pattern string P. @begin{Discussion} In an earlier version of the string handling packages, the definition of matching was symmetrical, namely C matches P if Value(Map,C) = Value(Map,P). However, applying the mapping to the pattern was confusing according to some reviewers. Furthermore, if the symmetrical version is needed, it can be achieved by applying the mapping to the pattern (via translation) prior to passing it as a parameter. @end{Discussion} String handling subprograms that deal with character mappings have parameters whose type is Character_Mapping. @begin{DescribeCode} @begin{Example}@Keepnext Identity : @key[constant] Character_Mapping; @end{Example} @Trailing@;Identity maps each Character to itself. @begin{Example}@Keepnext @key[function] To_Mapping (From, To : @key[in] Character_Sequence) @key[return] Character_Mapping; @end{Example} @Trailing@;To_Mapping produces a Character_Mapping such that each element of From maps to the corresponding element of To, and each other character maps to itself. If From'Length /= To'Length, or if some character is repeated in From, then Translation_Error is propagated. @begin{Example}@Keepnext @key[function] To_Domain (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @end{Example} @Trailing@;To_Domain returns the shortest Character_Sequence value D such that each character not in D maps to itself, and such that the characters in D are in ascending order. The lower bound of D is 1. @begin{Example}@Keepnext @key[function] To_Range (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0048],ARef=[AI95-00151-01]} @Trailing@;To_Range returns the Character_Sequence value R, @Chg{New=[],Old=[with lower bound 1 and upper bound Map'Length,]} such that if D = To_Domain(Map)@Chg{New=[, then R has the same bounds as D, and],Old=[ then]} D(I) maps to R(I) for each I in D'Range. @end{DescribeCode} An object F of type Character_Mapping_Function maps a Character value C to the Character value F.@key{all}(C), which is said to @i{match} C with respect to mapping function F. @Defn2[term=<match>,sec=<a character to a pattern character, with respect to a character mapping function>] @end{StaticSem} @begin{Notes} Character_Mapping and Character_Mapping_Function are used both for character equivalence mappings in the search subprograms (such as for case insensitivity) and as transformational mappings in the Translate subprograms. To_Domain(Identity) and To_Range(Identity) each returns the null string. @begin{Reason} Package Strings.Maps is not pure, since it declares an access-to-subprogram type. @end{Reason} @end{Notes} @begin{Examples} To_Mapping("ABCD", "ZZAB") returns a Character_Mapping that maps 'A' and 'B' to 'Z', 'C' to 'A', 'D' to 'B', and each other Character to itself. @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to types Character_Set and Character_Mapping, so that they can be used to declare default-initialized objects in preelaborated units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Strings.Maps is now Pure, so it can be used in pure units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0048],ARef=[AI95-00151-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of the range of the result of To_Range, since the Ada 95 definition makes no sense.]} @end{DiffWord95} @LabeledSubClause{Fixed-Length String Handling} @begin{Intro} The language-defined package Strings.Fixed provides string-handling subprograms for fixed-length strings; that is, for values of type Standard.String. Several of these subprograms are procedures that modify the contents of a String that is passed as an @key[out] or an @key[in] @key[out] parameter; each has additional parameters to control the effect when the logical length of the result differs from the parameter's length. For each function that returns a String, the lower bound of the returned value is 1. @begin{Discussion} @Chgref{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Most operations that @Chg{Version=[2],New=[yield],Old=[yields]} a String are provided both as a function and as a procedure. The functional form is possibly a more aesthetic style but may introduce overhead due to extra copying or dynamic memory usage in some implementations. Thus a procedural form, with an @key[in] @key[out] parameter so that all copying is done `in place', is also supplied.@end{discussion} The basic model embodied in the package is that a fixed-length string comprises significant characters and possibly padding (with space characters) on either or both ends. When a shorter string is copied to a longer string, padding is inserted, and when a longer string is copied to a shorter one, padding is stripped. The Move procedure in Strings.Fixed, which takes a String as an @key[out] parameter, allows the programmer to control these effects. Similar control is provided by the string transformation procedures. @end{Intro} @begin{StaticSem} @Leading@keepnext @Leading@;The library package Strings.Fixed has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Fixed]}@key[package] Ada.Strings.Fixed @key[is] @key[pragma] Preelaborate(Fixed); --@RI{ "Copy" procedure for strings of possibly different lengths} @key[procedure] @AdaSubDefn{Move} (Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@RI{ Search subprograms} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@;--@RI{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping) @key[return] String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@;--@RI{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Insert} (Source : @key[in] String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Right); @key[function] @AdaSubDefn{Delete} (Source : @key[in] String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] String; From : @key[in] Positive; Through : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@RI{String selector subprograms} @key[function] @AdaSubDefn{Trim} (Source : @key[in] String; Side : @key[in] Trim_End) @key[return] String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] String; Side : @key[in] Trim_End; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Trim} (Source : @key[in] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set; Justify : @key[in] Alignment := Strings.Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Head} (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Tail} (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @keepnext@;--@RI{String constructor functions} @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] String; @key[end] Ada.Strings.Fixed; @end{example} The effects of the above subprograms are as follows. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Move (Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Leading@;The Move procedure copies characters from Source to Target. If Source has the same length as Target, then the effect is to assign Source to Target. If Source is shorter than Target then: @begin{itemize} If Justify=Left, then Source is copied into the first Source'Length characters of Target. If Justify=Right, then Source is copied into the last Source'Length characters of Target. If Justify=Center, then Source is copied into the middle Source'Length characters of Target. In this case, if the difference in length between Target and Source is odd, then the extra Pad character is on the right. Pad is copied to each Target character not otherwise assigned. @end{itemize} If Source is longer than Target, then the effect is based on Drop. @begin{itemize} If Drop=Left, then the rightmost Target'Length characters of Source are copied into Target. If Drop=Right, then the leftmost Target'Length characters of Source are copied into Target. @Leading@;If Drop=Error, then the effect depends on the value of the Justify parameter and also on whether any characters in Source other than Pad would fail to be copied: @begin{inneritemize} If Justify=Left, and if each of the rightmost Source'Length-Target'Length characters in Source is Pad, then the leftmost Target'Length characters of Source are copied to Target. If Justify=Right, and if each of the leftmost Source'Length-Target'Length characters in Source is Pad, then the rightmost Target'Length characters of Source are copied to Target. @Trailing@;Otherwise, Length_Error is propagated. @end{inneritemize} @end{itemize} @begin{ramification} The Move procedure will work even if Source and Target overlap.@end{ramification} @begin{reason} The order of parameters (Source before Target) corresponds to the order in COBOL's MOVE verb.@end{reason} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Each Index function searches, starting from From, for a slice of Source, with length Pattern'Length, that matches Pattern with respect to Mapping; the parameter Going indicates the direction of the lookup. If From is not in Source'Range, then Index_Error is propagated. If Going = Forward, then Index returns the smallest index I which is greater than or equal to From such that the slice of Source starting at I matches Pattern. If Going = Backward, then Index returns the largest index I such that the slice of Source starting at I matches Pattern and has an upper bound less than or equal to From. If there is no such slice, then 0 is returned. If Pattern is the null string, then Pattern_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no default parameter for From; the default value would need to depend on other parameters (the bounds of Source and the direction Going). It is better to use overloaded functions rather than a special value to represent the default.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no default value for the Mapping parameter that is a Character_Mapping_Function; if there were, a call would be ambiguous since there is also a default for the Mapping parameter that is a Character_Mapping.]} @end{Discussion} @begin{Example}@Keepnext @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} @Comment{@ChgDeleted{Version=[2],Type=[Trailing],Text=[]}@Comment{Fake to hold conditional format.}Can't have both.} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Fake to hold conditional format.} @Chg{Version=[2],New=[If Going = Forward, returns], Old=[Each Index function searches for a slice of Source, with length Pattern'Length, that matches Pattern with respect to Mapping; the parameter Going indicates the direction of the lookup. If Going = Forward, then Index returns the smallest index I such that the slice of Source starting at I matches Pattern. If Going = Backward, then Index returns the largest index I such that the slice of Source starting at I matches Pattern. If there is no such slice, then 0 is returned. If Pattern is the null string then Pattern_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Index (Source, Pattern, Source'First, Forward, Mapping);]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Text=[otherwise returns]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Trailing],Text=[ Index (Source, Pattern, Source'Last, Backward, Mapping);]} @end{Example} @begin{discussion} @ChgRef{Version=[2],Kind=[Deleted]}@ChgNote{Moved up} @ChgAdded{Version=[2],Text=[There is no default value for the Mapping parameter that is a Character_Mapping_Function; if there were, a call would be ambiguous since there is also a default for the Mapping parameter that is a Character_Mapping.]} @end{discussion} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Index searches for the first or last occurrence of any of a set of characters (when Test=Inside), or any of the complement of a set of characters (when Test=Outside). If From is not in Source'Range, then Index_Error is propagated. Otherwise, it returns the smallest index I >= From (if Going=Forward) or the largest index I <= From (if Going=Backward) such that Source(I) satisfies the Test condition with respect to Set; it returns 0 if there is no such Character in Source.]} @begin{Example}@Keepnext @key[function] Index (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} @Comment{@ChgDeleted{Version=[2],Type=[Trailing],Text=[]}@Comment{Fake to hold conditional format.}Can't have both.} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Fake to hold conditional format.} @Chg{Version=[2],New=[If Going = Forward, returns], Old=[Index searches for the first or last occurrence of any of a set of characters (when Test=Inside), or any of the complement of a set of characters (when Test=Outside). It returns the smallest index I (if Going=Forward) or the largest index I (if Going=Backward) such that Source(I) satisfies the Test condition with respect to Set; it returns 0 if there is no such Character in Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Index (Source, Set, Source'First, Test, Forward);]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Text=[otherwise returns]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Trailing],Text=[ Index (Source, Set, Source'Last, Test, Backward);]} @end{Example} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index_Non_Blank (Source : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns Index (Source, Maps.To_Set(Space), From, Outside, Going);]} @begin{Example}@Keepnext @key[function] Index_Non_Blank (Source : @key[in] String; Going : @key[in] Direction := Forward) @key[return] Natural; @end{Example} @Trailing@;Returns Index(Source, Maps.To_Set(Space), Outside, Going) @begin{Example}@Keepnext @key[function] Count (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Count (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @end{Example} @Trailing@;Returns the maximum number of nonoverlapping slices of Source that match Pattern with respect to Mapping. If Pattern is the null string then Pattern_Error is propagated. @begin{reason} We say `maximum number' because it is possible to slice a source string in different ways yielding different numbers of matches. For example if Source is "ABABABA" and Pattern is "ABA", then Count yields 2, although there is a partitioning of Source that yields just 1 match, for the middle slice. Saying `maximum number' is equivalent to saying that the pattern match starts either at the low index or the high index position. @end{reason} @begin{Example}@Keepnext @key[function] Count (Source : @key[in] String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @end{Example} @Trailing@;Returns the number of occurrences in Source of characters that are in Set. @begin{Example}@Keepnext @key[procedure] Find_Token (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @Trailing@;Find_Token returns in First and Last the indices of the beginning and end of the first slice of Source all of whose elements satisfy the Test condition, and such that the elements (if any) immediately before and after the slice do not satisfy the Test condition. If no such slice exists, then the value returned for Last is zero, and the value returned for First is Source'First@Chg{New=[; however, if Source'First is not in Positive then Constraint_Error @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} is raised],Old=[]}. @begin{Example}@Keepnext @key[function] Translate (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping) @key[return] String;@* @key[function] Translate (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] String; @end{Example} @Trailing@;Returns the string S whose length is Source'Length and such that S(I) is the character to which Mapping maps the corresponding element of Source, for I in 1..Source'Length. @begin{Example}@Keepnext @key[procedure] Translate (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping);@* @key[procedure] Translate (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping_Function); @end{Example} @Trailing@;Equivalent to Source := Translate(Source, Mapping). @begin{Example}@Keepnext @key[function] Replace_Slice (Source : @key[in] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @Chg{New=[@Leading],Old=[@Trailing]}If Low > Source'Last+1, or High < Source'First@en@;1, then Index_Error is propagated. Otherwise@Chg{New=[:],Old=[, if High >= Low then the returned string comprises Source(Source'First..Low@en@;1) & By & Source(High+1..Source'Last), and if High < Low then the returned string is Insert(Source, Before=>Low, New_Item=>By).]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[1],Text=[If High >= Low, then the returned string comprises Source(Source'First..Low@en@;1) & By & Source(High+1..Source'Last), but with lower bound 1.@Trailing]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[1],Text=[If High < Low, then the returned string is Insert(Source, Before=>Low, New_Item=>By).]} @end{Itemize} @begin{Example}@Keepnext @key[procedure] Replace_Slice (Source : @key[in] @key[out] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Replace_Slice(Source, Low, High, By), Source, Drop, Justify, Pad). @begin{Example}@Keepnext @key[function] Insert (Source : @key[in] String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @end{Example} @Trailing@;Propagates Index_Error if Before is not in Source'First .. Source'Last+1; otherwise returns Source(Source'First..Before@en@;1) & New_Item & Source(Before..Source'Last), but with lower bound 1. @begin{Example}@Keepnext @key[procedure] Insert (Source : @key[in] @key[out] String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @end{Example} @Trailing@;Equivalent to Move(Insert(Source, Before, New_Item), Source, Drop). @begin{Example}@Keepnext @key[function] Overwrite (Source : @key[in] String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @end{Example} @Trailing@;Propagates Index_Error if Position is not in Source'First .. Source'Last+1; otherwise returns the string obtained from Source by consecutively replacing characters starting at Position with corresponding characters from New_Item. If the end of Source is reached before the characters in New_Item are exhausted, the remaining characters from New_Item are appended to the string. @begin{Example}@Keepnext @key[procedure] Overwrite (Source : @key[in] @key[out] String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Right); @end{Example} @Trailing@;Equivalent to Move(Overwrite(Source, Position, New_Item), Source, Drop). @begin{Example}@Keepnext @key[function] Delete (Source : @key[in] String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @Trailing@;If From <= Through, the returned string is Replace_Slice(Source, From, Through, ""), otherwise it is Source@Chg{New=[ with lower bound 1],Old=[]}. @begin{Example}@Keepnext @key[procedure] Delete (Source : @key[in] @key[out] String; From : @key[in] Positive; Through : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Delete(Source, From, Through), Source, Justify => Justify, Pad => Pad). @begin{Example}@Keepnext @key[function] Trim (Source : @key[in] String; Side : @key[in] Trim_End) @key[return] String; @end{Example} @Trailing@;Returns the string obtained by removing from Source all leading Space characters (if Side = Left), all trailing Space characters (if Side = Right), or all leading and trailing Space characters (if Side = Both). @begin{Example}@Keepnext @key[procedure] Trim (Source : @key[in] @key[out] String; Side : @key[in] Trim_End; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Trim(Source, Side), Source, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Trim (Source : @key[in] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] String; @end{Example} @Trailing@;Returns the string obtained by removing from Source all leading characters in Left and all trailing characters in Right. @begin{Example}@Keepnext @key[procedure] Trim (Source : @key[in] @key[out] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set; Justify : @key[in] Alignment := Strings.Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Trim(Source, Left, Right), Source, Justify => Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Head (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @end{Example} @Trailing@;Returns a string of length Count. If Count <= Source'Length, the string comprises the first Count characters of Source. Otherwise its contents are Source concatenated with Count@en@;Source'Length Pad characters. @begin{Example}@Keepnext @key[procedure] Head (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Head(Source, Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Tail (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @end{Example} @Trailing@;Returns a string of length Count. If Count <= Source'Length, the string comprises the last Count characters of Source. Otherwise its contents are Count-Source'Length Pad characters concatenated with Source. @begin{Example}@Keepnext @key[procedure] Tail (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Tail(Source, Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] String;@* @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} These functions replicate a character or string a specified number of times. The first function returns a string whose length is Left and each of whose elements is Right. The second function returns a string whose length is Left*Right'Length and whose value is the null string if Left = 0 and @Chg{New=[otherwise ],Old=[]}is (Left@en@;1)*Right & Right @Chg{New=[with lower bound 1],Old=[otherwise]}. @end{DescribeCode} @end{StaticSem} @begin{Notes} In the Index and Count functions taking Pattern and Mapping parameters, the actual String parameter passed to Pattern should comprise characters occurring as target characters of the mapping. Otherwise the pattern will not match. In the Insert subprograms, inserting at the end of a string is obtained by passing Source'Last+1 as the Before parameter. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Character_Mapping_Function is passed to any of the string handling subprograms, Constraint_Error is propagated. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Overloaded versions of Index and Index_Non_Blank are newly added to Strings.Fixed. If Strings.Fixed is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Index or Index_Non_Blank is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Find_Token may raise Constraint_Error if Source'First is not in Positive (which is only possible for a null string).]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Replace_Slice, Delete, and "*" always return a string with lower bound 1.]} @end{DiffWord95} @LabeledSubClause{Bounded-Length String Handling} @begin{Intro} The language-defined package Strings.Bounded provides a generic package each of whose instances yields a private type Bounded_String and a set of operations. An object of a particular Bounded_String type represents a String whose low bound is 1 and whose length can vary conceptually between 0 and a maximum size established at the generic instantiation. The subprograms for fixed-length string handling are either overloaded directly for Bounded_String, or are modified as needed to reflect the variability in length. Additionally, since the Bounded_String type is private, appropriate constructor and selector operations are provided. @begin{reason} Strings.Bounded declares an inner generic package, versus itself being directly a generic child of Strings, in order to retain compatibility with a version of the string-handling packages that is generic with respect to the character and string types.@end{reason} @begin{reason} The bound of a bounded-length string is specified as a parameter to a generic, versus as the value for a discriminant, because of the inappropriateness of assignment and equality of discriminated types for the copying and comparison of bounded strings.@end{reason} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Strings.Bounded has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Bounded]}@key[package] Ada.Strings.Bounded @key[is] @key[pragma] Preelaborate(Bounded); @key[generic] Max : Positive; --@RI{ Maximum length of a Bounded_String} @key[package] @AdaPackDefn{Generic_Bounded_Length} @key[is] @AdaObjDefn{Max_Length} : @key[constant] Positive := Max; @key[type] @AdaTypeDefn{Bounded_String} @key[is] @key[private]; @AdaObjDefn{Null_Bounded_String} : @key[constant] Bounded_String; @key[subtype] @AdaSubtypeDefn{Name=[Length_Range],Of=[Natural]} @key[is] Natural @key[range] 0 .. Max_Length; @key[function] @AdaSubDefn{Length} (Source : @key[in] Bounded_String) @key[return] Length_Range; --@RI{ Conversion, Concatenation, and Selection functions} @key[function] @AdaSubDefn{To_Bounded_String} (Source : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{To_String} (Source : @key[in] Bounded_String) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Set_Bounded_String} (Target : @key[out] Bounded_String; Source : @key[in] String; Drop : @key[in] Truncation := Error);]} @key[function] @AdaSubDefn{Append} (Left, Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Bounded_String; Right : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] String; Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Bounded_String; Right : @key[in] Character; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Character; Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] Bounded_String; Drop : @key[in] Truncation := Error); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] Character; Drop : @key[in] Truncation := Error); @key[function] "&" (Left, Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Bounded_String; Right : @key[in] Character) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Character; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] @AdaSubDefn{Element} (Source : @key[in] Bounded_String; Index : @key[in] Positive) @key[return] Character; @key[procedure] @AdaSubDefn{Replace_Element} (Source : @key[in] @key[out] Bounded_String; Index : @key[in] Positive; By : @key[in] Character); @key[function] @AdaSubDefn{Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Bounded_Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Bounded_String;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Bounded_Slice} (Source : @key[in] Bounded_String; Target : @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @key[function] "=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} --@RI{ Search @Chg{Version=[2],New=[subprograms],Old=[functions]}} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Bounded_String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Bounded_String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@; --@RI{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] Bounded_String; Mapping : @key[in] Maps.Character_Mapping) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Bounded_String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] Bounded_String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Bounded_String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@; --@RI{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Insert} (Source : @key[in] Bounded_String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] Bounded_String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] Bounded_String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] Bounded_String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Delete} (Source : @key[in] Bounded_String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] Bounded_String; From : @key[in] Positive; Through : @key[in] Natural); --@RI{String selector subprograms} @key[function] @AdaSubDefn{Trim} (Source : @key[in] Bounded_String; Side : @key[in] Trim_End) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Bounded_String; Side : @key[in] Trim_End); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Bounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Bounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set); @key[function] @AdaSubDefn{Head} (Source : @key[in] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Tail} (Source : @key[in] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error); --@RI{String constructor subprograms} @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] Bounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] Bounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] Character; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[private] ... -- @RI{not specified by the language} @key[end] Generic_Bounded_Length; @key[end] Ada.Strings.Bounded; @end{example} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[Bounded_String cannot be implemented as a (directly) controlled type, as Ada.Strings.Bounded.Generic_Bounded_Length can be instantiated at any nesting depth. Bounded_String could have a component of a controlled type, as long as that type is declared in some other (non-generic) package (including directly in Ada.Strings.Bounded).],Old=[]}]} @ChgNote{AI-344 allows controlled types to be declared at any nesting depth, so this note is obsolete.} @end{ImplNote} Null_Bounded_String represents the null string. If an object of type Bounded_String is not otherwise initialized, it will be initialized to the same value as Null_Bounded_String. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Length (Source : @key[in] Bounded_String) @key[return] Length_Range; @end{Example} @Trailing@;The Length function returns the length of the string represented by Source. @begin{Example}@Keepnext @key[function] To_Bounded_String (Source : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @end{Example} @Leading@;If Source'Length <= Max_Length then this function returns a Bounded_String that represents Source. Otherwise the effect depends on the value of Drop: @begin{itemize} If Drop=Left, then the result is a Bounded_String that represents the string comprising the rightmost Max_Length characters of Source. If Drop=Right, then the result is a Bounded_String that represents the string comprising the leftmost Max_Length characters of Source. @Trailing@;If Drop=Error, then Strings.Length_Error is propagated. @end{itemize} @begin{Example}@Keepnext @key[function] To_String (Source : @key[in] Bounded_String) @key[return] String; @end{Example} @Trailing@;To_String returns the String value with lower bound 1 represented by Source. If B is a Bounded_String, then B = To_Bounded_String(To_String(B)). @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[procedure] Set_Bounded_String (Target : @key[out] Bounded_String; Source : @key[in] String; Drop : @key[in] Truncation := Error);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Target := To_Bounded_String (Source, Drop);]} @end{DescribeCode} Each of the Append functions returns a Bounded_String obtained by concatenating the string or character given or represented by one of the parameters, with the string or character given or represented by the other parameter, and applying To_Bounded_String to the concatenation result string, with Drop as provided to the Append function. Each of the procedures Append(Source, New_Item, Drop) has the same effect as the corresponding assignment Source := Append(Source, New_Item, Drop). Each of the "&" functions has the same effect as the corresponding Append function, with Error as the Drop parameter. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Element (Source : @key[in] Bounded_String; Index : @key[in] Positive) @key[return] Character; @end{Example} @Trailing@;Returns the character at position Index in the string represented by Source; propagates Index_Error if Index > Length(Source). @begin{Example}@Keepnext @key[procedure] Replace_Element (Source : @key[in] @key[out] Bounded_String; Index : @key[in] Positive; By : @key[in] Character); @end{Example} @Trailing@;Updates Source such that the character at position Index in the string represented by Source is By; propagates Index_Error if Index > Length(Source). @begin{Example}@Keepnext @key[function] Slice (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgRef{Version=[1],Kind=[Revised],ARef=[AI95-00238-01]} @Trailing@;Returns the slice at positions Low through High in the string represented by Source; propagates Index_Error if Low > Length(Source)+1@Chg{New=[ or High > Length(Source)],Old=[]}.@Chg{Version=[2], New=[ The bounds of the returned string are Low and High.],Old=[]}. @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[function] Bounded_Slice (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the slice at positions Low through High in the string represented by Source as a bounded string; propagates Index_Error if Low > Length(Source)+1 or High > Length(Source).]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[procedure] Bounded_Slice (Source : @key[in] Bounded_String; Target : @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Target := Bounded_Slice (Source, Low, High);]} @end{DescribeCode} Each of the functions "=", "<", ">", "<=", and ">=" returns the same result as the corresponding String operation applied to the String values given or represented by the two parameters. Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token) has the same effect as the corresponding subprogram in Strings.Fixed applied to the string represented by the Bounded_String parameter. Each of the Translate subprograms, when applied to a Bounded_String, has an analogous effect to the corresponding subprogram in Strings.Fixed. For the Translate function, the translation is applied to the string represented by the Bounded_String parameter, and the result is converted (via To_Bounded_String) to a Bounded_String. For the Translate procedure, the string represented by the Bounded_String parameter after the translation is given by the Translate function for fixed-length strings applied to the string represented by the original value of the parameter. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} Each of the transformation subprograms (Replace_Slice, Insert, Overwrite, Delete), selector subprograms (Trim, Head, Tail), and constructor functions ("*") has an effect based on its corresponding subprogram in Strings.Fixed, and Replicate is based on Fixed."*". @Chg{New=[In the case of a function], Old=[For each of these subprograms]}, the corresponding fixed-length string subprogram is applied to the string represented by the Bounded_String parameter. To_Bounded_String is applied the result string, with Drop (or Error in the case of Generic_Bounded_Length."*") determining the effect when the string length exceeds Max_Length. @Chg{New=[In the case of a procedure, the corresponding function in Strings.@!Bounded.@!Generic_@!Bounded_@!Length is applied, with the result assigned into the Source parameter.],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The "/=" operations between Bounded_String and String, and between String and Bounded_String, are automatically defined based on the @Chg{Version=[2], New=[corresponding],Old=[corrsponding]} "=" operations. @end{Ramification} @end{StaticSem} @begin{ImplAdvice} Bounded string objects should not be implemented by implicit pointers and dynamic allocation. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Bounded string objects should not be implemented by implicit pointers and dynamic allocation.]}]} @begin{ImplNote} @Leading@;The following is a possible implementation of the private part of the package: @begin{example} @key[type] Bounded_String_Internals (Length : Length_Range := 0) @key[is] @key[record] Data : String(1..Length); @key[end] @key[record]; @key[type] Bounded_String @key[is] @key[record] Data : Bounded_String_Internals; --@RI{ Unconstrained} @key[end] @key[record]; Null_Bounded_String : @key[constant] Bounded_String := (Data => (Length => 0, Data => (1..0 => ' '))); @end{example} @end{ImplNote} @end{ImplAdvice} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00238-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @B[Amendment Correction:] The bounds of the string returned from Slice are now defined. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from Slice, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Procedure Set_Bounded_String, two Bounded_Slice subprograms, and overloaded versions of Index and Index_Non_Blank are newly added to Strings.Bounded. If Strings.Bounded is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Strings.Bounded is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the conditions for which Slice raises Index_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of transformation, selector, and constructor subprograms by describing the effects of procedures and functions separately.]} @end{DiffWord95} @LabeledSubClause{Unbounded-Length String Handling} @begin{Intro} The language-defined package Strings.Unbounded provides a private type Unbounded_String and a set of operations. An object of type Unbounded_String represents a String whose low bound is 1 and whose length can vary conceptually between 0 and Natural'Last. The subprograms for fixed-length string handling are either overloaded directly for Unbounded_String, or are modified as needed to reflect the flexibility in length. Since the Unbounded_String type is private, relevant constructor and selector operations are provided. @begin{reason} The transformation operations for fixed- and bounded-length strings that are not necessarily length preserving are supplied for Unbounded_String as procedures as well as functions. This allows an implementation to do an initial allocation for an unbounded string and to avoid further allocations as long as the length does not exceed the allocated length. @end{reason} @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Unbounded has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Unbounded]}@key[package] Ada.Strings.Unbounded @key[is] @key[pragma] Preelaborate(Unbounded); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Unbounded_String} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Unbounded_String);],Old=[]} @AdaObjDefn{Null_Unbounded_String} : @key[constant] Unbounded_String; @key[function] @AdaSubDefn{Length} (Source : @key[in] Unbounded_String) @key[return] Natural; @key[type] @AdaTypeDefn{String_Access} @key[is] @key[access] @key[all] String; @key[procedure] @AdaSubDefn{Free} (X : @key[in] @key[out] String_Access); --@RI{ Conversion, Concatenation, and Selection functions} @key[function] @AdaSubDefn{To_Unbounded_String} (Source : @key[in] String) @key[return] Unbounded_String; @key[function] @AdaSubDefn{To_Unbounded_String} (Length : @key[in] Natural) @key[return] Unbounded_String; @key[function] @AdaSubDefn{To_String} (Source : @key[in] Unbounded_String) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Set_Unbounded_String} (Target : @key[out] Unbounded_String; Source : @key[in] String);]} @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] Unbounded_String); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] String); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] Character); @key[function] "&" (Left, Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Unbounded_String; Right : @key[in] Character) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Character; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] @AdaSubDefn{Element} (Source : @key[in] Unbounded_String; Index : @key[in] Positive) @key[return] Character; @key[procedure] @AdaSubDefn{Replace_Element} (Source : @key[in] @key[out] Unbounded_String; Index : @key[in] Positive; By : @key[in] Character); @key[function] @AdaSubDefn{Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Unbounded_Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Unbounded_String;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Unbounded_Slice} (Source : @key[in] Unbounded_String; Target : @key[out] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @key[function] "=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; --@RI{ Search subprograms} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Unbounded_String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Unbounded_String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@;--@RI{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@;--@RI{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String); @key[function] @AdaSubDefn{Insert} (Source : @key[in] Unbounded_String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] Unbounded_String; Before : @key[in] Positive; New_Item : @key[in] String); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] Unbounded_String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] Unbounded_String; Position : @key[in] Positive; New_Item : @key[in] String); @key[function] @AdaSubDefn{Delete} (Source : @key[in] Unbounded_String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] Unbounded_String; From : @key[in] Positive; Through : @key[in] Natural); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Unbounded_String; Side : @key[in] Trim_End) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Unbounded_String; Side : @key[in] Trim_End); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Unbounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Unbounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set); @key[function] @AdaSubDefn{Head} (Source : @key[in] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Tail} (Source : @key[in] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space); @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] Unbounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] Unbounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Strings.Unbounded; @end{example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Unbounded_String needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} Null_Unbounded_String represents the null String. If an object of type Unbounded_String is not otherwise initialized, it will be initialized to the same value as Null_Unbounded_String. The function Length returns the length of the String represented by Source. The type String_Access provides a (non-private) access type for explicit processing of unbounded-length strings. The procedure Free performs an unchecked deallocation of an object of type String_Access. The function To_Unbounded_String(Source : in String) returns an Unbounded_String that represents Source. The function To_Unbounded_String(Length : in Natural) returns an Unbounded_String that represents an uninitialized String whose length is Length. @Leading@;The function To_String returns the String with lower bound 1 represented by Source. To_String and To_Unbounded_String are related as follows: @begin{itemize} If S is a String, then To_String(To_Unbounded_String(S)) = S. If U is an Unbounded_String, then To_Unbounded_String(To_String(U)) = U. @end{itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The procedure Set_Unbounded_String sets Target to an Unbounded_String that represents Source.]} For each of the Append procedures, the resulting string represented by the Source parameter is given by the concatenation of the original value of Source and the value of New_Item. Each of the "&" functions returns an Unbounded_String obtained by concatenating the string or character given or represented by one of the parameters, with the string or character given or represented by the other parameter, and applying To_Unbounded_String to the concatenation result string. The Element, Replace_Element, and Slice subprograms have the same effect as the corresponding bounded-length string subprograms. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The function Unbounded_Slice returns the slice at positions Low through High in the string represented by Source as an Unbounded_String. The procedure Unbounded_Slice sets Target to the Unbounded_String representing the slice at positions Low through High in the string represented by Source. Both routines propagate Index_Error if Low > Length(Source)+1 or High > Length(Source).]} Each of the functions "=", "<", ">", "<=", and ">=" returns the same result as the corresponding String operation applied to the String values given or represented by Left and Right. Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token) has the same effect as the corresponding subprogram in Strings.Fixed applied to the string represented by the Unbounded_String parameter. The Translate function has an analogous effect to the corresponding subprogram in Strings.Fixed. The translation is applied to the string represented by the Unbounded_String parameter, and the result is converted (via To_Unbounded_String) to an Unbounded_String. Each of the transformation functions (Replace_Slice, Insert, Overwrite, Delete), selector functions (Trim, Head, Tail), and constructor functions ("*") is likewise analogous to its corresponding subprogram in Strings.Fixed. For each of the subprograms, the corresponding fixed-length string subprogram is applied to the string represented by the Unbounded_String parameter, and To_Unbounded_String is applied the result string. For each of the procedures Translate, Replace_Slice, Insert, Overwrite, Delete, Trim, Head, and Tail, the resulting string represented by the Source parameter is given by the corresponding function for fixed-length strings applied to the string represented by Source's original value. @end{StaticSem} @begin{ImplReq} No storage associated with an Unbounded_String object shall be lost upon assignment or scope exit. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} A sample implementation of the private part of the package and several of the subprograms appears in the @Chg{Version=[2], New=[Ada 95 ],Old=[]}Rationale. @end{ImplNote} @end{ImplReq} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Type Unbounded_String is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and Unbounded_String does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as most Ada compilers have a controlled part in Unbounded_String, and thus would be illegal.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ Procedure Set_Unbounded_String, two Unbounded_Slice subprograms, and overloaded versions of Index and Index_Non_Blank are newly added to Strings.Unbounded. If Strings.Unbounded is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Strings.Unbounded is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added a @nt{pragma} Preelaborable_Initialization to type Unbounded_String, so that it can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @LabeledSubClause{String-Handling Sets and Mappings} @begin{Intro} The language-defined package Strings.Maps.Constants declares Character_Set and Character_Mapping constants corresponding to classification and conversion functions in package Characters.Handling. @begin{discussion} The Constants package is a child of Strings.Maps since it needs visibility of the private part of Strings.Maps in order to initialize the constants in a preelaborable way (i.e. via aggregates versus function calls). @end{discussion} @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Maps.Constants has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada.Strings.Maps],Child=[Constants]}@key[package] Ada.Strings.Maps.Constants @key[is] @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Constants); @AdaObjDefn{Control_Set} : @key[constant] Character_Set; @AdaObjDefn{Graphic_Set} : @key[constant] Character_Set; @AdaObjDefn{Letter_Set} : @key[constant] Character_Set; @AdaObjDefn{Lower_Set} : @key[constant] Character_Set; @AdaObjDefn{Upper_Set} : @key[constant] Character_Set; @AdaObjDefn{Basic_Set} : @key[constant] Character_Set; @AdaObjDefn{Decimal_Digit_Set} : @key[constant] Character_Set; @AdaObjDefn{Hexadecimal_Digit_Set} : @key[constant] Character_Set; @AdaObjDefn{Alphanumeric_Set} : @key[constant] Character_Set; @AdaObjDefn{Special_Set} : @key[constant] Character_Set; @AdaObjDefn{ISO_646_Set} : @key[constant] Character_Set; @AdaObjDefn{Lower_Case_Map} : @key[constant] Character_Mapping; --@RI{Maps to lower case for letters, else identity} @AdaObjDefn{Upper_Case_Map} : @key[constant] Character_Mapping; --@RI{Maps to upper case for letters, else identity} @AdaObjDefn{Basic_Map} : @key[constant] Character_Mapping; --@RI{Maps to basic letter for letters, else identity} @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Strings.Maps.Constants; @end{example} Each of these constants represents a correspondingly named set of characters or character mapping in Characters.Handling (see @refsecnum(The Package Characters.Handling)). @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Strings.Maps.Constants is now Pure, so it can be used in pure units.]} @end{Extend95} @LabeledSubClause{Wide_String Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00302-03]} Facilities for handling strings of Wide_Character elements are found in the packages Strings.@!Wide_Maps, Strings.@!Wide_Fixed, Strings.@!Wide_@!Bounded, Strings.@!Wide_@!Unbounded, and Strings.@!Wide_Maps.@!Wide_@!Constants@Chg{Version=[2],New=[, and in the functions Strings.@!Wide_Hash, Strings.@!Wide_Fixed.@!Wide_Hash, Strings.@!Wide_Bounded.@!Wide_Hash, and Strings.@!Wide_Unbounded.@!Wide_Hash],Old=[]}. They provide the same string-handling operations as the corresponding packages@Chg{Version=[2],New=[ and functions],Old=[]} for strings of Character elements. @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Fixed]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Bounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Unbounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Fixed],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Bounded],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Unbounded],Child=[Wide_@!Hash]} @ChildUnit{Parent=[Ada.Strings.Wide_@!Maps],Child=[Wide_@!Constants]} @end{Intro} @begin{StaticSem} The package Strings.Wide_Maps has the following declaration. @begin{example} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Maps]}@key[package] Ada.Strings.Wide_Maps @key[is] @key[pragma] Preelaborate(Wide_Maps); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@RI{ Representation for a set of Wide_Character values:} @key[type] @AdaTypeDefn{Wide_Character_Set} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Wide_Character_Set);],Old=[]} @AdaObjDefn{Null_Set} : @key[constant] Wide_Character_Set; @key[type] @AdaTypeDefn{Wide_Character_Range} @key[is] @key[record] Low : Wide_Character; High : Wide_Character; @key[end] @key[record]; -- @RI{Represents Wide_Character range Low..High} @key[type] @AdaTypeDefn{Wide_Character_Ranges} @key[is] @key[array] (Positive @key[range] <>) @key[of] Wide_Character_Range; @key[function] @AdaSubDefn{To_Set} (Ranges : @key[in] Wide_Character_Ranges) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Set} (Span : @key[in] Wide_Character_Range) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Ranges} (Set : @key[in] Wide_Character_Set) @key[return] Wide_Character_Ranges; @key[function] "=" (Left, Right : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] "@key[not]" (Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[and]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[or]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[xor]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "-" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{Is_In} (Element : @key[in] Wide_Character; Set : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Subset} (Elements : @key[in] Wide_Character_Set; Set : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Wide_Character_Set; Right : @key[in] Wide_Character_Set) @key[return] Boolean @key[renames] Is_Subset; --@RI{ Alternative representation for a set of Wide_Character values:} @key[subtype] @AdaSubtypeDefn{Name=[Wide_Character_Sequence],Of=[Wide_String]} @key[is] Wide_String; @key[function] @AdaSubDefn{To_Set} (Sequence : @key[in] Wide_Character_Sequence) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Set} (Singleton : @key[in] Wide_Character) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Sequence} (Set : @key[in] Wide_Character_Set) @key[return] Wide_Character_Sequence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@RI{ Representation for a Wide_Character to Wide_Character mapping:} @key[type] @AdaTypeDefn{Wide_Character_Mapping} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Wide_Character_Mapping);],Old=[]} @key[function] @AdaSubDefn{Value} (Map : @key[in] Wide_Character_Mapping; Element : @key[in] Wide_Character) @key[return] Wide_Character; @AdaObjDefn{Identity} : @key[constant] Wide_Character_Mapping; @key[function] @AdaSubDefn{To_Mapping} (From, To : @key[in] Wide_Character_Sequence) @key[return] Wide_Character_Mapping; @key[function] @AdaSubDefn{To_Domain} (Map : @key[in] Wide_Character_Mapping) @key[return] Wide_Character_Sequence; @key[function] @AdaSubDefn{To_Range} (Map : @key[in] Wide_Character_Mapping) @key[return] Wide_Character_Sequence; @key{type} @AdaTypeDefn{Wide_Character_Mapping_Function} @key{is} @key{access} @key{function} (From : @key{in} Wide_Character) @key{return} Wide_Character; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Strings.Wide_Maps; @end{example} The context clause for each of the packages Strings.Wide_Fixed, Strings.Wide_Bounded, and Strings.Wide_Unbounded identifies Strings.Wide_Maps instead of Strings.Maps. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00302-03]} @Leading@;For each of the packages Strings.Fixed, Strings.Bounded, Strings.Unbounded, and Strings.Maps.Constants@Chg{Version=[2],New=[, and for functions Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash, and Strings.Unbounded.Hash,],Old=[]} the corresponding wide string package has the same contents except that @begin{itemize} Wide_Space replaces Space Wide_Character replaces Character Wide_String replaces String Wide_Character_Set replaces Character_Set Wide_Character_Mapping replaces Character_Mapping Wide_Character_Mapping_Function replaces Character_Mapping_Function Wide_Maps replaces Maps Bounded_Wide_String replaces Bounded_String Null_Bounded_Wide_String replaces Null_Bounded_String To_Bounded_Wide_String replaces To_Bounded_String To_Wide_String replaces To_String @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Bounded_Wide_String replaces Set_Bounded_String]} Unbounded_Wide_String replaces Unbounded_String Null_Unbounded_Wide_String replaces Null_Unbounded_String Wide_String_Access replaces String_Access To_Unbounded_Wide_String replaces To_Unbounded_String @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Unbounded_Wide_String replaces Set_Unbounded_String]} @end{Itemize} @Leading@keepnext@;The following additional declaration is present in Strings.Wide_Maps.Wide_Constants: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @AdaObjDefn{Character_Set} : @key[constant] Wide_Maps.Wide_Character_Set; --@RI{Contains each Wide_Character value WC such that}@Chg{Version=[2],New=[ --],Old=[]}@RI{Characters.@Chg{Version=[2],New=[Conversions.],Old=[]}Is_Character(WC) is True} @end{example} @end{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Each Wide_Character_Set constant in the package Strings.Wide_Maps.Wide_Constants contains no values outside the Character portion of Wide_Character. Similarly, each Wide_Character_Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Character.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Pure is replaced by @nt{pragma} Preelaborate in Strings.Wide_Maps.Wide_Constants.]} @begin{Notes} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Wide_Character_Mapping_Function is passed to any of the Wide_String handling subprograms, Constraint_Error is propagated. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Each Wide_Character_Set constant in the package Strings.Wide_Maps.Wide_Constants contains no values outside the Character portion of Wide_Character. Similarly, each Wide_Character_Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Character.]} @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Various new operations are added to Strings.Wide_Fixed, Strings.Wide_Bounded, and Strings.Wide_Unbounded. If one of these packages is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to types Wide_Character_Set and Wide_Character_Mapping, so that they can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Corrected the description of Character_Set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Added wide versions of Strings.Hash and Strings.Unbounded.Hash.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Added wording so that Strings.Wide_Maps.Wide_Constants does not change to Pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The second Note is now normative text, since there is no way to derive it from the other rules. It's a little weird given the use of Unicode character classifications in Ada 2005; but changing it would be inconsistent with Ada 95 and a one-to-one mapping isn't necessarily correct anyway.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Wide_Wide_String Handling]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Facilities for handling strings of Wide_Wide_Character elements are found in the packages Strings.@!Wide_Wide_@!Maps, Strings.@!Wide_Wide_@!Fixed, Strings.@!Wide_Wide_@!Bounded, Strings.@!Wide_Wide_@!Unbounded, and Strings.@!Wide_Wide_@!Maps.@!Wide_Wide_@!Constants, and in the functions Strings.@!Wide_Wide_@!Hash, Strings.@!Wide_Wide_@!Fixed.@!Wide_Wide_@!Hash, Strings.@!Wide_Wide_@!Bounded.@!Wide_@!Wide_@!Hash, and Strings.@!Wide_Wide_@!Unbounded.@!Wide_@!Wide_@!Hash. They provide the same string-handling operations as the corresponding packages and functions for strings of Character elements. @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Fixed]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Bounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Unbounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Fixed],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Bounded],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Unbounded],Child=[Wide_Wide_@!Hash]} @ChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Maps],Child=[Wide_Wide_@!Constants]}]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The library package Strings.Wide_Wide_Maps has the following declaration.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<package> Ada.Strings.Wide_Wide_Maps @key<is>@ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Maps]} @key<pragma> Preelaborate(Wide_Wide_Maps);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Representation for a set of Wide_Wide_Character values:] @key<type> @AdaTypeDefn{Wide_Wide_Character_Set} @key<is private>; @key<pragma> Preelaborable_Initialization(Wide_Wide_Character_Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Null_Set} : @key<constant> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Range} @key<is> @key<record> Low : Wide_Wide_Character; High : Wide_Wide_Character; @key<end record>; -- @RI[Represents Wide_Wide_Character range Low..High]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Ranges} @key<is array> (Positive @key<range> <>) @key<of> Wide_Wide_Character_Range;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Ranges : @key<in> Wide_Wide_Character_Ranges) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Span : @key<in> Wide_Wide_Character_Range) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ranges} (Set : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Ranges;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "=" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "@key<not>" (Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<and>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<or>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<xor>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "-" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_In} (Element : @key<in> Wide_Wide_Character; Set : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Subset} (Elements : @key<in> Wide_Wide_Character_Set; Set : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "<=" (Left : @key<in> Wide_Wide_Character_Set; Right : @key<in> Wide_Wide_Character_Set) @key<return> Boolean @key<renames> Is_Subset;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Alternative representation for a set of Wide_Wide_Character values:] @key<subtype> @AdaSubtypeDefn{Name=[Wide_Wide_Character_Sequence],Of=[Wide_Wide_String]} @key<is> Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Sequence : @key<in> Wide_Wide_Character_Sequence) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Singleton : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Sequence} (Set : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Representation for a Wide_Wide_Character to Wide_Wide_Character] -- @RI[mapping:] @key<type> @AdaTypeDefn{Wide_Wide_Character_Mapping} @key<is private>; @key<pragma> Preelaborable_Initialization(Wide_Wide_Character_Mapping);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Map : @key<in> Wide_Wide_Character_Mapping; Element : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Identity} : @key<constant> Wide_Wide_Character_Mapping;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Mapping} (From, To : @key<in> Wide_Wide_Character_Sequence) @key<return> Wide_Wide_Character_Mapping;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Domain} (Map : @key<in> Wide_Wide_Character_Mapping) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Range} (Map : @key<in> Wide_Wide_Character_Mapping) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Mapping_Function} @key<is> @key<access function> (From : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<private> ... -- @RI[not specified by the language] @key<end> Ada.Strings.Wide_Wide_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Strings.Wide_@!Maps],Child=[Wide_@!Constants]} The context clause for each of the packages Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, and Strings.Wide_Wide_Unbounded identifies Strings.Wide_Wide_Maps instead of Strings.Maps.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each of the packages Strings.@!Fixed, Strings.@!Bounded, Strings.@!Unbounded, and Strings.@!Maps.Constants, and for functions Strings.@!Hash, Strings.@!Fixed.Hash, Strings.@!Bounded.Hash, and Strings.@!Unbounded.Hash, the corresponding wide wide string package or function has the same contents except that]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Space replaces Space]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character replaces Character]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_String replaces String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Set replaces Character_Set]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Mapping replaces Character_Mapping]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Mapping_Function replaces Character_Mapping_Function]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Maps replaces Maps]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Bounded_Wide_Wide_String replaces Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Null_Bounded_Wide_Wide_String replaces Null_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Bounded_Wide_Wide_String replaces To_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Wide_Wide_String replaces To_String]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Bounded_Wide_Wide_String replaces Set_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unbounded_Wide_Wide_String replaces Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Null_Unbounded_Wide_Wide_String replaces Null_Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_String_Access replaces String_Access]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Unbounded_Wide_Wide_String replaces To_Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Unbounded_Wide_Wide_String replaces Set_Unbounded_String]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following additional declarations are present in Strings.Wide_Wide_Maps.Wide_Wide_Constants:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@AdaObjDefn{Character_Set} : @key<constant> Wide_Wide_Maps.Wide_Wide_Character_Set; -- @RI[Contains each Wide_Wide_Character value WWC such that] -- @RI[Characters.Conversions.Is_Character(WWC) is True] @AdaObjDefn{Wide_Character_Set} : @key<constant> Wide_Wide_Maps.Wide_Wide_Character_Set; -- @RI[Contains each Wide_Wide_Character value WWC such that] -- @RI[Characters.Conversions.Is_Wide_Character(WWC) is True]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Each Wide_Wide_Character_Set constant in the package Strings.@!Wide_Wide_@!Maps.@!Wide_Wide_@!Constants contains no values outside the Character portion of Wide_Wide_@!Character. Similarly, each Wide_Wide_@!Character_@!Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Wide_Character.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Pure is replaced by @nt{pragma} Preelaborate in Strings.Wide_Wide_Maps.Wide_Wide_Constants.]} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Wide_Wide_Character_Mapping_Function is passed to any of the Wide_Wide_String handling subprograms, Constraint_Error is propagated.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The double-wide string-handling packages (Strings.Wide_Wide_Maps, Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, Strings.Wide_Wide_Unbounded, and Strings.Wide_Wide_Maps.Wide_Wide_Constants), and functions Strings.Wide_Wide_Hash and Strings.Wide_Wide_Unbounded.Wide_Wide_Hash are new.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[String Hashing]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<function> Ada.Strings.Hash (Key : String) @key<return> Containers.Hash_Type;@SubChildUnit{Parent=[Ada.Strings],Child=[Hash]} @key<pragma> Pure(Hash);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns an implementation-defined value which is a function of the value of Key. If @i<A> and @i<B> are strings such that @i<A> equals @i<B>, Hash(@i<A>) equals Hash(@i<B>).]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values returned by Strings.Hash.]}]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Fixed.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers, Ada.Strings.Hash; @key<function> Ada.Strings.Fixed.Hash (Key : String) @key<return> Containers.Hash_Type @key<renames> Ada.Strings.Hash; @key<pragma> Pure(Hash);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library function Strings.Bounded.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<generic>@SubChildUnit{Parent=[Ada.Strings.Bounded],Child=[Hash]} @key<with package> Bounded @key<is> @key<new> Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key<function> Ada.Strings.Bounded.Hash (Key : Bounded.Bounded_String) @key<return> Containers.Hash_Type; @key<pragma> Preelaborate(Hash);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Strings.Bounded.Hash is equivalent to the function call Strings.Hash (Bounded.To_String (Key));]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Unbounded.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<function> Ada.Strings.Unbounded.Hash (Key : Unbounded_String)@SubChildUnit{Parent=[Ada.Strings.Unbounded],Child=[Hash]} @key<return> Containers.Hash_Type; @key<pragma> Preelaborate(Hash);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Strings.Unbounded.Hash is equivalent to the function call Strings.Hash (To_String (Key));]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The Hash functions should be good hash functions, returning a wide spread of values for different string values. It should be unlikely for similar strings to return the same value.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Strings.Hash should be good a hash function, returning a wide spread of values for different string values, and similar strings should rarely return the same value.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The other functions are defined in terms of Strings.Hash, so they don't need separate advice in the Annex.]} @end{Ramification} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash, and Strings.Unbounded.Hash functions are new.]} @end{Extend95} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/real_attribs.mss�����������������������������������������������������0000755�0001752�0001001�00000076706�12273462240�020640� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(realattribs, Root="ada.mss") @Comment{$Date: 2005/08/17 00:07:41 $} @comment{$Source: e:\\cvsroot/ARM/Source/real_attribs.mss,v $} @comment{$Revision: 1.25 $} @LabeledSubClause{Attributes of Floating Point Types} @begin{StaticSem} @Leading@Defn2{Term=[representation-oriented attributes], Sec=[of a floating point subtype]} The following @i{representation-oriented attributes} are defined for @PrefixType{every subtype S of a floating point type @i{T}}. @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Radix>, Text=[Yields the radix of the hardware representation of the type @i{T}. The value of this attribute is of the type @i{universal_integer}.]} @end{Description} @Defn{canonical form} The values of other representation-oriented attributes of a floating point subtype, and of the @lquotes@;primitive function@rquotes@; attributes of a floating point subtype described later, are defined in terms of a particular representation of nonzero values called the @i{canonical form}. The canonical form (for the type @i{T}) is the form@* @ @ @ @ @PorM @RI{mantissa} @Times @RI{T}@R['Machine_Radix]@+{@RI{exponent}}@* where @begin{Itemize} @i{mantissa} is a fraction in the number base @i{T}'Machine_Radix, the first digit of which is nonzero, and @i{exponent} is an integer. @end{Itemize} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Mantissa>, Text=[Yields the largest value of @RI{p} such that every value expressible in the canonical form (for the type @i{T}), having a @RI{p}-digit @i{mantissa} and an @i{exponent} between @i{T}'Machine_Emin and @i{T}'Machine_Emax, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} Values of a type held in an extended register are, in general, not machine numbers of the type, since they cannot be expressed in the canonical form with a sufficiently short @i{mantissa}. @end{Ramification} @Attribute{Prefix=<S>, AttrName=<Machine_Emin>, Text=[Yields the smallest (most negative) value of @i{exponent} such that every value expressible in the canonical form (for the type @i{T}), having a @i{mantissa} of @i{T}'Machine_Mantissa digits, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Machine_Emax>, Text=[Yields the largest (most positive) value of @i{exponent} such that every value expressible in the canonical form (for the type @i{T}), having a @i{mantissa} of @i{T}'Machine_Mantissa digits, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} Note that the above definitions do not determine unique values for the representation-oriented attributes of floating point types. The implementation may choose any set of values that collectively satisfies the definitions. @end{Ramification} @Attribute{Prefix=<S>, AttrName=<Denorm>, Text=[Yields the value True if every value expressible in the form@* @ @ @ @ @PorM @RI{mantissa} @Times @RI{T}@R{'Machine_Radix}@+{@RI{T}@R{'Machine_Emin}}@* where @i{mantissa} is a nonzero @i{T}'Machine_Mantissa-digit fraction in the number base @i{T}'Machine_Radix, the first digit of which is zero, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @Defn{denormalized number} The values described by the formula in the definition of S'Denorm are called @i{denormalized numbers}. @Defn{normalized number} A nonzero machine number that is not a denormalized number is a @i{normalized number}. @Defn{represented in canonical form} @Defn{canonical-form representation} A normalized number @RI{x} of a given type @i{T} is said to be @i{represented in canonical form} when it is expressed in the canonical form (for the type @i{T}) with a @i{mantissa} having @i{T}'Machine_Mantissa digits; the resulting form is the @i{canonical-form representation} of @RI{x}. @begin{Discussion} The intent is that S'Denorm be True when such denormalized numbers exist and are generated in the circumstances defined by IEC 559:1989, though the latter requirement is not formalized here. @end{Discussion} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Rounds>, Text=[Yields the value True if rounding is performed on inexact results of every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @begin{Discussion} @Leading@;It is difficult to be more precise about what it means to round the result of a predefined operation. If the implementation does not use extended registers, so that every arithmetic result is necessarily a machine number, then rounding seems to imply two things: @begin{Itemize} S'Model_Mantissa = S'Machine_Mantissa, so that operand preperturbation never occurs; when the exact mathematical result is not a machine number, the result of a predefined operation must be the nearer of the two adjacent machine numbers. @end{Itemize} Technically, this attribute should yield False when extended registers are used, since a few computed results will cross over the half-way point as a result of double rounding, if and when a value held in an extended register has to be reduced in precision to that of the machine numbers. It does not seem desirable to preclude the use of extended registers when S'Machine_Rounds could otherwise be True. @end{Discussion} @Attribute{Prefix=<S>, AttrName=<Machine_Overflows>, Text=[Yields the value True if overflow and divide-by-zero are detected and reported by raising Constraint_Error for every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @Attribute{Prefix=<S>, AttrName=<Signed_Zeros>, Text=[Yields the value True if the hardware representation for the type @i{T} has the capability of representing both positively and negatively signed zeros, these being generated and used by the predefined operations of the type @i{T} as specified in IEC 559:1989; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @Leading@Defn{normalized exponent} For every value @RI{x} of a floating point type @i{T}, the @i{normalized exponent} of @RI{x} is defined as follows: @begin{Itemize} the normalized exponent of zero is (by convention) zero; for nonzero @RI{x}, the normalized exponent of @RI{x} is the unique integer @RI{k} such that @RI{T}@R['Machine_Radix]@+{@RI{k}@en@;1} @leq @Abs{@RI{x}} @Lt @RI{T}@R['Machine_Radix]@+{@RI{k}}. @end{Itemize} @begin{Ramification} The normalized exponent of a normalized number @RI{x} is the value of @i{exponent} in the canonical-form representation of @RI{x}. The normalized exponent of a denormalized number is less than the value of @i{T}'Machine_Emin. @end{Ramification} @begin{Wide} @Leading@Defn{primitive function} The following @i{primitive function attributes} are defined for any subtype S of a floating point type @i{T}. @end{Wide} @begin(Description) @AttributeLeading{Prefix=<S>, AttrName=<Exponent>, Text=[S'Exponent denotes a function with the following specification: @begin(DescExample) @key(function) S'Exponent (@RI(X) : @RI(T)) @key(return) @RI(universal_integer) @end(DescExample) @NoPrefix@;The function yields the normalized exponent of @i{X}.]} @AttributeLeading{Prefix=<S>, AttrName=<Fraction>, Text=[S'Fraction denotes a function with the following specification: @begin(DescExample) @key(function) S'Fraction (@RI(X) : @RI(T)) @key(return) @RI(T) @end(DescExample) @NoPrefix@;The function yields the value @RI(X) @Times @RI(T)@R('Machine_Radix)@+(@en@RI(k)), where @RI(k) is the normalized exponent of @i(X). A zero result@Redundant(, which can only occur when @i(X) is zero,) has the sign of @i(X).]} @begin{Discussion} Informally, when @i{X} is a normalized number, the result is the value obtained by replacing the @i{exponent} by zero in the canonical-form representation of @i{X}. @end{Discussion} @begin{Ramification} Except when @i{X} is zero, the magnitude of the result is greater than or equal to the reciprocal of @i{T}'Machine_Radix and less than one; consequently, the result is always a normalized number, even when @i{X} is a denormalized number. @end{Ramification} @begin{ImplNote} When @i{X} is a denormalized number, the result is the value obtained by replacing the @i{exponent} by zero in the canonical-form representation of the result of scaling @i{X} up sufficiently to normalize it. @end{ImplNote} @AttributeLeading{Prefix=<S>, AttrName=<Compose>, Text=[S'Compose denotes a function with the following specification: @begin{DescExample} @key(function) S'Compose (@RI{Fraction} : @RI{T}; @RI{Exponent} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} Let @RI{v} be the value @RI{Fraction} @Times @RI{T}@R('Machine_Radix)@+{@RI{Exponent}@en@RI{k}}, where @RI{k} is the normalized exponent of @i{Fraction}. If @RI{v} is a machine number of the type @i{T}, or if @Abs{@RI{v}} @geq @RI{T}@R('Model_Small), the function yields @RI{v}; otherwise, it yields either one of the machine numbers of the type @i{T} adjacent to @RI{v}. @IndexCheck{Range_Check}Constraint_Error is optionally raised if @RI{v} is outside the base range of S. A zero result has the sign of @i{Fraction} when S'Signed_Zeros is True.]} @begin{Discussion} Informally, when @i{Fraction} and @RI{v} are both normalized numbers, the result is the value obtained by replacing the @i{exponent} by @i{Exponent} in the canonical-form representation of @i{Fraction}. @end{Discussion} @begin{Ramification} If @i{Exponent} is less than @i{T}'Machine_Emin and @i{Fraction} is nonzero, the result is either zero, @i{T}'Model_Small, or (if @i{T}'Denorm is True) a denormalized number. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Scaling>, Text=[S'Scaling denotes a function with the following specification: @begin{DescExample} @key(function) S'Scaling (@RI{X} : @RI{T}; @RI{Adjustment} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} Let @RI{v} be the value @RI{X} @Times @RI{T}@R('Machine_Radix)@+{@RI{Adjustment}}. If @RI{v} is a machine number of the type @i{T}, or if @Abs{@RI{v}} @geq @RI{T}@R('Model_Small), the function yields @RI{v}; otherwise, it yields either one of the machine numbers of the type @i{T} adjacent to @RI{v}. @IndexCheck{Range_Check}Constraint_Error is optionally raised if @RI{v} is outside the base range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Discussion} Informally, when @i{X} and @RI{v} are both normalized numbers, the result is the value obtained by increasing the @i{exponent} by @i{Adjustment} in the canonical-form representation of @i{X}. @end{Discussion} @begin{Ramification} If @i{Adjustment} is sufficiently small (i.e., sufficiently negative), the result is either zero, @i{T}'Model_Small, or (if @i{T}'Denorm is True) a denormalized number. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Floor>, Text=[S'Floor denotes a function with the following specification: @begin{DescExample} @key(function) S'Floor (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Floor{@RI{X}}, i.e., the largest (most positive) integral value less than or equal to @i{X}. When @i{X} is zero, the result has the sign of @i{X}; a zero result otherwise has a positive sign.]} @AttributeLeading{Prefix=<S>, AttrName=<Ceiling>, Text=[S'Ceiling denotes a function with the following specification: @begin{DescExample} @key(function) S'Ceiling (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Ceiling{@RI{X}}, i.e., the smallest (most negative) integral value greater than or equal to @i{X}. When @i{X} is zero, the result has the sign of @i{X}; a zero result otherwise has a negative sign when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Rounding>, Text=[S'Rounding denotes a function with the following specification: @begin{DescExample} @key(function) S'Rounding (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the integral value nearest to @i{X}, rounding away from zero if @i{X} lies exactly halfway between two integers. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Unbiased_Rounding>, Text=[S'Unbiased_Rounding denotes a function with the following specification: @begin{DescExample} @key(function) S'Unbiased_Rounding (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the integral value nearest to @i{X}, rounding toward the even integer if @i{X} lies exactly halfway between two integers. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Machine_Rounding>, ARef=[AI95-00267-01], Text=[@Chg{Version=[2],New=[S'Machine_Rounding denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key(function) S'Machine_Rounding (@RI{X} : @RI{T}) @key(return) @RI{T}]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The function yields the integral value nearest to @i{X}. If @i{X} lies exactly halfway between two integers, one of those integers is returned, but which of them is returned is unspecified. A zero result has the sign of @i{X} when S'Signed_Zeros is True. This function provides access to the rounding behavior which is most efficient on the target processor.@PDefn{unspecified}]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[We leave the rounding unspecified, so that users cannot depend on a particular rounding. This attribute is intended for use in cases where the particular rounding chosen is irrelevant. If there is a need to know which way values halfway between two integers are rounded, one of the other rounding attributes should be used.]} @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Truncation>, Text=[S'Truncation denotes a function with the following specification: @begin{DescExample} @key(function) S'Truncation (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Ceiling{@RI{X}} when @i{X} is negative, and @Floor{@RI{X}} otherwise. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Remainder>, Text=[S'Remainder denotes a function with the following specification: @begin{DescExample} @key(function) S'Remainder (@RI{X}, @RI{Y} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For nonzero @i{Y}, let @RI{v} be the value @RI{X} @en @RI{n} @Times @RI{Y}, where @RI{n} is the integer nearest to the exact value of @RI{X}/@RI{Y}; if @Abs{@RI{n} @en @RI{X}/@RI{Y}} = 1/2, then @RI(n) is chosen to be even. If @RI{v} is a machine number of the type @i{T}, the function yields @RI{v}; otherwise, it yields zero. @IndexCheck{Division_Check}Constraint_Error is raised if @i{Y} is zero. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Ramification} The magnitude of the result is less than or equal to one-half the magnitude of @i{Y}. @end{Ramification} @begin{Discussion} Given machine numbers @i{X} and @i{Y} of the type @i{T}, @RI{v} is necessarily a machine number of the type @i{T}, except when @i{Y} is in the neighborhood of zero, @i{X} is sufficiently close to a multiple of @i{Y}, and @i{T}'Denorm is False. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Adjacent>, Text=[S'Adjacent denotes a function with the following specification: @begin{DescExample} @key(function) S'Adjacent (@RI{X}, @RI{Towards} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If @RI{Towards} = @RI{X}, the function yields @i{X}; otherwise, it yields the machine number of the type @i{T} adjacent to @i{X} in the direction of @i{Towards}, if that machine number exists. @IndexCheck{Range_Check}If the result would be outside the base range of S, Constraint_Error is raised. When @i{T}'Signed_Zeros is True, a zero result has the sign of @i{X}. When @i{Towards} is zero, its sign has no bearing on the result.]} @begin{Ramification} The value of S'Adjacent(0.0, 1.0) is the smallest normalized positive number of the type @i{T} when @i{T}'Denorm is False and the smallest denormalized positive number of the type @i{T} when @i{T}'Denorm is True. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Copy_Sign>, Text=[S'Copy_Sign denotes a function with the following specification: @begin{DescExample} @key(function) S'Copy_Sign (@RI{Value}, @RI{Sign} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If the value of @i{Value} is nonzero, the function yields a result whose magnitude is that of @i{Value} and whose sign is that of @i{Sign}; otherwise, it yields the value zero. @IndexCheck{Range_Check}Constraint_Error is optionally raised if the result is outside the base range of S. A zero result has the sign of @i{Sign} when S'Signed_Zeros is True.]} @begin{Discussion} S'Copy_Sign is provided for convenience in restoring the sign to a quantity from which it has been temporarily removed, or to a related quantity. When S'Signed_Zeros is True, it is also instrumental in determining the sign of a zero quantity, when required. (Because negative and positive zeros compare equal in systems conforming to IEC 559:1989, a negative zero does @i{not} appear to be negative when compared to zero.) The sign determination is accomplished by transferring the sign of the zero quantity to a nonzero quantity and then testing for a negative result. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Leading_Part>, Text=[S'Leading_Part denotes a function with the following specification: @begin{DescExample} @key(function) S'Leading_Part (@RI{X} : @RI{T}; @RI{Radix_Digits} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;Let @RI{v} be the value @RI{T}@R('Machine_Radix)@+{@RI{k}@en@RI{Radix_Digits}}, where @RI{k} is the normalized exponent of @i{X}. The function yields the value @begin{Itemize} @Floor{@RI{X}/@RI{v}} @Times @RI{v}, when @i{X} is nonnegative and @i{Radix_Digits} is positive; @Ceiling{@RI{X}/@RI{v}} @Times @RI{v}, when @i{X} is negative and @i{Radix_Digits} is positive. @end{Itemize} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} @IndexCheck{Range_Check}Constraint_Error is raised when @i{Radix_Digits} is zero or negative. A zero result@Redundant{, which can only occur when @i{X} is zero,} has the sign of @i{X}.]} @begin{Discussion} Informally, if @i{X} is nonzero, the result is the value obtained by retaining only the specified number of (leading) significant digits of @i{X} (in the machine radix), setting all other digits to zero. @end{Discussion} @begin{ImplNote} The result can be obtained by first scaling @i{X} up, if necessary to normalize it, then masking the mantissa so as to retain only the specified number of leading digits, then scaling the result back down if @i{X} was scaled up. @end{ImplNote} @AttributeLeading{Prefix=<S>, AttrName=<Machine>, Text=[S'Machine denotes a function with the following specification: @begin{DescExample} @key(function) S'Machine (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If @i{X} is a machine number of the type @i{T}, the function yields @i{X}; otherwise, it yields the value obtained by rounding or truncating @i{X} to either one of the adjacent machine numbers of the type @i(T). @IndexCheck{Range_Check}Constraint_Error is raised if rounding or truncating @i{X} to the precision of the machine numbers results in a value outside the base range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Discussion} All of the primitive function attributes except Rounding and Machine correspond to subprograms in the Generic_Primitive_Functions generic package proposed as a separate ISO standard (ISO/IEC DIS 11729) for Ada 83. The Scaling, Unbiased_Rounding, and Truncation attributes correspond to the Scale, Round, and Truncate functions, respectively, in Generic_Primitive_Functions. The Rounding attribute rounds away from zero; this functionality was not provided in Generic_Primitive_Functions. The name Round was not available for either of the primitive function attributes that perform rounding, since an attribute of that name is used for a different purpose for decimal fixed point types. Likewise, the name Scale was not available, since an attribute of that name is also used for a different purpose for decimal fixed point types. The functionality of the Machine attribute was also not provided in Generic_Primitive_Functions. The functionality of the Decompose procedure of Generic_Primitive_Functions is only provided in the form of the separate attributes Exponent and Fraction. The functionality of the Successor and Predecessor functions of Generic_Primitive_Functions is provided by the extension of the existing Succ and Pred attributes. @end{Discussion} @begin{ImplNote} The primitive function attributes may be implemented either with appropriate floating point arithmetic operations or with integer and logical operations that act on parts of the representation directly. The latter is strongly encouraged when it is more efficient than the former; it is mandatory when the former cannot deliver the required accuracy due to limitations of the implementation's arithmetic operations. @end{ImplNote} @end(Description) @begin{Wide} @Leading@Defn2{Term=[model-oriented attributes], Sec=[of a floating point subtype]} The following @i{model-oriented attributes} are defined for any subtype S of a floating point type @i{T}. @end{Wide} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Model_Mantissa>, Text=[If the Numerics Annex is not supported, this attribute yields an implementation defined value that is greater than or equal to @Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + 1, where @RI{d} is the requested decimal precision of @i{T}, and less than or equal to the value of @i{T}'Machine_Mantissa. See @RefSecNum{Model-Oriented Attributes of Floating Point Types} for further requirements that apply to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Model_Emin>, Text=[If the Numerics Annex is not supported, this attribute yields an implementation defined value that is greater than or equal to the value of @i{T}'Machine_Emin. See @RefSecNum{Model-Oriented Attributes of Floating Point Types} for further requirements that apply to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Model_Epsilon>, Text=[Yields the value @RI{T}@R('Machine_Radix)@+{1 @en @RI{T}@R('Model_Mantissa)}. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} In most implementations, this attribute yields the absolute value of the difference between one and the smallest machine number of the type @i{T} above one which, when added to one, yields a machine number different from one. Further discussion can be found in @RefSecNum{Model-Oriented Attributes of Floating Point Types}. @end{Discussion} @Attribute{Prefix=<S>, AttrName=<Model_Small>, Text=[Yields the value @RI{T}@R('Machine_Radix)@+{@RI{T}@R('Model_Emin) @en 1}. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} In most implementations, this attribute yields the smallest positive normalized number of the type @i{T}, i.e. the number corresponding to the positive underflow threshold. In some implementations employing a radix-complement representation for the type @i{T}, the positive underflow threshold is closer to zero than is the negative underflow threshold, with the consequence that the smallest positive normalized number does not coincide with the positive underflow threshold (i.e., it exceeds the latter). Further discussion can be found in @RefSecNum{Model-Oriented Attributes of Floating Point Types}. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Model>, Text=[S'Model denotes a function with the following specification: @begin{DescExample} @key(function) S'Model (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;If the Numerics Annex is not supported, the meaning of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex.]} @Attribute{Prefix=<S>, AttrName=<Safe_First>, Text=[Yields the lower bound of the safe range (see @RefSecNum{Floating Point Types}) of the type @i{T}. If the Numerics Annex is not supported, the value of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_real}.]} @Attribute{Prefix=<S>, AttrName=<Safe_Last>, Text=[Yields the upper bound of the safe range (see @RefSecNum{Floating Point Types}) of the type @i{T}. If the Numerics Annex is not supported, the value of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} A predefined floating point arithmetic operation that yields a value in the safe range of its result type is guaranteed not to overflow. @end{Discussion} @begin{Honest} An exception is made for exponentiation by a negative exponent in @RefSecNum{Highest Precedence Operators}. @end{Honest} @ImplDef{The values of the Model_Mantissa, Model_Emin, Model_Epsilon, Model, Safe_First, and Safe_Last attributes, if the Numerics Annex is not supported.} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The Epsilon and Mantissa attributes of floating point types are removed from the language and replaced by Model_Epsilon and Model_Mantissa, which may have different values (as a result of changes in the definition of model numbers); the replacement of one set of attributes by another is intended to convert what would be an inconsistent change into an incompatible change. The Emax, Small, Large, Safe_Emax, Safe_Small, and Safe_Large attributes of floating point types are removed from the language. Small and Safe_Small are collectively replaced by Model_Small, which is functionally equivalent to Safe_Small, though it may have a slightly different value. The others are collectively replaced by Safe_First and Safe_Last. Safe_Last is functionally equivalent to Safe_Large, though it may have a different value; Safe_First is comparable to the negation of Safe_Large but may differ slightly from it as well as from the negation of Safe_Last. Emax and Safe_Emax had relatively few uses in Ada 83; T'Safe_Emax can be computed in the revised language as Integer'Min(T'Exponent(T'Safe_First), T'Exponent(T'Safe_Last)). Implementations are encouraged to eliminate the incompatibilities discussed here by retaining the old attributes, during a transition period, in the form of implementation-defined attributes with their former values. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The Model_Emin attribute is new. It is conceptually similar to the negation of Safe_Emax attribute of Ada 83, adjusted for the fact that the model numbers now have the hardware radix. It is a fundamental determinant, along with Model_Mantissa, of the set of model numbers of a type (see @RefSecNum{Model of Floating Point Arithmetic}). The Denorm and Signed_Zeros attributes are new, as are all of the primitive function attributes. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00388-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Machine_Rounding attribute is new.]} @end{Extend95} @LabeledSubClause{Attributes of Fixed Point Types} @begin{StaticSem} @Leading@Defn2{Term=[representation-oriented attributes], Sec=[of a fixed point subtype]} The following @i{representation-oriented} attributes are defined for @PrefixType{every subtype S of a fixed point type @i{T}}. @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Radix>, Text=[Yields the radix of the hardware representation of the type @i{T}. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Machine_Rounds>, Text=[Yields the value True if rounding is performed on inexact results of every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @Attribute{Prefix=<S>, AttrName=<Machine_Overflows>, Text=[Yields the value True if overflow and divide-by-zero are detected and reported by raising Constraint_Error for every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The Mantissa, Large, Safe_Small, and Safe_Large attributes of fixed point types are removed from the language. Implementations are encouraged to eliminate the resulting incompatibility by retaining these attributes, during a transition period, in the form of implementation-defined attributes with their former values. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The Machine_Radix attribute is now allowed for fixed point types. It is also specifiable in an attribute definition clause (see @RefSecNum{Machine_Radix Attribute Definition Clause}). @end{Extend83} ����������������������������������������������������������org.adaic.arm_form/source_2005/rm.msm���������������������������������������������������������������0000755�0001752�0001001�00000013250�12273462240�016556� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the RM (public versions)} @Comment{Global properties} @HideIndexEntries @HideAnnotations @HideISO @NumberParagraphs @LinkNonTerminals @Title{Version=[0],Text=[Ada Reference Manual]}@Comment{Same title for all versions} @FilePrefix{RM} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @RTFHeaderPrefix{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @Comment{PDFs: @RTFHeaderPrefix{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]}} @Comment{Springer:}@RTFHeaderPrefix{Version=[2],Text=[Consolidated Ada Reference Manual - 2005 Edition]} @RTFPageSize{Ada95} @RTFFonts{Serif=[Times],SansSerif=[Arial]} @Comment{HTML properties} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]}@Comment{Was "4Comp" for the Consolidated AARM} @HTMLNavBar{RefName=[RM-STDS.html],SrchName=[RM-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><SPAN Style="font-size:200%; color: rgb(0,0,153)"><B>Ada Reference Manual</B></SPAN> — <A HREF="RM-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="vertical-align: middle">Sponsored by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO requires skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO requires skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/rt.mss���������������������������������������������������������������0000755�0001752�0001001�00000653627�12273462240�016615� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{ $Source: e:\\cvsroot/ARM/Source/rt.mss,v $ } @comment{ $Revision: 1.75 $ $Date: 2006/10/19 06:40:31 $ $Author: Randy $ } @Part(realtime, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:31 $} @LabeledNormativeAnnex{Real-Time Systems} @begin{Intro} @Defn{real-time systems} @Defn{embedded systems} This Annex specifies additional characteristics of Ada implementations intended for real-time systems software. To conform to this Annex, an implementation shall also conform to the Systems Programming Annex. @end{Intro} @begin{Metrics} The metrics are documentation requirements; an implementation shall document the values of the language-defined metrics for at least one configuration @Redundant[of hardware or an underlying system] supported by the implementation, and shall document the details of that configuration. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Values of all @MetricsTitle.]}]}@ChgNote{We're going to document the individual metrics sections.} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The details of the configuration used to generate the values of all metrics.]}]} @begin{Reason} The actual values of the metrics are likely to depend on hardware configuration details that are variable and generally outside the control of a compiler vendor. @end{Reason} The metrics do not necessarily yield a simple number. @Redundant[For some, a range is more suitable, for others a formula dependent on some parameter is appropriate, and for others, it may be more suitable to break the metric into several cases.] Unless specified otherwise, the metrics in this annex are expressed in processor clock cycles. For metrics that require documentation of an upper bound, if there is no upper bound, the implementation shall report that the metric is unbounded. @begin{Discussion} There are several good reasons to specify metrics in seconds; there are however equally good reasons to specify them in processor clock cycles. In defining the metrics, we have tried to strike a balance on a case-by-case basis. It has been suggested that all metrics should be given names, so that @lquotes@;data-sheets@rquotes@; could be formulated and published by vendors. However the paragraph number can serve that purpose. @end{Discussion} @end{Metrics} @begin{Notes} The specification of the metrics makes a distinction between upper bounds and simple execution times. Where something is just specified as @lquotes@;the execution time of@rquotes@; a piece of code, this leaves one the freedom to choose a nonpathological case. This kind of metric is of the form @lquotes@;there exists a program such that the value of the metric is V@rquotes@;. Conversely, the meaning of upper bounds is @lquotes@;there is no program such that the value of the metric is greater than V@rquotes@;. This kind of metric can only be partially tested, by finding the value of V for one or more test programs. The metrics do not cover the whole language; they are limited to features that are specified in @RefSec{Systems Programming} and in this Annex. The metrics are intended to provide guidance to potential users as to whether a particular implementation of such a feature is going to be adequate for a particular real-time application. As such, the metrics are aimed at known implementation choices that can result in significant performance differences. The purpose of the metrics is not necessarily to provide fine-grained quantitative results or to serve as a comparison between different implementations on the same or different platforms. Instead, their goal is rather qualitative; to define a standard set of approximate values that can be measured and used to estimate the general suitability of an implementation, or to evaluate the comparative utility of certain features of an implementation for a particular real-time application. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Task Priorities} @begin{Intro} @Redundant[This clause specifies the priority model for real-time systems. In addition, the methods for specifying priorities are defined.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @leading@keepnext@;The form of a @nt{pragma} Priority is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Priority)(@Syn2{expression});' @begin{SyntaxText} @leading@keepnext@;The form of a @nt{pragma} Interrupt_Priority is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Interrupt_Priority)[(@Syn2{expression})];' @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(Priority pragma argument)} @PDefn2{Term=[expected type], Sec=(Interrupt_Priority pragma argument)} The expected type for the @nt{expression} in a Priority or Interrupt_Priority pragma is Integer. @end{Resolution} @begin{Legality} A Priority pragma is allowed only immediately within a @nt{task_definition}, a @nt{protected_definition}, or the @nt{declarative_part} of a @nt{subprogram_body}. An Interrupt_Priority pragma is allowed only immediately within a @nt{task_definition} or a @nt{protected_definition}. At most one such pragma shall appear within a given construct. For a Priority pragma that appears in the @nt{declarative_part} of a @nt{subprogram_body}, the @nt{expression} shall be static, and its value shall be in the range of System.Priority. @begin{Reason} This value is needed before it gets elaborated, when the environment task starts executing. @end{Reason} @end{Legality} @begin{StaticSem} @leading@keepnext@;The following declarations exist in package System: @begin{example} @key{subtype} Any_Priority @key{is} Integer @key{range} @RI{implementation-defined}; @key{subtype} Priority @key{is} Any_Priority @key{range} Any_Priority'First .. @RI{implementation-defined}; @key{subtype} Interrupt_Priority @key{is} Any_Priority @key{range} Priority'Last+1 .. Any_Priority'Last; Default_Priority : @key{constant} Priority := (Priority'First + Priority'Last)/2; @end{example} @ImplDef{The declarations of Any_Priority and Priority.} The full range of priority values supported by an implementation is specified by the subtype Any_Priority. The subrange of priority values that are high enough to require the blocking of one or more interrupts is specified by the subtype Interrupt_@!Priority. @Redundant[The subrange of priority values below System.@!Interrupt_@!Priority'First is specified by the subtype System.@!Priority.] The priority specified by a Priority or Interrupt_Priority pragma is the value of the @nt{expression} in the pragma, if any. If there is no @nt{expression} in an Interrupt_Priority pragma, the priority value is Interrupt_Priority'Last. @end{StaticSem} @begin{RunTime} A Priority pragma has no effect if it occurs in the @nt{declarative_part} of the @nt{subprogram_body} of a subprogram other than the main subprogram. @Defn{task priority} @Defn{priority} @Defn{priority inheritance} @Defn{base priority} @Defn{active priority} A @i{task priority} is an integer value that indicates a degree of urgency and is the basis for resolving competing demands of tasks for resources. Unless otherwise specified, whenever tasks compete for processors or other implementation-defined resources, the resources are allocated to the task with the highest priority value. The @i{base priority} of a task is the priority with which it was created, or to which it was later set by Dynamic_Priorities.Set_Priority (see @RefSecNum{Dynamic Priorities}). At all times, a task also has an @i{active priority}, which generally reflects its base priority as well as any priority it inherits from other sources. @i{Priority inheritance} is the process by which the priority of a task or other entity (e.g. a protected object; see @RefSecNum{Priority Ceiling Locking}) is used in the evaluation of another task's active priority. @ImplDef{Implementation-defined execution resources.} The effect of specifying such a pragma in a @nt{protected_definition} is discussed in @RefSecNum{Priority Ceiling Locking}. @Defn2{Term=[creation], Sec=(of a task object)} The @nt{expression} in a Priority or Interrupt_Priority pragma that appears in a @nt{task_definition} is evaluated for each task object (see @RefSecNum{Task Units and Task Objects}). For a Priority pragma, the value of the @nt{expression} is converted to the subtype Priority; for an Interrupt_Priority pragma, this value is converted to the subtype Any_Priority. The priority value is then associated with the task object whose @nt{task_definition} contains the pragma. @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)} Likewise, the priority value is associated with the environment task if the pragma appears in the @nt{declarative_part} of the main subprogram. The initial value of a task's base priority is specified by default or by means of a Priority or Interrupt_Priority pragma. @Redundant[After a task is created, its base priority can be changed only by a call to Dynamic_Priorities.Set_Priority (see @RefSecNum{Dynamic Priorities}).] The initial base priority of a task in the absence of a pragma is the base priority of the task that creates it at the time of creation (see @RefSecNum{Task Units and Task Objects}). If a pragma Priority does not apply to the main subprogram, the initial base priority of the environment task is System.Default_Priority. @Redundant[The task's active priority is used when the task competes for processors. Similarly, the task's active priority is used to determine the task's position in any queue when Priority_Queuing is specified (see @RefSecNum{Entry Queuing Policies}).] @Leading@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} At any time, the active priority of a task is the maximum of all the priorities the task is inheriting at that instant. For a task that is not held (see @RefSecNum{Asynchronous Task Control}), its base priority is @Chg{Version=[2],New=[],Old=[always ]}a source of priority inheritance @Chg{Version=[2],New=[unless otherwise specified for a particular task dispatching policy],Old=[]}. Other sources of priority inheritance are specified under the following conditions: @begin{Discussion} Other parts of the annex, e.g. @RefSecNum{Asynchronous Task Control}, define other sources of priority inheritance. @end{Discussion} @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0072],ARef=[AI95-00092-01]} During activation, a task being activated inherits the active priority @Chg{New=[that],Old=[of the]} its activator (see @RefSecNum{Task Execution - Task Activation})@Chg{New=[ had at the time the activation was initiated],Old=[]}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0072],ARef=[AI95-00092-01]} During rendezvous, the task accepting the entry call inherits the @Chg{New=[],Old=[active ]}priority of the @Chg{New=[entry call],Old=[caller]} (see @RefSecNum{Entry Calls}@Chg{New=[ and @RefSecNum{Entry Queuing Policies}],Old=[]}). During a protected action on a protected object, a task inherits the ceiling priority of the protected object (see @RefSecNum{Intertask Communication} and @RefSecNum{Priority Ceiling Locking}). @end{itemize} In all of these cases, the priority ceases to be inherited as soon as the condition calling for the inheritance no longer exists. @end{RunTime} @begin{ImplReq} The range of System.Interrupt_Priority shall include at least one value. The range of System.Priority shall include at least 30 values. @end{ImplReq} @begin{Notes} The priority expression can include references to discriminants of the enclosing type. It is a consequence of the active priority rules that at the point when a task stops inheriting a priority from another source, its active priority is re-evaluated. This is in addition to other instances described in this Annex for such re-evaluation. An implementation may provide a non-standard mode in which tasks inherit priorities under conditions other than those specified above. @begin{Ramification} The use of a Priority or Interrupt_Priority pragma does not require the package System to be named in a @nt{with_clause} for the enclosing @nt{compilation_unit}. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The priority of a task is per-object and not per-type. Priorities need not be static anymore (except for the main subprogram). @end{Extend83} @begin{DiffWord83} The description of the Priority pragma has been moved to this annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0072],ARef=[AI95-00092-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that dynamic priority changes are not transitive - that is, they don't apply to tasks that are being activated by or in rendezvous with the task that had its priority changed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[Generalized the definition of priority inheritance to take into account the differences between the existing and new dispatching policies.]} @end{DiffWord95} @LabeledClause{Priority Scheduling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Redundant[This clause describes the rules that determine which task is selected for execution when more than one task is ready (see @Chg{Version=[2],New=[@RefSecNum{Tasks and Synchronization}], Old=[@RefSecNum{Task Execution - Task Activation}]}).@Chg{Version=[2], New=[],Old=[ The rules have two parts: the task dispatching model (see @RefSecNum{The Task Dispatching Model}), and a specific task dispatching policy (see @RefSecNum{Task Dispatching Pragmas}).]}] @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[This introduction is simplified in order to reflect the rearrangement and expansion of this clause.]} @end{DiffWord95} @LabeledSubClause{The Task Dispatching Model} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Redundant[The task dispatching model specifies @Chg{Version=[2], New=[task],Old=[preemptive]} scheduling, based on conceptual priority-ordered ready queues.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<package> Ada.Dispatching @key<is>@ChildUnit{Parent=[Ada],Child=[Dispatching]} @key<pragma> Pure(Dispatching); @AdaExcDefn{Dispatching_Policy_Error} : @key<exception>; @key<end> Ada.Dispatching;]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Dispatching serves as the parent of other language-defined library units concerned with task dispatching.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} A task @Chg{Version=[2],New=[can become],Old=[runs (that is, it becomes]} a @i{running task}@Chg{Version=[2],New=[],Old=[)]} only @Chg{Version=[2], New=[if],Old=[when]} it is ready (see @Chg{Version=[2],New=[@RefSecNum{Tasks and Synchronization}], Old=[@RefSecNum{Task Execution - Task Activation}]}) and the execution resources required by that task are available. Processors are allocated to tasks based on each task's active priority. It is implementation defined whether, on a multiprocessor, a task that is waiting for access to a protected object keeps its processor busy. @ImplDef{Whether, on a multiprocessor, a task that is waiting for access to a protected object keeps its processor busy.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{task dispatching} @Defn{dispatching, task} @RootDefn{task dispatching point} @RootDefn{dispatching point} @i{Task dispatching} is the process by which one ready task is selected for execution on a processor. This selection is done at certain points during the execution of a task called @i{task dispatching points}. A task reaches a task dispatching point whenever it becomes blocked, and @Chg{Version=[2],New=[when it terminates],Old=[whenever it becomes ready. In addition, the completion of an @nt{accept_statement} (see @RefSecNum{Entries and Accept Statements}), and task termination are task dispatching points for the executing task]}. @Redundant[Other task dispatching points are defined throughout this Annex@Chg{Version=[2],New=[ for specific policies],Old=[]}.] @begin{Ramification} On multiprocessor systems, more than one task can be chosen, at the same time, for execution on more than one processor, as explained below. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{ready queue} @Defn{head (of a queue)} @Defn{tail (of a queue)} @Defn{ready task} @PDefn{task dispatching policy} @PDefn{dispatching policy for tasks} @i{Task dispatching policies} are specified in terms of conceptual @i{ready queues}@Chg{Version=[2],New=[ and],Old=[,]} task states@Chg{Version=[2], New=[],Old=[, and task preemption]}. A ready queue is an ordered list of ready tasks. The first position in a queue is called the @i{head of the queue}, and the last position is called the @i{tail of the queue}. A task is @i{ready} if it is in a ready queue, or if it is running. Each processor has one ready queue for each priority value. At any instant, each ready queue of a processor contains exactly the set of tasks of that priority that are ready for execution on that processor, but are not running on any processor; that is, those tasks that are ready, are not running on any processor, and can be executed using that processor and other available resources. A task can be on the ready queues of more than one processor. @begin{Discussion} The core language defines a ready task as one that is not blocked. Here we refine this definition and talk about ready queues. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{running task} Each processor also has one @i{running task}, which is the task currently being executed by that processor. Whenever a task running on a processor reaches a task dispatching point@Chg{Version=[2],New=[ it goes back to one or more ready queues; a], Old=[, one]} task @Chg{Version=[2],New=[(possibly the same task) ],Old=[]}is @Chg{Version=[2],New=[then ],Old=[]}selected to run on that processor. The task selected is the one at the head of the highest priority nonempty ready queue; this task is then removed from all ready queues to which it belongs. @begin{Discussion} There is always at least one task to run, if we count the idle task. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[@Defn{preemptible resource} A preemptible resource is a resource that while allocated to one task can be allocated (temporarily) to another instead. Processors are preemptible resources. Access to a protected object (see @RefSecNum{Protected Subprograms and Protected Actions}) is a nonpreemptible resource. @Defn{preempted task} When a higher-priority task is dispatched to the processor, and the previously running task is placed on the appropriate ready queue, the latter task is said to be @i{preempted}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[A processor that is executing a task is available to execute tasks of higher priority, within the set of tasks that that processor is able to execute. Write access to a protected object, on the other hand, cannot be granted to a new task before the old task has released it.]} @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} A new running task is also selected whenever there is a nonempty ready queue with a higher priority than the priority of the running task, or when the task dispatching policy requires a running task to go back to a ready queue. @Redundant[These are also task dispatching points.]]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Thus, when a task becomes ready, this is a task dispatching point for all running tasks of lower priority.]} @end{Ramification} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} An implementation is allowed to define additional resources as execution resources, and to define the corresponding allocation policies for them. Such resources may have an implementation@Chg{Version=[2],New=[-],Old=[ ]}defined effect on task dispatching@Chg{Version=[2],New=[], Old=[ (see @RefSecNum{Task Dispatching Pragmas})]}. @ChgImplDef{Version=[2],Kind=[Revised], Text=[The @Chg{Version=[2],New=[effect],Old=[affect]} of implementation@Chg{Version=[2],New=[-],Old=[ ]}defined execution resources on task dispatching.]} An implementation may place implementation-defined restrictions on tasks whose active priority is in the Interrupt_Priority range. @begin{Ramification} For example, on some operating systems, it might be necessary to disallow them altogether. This permission applies to tasks whose priority is set to interrupt level for any reason: via a pragma, via a call to Dynamic_Priorities.Set_Priority, or via priority inheritance. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00321-01]} @ChgNote{This was moved up from the previous section.} @ChgAdded{Version=[2],Text=[@Redundant[For optimization purposes,] an implementation may alter the points at which task dispatching occurs, in an implementation-defined manner. However, a @nt{delay_statement} always corresponds to at least one task dispatching point.]} @end{ImplPerm} @begin{Notes} Section 9 specifies under which circumstances a task becomes ready. The ready state is affected by the rules for task activation and termination, delay statements, and entry calls. @PDefn{blocked} When a task is not ready, it is said to be blocked. An example of a possible implementation-defined execution resource is a page of physical memory, which needs to be loaded with a particular page of virtual memory before a task can continue execution. The ready queues are purely conceptual; there is no requirement that such lists physically exist in an implementation. While a task is running, it is not on any ready queue. Any time the task that is running on a processor is added to a ready queue, a new running task is selected for that processor. In a multiprocessor system, a task can be on the ready queues of more than one processor. At the extreme, if several processors share the same set of ready tasks, the contents of their ready queues is identical, and so they can be viewed as sharing one ready queue, and can be implemented that way. @Redundant[Thus, the dispatching model covers multiprocessors where dispatching is implemented using a single ready queue, as well as those with separate dispatching domains.] The priority of a task is determined by rules specified in this subclause, and under @RefSec{Task Priorities}, @RefSec{Priority Ceiling Locking}, and @RefSec{Dynamic Priorities}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgNote{This note is moved up from the next subclause.} @ChgAdded{Version=[2],Text=[The setting of a task's base priority as a result of a call to Set_Priority does not always take effect immediately when Set_Priority is called. The effect of setting the task's base priority is deferred while the affected task performs a protected action.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[This description is simplified to describe only the parts of the dispatching model common to all policies. In particular, rules about preemption are moved elsewhere. This makes it easier to add other policies (which may not involve preemption).]} @end{DiffWord95} @LabeledRevisedSubClause{Version=[2], New=[Task Dispatching Pragmas], Old=[The Standard Task Dispatching Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause allows a single task dispatching policy to be defined for all priorities, or the range of priorities to be split into subranges that are assigned individual dispatching policies.]]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Task_Dispatching_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Task_Dispatching_Policy)(@SynI{policy_}@Syn2{identifier});' @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Priority_Specific_Dispatching is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Priority_Specific_Dispatching> (@* @ @ @ @ @ @SynI{policy_}@Syn2{identifier}, @SynI{first_priority_}@Syn2{expression}, @SynI{last_priority_}@Syn2{expression});''} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The expected type for @SynI{first_priority_}@nt{expression} and @SynI{last_priority_}@nt{expression} is Integer.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01],ARef=[AI95-00355-01]} The @SynI{policy_}@nt{identifier} @Chg{Version=[2],New=[used in a @nt{pragma} Task_Dispatching_Policy shall be the name of a task dispatching policy], Old=[shall either be FIFO_Within_Priorities or an implementation-defined @Syn2{identifier}]}. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined @SynI{policy_}@Syn2{identifier}s allowed in a @nt{pragma} Task_Dispatching_Policy.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} used in a @nt{pragma} Priority_Specific_Dispatching shall be the name of a task dispatching policy.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Both @Syni{first_priority_}@!@nt{expression} and @Syni{last_priority_}@!@nt{expression} shall be static expressions in the range of System.Any_Priority; @SynI{last_priority_}@!@nt{expression} shall have a value greater than or equal to @SynI{first_priority_}@!@nt{expression}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Task_Dispatching_Policy specifies the single task dispatching policy.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Priority_Specific_Dispatching specifies the task dispatching policy for the specified range of priorities. Tasks with base priorities within the range of priorities specified in a Priority_Specific_Dispatching pragma have their active priorities determined according to the specified dispatching policy. Tasks with active priorities within the range of priorities specified in a Priority_Specific_Dispatching pragma are dispatched according to the specified dispatching policy.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Each ready queue is managed by exactly one policy. Anything else would be chaos. The ready queue is determined by the active priority. However, how the active priority is calculated is determined by the policy; in order to break out of this circle, we have to say that the active priority is calculated by the method determined by the policy of the base priority.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas the dispatching policy for priorities not covered by any Priority_Specific_Dispatching pragmas is FIFO_Within_Priorities.]} @end{StaticSem} @begin{LinkTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @PDefn2{Term=[configuration pragma], Sec=(Task_Dispatching_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Task_Dispatching_Policy)} A Task_Dispatching_Policy pragma is a configuration pragma.@Chg{Version=[2], New=[ A Priority_Specific_Dispatching pragma is a configuration pragma. @PDefn2{Term=[configuration pragma], Sec=(Priority_Specific_Dispatching)} @PDefn2{Term=[pragma, configuration], Sec=(Priority_Specific_Dispatching)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The priority ranges specified in more than one Priority_Specific_Dispatching pragma within the same partition shall not be overlapping.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas it shall not contain a Task_Dispatching_Policy pragma.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00333-01]} @ChgDeleted{Version=[2],Text=[If the FIFO_Within_Priorities policy is specified for a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @Defn{task dispatching policy} @Redundant[A @i{task dispatching policy} specifies the details of task dispatching that are not covered by the basic task dispatching model. These rules govern when tasks are inserted into and deleted from the ready queues@Chg{Version=[2],New=[],Old=[, and whether a task is inserted at the head or the tail of the queue for its active priority]}.] @Chg{Version=[2],New=[A single],Old=[The]} task dispatching policy is specified by a Task_Dispatching_Policy @Chg{Version=[2],New=[],Old=[configuration ]}pragma. @Chg{Version=[2],New=[Pragma Priority_Specific_Dispatching assigns distinct dispatching policies to subranges of System.Any_Priority.], Old=[@PDefn{unspecified}If no such pragma appears in any of the program units comprising a partition, the task dispatching policy for that partition is unspecified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@PDefn{unspecified}If neither @nt{pragma} applies to any of the program units comprising a partition, the task dispatching policy for that partition is unspecified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas a task dispatching point occurs for the currently running task of a processor whenever there is a non-empty ready queue for that processor with a higher priority than the priority of the running task.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If we have priority specific dispatching then we want preemption across the entire range of priorities. That prevents higher priority tasks from being blocked by lower priority tasks that have a different policy. On the other hand, if we have a single policy for the entire partition, we want the characteristics of that policy to apply for preemption; specifically, we may not require any preemption. Note that policy Non_Preemptive_FIFO_Within_Priorities is not allowed in a priority specific dispatching pragma.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A task that has its base priority changed may move from one dispatching policy to another. It is immediately subject to the new dispatching policy.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Once subject to the new dispatching policy, it may be immediately preempted or dispatched, according the rules of the new policy.]} @end{Ramification} @ChgNote{The following stuff is moved to the next subclause} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 7 through 13 were moved to D.2.3.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[The language defines only one task dispatching policy, FIFO_Within_Priorities; when this policy is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority, except in the case where the active priority is lowered due to the loss of inherited priority, in which case the task is added at the head of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} Each of the events specified above is a task dispatching point (see @RefSecNum{The Task Dispatching Model}).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[In addition, when a task is preempted, it is added at the head of the ready queue for its active priority.]} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00333-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking and also one or more Priority_Specific_Dispatching pragmas to be given.]} @end{ImplReq} @begin{DocReq} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 14 through 16 were moved to D.2.3.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn{priority inversion} @i{Priority inversion} is the duration for which a task remains at the head of the highest priority ready queue while the processor executes a lower priority task. The implementation shall document:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[The maximum priority inversion a user task can experience due to activity of the implementation (on behalf of lower priority tasks), and]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[whether execution of a task can be preempted by the implementation processing of delay expirations for lower priority tasks, and if so, for how long.]} @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of priority inversion.]}]} @end{Itemize} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other task dispatching policies, but need not support more than one @Chg{Version=[2],New=[task dispatching], Old=[such]} policy per partition. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @Chg{Version=[2],New=[An implementation need not support @nt{pragma} Priority_Specific_Dispatching if it is infeasible to support it in the target environment.], Old=[@Redundant[For optimization purposes,] an implementation may alter the points at which task dispatching occurs, in an implementation defined manner. However, a @nt{delay_statement} always corresponds to at least one task dispatching point.]} @ChgImplDef{Version=[2],Kind=[Revised],Text=[Implementation defined task dispatching@Chg{Version=[2],New=[ policies],Old=[]}.]} @end{ImplPerm} @begin{Notes} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 19 through 21 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[If the active priority of a running task is lowered due to loss of inherited priority (as it is on completion of a protected operation) and there is a ready task of the same active priority that is not running, the running task continues to run (provided that there is no higher priority task).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[The setting of a task's base priority as a result of a call to Set_Priority does not always take effect immediately when Set_Priority is called. The effect of setting the task's base priority is deferred while the affected task performs a protected action.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[Setting the base priority of a ready task causes the task to move to the end of the queue for its active priority, regardless of whether the active priority of the task actually changes.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @B[Amendment Correction:] It is no longer required to specify Ceiling_Locking with the language-defined task dispatching policies; we only require that implementations @i<allow> them to be used together.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@key{Pragma} Priority_Specific_Dispatching is new; it allows specifying different policies for different priorities.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one task dispatching policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[This description is simplified to describe only the rules for the Task_Dispatching_Policy pragma that are common to all policies. In particular, rules about preemption are moved elsewhere. This makes it easier to add other policies (which may not involve preemption).]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Preemptive Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause defines a preemptive task dispatching policy.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} FIFO_Within_Priorities is a task dispatching policy.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[When FIFO_Within_Priorities is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority, except in the case where the active priority is lowered due to the loss of inherited priority, in which case the task is added at the head of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} Each of the events specified above is a task dispatching point (see @RefSecNum{The Task Dispatching Model}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[A task dispatching point occurs for the currently running task of a processor whenever there is a nonempty ready queue for that processor with a higher priority than the priority of the running task. The currently running task is said to be @i<preempted> and it is added at the head of the ready queue for its active priority.@Defn2{Term=[preempt],Sec=[a running task]}]} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as FIFO_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the FIFO_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{priority inversion} @i{Priority inversion} is the duration for which a task remains at the head of the highest priority nonempty ready queue while the processor executes a lower priority task. The implementation shall document:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The maximum priority inversion a user task can experience due to activity of the implementation (on behalf of lower priority tasks), and]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The maximum priority inversion a user task can experience from the implementation.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[whether execution of a task can be preempted by the implementation processing of delay expirations for lower priority tasks, and if so, for how long.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The amount of time that a task can be preempted for processing on behalf of lower-priority tasks.]}]} @end{Itemize} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[If the active priority of a running task is lowered due to loss of inherited priority (as it is on completion of a protected operation) and there is a ready task of the same active priority that is not running, the running task continues to run (provided that there is no higher priority task).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[Setting the base priority of a ready task causes the task to move to the tail of the queue for its active priority, regardless of whether the active priority of the task actually changes.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[This subclause is new; it mainly consists of text that was found in @RefSecNum{The Task Dispatching Model} and @RefSecNum{Task Dispatching Pragmas} in Ada 95. This was separated out so the definition of additional policies was easier.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[We require that implementations allow this policy and Ceiling_Locking together.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[We explicitly defined FIFO_Within_Priorities to be a task dispatching policy.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Non-Preemptive Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause defines a non-preemptive task dispatching policy.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} Non_Preemptive_FIFO_Within_Priorities is a task dispatching policy.]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Non_Preemptive_FIFO_Within_Priorities shall not be specified as the @SynI{policy_}@nt{identifier} of @nt{pragma} Priority_Specific_Dispatching (see @RefSecNum{Task Dispatching Pragmas}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The non-preemptive nature of this policy could cause the policies of higher priority tasks to malfunction, missing deadlines and having unlimited priority inversion. That would render the use of such policies impotent and misleading. As such, this policy only makes sense for a complete system.]} @end{Reason} @end{Legality} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[When Non_Preemptive_FIFO_Within_Priorities is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For this policy, a non-blocking @nt{delay_statement} is the only non-blocking event that is a task dispatching point (see @RefSecNum{The Task Dispatching Model}).@PDefn{task dispatching point} @PDefn{dispatching point}]} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as Non_Preemptive_FIFO_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the Non_Preemptive_FIFO_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[Since implementations are allowed to round all ceiling priorities in subrange System.Priority to System.Priority'Last (see @RefSecNum{Priority Ceiling Locking}), an implementation may allow a task to execute within a protected object without raising its active priority provided the associated protected unit does not contain pragma Interrupt_Priority, Interrupt_Handler, or Attach_Handler.]} @end{ImplPerm} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy Non_Preemptive_FIFO_Within_Priorities is new.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Round Robin Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause defines the task dispatching policy Round_Robin_Within_Priorities and the package Round_Robin.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy}_@nt{identifier} Round_Robin_Within_Priorities is a task dispatching policy.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} System; @key{with} Ada.Real_Time; @key{package} Ada.Dispatching.Round_Robin @key{is}@ChildUnit{Parent=[Ada.Dispatching],Child=[Round_Robin]} @AdaObjDefn{Default_Quantum} : @key{constant} Ada.Real_Time.Time_Span := @RI[implementation-defined]; @key{procedure} @AdaSubDefn{Set_Quantum} (Pri : @key{in} System.Priority; Quantum : @key{in} Ada.Real_Time.Time_Span); @key{procedure} @AdaSubDefn{Set_Quantum} (Low, High : @key{in} System.Priority; Quantum : @key{in} Ada.Real_Time.Time_Span); @key{function} @AdaSubDefn{Actual_Quantum} (Pri : System.Priority) @key{return} Ada.Real_Time.Time_Span; @key{function} @AdaSubDefn{Is_Round_Robin} (Pri : System.Priority) @key{return} Boolean; @key{end} Ada.Dispatching.Round_Robin;]} @end{Example} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The value of Default_Quantum in Dispatching.Round_Robin.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[When task dispatching policy Round_Robin_Within_Priorities is the single policy in effect for a partition, each task with priority in the range of System.Interrupt_Priority is dispatched according to policy FIFO_Within_Priorities.]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The procedures Set_Quantum set the required Quantum value for a single priority level Pri or a range of priority levels Low .. High. If no quantum is set for a Round Robin priority level, Default_Quantum is used.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The function Actual_Quantum returns the actual quantum used by the implementation for the priority level Pri.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The function Is_Round_Robin returns True if priority Pri is covered by task dispatching policy Round_Robin_Within_Priorities; otherwise it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A call of Actual_Quantum or Set_Quantum raises exception Dispatching.Dispatching_Policy_Error if a predefined policy other than Round_Robin_Within_Priorities applies to the specified priority or any of the priorities in the specified range.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Round_Robin_Within_Priorities, the dispatching rules for FIFO_Within_Priorities apply with the following additional rules:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task is added or moved to the tail of the ready queue for its base priority, it has an execution time budget equal to the quantum for that priority level. This will also occur when a blocked task becomes executable again.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task is preempted (by a higher priority task) and is added to the head of the ready queue for its priority level, it retains its remaining budget.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While a task is executing, its budget is decreased by the amount of execution time it uses. The accuracy of this accounting is the same as that for execution time clocks (see @RefSecNum{Execution Time}).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that this happens even when the task is executing at a higher, inherited priority, and even if that higher priority is dispatched by a different policy than round robin.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task has exhausted its budget and is without an inherited priority (and is not executing within a protected operation), it is moved to the tail of the ready queue for its priority level. This is a task dispatching point.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, it will be given a budget as described in the first bullet.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rules for FIFO_Within_Priority (to which these bullets are added) say that a task that has its base priority set to a Round Robin priority is moved to the tail of the ready queue for its new priority level, and then will be given a budget as described in the first bullet. That happens whether or not the task's original base priority was a Round Robin priority.]} @end{Ramification} @end{Itemize} @end{Runtime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as Round_Robin_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the Round_Robin_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall document the quantum values supported.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The quantum values supported for round robin dispatching.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall document the accuracy with which it detects the exhaustion of the budget of a task.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The accuracy of the detection of the exhaustion of the budget of a task for round robin dispatching.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Due to implementation constraints, the quantum value returned by Actual_Quantum might not be identical to that set with Set_Quantum.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A task that executes continuously with an inherited priority will not be subject to round robin dispatching.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy Round_Robin_Within_Priorities and package Dispatching.Round_Robin are new.]} @end{Extend95} @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledAddedSubClause{Version=[2],Name=[Earliest Deadline First Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The deadline of a task is an indication of the urgency of the task; it represents a point on an ideal physical time line. The deadline might affect how resources are allocated to the task.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[This clause defines a package for representing the deadline of a task and a dispatching policy that defines Earliest Deadline First (EDF) dispatching. A pragma is defined to assign an initial deadline to a task.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This pragma is the only way of assigning an initial deadline to a task so that its activation can be controlled by EDF scheduling. This is similar to the way pragma Priority is used to give an initial priority to a task.]} @end{Discussion} @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[To predict the behavior of a multi-tasking program it is necessary to control access to the processor which is preemptive, and shared objects which are usually non-preemptive and embodied in protected objects. Two common dispatching policies for the processor are fixed priority and EDF. The most effective control over shared objects is via preemption levels. With a pure priority scheme a single notion of priority is used for processor dispatching and preemption levels. With EDF and similar schemes priority is used for preemption levels (only), with another measure used for dispatching. T.P. Baker showed (@i<Real-Time Systems>, March 1991, vol. 3, num. 1, @i<Stack-Based Scheduling of Realtime Processes>) that for EDF a newly released task should only preempt the currently running task if it has an earlier deadline and a higher preemption level than any currently @lquotes@;locked@rquotes protected object. The rules of this clause implement this scheme including the case where the newly released task should execute before some existing tasks but not preempt the currently executing task.]} @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Relative_Deadline is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Relative_Deadline> (@SynI{relative_deadline_}@Syn2{expression});''} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The expected type for @SynI{relative_deadline_}@nt{expression} is Real_Time.Time_Span.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[A Relative_Deadline pragma is allowed only immediately within a @nt{task_definition} or the @nt{declarative_part} of a @nt{subprogram_body}. At most one such pragma shall appear within a given construct.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} EDF_Across_Priorities is a task dispatching policy.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Real_Time; @key{with} Ada.Task_Identification; @key{package} Ada.Dispatching.EDF @key{is}@ChildUnit{Parent=[Ada.Dispatching],Child=[EDF]} @key{subtype} @AdaSubtypeDefn{Name=[Deadline],Of=[Time]} @key{is} Ada.Real_Time.Time; @AdaObjDefn{Default_Deadline} : @key{constant} Deadline := Ada.Real_Time.Time_Last; @key{procedure} @AdaSubDefn{Set_Deadline} (D : @key{in} Deadline; T : @key{in} Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task); @key{procedure} @AdaSubDefn{Delay_Until_And_Set_Deadline} ( Delay_Until_Time : @key{in} Ada.Real_Time.Time; Deadline_Offset : @key{in} Ada.Real_Time.Time_Span); @key{function} @AdaSubDefn{Get_Deadline} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key{return} Deadline; @key{end} Ada.Dispatching.EDF;]} @end{Example} @end{StaticSem} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[If the EDF_Across_Priorities policy is specified for a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[If the EDF_Across_Priorities policy appears in a Priority_Specific_Dispatching pragma (see @RefSecNum{Task Dispatching Pragmas}) in a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike the other language-defined dispatching policies, the semantic description of EDF_Across_Priorities assumes Ceiling_Locking (and a ceiling priority) in order to make the mapping between deadlines and priorities work. Thus, we require both policies to be specified if EDF is used in the partition.]} @end{Reason} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[A Relative_Deadline pragma has no effect if it occurs in the @nt{declarative_part} of the @nt{subprogram_body} of a subprogram other than the main subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The initial absolute deadline of a task containing pragma Relative_Deadline is the value of Real_Time.Clock + @SynI{relative_deadline_}@nt{expression}, where the call of Real_Time.Clock is made between task creation and the start of its activation. If there is no Relative_Deadline pragma then the initial absolute deadline of a task is the value of Default_Deadline. @Redundant[The environment task is also given an initial deadline by this rule.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task is a normal task by @RefSecNum{Program Execution}, so of course this rule applies to it.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The procedure Set_Deadline changes the absolute deadline of the task to D. The function Get_Deadline returns the absolute deadline of the task.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The procedure Delay_Until_And_Set_Deadline delays the calling task until time Delay_Until_Time. When the task becomes runnable again it will have deadline Delay_Until_Time + Deadline_Offset.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[On a system with a single processor, the setting of the deadline of a task to the new value occurs immediately at the first point that is outside the execution of a protected action. If the task is currently on a ready queue it is removed and re-entered on to the ready queue determined by the rules defined below.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When EDF_Across_Priorities is specified for priority range @i<Low>..@i<High> all ready queues in this range are ordered by deadline. The task at the head of a queue is the one with the earliest deadline.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A task dispatching point occurs for the currently running task @i<T> to which policy EDF_Across_Priorities applies:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[when a change to the deadline of @i<T> occurs;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[there is a task on the ready queue for the active priority of @i<T> with a deadline earlier than the deadline of @i<T>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[there is a non-empty ready queue for that processor with a higher priority than the active priority of the running task.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In these cases, the currently running task is said to be preempted and is returned to the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a task @i<T> to which policy EDF_Across_Priorities applies, the base priority is not a source of priority inheritance; the active priority when first activated or while it is blocked is defined as the maximum of the following:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the lowest priority in the range specified as EDF_Across_Priorities that includes the base priority of @i<T>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the priorities, if any, currently inherited by @i<T>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the highest priority @i<P>, if any, less than the base priority of @i<T> such that one or more tasks are executing within a protected object with ceiling priority @i<P> and task @i<T> has an earlier deadline than all such tasks.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The active priority of @i<T> might be lower than its base priority.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When a task @i<T> is first activated or becomes unblocked, it is added to the ready queue corresponding to this active priority. Until it becomes blocked again, the active priority of @i<T> remains no less than this value; it will exceed this value only while it is inheriting a higher priority.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules ensure that a task executing in a protected object is preempted only by a task with a shorter deadline and a higher base priority. This matches the traditional preemption level description without the need to define a new kind of protected object locking.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a ready task takes effect and the new priority is in a range specified as EDF_Across_Priorities, the task is added to the ready queue corresponding to its new active priority, as determined above.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[For all the operations defined in Dispatching.EDF, Tasking_Error is raised if the task identified by T has terminated. Program_Error is raised if the value of T is Null_Task_Id.]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If EDF_Across_Priorities is specified for priority range @i<Low>..@i<High>, it is a bounded error to declare a protected object with ceiling priority @i<Low> or to assign the value @i<Low> to attribute 'Priority. In either case either Program_Error is raised or the ceiling of the protected object is assigned the value @i<Low>+1.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the subprograms of this package and the corresponding task object no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[On a multiprocessor, the implementation shall document any conditions that cause the completion of the setting of the deadline of a task to be delayed later than what is specified for a single processor.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any conditions that cause the completion of the setting of the deadline of a task to be delayed for a multiprocessor.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[If two adjacent priority ranges, @i<A>..@i<B> and @i<B>+1..@i<C> are specified to have policy EDF_Across_Priorities then this is not equivalent to this policy being specified for the single range, @i<A>..@i<C>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The above rules implement the preemption-level protocol (also called Stack Resource Policy protocol) for resource sharing under EDF dispatching. The preemption-level for a task is denoted by its base priority. The definition of a ceiling preemption-level for a protected object follows the existing rules for ceiling locking.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[An implementation may support additional dispatching policies by replacing absolute deadline with an alternative measure of urgency.]} @end{ImplNote} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy EDF_Across_Priorities and package Dispatching.EDF are new.]} @end{Extend95} @LabeledClause{Priority Ceiling Locking} @begin{Intro} @Redundant[This clause specifies the interactions between priority task scheduling and protected object ceilings. This interaction is based on the concept of the @i{ceiling priority} of a protected object.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Locking_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Locking_Policy)(@SynI{policy_}@Syn2{identifier});' @end{Syntax} @begin{Legality} The @SynI{policy_}@Syn2{identifier} shall either be Ceiling_Locking or an implementation-defined @Syn2{identifier}. @ImplDef{Implementation-defined @SynI{policy_}@Syn2{identifier}s allowed in a @nt{pragma} Locking_Policy.} @end{Legality} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Locking_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Locking_Policy)} A Locking_Policy pragma is a configuration pragma. @end{LinkTime} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0073],ARef=[AI95-00091-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @Defn{locking policy} @Redundant[A locking policy specifies the details of protected object locking. @Chg{Version=[2],New=[All protected objects have a priority. The locking policy specifies the meaning of the priority of a],Old=[These rules specify whether or not]} protected @Chg{Version=[2], New=[object],Old=[objects have priorities]}, and the relationships between these priorities and task priorities. In addition, the policy specifies the state of a task when it executes a protected action, and how its active priority is affected by the locking.] The @i{locking policy} is specified by a Locking_Policy pragma. For implementation-defined locking policies, the @Chg{Version=[2],New=[meaning of the priority of],Old=[effect of a Priority or Interrupt_Priority pragma on]} a protected object is implementation defined. If no Locking_Policy pragma @Chg{New=[applies to],Old=[appears in]} any of the program units comprising a partition, the locking policy for that partition, as well as the @Chg{Version=[2],New=[meaning of the priority of],Old=[effect of specifying either a Priority or Interrupt_Priority pragma for]} a protected object, are implementation defined. @Chg{Version=[2],New=[@Defn2{Term=[Priority],Sec=[of a protected object]}],Old=[]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The locking policy if no Locking_Policy pragma applies to any unit of a partition.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The @nt{expression} of a Priority or Interrupt_Priority pragma (see @RefSecNum{Task Priorities}) is evaluated as part of the creation of the corresponding protected object and converted to the subtype System.Any_Priority or System.Interrupt_Priority, respectively. The value of the expression is the initial priority of the corresponding protected object. If no Priority or Interrupt_Priority pragma applies to a protected object, the initial priority is specified by the locking policy. @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)}]} @Leading@;There is one predefined locking policy, Ceiling_Locking; this policy is defined as follows: @begin{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @Defn2{Term=[ceiling priority], Sec=(of a protected object)} Every protected object has a @i{ceiling priority}, which is determined by either a Priority or Interrupt_Priority pragma as defined in @RefSecNum{Task Priorities}@Chg{Version=[2],New=[, or by assignment to the Priority attribute as described in @RefSecNum{Dynamic Priorities for Protected Objects}],Old=[]}. The ceiling priority of a protected object (or ceiling, for short) is an upper bound on the active priority a task can have when it calls protected operations of that protected object. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} The @Chg{Version=[2],New=[initial ceiling priority of a],Old=[@nt{expression} of a Priority or Interrupt_Priority pragma is evaluated as part of the creation of the corresponding]} protected object @Chg{Version=[2],New=[is equal to the initial priority for that object.],Old=[and converted to the subtype System.Any_Priority or System.Interrupt_Priority, respectively. The value of the @nt{expression} is the ceiling priority of the corresponding protected object. @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} If an Interrupt_Handler or Attach_Handler pragma (see @RefSecNum{Protected Procedure Handlers}) appears in a @nt{protected_definition} without an Interrupt_Priority pragma, the @Chg{Version=[2],New=[initial],Old=[ceiling]} priority of protected objects of that type is implementation defined, but in the range of the subtype System.Interrupt_Priority. @ImplDef{Default ceiling priorities.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} If no @nt{pragma} Priority, Interrupt_Priority, Interrupt_Handler, or Attach_Handler is specified in the @nt{protected_definition}, then the @Chg{Version=[2],New=[initial],Old=[ceiling]} priority of the corresponding protected object is System.Priority'Last. While a task executes a protected action, it inherits the ceiling priority of the corresponding protected object. @IndexCheck{Ceiling_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} When a task calls a protected operation, a check is made that its active priority is not higher than the ceiling of the corresponding protected object; Program_Error is raised if this check fails. @end{Itemize} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Following any change of priority, it is a bounded error for the active priority of any task with a call queued on an entry of a protected object to be higher than the ceiling priority of the protected object. @PDefn2{Term=(bounded error),Sec=(cause)} In this case one of the following applies:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[at any time prior to executing the entry body Program_Error is raised in the calling task; @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object and then Program_Error is raised in the calling task; or @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object that was in effect when the entry call was queued.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]}@Comment{This note was moved along with the above rules} @ChgAdded{Version=[2],Text=[Note that the error is @lquotes@;blamed@rquotes@; on the task that did the entry call, not the task that changed the priority of the task or protected object. This seems to make sense for the case of changing the priority of a task blocked on a call, since if the Set_Priority had happened a little bit sooner, before the task queued a call, the entry-calling task would get the error. Similarly, there is no reason not to raise the priority of a task that is executing in an @nt{abortable_part}, so long as its priority is lowered before it gets to the end and needs to cancel the call. The priority might need to be lowered to allow it to remove the call from the entry queue, in order to avoid violating the ceiling. This seems relatively harmless, since there is an error, and the task is about to start raising an exception anyway.]} @end{Ramification} @end{Bounded} @begin{ImplPerm} The implementation is allowed to round all ceilings in a certain subrange of System.Priority or System.Interrupt_Priority up to the top of that subrange, uniformly. @begin{Discussion} For example, an implementation might use Priority'Last for all ceilings in Priority, and Interrupt_Priority'Last for all ceilings in Interrupt_Priority. This would be equivalent to having two ceiling priorities for protected objects, @lquotes@;nonpreemptible@rquotes@; and @lquotes@;noninterruptible@rquotes@;, and is an allowed behavior. Note that the implementation cannot choose a subrange that crosses the boundary between normal and interrupt priorities. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other locking policies, but need not support more than one @Chg{Version=[2],New=[locking],Old=[such]} policy per partition. @Redundant[Since implementations are allowed to place restrictions on code that runs at an interrupt-level active priority (see @RefSecNum{Protected Procedure Handlers} and @RefSecNum{The Task Dispatching Model}), the implementation may implement a language feature in terms of a protected object with an implementation-defined ceiling, but the ceiling shall be no less than Priority'Last.] @ImplDef{The ceiling of any protected object used internally by the implementation.} @begin{TheProof} This permission follows from the fact that the implementation can place restrictions on interrupt handlers and on any other code that runs at an interrupt-level active priority. The implementation might protect a storage pool with a protected object whose ceiling is Priority'Last, which would cause @nt{allocator}s to fail when evaluated at interrupt priority. Note that the ceiling of such an object has to be at least Priority'Last, since there is no permission for @nt{allocator}s to fail when evaluated at a non-interrupt priority. @end{TheProof} @end{ImplPerm} @begin{ImplAdvice} The implementation should use names that end with @lquotes@;_Locking@rquotes@; for implementation-defined locking policies. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Names that end with @lquotes@;_Locking@rquotes@; should be used for implementation-defined locking policies.]}]} @end{ImplAdvice} @begin{Notes} While a task executes in a protected action, it can be preempted only by tasks whose active priorities are higher than the ceiling priority of the protected object. If a protected object has a ceiling priority in the range of Interrupt_Priority, certain interrupts are blocked while protected actions of that object execute. In the extreme, if the ceiling is Interrupt_Priority'Last, all blockable interrupts are blocked during that time. The ceiling priority of a protected object has to be in the Interrupt_Priority range if one of its procedures is to be used as an interrupt handler (see @RefSecNum{Interrupt Support}). When specifying the ceiling of a protected object, one should choose a value that is at least as high as the highest active priority at which tasks can be executing when they call protected operations of that object. In determining this value the following factors, which can affect active priority, should be considered: the effect of Set_Priority, nested protected operations, entry calls, task activation, and other implementation-defined factors. Attaching a protected procedure whose ceiling is below the interrupt hardware priority to an interrupt causes the execution of the program to be erroneous (see @RefSecNum{Protected Procedure Handlers}). On a single processor implementation, the ceiling priority rules guarantee that there is no possibility of deadlock involving only protected subprograms (excluding the case where a protected operation calls another protected operation on the same protected object). @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} All protected objects now have a priority, which is the value of the Priority attribute of @RefSecNum{Dynamic Priorities for Protected Objects}. How this value is interpreted depends on the locking policy; for instance, the ceiling priority is derived from this value when the locking policy is Ceiling_Locking.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0073],ARef=[AI95-00091-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to reflect that pragma Locking_Policy cannot be inside of a program unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one locking policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The bounded error for the priority of a task being higher than the ceiling of an object it is currently in was moved here from @RefSecNum{Dynamic Priorities}, so that it applies no matter how the situation arises.]} @end{DiffWord95} @Comment{@RMNewPage Break here so printed Ada 95 RM looks better.} @LabeledClause{Entry Queuing Policies} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0074],ARef=[AI95-00068-01]} @Redundant[@Defn{queuing policy} This clause specifies a mechanism for a user to choose an entry @i{queuing policy}. It also defines @Chg{New=[two],Old=[one]} such polic@Chg{New=[ies],Old=[y]}. Other policies are implementation defined.] @ImplDef{Implementation-defined queuing policies.} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Queuing_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Queuing_Policy)(@SynI{policy_}@Syn2{identifier});' @end{Syntax} @begin{Legality} The @SynI{policy_}@Syn2{identifier} shall be either FIFO_Queuing, Priority_Queuing or an implementation-defined @Syn2{identifier}. @end{Legality} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Queuing_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Queuing_Policy)} A Queuing_Policy pragma is a configuration pragma. @end{LinkTime} @begin{RunTime} @Defn{queuing policy} @Redundant[A @i{queuing policy} governs the order in which tasks are queued for entry service, and the order in which different entry queues are considered for service.] The queuing policy is specified by a Queuing_Policy pragma. @begin{Ramification} The queuing policy includes entry queuing order, the choice among open alternatives of a @nt{selective_accept}, and the choice among queued entry calls of a protected object when more than one @nt{entry_barrier} @nt{condition} is True. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} Two queuing policies, FIFO_Queuing and Priority_Queuing, are language defined. If no Queuing_Policy pragma @Chg{Version=[2],New=[applies to],Old=[appears in]} any of the program units comprising the partition, the queuing policy for that partition is FIFO_Queuing. The rules for this policy are specified in @RefSecNum{Entry Calls} and @RefSecNum{Selective Accept}. @Leading@Keepnext@;The Priority_Queuing policy is defined as follows: @begin{itemize} @Defn{priority of an entry call} The calls to an entry @Redundant[(including a member of an entry family)] are queued in an order consistent with the priorities of the calls. The @i{priority of an entry call} is initialized from the active priority of the calling task at the time the call is made, but can change later. Within the same priority, the order is consistent with the calling (or requeuing, or priority setting) time (that is, a FIFO order). @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0075],ARef=[AI95-00205-01]} After a call is first queued, changes to the active priority of a task do not affect the priority of the call, unless the base priority of the task is set@Chg{New=[ while the task is blocked on an entry call],Old=[]}. When the base priority of a task is set (see @RefSecNum{Dynamic Priorities}), if the task is blocked on an entry call, and the call is queued, the priority of the call is updated to the new active priority of the calling task. This causes the call to be removed from and then reinserted in the queue at the new active priority. @begin{Reason} A task is blocked on an entry call if the entry call is simple, conditional, or timed. If the call came from the @nt{triggering_statement} of an @nt{asynchronous_select}, or a requeue thereof, then the task is not blocked on that call; such calls do not have their priority updated. Thus, there can exist many queued calls from a given task (caused by many nested ATC's), but a task can be blocked on only one call at a time. A previous version of Ada 9X required queue reordering in the @nt{asynchronous_select} case as well. If the call corresponds to a @lquotes@;synchronous@rquotes@; entry call, then the task is blocked while queued, and it makes good sense to move it up in the queue if its priority is raised. However, if the entry call is @lquotes@;asynchronous,@rquotes@; that is, it is due to an @nt{asynchronous_select} whose @nt{triggering_statement} is an entry call, then the task is not waiting for this entry call, so the placement of the entry call on the queue is irrelevant to the rate at which the task proceeds. Furthermore, when an entry is used for @nt{asynchronous_select}s, it is almost certain to be a @lquotes@;broadcast@rquotes@; entry or have only one caller at a time. For example, if the entry is used to notify tasks of a mode switch, then all tasks on the entry queue would be signaled when the mode changes. Similarly, if it is indicating some interrupting event such as a control-C, all tasks sensitive to the interrupt will want to be informed that the event occurred. Hence, the order on such a queue is essentially irrelevant. Given the above, it seems an unnecessary semantic and implementation complexity to specify that asynchronous queued calls are moved in response to dynamic priority changes. Furthermore, it is somewhat inconsistent, since the call was originally queued based on the active priority of the task, but dynamic priority changes are changing the base priority of the task, and only indirectly the active priority. We say explicitly that asynchronous queued calls are not affected by normal changes in active priority during the execution of an @nt{abortable_part}. Saying that, if a change in the base priority affects the active priority, then we do want the calls reordered, would be inconsistent. It would also require the implementation to maintain a readily accessible list of all queued calls which would not otherwise be necessary. Several rules were removed or simplified when we changed the rules so that calls due to @nt{asynchronous_select}s are never moved due to intervening changes in active priority, be they due to protected actions, some other priority inheritance, or changes in the base priority. @end{Reason} When more than one @nt{condition} of an @nt{entry_barrier} of a protected object becomes True, and more than one of the respective queues is nonempty, the call with the highest priority is selected. If more than one such call has the same priority, the call that is queued on the entry whose declaration is first in textual order in the @nt{protected_definition} is selected. For members of the same entry family, the one with the lower family index is selected. If the expiration time of two or more open @nt{delay_alternative}s is the same and no other @nt{accept_alternative}s are open, the @nt{sequence_of_statements} of the @nt{delay_alternative} that is first in textual order in the @nt{selective_accept} is executed. When more than one alternative of a @nt{selective_accept} is open and has queued calls, an alternative whose queue has the highest-priority call at its head is selected. If two or more open alternatives have equal-priority queued calls, then a call on the entry in the @nt{accept_alternative} that is first in textual order in the @nt{selective_accept} is selected. @end{itemize} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other queuing policies, but need not support more than one @Chg{Version=[2],New=[queuing],Old=[such]} policy per partition. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0116],ARef=[AI95-00069-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[This rule is really redundant, as @RefSecNum(Pragmas and Program Units) allows an implementation to limit the use of configuration pragmas to an empty environment. In that case, there would be no way to have multiple policies in a partition.@Chg{Version=[2],New=[], Old=[ In any case, the wording here really ought to be "...more than one queuing policy per partition.", since this part of the rule applies to all queuing policies, not just implementation-defined ones.]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[Implementations are allowed to defer the reordering of entry queues following a change of base priority of a task blocked on the entry call if it is not practical to reorder the queue immediately.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Priority change is immediate, but the effect of the change on entry queues can be deferred. That is necessary in order to implement priority changes on top of a non-Ada kernel.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The reordering should occur as soon as the blocked task can itself perform the reinsertion into the entry queue.]} @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} The implementation should use names that end with @lquotes@;_Queuing@rquotes@; for implementation-defined queuing policies. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Names that end with @lquotes@;_Queuing@rquotes@; should be used for implementation-defined queuing policies.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0074],ARef=[AI95-00068-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the number of queuing policies defined.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0075],ARef=[AI95-00205-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected so that a call of Set_Priority in an abortable part does not change the priority of the triggering entry call.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[Added a permission to defer queue reordering when the base priority of a task is changed. This is a counterpart to stronger requirements on the implementation of priority change.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one queuing policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Fixed wording to make clear that @nt{pragma} never appears inside of a unit; rather it @lquotes@;applies to@rquotes the unit.]} @end{DiffWord95} @LabeledClause{Dynamic Priorities} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause describes how the priority of an entity can be modified or queried at run time.]]} @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[This clause is turned into two subclauses. This clause introduction is new.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Dynamic Priorities for Tasks]} @begin{Intro} @Redundant[This clause describes how the base priority of a task can be modified or queried at run time.] @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[with] System; @key[with] Ada.Task_Identification; @RI{-- See @RefSecNum[The Package Task_Identification]} @key[package] Ada.Dynamic_Priorities @key[is]@ChildUnit{Parent=[Ada],Child=[Dynamic_Priorities]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Dynamic_Priorities);],Old=[]} @key[procedure] @AdaSubDefn{Set_Priority}(Priority : @key[in] System.Any_Priority; T : @key[in] Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task); @key[function] @AdaSubDefn{Get_Priority} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key[return] System.Any_Priority; @key[end] Ada.Dynamic_Priorities; @end{example} @end{StaticSem} @begin{RunTime} The procedure Set_Priority sets the base priority of the specified task to the specified Priority value. Set_Priority has no effect if the task is terminated. The function Get_Priority returns T's current base priority. @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Tasking_Error is raised if the task is terminated. @begin{Reason} There is no harm in setting the priority of a terminated task. A previous version of Ada 9X made this a run-time error. However, there is little difference between setting the priority of a terminated task, and setting the priority of a task that is about to terminate very soon; neither case should be an error. Furthermore, the run-time check is not necessarily feasible to implement on all systems, since priority changes might be deferred due to inter-processor communication overhead, so the error might not be detected until after Set_Priority has returned. However, we wish to allow implementations to avoid storing @lquotes@;extra@rquotes@; information about terminated tasks. Therefore, we make Get_Priority of a terminated task raise an exception; the implementation need not continue to store the priority of a task that has terminated. @end{Reason} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised by Set_Priority and Get_Priority if T is equal to Null_Task_Id. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00188-02]} @Chg{Version=[2],New=[On a system with a single processor, the setting of], Old=[Setting]} the @Chg{Version=[2],New=[],Old=[task's ]}base priority@Chg{Version=[2],New=[ of a task @i{T}],Old=[]} to the new value @Chg{Version=[2], New=[occurs immediately at the first point when @i{T} is outside the execution of],Old=[takes place as soon as is practical but not while the task is performing]} a protected action@Chg{Version=[2],New=[],Old=[. This setting occurs no later then the next abort completion point of the task T (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements})]}. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00188-02]} @Chg{Version=[2],New=[The priority change is immediate if the target task is on a delay queue or a ready queue outside of a protected action. However, consider when],Old=[When]} Set_Priority is called by a task T1 to set the priority of T2, if T2 is blocked, waiting on an entry call queued on a protected object, the entry queue needs to be reordered. Since T1 might have a priority that is higher than the ceiling of the protected object, T1 cannot, in general, do the reordering. One way to implement this is to wake T2 up and have T2 do the work. This is similar to the disentangling of queues that needs to happen when a high-priority task aborts a lower-priority task, which might have a call queued on a protected object with a low ceiling.@Chg{Version=[2],New=[ We have an @ImplPermName in @RefSecNum{Entry Queuing Policies} to allow this implementation. We could have required an immediate priority change if on a ready queue during a protected action, but that would have required extra checks for ceiling violations to meet @BoundedName requirements of @RefSecNum{Priority Ceiling Locking} and potentially could cause a protected action to be abandoned in the middle (by raising Program_Error). That seems bad.],Old=[]} @end{ImplNote} @begin{Reason} @Leading@;A previous version of Ada 9X made it a run-time error for a high-priority task to set the priority of a lower-priority task that has a queued call on a protected object with a low ceiling. This was changed because: @begin{Itemize} The check was not feasible to implement on all systems, since priority changes might be deferred due to inter-processor communication overhead. The calling task would continue to execute without finding out whether the operation succeeded or not. The run-time check would tend to cause intermittent system failures @em how is the caller supposed to know whether the other task happens to have a queued call at any given time? Consider for example an interrupt that needs to trigger a priority change in some task. The interrupt handler could not safely call Set_Priority without knowing exactly what the other task is doing, or without severely restricting the ceilings used in the system. If the interrupt handler wants to hand the job off to a third task whose job is to call Set_Priority, this won't help, because one would normally want the third task to have high priority. @end{Itemize} @end{Reason} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00327-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If a task is blocked on a protected entry call, and the call is queued, it is a bounded error to raise its base priority above the ceiling priority of the corresponding protected object. When an entry call is cancelled, it is a bounded error if the priority of the calling task is higher than the ceiling priority of the corresponding protected object. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} In either of these cases, either Program_Error is raised in the task that called the entry, or its priority is temporarily lowered, or both, or neither.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Note that the error is @lquotes@;blamed@rquotes@; on the task that did the entry call, not the task that called Set_Priority. This seems to make sense for the case of a task blocked on a call, since if the Set_Priority had happened a little bit sooner, before the task queued a call, the entry-calling task would get the error. In the other case, there is no reason not to raise the priority of a task that is executing in an @nt{abortable_part}, so long as its priority is lowered before it gets to the end and needs to cancel the call. The priority might need to be lowered to allow it to remove the call from the entry queue, in order to avoid violating the ceiling. This seems relatively harmless, since there is an error, and the task is about to start raising an exception anyway.]} @end{Ramification} @end{Bounded} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If any subprogram in this package is called with a parameter T that specifies a task object that no longer exists, the execution of the program is erroneous. @begin{Ramification} Note that this rule overrides the above rule saying that Program_Error is raised on Get_Priority of a terminated task. If the task object still exists, and the task is terminated, Get_Priority raises Program_Error. However, if the task object no longer exists, calling Get_Priority causes erroneous execution. @end{Ramification} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[On a multiprocessor, the implementation shall document any conditions that cause the completion of the setting of the priority of a task to be delayed later than what is specified for a single processor.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any conditions that cause the completion of the setting of the priority of a task to be delayed for a multiprocessor.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metric: @begin{Itemize} The execution time of a call to Set_Priority, for the nonpreempting case, in processor clock cycles. This is measured for a call that modifies the priority of a ready task that is not running (which cannot be the calling one), where the new base priority of the affected task is lower than the active priority of the calling task, and the affected task is not on any entry queue and is not executing a protected operation. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for Set_Priority.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} Setting a task's base priority affects task dispatching. First, it can change the task's active priority. Second, under the @Chg{Version=[2], New=[FIFO_Within_Priorities],Old=[standard task dispatching]} policy it always causes the task to move to the tail of the ready queue corresponding to its active priority, even if the new base priority is unchanged. Under the priority queuing policy, setting a task's base priority has an effect on a queued entry call if the task is blocked waiting for the call. That is, setting the base priority of a task causes the priority of a queued entry call from that task to be updated and the call to be removed and then reinserted in the entry queue at the new priority (see @RefSecNum{Entry Queuing Policies}), unless the call originated from the @nt{triggering_statement} of an @nt{asynchronous_select}. The effect of two or more Set_Priority calls executed in parallel on the same task is defined as executing these calls in some serial order. @begin{TheProof} This follows from the general reentrancy requirements stated near the beginning of @RefSec{Predefined Language Environment}. @end{TheProof} The rule for when Tasking_Error is raised for Set_Priority or Get_Priority is different from the rule for when Tasking_Error is raised on an entry call (see @RefSecNum{Entry Calls}). In particular, setting or querying the priority of a completed or an abnormal task is allowed, so long as the task is not yet terminated. Changing the priorities of a set of tasks can be performed by a series of calls to Set_Priority for each task separately. For this to work reliably, it should be done within a protected operation that has high enough ceiling priority to guarantee that the operation completes without being preempted by any of the affected tasks. @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Priority changes are now required to be done immediately so long as the target task is not on an entry queue.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Dynamic_Priorities is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[This Ada 95 clause was turned into a subclause. The paragraph numbers are the same as those for @RefSecNum{Dynamic Priorities} in Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[There is no @lquotes@;standard@rquotes policy anymore, so that phrase was replaced by the name of a specific policy in the notes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The bounded error for the priority of a task being higher than the ceiling of an object it is currently in was moved to @RefSecNum{Priority Ceiling Locking}, so that it applies no matter how the situation arises.]} @end{DiffWord95} @RMNewPage@Comment{For printed Ada 2005 RM} @LabeledAddedSubClause{Version=[2],Name=[Dynamic Priorities for Protected Objects]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[This clause specifies how the priority of a protected object can be modified or queried at run time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following attribute is defined for @PrefixType{a @nt{prefix} P that denotes a protected object}:]} @begin(Description) @ChgAttribute{Version=[2],Kind=[AddedNormal],ChginAnnex=[T], Leading=<F>, Prefix=<P>, AttrName=<Priority>, ARef=[AI95-00327-01], Text=[@Chg{Version=[2],New=[Denotes a non-aliased component of the protected object P. This component is of type System.Any_Priority and its value is the priority of P. P'Priority denotes a variable if and only if P denotes a variable. A reference to this attribute shall appear only within the body of P.],Old=[]}]} @EndPrefixType{} @end{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The initial value of this attribute is the initial value of the priority of the protected object@Redundant[, and can be changed by an assignment].]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[If the locking policy Ceiling_Locking (see @RefSecNum{Priority Ceiling Locking}) is in effect then the ceiling priority of a protected object @i<P> is set to the value of @i<P>'Priority at the end of each protected action of @i<P>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00445-01]} @ChgAdded{Version=[2],Text=[If the locking policy Ceiling_Locking is in effect, then for a protected object @i<P> with either an Attach_Handler or Interrupt_Handler pragma applying to one of its procedures, a check is made that the value to be assigned to @i<P>'Priority is in the range System.Interrupt_Priority. If the check fails, Program_Error is raised.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{Runtime} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The implementation shall document the following metric:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The difference in execution time of calls to the following procedures in protected object P:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<protected> P @key<is> @key<procedure> Do_Not_Set_Ceiling (Pr : System.Any_Priority); @key<procedure> Set_Ceiling (Pr : System.Any_Priority); @key<end> P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<protected body> P @key<is> @key<procedure> Do_Not_Set_Ceiling (Pr : System.Any_Priority) @key<is> @key<begin> @key<null>; @key<end>; @key<procedure> Set_Ceiling (Pr : System.Any_Priority) @key<is> @key<begin> P'Priority := Pr; @key<end>; @key<end> P;]} @end{Example} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for setting the priority of a protected object.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[Since P'Priority is a normal variable, the value following an assignment to the attribute immediately reflects the new value even though its impact on the ceiling priority of P is postponed until completion of the protected action in which it is executed.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01],ARef=[AI95-00445-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The ability to dynamically change and query the priority of a protected object is new.]} @end{Extend95} @RMNewPage@Comment{For printed RM Ada 2005 only} @LabeledClause{Preemptive Abort} @begin{Intro} @Redundant[This clause specifies requirements on the immediacy with which an aborted construct is completed.] @end{Intro} @begin{RunTime} On a system with a single processor, an aborted construct is completed immediately at the first point that is outside the execution of an abort-deferred operation. @end{RunTime} @begin{DocReq} On a multiprocessor, the implementation shall document any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[On a multiprocessor, any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[On a multiprocessor, any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metrics: @begin{Itemize} The execution time, in processor clock cycles, that it takes for an @nt{abort_statement} to cause the completion of the aborted task. This is measured in a situation where a task T2 preempts task T1 and aborts T1. T1 does not have any finalization code. T2 shall verify that T1 has terminated, by means of the Terminated attribute. On a multiprocessor, an upper bound in seconds, on the time that the completion of an aborted task can be delayed beyond the point that it is required for a single processor. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An upper bound on the execution time of an @nt{asynchronous_select}, in processor clock cycles. This is measured between a point immediately before a task T1 executes a protected operation Pr.Set that makes the @nt{condition} of an @nt{entry_barrier} Pr.Wait @Chg{Version=[2], New=[True],Old=[true]}, and the point where task T2 resumes execution immediately after an entry call to Pr.Wait in an @nt{asynchronous_select}. T1 preempts T2 while T2 is executing the abortable part, and then blocks itself so that T2 can execute. The execution time of T1 is measured separately, and subtracted. An upper bound on the execution time of an @nt{asynchronous_select}, in the case that no asynchronous transfer of control takes place. This is measured between a point immediately before a task executes the @nt{asynchronous_select} with a nonnull abortable part, and the point where the task continues execution immediately after it. The execution time of the abortable part is subtracted. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for aborts.]}]} @end{Metrics} @begin{ImplAdvice} Even though the @nt{abort_statement} is included in the list of potentially blocking operations (see @RefSecNum{Protected Subprograms and Protected Actions}), it is recommended that this statement be implemented in a way that never requires the task executing the @nt{abort_statement} to block. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The @nt{abort_statement} should not require the task executing the statement to block.]}]} On a multi-processor, the delay associated with aborting a task on another processor should be bounded; the implementation should use periodic polling, if necessary, to achieve this. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[On a multi-processor, the delay associated with aborting a task on another processor should be bounded.]}]} @end{ImplAdvice} @begin{Notes} Abortion does not change the active or base priority of the aborted task. Abortion cannot be more immediate than is allowed by the rules for deferral of abortion during finalization and in protected actions. @end{Notes} @LabeledClause{Tasking Restrictions} @begin{Intro} @Redundant[This clause defines restrictions that can be used with a pragma Restrictions (see @RefSecNum{Pragma Restrictions}) to facilitate the construction of highly efficient tasking run-time systems.] @end{Intro} @begin{StaticSem} @Leading@;The following @SynI{restriction_}@nt{identifier}s are language defined: @begin{Description} @Defn2{Term=[Restrictions],Sec=(No_Task_Hierarchy)}No_Task_Hierarchy @\All (nonenvironment) tasks depend directly on the environment task of the partition. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00360-01]} @Defn2{Term=[Restrictions],Sec=(No_Nested_Finalization)}No_Nested_Finalization @\Objects @Chg{Version=[2],New=[of a type that needs finalization (see @RefSecNum{User-Defined Assignment and Finalization})],Old=[with controlled@Chg{New=[, protected, or task],Old=[]} parts]} and access types that designate @Chg{Version=[2],New=[a type that needs finalization],Old=[such objects@Chg{New=[,],Old=[]}]} shall be declared only at library level. @begin{Ramification} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgNote{This is no longer true.} @ChgDeleted{Version=[1],Text=[Note that protected types with entries and interrupt-handling protected types have nontrivial finalization actions. However, this restriction does not restrict those things.]} @end{Ramification} @Defn2{Term=[Restrictions],Sec=(No_Abort_Statements)}No_Abort_Statements @\There are no @nt{abort_statement}s, and there are no calls on Task_Identification.Abort_Task. @Defn2{Term=[Restrictions],Sec=(No_Terminate_Alternatives)}No_Terminate_Alternatives @\There are no @nt{selective_accept}s with @nt{terminate_alternative}s. @Defn2{Term=[Restrictions],Sec=(No_Task_Allocators)}No_Task_Allocators @\There are no @nt{allocator}s for task types or types containing task subcomponents. @Defn2{Term=[Restrictions],Sec=(No_Implicit_Heap_Allocations)}No_Implicit_Heap_Allocations @\There are no operations that implicitly require heap storage allocation to be performed by the implementation. The operations that implicitly require heap storage allocation are implementation defined. @ImplDef{Any operations that implicitly require heap storage allocation.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} No_Dynamic_Priorities @\There are no semantic dependences on the package Dynamic_Priorities@Chg{Version=[2],New=[, and no occurrences of the attribute Priority],Old=[]}. @Defn2{Term=[Restrictions],Sec=(No_Dynamic_Priorities)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @Chg{Version=[2],New=[@Defn2{Term=[Restrictions],Sec=(No_Dynamic_Attachment)}No_Dynamic_Attachment], Old=[@Defn2{Term=[Restrictions],Sec=(No_Asynchronous_Control)}No_Asynchronous_Control]} @\There @Chg{Version=[2],New=[is no call to any of the operations defined in package Interrupts (Is_Reserved, Is_Attached, Current_Handler, Attach_Handler, Exchange_Handler, Detach_Handler, and Reference).], Old=[are no semantic dependences on the package Asynchronous_Task_Control.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Local_Protected_Objects)}No_Local_Protected_Objects @\Protected objects shall be declared only at library level.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Local_Timing_Events)}No_Local_Timing_Events @\Timing_Events shall be declared only at library level.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Protected_Type_Allocators)}No_Protected_Type_Allocators @\There are no @nt{allocator}s for protected types or types containing protected type subcomponents.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Relative_Delay)}No_Relative_Delay @\There are no @nt{delay_relative_statement}s.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Requeue_Statements)}No_Requeue_Statements @\There are no @nt{requeue_statement}s.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Select_Statements)}No_Select_Statements @\There are no @nt{select_statement}s.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Specific_Termination_Handlers)}No_Specific_Termination_Handlers @\There are no calls to the Set_Specific_Handler and Specific_Handler subprograms in Task_Termination.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(Simple_Barriers)}Simple_Barriers @\The Boolean expression in an entry barrier shall be either a static Boolean expression or a Boolean component of the enclosing protected object.]} @end{Description} @Leading@;The following @SynI{restriction_parameter_}@nt{identifier}s are language defined: @begin{Description} @Defn2{Term=[Restrictions],Sec=(Max_Select_Alternatives)}Max_Select_Alternatives @\Specifies the maximum number of alternatives in a @nt{selective_accept}. @Defn2{Term=[Restrictions],Sec=(Max_Task_Entries)}Max_Task_Entries @\Specifies the maximum number of entries per task. The bounds of every entry family of a task unit shall be static, or shall be defined by a discriminant of a subtype whose corresponding bound is static. @Redundant[A value of zero indicates that no rendezvous are possible.] Max_Protected_Entries @\Specifies the maximum number of entries per protected type. The bounds of every entry family of a protected unit shall be static, or shall be defined by a discriminant of a subtype whose corresponding bound is static. @Defn2{Term=[Restrictions],Sec=(Max_Protected_Entries)} @end{Description} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0076],ARef=[AI95-00067-01]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_}@nt{identifier} is language defined:]}@Comment{Use ChgAdded so we get conditional Leading.}@Chg{Version=[1],New=[],Old=[If the following restrictions are violated, the behavior is implementation defined. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If an implementation chooses to detect such a violation, Storage_Error should be raised.]} @begin{Description} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions],Sec=(No_Task_Termination)}No_Task_Termination @\All tasks are non-terminating. It is implementation-defined what happens if a task attempts to terminate. If there is a fall-back handler (see C.7.3) set for the partition it should be called when the first task attempts to terminate.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[When restriction No_Task_Termination applies to a partition, what happens when a task terminates.]}]} @end{Description} @Leading@;The following @SynI{restriction_parameter_}@nt{identifier}s are language defined: @begin{Description} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[Restrictions],Sec=(Max_Storage_At_Blocking)}Max_Storage_At_Blocking @\Specifies the maximum portion @redundant[(in storage elements)] of a task's Storage_Size that can be retained by a blocked task@Chg{New=[. If an implementation chooses to detect a violation of this restriction, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Storage_At_Blocking is violated.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[Restrictions],Sec=(Max_Asynchronous_Select_Nesting)}Max_Asynchronous_Select_Nesting @\Specifies the maximum dynamic nesting level of @nt{asynchronous_select}s. A value of zero prevents the use of any @nt{asynchronous_@!select}@Chg{New=[ and, if a program contains an @nt{asynchronous_@!select}, it is illegal. @ChgNote{Part of the previous rule is redundant, but it is a different part [all of it for Old; from "prevents" to "and," for New] for each. So we omit it.} If an implementation chooses to detect a violation of this restriction for values other than zero, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Asynchronous_Select_Nesting is violated.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[Restrictions],Sec=(Max_Tasks)}Max_Tasks @\Specifies the maximum number of task creations that may be executed over the lifetime of a partition, not counting the creation of the environment task@Chg{New=[. A value of zero prevents any task creation and, if a program contains a task creation, it is illegal. If an implementation chooses to detect a violation of this restriction, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @begin{Ramification} Note that this is not a limit on the number of tasks active at a given time; it is a limit on the total number of task creations that occur. @end{Ramification} @begin{ImplNote} We envision an implementation approach that places TCBs or pointers to them in a fixed-size table, and never reuses table elements. @end{ImplNote} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Tasks is violated.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(Max_Entry_Queue_Length)}Max_Entry_Queue_Length @\Max_Entry_Queue_Length defines the maximum number of calls that are queued on an entry. Violation of this restriction results in the raising of Program_Error at the point of the call or requeue.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{Description} It is implementation defined whether the use of pragma Restrictions results in a reduction in executable program size, storage requirements, or execution time. If possible, the implementation should provide quantitative descriptions of such effects for each restriction. @ChgImplDef{Version=[2],Kind=[Revised],Text=[@Chg{Version=[2], New=[Whether the use of],Old=[Implementation-defined aspects of]} pragma Restrictions@Chg{Version=[2],New=[ results in a reduction in program code or data size or execution time],Old=[]}.]} @end{RunTime} @begin{ImplAdvice} When feasible, the implementation should take advantage of the specified restrictions to produce a more efficient implementation. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When feasible, specified restrictions should be used to produce a more efficient implementation.]}]} @end{ImplAdvice} @begin{Notes} The above Storage_Checks can be suppressed with pragma Suppress. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The No_Nested_Finalization is now defined in terms of types that need finalization. These types include a variety of language-defined types that @i<might> be implemented with a controlled type. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and one of these language-defined types does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as other Ada compilers may have had a controlled part, and thus would be illegal under the restriction.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Restrictions No_Dynamic_Attachment, No_Local_Protected_Objects, No_Protected_Type_Allocators, No_Local_Timing_Events, No_Relative_Delay, No_Requeue_Statement, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Termination, Max_Entry_Queue_Length, and Simple_Barriers are newly added to Ada.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that No_Nested_Finalization covered task and protected parts as well.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0076],ARef=[AI95-00067-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed the description of Max_Tasks and Max_Asynchronous_Select_Nested to eliminate conflicts with the High Integrity Annex (see @RefSecNum{High Integrity Restrictions}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[Added using of the new Priority attribute to the restriction No_Dynamic_Priorities.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Restriction No_Asynchronous_Control is now obsolescent.]} @end{DiffWord95} @LabeledClause{Monotonic Time} @begin{Intro} @Redundant[This clause specifies a high-resolution, monotonic clock package.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{example} @key[package] Ada.Real_Time @key[is]@ChildUnit{Parent=[Ada],Child=[Real_Time]} @key[type] @AdaTypeDefn{Time} @key[is] @key[private]; @AdaObjDefn{Time_First} : @key[constant] Time; @AdaObjDefn{Time_Last} : @key[constant] Time; @AdaObjDefn{Time_Unit} : @key[constant] := @RI{implementation-defined-real-number}; @key[type] @AdaTypeDefn{Time_Span} @key[is] @key[private]; @AdaObjDefn{Time_Span_First} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Last} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Zero} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Unit} : @key[constant] Time_Span; @AdaObjDefn{Tick} : @key[constant] Time_Span; @key[function] @AdaSubDefn{Clock} @key[return] Time; @key[function] "+" (Left : Time; Right : Time_Span) @key[return] Time; @key[function] "+" (Left : Time_Span; Right : Time) @key[return] Time; @key[function] "-" (Left : Time; Right : Time_Span) @key[return] Time; @key[function] "-" (Left : Time; Right : Time) @key[return] Time_Span; @key[function] "<" (Left, Right : Time) @key[return] Boolean; @key[function] "<="(Left, Right : Time) @key[return] Boolean; @key[function] ">" (Left, Right : Time) @key[return] Boolean; @key[function] ">="(Left, Right : Time) @key[return] Boolean; @key[function] "+" (Left, Right : Time_Span) @key[return] Time_Span; @key[function] "-" (Left, Right : Time_Span) @key[return] Time_Span; @key[function] "-" (Right : Time_Span) @key[return] Time_Span; @key[function] "*" (Left : Time_Span; Right : Integer) @key{return} Time_Span; @key[function] "*" (Left : Integer; Right : Time_Span) @key{return} Time_Span; @key[function] "/" (Left, Right : Time_Span) @key[return] Integer; @key[function] "/" (Left : Time_Span; Right : Integer) @key[return] Time_Span; @key[function] "@key[abs]"(Right : Time_Span) @key[return] Time_Span; @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[function] "<" (Left, Right : Time_Span) @key[return] Boolean; @key[function] "<="(Left, Right : Time_Span) @key[return] Boolean; @key[function] ">" (Left, Right : Time_Span) @key[return] Boolean; @key[function] ">="(Left, Right : Time_Span) @key[return] Boolean; @key[function] @AdaSubDefn{To_Duration} (TS : Time_Span) @key[return] Duration; @key[function] @AdaSubDefn{To_Time_Span} (D : Duration) @key[return] Time_Span; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00386-01]} @key[function] @AdaSubDefn{Nanoseconds} (NS : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Microseconds} (US : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Milliseconds} (MS : Integer) @key{return} Time_Span;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Seconds} (S : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Minutes} (M : Integer) @key{return} Time_Span;],Old=[]} @key[type] @AdaTypeDefn{Seconds_Count} @key[is] @key[range] @RI{implementation-defined}; @key{procedure} @AdaSubDefn{Split}(T : @key{in} Time; SC : @key{out} Seconds_Count; TS : @key{out} Time_Span); @key{function} @AdaSubDefn{Time_Of}(SC : Seconds_Count; TS : Time_Span) @key{return} Time; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Real_Time; @end{example} @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of package Real_Time.]}]} @Defn{real time} In this Annex, @i{real time} is defined to be the physical time as observed in the external environment. The type Time is a @i{time type} as defined by @RefSecNum{Delay Statements, Duration, and Time}; @Redundant[values of this type may be used in a @nt{delay_until_statement}.] Values of this type represent segments of an ideal time line. The set of values of the type Time corresponds one-to-one with an implementation-defined range of mathematical integers. @begin{Discussion} Informally, real time is defined to be the International Atomic Time (TAI) which is monotonic and nondecreasing. We use it here for the purpose of discussing rate of change and monotonic behavior only. It does not imply anything about the absolute value of Real_Time.Clock, or about Real_Time.Time being synchronized with TAI. It is also used for real time in the metrics, for comparison purposes. @end{Discussion} @begin{ImplNote} The specification of TAI as @lquotes@;real time@rquotes@; does not preclude the use of a simulated TAI clock for simulated execution environments. @end{ImplNote} @Defn{epoch} @PDefn{unspecified} The Time value I represents the half-open real time interval that starts with E+I*Time_Unit and is limited by E+(I+1)*Time_Unit, where Time_Unit is an implementation-defined real number and E is an unspecified origin point, the @i{epoch}, that is the same for all values of the type Time. It is not specified by the language whether the time values are synchronized with any standard time reference. @Redundant[For example, E can correspond to the time of system initialization or it can correspond to the epoch of some time standard.] @begin{Discussion} E itself does not have to be a proper time value. This half-open interval I consists of all real numbers R such that E+I*Time_Unit <= R < E+(I+1)*Time_Unit. @end{Discussion} Values of the type Time_Span represent length of real time duration. The set of values of this type corresponds one-to-one with an implementation-defined range of mathematical integers. The Time_Span value corresponding to the integer I represents the real-time duration I*Time_Unit. @begin{Reason} The purpose of this type is similar to Standard.Duration; the idea is to have a type with a higher resolution. @end{Reason} @begin{Discussion} We looked at many possible names for this type: Real_Time.Duration, Fine_Duration, Interval, Time_Interval_Length, Time_Measure, and more. Each of these names had some problems, and we've finally settled for Time_Span. @end{Discussion} Time_First and Time_Last are the smallest and largest values of the Time type, respectively. Similarly, Time_Span_First and Time_Span_Last are the smallest and largest values of the Time_Span type, respectively. A value of type Seconds_Count represents an elapsed time, measured in seconds, since the epoch. @end{StaticSem} @begin{RunTime} Time_Unit is the smallest amount of real time representable by the Time type; it is expressed in seconds. Time_Span_Unit is the difference between two successive values of the Time type. It is also the smallest positive value of type Time_Span. Time_Unit and Time_Span_Unit represent the same real time duration. @Defn{clock tick} A @i{clock tick} is a real time interval during which the clock value (as observed by calling the Clock function) remains constant. Tick is the average length of such intervals. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00432-01]} The function To_Duration converts the value TS to a value of type Duration. Similarly, the function To_Time_Span converts the value D to a value of type Time_Span. For @Chg{Version=[2],New=[To_Duration], Old=[both operations]}, the result is rounded to the nearest @Chg{Version=[2],New=[value of type Duration], Old=[exactly representable value]} (away from zero if exactly halfway between two @Chg{Version=[2],New=[], Old=[exactly representable ]}values).@Chg{Version=[2],New=[ If the result is outside the range of Duration, Constraint_Error is raised. For To_Time_Span, the value of D is first rounded to the nearest integral multiple of Time_Unit, away from zero if exactly halfway between two multiples. If the rounded value is outside the range of Time_Span, Constraint_Error is raised. Otherwise, the value is converted to the type Time_Span.],Old=[]} To_Duration(Time_Span_Zero) returns 0.0, and To_Time_Span(0.0) returns Time_Span_Zero. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00386-01],ARef=[AI95-00432-01]} The functions Nanoseconds, Microseconds, @Chg{Version=[2],New=[], Old=[and ]}Milliseconds@Chg{Version=[2],New=[, Seconds, and Minutes],Old=[]} convert the input parameter to a value of the type Time_Span. NS, US,@Chg{Version=[2],New=[],Old=[ and]} MS@Chg{Version=[2],New=[, S, and M],Old=[]} are interpreted as a number of nanoseconds, microseconds,@Chg{Version=[2],New=[],Old=[ and]} milliseconds@Chg{Version=[2],New=[, seconds, and minutes],Old=[]} respectively.@Chg{Version=[2],New=[ The input parameter is first converted to seconds and rounded to the nearest integral multiple of Time_Unit, ], Old=[The result is rounded to the nearest exactly representable value (]}away from zero if exactly halfway between two @Chg{Version=[2],New=[multiples. If the rounded value is outside the range of Time_Span, Constraint_Error is raised. Otherwise, the rounded value is converted to the type Time_Span], Old=[exactly representable values)]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00432-01]} @ChgDeleted{Version=[2],Text=[The above does not imply that the Time_Span type will have to accommodate Integer'Last of milliseconds; Constraint_Error is allowed to be raised.]} @end{Discussion} The effects of the operators on Time and Time_Span are as for the operators defined for integer types. @begin{ImplNote} Though time values are modeled by integers, the types Time and Time_Span need not be implemented as integers. @end{ImplNote} The function Clock returns the amount of time since the epoch. The effects of the Split and Time_Of operations are defined as follows, treating values of type Time, Time_Span, and Seconds_Count as mathematical integers. The effect of Split(T,SC,TS) is to set SC and TS to values such that T*Time_Unit = SC*1.0 + TS*Time_Unit, and 0.0 <= TS*Time_Unit < 1.0. The value returned by Time_Of(SC,TS) is the value T such that T*Time_Unit = SC*1.0 + TS*Time_Unit. @end{RunTime} @begin{ImplReq} The range of Time values shall be sufficient to uniquely represent the range of real times from program start-up to 50 years later. Tick shall be no greater than 1 millisecond. Time_Unit shall be less than or equal to 20 microseconds. @begin{ImplNote} The required range and accuracy of Time are such that 32-bits worth of seconds and 32-bits worth of ticks in a second could be used as the representation. @end{ImplNote} Time_Span_First shall be no greater than @en@;3600 seconds, and Time_Span_Last shall be no less than 3600 seconds. @begin{Reason} This is equivalent to @PorM one hour and there is still room for a two-microsecond resolution. @end{Reason} @Defn{clock jump} A @i{clock jump} is the difference between two successive distinct values of the clock (as observed by calling the Clock function). There shall be no backward clock jumps. @end{ImplReq} @begin{DocReq} The implementation shall document the values of Time_First, Time_Last, Time_Span_@!First, Time_Span_@!Last, Time_Span_@!Unit, and Tick. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values of Time_First, Time_Last, Time_Span_@!First, Time_Span_@!Last, Time_Span_@!Unit, and Tick for package Real_Time.]}]} The implementation shall document the properties of the underlying time base used for the clock and for type Time, such as the range of values supported and any relevant aspects of the underlying hardware or operating system facilities used. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The properties of the underlying time base used in package Real_Time.]}]} @begin{Discussion} If there is an underlying operating system, this might include information about which system call is used to implement the clock. Otherwise, it might include information about which hardware clock is used. @end{Discussion} The implementation shall document whether or not there is any synchronization with external time references, and if such synchronization exists, the sources of synchronization information, the frequency of synchronization, and the synchronization method applied. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any synchronization of package Real_Time with external time references.]}]} @ChgRef{Version=[1],Kind=[Revised]} The implementation shall document any aspects of the @Chg{New=[], Old=[the]} @chgnote{Correct typo as noted at Potsdam ARG meeting} external environment that could interfere with the clock behavior as defined in this clause. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any aspects of the external environment that could interfere with package Real_Time.]}]} @begin{Discussion} For example, the implementation is allowed to rely on the time services of an underlying operating system, and this operating system clock can implement time zones or allow the clock to be reset by an operator. This dependence has to be documented. @end{Discussion} @end{DocReq} @begin{Metrics} For the purpose of the metrics defined in this clause, real time is defined to be the International Atomic Time (TAI). @Leading@;The implementation shall document the following metrics: @begin{Itemize} An upper bound on the real-time duration of a clock tick. This is a value D such that if t1 and t2 are any real times such that t1 < t2 and Clock@-{t1} = Clock@-{t2} then t2 @en@; t1 <= D. An upper bound on the size of a clock jump. @Defn{drift rate} An upper bound on the @i{drift rate} of Clock with respect to real time. This is a real number D such that @begin{display} E*(1@en@;D) <= (Clock@-{t+E} @en@; Clock@-{t}) <= E*(1+D) provided that: Clock@-{t} + E*(1+D) <= Time_Last. @end{display} where Clock@-{t} is the value of Clock at time t, and E is a real time duration not less than 24 hours. The value of E used for this metric shall be reported. @begin{Reason} This metric is intended to provide a measurement of the long term (cumulative) deviation; therefore, 24 hours is the lower bound on the measurement period. On some implementations, this is also the maximum period, since the language does not require that the range of the type Duration be more than 24 hours. On those implementations that support longer-range Duration, longer measurements should be performed. @end{Reason} An upper bound on the execution time of a call to the Clock function, in processor clock cycles. Upper bounds on the execution times of the operators of the types Time and Time_Span, in processor clock cycles. @begin{ImplNote} A fast implementation of the Clock function involves repeated reading until you get the same value twice. It is highly improbable that more than three reads will be necessary. Arithmetic on time values should not be significantly slower than 64-bit arithmetic in the underlying machine instruction set. @end{ImplNote} @end{Itemize} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The metrics for package Real_Time.]}]} @end{Metrics} @begin{ImplPerm} Implementations targeted to machines with word size smaller than 32 bits need not support the full range and granularity of the Time and Time_Span types. @begin{Discussion} These requirements are based on machines with a word size of 32 bits. Since the range and granularity are implementation defined, the supported values need to be documented. @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} When appropriate, implementations should provide configuration mechanisms to change the value of Tick. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[When appropriate, mechanisms to change the value of Tick should be provided.]}]} @begin{Reason} This is often needed when the compilation system was originally targeted to a particular processor with a particular interval timer, but the customer uses the same processor with a different interval timer. @end{Reason} @begin{Discussion} Tick is a deferred constant and not a named number specifically for this purpose. @end{Discussion} @begin{ImplNote} This can be achieved either by pre-run-time configuration tools, or by having Tick be initialized (in the package private part) by a function call residing in a board specific module. @end{ImplNote} It is recommended that Calendar.Clock and Real_Time.Clock be implemented as transformations of the same time base. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Calendar.Clock and Real_Time.Clock should be transformations of the same time base.]}]} It is recommended that the @lquotes@;best@rquotes@; time base which exists in the underlying system be available to the application through Clock. @lquotes@;Best@rquotes@; may mean highest accuracy or largest range. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The @lquotes@;best@rquotes@; time base which exists in the underlying system should be available to the application through Real_Time.Clock.]}]} @end{ImplAdvice} @begin{Notes} The rules in this clause do not imply that the implementation can protect the user from operator or installation errors which could result in the clock being set incorrectly. Time_Unit is the granularity of the Time type. In contrast, Tick represents the granularity of Real_Time.Clock. There is no requirement that these be the same. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00386-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Functions Seconds and Minutes are newly added to Real_Time. If Real_Time is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Seconds or Minutes is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00432-01]} @ChgAdded{Version=[2],Text=[Added wording explaining how and when many of these functions can raise Constraint_Error. While there always was an intent to raise Constraint_Error if the values did not fit, there never was any wording to that effect, and since Time_Span was a private type, the normal numeric type rules do not apply to it.]} @end{DiffWord95} @LabeledClause{Delay Accuracy} @begin{Intro} @Redundant[This clause specifies performance requirements for the @nt{delay_statement}. The rules apply both to @nt{delay_@!relative_@!statement} and to @nt{delay_@!until_@!statement}. Similarly, they apply equally to a simple @nt{delay_@!statement} and to one which appears in a @nt{delay_@!alternative}.] @end{Intro} @begin{RunTime} @Leading@;The effect of the @nt{delay_statement} for Real_Time.Time is defined in terms of Real_Time.Clock: @begin{itemize} If C@-{1} is a value of Clock read before a task executes a @nt{delay_relative_statement} with duration D, and C@-{2} is a value of Clock read after the task resumes execution following that @nt{delay_statement}, then C@-{2} @en@; C@-{1} >= D. If C is a value of Clock read after a task resumes execution following a @nt{delay_until_statement} with Real_Time.Time value T, then C >= T. @end{itemize} @PDefn2{Term=[potentially blocking operation],Sec=(delay_statement)} @PDefn2{Term=[blocking, potentially],Sec=(delay_statement)} A simple @nt{delay_statement} with a negative or zero value for the expiration time does not cause the calling task to be blocked; it is nevertheless a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @ChgRef{Version=[2],Kind=[Revised]} When a @nt{delay_statement} appears in a @nt{delay_alternative} of a @nt{timed_entry_call} the selection of the entry call is attempted, regardless of the specified expiration time. When a @nt{delay_statement} appears in a @Chg{Version=[2],New=[@nt{select_alternative}],Old=[@ntf{selective_accept_alternative}]}, and a call is queued on one of the open entries, the selection of that entry call proceeds, regardless of the value of the delay expression. @begin{Ramification} The effect of these requirements is that one has to always attempt a rendezvous, regardless of the value of the delay expression. This can be tested by issuing a @nt{timed_entry_call} with an expiration time of zero, to an open entry. @end{Ramification} @end{RunTime} @begin{DocReq} The implementation shall document the minimum value of the delay expression of a @nt{delay_relative_statement} that causes the task to actually be blocked. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The minimum value of the delay expression of a @nt{delay_relative_statement} that causes a task to actually be blocked.]}]} The implementation shall document the minimum difference between the value of the delay expression of a @nt{delay_until_statement} and the value of Real_Time.Clock, that causes the task to actually be blocked. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of @nt{delay_statement}s.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The minimum difference between the value of the delay expression of a @nt{delay_until_statement} and the value of Real_Time.Clock, that causes the task to actually be blocked.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metrics: @begin{Itemize} An upper bound on the execution time, in processor clock cycles, of a @nt{delay_relative_statement} whose requested value of the delay expression is less than or equal to zero. An upper bound on the execution time, in processor clock cycles, of a @nt{delay_until_statement} whose requested value of the delay expression is less than or equal to the value of Real_Time.Clock at the time of executing the statement. Similarly, for Calendar.Clock. @Defn{lateness} @Defn{actual duration} An upper bound on the @i{lateness} of a @nt{delay_relative_statement}, for a positive value of the delay expression, in a situation where the task has sufficient priority to preempt the processor as soon as it becomes ready, and does not need to wait for any other execution resources. The upper bound is expressed as a function of the value of the delay expression. The lateness is obtained by subtracting the value of the delay expression from the @i{actual duration}. The actual duration is measured from a point immediately before a task executes the @nt{delay_statement} to a point immediately after the task resumes execution following this statement. An upper bound on the lateness of a @nt{delay_until_statement}, in a situation where the value of the requested expiration time is after the time the task begins executing the statement, the task has sufficient priority to preempt the processor as soon as it becomes ready, and it does not need to wait for any other execution resources. The upper bound is expressed as a function of the difference between the requested expiration time and the clock value at the time the statement begins execution. The lateness of a @nt{delay_until_statement} is obtained by subtracting the requested expiration time from the real time that the task resumes execution following this statement. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for delay statements.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00355-01]} @ChgDeleted{Version=[2],Text=[The execution time of a @nt{delay_statement} that does not cause the task to be blocked (e.g. @lquotes@;@key[delay] 0.0;@rquotes@; ) is of interest in situations where delays are used to achieve voluntary round-robin task dispatching among equal-priority tasks.]} @end{Notes} @begin{DiffWord83} The rules regarding a @nt{timed_entry_call} with a very small positive Duration value, have been tightened to always require the check whether the rendezvous is immediately possible. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The note about @lquotes@;voluntary round-robin@rquote, while still true, has been deleted as potentially confusing as it is describing a different kind of round-robin than is defined by the round-robin dispatching policy.]} @end{DiffWord95} @LabeledClause{Synchronous Task Control} @begin{Intro} @Redundant[This clause describes a language-defined private semaphore (suspension object), which can be used for @i{two-stage suspend} operations and as a simple building block for implementing higher-level queues.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key{package} Ada.Synchronous_Task_Control @key{is}@ChildUnit{Parent=[Ada],Child=[Synchronous_Task_Control]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Synchronous_Task_Control);],Old=[]} @key{type} @AdaTypeDefn{Suspension_Object} @key{is} @key{limited} @key{private}; @key{procedure} @AdaSubDefn{Set_True}(S : @key{in} @key{out} Suspension_Object); @key{procedure} @AdaSubDefn{Set_False}(S : @key{in} @key{out} Suspension_Object); @key{function} @AdaSubDefn{Current_State}(S : Suspension_Object) @key{return} Boolean; @key{procedure} @AdaSubDefn{Suspend_Until_True}(S : @key{in} @key{out} Suspension_Object); @key{private} ... -- @RI{not specified by the language} @key{end} Ada.Synchronous_Task_Control; @end{example} The type Suspension_Object is a by-reference type.@begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]}@ChgNote{This is a real term now, let's get it right} The implementation can ensure this by, for example, making the full view @Chg{Version=[2],New=[an explicitly],Old=[a]} limited record type.@end{implnote} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An object of the type Suspension_Object has two visible states: @Chg{Version=[2],New=[True],Old=[true]} and @Chg{Version=[2],New=[False],Old=[false]}. Upon initialization, its value is set to @Chg{Version=[2],New=[False],Old=[false]}. @begin{Discussion} This object is assumed to be private to the declaring task, i.e. only that task will call Suspend_Until_True on this object, and the count of callers is at most one. Other tasks can, of course, change and query the state of this object. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The operations Set_True and Set_False are atomic with respect to each other and with respect to Suspend_Until_True; they set the state to @Chg{Version=[2],New=[True],Old=[true]} and @Chg{Version=[2],New=[False],Old=[false]} respectively. Current_State returns the current state of the object. @begin{Discussion} This state can change immediately after the operation returns. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The procedure Suspend_Until_True blocks the calling task until the state of the object S is @Chg{Version=[2],New=[True],Old=[true]}; at that point the task becomes ready and the state of the object becomes @Chg{Version=[2],New=[False],Old=[false]}. @PDefn2{Term=[potentially blocking operation],Sec=(Suspend_Until_True)} @PDefn2{Term=[blocking, potentially],Sec=(Suspend_Until_True)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised upon calling Suspend_Until_True if another task is already waiting on that suspension object. Suspend_Until_True is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @end{RunTime} @begin{ImplReq} The implementation is required to allow the calling of Set_False and Set_True during any protected action, even one that has its ceiling priority in the Interrupt_Priority range. @end{ImplReq} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Synchronous_Task_Control is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @LabeledClause{Asynchronous Task Control} @begin{Intro} @Redundant[This clause introduces a language-defined package to do asynchronous suspend/resume on tasks. It uses a conceptual @i{held priority} value to represent the task's @i{held} state.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key{with} Ada.Task_Identification; @key{package} Ada.Asynchronous_Task_Control @key{is}@ChildUnit{parent=[Ada],Child=[Asynchronous_Task_Control]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Asynchronous_Task_Control);],Old=[]} @key{procedure} @AdaSubDefn{Hold}(T : @key[in] Ada.Task_Identification.Task_Id); @key{procedure} @AdaSubDefn{Continue}(T : @key[in] Ada.Task_Identification.Task_Id); @key{function} @AdaSubDefn{Is_Held}(T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{end} Ada.Asynchronous_Task_Control; @end{example} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} @PDefn2{Term=[task state], Sec=(held)} @Defn{held priority} @Defn{idle task} After the Hold operation has been applied to a task, the task becomes @i{held}. For each processor there is a conceptual @i{idle task}, which is always ready. The base priority of the idle task is below System.@!Any_@!Priority'First. The @i{held priority} is a constant of the type @Chg{Version=[2],New=[Integer],Old=[integer]} whose value is below the base priority of the idle task. @begin{Discussion} The held state should not be confused with the blocked state as defined in @RefSecNum{Task Execution - Task Activation}; the task is still ready. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[For any priority below System.Any_Priority'First, the task dispatching policy is FIFO_Within_Priorities.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This applies even if a Task_Dispatching_Policy specifies the policy for all of the priorities of the partition.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A task at the held priority never runs, so it is not necessary to implement FIFO_Within_Priorities for systems that have only one policy (such as EDF_Across_Priorities).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} The Hold operation sets the state of T to held. For a held task@Chg{Version=[2],New=[, the active priority is reevaluated as if the base priority of the task were the held priority],Old=[: the task's own base priority does not constitute an inheritance source (see @RefSecNum{Task Priorities}), and the value of the held priority is defined to be such a source instead]}. @begin{Ramification} For example, if T is currently inheriting priorities from other sources (e.g. it is executing in a protected action), its active priority does not change, and it continues to execute until it leaves the protected action. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} The Continue operation resets the state of T to not-held; @Chg{Version=[2],New=[its],Old=[T's]} active priority is then reevaluated as @Chg{Version=[2],New=[determined by the task dispatching policy associated with its base priority.],Old=[described in @RefSecNum{Task Priorities}. @Redundant[This time, T's base priority is taken into account.]]} The Is_Held function returns True if and only if T is in the held state. @begin{Discussion} Note that the state of T can be changed immediately after Is_Held returns. @end{Discussion} As part of these operations, a check is made that the task identified by T is not terminated. @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Tasking_Error is raised if the check fails. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the value of T is Null_Task_Id. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If any operation in this package is called with a parameter T that specifies a task object that no longer exists, the execution of the program is erroneous. @end{Erron} @begin{ImplPerm} An implementation need not support Asynchronous_Task_Control if it is infeasible to support it in the target environment. @begin{Reason} A direct implementation of the Asynchronous_Task_Control semantics using priorities is not necessarily efficient enough. Thus, we envision implementations that use some other mechanism to set the @lquotes@;held@rquotes@; state. If there is no other such mechanism, support for Asynchronous_Task_Control might be infeasible, because an implementation in terms of priority would require one idle task per processor. On some systems, programs are not supposed to know how many processors are available, so creating enough idle tasks would be problematic. @end{Reason} @end{ImplPerm} @begin{Notes} It is a consequence of the priority rules that held tasks cannot be dispatched on any processor in a partition (unless they are inheriting priorities) since their priorities are defined to be below the priority of any idle task. The effect of calling Get_Priority and Set_Priority on a Held task is the same as on any other task. Calling Hold on a held task or Continue on a non-held task has no effect. @Leading@;The rules affecting queuing are derived from the above rules, in addition to the normal priority rules: @begin{itemize} When a held task is on the ready queue, its priority is so low as to never reach the top of the queue as long as there are other tasks on that queue. If a task is executing in a protected action, inside a rendezvous, or is inheriting priorities from other sources (e.g. when activated), it continues to execute until it is no longer executing the corresponding construct. If a task becomes held while waiting (as a caller) for a rendezvous to complete, the active priority of the accepting task is not affected. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} If a task becomes held while waiting in a @nt{selective_accept}, and a@Chg{New=[n],Old=[]} entry call is issued to one of the open entries, the corresponding @Chg{New=[@nt{accept_@!alternative}],Old=[accept body]} executes. When the rendezvous completes, the active priority of the accepting task is lowered to the held priority (unless it is still inheriting from other sources), and the task does not execute until another Continue. The same holds if the held task is the only task on a protected entry queue whose barrier becomes open. The corresponding entry body executes. @end{itemize} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Asynchronous_Task_Control is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0077],ARef=[AI95-00111-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected to eliminate the use of the undefined term @lquotes@;accept body@rquotes@;.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The description of held tasks was changed to reflect that the calculation of active priorities depends on the dispatching policy of the base priority. Thus, the policy of the held priority was specified in order to avoid surprises (especially when using the EDF policy).]} @end{DiffWord95} @LabeledClause{Other Optimizations and Determinism Rules} @begin{Intro} @Redundant[This clause describes various requirements for improving the response and determinism in a real-time system.] @end{Intro} @begin{ImplReq} If the implementation blocks interrupts (see @RefSecNum{Interrupt Support}) not as a result of direct user action (e.g. an execution of a protected action) there shall be an upper bound on the duration of this blocking. @begin{Ramification} The implementation shall not allow itself to be interrupted when it is in a state where it is unable to support all the language-defined operations permitted in the execution of interrupt handlers. (see @RefSecNum{Protected Subprograms and Protected Actions}). @end{Ramification} The implementation shall recognize entry-less protected types. The overhead of acquiring the execution resource of an object of such a type (see @RefSecNum{Protected Subprograms and Protected Actions}) shall be minimized. In particular, there should not be any overhead due to evaluating @nt{entry_barrier} @nt{condition}s. @begin{ImplNote} Ideally the overhead should just be a spin-lock. @end{ImplNote} Unchecked_Deallocation shall be supported for terminated tasks that are designated by access types, and shall have the effect of releasing all the storage associated with the task. This includes any run-time system or heap storage that has been implicitly allocated for the task by the implementation. @end{ImplReq} @begin{DocReq} The implementation shall document the upper bound on the duration of interrupt blocking caused by the implementation. If this is different for different interrupts or interrupt priority levels, it should be documented for each case. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[The upper bound on the duration of interrupt blocking caused by the implementation.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The upper bound on the duration of interrupt blocking caused by the implementation.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metric: @begin{Itemize} The overhead associated with obtaining a mutual-exclusive access to an entry-less protected object. This shall be measured in the following way: @NoPrefix@Leading@keepnext@;For a protected object of the form: @begin{example} @key{protected} Lock @key{is} @key{procedure} Set; @Key{function} Read @Key{return} Boolean; @key{private} Flag : Boolean := False; @key{end} Lock; @key{protected body} Lock @key{is} @key{procedure} Set @key{is} @key{begin} Flag := True; @key{end} Set; @Key{function} Read @Key{return} Boolean @key{Begin} @key{return} Flag; @key{end} Read; @key{end} Lock; @end{example} @NoPrefix@;The execution time, in processor clock cycles, of a call to Set. This shall be measured between the point just before issuing the call, and the point just after the call completes. The function Read shall be called later to verify that Set was indeed called (and not optimized away). The calling task shall have sufficiently high priority as to not be preempted during the measurement period. The protected object shall have sufficiently high ceiling priority to allow the task to call Set. @NoPrefix@;For a multiprocessor, if supported, the metric shall be reported for the case where no contention (on the execution resource) exists @Redundant[from tasks executing on other processors]. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for entry-less protected objects.]}]} @end{Metrics} @LabeledAddedClause{Version=[2],Name=[Run-time Profiles]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause specifies a mechanism for defining run-time profiles.]]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Profile is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=`@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Profile> (@SynI{profile_}@Syn2{identifier} {, @SynI{profile_}@Syn2{pragma_argument_association}});''} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[The @SynI{profile_}@nt{identifier} shall be the name of a run-time profile. The semantics of any @SynI{profile_}@nt{pragma_@!argument_@!association}s are defined by the run-time profile specified by the @SynI{profile_}@nt{identifier}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[ A profile is equivalent to the set of configuration pragmas that is defined for each run-time profile.]} @end{StaticSem} @begin{Linktime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Profile)} @PDefn2{Term=[pragma, configuration], Sec=(Profile)} A @nt{pragma} Profile is a configuration pragma. There may be more than one @nt{pragma} Profile for a partition.]} @end{Linktime} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Profile is new.]} @end{Extend95} @RMNewPage @LabeledAddedSubClause{Version=[2],Name=[The Ravenscar Profile]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[@Redundant[This clause defines the Ravenscar profile.]@Defn{Ravenscar}]} @end{Intro} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[The @SynI{profile_}@nt{identifier} Ravenscar is a run-time profile. For run-time profile Ravenscar, there shall be no @Syni{profile_}@nt{pragma_argument_association}s.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The run-time profile Ravenscar is equivalent to the following set of pragmas:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI95-00297-01],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[ @key{pragma} Task_Dispatching_Policy (FIFO_Within_Priorities); @key{pragma} Locking_Policy (Ceiling_Locking); @key{pragma} Detect_Blocking; @key{pragma} Restrictions ( No_Abort_Statements, No_Dynamic_Attachment, No_Dynamic_Priorities, No_Implicit_Heap_Allocations, No_Local_Protected_Objects, No_Local_Timing_Events, No_Protected_Type_Allocators, No_Relative_Delay, No_Requeue_Statements, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Allocators, No_Task_Hierarchy, No_Task_Termination, Simple_Barriers, Max_Entry_Queue_Length => 1, Max_Protected_Entries => 1, Max_Task_Entries => 0, No_Dependence => Ada.Asynchronous_Task_Control, No_Dependence => Ada.Calendar, No_Dependence => Ada.Execution_Time.Group_Budget, No_Dependence => Ada.Execution_Time.Timers, No_Dependence => Ada.Task_Attributes);]} @end{Example} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Ravenscar profile is named for the location of the meeting that defined its initial version. The name is now in widespread use, so we stick with existing practice, rather than using a more descriptive name.@Comment{ This is another example of Ada's lousy marketing sense; casual readers, especially those outside of Ada, have no conception of what @lquotes@;Ravenscar@rquotes@; is, and thus are much less likely to investigate it to find out how it can help them.}]} @end{Discussion} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[ The effect of the Max_Entry_Queue_Length => 1 restriction applies only to protected entry queues due to the accompanying restriction of Max_Task_Entries => 0.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Ravenscar profile is new.]} @end{Extend95} @RMNewPage@Comment{For printed Ada 2007 RM} @LabeledAddedClause{Version=[2],Name=[Execution Time]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[This clause describes a language-defined package to measure execution time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Task_Identification; @key{with} Ada.Real_Time; @key{use} Ada.Real_Time; @key{package} Ada.Execution_Time @key{is}@ChildUnit{Parent=[Ada],Child=[Execution_Time]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{CPU_Time} @key{is private}; @AdaObjDefn{CPU_Time_First} : @key{constant} CPU_Time; @AdaObjDefn{CPU_Time_Last} : @key{constant} CPU_Time; @AdaObjDefn{CPU_Time_Unit} : @key{constant} := @RI{implementation-defined-real-number}; @AdaObjDefn{CPU_Tick} : @key{constant} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Clock} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key{return} CPU_Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : CPU_Time; Right : Time_Span) @key{return} CPU_Time; @key{function} "+" (Left : Time_Span; Right : CPU_Time) @key{return} CPU_Time; @key{function} "-" (Left : CPU_Time; Right : Time_Span) @key{return} CPU_Time; @key{function} "-" (Left : CPU_Time; Right : CPU_Time) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} "<=" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} ">" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} ">=" (Left, Right : CPU_Time) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Split} (T : @key{in} CPU_Time; SC : @key{out} Seconds_Count; TS : @key{out} Time_Span);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Of} (SC : Seconds_Count; TS : Time_Span := Time_Span_Zero) @key{return} CPU_Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- @RI[not specified by the language] @key{end} Ada.Execution_Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[execution time],Sec=[of a task]} @Defn2{Term=[CPU time],Sec=[of a task]} The @i<execution time> or CPU time of a given task is defined as the time spent by the system executing that task, including the time spent executing run-time or system services on its behalf. The mechanism used to measure execution time is implementation defined. It is implementation defined which task, if any, is charged the execution time that is consumed by interrupt handlers and run-time services on behalf of the system.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation-defined properties above and of the values declared in the package are repeated in @DocReqTitle, so we don't mark them as implementation-defined.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type CPU_Time represents the execution time of a task. The set of values of this type corresponds one-to-one with an implementation-defined range of mathematical integers.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The CPU_Time value I represents the half-open execution-time interval that starts with I*CPU_Time_Unit and is limited by (I+1)*CPU_Time_Unit, where CPU_Time_Unit is an implementation-defined real number. For each task, the execution time value is set to zero at the creation of the task.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since it is implementation-defined which task is charged execution time for system services, the execution time value may become non-zero even before the start of the activation of the task.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[CPU_Time_First and CPU_Time_Last are the smallest and largest values of the CPU_Time type, respectively.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{CPU clock tick} CPU_Time_Unit is the smallest amount of execution time representable by the CPU_Time type; it is expressed in seconds. A @i<CPU clock tick> is an execution time interval during which the clock value (as observed by calling the Clock function) remains constant. CPU_Tick is the average length of such intervals.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The effects of the operators on CPU_Time and Time_Span are as for the operators defined for integer types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The function Clock returns the current execution time of the task identified by T; Tasking_Error is raised if that task has terminated; Program_Error is raised if the value of T is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The effects of the Split and Time_Of operations are defined as follows, treating values of type CPU_Time, Time_Span, and Seconds_Count as mathematical integers. The effect of Split (T, SC, TS) is to set SC and TS to values such that T*CPU_Time_Unit = SC*1.0 + TS*CPU_Time_Unit, and 0.0 <= TS*CPU_Time_Unit < 1.0. The value returned by Time_Of(SC,TS) is the execution-time value T such that T*CPU_Time_Unit=SC*1.0 + TS*CPU_Time_Unit.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of Clock, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The range of CPU_Time values shall be sufficient to uniquely represent the range of execution times from the task start-up to 50 years of execution time later. CPU_Tick shall be no greater than 1 millisecond.]} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The implementation shall document the values of CPU_Time_First, CPU_Time_Last, CPU_Time_Unit, and CPU_Tick.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values of CPU_Time_First, CPU_Time_Last, CPU_Time_Unit, and CPU_Tick of package Execution_Time.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The implementation shall document the properties of the underlying mechanism used to measure execution times, such as the range of values supported and any relevant aspects of the underlying hardware or operating system facilities used.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The properties of the mechanism used to implement package Execution_Time.]}]} @end{DocReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The implementation shall document the following metrics:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text={An upper bound on the execution-time duration of a clock tick. This is a value D such that if t1 and t2 are any execution times of a given task such that t1 < t2 and Clock@-{t1} = Clock@-{t2} then t2 @en@; t1 <= D.}} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An upper bound on the size of a clock jump. A clock jump is the difference between two successive distinct values of an execution-time clock (as observed by calling the Clock function with the same Task_Id).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An upper bound on the execution time of a call to the Clock function, in processor clock cycles.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Upper bounds on the execution times of the operators of the type CPU_Time, in processor clock cycles.]} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for execution time.]}]} @end{Metrics} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[Implementations targeted to machines with word size smaller than 32 bits need not support the full range and granularity of the CPU_Time type.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When appropriate, implementations should provide configuration mechanisms to change the value of CPU_Tick.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When appropriate, implementations should provide configuration mechanisms to change the value of Execution_Time.CPU_Tick.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[Execution Time Timers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[This clause describes a language-defined package that provides a facility for calling a handler when a task has used a defined amount of CPU time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} System; @key{package} Ada.Execution_Time.Timers @key{is}@ChildUnit{Parent=[Ada.Execution_Time],Child=[Timers]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timer} (T : @key{not null access constant} Ada.Task_Identification.Task_Id) @key{is} @key{tagged limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timer_Handler} @key{is} @key{access protected procedure} (TM : @key{in out} Timer);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Min_Handler_Ceiling} : @key{constant} System.Any_Priority := @RI[implementation-defined];]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (TM : @key{in out} Timer; In_Time : @key{in} Time_Span; Handler : @key{in} Timer_Handler); @key{procedure} @AdaSubDefn{Set_Handler} (TM : @key{in out} Timer; At_Time : @key{in} CPU_Time; Handler : @key{in} Timer_Handler); @key{function} @AdaSubDefn{Current_Handler} (TM : Timer) @key{return} Timer_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (TM : @key{in out} Timer; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Remaining} (TM : Timer) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Timer_Resource_Error} : @key{exception};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- not specified by the language @key{end} Ada.Execution_Time.Timers;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type Timer represents an execution-time event for a single task and is capable of detecting execution-time overruns. The access discriminant T identifies the task concerned. The type Timer needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[An object of type Timer is said to be @i<set> if it is associated with a non-null value of type Timer_Handler and @i<cleared> otherwise. All Timer objects are initially cleared. @PDefn2{Term=[set],Sec=[execution timer object]} @PDefn2{Term=[clear],Sec=[execution timer object]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type Timer_Handler identifies a protected procedure to be executed by the implementation when the timer expires. Such a protected procedure is called a @i<handler>. @PDefn2{Term=[handler],Sec=[execution timer]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Type Timer is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific timer object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Timer can be declared; a double type conversion can be used to access the extension data. An example of how this can be done can be found for the similar type Timing_Event, see @RefSecNum{Timing Events}.]} @end{Discussion} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When a Timer object is created, or upon the first call of a Set_Handler procedure with the timer as parameter, the resources required to operate an execution-time timer based on the associated execution-time clock are allocated and initialized. If this operation would exceed the available resources, Timer_Resource_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The procedures Set_Handler associate the handler Handler with the timer TM; if Handler is @key[null], the timer is cleared, otherwise it is set. The first procedure Set_Handler loads the timer TM with an interval specified by the Time_Span parameter. In this mode, the timer TM @i<expires> when the execution time of the task identified by TM.T.@key[all] has increased by In_Time; if In_Time is less than or equal to zero, the timer expires immediately. The second procedure Set_Handler loads the timer TM with the absolute value specified by At_Time. In this mode, the timer TM expires when the execution time of the task identified by TM.T.@key[all] reaches At_Time; if the value of At_Time has already been reached when Set_Handler is called, the timer expires immediately.@Defn2{Term=[expires], Sec=[execution timer]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since an access-to-constant can designate a variable, the Task_Id value designated by the discriminant of a Timer object can be changed after the object is created. Thus, an implementation cannot use the value of the Task_Id other than where this Standard specifies. For instance, the Task_Id should be read when the timer is set, but it should not be used when the timer expires (as it may designate a different task at that point.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[A call of a procedure Set_Handler for a timer that is already set replaces the handler and the (absolute or relative) execution time; if Handler is not @b<null>, the timer remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When a timer expires, the associated handler is executed, passing the timer as parameter. The initial action of the execution of the handler is to clear the event.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the timer TM if that timer is set; otherwise it returns @b<null>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the timer if it is set. Cancelled is assigned True if the timer was set prior to it being cleared; otherwise it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The function Time_Remaining returns the execution time interval that remains until the timer TM would expire, if that timer is set; otherwise it returns Time_Span_Zero.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The constant Min_Handler_Ceiling is the minimum ceiling priority required for a protected object with a handler to ensure that no ceiling violation will occur when that handler is invoked.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Timer, the timer is cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[For all the subprograms defined in this package, Tasking_Error is raised if the task identified by TM.T.@key[all] has terminated, and Program_Error is raised if the value of TM.T.@key[all] is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked as part of the expiration of a timer has no effect.]} @end{Runtime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of any of the subprograms defined in this package, if the task identified by TM.T.@key[all] no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[For a given Timer object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Timer object. The replacement of a handler by a call of Set_Handler shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if an event occurs when Set_Handler is changing the handler then either the new or old handler is executed in response to the appropriate event. It is never possible for a new handler to be executed in response to an old event]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When an object of type Timer is finalized, the system resources used by the timer shall be deallocated.]} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[Implementations may limit the number of timers that can be defined for each task. If this limit is exceeded then Timer_Resource_Error is raised.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[A Timer_Handler can be associated with several Timer objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time.Timers is new.]} @end{Extend95} @RMNewPage@Comment{For printed Ada 2007 RM} @LabeledAddedSubclause{Version=[2],Name=[Group Execution Time Budgets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[This clause describes a language-defined package to assign execution time budgets to groups of tasks.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} System; @key{package} Ada.Execution_Time.Group_Budgets @key{is}@ChildUnit{Parent=[Ada.Execution_Time],Child=[Group_Budgets]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Group_Budget} @key{is tagged limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Group_Budget_Handler} @key{is access} @key{protected procedure} (GB : @key{in out} Group_Budget);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Task_Array} @key{is array} (Positive @key{range} <>) @key{of} Ada.Task_Identification.Task_Id;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Min_Handler_Ceiling} : @key{constant} System.Any_Priority := @RI[implementation-defined];]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Add_Task} (GB : @key{in out} Group_Budget; T : @key{in} Ada.Task_Identification.Task_Id); @key{procedure} @AdaSubDefn{Remove_Task} (GB: @key{in out} Group_Budget; T : @key{in} Ada.Task_Identification.Task_Id); @key{function} @AdaSubDefn{Is_Member} (GB : Group_Budget; T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{function} @AdaSubDefn{Is_A_Group_Member} (T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{function} @AdaSubDefn{Members} (GB : Group_Budget) @key{return} Task_Array;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replenish} (GB : @key{in out} Group_Budget; To : @key{in} Time_Span); @key{procedure} @AdaSubDefn{Add} (GB : @key{in out} Group_Budget; Interval : @key{in} Time_Span); @key{function} @AdaSubDefn{Budget_Has_Expired} (GB : Group_Budget) @key{return} Boolean; @key{function} @AdaSubDefn{Budget_Remaining} (GB : Group_Budget) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (GB : @key{in out} Group_Budget; Handler : @key{in} Group_Budget_Handler); @key{function} @AdaSubDefn{Current_Handler} (GB : Group_Budget) @key{return} Group_Budget_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (GB : @key{in out} Group_Budget; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Group_Budget_Error} : @key{exception};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} -- not specified by the language @key{end} Ada.Execution_Time.Group_Budgets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The type Group_Budget represents an execution time budget to be used by a group of tasks. The type Group_Budget needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}). A task can belong to at most one group. Tasks of any priority can be added to a group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An object of type Group_Budget has an associated nonnegative value of type Time_Span known as its @i<budget>, which is initially Time_Span_Zero. The type Group_Budget_Handler identifies a protected procedure to be executed by the implementation when the budget is @i<exhausted>, that is, reaches zero. Such a protected procedure is called a @i<handler>.@Defn{budget}@Defn2{Term=[exhaust],Sec=[a budget]} @PDefn2{Term=[handler],Sec=[group budget]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An object of type Group_Budget also includes a handler, which is a value of type Group_Budget_Handler. The handler of the object is said to be @i<set> if it is not null and @i<cleared> otherwise. The handler of all Group_Budget objects is initially cleared. @PDefn2{Term=[set],Sec=[group budget object]} @PDefn2{Term=[clear],Sec=[group budget object]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Type Group_Budget is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific group budget object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Group_Budget can be declared; a double type conversion can be used to access the extension data. An example of how this can be done can be found for the similar type Timing_Event, see @RefSecNum{Timing Events}.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Add_Task adds the task identified by T to the group GB; if that task is already a member of some other group, Group_Budget_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Remove_Task removes the task identified by T from the group GB; if that task is not a member of the group GB, Group_Budget_Error is raised. After successful execution of this procedure, the task is no longer a member of any group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Is_Member returns True if the task identified by T is a member of the group GB; otherwise it return False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Is_A_Group_Member returns True if the task identified by T is a member of some group; otherwise it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Members returns an array of values of type Task_Identification.Task_Id identifying the members of the group GB. The order of the components of the array is unspecified.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Replenish loads the group budget GB with To as the Time_Span value. The exception Group_Budget_Error is raised if the Time_Span value To is non-positive. Any execution of any member of the group of tasks results in the budget counting down, unless exhausted. When the budget becomes exhausted (reaches Time_Span_Zero), the associated handler is executed if the handler of group budget GB is set. Nevertheless, the tasks continue to execute.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Add modifies the budget of the group GB. A positive value for Interval increases the budget. A negative value for Interval reduces the budget, but never below Time_Span_Zero. A zero value for Interval has no effect. A call of procedure Add that results in the value of the budget going to Time_Span_Zero causes the associated handler to be executed if the handler of the group budget GB is set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Budget_Has_Expired returns True if the budget of group GB is exhausted (equal to Time_Span_Zero); otherwise it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Budget_Remaining returns the remaining budget for the group GB. If the budget is exhausted it returns Time_Span_Zero. This is the minimum value for a budget.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Set_Handler associates the handler Handler with the Group_Budget GB; if Handler is @b<null>, the handler of Group_Budget is cleared, otherwise it is set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[A call of Set_Handler for a Group_Budget that already has a handler set replaces the handler; if Handler is not @b<null>, the handler for Group_Budget remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the group budget GB if the handler for that group budget is set; otherwise it returns @b<null>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the handler for the group budget if it is set. Cancelled is assigned True if the handler for the group budget was set prior to it being cleared; otherwise it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The constant Min_Handler_Ceiling is the minimum ceiling priority required for a protected object with a handler to ensure that no ceiling violation will occur when that handler is invoked.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The precision of the accounting of task execution time to a Group_Budget is the same as that defined for execution-time clocks from the parent package.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Group_Budget all member tasks are removed from the group identified by that object.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[If a task is a member of a Group_Budget when it terminates then as part of the finalization of the task it is removed from the group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[For all the operations defined in this package, Tasking_Error is raised if the task identified by T has terminated, and Program_Error is raised if the value of T is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked when the budget of a group of tasks becomes exhausted has no effect.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of any of the subprograms defined in this package, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[For a given Group_Budget object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Group_Budget object. The replacement of a handler, by a call of Set_Handler, shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if the budget is exhausted when Set_Handler is changing the handler then either the new or old handler is executed and the exhausting event is not lost.]} @end{Reason} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[Clearing or setting of the handler of a group budget does not change the current value of the budget. Exhaustion or loading of a budget does not change whether the handler of the group budget is set or cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[A Group_Budget_Handler can be associated with several Group_Budget objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time.Group_Budgets is new.]} @end{Extend95} @LabeledAddedClause{Version=[2],Name=[Timing Events]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[This clause describes a language-defined package to allow user-defined protected procedures to be executed at a specified time without the need for a task or a delay statement.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Real_Time.Timing_Events @key{is}@ChildUnit{Parent=[Ada.Real_Time],Child=[Timing_Events]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timing_Event} @key{is tagged limited private}; @key{type} @AdaTypeDefn{Timing_Event_Handler} @key{is access protected procedure} (Event : @key{in out} Timing_Event);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (Event : @key{in out} Timing_Event; At_Time : @key{in} Time; Handler : @key{in} Timing_Event_Handler); @key{procedure} @AdaSubDefn{Set_Handler} (Event : @key{in out} Timing_Event; In_Time : @key{in} Time_Span; Handler : @key{in} Timing_Event_Handler); @key{function} @AdaSubDefn{Current_Handler} (Event : Timing_Event) @key{return} Timing_Event_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (Event : @key{in out} Timing_Event; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Of_Event} (Event : Timing_Event) @key{return} Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- @RI[not specified by the language] @key{end} Ada.Real_Time.Timing_Events;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The type Timing_Event represents a time in the future when an event is to occur. The type Timing_Event needs finalization (see @RefSecNum{User-Defined Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[An object of type Timing_Event is said to be @i<set> if it is associated with a non-null value of type Timing_Event_Handler and @i<cleared> otherwise. All Timing_Event objects are initially cleared. @PDefn2{Term=[set],Sec=[timing event object]} @PDefn2{Term=[clear],Sec=[timing event object]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The type Timing_Event_Handler identifies a protected procedure to be executed by the implementation when the timing event occurs. Such a protected procedure is called a @i{handler}. @PDefn2{Term=[handler],Sec=[timing event]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Type Timing_Event is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific timing event object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Timing_Event can be declared; a double type conversion can be used to access the extension data. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Toaster_Timing_Event @key{is new} Timing_Event @key{with record} Slot : Natural; @key{end record};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{protected body} Toaster @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Timer(Event : @key{in out} Timing_Event) @key{is} @key{begin} Pop_Up_Toast (Toaster_Timing_Event(Timing_Event'Class(Event)).Slot); @key{end} Timer;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key{end} Toaster;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The extra conversion to the class-wide type is necessary to make the conversions legal. While this usage is clearly ugly, we think that the need for this sort of usage will be rare, so we can live with it. It's certainly better than having no way to associate data with an event.]} @end{Discussion} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The procedures Set_Handler associate the handler Handler with the event Event; if Handler is @key{null}, the event is cleared, otherwise it is set. The first procedure Set_Handler sets the execution time for the event to be At_Time. The second procedure Set_Handler sets the execution time for the event to be Real_Time.Clock + In_Time.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[A call of a procedure Set_Handler for an event that is already set replaces the handler and the time of execution; if Handler is not @key{null}, the event remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[As soon as possible after the time set for the event, the handler is executed, passing the event as parameter. The handler is only executed if the timing event is in the set state at the time of execution. The initial action of the execution of the handler is to clear the event.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The second sentence of this paragraph is because of a potential race condition. The time might expire and yet before the handler is executed, some task could call Cancel_Handler (or equivalently call Set_Handler with a @key{null} parameter) and thus clear the handler.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect when a procedure Set_Handler is called, a check is made that the ceiling priority of Handler.@key{all} is Interrupt_Priority'Last. If the check fails, Program_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[If a procedure Set_Handler is called with zero or negative In_Time or with At_Time indicating a time in the past then the handler is executed immediately by the task executing the call of Set_Handler. The timing event Event is cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the event Event if that event is set; otherwise it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the event if it is set. Cancelled is assigned True if the event was set prior to it being cleared; otherwise it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The function Time_Of_Event returns the time of the event if the event is set; otherwise it returns Real_Time.Time_First.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Timing_Event, the Timing_Event is cleared.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the only finalization defined by the language that has a visible effect; but an implementation may have other finalization that it needs to perform. Implementations need to ensure that the event is cleared before anything else is finalized that would prevent a set event from being triggered.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[If several timing events are set for the same time, they are executed in FIFO order of being set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked by a timing event has no effect.]} @end{Runtime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[For a given Timing_Event object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Timing_Event object. The replacement of a handler by a call of Set_Handler shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if an event occurs when Set_Handler is changing the handler then either the new or old handler is executed in response to the appropriate event. It is never possible for a new handler to be executed in response to an old event.]} @end{Reason} @end{ImplReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The implementation shall document the following metric:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An upper bound on the lateness of the execution of a handler. That is, the maximum time between when a handler is actually executed and the time specified when the event was set.]} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for timing events.]}]} @end{Metrics} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The protected handler procedure should be executed directly by the real-time clock interrupt mechanism.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For a timing event, the handler should be executed directly by the real-time clock interrupt mechanism.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[Since a call of Set_Handler is not a potentially blocking operation, it can be called from within a handler.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[A Timing_Event_Handler can be associated with several Timing_Event objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Real_Time.Timing_Events is new.]} @end{Extend95} ���������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/safety.mss�����������������������������������������������������������0000755�0001752�0001001�00000146642�12273462240�017455� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{ $Source: e:\\cvsroot/ARM/Source/safety.mss,v $ } @Comment{ $Revision: 1.39 $ $Date: 2006/10/19 06:40:32 $ $Author: Randy $ } @Part(safety, Root="ada.mss") @Comment{$Date: 2006/10/19 06:40:32 $} @LabeledRevisedNormativeAnnex{Version=[2], New=[High Integrity Systems], Old=[Safety and Security]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00347-01]} @Leading@Defn{safety-critical systems} @Defn{secure systems} This Annex addresses requirements for @Chg{Version=[2], New=[high integrity ],Old=[]}systems @Chg{Version=[2],New=[(including], Old=[that are]} safety@Chg{Version=[2],New=[-],Old=[ ]}critical @Chg{Version=[2],New=[systems and],Old=[or have]} security@Chg{Version=[2],New=[-critical systems)],Old=[ constraints]}. It provides facilities and specifies documentation requirements that relate to several needs: @begin{Itemize} Understanding program execution; Reviewing object code; Restricting language constructs whose usage might complicate the demonstration of program correctness @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}Execution understandability is supported by pragma Normalize_Scalars, and also by requirements for the implementation to document the effect of a program in the presence of a bounded error or where the language rules leave the effect unspecified. @PDefn{unspecified} The @nt[pragma]s Reviewable and Restrictions relate to the other requirements addressed by this Annex. @end{Intro} @begin{Notes} The @attr[Valid] attribute (see @RefSecNum(The Valid Attribute)) is also useful in addressing these needs, to avoid problems that could otherwise arise from scalars that have values outside their declared range constraints. @begin{Discussion} The Annex tries to provide high assurance rather than language features. However, it is not possible, in general, to test for high assurance. For any specific language feature, it is possible to demonstrate its presence by a functional test, as in the ACVC. One can also check for the presence of some documentation requirements, but it is not easy to determine objectively that the documentation is @lquotes@;adequate@rquotes@;. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[The title of this annex was changed to better reflect its purpose and scope. High integrity systems has become the standard way of identifying systems that have high reliability requirements; it subsumes terms such as safety and security. Moreover, the annex does not include any security specific features and as such the previous title is somewhat misleading.]} @end{DiffWord95} @LabeledClause{Pragma Normalize_Scalars} @begin{Intro} This pragma ensures that an otherwise uninitialized scalar object is set to a predictable value, but out of range if possible. @begin[discussion] The goal of the pragma is to reduce the impact of a bounded error that results from a reference to an uninitialized scalar object, by having such a reference violate a range check and thus raise Constraint_Error. @end[discussion] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Normalize_Scalars is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Normalize_Scalars);' @end{Syntax} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Normalize_Scalars)} @PDefn2{Term=[pragma, configuration], Sec=(Normalize_Scalars)} Pragma Normalize_Scalars is a configuration pragma. It applies to all @nt[compilation_unit]s included in a partition. @end{LinkTime} @begin{DocReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If a @nt{pragma} Normalize_Scalars applies, the implementation shall document the implicit initial @Chg{Version=[2], New=[values],Old=[value]} for scalar subtypes, and shall identify each case in which such a value is used and is not an invalid representation. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[If a @nt{pragma} Normalize_Scalars applies, the implicit initial values of scalar subtypes shall be documented. Such a value should be an invalid representation when possible; any cases when is it not shall be documented.]}]} @begin{Honest} It's slightly inaccurate to say that the value is a representation, but the point should be clear anyway. @end{Honest} @begin{Discussion} By providing a type with a size specification so that spare bits are present, it is possible to force an implementation of Normalize_Scalars to use an out of range value. This can be tested for by ensuring that Constraint_Error is raised. Similarly, for an unconstrained integer type, in which no spare bit is surely present, one can check that the initialization takes place to the value specified in the documentation of the implementation. For a floating point type, spare bits might not be available, but a range constraint can provide the ability to use an out of range value. If it is difficult to document the general rule for the implicit initial value, the implementation might choose instead to record the value on the object code listing or similar output produced during compilation. @end{Discussion} @end{DocReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Whenever possible, the implicit initial @Chg{Version=[2], New=[values],Old=[value]} for a scalar subtype should be an invalid representation (see @RefSecNum{Data Validity}). @begin{Discussion} When an out of range value is used for the initialization, it is likely that constraint checks will detect it. In addition, it can be detected by the Valid attribute. @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule is included in the documentation requirements, and thus does not need a separate summary item.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} The initialization requirement applies to uninitialized scalar objects that are subcomponents of composite objects, to allocated objects, and to stand-alone objects. It also applies to scalar @key{out} parameters. Scalar subcomponents of composite @key{out} parameters are initialized to the corresponding part of the actual, by virtue of @RefSecNum(Parameter Associations). The initialization requirement does not apply to a scalar for which pragma Import has been specified, since initialization of an imported object is performed solely by the foreign language environment (see @RefSecNum[Interfacing Pragmas]). The use of pragma Normalize_Scalars in conjunction with Pragma Restrictions(No_Exceptions) may result in erroneous execution (see @RefSecNum[High Integrity Restrictions]). @begin{Discussion} Since the effect of an access to an out of range value will often be to raise Constraint_Error, it is clear that suppressing the exception mechanism could result in erroneous execution. In particular, the assignment to an array, with the array index out of range, will result in a write to an arbitrary store location, having unpredictable effects. @end{Discussion} @end{Notes} @LabeledClause{Documentation of Implementation Decisions} @begin{DocReq} @PDefn{unspecified} The implementation shall document the range of effects for each situation that the language rules identify as either a bounded error or as having an unspecified effect. If the implementation can constrain the effects of erroneous execution for a given construct, then it shall document such constraints. @Redundant[The documentation might be provided either independently of any compilation unit or partition, or as part of an annotated listing for a given unit or partition. See also @RefSecNum(Conformity of an Implementation with the Standard), and @RefSecNum(Structure).] @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Information regarding bounded errors and erroneous execution.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The range of effects for each bounded error and each unspecified effect. If the effects of a given erroneous construct are constrained, the constraints shall be documented.]}]} @end{DocReq} @begin{Notes} Among the situations to be documented are the conventions chosen for parameter passing, the methods used for the management of run-time storage, and the method used to evaluate numeric expressions if this involves extended range or extra precision. @begin{Discussion} Look up @lquotes@;unspecified@rquotes@; and @lquotes@;erroneous execution@rquotes@; in the index for a list of the cases. The management of run-time storage is particularly important. For safety applications, it is often necessary to show that a program cannot raise Storage_Error, and for security applications that information cannot leak via the run-time system. Users are likely to prefer a simple storage model that can be easily validated. The documentation could helpfully take into account that users may well adopt a subset to avoid some forms of erroneous execution, for instance, not using the abort statement, so that the effects of a partly completed @nt{assignment_statement} do not have to be considered in the validation of a program (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}). For this reason documentation linked to an actual compilation may be most useful. Similarly, an implementation may be able to take into account use of the Restrictions pragma. @end{Discussion} @end{Notes} @LabeledClause{Reviewable Object Code} @begin{Intro} Object code review and validation are supported by pragmas Reviewable and Inspection_Point. @end{Intro} @LabeledSubClause{Pragma Reviewable} @begin{Intro} This pragma directs the implementation to provide information to facilitate analysis and review of a program's object code, in particular to allow determination of execution time and storage usage and to identify the correspondence between the source and object programs. @begin{Discussion} Since the purpose of this pragma is to provide information to the user, it is hard to objectively test for conformity. In practice, users want the information in an easily understood and convenient form, but neither of these properties can be easily measured. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Reviewable is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Reviewable);' @end{Syntax} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Reviewable)} @PDefn2{Term=[pragma, configuration], Sec=(Reviewable)} Pragma Reviewable is a configuration pragma. It applies to all @nt[compilation_unit]s included in a partition. @end{LinkTime} @begin{ImplReq} @Leading@;The implementation shall provide the following information for any compilation unit to which such a pragma applies: @begin{Discussion} The list of requirements can be checked for, even if issues like intelligibility are not addressed. @end{Discussion} @begin{itemize} Where compiler-generated run-time checks remain; @begin{Discussion} A constraint check which is implemented via a check on the upper and lower bound should clearly be indicated. If a check is implicit in the form of machine instructions used (such an overflow checking), this should also be covered by the documentation. It is particularly important to cover those checks which are not obvious from the source code, such as that for stack overflow. @end{Discussion} An identification of any construct with a language-defined check that is recognized prior to run time as certain to fail if executed (even if the generation of run-time checks has been suppressed); @begin{Discussion} In this case, if the compiler determines that a check must fail, the user should be informed of this. However, since it is not in general possible to know what the compiler will detect, it is not easy to test for this. In practice, it is thought that compilers claiming conformity to this Annex will perform significant optimizations and therefore @i{will} detect such situations. Of course, such events could well indicate a programmer error. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00209-01]} For each @Chg{Version=[2],New=[read of],Old=[reference to]} a scalar object, an identification of the @Chg{Version=[2],New=[read],Old=[reference]} as either @lquotes@;known to be initialized,@rquotes@; or @lquotes@;possibly uninitialized,@rquotes@; independent of whether pragma Normalize_Scalars applies; @begin{Discussion} This issue again raises the question as to what the compiler has determined. A lazy implementation could clearly mark all scalars as @lquotes@;possibly uninitialized@rquotes@;, but this would be very unhelpful to the user. It should be possible to analyze a range of scalar uses and note the percentage in each class. Note that an access marked @lquotes@;known to be initialized@rquotes@; does not imply that the value is in range, since the initialization could be from an (erroneous) call of unchecked conversion, or by means external to the Ada program. @end{Discussion} Where run-time support routines are implicitly invoked; @begin{Discussion} Validators will need to know the calls invoked in order to check for the correct functionality. For instance, for some safety applications, it may be necessary to ensure that certain sections of code can execute in a particular time. @end{Discussion} @Leading@Keepnext@;An object code listing, including: @begin{inneritemize} Machine instructions, with relative offsets; @begin{Discussion} The machine instructions should be in a format that is easily understood, such as the symbolic format of the assembler. The relative offsets are needed in numeric format, to check any alignment restrictions that the architecture might impose. @end{Discussion} Where each data object is stored during its lifetime; @begin{Discussion} This requirement implies that if the optimizer assigns a variable to a register, this needs to be evident. @end{Discussion} Correspondence with the source program, including an identification of the code produced per declaration and per statement. @begin{Discussion} This correspondence will be quite complex when extensive optimization is performed. In particular, address calculation to access some data structures could be moved from the actual access. However, when all the machine code arising from a statement or declaration is in one basic block, this must be indicated by the implementation. @end{Discussion} @end{inneritemize} An identification of each construct for which the implementation detects the possibility of erroneous execution; @begin{Discussion} This requirement is quite vague. In general, it is hard for compilers to detect erroneous execution and therefore the requirement will be rarely invoked. However, if the pragma Suppress is used and the compiler can show that a predefined exception will be raised, then such an identification would be useful. @end{Discussion} @Trailing@;For each subprogram, block, task, or other construct implemented by reserving and subsequently freeing an area on a run-time stack, an identification of the length of the fixed-size portion of the area and an indication of whether the non-fixed size portion is reserved on the stack or in a dynamically-managed storage region. @begin{Discussion} This requirement is vital for those requiring to show that the storage available to a program is sufficient. This is crucial in those cases in which the internal checks for stack overflow are suppressed (perhaps by @key[pragma] Restrictions(No_Exceptions)). @end{Discussion} @end{itemize} @Leading@;The implementation shall provide the following information for any partition to which the pragma applies: @begin{Itemize} An object code listing of the entire partition, including initialization and finalization code as well as run-time system components, and with an identification of those instructions and data that will be relocated at load time; @begin{Discussion} The object code listing should enable a validator to estimate upper bounds for the time taken by critical parts of a program. Similarly, by an analysis of the entire partition, it should be possible to ensure that the storage requirements are suitably bounded, assuming that the partition was written in an appropriate manner.@end{discussion} A description of the run-time model relevant to the partition. @begin{Discussion} For example, a description of the storage model is vital, since the Ada language does not explicitly define such a model. @end{Discussion} @end{itemize} @end{ImplReq} @Chgnote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}The implementation shall provide control- and data-flow information, both within each compilation unit and across the compilation units of the partition. @begin{Discussion} This requirement is quite vague, since it is unclear what control and data flow information the compiler has produced. It is really a plea not to throw away information that could be useful to the validator. Note that the data flow information is relevant to the detection of @lquotes@;possibly uninitialized@rquotes@; objects referred to above. @end{Discussion} @begin{ImplAdvice} The implementation should provide the above information in both a human-readable and machine-readable form, and should document the latter so as to ease further processing by automated tools. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The information produced by @nt{pragma} Reviewable should be provided in both a human-readable and machine-readable form, and the latter form should be documented.]}]} Object code listings should be provided both in a symbolic format and also in an appropriate numeric format (such as hexadecimal or octal). @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Object code listings should be provided both in a symbolic format and in a numeric format.]}]} @begin{Reason} This is to enable other tools to perform any analysis that the user needed to aid validation. The format should be in some agreed form. @end{Reason} @end{ImplAdvice} @begin{Notes} The order of elaboration of library units will be documented even in the absence of @nt[pragma] Reviewable (see @RefSecNum{Program Execution}). @end{Notes} @begin[discussion] There might be some interactions between pragma Reviewable and compiler optimizations. For example, an implementation may disable some optimizations when pragma Reviewable is in force if it would be overly complicated to provide the detailed information to allow review of the optimized object code. See also @nt<pragma> Optimize (@RefSecNum{Pragmas}). @end[discussion] @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00209-01]} @ChgAdded{Version=[2],Text=[The wording was clarified that pragma Reviewable applies to each read of an object, as it makes no sense to talk about the state of an object that will immediately be overwritten.]} @end{DiffWord95} @LabeledSubClause{Pragma Inspection_Point} @begin{Intro} An occurrence of a pragma Inspection_Point identifies a set of objects each of whose values is to be available at the point(s) during program execution corresponding to the position of the pragma in the compilation unit. The purpose of such a pragma is to facilitate code validation. @begin{Discussion} Inspection points are a high level equivalent of break points used by debuggers. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Inspection_Point is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Inspection_Point)[(@SynI{object_}@Syn2{name} {, @SynI{object_}@Syn2{name}})];' @end{Syntax} @begin{Legality} A pragma Inspection_Point is allowed wherever a @nt[declarative_item] or @nt[statement] is allowed. Each @SynI{object_}name shall statically denote the declaration of an object. @begin{Discussion} The static denotation is required, since no dynamic evaluation of a name is involved in this pragma. @end{Discussion} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Defn{inspection point} An @i{inspection point} is a point in the object code corresponding to the occurrence of a pragma Inspection_@!Point in the compilation unit. @Defn{inspectable object} An object is @i{inspectable} at an inspection point if the corresponding pragma Inspection_Point either has an argument denoting that object, or has no arguments@Chg{New=[ and the @Chg{Version=[2],New=[declaration of the ],Old=[]}object is visible at the inspection point],Old=[]}. @begin{ramification} If a pragma Inspection_Point is in an in-lined subprogram, there might be numerous inspection points in the object code corresponding to the single occurrence of the pragma in the source; similar considerations apply if such a pragma is in a generic, or in a loop that has been @lquotes@;unrolled@rquotes@; by an optimizer. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgAdded{Version=[1],Text=[The short form of the pragma is a convenient shorthand for listing all objects which could be explicitly made inspectable by the long form of the pragma; thus only visible objects are made inspectable by it. Objects that are not visible at the point of the pragma are not made inspectable by the short form pragma. This is necessary so that implementations need not keep information about (or prevent optimizations on) a unit simply because some other unit @i<might> contain a short form Inspection_Point pragma.]} @end{ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0093],ARef=[AI95-00207-01]} If the short form of the pragma is used, then all@Chg{New=[ visible],Old=[]} objects are inspectable. This implies that @Chg{New=[global objects from other compilation units], Old=[objects out of scope at the point of the pragma]} are inspectable. A good interactive debugging system could provide information similar to a post-mortem dump at such inspection points. The annex does not require that any inspection facility is provided, merely that the information is available to understand the state of the machine at those points. @end{Discussion} @end{StaticSem} @begin{RunTime} Execution of a pragma Inspection_Point has no effect. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Although an inspection point has no (semantic) effect, the removal or adding @Chg{Version=[2],New=[of ],Old=[]}a new point could change the machine code generated by the compiler. @end{Discussion} @end{RunTime} @begin{ImplReq} Reaching an inspection point is an external interaction with respect to the values of the inspectable objects at that point (see @RefSecNum{Conformity of an Implementation with the Standard}). @begin{Ramification} The compiler is inhibited from moving an assignment to an inspectable variable past an inspection point for that variable. On the other hand, the evaluation of an expression that might raise an exception may be moved past an inspection point (see @RefSecNum[Exceptions and Optimization]).@end{ramification} @end{ImplReq} @begin{DocReq} For each inspection point, the implementation shall identify a mapping between each inspectable object and the machine resources (such as memory locations or registers) from which the object's value can be obtained. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of pragma Inspection_Point.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For each inspection point, a mapping between each inspectable object and the machine resources where the object's value can be obtained shall be provided.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00209-01]} The implementation is not allowed to perform @lquotes@;dead store elimination@rquotes@; on the last assignment to a variable prior to a point where the variable is inspectable. Thus an inspection point has the effect of an implicit @Chg{Version=[2],New=[read of],Old=[reference to]} each of its inspectable objects. Inspection points are useful in maintaining a correspondence between the state of the program in source code terms, and the machine state during the program's execution. Assertions about the values of program objects can be tested in machine terms at inspection points. Object code between inspection points can be processed by automated tools to verify programs mechanically. @begin{Discussion} Although it is not a requirement of the annex, it would be useful if the state of the stack and heap could be interrogated. This would allow users to check that a program did not have a `storage leak'. @end{Discussion} The identification of the mapping from source program objects to machine resources is allowed to be in the form of an annotated object listing, in human-readable or tool-processable form. @begin{Discussion} In principle, it is easy to check an implementation for this pragma, since one merely needs to check the content of objects against those values known from the source listing. In practice, one needs a tool similar to an interactive debugger to perform the check. @end{Discussion} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of the Inspection_Point pragma to apply to only variables visible at the point of the pragma. Otherwise, the compiler would have to assume that some other code somewhere could have a pragma Inspection_Point, preventing many optimizations (such as unused object elimination).]} @end{DiffWord95} @LabeledRevisedClause{Version=[2],New=[High Integrity Restrictions],Old=[Safety and Security Restrictions]} @begin{Intro} This clause defines restrictions that can be used with pragma Restrictions (see @RefSecNum(Pragma Restrictions)); these facilitate the demonstration of program correctness by allowing tailored versions of the run-time system. @begin{Discussion} Note that the restrictions are absolute. If a partition has 100 library units and just one needs Unchecked_Conversion, then the pragma cannot be used to ensure the other 99 units do not use Unchecked_Conversion. Note also that these are restrictions on all Ada code within a partition, and therefore it may not be evident from the specification of a package whether a restriction can be imposed. @end{Discussion} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00347-01],ARef=[AI95-00394-01]} @ChgDeleted{Version=[2],Text=[The following restrictions, the same as in @RefSecNum{Tasking Restrictions}, apply in this Annex: No_Task_@!Hierarchy, No_Abort_@!Statement, No_Implicit_@!Heap_@!Allocation, Max_@!Task_@!Entries is 0, Max_@!Asynchronous_@!Select_@!Nesting is 0, and Max_@!Tasks is 0. @redundant[The last three restrictions are checked prior to program execution.]]} @Trailing@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00394-01]} The following @Chg{Version=[2],New=[@SynI{restriction_}@nt{identifier}s are language defined:],Old=[additional restrictions apply in this Annex.]} @leading@keepnext@b{Tasking-related restriction:} @begin{Description} @Trailing@;@Defn2{Term=[Restrictions],Sec=(No_Protected_Types)}No_Protected_Types @\There are no declarations of protected types or protected objects. @end{Description} @leading@keepnext@b{Memory-management related restrictions:} @begin{Description} @Defn2{Term=[Restrictions],Sec=(No_Allocators)}No_Allocators @\There are no occurrences of an @nt{allocator}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0042],ARef=[AI95-00130]} @Defn2{Term=[Restrictions],Sec=(No_Local_Allocators)}No_Local_Allocators @\@nt{Allocator}s are prohibited in subprograms, generic subprograms, tasks, and entry bodies@Chg{New=[],Old=[; instantiations of generic packages are also prohibited in these contexts]}. @begin[Ramification] Thus @nt{allocator}s are permitted only in expressions whose evaluation can only be performed before the main subprogram is invoked. @end[Ramification] @begin[Reason] @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0042],ARef=[AI95-00130]} @ChgNote{The associated rule has been deleted.} @ChgDeleted{Version=[1],Text=[The reason for the prohibition against instantiations of generic packages is to avoid contract model violations. An alternative would be to prohibit @nt{allocator}s from generic packages, but it seems preferable to allow generality on the defining side and then place the restrictions on the usage (instantiation), rather than inhibiting what can be in the generic while liberalizing where they can be instantiated.]} @end[Reason] @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00394-01]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Deallocation)}No_Unchecked_Deallocation @\Semantic dependence on Unchecked_Deallocation is not allowed.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[This restriction would be useful in those contexts in which heap storage is needed on program start-up, but need not be increased subsequently. The danger of a dangling pointer can therefore be avoided.]} @end{Discussion} @Trailing@;Immediate_Reclamation @\Except for storage occupied by objects created by @nt{allocator}s and not deallocated via unchecked deallocation, any storage reserved at run time for an object is immediately reclaimed when the object no longer exists. @Defn2{Term=[Restrictions],Sec=(Immediate_Reclamation)} @begin{Discussion} Immediate reclamation would apply to storage created by the compiler, such as for a return value from a function whose size is not known at the call site. @end{Discussion} @end{Description} @leading@keepnext@b{Exception-related restriction:} @begin{Description} @Trailing@Defn2{Term=[Restrictions],Sec=(No_Exceptions)}No_Exceptions @\@nt{Raise_statement}s and @nt{exception_handler}s are not allowed. No language-defined run-time checks are generated; however, a run-time check performed automatically by the hardware is permitted. @begin{Discussion} This restriction mirrors a method of working that is quite common in the safety area. The programmer is required to show that exceptions cannot be raised. Then a simplified run-time system is used without exception handling. However, some hardware checks may still be enforced. If the software check would have failed, or if the hardware check actually fails, then the execution of the program is unpredictable. There are obvious dangers in this approach, but it is similar to programming at the assembler level. @end{Discussion} @end{Description} @leading@keepnext@b{Other restrictions:} @begin{Description} @Defn2{Term=[Restrictions],Sec=(No_Floating_Point)}No_Floating_Point @\Uses of predefined floating point types and operations, and declarations of new floating point types, are not allowed. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The intention is to avoid the use of floating point hardware at run time, but this is expressed in language terms. It is conceivable that floating point is used implicitly in some contexts, say fixed point type conversions of high accuracy. However, the @ImplReqTitle below make it clear that the restriction would apply to the @lquotes@;run-time system@rquotes@; and hence not be allowed. This @Chg{Version=[2],New=[restriction],Old=[parameter]} could be used to inform a compiler that a variant of the architecture is being used which does not have floating point instructions. @end{Discussion} @Defn2{Term=[Restrictions],Sec=(No_Fixed_Point)}No_Fixed_Point @\Uses of predefined fixed point types and operations, and declarations of new fixed point types, are not allowed. @begin{Discussion} This restriction would have the side-effect of prohibiting the @nt{delay_relative_statement}. As with the No_Floating_Point restriction, this might be used to avoid any question of rounding errors. Unless an Ada run-time is written in Ada, it seems hard to rule out implicit use of fixed point, since at the machine level, fixed point is virtually the same as integer arithmetic. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00394-01]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Conversion)}No_Unchecked_Conversion @\Semantic dependence on the predefined generic Unchecked_Conversion is not allowed.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Most critical applications would require some restrictions or additional validation checks on uses of unchecked conversion. If the application does not require the functionality, then this restriction provides a means of ensuring the design requirement has been satisfied. The same applies to several of the following restrictions.]} @end{Discussion} No_Access_Subprograms @\The declaration of access-to-subprogram types is not allowed. @Defn2{Term=[Restrictions],Sec=(No_Access_Subprograms)} @begin{Discussion}@ChgNote{Moved from above} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Most critical applications would require some restrictions or additional validation checks on uses of access-to-subprogram types. If the application does not require the functionality, then this restriction provides a means of ensuring the design requirement has been satisfied. The same applies to several of the following restrictions, and to restriction No_Dependence => Ada.Unchecked_Conversion.]} @end{Discussion} @Defn2{Term=[Restrictions],Sec=(No_Unchecked_Access)}No_Unchecked_Access @\The @attr[Unchecked_Access] attribute is not allowed. @Defn2{Term=[Restrictions],Sec=(No_Dispatch)}No_Dispatch @\Occurrences of T'Class are not allowed, for any (tagged) subtype T. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn2{Term=[Restrictions],Sec=(No_IO)}No_IO @\Semantic dependence on any of the library units Sequential_IO, Direct_IO, Text_IO, Wide_Text_IO, @Chg{Version=[2], New=[Wide_Wide_Text_IO, ],Old=[]}or Stream_IO is not allowed. @begin{Discussion} Excluding the input-output facilities of an implementation may be needed in those environments which cannot support the supplied functionality. A program in such an environment is likely to require some low level facilities or a call on a non-Ada feature. @end{Discussion} @Defn2{Term=[Restrictions],Sec=(No_Delay)}No_Delay @\@nt[Delay_Statement]s and semantic dependence on package Calendar are not allowed. @begin[Ramification] This implies that @nt[delay_alternative]s in a @nt[select_statement] are prohibited. The purpose of this restriction is to avoid the need for timing facilities within the run-time system. @end[ramification] @Defn2{Term=[Restrictions],Sec=(No_Recursion)}No_Recursion @\As part of the execution of a subprogram, the same subprogram is not invoked. @Defn2{Term=[Restrictions],Sec=(No_Reentrancy)}No_Reentrancy @\During the execution of a subprogram by a task, no other task invokes the same subprogram. @end{description} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[An implementation of this Annex shall support:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the restrictions defined in this subclause; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the following restrictions defined in @RefSecNum{Tasking Restrictions}: No_Task_Hierarchy, No_Abort_Statement, No_Implicit_Heap_Allocation; and]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[the @key{pragma} Profile(Ravenscar); and]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[The reference to pragma Profile(Ravenscar) is intended to show that properly restricted tasking is appropriate for use in high integrity systems. The Ada 95 Annex seemed to suggest that tasking was inappropriate for such systems.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following uses of @SynI{restriction_parameter_}@nt{identifier}s defined in @RefSecNum{Tasking Restrictions}@Redundant[, which are checked prior to program execution]:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Task_Entries => 0,]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Asynchronous_Select_Nesting => 0, and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Tasks => 0.]} @end{InnerItemize} @end{Itemize} If an implementation supports @nt[pragma] Restrictions for a particular argument, then except for the restrictions No_Unchecked_Deallocation, No_Unchecked_Conversion, No_Access_Subprograms, and No_Unchecked_Access, the associated restriction applies to the run-time system. @begin[reason] Permission is granted for the run-time system to use the specified otherwise-restricted features, since the use of these features may simplify the run-time system by allowing more of it to be written in Ada. @end[reason] @begin{Discussion} The restrictions that are applied to the partition are also applied to the run-time system. For example, if No_Floating_Point is specified, then an implementation that uses floating point for implementing the delay statement (say) would require that No_Floating_Point is only used in conjunction with No_Delay. It is clearly important that restrictions are effective so that Max_Tasks=0 does imply that tasking is not used, even implicitly (for input-output, say). An implementation of tasking could be produced based upon a run-time system written in Ada in which the rendezvous was controlled by protected types. In this case, No_Protected_Types could only be used in conjunction with Max_Task_Entries=0. Other implementation dependencies could be envisaged. If the run-time system is not written in Ada, then the wording needs to be applied in an appropriate fashion. @end{Discussion} @end{ImplReq} @begin{DocReq} If a pragma Restrictions(No_Exceptions) is specified, the implementation shall document the effects of all constructs where language-defined checks are still performed automatically (for example, an overflow check performed by the processor). @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of pragma Restrictions.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ If a pragma Restrictions(No_Exceptions) is specified, the effects of all constructs where language-defined checks are still performed.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The documentation requirements here are quite difficult to satisfy. One method is to review the object code generated and determine the checks that are still present, either explicitly, or implicitly within the architecture. As another example from that of overflow, consider the question of @Chg{Version=[2],New=[dereferencing],Old=[deferencing]} a null pointer. This could be undertaken by a memory access trap when checks are performed. When checks are suppressed via the argument No_Exceptions, it would not be necessary to have the memory access trap mechanism enabled. @end{Discussion} @end{DocReq} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if pragma Restrictions(No_Exceptions) has been specified and the conditions arise under which a generated language-defined run-time check would fail. @begin{Discussion} The situation here is very similar to the application of pragma Suppress. Since users are removing some of the protection the language provides, they had better be careful! @end{Discussion} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if pragma Restrictions(No_Recursion) has been specified and a subprogram is invoked as part of its own execution, or if pragma Restrictions(No_Reentrancy) has been specified and during the execution of a subprogram by a task, another task invokes the same subprogram. @begin{Discussion} In practice, many implementations may not exploit the absence of recursion or need for reentrancy, in which case the program execution would be unaffected by the use of recursion or reentrancy, even though the program is still formally erroneous. @end{Discussion} @end{Erron} @ChgNote{I can't find any reason in the normative wording for this item; therefore I've removed it. The notes below (commented out anyway) refer only to a non-standard mode, which is irrelevant in the Standard.} @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Any restrictions on pragma Restrictions.]}]} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Uses of @Syni{restriction_parameter_}@nt{identifier} No_Dependence defined in @RefSecNum{Language-Defined Restrictions}: No_Dependence => Ada.@!Unchecked_@!Deallocation and No_Dependence => Ada.@!Unchecked_@!Conversion may be appropriate for high-integrity systems. Other uses of No_Dependence can also be appropriate for high-integrity systems.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The specific mention of these two uses is meant to replace the identifiers now banished to @RefSec{Dependence Restriction Identifiers}.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence => Ada.Unchecked_Deallocation would be useful in those contexts in which heap storage is needed on program start-up, but need not be increased subsequently. The danger of a dangling pointer can therefore be avoided.]}@ChgNote{Moved down from above.} @end{Discussion} @end{Notes} @begin{comment} @begin{Notes} The standard mode for pragma Restrictions is that a compilation unit (or a partition if at link time) is illegal if it makes use of a feature identified in the pragma. However, an implementation is allowed to have a mode of operation where it issues a warning message versus rejecting the unit or partition, and where the run-time system supplied for the partition includes support for the identified feature. An implementation need not independently support the restrictions identified above, but may instead require that if a particular restriction is identified in a @nt(pragma) Restrictions, then other restrictions (the exact set of which is implementation defined) need also to be identified. In such a case, if the additional restrictions are not specified in a @nt(pragma) Restrictions, and a unit or partition uses such a feature, the implementation should @begin{itemize} issue a warning that the pragma is being ignored (that is, the full RTS is being used), identify to the user the additional restrictions that need to be specified in the pragma in order to obtain the reduced RTS, and identify any constructs that would use any of the features so proscribed @end{itemize} @end{Notes} @end{comment} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} No_Local_Allocators no longer prohibits generic instantiations.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Wide_Wide_Text_IO (which is new) is added to the No_IO restriction.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[The title of this clause was changed to match the change to the Annex title. Pragma Profile(Ravenscar) is part of this annex.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence is used instead of special @i<restriction_>@nt<identifier>s. The old names are banished to Obsolescent Features (see @RefSecNum{Dependence Restriction Identifiers}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[The bizarre wording @lquotes@;apply in this Annex@rquotes (which no one quite can explain the meaning of) is banished.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Pragma Detect_Blocking]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[The following @nt{pragma} forces an implementation to detect potentially blocking operations within a protected operation.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Detect_Blocking is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Detect_Blocking>;']} @end{Syntax} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Detect_Blocking)} @PDefn2{Term=[pragma, configuration], Sec=(Detect_Blocking)} A @nt{pragma} Detect_Blocking is a configuration pragma.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An implementation is required to detect a potentially blocking operation within a protected operation, and to raise Program_Error (see @RefSecNum{Protected Subprograms and Protected Actions}).]} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An implementation is allowed to reject a @nt{compilation_unit} if a potentially blocking operation is present directly within an @nt{entry_body} or the body of a protected subprogram.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An operation that causes a task to be blocked within a foreign language domain is not defined to be potentially blocking, and need not be detected.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Pragma Detect_Blocking is new.]} @end{Extend95} @RMNewPage@Comment{For printed version of Ada 2007 RM} @LabeledAddedClause{Version=[2],Name=[Pragma Partition_Elaboration_Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[This clause defines a @nt{pragma} for user control over elaboration policy.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Partition_Elaboration_Policy is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@AddedPragmaSyn`Version=[2],@key{pragma} @prag<Partition_Elaboration_Policy> (@SynI<policy_>@Syn2<identifier>);']} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @SynI<policy_>@nt{identifier} shall be either Sequential, Concurrent or an implementation-defined identifier.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[Implementation-defined @SynI<policy_>@nt<identifier>s allowed in a @nt{pragma} Partition_Elaboration_Policy.],Old=[]}]} @end{SyntaxText} @end{Syntax} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Partition_Elaboration_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Partition_Elaboration_Policy)} A @nt{pragma} Partition_Elaboration_Policy is a configuration pragma. It specifies the elaboration policy for a partition. At most one elaboration policy shall be specified for a partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[If the Sequential policy is specified for a partition then pragma Restrictions (No_Task_Hierarchy) shall also be specified for the partition.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[Notwithstanding what this International Standard says elsewhere, this @nt{pragma} allows partition elaboration rules concerning task activation and interrupt attachment to be changed. If the @SynI{policy_}@nt{identifier} is Concurrent, or if there is no pragma Partition_Elaboration_Policy defined for the partition, then the rules defined elsewhere in this Standard apply.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the partition elaboration policy is Sequential, then task activation and interrupt attachment are performed in the following sequence of steps:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The activation of all library-level tasks and the attachment of interrupt handlers are deferred until all library units are elaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The interrupt handlers are attached by the environment task.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task is suspended while the library-level tasks are activated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task executes the main subprogram (if any) concurrently with these executing tasks.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If several dynamic interrupt handler attachments for the same interrupt are deferred, then the most recent call of Attach_Handler or Exchange_Handler determines which handler is attached.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If any deferred task activation fails, Tasking_Error is raised at the beginning of the sequence of statements of the body of the environment task prior to calling the main subprogram.]} @end{RunTime} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[If the partition elaboration policy is Sequential and the Environment task becomes permanently blocked during elaboration then the partition is deadlocked and it is recommended that the partition be immediately terminated.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the partition elaboration policy is Sequential and the Environment task becomes permanently blocked during elaboration then the partition should be immediately terminated.]}]} @end{ImplAdvice} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[If the partition elaboration policy is Sequential and any task activation fails then an implementation may immediately terminate the active partition to mitigate the hazard posed by continuing to execute with a subset of the tasks being active.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If any deferred task activation fails, the environment task is unable to handle the Tasking_Error exception and completes immediately. By contrast, if the partition elaboration policy is Concurrent, then this exception could be handled within a library unit.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Partition_Elaboration_Policy is new.]} @end{Extend95} ����������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/sp.mss���������������������������������������������������������������0000755�0001752�0001001�00000255643�12273462240�016606� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/sp.mss,v $ } @comment{ $Revision: 1.47 $ $Date: 2006/10/18 00:25:28 $ $Author: Randy $ } @Part(sysprog, Root="ada.mss") @Comment{$Date: 2006/10/18 00:25:28 $} @LabeledNormativeAnnex{Systems Programming} @begin{Intro} @Redundant[@Defn{systems programming} @Defn{low-level programming} @Defn{real-time systems} @Defn{embedded systems} @Defn{distributed systems} @Defn{information systems} The Systems Programming Annex specifies additional capabilities provided for low-level programming. These capabilities are also required in many real-time, embedded, distributed, and information systems.] @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Access to Machine Operations} @begin{Intro} @Redundant[This clause specifies rules regarding access to machine instructions from within an Ada program.] @ChgImplDef{Version=[2],Kind=[Revised],Text=[@Chg{Version=[2], New=[Implementation-defined intrinsic subprograms], Old=[Support for access to machine instructions]}.]} @end{Intro} @begin{ImplReq} @Defn{machine code insertion} The implementation shall support machine code insertions (see @RefSecNum{Machine Code Insertions}) or intrinsic subprograms (see @RefSecNum{Conformance Rules}) (or both). Implementation-defined attributes shall be provided to allow the use of Ada entities as operands. @end{ImplReq} @begin{ImplAdvice} The machine code or intrinsics support should allow access to all operations normally available to assembly language programmers for the target environment, including privileged instructions, if any. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The machine code or intrinsics support should allow access to all operations normally available to assembly language programmers for the target environment.]}]} @begin{Ramification} Of course, on a machine with protection, an attempt to execute a privileged instruction in user mode will probably trap. Nonetheless, we want implementations to provide access to them so that Ada can be used to write systems programs that run in privileged mode. @end{Ramification} @Defn{interface to assembly language} @Defn2{Term=[language], Sec=(interface to assembly)} @Defn{mixed-language programs} @Defn{assembly language} The interfacing pragmas (see @RefSecNum{Interface to Other Languages}) should support interface to assembler; the default assembler should be associated with the convention identifier Assembler. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Interface to assembler should be supported; the default assembler should be associated with the convention identifier Assembler.]}]} If an entity is exported to assembly language, then the implementation should allocate it at an addressable location, and should ensure that it is retained by the linking process, even if not otherwise referenced from the Ada code. The implementation should assume that any call to a machine code or assembler subprogram is allowed to read or update every object that is specified as exported. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an entity is exported to assembly language, then the implementation should allocate it at an addressable location even if not otherwise referenced from the Ada code. A call to a machine code or assembler subprogram should be treated as if it could read or update every object that is specified as exported.]}]} @end{ImplAdvice} @begin{DocReq} The implementation shall document the overhead associated with calling machine-code or intrinsic subprograms, as compared to a fully-inlined call, and to a regular out-of-line call. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The overhead of calling machine-code or intrinsic subprograms.]}]} The implementation shall document the types of the package System.Machine_Code usable for machine code insertions, and the attributes to be used in machine code insertions for references to Ada entities. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The types and attributes used in machine code insertions.]}]} The implementation shall document the subprogram calling conventions associated with the convention identifiers available for use with the interfacing pragmas (Ada and Assembler, at a minimum), including register saving, exception propagation, parameter passing, and function value returning. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The subprogram calling conventions for all supported convention identifiers.]}]} For exported and imported subprograms, the implementation shall document the mapping between the Link_Name string, if specified, or the Ada designator, if not, and the external link name used for such a subprogram. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of access to machine operations.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The mapping between the Link_Name or Ada designator and the external link name.]}]} @end{DocReq} @begin{ImplAdvice} The implementation should ensure that little or no overhead is associated with calling intrinsic and machine-code subprograms. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Little or no overhead should be associated with calling intrinsic and machine-code subprograms.]}]} @Leading@;It is recommended that intrinsic subprograms be provided for convenient access to any machine operations that provide special capabilities or efficiency and that are not otherwise available through the language constructs. Examples of such instructions include: @begin{itemize} Atomic read-modify-write operations @em e.g., test and set, compare and swap, decrement and test, enqueue/dequeue. Standard numeric functions @em e.g., @i{sin}, @i{log}. String manipulation operations @em e.g., translate and test. Vector operations @em e.g., compare vector against thresholds. Direct operations on I/O ports. @end{itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Intrinsic subprograms should be provided to access any machine operations that provide special capabilities or efficiency not normally available.]}]} @end{ImplAdvice} @LabeledClause{Required Representation Support} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} This clause specifies minimal requirements on the @Chg{Version=[2],New=[],Old=[implementation's ]}support for representation items and related features. @end{Intro} @begin{ImplReq} @PDefn2{Term=[recommended level of support], Sec=(required in Systems Programming Annex)} The implementation shall support at least the functionality defined by the recommended levels of support in Section 13. @end{ImplReq} @LabeledClause{Interrupt Support} @begin{Intro} @Redundant[This clause specifies the language-defined model for hardware interrupts in addition to mechanisms for handling interrupts.] @IndexSee{Term=[signal],See=(interrupt)} @end{Intro} @begin{RunTime} @Defn{interrupt} @Redundant[An @i{interrupt} represents a class of events that are detected by the hardware or the system software.] @Defn2{Term=[occurrence], Sec=(of an interrupt)} Interrupts are said to occur. An @i{occurrence} of an interrupt is separable into generation and delivery. @Defn2{Term=[generation], Sec=(of an interrupt)} @i{Generation} of an interrupt is the event in the underlying hardware or system that makes the interrupt available to the program. @Defn2{Term=[delivery], Sec=(of an interrupt)} @i{Delivery} is the action that invokes part of the program as response to the interrupt occurrence. @Defn{pending interrupt occurrence} Between generation and delivery, the interrupt occurrence @Redundant[(or interrupt)] is @i{pending}. @Defn{blocked interrupt} Some or all interrupts may be @i{blocked}. When an interrupt is blocked, all occurrences of that interrupt are prevented from being delivered. @Defn2{Term=[attaching], Sec=(to an interrupt)} @Defn{reserved interrupt} Certain interrupts are @i{reserved}. The set of reserved interrupts is implementation defined. A reserved interrupt is either an interrupt for which user-defined handlers are not supported, or one which already has an attached handler by some other implementation-defined means. @Defn{interrupt handler}@PDefn2{Term=[handler],Sec=[interrupt]} Program units can be connected to non-reserved interrupts. While connected, the program unit is said to be @i{attached} to that interrupt. The execution of that program unit, the @i{interrupt handler}, is invoked upon delivery of the interrupt occurrence. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of interrupts.]}]} @begin{Honest} As an obsolescent feature, interrupts may be attached to task entries by an address clause. See @RefSecNum{Interrupt Entries}. @end{Honest} While a handler is attached to an interrupt, it is called once for each delivered occurrence of that interrupt. While the handler executes, the corresponding interrupt is blocked. While an interrupt is blocked, all occurrences of that interrupt are prevented from being delivered. Whether such occurrences remain pending or are lost is implementation defined. @Defn{default treatment} Each interrupt has a @i{default treatment} which determines the system's response to an occurrence of that interrupt when no user-defined handler is attached. The set of possible default treatments is implementation defined, as is the method (if one exists) for configuring the default treatments for interrupts. An interrupt is delivered to the handler (or default treatment) that is in effect for that interrupt at the time of delivery. An exception propagated from a handler that is invoked by an interrupt has no effect. @Redundant[If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect, the interrupt handler executes with the active priority that is the ceiling priority of the corresponding protected object.] @end{RunTime} @begin{ImplReq} The implementation shall provide a mechanism to determine the minimum stack space that is needed for each interrupt handler and to reserve that space for the execution of the handler. @Redundant{This space should accommodate nested invocations of the handler where the system permits this.} If the hardware or the underlying system holds pending interrupt occurrences, the implementation shall provide for later delivery of these occurrences to the program. If the Ceiling_Locking policy is not in effect, the implementation shall provide means for the application to specify whether interrupts are to be blocked during protected actions. @end{ImplReq} @begin{DocReq} @Leading@;The implementation shall document the following items: @begin{Discussion} This information may be different for different forms of interrupt handlers. @end{Discussion} @begin{Enumerate} For each interrupt, which interrupts are blocked from delivery when a handler attached to that interrupt executes (either as a result of an interrupt delivery or of an ordinary call on a procedure of the corresponding protected object). Any interrupts that cannot be blocked, and the effect of attaching handlers to such interrupts, if this is permitted. Which run-time stack an interrupt handler uses when it executes as a result of an interrupt delivery; if this is configurable, what is the mechanism to do so; how to specify how much space to reserve on that stack. Any implementation- or hardware-specific activity that happens before a user-defined interrupt handler gets control (e.g., reading device registers, acknowledging devices). Any timing or other limitations imposed on the execution of interrupt handlers. The state (blocked/unblocked) of the non-reserved interrupts when the program starts; if some interrupts are unblocked, what is the mechanism a program can use to protect itself before it can attach the corresponding handlers. Whether the interrupted task is allowed to resume execution before the interrupt handler returns. The treatment of interrupt occurrences that are generated while the interrupt is blocked; i.e., whether one or more occurrences are held for later delivery, or all are lost. Whether predefined or implementation-defined exceptions are raised as a result of the occurrence of any interrupt, and the mapping between the machine interrupts (or traps) and the predefined exceptions. On a multi-processor, the rules governing the delivery of an interrupt to a particular processor. @end{Enumerate} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The treatment of interrupts.]}]} @ChgNote{A Bob Duff explanation, but this is just too much junk.} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If the underlying system or hardware does not allow interrupts to be blocked, then no blocking is required @Redundant[as part of the execution of subprograms of a protected object @Chg{Version=[2],New=[for which],Old=[whose]} one of its subprograms is an interrupt handler]. In a multi-processor with more than one interrupt subsystem, it is implementation defined whether (and how) interrupt sources from separate subsystems share the same Interrupt_ID type (see @RefSecNum{The Package Interrupts}). In particular, the meaning of a blocked or pending interrupt may then be applicable to one processor only. @begin{discussion} This issue is tightly related to the issue of scheduling on a multi-processor. In a sense, if a particular interrupt source is not available to all processors, the system is not truly homogeneous. One way to approach this problem is to assign sub-ranges within Interrupt_ID to each interrupt subsystem, such that @lquotes@;similar@rquotes@; interrupt sources (e.g. a timer) in different subsystems get a distinct id. @end{Discussion} Implementations are allowed to impose timing or other limitations on the execution of interrupt handlers. @begin{Reason} These limitations are often necessary to ensure proper behavior of the implementation. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Other forms of handlers are allowed to be supported, in which case@Chg{Version=[2],New=[],Old=[,]} the rules of this @Chg{Version=[2],New=[clause],Old=[subclause]} should be adhered to. The active priority of the execution of an interrupt handler is allowed to vary from one occurrence of the same interrupt to another. @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If the Ceiling_Locking policy is not in effect, the implementation should provide means for the application to specify which interrupts are to be blocked during protected actions, if the underlying system allows for @Chg{Version=[2],New=[finer-grained],Old=[a finer-grain]} control of interrupt blocking. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the Ceiling_Locking policy is not in effect and the target system allows for finer-grained control of interrupt blocking, a means for the application to specify which interrupts are to be blocked during protected actions should be provided.]}]} @end{ImplAdvice} @begin{Notes} The default treatment for an interrupt can be to keep the interrupt pending or to deliver it to an implementation-defined handler. Examples of actions that an implementation-defined handler is allowed to perform include aborting the partition, ignoring (i.e., discarding occurrences of) the interrupt, or queuing one or more occurrences of the interrupt for possible later delivery when a user-defined handler is attached to that interrupt. It is a bounded error to call Task_Identification.Current_Task (see @RefSecNum{The Package Task_Identification}) from an interrupt handler. The rule that an exception propagated from an interrupt handler has no effect is modeled after the rule about exceptions propagated out of task bodies. @end{Notes} @LabeledSubClause{Protected Procedure Handlers} @begin{Syntax} @begin{SyntaxText} @Leading@keepnext@;The form of a @nt{pragma} Interrupt_Handler is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Interrupt_Handler)(@SynI{handler_}@Syn2{name});' @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Attach_Handler is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Attach_Handler)(@SynI{handler_}@Syn2{name}, @Syn2{expression});' @end{Syntax} @begin{Resolution} For the Interrupt_Handler and Attach_Handler pragmas, the @SynI{handler_}@nt{name} shall resolve to denote a protected procedure with a parameterless profile. For the Attach_Handler pragma, the expected type for the @nt{expression} is Interrupts.Interrupt_ID (see @RefSecNum{The Package Interrupts}). @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The Attach_Handler pragma is only allowed immediately within the @nt{protected_definition} where the corresponding subprogram is declared. The corresponding @nt{protected_@!type_@!declaration} or @nt{single_@!protected_@!declaration} shall be a library@Chg{Version=[2],New=[-],Old=[]}level declaration. @begin{Discussion} In the case of a @nt{protected_type_declaration}, an @nt{object_declaration} of an object of that type need not be at library level. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00253-01],ARef=[AI95-00303-01]} The Interrupt_Handler pragma is only allowed immediately within @Chg{Version=[2],New=[the],Old=[a]} @nt{protected_definition}@Chg{Version=[2],New=[ where the corresponding subprogram is declared],Old=[]}. The cor@!responding @nt{protected_@!type_declaration} @Chg{Version=[2],New=[or @nt{single_@!protected_@!declaration} ],Old=[]}shall be a library@Chg{Version=[2],New=[-],Old=[]}level declaration.@Chg{Version=[2],New=[],Old=[ In addition, any @nt{object_@!declaration} of such a type shall be a library level declaration.]} @end{Legality} @begin{RunTime} If the pragma Interrupt_Handler appears in a @nt{protected_definition}, then the corresponding procedure can be attached dynamically, as a handler, to interrupts (see @RefSecNum{The Package Interrupts}). @Redundant[Such procedures are allowed to be attached to multiple interrupts.] @Defn2{Term=[creation], Sec=(of a protected object)} @Defn2{Term=[initialization], Sec=(of a protected object)} The @nt{expression} in the Attach_Handler pragma @Redundant[as evaluated at object creation time] specifies an interrupt. As part of the initialization of that object, if the Attach_Handler pragma is specified, the @SynI{handler} procedure is attached to the specified interrupt. @IndexCheck{Reserved_Check} A check is made that the corresponding interrupt is not reserved. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the check fails, and the existing treatment for the interrupt is not affected. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Defn2{Term=[initialization], Sec=(of a protected object)} @IndexCheck{Ceiling_Check} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect@Chg{Version=[2],New=[,],Old=[]} then upon the initialization of a protected object @Chg{Version=[2],New=[for which],Old=[that]} either an Attach_Handler or Interrupt_Handler pragma applies to one of its procedures, a check is made that the ceiling priority defined in the @nt{protected_definition} is in the range of System.@!Interrupt_Priority. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the check fails, Program_Error is raised. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0068],ARef=[AI95-00121-01]} @Defn2{Term=[finalization], Sec=(of a protected object)} When a protected object is finalized, for any of its procedures that are attached to interrupts, the handler is detached. If the handler was attached by a procedure in the Interrupts package or if no user handler was previously attached to the interrupt, the default treatment is restored. @Chg{New=[If an Attach_@!Handler pragma was used and the most recently attached handler for the same interrupt is the same as the one that was attached at the time the protected object was initialized], Old=[Otherwise, @Redundant[that is, if an Attach_@!Handler pragma was used]]}, the previous handler is restored. @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00303-01]} @Chg{New=[If all protected objects for interrupt handlers are declared at the library@Chg{Version=[2],New=[ ],Old=[-]}level],Old=[Since only library-level protected procedures can be attached as handlers using the Interrupts package]}, the finalization discussed above occurs only as part of the finalization of all library-level packages in a partition. @Chg{New=[However, objects of a protected type containing an Attach_@!Handler pragma need not be at the library level. Thus, an implementation needs to be able to restore handlers during the execution of the program.@Chg{Version=[2], New=[ (An object with an Interrupt_@!Handler pragma also need not be at the library level, but such a handler cannot be attached to an interrupt using the Interrupts package.)], Old=[]}],Old=[]} @end{Discussion} When a handler is attached to an interrupt, the interrupt is blocked @Redundant[(subject to the @ImplPermName in @RefSecNum{Interrupt Support})] during the execution of every protected action on the protected object containing the handler. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect and an interrupt is delivered to a handler, and the interrupt hardware priority is higher than the ceiling priority of the corresponding protected object, the execution of the program is erroneous. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the handlers for a given interrupt attached via pragma Attach_Handler are not attached and detached in a stack-like (LIFO) order, program execution is erroneous. In particular, when a protected object is finalized, the execution is erroneous if any of the procedures of the protected object are attached to interrupts via pragma Attach_@!Handler and the most recently attached handler for the same interrupt is not the same as the one that was attached at the time the protected object was initialized.]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgAdded{Version=[1],Text=[This simplifies implementation of the Attach_@!Handler pragma by not requiring a check that the current handler is the same as the one attached by the initialization of a protected object.]} @end{Discussion} @end{Erron} @begin{Metrics} @Leading@Keepnext@;The following metric shall be documented by the implementation: @ChgNote{This was @begin{enumerate}, which is wrong} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The worst@Chg{Version=[2],New=[-],Old=[ ]}case overhead for an interrupt handler that is a parameterless protected procedure, in clock cycles. This is the execution time not directly attributable to the handler procedure or the interrupted execution. It is estimated as C @en@; (A+B), where A is how long it takes to complete a given sequence of instructions without any interrupt, B is how long it takes to complete a normal call to a given protected procedure, and C is how long it takes to complete the same sequence of instructions when it is interrupted by one execution of the same procedure called via an interrupt. @begin{ImplNote} The instruction sequence and interrupt handler used to measure interrupt handling overhead should be chosen so as to maximize the execution time cost due to cache misses. For example, if the processor has cache memory and the activity of an interrupt handler could invalidate the contents of cache memory, the handler should be written such that it invalidates all of the cache memory. @end{ImplNote} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for interrupt handlers.]}]} @ChgNote{This was @end{enumerate}, which is wrong} @end{Itemize} @end{Metrics} @begin{ImplPerm} When the pragmas Attach_Handler or Interrupt_Handler apply to a protected procedure, the implemen@!tation is allowed to impose implementation-defined restrictions on the corresponding @nt{protected_@!type_@!declaration} and @nt{protected_@!body}. @begin{Ramification} The restrictions may be on the constructs that are allowed within them, and on ordinary calls (i.e. not via interrupts) on protected operations in these protected objects. @end{Ramification} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2], New=[Any restrictions on a protected procedure or its containing type when a @nt{pragma} Attach_handler or Interrupt_Handler applies.],Old=[]}]} An implementation may use a different mechanism for invoking a protected procedure in response to a hardware interrupt than is used for a call to that protected procedure from a task. @begin{Discussion} This is despite the fact that the priority of an interrupt handler (see @RefSecNum{Task Priorities}) is modeled after a hardware task calling the handler. @end{Discussion} @Defn{notwithstanding} Notwithstanding what this subclause says elsewhere, the Attach_Handler and Interrupt_Handler pragmas are allowed to be used for other, implementation defined, forms of interrupt handlers. @begin{Ramification} For example, if an implementation wishes to allow interrupt handlers to have parameters, it is allowed to do so via these pragmas; it need not invent implementation-defined pragmas for the purpose. @end{Ramification} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2], New=[Any other forms of interrupt handler supported by the Attach_Handler and Interrupt_Handler pragmas.],Old=[]}]} @end{ImplPerm} @begin{ImplAdvice} Whenever possible, the implementation should allow interrupt handlers to be called directly by the hardware. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Interrupt handlers should be called directly by the hardware.]}]} Whenever practical, the implementation should detect violations of any implementation-defined restrictions before run time. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Violations of any implementation-defined restrictions on interrupt handlers should be detected before run time.]}]} @end{ImplAdvice} @begin{Notes} The Attach_Handler pragma can provide static attachment of handlers to interrupts if the implementation supports preelaboration of protected objects. (See @RefSecNum{Preelaboration Requirements}.) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Chg{Version=[2],New=[A],Old=[The ceiling priority of a]} protected object that @Chg{Version=[2],New=[has a (protected) procedure], Old=[one of its procedures is]} attached to an interrupt should @Chg{Version=[2],New=[have a ceiling priority], Old=[be]} at least as high as the highest processor priority at which that interrupt will ever be delivered. Protected procedures can also be attached dynamically to interrupts via operations declared in the predefined package Interrupts. An example of a possible implementation-defined restriction is disallowing the use of the standard storage pools within the body of a protected procedure that is an interrupt handler. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00253-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Corrected the wording so that the rules for the use of Attach_Handler and Interrupt_Handler are identical. This means that uses of pragma Interrupt_Handler outside of the target protected type or single protected object are now illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of @lquotes@;the previous handler@rquotes when finalizing protected objects containing interrupt handlers.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00303-01]} @ChgAdded{Version=[2],Text=[Dropped the requirement that an object of a type containing an Interrupt_Handler pragma must be declared at the library level. This was a generic contract model violation. This change is not an extension, as an attempt to attach such a handler with a routine in package Interrupts will fail an accessibility check anyway. Moreover, implementations can retain the rule as an implementation-defined restriction on the use of the type, as permitted by the @ImplPermTitle above.]} @end{Diffword95} @LabeledSubClause{The Package Interrupts} @begin{StaticSem} @Leading@Keepnext@;The following language-defined packages exist: @begin{example} @key{with} System;@ChildUnit{Parent=[Ada],Child=[Interrupts]} @key[package] Ada.Interrupts @key[is] @key[type] @AdaTypeDefn{Interrupt_ID} @key[is] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Parameterless_Handler} @key[is] @key[access] @key[protected] @key[procedure]; @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[function] @AdaSubDefn{Is_Reserved} (Interrupt : Interrupt_ID) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Attached} (Interrupt : Interrupt_ID) @key[return] Boolean; @key[function] @AdaSubDefn{Current_Handler} (Interrupt : Interrupt_ID) @key[return] Parameterless_Handler; @key[procedure] @AdaSubDefn{Attach_Handler} (New_Handler : @key[in] Parameterless_Handler; Interrupt : @key[in] Interrupt_ID); @key[procedure] @AdaSubDefn{Exchange_Handler} (Old_Handler : @key[out] Parameterless_Handler; New_Handler : @key[in] Parameterless_Handler; Interrupt : @key[in] Interrupt_ID); @key[procedure] @AdaSubDefn{Detach_Handler} (Interrupt : @key[in] Interrupt_ID); @key[function] @AdaSubDefn{Reference}(Interrupt : Interrupt_ID) @key{return} System.Address; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Interrupts; @key[package] Ada.Interrupts.Names @key[is]@ChildUnit{Parent=[Ada.Interrupts],Child=[Names]} @RI{implementation-defined} : @key[constant] Interrupt_ID := @RI{implementation-defined}; . . . @RI{implementation-defined} : @key[constant] Interrupt_ID := @RI{implementation-defined}; @key[end] Ada.Interrupts.Names; @end{example} @end{StaticSem} @begin{RunTime} The Interrupt_ID type is an implementation-defined discrete type used to identify interrupts. The Is_Reserved function returns True if and only if the specified interrupt is reserved. The Is_Attached function returns True if and only if a user-specified interrupt handler is attached to the interrupt. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0069],ARef=[AI95-00166-01]} The Current_Handler function returns a value that represents the attached handler of the interrupt. If no user-defined handler is attached to the interrupt, Current_Handler returns @Chg{New=[@key{null}], Old=[a value that designates the default treatment; calling Attach_Handler or Exchange_Handler with this value restores the default treatment]}. The Attach_Handler procedure attaches the specified handler to the interrupt, overriding any existing treatment (including a user handler) in effect for that interrupt. If New_Handler is @key[null], the default treatment is restored. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If New_Handler designates a protected procedure to which the pragma Interrupt_@!Handler does not apply, Program_Error is raised. In this case, the operation does not modify the existing interrupt treatment. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0069],ARef=[AI95-00166-01]} The Exchange_Handler procedure operates in the same manner as Attach_Handler with the addition that the value returned in Old_Handler designates the previous treatment for the specified interrupt.@Chg{New=[ If the previous treatment is not a user-defined handler, @key[null] is returned.],Old=[]} @begin{Ramification} Calling Attach_Handler or Exchange_Handler with this value for New_Handler restores the previous handler. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0069],ARef=[AI95-00166-01]} @ChgAdded{Version=[1],Text=[If the application uses only parameterless procedures as handlers (other types of handlers may be provided by the implementation, but are not required by the standard), then if Old_Handler is not @key(null), it may be called to execute the previous handler. This provides a way to cascade application interrupt handlers. However, the default handler cannot be cascaded this way (Old_Handler must be @key(null) for the default handler).]} @end{Ramification} The Detach_Handler procedure restores the default treatment for the specified interrupt. For all operations defined in this package that take a parameter of type Interrupt_ID, with the exception of Is_Reserved and Reference, a check is made that the specified interrupt is not reserved. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if this check fails. If, by using the Attach_Handler, Detach_Handler, or Exchange_Handler procedures, an attempt is made to detach a handler that was attached statically (using the pragma Attach_Handler), the handler is not detached and Program_Error is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The Reference function returns a value of type System.Address that can be used to attach a task entry@Chg{Version=[2],New=[],Old=[,]} via an address clause (see @RefSecNum{Interrupt Entries}) to the interrupt specified by Interrupt. This function raises Program_Error if attaching task entries to interrupts (or to this particular interrupt) is not supported. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @end{RunTime} @begin{ImplReq} At no time during attachment or exchange of handlers shall the current handler of the corresponding interrupt be undefined. @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect@Chg{Version=[2],New=[,],Old=[]} the implementation shall document the default ceiling priority assigned to a protected object that contains either the Attach_Handler or Interrupt_Handler pragmas, but not the Interrupt_Priority pragma. @Redundant[This default need not be the same for all interrupts.] @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the Ceiling_Locking policy is in effect, the default ceiling priority for a protected object that contains an interrupt handler pragma.]}]} @end{DocReq} @begin{ImplAdvice} If implementation-defined forms of interrupt handler procedures are supported, such as protected procedures with parameters, then for each such form of a handler, a type analogous to Parameterless_@!Handler should be specified in a child package of Interrupts, with the same operations as in the predefined package Interrupts. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If implementation-defined forms of interrupt handler procedures are supported, then for each such form of a handler, a type analogous to Parameterless_@!Handler should be specified in a child package of Interrupts, with the same operations as in the predefined package Interrupts.]}]} @end{ImplAdvice} @begin{Notes} The package Interrupts.Names contains implementation-defined names (and constant values) for the interrupts that are supported by the implementation. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of interrupt handlers:} @begin{example} Device_Priority : @key[constant] @key[array] (1..5) of System.Interrupt_Priority := ( ... );@Softpage @key[protected] @key[type] Device_Interface (Int_ID : Ada.Interrupts.Interrupt_ID) @key[is] @key[procedure] Handler; @key[pragma] Attach_Handler(Handler, Int_ID); ... @key[pragma] Interrupt_Priority(Device_Priority(Int_ID)); @key[end] Device_Interface;@Softpage ... Device_1_Driver : Device_Interface(1); ... Device_5_Driver : Device_Interface(5); ... @end{example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0069],ARef=[AI95-00166-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the value returned by Current_Handler and Exchange_Handler for the default treatment is null.]} @end{Diffword95} @LabeledClause{Preelaboration Requirements} @begin{Intro} @Redundant[This clause specifies additional implementation and documentation requirements for the Preelaborate pragma (see @RefSecNum{Elaboration Control}).] @end{Intro} @begin{ImplReq} The implementation shall not incur any run-time overhead for the elaboration checks of subprograms and @ntf{protected_bodies} declared in preelaborated library units. The implementation shall not execute any memory write operations after load time for the elaboration of constant objects declared immediately within the declarative region of a preelaborated library package, so long as the subtype and initial expression (or default initial expressions if initialized by default) of the @nt<object_declaration> satisfy the following restrictions. @Defn{load time} The meaning of @i{load time} is implementation defined. @begin{Discussion} On systems where the image of the partition is initially copied from disk to RAM, or from ROM to RAM, prior to starting execution of the partition, the intention is that @lquotes@;load time@rquotes@; consist of this initial copying step. On other systems, load time and run time might actually be interspersed. @end{Discussion} @begin{itemize} Any @nt<subtype_mark> denotes a statically constrained subtype, with statically constrained subcomponents, if any; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[no @nt{subtype_mark} denotes a controlled type, a private type, a private extension, a generic formal private type, a generic formal derived type, or a descendant of such a type;]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[For an implementation that uses the registration method of finalization, a controlled object will require some code executed to register the object at the appropriate point. The other types are those that @i{might} have a controlled component. None of these types were allowed in preelaborated units in Ada 95. These types are covered by the @ImplAdviceTitle, of course, so they should still execute as little code as possible.]} @end{Reason} any @nt<constraint> is a static constraint; any @nt<allocator> is for an access-to-constant type; any uses of predefined operators appear only within static expressions; any @ntf<primaries> that are @nt<name>s, other than @nt<attribute_reference>s for the Access or Address attributes, appear only within static expressions; @begin{ramification} This cuts out @nt<attribute_reference>s that are not static, except for Access and Address. @end{Ramification} any @nt<name> that is not part of a static expression is an expanded name or @nt<direct_name> that statically denotes some entity; @begin{Ramification} This cuts out @nt<function_call>s and @nt<type_conversion>s that are not static, including calls on attribute functions like 'Image and 'Value. @end{Ramification} any @nt<discrete_choice> of an @nt<array_aggregate> is static; no language-defined check associated with the elaboration of the @nt<object_declaration> can fail. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The intent is that aggregates all of whose scalar subcomponents are static@Chg{Version=[2],New=[],Old=[,]} and all of whose access subcomponents are @key(null), allocators for access-to-constant types, or X'Access, will be supported with no run-time code generated. @end{Reason} @end{itemize} @end{ImplReq} @begin{DocReq} The implementation shall document any circumstances under which the elaboration of a preelaborated package causes code to be executed at run time. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Any circumstances when the elaboration of a preelaborated package causes code to be executed.]}]} The implementation shall document whether the method used for initialization of preelaborated variables allows a partition to be restarted without reloading. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Whether a partition can be restarted without reloading.]}]} @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of preelaboration.]}]} @begin{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This covers the issue of the @Chg{Version=[2],New=[run-time system],Old=[RTS]} itself being restartable, so that need not be a separate @DocReqName. @end{discussion} @end{DocReq} @begin{ImplAdvice} It is recommended that preelaborated packages be implemented in such a way that there should be little or no code executed at run time for the elaboration of entities not already covered by the @ImplReqName@;s. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Preelaborated packages should be implemented such that little or no code is executed at run time for the elaboration of entities.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[Added wording to exclude the additional kinds of types allowed in preelaborated units from the @ImplReqTitle.]} @end{DiffWord95} @LabeledClause{Pragma Discard_Names} @begin{Intro} @Redundant[A @nt{pragma} Discard_Names may be used to request a reduction in storage used for the names of certain entities.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Discard_Names is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Discard_Names)[([On => ] @Syn2[local_name])];' @begin{SyntaxText} A @nt{pragma} Discard_Names is allowed only immediately within a @nt{declarative_part}, immediately within a @nt{package_specification}, or as a configuration pragma. @PDefn2{Term=[configuration pragma], Sec=(Discard_Names)} @PDefn2{Term=[pragma, configuration], Sec=(Discard_Names)} @end{SyntaxText} @end{Syntax} @begin{Legality} The @nt{local_name} (if present) shall denote a non-derived enumeration @Redundant[first] subtype, a tagged @Redundant[first] subtype, or an exception. The pragma applies to the type or exception. Without a @nt{local_name}, the pragma applies to all such entities declared after the pragma, within the same declarative region. Alternatively, the pragma can be used as a configuration pragma. If the pragma applies to a type, then it applies also to all descendants of the type. @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Discard_Names)} @PDefn2{Term=[pragma, representation], Sec=(Discard_Names)} If a @nt{local_name} is given, then a @nt{pragma} Discard_Names is a representation pragma. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00400-01]} If the pragma applies to an enumeration type, then the semantics of the @Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and @Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} attributes are implementation defined for that type@Redundant[; the semantics of Image@Chg{Version=[2],New=[, Wide_Image,],Old=[ and]} Value@Chg{Version=[2],New=[, and Wide_Value],Old=[]} are still defined in terms of @Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and @Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]}]. In addition, the semantics of Text_IO.Enumeration_IO are implementation defined. If the pragma applies to a tagged type, then the semantics of the Tags.@!@Chg{Version=[2],New=[Wide_Wide_@!Expanded_@!Name], Old=[Expanded_@!Name]} function are implementation defined for that type@Chg{Version=[2],New=[@Redundant[; the semantics of Tags.@!Expanded_@!Name and Tags.@!Wide_@!Expanded_@!Name are still defined in terms of Tags.@!Wide_Wide_@!Expanded_@!Name]], Old=[]}. If the pragma applies to an exception, then the semantics of the Exceptions.@!@Chg{Version=[2],New=[Wide_Wide_@!Exception_@!Name], Old=[Exception_@!Name]} function are implementation defined for that exception@Chg{Version=[2],New=[@Redundant[; the semantics of Exceptions.@!Exception_@!Name and Exceptions.@!Wide_@!Exception_@!Name are still defined in terms of Exceptions.@!Wide_Wide_@!Exception_@!Name]], Old=[]}. @ImplDef{The semantics of pragma Discard_Names.} @begin{Ramification} The Width attribute is still defined in terms of Image. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The semantics of S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} are implementation defined for any subtype of an enumeration type to which the pragma applies. (The pragma actually names the first subtype, of course.) @end{Ramification} @end{StaticSem} @begin{ImplAdvice} If the pragma applies to an entity, then the implementation should reduce the amount of storage used for storing names associated with that entity. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If @nt{pragma} Discard_Names applies to an entity, then the amount of storage used for storing names associated with that entity should be reduced.]}]} @begin{Reason} A typical implementation of the Image attribute for enumeration types is to store a table containing the names of all the enumeration literals. Pragma Discard_Names allows the implementation to avoid storing such a table without having to prove that the Image attribute is never used (which can be difficult in the presence of separate compilation). We did not specify the semantics of the Image attribute in the presence of this pragma because different semantics might be desirable in different situations. In some cases, it might make sense to use the Image attribute to print out a useful value that can be used to identify the entity given information in compiler-generated listings. In other cases, it might make sense to get an error at compile time or at run time. In cases where memory is plentiful, the simplest implementation makes sense: ignore the pragma. Implementations that are capable of avoiding the extra storage in cases where the Image attribute is never used might also wish to ignore the pragma. The same applies to the Tags.Expanded_Name and Exceptions.Exception_Name functions. @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect that the double wide image and value functions are now the master versions that the others are defined from.]} @end{DiffWord95} @LabeledClause{Shared Variable Control} @begin{Intro} @Redundant[This clause specifies representation pragmas that control the use of shared variables.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@;The form for pragmas Atomic, Volatile, Atomic_Components, and Volatile_Components is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Atomic)(@Syn2{local_name});' @PragmaSyn`@key{pragma} @prag(Volatile)(@Syn2{local_name});' @PragmaSyn`@key{pragma} @prag(Atomic_Components)(@SynI{array_}@Syn2{local_name});' @PragmaSyn`@key{pragma} @prag(Volatile_Components)(@SynI{array_}@Syn2{local_name});' @end{Syntax} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00272-01]} @Defn{atomic} An @i{atomic} type is one to which a pragma Atomic applies. An @i{atomic} object (including a component) is one to which a pragma Atomic applies, or a component of an array to which a pragma Atomic_Components applies, or any object of an atomic type@Chg{Version=[2], New=[, other than objects obtained by evaluating a slice],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00272-01]} @ChgAdded{Version=[2],Text=[A slice of an atomic array object is not itself atomic. That's necessary as executing a read or write of a dynamic number of components in a single instruction is not possible on many targets.]} @end{Ramification} @Defn{volatile} A @i{volatile} type is one to which a pragma Volatile applies. A @i{volatile} object (including a component) is one to which a pragma Volatile applies, or a component of an array to which a pragma Volatile_@!Components applies, or any object of a volatile type. In addition, every atomic type or object is also defined to be volatile. Finally, if an object is volatile, then so are all of its subcomponents @Redundant[(the same does not apply to atomic)]. @end{Intro} @begin{Resolution} The @nt{local_name} in an Atomic or Volatile pragma shall resolve to denote either an @nt{object_declaration}, a non-inherited @nt{component_@!declaration}, or a @nt{full_type_@!declaration}. The @SynI{array_}@nt{local_name} in an Atomic_@!Components or Volatile_@!Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type. @end{Resolution} @begin{Legality} @Defn{indivisible} It is illegal to apply either an Atomic or Atomic_Components pragma to an object or type if the implementation cannot support the indivisible reads and updates required by the pragma (see below). It is illegal to specify the Size attribute of an atomic object, the Component_Size attribute for an array type with atomic components, or the layout attributes of an atomic component, in a way that prevents the implementation from performing the required indivisible reads and updates. If an atomic object is passed as a parameter, then the type of the formal parameter shall either be atomic or allow pass by copy @Redundant[(that is, not be a nonatomic by-reference type)]. If an atomic object is used as an actual for a generic formal object of mode @key{in out}, then the type of the generic formal object shall be atomic. If the @nt<prefix> of an @nt<attribute_reference> for an Access attribute denotes an atomic object @Redundant[(including a component)], then the designated type of the resulting access type shall be atomic. If an atomic type is used as an actual for a generic formal derived type, then the ancestor of the formal type shall be atomic or allow pass by copy. Corresponding rules apply to volatile objects and types. If a pragma Volatile, Volatile_Components, Atomic, or Atomic_Components applies to a stand-alone constant object, then a pragma Import shall also apply to it. @begin{Ramification} Hence, no initialization expression is allowed for such a constant. Note that a constant that is atomic or volatile because of its type is allowed. @end{Ramification} @begin{Reason} Stand-alone constants that are explicitly specified as Atomic or Volatile only make sense if they are being manipulated outside the Ada program. From the Ada perspective the object is read-only. Nevertheless, if imported and atomic or volatile, the implementation should presume it might be altered externally. For an imported stand-alone constant that is not atomic or volatile, the implementation can assume that it will not be altered. @end{Reason} @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Atomic)} @PDefn2{Term=[pragma, representation], Sec=(Atomic)} @PDefn2{Term=[representation pragma], Sec=(Volatile)} @PDefn2{Term=[pragma, representation], Sec=(Volatile)} @PDefn2{Term=[representation pragma], Sec=(Atomic_Components)} @PDefn2{Term=[pragma, representation], Sec=(Atomic_Components)} @PDefn2{Term=[representation pragma], Sec=(Volatile_Components)} @PDefn2{Term=[pragma, representation], Sec=(Volatile_Components)} These @nt{pragma}s are representation pragmas (see @RefSecNum{Operational and Representation Items}). @end{StaticSem} @begin{RunTime} For an atomic object (including an atomic component) all reads and updates of the object as a whole are indivisible. For a volatile object all reads and updates of the object as a whole are performed directly to memory. @begin{ImplNote} This precludes any use of register temporaries, caches, and other similar optimizations for that object. @end{ImplNote} @Defn2{Term=[sequential], Sec=(actions)} Two actions are sequential (see @RefSecNum{Shared Variables}) if each is the read or update of the same atomic object. @PDefn2{Term=[by-reference type], Sec=(atomic or volatile)} If a type is atomic or volatile and it is not a by-copy type, then the type is defined to be a by-reference type. If any subcomponent of a type is atomic or volatile, then the type is defined to be a by-reference type. If an actual parameter is atomic or volatile, and the corresponding formal parameter is not, then the parameter is passed by copy. @begin{ImplNote} Note that in the case where such a parameter is normally passed by reference, a copy of the actual will have to be produced at the call-site, and a pointer to the copy passed to the formal parameter. If the actual is atomic, any copying has to use indivisible read on the way in, and indivisible write on the way out. @end{ImplNote} @begin{Reason} It has to be known at compile time whether an atomic or a volatile parameter is to be passed by copy or by reference. For some types, it is unspecified whether parameters are passed by copy or by reference. The above rules further specify the parameter passing rules involving atomic and volatile types and objects. @end{Reason} @end{RunTime} @begin{ImplReq} @PDefn2{Term=[external effect], Sec=(volatile/atomic objects)} The external effect of a program (see @RefSecNum(Conformity of an Implementation with the Standard)) is defined to include each read and update of a volatile or atomic object. The implementation shall not generate any memory reads or updates of atomic or volatile objects other than those specified by the program. @begin{Discussion} The presumption is that volatile or atomic objects might reside in an @lquotes@;active@rquotes@; part of the address space where each read has a potential side-effect, and at the very least might deliver a different value. @Leading@;The rule above and the definition of external effect are intended to prevent (at least) the following incorrect optimizations, where V is a volatile variable: @begin{itemize} X:= V; Y:=V; cannot be allowed to be translated as Y:=V; X:=V; Deleting redundant loads: X:= V; X:= V; shall read the value of V from memory twice. Deleting redundant stores: V:= X; V:= X; shall write into V twice. Extra stores: V:= X+Y; should not translate to something like V:= X; V:= V+Y; Extra loads: X:= V; Y:= X+Z; X:=X+B; should not translate to something like Y:= V+Z; X:= V+B; Reordering of loads from volatile variables: X:= V1; Y:= V2; (whether or not V1 = V2) should not translate to Y:= V2; X:= V1; Reordering of stores to volatile variables: V1:= X; V2:= X; should not translate to V2:=X; V1:= X; @end{itemize} @end{Discussion} If a pragma Pack applies to a type any of whose subcomponents are atomic, the implementation shall not pack the atomic subcomponents more tightly than that for which it can support indivisible reads and updates. @begin{ImplNote} A warning might be appropriate if no packing whatsoever can be achieved. @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[A load or store of a volatile object whose size is a multiple of System.Storage_Unit and whose alignment is nonzero, should be implemented by accessing exactly the bits of the object and no others.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A load or store of a volatile object whose size is a multiple of System.Storage_Unit and whose alignment is nonzero, should be implemented by accessing exactly the bits of the object and no others.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since any object can be a volatile object, including packed array components and bit-mapped record components, we require the above only when it is reasonable to assume that the machine can avoid accessing bits outside of the object.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies that the load or store of a volatile object that meets the above requirement should not be combined with that of any other object, nor should it access any bits not belonging to any other object. This means that the suitability of the implementation for memory-mapped I/O can be determined from its documentation, as any cases where the implementation does not follow @ImplAdviceTitle must be documented.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[A load or store of an atomic object should, where possible, be implemented by a single load or store instruction.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A load or store of an atomic object should be implemented by a single load or store instruction.]}]} @end{ImplAdvice} @begin{Notes} An imported volatile or atomic constant behaves as a constant (i.e. read-only) with respect to other parts of the Ada program, but can still be modified by an @lquotes@;external source.@rquotes@; @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Pragma Atomic replaces Ada 83's pragma Shared. The name @lquotes@;Shared@rquotes@; was confusing, because the pragma was not used to mark variables as shared. @end{Incompatible83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[Added @ImplAdviceTitle to clarify the meaning of Atomic and Volatile in machine terms. The documentation that this advice applies will make the use of Ada implementations more predictable for low-level (such as device register) programming.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00272-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that a slice of an object of an atomic type is not atomic, just like a component of an atomic type is not (necessarily) atomic.]} @end{Diffword95} @LabeledRevisedClause{Version=[2],New=[Task Information], Old=[Task Identification and Attributes]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00266-02]} @Redundant[This clause describes operations and attributes that can be used to obtain the identity of a task. In addition, a package that associates user-defined information with a task is defined.@Chg{Version=[2],New=[ Finally, a package that associates termination procedures with a task or set of tasks is defined.],Old=[]}] @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[The title and text here were updated to reflect the addition of task termination procedures to this clause.]} @end{DiffWord95} @LabeledSubClause{The Package Task_Identification} @begin{StaticSem} @Leading@Keepnext@;The following language-defined library package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[package] Ada.Task_Identification @key[is]@ChildUnit{Parent=[Ada],Child=[Task_Identification]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Task_Identification);],Old=[]} @key[type] @AdaTypeDefn{Task_Id} @key[is] @key{private};@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization (Task_Id);],Old=[]} @AdaSubDefn{Null_Task_Id} : @key{constant} Task_Id; @key{function} "=" (Left, Right : Task_Id) @key{return} Boolean; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0070],ARef=[AI95-00101-01]} @key{function} @AdaSubDefn{Image} (T : Task_Id) @key{return} String; @key[function] @AdaSubDefn{Current_Task} @key[return] Task_Id; @Key[procedure] @AdaSubDefn{Abort_Task} (T : @key[in] @Chg{New=[],Old=[@key[out] ]}Task_Id); @key[function] @AdaSubDefn{Is_Terminated}(T : Task_Id) @key{return} Boolean; @key[function] @AdaSubDefn{Is_Callable} (T : Task_Id) @key{return} Boolean; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Task_Identification; @end{example} @end{StaticSem} @begin{RunTime} A value of the type Task_Id identifies an existent task. The constant Null_Task_Id does not identify any task. Each object of the type Task_Id is default initialized to the value of Null_Task_Id. The function "=" returns True if and only if Left and Right identify the same task or both have the value Null_Task_Id. The function Image returns an implementation-defined string that identifies T. If T equals Null_Task_Id, Image returns an empty string. @ImplDef{The result of the Task_Identification.Image attribute.} The function Current_Task returns a value that identifies the calling task. The effect of Abort_Task is the same as the @nt{abort_statement} for the task identified by T. @Redundant[In addition, if T identifies the environment task, the entire partition is aborted, See @RefSecNum{Partitions}.] The functions Is_Terminated and Is_Callable return the value of the corresponding attribute of the task identified by T. @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0115],ARef=[AI95-00206-01]} @ChgAdded{Version=[1],Text=[These routines can be called with an argument identifying the environment task. Is_Terminated will always be False for such a call, but Is_Callable (usually True) could be False if the environment task is waiting for the termination of dependent tasks. Thus, a dependent task can use Is_Callable to determine if the main subprogram has completed.]} @end{Ramification} @Leading@;For @PrefixType{a @nt<prefix> T that is of a task type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<T>, AttrName=<Identity>, Text=[Yields a value of the type Task_Id that identifies the task denoted by T.]} @end{Description} @EndPrefixType{} @Leading@;For @PrefixType{a @nt<prefix> E that denotes an @nt<entry_declaration>}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<E>, AttrName=<Caller>, Text=[Yields a value of the type Task_Id that identifies the task whose call is now being serviced. Use of this attribute is allowed only inside an @nt{entry_body} or @nt{accept_statement} corresponding to the @nt{entry_declaration} denoted by E.]} @end{Description} @EndPrefixType{} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if a value of Null_Task_Id is passed as a parameter to Abort_Task, Is_Terminated, and Is_Callable. @PDefn2{Term=[potentially blocking operation],Sec=(Abort_Task)} @PDefn2{Term=[blocking, potentially],Sec=(Abort_Task)} Abort_Task is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call the Current_Task function from an entry body@Chg{Version=[2],New=[,],Old=[ or an]} interrupt handler@Chg{Version=[2], New=[, or finalization of a task attribute],Old=[]}. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised, or an implementation-defined value of the type Task_Id is returned. @ChgImplDef{Version=[2],Kind=[Revised],Text=[The value of Current_Task when in a protected entry@Chg{Version=[2],New=[,],Old=[ or]} interrupt handler@Chg{Version=[2], New=[, or finalization of a task attribute],Old=[]}.]} @begin{ImplNote} This value could be Null_Task_Id, or the ID of some user task, or that of an internal task created by the implementation. @end{ImplNote} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]}@Comment{This really should reference AI05-0004, but we don't have that yet. And that hasn't been approved, either} @ChgAdded{Version=[2],Text=[An entry barrier is syntactically part of an @nt{entry_body}, so a call to Current_Task from an entry barrier is also covered by this rule.]} @end{Ramification} @end{Bounded} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the operations declared in this package (or any language-defined child of this package), and the corresponding task object no longer exists, the execution of the program is erroneous. @end{Erron} @begin{DocReq} The implementation shall document the effect of calling Current_Task from an entry body or interrupt handler. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[The effect of calling Current_Task from an entry body or interrupt handler.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The effect of calling Current_Task from an entry body or interrupt handler.]}]} @end{DocReq} @begin{Notes} This package is intended for use in writing user-defined task scheduling packages and constructing server tasks. Current_Task can be used in conjunction with other operations requiring a task as an argument such as Set_Priority (see @RefSecNum{Dynamic Priorities}). The function Current_Task and the attribute Caller can return a Task_Id value that identifies the environment task. @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Task_Identification is now preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0070],ARef=[AI95-00101-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the mode of the parameter to Abort_Task to @key{in}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Corrected the wording to include finalization of a task attribute in the bounded error case; we don't want to specify which task does these operations.]} @end{Diffword95} @LabeledSubClause{The Package Task_Attributes} @begin{StaticSem} @Leading@Keepnext@;The following language-defined generic library package exists: @begin{example} @key{with} Ada.Task_Identification; @key{use} Ada.Task_Identification; @key{generic} @key{type} Attribute @key{is} @key{private}; Initial_Value : @key[in] Attribute; @key{package} Ada.Task_Attributes @key{is}@ChildUnit{Parent=[Ada],Child=[Task_Attributes]} @key{type} @AdaTypeDefn{Attribute_Handle} @key{is} @key{access} @key{all} Attribute; @key{function} @AdaSubDefn{Value}(T : Task_Id := Current_Task) @key{return} Attribute; @key{function} @AdaSubDefn{Reference}(T : Task_Id := Current_Task) @key{return} Attribute_Handle; @key{procedure} @AdaSubDefn{Set_Value}(Val : @key[in] Attribute; T : @key[in] Task_Id := Current_Task); @key{procedure} @AdaSubDefn{Reinitialize}(T : @key[in] Task_Id := Current_Task); @key{end} Ada.Task_Attributes; @end{example} @end{StaticSem} @begin{RunTime} When an instance of Task_Attributes is elaborated in a given active partition, an object of the actual type corresponding to the formal type Attribute is implicitly created for each task (of that partition) that exists and is not yet terminated. This object acts as a user-defined attribute of the task. A task created previously in the partition and not yet terminated has this attribute from that point on. Each task subsequently created in the partition will have this attribute when created. In all these cases, the initial value of the given attribute is Initial_Value. The Value operation returns the value of the corresponding attribute of T. The Reference operation returns an access value that designates the corresponding attribute of T. The Set_Value operation performs any finalization on the old value of the attribute of T and assigns Val to that attribute (see @RefSecNum{Assignment Statements} and @RefSecNum{User-Defined Assignment and Finalization}). The effect of the Reinitialize operation is the same as Set_Value where the Val parameter is replaced with Initial_Value. @begin{ImplNote} In most cases, the attribute memory can be reclaimed at this point. @end{ImplNote} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} For all the operations declared in this package, Tasking_Error is raised if the task identified by T is terminated. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the value of T is Null_Task_Id. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[After a task has terminated, all of its attributes are finalized, unless they have been finalized earlier. When the master of an instantiation of Ada.Task_Attributes is finalized, the corresponding attribute of each task is finalized, unless it has been finalized earlier.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is necessary so that a task attribute does not outlive its type. For instance, that's possible if the instantiation is nested, and the attribute is on a library-level task.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The task owning an attribute cannot, in general, finalize that attribute. That's because the attributes are finalized @i<after> the task is terminated; moreover, a task may have attributes as soon as it is created; the task may never even have been activated.]} @end{Ramification} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If the package Ada.Task_Attributes is instantiated with a controlled type and the controlled type has user-defined Adjust or Finalize operations that in turn access task attributes by any of the above operations, then a call of Set_Value of the instantiated package constitutes a bounded error. The call may perform as expected or may result in forever blocking the calling task and subsequently some or all tasks of the partition.]} @end{Bounded} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to dereference the access value returned by a given call on Reference after a subsequent call on Reinitialize for the same task attribute, or after the associated task terminates. @begin{Reason} This allows the storage to be reclaimed for the object associated with an attribute upon Reinitialize or task termination. @end{Reason} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the operations declared in this package and the corresponding task object no longer exists, the execution of the program is erroneous. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00237-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} @Chg{Version=[2],New=[An access],Old=[Accesses]} to @Chg{Version=[2],New=[a ],Old=[]}task @Chg{Version=[2],New=[attribute],Old=[attributes]} via a value of type Attribute_Handle @Chg{Version=[2],New=[is],Old=[are]} erroneous if executed concurrently with @Chg{Version=[2],New=[another such access], Old=[each other]} or @Chg{Version=[2],New=[a call],Old=[with calls]} of any of the operations declared in package Task_Attributes.@Chg{Version=[2],New=[ An access to a task attribute is erroneous if executed concurrently with or after the finalization of the task attribute.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[There is no requirement of atomicity on accesses via a value of type Attribute_Handle.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A task attribute can only be accessed after finalization through a value of type Attribute_Handle. Operations in package Task_Attributes cannot be used to access a task attribute after finalization, because either the master of the instance has been or is in the process of being left (in which case the instance is out of scope and thus cannot be called), or the associated task is already terminated (in which case Tasking_Error is raised for any attempt to call a task attribute operation).]} @end{Ramification} @end{Erron} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0071],ARef=[AI95-00165-01]} @Chg{New=[For a given attribute of a given task, the],Old=[The]} implementation shall perform @Chg{New=[the operations declared in this package], Old=[each of the above operations for a given attribute of a given task]} atomically with respect to any @Chg{New=[of these operations of], Old=[other of the above operations for]} the same attribute of the same task. @Chg{New=[The granularity of any locking mechanism necessary to achieve such atomicity is implementation defined.],Old=[]} @ChgImplDef{Version=[1],Kind=[Added],Text=[@Chg{New=[Granularity of locking for Task_Attributes.],Old=[]}]} @begin{Ramification} Hence, other than by dereferencing an access value returned by Reference, an attribute of a given task can be safely read and updated concurrently by multiple tasks. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]} @Chg{Version=[2],New=[After],Old=[When a]} task @Chg{Version=[2],New=[attributes are finalized],Old=[terminates]}, the implementation shall @Chg{Version=[2],New=[],Old=[finalize all attributes of the task, and ]}reclaim any @Chg{Version=[2],New=[],Old=[other ]}storage associated with the attributes. @end{ImplReq} @begin{DocReq} The implementation shall document the limit on the number of attributes per task, if any, and the limit on the total storage for attribute values per task, if such a limit exists. In addition, if these limits can be configured, the implementation shall document how to configure them. @ChgImplDef{Version=[2],Kind=[Deleted],Text=[@ChgDeleted{Version=[2], Text=[@Chg{New=[Limits on the number and size of task attributes, and how to configure them.], Old=[Implementation-defined aspects of Task_Attributes.]}]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For package Task_Attributes, limits on the number and size of task attributes, and how to configure any limits.]}]} @end{DocReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The implementation shall document the following metrics: A task calling the following subprograms shall execute @Chg{Version=[2],New=[at],Old=[in]} a sufficiently high priority as to not be preempted during the measurement period. This period shall start just before issuing the call and end just after the call completes. If the attributes of task T are accessed by the measurement tests, no other task shall access attributes of that task during the measurement period. For all measurements described here, the Attribute type shall be a scalar @Chg{Version=[2],New=[type ],Old=[]}whose size is equal to the size of the predefined @Chg{Version=[2],New=[type Integer],Old=[integer size]}. For each measurement, two cases shall be documented: one where the accessed attributes are of the calling task @Redundant[(that is, the default value for the T parameter is used)], and the other, where T identifies another, non-terminated, task. @Leading@;The following calls (to subprograms in the Task_Attributes package) shall be measured: @begin{Itemize} a call to Value, where the return value is Initial_Value; a call to Value, where the return value is not equal to Initial_Value; a call to Reference, where the return value designates a value equal to Initial_Value; a call to Reference, where the return value designates a value not equal to Initial_Value; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} a call to Set_Value where the Val parameter is not equal to Initial_Value and the old attribute value is equal to Initial_Value@Chg{Version=[2],New=[;],Old=[.]} a call to Set_Value where the Val parameter is not equal to Initial_Value and the old attribute value is not equal to Initial_Value. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for the Task_Attributes package.]}]} @end{Metrics} @begin{ImplPerm} An implementation need not actually create the object corresponding to a task attribute until its value is set to something other than that of Initial_Value, or until Reference is called for the task attribute. Similarly, when the value of the attribute is to be reinitialized to that of Initial_Value, the object may instead be finalized and its storage reclaimed, to be recreated when needed later. While the object does not exist, the function Value may simply return Initial_Value, rather than implicitly creating the object. @begin{Discussion} The effect of this permission can only be observed if the assignment operation for the corresponding type has side-effects. @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This permission means that even though every task has every attribute, storage need only be allocated for those attributes @Chg{Version=[2],New=[for which function Reference has been invoked],Old=[that have been Reference'd]} or set to a value other than that of Initial_Value. @end{ImplNote} An implementation is allowed to place restrictions on the maximum number of attributes a task may have, the maximum size of each attribute, and the total storage size allocated for all the attributes of a task. @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Some implementations are targeted to domains in which memory use at run time must be completely deterministic. For such implementations, it is recommended that the storage for task attributes will be pre-allocated statically and not from the heap. This can be accomplished by either placing restrictions on the number and the size of the @Chg{Version=[2], New=[],Old=[task's ]}attributes@Chg{Version=[2],New=[ of a task],Old=[]}, or by using the pre-allocated storage for the first N attribute objects, and the heap for the others. In the latter case, N should be documented. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the target domain requires deterministic memory use at run time, storage for task attributes should be pre-allocated statically and the number of attributes pre-allocated should be documented.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't mention @lquotes@;restrictions on the size and number@rquotes (that is, limits) in the text for the Annex, because it is covered by the @DocReqName above, and we try not to repeat requirements in the Annex (they're enough work to meet without having to do things twice).]} @end{Discussion} @end{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Finalization of task attributes and reclamation of associated storage should be performed as soon as possible after task termination.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Finalization of task attributes and reclamation of associated storage should be performed as soon as possible after task termination.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[This is necessary because the normative wording only says that attributes are finalized @lquotes@;after@rquotes@; task termination. Without this advice, waiting until the instance is finalized would meet the requirements (it is after termination, but may be a very long time after termination). We can't say anything more specific than this, as we do not want to require the overhead of an interaction with the tasking system to be done at a specific point.]} @end{Reason} @begin{Notes} An attribute always exists (after instantiation), and has the initial value. It need not occupy memory until the first operation that potentially changes the attribute value. The same holds true after Reinitialize. The result of the Reference function should be used with care; it is always safe to use that result in the task body whose attribute is being accessed. However, when the result is being used by another task, the programmer must make sure that the task whose attribute is being accessed is not yet terminated. Failing to do so could make the program execution erroneous. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00434-01]} @ChgDeleted{Version=[2],Text=[As specified in @RefSecNum{The Package Task_Identification}, if the parameter T (in a call on a subprogram of an instance of this package) identifies a nonexistent task, the execution of the program is erroneous.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that use of task attribute operations from within a task attribute operation (by an Adjust or Finalize call) is a bounded error, and that concurrent use of attribute handles is erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Clarified the wording so that the finalization takes place after the termination of the task or when the instance is finalized (whichever is sooner).]} @end{Diffword95} @LabeledAddedSubClause{Version=[2],Name=[The Package Task_Termination]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Task_Identification; @key<with> Ada.Exceptions; @key<package> Ada.Task_Termination @key<is>@ChildUnit{Parent=[Ada],Child=[Task_Termination]} @key<pragma> Preelaborate(Task_Termination);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Cause_Of_Termination} @key<is> (Normal, Abnormal, Unhandled_Exception);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Termination_Handler} @key<is access protected procedure> (Cause : @key<in> Cause_Of_Termination; T : @key<in> Ada.Task_Identification.Task_Id; X : @key<in> Ada.Exceptions.Exception_Occurrence);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Set_Dependents_Fallback_Handler} (Handler: @key<in> Termination_Handler); @key<function> @AdaSubDefn{Current_Task_Fallback_Handler} @key<return> Termination_Handler;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Set_Specific_Handler} (T : @key<in> Ada.Task_Identification.Task_Id; Handler : @key<in> Termination_Handler); @key<function> @AdaSubDefn{Specific_Handler} (T : Ada.Task_Identification.Task_Id) @key<return> Termination_Handler;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Task_Termination;]} @end{Example} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[@Defn{termination handler}@Defn2{Term=[handler],Sec=[termination]} The type Termination_Handler identifies a protected procedure to be executed by the implementation when a task terminates. Such a protected procedure is called a @i<handler>. In all cases T identifies the task that is terminating. If the task terminates due to completing the last statement of its body, or as a result of waiting on a terminate alternative, then Cause is set to Normal and X is set to Null_Occurrence. If the task terminates because it is being aborted, then Cause is set to Abnormal and X is set to Null_Occurrence. If the task terminates because of an exception raised by the execution of its @nt{task_body}, then Cause is set to Unhandled_Exception and X is set to the associated exception occurrence.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[@Defn{fall-back handler}@Defn2{Term=[termination handler],Sec=[fall-back]} @Defn{specific handler}@Defn2{Term=[termination handler],Sec=[specific]} @Defn2{Term=[set],Sec=[termination handler]} @Defn2{Term=[cleared],Sec=[termination handler]} Each task has two termination handlers, a @i<fall-back handler> and a @i<specific handler>. The specific handler applies only to the task itself, while the fall-back handler applies only to the dependent tasks of the task. A handler is said to be @i<set> if it is associated with a non-null value of type Termination_Handler, and @i<cleared> otherwise. When a task is created, its specific handler and fall-back handler are cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[The procedure Set_Dependents_Fallback_Handler changes the fall-back handler for the calling task; if Handler is @key{null}, that fall-back handler is cleared, otherwise it is set to be Handler.@key{all}. If a fall-back handler had previously been set it is replaced.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[The function Current_Task_Fallback_Handler returns the fall-back handler that is currently set for the calling task, if one is set; otherwise it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[The procedure Set_Specific_Handler changes the specific handler for the task identified by T; if Handler is @key{null}, that specific handler is cleared, otherwise it is set to be Handler.@key{all}. If a specific handler had previously been set it is replaced.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[The function Specific_Handler returns the specific handler that is currently set for the task identified by T, if one is set; otherwise it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[As part of the finalization of a @nt{task_body}, after performing the actions specified in @RefSecNum{User-Defined Assignment and Finalization} for finalization of a master, the specific handler for the task, if one is set, is executed. If the specific handler is cleared, a search for a fall-back handler proceeds by recursively following the master relationship for the task. If a task is found whose fall-back handler is set, that handler is executed; otherwise, no handler is executed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[For Set_Specific_Handler or Specific_Handler, Tasking_Error is raised if the task identified by T has already terminated. Program_Error is raised if the value of T is Ada.Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler that is invoked as part of the termination of a task has no effect.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[For a call of Set_Specific_Handler or Specific_Handler, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Task_Termination is new.]} @end{Extend95} ���������������������������������������������������������������������������������������������org.adaic.arm_form/source_2005/syntax.mss�����������������������������������������������������������0000755�0001752�0001001�00000002674�12273462240�017504� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(syntax, Root="ada.mss") @Comment{$Date: 2006/06/23 04:24:54 $} @LabeledInformativeAnnex{Syntax Summary} @comment{$Source: e:\\cvsroot/ARM/Source/syntax.mss,v $} @comment{$Revision: 1.18 $} @NoParaNum@Defn2{Term=[syntax], Sec=(complete listing)} @Defn2{Term=[grammar], Sec=(complete listing)} @Defn2{Term=[context free grammar], Sec=(complete listing)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(complete listing)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(complete listing)} This Annex summarizes the complete syntax of the language. See @RefSecNum{Method of Description and Syntax Notation} for a description of the notation used. @SyntaxSummary @NewPage @NoParaNum@Heading{Syntax Cross Reference} @NoParaNum@Defn2{Term=[syntax], Sec=(cross reference)} @Defn2{Term=[grammar], Sec=(cross reference)} @Defn2{Term=[context free grammar], Sec=(cross reference)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(cross reference)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(cross reference)} @ChgAdded{Version=[2],Text=[In the following syntax cross reference, each syntactic category is followed by the clause number where it is defined. In addition, each syntactic category @i{S} is followed by a list of the categories that use @i{S} in their definitions. For example, the first listing below shows that @nt{abort_statement} appears in the definition of @nt{simple_statement}.]} @Comment{This explanation is a simplified version of the Ada 83 one.} @SyntaxXRef ��������������������������������������������������������������������org.adaic.arm_form/source_2005/title.mss������������������������������������������������������������0000755�0001752�0001001�00000017503�12273462240�017274� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(title, Root="ada.mss") @comment{$Source: e:\\cvsroot/ARM/Source/title.mss,v $} @comment{$Revision: 1.33 $ $Date: 2006/11/09 06:29:49 $} @begin{ISOOnly} @Noparanum@Right{@Swiss{@Grow{@B{INTERNATIONAL STANDARD} ISO/IEC 8652:@Chg{Version=[2],New=[2007(E) Ed. 3],Old=[1995(E)@Chg{Version=[1], New=[ with COR.1:2001], Old=[]}]}}}} @end{ISOOnly} @begin{NotISO} @Noparanum@Right{@Swiss{@Grow{@B{Ada Reference Manual}, ISO/IEC 8652:@Chg{Version=[2],New=[2007(E) Ed. 3],Old=[1995(E)@Chg{Version=[1], New=[ with COR.1:2001], Old=[]}]}}}} @end{NotISO} @Noparanum@ @* @ @* @ @* @begin{ISOOnly} @Noparanum@swiss{@shrink{@shrink{@shrink{INTERNATIONAL ORGANIZATION FOR STANDARDIZATION}}}} @Noparanum@swiss{@shrink{@shrink{@shrink{INTERNATIONAL ELECTROTECHNICAL COMMISSION}}}} @end{ISOOnly} @Noparanum@ @* @ @* @begin{ISOOnly} @Noparanum@Swiss{@Grow{@Grow{@Grow{@Grow{@Grow{@b{Information technology @Em Programming languages @Em Ada}}}}}}} @end{ISOOnly} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @begin{NotISO} @Noparanum@ @*@;@comment{A dummy paragraph containing three blank lines} @ @* @ @* @ @* @end{NotISO} @begin{ISOOnly} @Comment{Jim Moore wants this deleted, as it is confusing.} @Noparanum@Chg{New=[@ @*@Comment{Dummy paragraph}], Old=[@Swiss{[Revision of first edition (ISO 8652:1987)]}]} @end{ISOOnly} @Noparanum@ @* @begin{NotISO} @begin{RMOnly} @Noparanum@Heading{@Grow{@Grow{@Grow{Ada Reference Manual}}}} @end{RMOnly} @begin{AARMOnly} @Noparanum@Heading{@Grow{@Grow{@Grow{Annotated Ada Reference Manual}}}} @end{AARMOnly} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@Center{@Swiss{@Grow{ISO/IEC 8652:1995(E)}}} @Noparanum@Center{@Swiss{@Chg{Version=[1], New=[@Grow{with Technical Corrigendum 1}], Old=[]}}} @Noparanum@Center{@Swiss{@Chg{Version=[2], New=[@Grow{and Amendment 1}], Old=[]}}} @end{NotISO} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@Center{@Swiss{@Grow{Language and Standard Libraries}}} @Noparanum@Comment{The following puts the copyright near the bottom of the page} @ @*@*@*@*@*@*@*@*@*@* @Noparanum@;Copyright @Latin1(169) 1992, 1993, 1994, 1995 Intermetrics, Inc. @Noparanum@;@Chg{Version=[1], New=[Copyright @Latin1(169) 2000 The MITRE Corporation, Inc.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006 AXE Consultants], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006 Ada-Europe], Old=[]} @NewPage @Comment{For ISO version, the back of the title page is blank, and the copyright ought to appear at the bottom of the table of contents. [But that probably is changed by now.} @begin{NotISO} @Comment{The following puts the copyright near the bottom of the page} @Noparanum@ @*@*@*@*@* @Noparanum@;@b{Ada Reference Manual - Language and Standard Libraries} @Noparanum@;Copyright @Latin1(169) 1992, 1993, 1994, 1995, Intermetrics, Inc. @Noparanum@;This copyright is assigned to the U.S. Government. All rights reserved. @Noparanum@;This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Compiled copies of standard library units and examples need not contain this copyright notice so long as the notice is included in all copies of source code and documentation. @ThinLine @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[1], New=[@b{Technical Corrigendum 1}], Old=[]} @Noparanum@;@Chg{Version=[1], New=[Copyright @Latin1(169) 2000, The MITRE Corporation. All Rights Reserved.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of MITRE.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[You use this document on the condition that you indemnify and hold harmless MITRE, its Board of Trustees, officers, agents, and employees, from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[MITRE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL MITRE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF MITRE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[2], New=[@b{Amendment 1}], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006, AXE Consultants. All Rights Reserved.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of AXE.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[You use this document on the condition that you indemnify and hold harmless AXE, its board, officers, agents, and employees, from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[AXE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL AXE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF AXE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[2], New=[@b{Consolidated Standard}], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006, Ada-Europe.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of Ada-Europe.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[You use this document on the condition that you indemnify and hold harmless Ada-Europe and its Board from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[ADA-EUROPE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL ADA-EUROPE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF ADA-EUROPE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @end{NotISO} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/���������������������������������������������������������������������0000755�0001752�0001001�00000000000�12273462364�015423� 5����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/01.mss���������������������������������������������������������������0000755�0001752�0001001�00000272172�12066652506�016404� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(01, Root="ada.mss") @PrefaceSection{} @Comment{Go to odd page.} @begin{Comment} The following stuff is to get the "INTERNATIONAL STANDARD" title between two horizontal rules at the top of page 1. (RLB-The following is a hack: I probably ought to add a style just for this purpose) @end{Comment} @thickline @begin{WideAbove} @noparanum@leading@tabclear()@tabset(P45) @Swiss<@Grow[@B{INTERNATIONAL STANDARD@\ISO/IEC 8652:@Chg{Version=[2],New=[@Chg{Version=[3],New=[2012(E)],Old=[2007(E), Ed. 3]}],Old=[@Chg{Version=[1], New=[1995(E) with COR.1:2001], Old=[]}]}}]> @end{WideAbove} @thickline @begin{Title} @noparanum@ @*@comment{Some vertical whitespace} @noparanum@Swiss{@b{Information technology @Em Programming}}@* @noparanum@Swiss{@b{Languages @Em Ada}} @noparanum@ @*@comment{Some vertical whitespace} @end{Title} @LabeledSectionNoBreak{General} @Comment{$Date: 2012/12/14 04:10:48 $} @Comment{$Source: e:\\cvsroot/ARM/Source/01.mss,v $} @Comment{$Revision: 1.85 $} @begin{Intro} @Chgref{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0299-1]} @ChgDeleted{Version=[3],Text=[Ada is a programming language designed to support the construction of long-lived, highly reliable software systems. The language includes facilities to define packages of related types, objects, and operations. The packages may be parameterized and the types may be extended to support the construction of libraries of reusable, adaptable software components. The operations may be implemented as subprograms using conventional sequential control structures, or as entries that include synchronization of concurrent threads of control as part of their invocation. The language treats modularity in the physical sense as well, with a facility to support separate compilation.]} @Chgref{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0269-1],ARef=[AI05-0299-1]} @ChgDeleted{Version=[3],Text=[The language includes a complete facility for the support of real-time, concurrent programming. Errors can be signaled as exceptions and handled explicitly. The language also covers systems programming; this requires precise control over the representation of data and access to system-dependent properties. Finally, a predefined environment of standard packages is provided, including facilities for, among others, input-output, string manipulation, numeric elementary functions, and random number generation.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This Annotated Ada Reference Manual (AARM) contains the entire text of the @Chg{Version=[3],New=[third edition of the ],Old=[]}Ada Reference Manual @Chg{Version=[3],New=[ (the Ada 2012 RM],Old=[@Chg{Version=[2],New=[ with Amendment 1 (the Ada 2005 RM],Old=[(RM95]}]}), plus certain annotations. The annotations give a more in-depth analysis of the language. They describe the reason for each nonobvious rule, and point out interesting ramifications of the rules and interactions among the rules (interesting to language lawyers, that is). Differences between Ada 83@Chg{Version=[2],New=[, Ada 95, @Chg{Version=[3],New=[],Old=[and ]}Ada 2005@Chg{Version=[3],New=[, and Ada 2012],Old=[]}],Old=[ and Ada 95]} are listed. (The text you are reading now is an annotation.) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} The AARM stresses detailed correctness and uniformity over readability and understandability. We're not trying to make the language @lquotes@;appear@rquotes@; simple here; on the contrary, we're trying to expose hidden complexities, so we can more easily detect language bugs. The @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95]}, on the other hand, is intended to be a more readable document for programmers. @Leading@keepnext@;The annotations in the AARM are as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} Text that is logically redundant is shown @Redundant[in square brackets, like this]. Technically, such text could be written as a @NotesName in the @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM (and the Ada 95 @Chg{Version=[3],New=[and 2005 RMs],Old=[RM]} before it)],Old=[RM95]}, since it is really a theorem that can be proven from the nonredundant rules of the language. We use the square brackets instead when it seems to make the @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95]} more readable. The rules of the language (and some AARM-only text) are categorized, and placed under certain @i{sub-headings} that indicate the category. For example, the distinction between @ResolutionName@;s and @LegalityName@;s is particularly important, as explained in @RefSecNum{The Context of Overload Resolution}. Text under the following sub-headings appears in both documents: @begin(Inneritemize) The unlabeled text at the beginning of each clause or subclause, @SyntaxTitle, @ResolutionTitle, @LegalityTitle, @StaticSemTitle, @LinkTimeTitle, @RunTimeTitle, @BoundedTitle, @ErronTitle, @ImplReqTitle, @DocReqTitle, @MetricsTitle, @ImplPermTitle, @ImplAdviceTitle, @NotesTitle, @ExamplesTitle. @end(Inneritemize) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} Text under the following sub-headings does not appear in the @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95]}: @begin(Inneritemize) @MetaRulesTitle, @Inconsistent83Title, @Incompatible83Title, @Extend83Title, @ChgRef{Version=[2],Kind=[Revised]} @DiffWord83Title@Chg{Version=[2],New=[,],Old=[.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Inconsistent95Title,]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Incompatible95Title,]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Extend95Title,]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @ChgAdded{Version=[2],Text=[@DiffWord95Title@Chg{Version=[3],New=[,],Old=[.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@Inconsistent2005Title,]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@Incompatible2005Title,]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@Extend2005Title,]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@DiffWord2005Title.]} @end(Inneritemize) The AARM also includes the following kinds of annotations. These do not necessarily annotate the immediately preceding rule, although they often do. @end{Itemize} @end{Discussion} @begin{Reason} An explanation of why a certain rule is necessary, or why it is worded in a certain way. @end{Reason} @begin{Ramification} An obscure ramification of the rules that is of interest only to language lawyers. (If a ramification of the rules is of interest to programmers, then it appears under @NotesTitle.) @end{Ramification} @begin{TheProof} An informal proof explaining how a given @NotesName or @Redundant[marked-as-redundant] piece of text follows from the other rules of the language. @end{TheProof} @begin{ImplNote} A hint about how to implement a feature, or a particular potential pitfall that an implementer needs to be aware of. @b{Change:} Change annotations are not used in this version. Changes from previous versions have been removed. Changes in this version are marked with versioned paragraph numbers, as explained in the @lquotes@;Corrigendum Changes@rquotes@; clause of the @lquotes@;Introduction@rquotes@;. @end{ImplNote} @begin{Discussion} Other annotations not covered by the above. @end{Discussion} @begin{Honest} A rule that is considered logically necessary to the definition of the language, but which is so obscure or pedantic that only a language lawyer would care. These are the only annotations that could be considered part of the language definition. @end{Honest} @begin{GlossaryMarker} The text of a Glossary entry @em this text will also appear in @RefSec{Glossary}. @end{GlossaryMarker} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} In general, @Chg{Version=[2],New=[the Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95]} text appears in the normal font, whereas AARM-only text appears in a smaller font. @NotesName@;s also appear in the smaller font, as recommended by ISO/IEC style guidelines. Ada examples are also usually printed in a smaller font. If you have trouble finding things, be sure to use the index. @Defn{italics, like this} Each defined term appears there, and also in @i{italics, like this}. Syntactic categories defined in BNF are also indexed. A definition marked @lquotes@;[distributed]@rquotes@; is the main definition for a term whose complete definition is given in pieces distributed throughout the document. The pieces are marked @lquotes@;[partial]@rquotes@; or with a phrase explaining what cases the partial definition applies to. @end{Discussion} @end{Intro} @LabeledClause{Scope} @begin{Intro} @Chgref{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} This International Standard specifies the form and meaning of programs written in Ada. Its purpose is to promote the portability of Ada programs to a variety of @Chg{Version=[3],New=[computing],Old=[data processing]} systems. @Chgref{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Ada is a programming language designed to support the construction of long-lived, highly reliable software systems. The language includes facilities to define packages of related types, objects, and operations. The packages may be parameterized and the types may be extended to support the construction of libraries of reusable, adaptable software components. The operations may be implemented as subprograms using conventional sequential control structures, or as entries that include synchronization of concurrent threads of control as part of their invocation. Ada supports object-oriented programming by providing classes and interfaces, inheritance, polymorphism of variables and methods, and generic units. The language treats modularity in the physical sense as well, with a facility to support separate compilation.]} @Chgref{Version=[3],Kind=[AddedNormal],ARef=[AI05-0269-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[The language provides rich support for real-time, concurrent programming, and includes facilities for multicore and multiprocessor programming. Errors can be signaled as exceptions and handled explicitly. The language also covers systems programming; this requires precise control over the representation of data and access to system-dependent properties. Finally, a predefined environment of standard packages is provided, including facilities for, among others, input-output, string manipulation, numeric elementary functions, and random number generation, and definition and use of containers.]} @end{Intro} @LabeledSubClause{Extent} @begin{Intro} @Leading@keepnext@;This International Standard specifies: @begin(Itemize) The form of a program written in Ada; The effect of translating and executing such a program; The manner in which program units may be combined to form Ada programs; The language-defined library units that a conforming implementation is required to supply; The permissible variations within the standard, and the manner in which they are to be documented; Those violations of the standard that a conforming implementation is required to detect, and the effect of attempting to translate or execute a program containing such violations; Those violations of the standard that a conforming implementation is not required to detect. @end(Itemize) @begin{WideAbove} @Leading@keepnext@;This International Standard does not specify: @end{WideAbove} @begin(Itemize) The means whereby a program written in Ada is transformed into object code executable by a processor; The means whereby translation or execution of programs is invoked and the executing units are controlled; The size or speed of the object code, or the relative execution speed of different language constructs; The form or contents of any listings produced by implementations; in particular, the form or contents of error or warning messages; The effect of unspecified execution. The size of a program or program unit that will exceed the capacity of a particular conforming implementation. @end(Itemize) @end{Intro} @LabeledSubClause{Structure} @begin{Intro} @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This International Standard contains thirteen @Chg{Version=[3],New=[clauses],Old=[sections]}, @Chg{Version=[3],New=[fifteen],Old=[fourteen]} annexes, and an index. @begin{Discussion} @Chgref{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[What Ada 83 called a @ldquote@;chapter@rdquote and Ada 95 (and Ada 2005) called a @ldquote@;section@rdquote is called a @ldquote@;clause@rdquote in this Standard. Similarly, what Ada 83 called a @ldquote@;section@rdquote and Ada 95 (and Ada 2005) called a @ldquote@;clause@rdquote is called a @ldquote@;subclause@rdquote in this Standard. Confused yet? This terminology is out of our hands; it is (and was) forced by ever-changing ISO rules for drafting Standards.]} @end{Discussion} @Leading@Defn{core language} The @i{core} of the Ada language consists of: @begin{Itemize} @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Chg{Version=[3],New=[Clauses],Old=[Sections]} 1 through 13 @RefSec{Predefined Language Environment} @RefSec{Interface to Other Languages} @RefSec{Obsolescent Features} @end{Itemize} @begin{WideAbove} @Leading@Defn{Specialized Needs Annexes} @Defn2{Term=[Annex],Sec=(Specialized Needs)} @Defn{application areas} The following @i{Specialized Needs Annexes} define features that are needed by certain application areas: @end{WideAbove} @begin{Itemize} @RefSec{Systems Programming} @RefSec{Real-Time Systems} @RefSec{Distributed Systems} @RefSec{Information Systems} @RefSec{Numerics} @RefSec{High Integrity Systems} @end{Itemize} @begin{WideAbove} @Leading@Defn{normative} @Defn2{Term=[Annex],Sec=(normative)} The core language and the Specialized Needs Annexes are normative, except that the material in each of the items listed below is informative: @end{WideAbove} @begin(Itemize) Text under a NOTES or Examples heading. @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Each @Chg{Version=[3],New=[],Old=[clause or ]}subclause whose title starts with the word @lquotes@;Example@rquotes@; or @lquotes@;Examples@rquotes@;. @end(Itemize) All implementations shall conform to the core language. In addition, an implementation may conform separately to one or more Specialized Needs Annexes. @begin{WideAbove} @Leading@Keepnext@Defn{informative} @IndexSee{Term=[nonnormative],See=(informative)} @Defn2{Term=[Annex],Sec=(informative)} The following Annexes are informative: @end{WideAbove} @begin{Itemize} @RefSec{Language-Defined Aspects and Attributes} @RefSec{Language-Defined Pragmas} @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @Chg{Version=[3],New=[@RefSec{Summary of Documentation Requirements}],Old=[@RefSec{Implementation-Defined Characteristics}]} @RefSec{Glossary} @RefSec{Syntax Summary} @Chgref{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@RefSec{Language-Defined Entities}]} @end{Itemize} @begin(Discussion) The idea of the Specialized Needs Annexes is that implementations can choose to target certain application areas. For example, an implementation specifically targeted to embedded machines might support the application-specific features for Real-time Systems, but not the application-specific features for Information Systems. The Specialized Needs Annexes extend the core language only in ways that users, implementations, and standards bodies are allowed to extend the language; for example, via additional library units, attributes, representation items (see @RefSecNum{Operational and Representation Aspects}), @nt{pragma}s, and constraints on semantic details that are left unspecified by the core language. Many implementations already provide much of the functionality defined by Specialized Needs Annexes; our goal is to increase uniformity among implementations by defining standard ways of providing the functionality. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]}@ChgNote{Make consistent with 18009} We recommend that the @Chg{Version=[2],New=[certification],Old=[validation]} procedures allow implementations to @Chg{Version=[2],New=[certify],Old=[validate]} the core language, plus any set of the Specialized Needs Annexes. We recommend that implementations @i{not} be allowed to @Chg{Version=[2],New=[certify],Old=[validate]} a portion of one of the Specialized Needs Annexes, although implementations can, of course, provide @Chg{Version=[2], New=[uncertified],Old=[unvalidated]} support for such portions. We have designed the Specialized Needs Annexes assuming that this recommendation is followed. Thus, our decisions about what to include and what not to include in those annexes are based on the assumption that each annex is @Chg{Version=[2],New=[certified],Old=[validated]} in an @lquotes@;all-or-nothing@rquotes@; manner. An implementation may, of course, support extensions that are different from (but possibly related to) those defined by one of the Specialized Needs Annexes. We recommend that, where appropriate, implementations do this by adding library units that are children of existing language-defined library packages. An implementation should not provide extensions that conflict with those defined in the Specialized Needs Annexes, in the following sense: Suppose an implementation supports a certain error-free program that uses only functionality defined in the core and in the Specialized Needs Annexes. The implementation should ensure that that program will still be error free in some possible full implementation of all of the Specialized Needs Annexes, and that the semantics of the program will not change. For example, an implementation should not provide a package with the same name as one defined in one of the Specialized Needs Annexes, but that behaves differently, @i{even if that implementation does not claim conformance to that Annex}. Note that the Specialized Needs Annexes do not conflict with each other; it is the intent that a single implementation can conform to all of them. @end(Discussion) @begin{WideAbove} @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Each @Chg{Version=[3],New=[section],Old=[clause]} is divided into @Chg{Version=[3],New=[],Old=[clauses and]} subclauses that have a common structure. Each @Chg{Version=[3],New=[],Old=[section, ]}clause@Chg{Version=[3],New=[],Old=[,]} and subclause first introduces its subject. After the introductory text, text is labeled with the following headings: @end{WideAbove} @end{Intro} @begin{MetaRules} These are not rules of the language, but guiding principles or goals used in defining the rules of the language. In some cases, the goal is only partially met; such cases are explained. @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95]}. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Defn2{Term=[syntax], Sec=(under Syntax heading)} @Defn2{Term=[grammar], Sec=(under Syntax heading)} @Defn2{Term=[context free grammar], Sec=(under Syntax heading)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(under Syntax heading)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(under Syntax heading)} Syntax rules (indented). @end{SyntaxText} @end{Syntax} @begin{Resolution} @Chgref{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{name resolution rules} @Defn{overloading rules} @Defn{resolution rules} Compile-time rules that are used in name resolution, including overload resolution. @begin{Discussion} These rules are observed at compile time. (We say @lquotes@;observed@rquotes@; rather than @lquotes@;checked,@rquotes@; because these rules are not individually checked. They are really just part of the @LegalityName@;s in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules} that require exactly one interpretation of each constituent of a complete context.) The only rules used in overload resolution are the @SyntaxName@;s and the @ResolutionName@;s. When dealing with nonoverloadable declarations it sometimes makes no semantic difference whether a given rule is a @ResolutionName or a @LegalityName, and it is sometimes difficult to decide which it should be. We generally make a given rule a @ResolutionName only if it has to be. For example, @lquotes@;The @nt{name}, if any, in a @nt{raise_statement} shall be the @nt{name} of an exception.@rquotes@; is under @lquotes@;@LegalityTitle.@rquotes@; @end{Discussion} @end{Resolution} @begin{Legality} @Defn{legality rules} @Defn{compile-time error} @Defn2{Term=[error], Sec=(compile-time)} Rules that are enforced at compile time. @Defn2{Term=[legal], Sec=(construct)} @Defn2{Term=[illegal], Sec=(construct)} A construct is @i{legal} if it obeys all of the @LegalityName@;s. @begin{Discussion} These rules are not used in overload resolution. Note that run-time errors are always attached to exceptions; for example, it is not @lquotes@;illegal@rquotes@; to divide by zero, it just raises an exception. @end{Discussion} @end{Legality} @begin{StaticSem} @Defn{static semantics} @Defn{compile-time semantics} A definition of the compile-time effect of each construct. @begin{Discussion} The most important compile-time effects represent the effects on the symbol table associated with declarations (implicit or explicit). In addition, we use this heading as a bit of a grab bag for equivalences, package specifications, etc. For example, this is where we put statements like so-and-so is equivalent to such-and-such. (We ought to try to really mean it when we say such things!) Similarly, statements about magically-generated implicit declarations go here. These rules are generally written as statements of fact about the semantics, rather than as a you-shall-do-such-and-such sort of thing. @end{Discussion} @end{StaticSem} @begin{LinkTime} @Defn{post-compilation error} @Defn{post-compilation rules} @IndexSee{Term=[link-time error],See=(post-compilation error)} @Defn2{Term=[error], Sec=(link-time)} Rules that are enforced before running a partition. @Defn2{Term=[legal], Sec=(partition)} @Defn2{Term=[illegal], Sec=(partition)} A partition is legal if its compilation units are legal and it obeys all of the @LinkTimeName@;s. @begin{Discussion} It is not specified exactly when these rules are checked, so long as they are checked for any given partition before that partition starts running. An implementation may choose to check some such rules at compile time, and reject @nt{compilation_unit}s accordingly. Alternatively, an implementation may check such rules when the partition is created (usually known as @lquotes@;link time@rquotes@;), or when the partition is mapped to a particular piece of hardware (but before the partition starts running). @end{Discussion} @end{LinkTime} @begin{RunTime} @Defn{dynamic semantics} @Defn{run-time semantics} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} A definition of the run-time effect of each construct. @begin{Discussion} This heading describes what happens at run time. Run-time checks, which raise exceptions upon failure, are described here. Each item that involves a run-time check is marked with the name of the check @em these are the same check names that are used in a @nt{pragma} Suppress. Principle: Every check should have a name, usable in a @nt{pragma} Suppress. @end{Discussion} @end{RunTime} @begin{Bounded} @Defn{bounded error} @SeeAlso{Primary=[error], Other=(bounded error)} Situations that result in bounded (run-time) errors (see @RefSecNum{Classification of Errors}). @begin{Discussion} The @lquotes@;bounds@rquotes@; of each such error are described here @em that is, we characterize the set of all possible behaviors that can result from a bounded error occurring at run time. @end{Discussion} @end{Bounded} @begin{Erron} @Defn{erroneous execution} @SeeAlso{Primary=[error], Other=(erroneous execution)} Situations that result in erroneous execution (see @RefSecNum{Classification of Errors}). @end{Erron} @begin{ImplReq} @Defn{implementation requirements} Additional requirements for conforming implementations. @begin{Discussion} ...as opposed to rules imposed on the programmer. An example might be, @lquotes@;The smallest representable duration, Duration'Small, shall not be greater than twenty milliseconds.@rquotes@; It's really just an issue of how the rule is worded. We could write the same rule as @lquotes@;The smallest representable duration is an implementation-defined value less than or equal to 20 milliseconds@rquotes@; and then it would be under @lquotes@;@StaticSemTitle.@rquotes@; @end{Discussion} @end{ImplReq} @begin{DocReq} @Defn{documentation requirements} Documentation requirements for conforming implementations. @begin{Discussion} These requirements are beyond those that are implicitly specified by the phrase @lquotes@;implementation defined@rquotes@;. The latter require documentation as well, but we don't repeat these cases under this heading. Usually this heading is used for when the description of the documentation requirement is longer and does not correspond directly to one, narrow normative sentence. @end{Discussion} @end{DocReq} @begin{Metrics} @Defn{metrics} Metrics that are specified for the time/space properties of the execution of certain language constructs. @end{Metrics} @begin{ImplPerm} @Defn{implementation permissions} Additional permissions given to the implementer. @begin{Discussion} For example, @lquotes@;The implementation is allowed to impose further restrictions on the record aggregates allowed in code statements.@rquotes@; When there are restrictions on the permission, those restrictions are given here also. For example, @lquotes@;An implementation is allowed to restrict the kinds of subprograms that are allowed to be main subprograms. However, it shall support at least parameterless procedures.@rquotes@; @em we don't split this up between here and @lquotes@;@ImplReqTitle.@rquotes@; @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} @Defn{implementation advice} @Defn{advice} Optional advice given to the implementer. The word @lquotes@;should@rquotes@; is used to indicate that the advice is a recommendation, not a requirement. It is implementation defined whether or not a given recommendation is obeyed. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[Whether or not each recommendation given in @ImplAdviceTitle is followed@Chg{Version=[2], New=[ @em see @RefSec{Implementation Advice} for a listing],Old=[]}.]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised]} The advice generally shows the intended implementation, but the implementer is free to ignore it. The implementer is the sole arbiter of whether or not the advice has been obeyed, if not, whether the reason is a good one, and whether the required documentation is sufficient. @Chg{Version=[1],New=[],Old=[@PDefn2{Term=[ACVC],Sec=(Ada Compiler Validation Capability)} @PDefn2{Term=[Ada Compiler Validation Capability],Sec=(ACVC)}]} It would be wrong for the @Chg{Version=[1],New=[ACATS],Old=[ACVC]} to enforce any of this advice. For example, @lquotes@;Whenever possible, the implementation should choose a value no greater than fifty microseconds for the smallest representable duration, Duration'Small.@rquotes@; We use this heading, for example, when the rule is so low level or implementation-oriented as to be untestable. We also use this heading when we wish to encourage implementations to behave in a certain way in most cases, but we do not wish to burden implementations by requiring the behavior. @end{Discussion} @end{ImplAdvice} @begin{Notes} @Defn{notes} Notes emphasize consequences of the rules described in the (sub)clause or elsewhere. This material is informative. @end{Notes} @begin{Examples} Examples illustrate the possible forms of the constructs described. This material is informative. @begin{Discussion} @ @* @Comment{Two blank lines: why? Because it was in the original.} @* The next three headings list all language changes between Ada 83 and Ada 95. Language changes are any change that changes the set of text strings that are legal Ada programs, or changes the meaning of any legal program. Wording changes, such as changes in terminology, are not language changes. Each language change falls into one of the following three categories: @end{Discussion} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} This heading lists all of the upward inconsistencies between Ada 83 and Ada 95. Upward inconsistencies are situations in which a legal Ada 83 program is a legal Ada 95 program with different semantics. This type of upward incompatibility is the worst type for users, so we only tolerate it in rare situations. (Note that the semantics of a program is not the same thing as the behavior of the program. Because of Ada's indeterminacy, the @lquotes@;semantics@rquotes@; of a given feature describes a @i{set} of behaviors that can be exhibited by that feature. The set can contain more than one allowed behavior. Thus, when we ask whether the semantics changes, we are asking whether the set of behaviors changes.) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95@Chg{Version=[3],New=[,],Old=[ or]} Ada 2005@Chg{Version=[3],New=[, or Ada 2012],Old=[]} RM],Old=[RM95]}. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} This heading lists all of the upward incompatibilities between Ada 83 and Ada 95, except for the ones listed under @lquotes@;@Inconsistent83Title@rquotes@; above. These are the situations in which a legal Ada 83 program is illegal in Ada 95. We do not generally consider a change that turns erroneous execution into an exception, or into an illegality, to be upwardly incompatible. @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95@Chg{Version=[3],New=[,],Old=[ or]} Ada 2005@Chg{Version=[3],New=[, or Ada 2012],Old=[]} RM],Old=[RM95]}. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 95 program is not a legal Ada 83 program. The vast majority of language changes fall into this category. @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95@Chg{Version=[3],New=[,],Old=[ or]} Ada 2005@Chg{Version=[3],New=[, or Ada 2012],Old=[]} RM],Old=[RM95]}. @Leading@ @* @Comment{Two blank lines: why? Because it was in the original.} @* As explained above, the next heading does not represent any language change: @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised]} @Defn{wording changes from Ada 83} This heading lists some of the nonsemantic changes between @Chg{Version=[2], New=[the Ada 83 RM],Old=[RM83]} and the @Chg{Version=[2],New=[Ada 95 RM],Old=[RM95]}. It is incomplete; we have not attempted to list all wording changes, but only the @lquotes@;interesting@rquotes@; ones. @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This is not part of the definition of the language, and does not appear in the @Chg{Version=[2],New=[Ada 95@Chg{Version=[3],New=[,],Old=[ or]} Ada 2005@Chg{Version=[3],New=[, or Ada 2012],Old=[]} RM],Old=[RM95]}. @end{DiffWord83} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* The next three headings list all language changes between Ada 95 and Ada 2005 (the language defined by the Ada 95 standard plus Technical Corrigendum 1 plus Amendment 1). Each language change falls into one of the following three categories:]} @end{Discussion} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} This heading lists all of the upward inconsistencies between Ada 95 and Ada 2005. Upward inconsistencies are situations in which a legal Ada 95 program is a legal Ada 2005 program with different semantics.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[Inconsistencies marked with @b[Corrigendum:]@Defn{Corrigendum} are corrections to the original Ada 95 definition introduced by Corrigendum 1. Inconsistencies marked with @b[Amendment Correction:]@Defn{Amendment Correction} are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are inconsistencies caused by Ada Issues classified as Binding Interpretations; implementations of Ada 95 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not inconsistencies between Ada 95 and Ada 2005. Practically, however, they very well may be, as early Ada 95 implementations @Chg{Version=[3],New=[might],Old=[may]} not follow the recommendation. Inconsistencies so marked are not portable between Ada 95 implementations, while usually Ada 2005 will have more clearly defined behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 @Chg{Version=[3],New=[or Ada 2012],Old=[]} RM.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} This heading lists all of the upward incompatibilities between Ada 95 and Ada 2005, except for the ones listed under @lquotes@;@Inconsistent95Title@rquotes@; above. These are the situations in which a legal Ada 95 program is illegal in Ada 2005.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[As with inconsistencies, incompatibilities marked with @b[Corrigendum:] are corrections to the original Ada 95 definition introduced by Corrigendum 1. Incompatibilities marked with @b[Amendment Correction:] are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are incompatibilities caused by Ada Issues classified as Binding Interpretations; implementations of Ada 95 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not incompatibilities between Ada 95 and Ada 2005. Practically, however, they very well may be, as early Ada 95 implementations @Chg{Version=[3],New=[might],Old=[may]} not follow the recommendation. Therefore, some Ada 95 implementations may be able to compile the examples, while others @Chg{Version=[3],New=[might],Old=[may]} not. In @Chg{Version=[3],New=[contrast],Old=[constrast]}, Ada 2005 compilers will have consistent behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 @Chg{Version=[3],New=[or Ada 2012],Old=[]} RM.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Defn{extensions to Ada 95} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 2005 program is not a legal Ada 95 program. The vast majority of language changes fall into this category.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[As with incompatibilities, extensions marked with @b[Corrigendum:] are corrections to the original Ada 95 definition introduced by Corrigendum 1. Extensions marked with @b[Amendment Correction:] are corrections to the original Ada 95 definition added by Amendment 1. Formally, these are extensions allowed by Ada Issues classified as Binding Interpretations. As corrections, implementations of Ada 95 are allowed to implement these extensions. Thus, these strictly speaking are not extensions of Ada 95; they're part of Ada 95. Practically, however, they very well may be extensions, as early Ada 95 implementations @Chg{Version=[3],New=[might],Old=[may]} not implement the extension. Therefore, some Ada 95 implementations may be able to compile the examples, while others @Chg{Version=[3],New=[might],Old=[may]} not. In @Chg{Version=[3],New=[contrast],Old=[constrast]}, Ada 2005 compilers will always support the extensions. Therefore, we document these for completeness.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 @Chg{Version=[3],New=[or Ada 2012],Old=[]} RM.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* As explained above, the next heading does not represent any language change:]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Defn{wording changes from Ada 95} This heading lists some of the nonsemantic changes between the Ada 95 RM and the Ada 2005 RM. This heading lists only @lquotes@;interesting@rquotes@; changes (for instance, editorial corrections are not listed). Changes which come from Technical Corrigendum 1 are marked @b{Corrigendum}; unmarked changes come from Amendment 1.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[This is not part of the definition of the language, and does not appear in the Ada 2005 @Chg{Version=[3],New=[or Ada 2012],Old=[]} RM.]} @end{DiffWord95} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* The next three headings list all language changes between Ada 2005 (the language defined by the Ada 95 standard plus Technical Corrigendum 1 plus Amendment 1) and Ada 2012 (the language defined by the third edition of the Standard@Comment{was: Ada 95 standard plus Technical Corrigendum 1 plus Amendment 1 plus Amendment 2}). Each language change falls into one of the following three categories:]} @end{Discussion} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} This heading lists all of the upward inconsistencies between Ada 2005 and Ada 2012. Upward inconsistencies are situations in which a legal Ada 2005 program is a legal Ada 2012 program with different semantics.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Inconsistencies marked with @b[Correction:]@Defn{Correction} are corrections to the original Ada 2005 definition added by the third edition of the Standard. Formally, these are inconsistencies caused by Ada Issues classified as Binding Interpretations; implementations of Ada 2005 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not inconsistencies between Ada 2005 and Ada 2012. Practically, however, they very well may be, as early Ada 2005 implementations might not follow the recommendation. Inconsistencies so marked are not portable between Ada 2005 implementations, while usually Ada 2012 will have more clearly defined behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is not part of the definition of the language, and does not appear in the Ada 2012 RM.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} This heading lists all of the upward incompatibilities between Ada 2005 and Ada 2012, except for the ones listed under @lquotes@;@Inconsistent2005Title@rquotes@; above. These are the situations in which a legal Ada 2005 program is illegal in Ada 2012.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[As with inconsistencies, incompatibilities marked with @b[Correction:] are corrections to the original Ada 2005 definition added by the third edition. Formally, these are incompatibilities caused by Ada Issues classified as Binding Interpretations; implementations of Ada 2005 are supposed to follow these corrections, not the original flawed language definition. Thus, these strictly speaking are not incompatibilities between Ada 2005 and Ada 2012. Practically, however, they very well may be, as early Ada 2005 implementations might not follow the recommendation. Therefore, some Ada 2005 implementations may be able to compile the examples, while others might not. In @Chg{Version=[3],New=[contrast],Old=[constrast]}, Ada 2012 compilers will have consistent behavior. Therefore, we document these for completeness.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is not part of the definition of the language, and does not appear in the Ada 2012 RM.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} This heading is used to list all upward compatible language changes; that is, language extensions. These are the situations in which a legal Ada 2012 program is not a legal Ada 2005 program. The vast majority of language changes fall into this category.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[As with incompatibilities, extensions marked with @b[Correction:] are corrections to the original Ada 2005 definition added by the third edition. Formally, these are extensions allowed by Ada Issues classified as Binding Interpretations. As corrections, implementations of Ada 2005 (and sometimes Ada 95) are allowed to implement these extensions. Thus, these strictly speaking are not extensions of Ada 2005; they're part of Ada 2005. Practically, however, they very well may be extensions, as early Ada 2005 implementations might not implement the extension. Therefore, some Ada 2005 implementations may be able to compile the examples, while others might not. In contrast, Ada 2012 compilers will always support the extensions. Therefore, we document these for completeness.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is not part of the definition of the language, and does not appear in the Ada 2012 RM.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[@ @* @Comment{Two blank lines: why? Because it was in the Ada 95 original.} @* As explained above, the next heading does not represent any language change:]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@Defn{wording changes from Ada 2005} This heading lists some of the nonsemantic changes between the Ada 2005 RM and the Ada 2012 RM. This heading lists only @lquotes@;interesting@rquotes@; changes (for instance, editorial corrections are not listed). Items marked @b[Correction:] come from Ada Issues classified as Binding Interpretations and strictly speaking belong to Ada 2005; other items only belong to Ada 2012.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is not part of the definition of the language, and does not appear in the Ada 2012 RM.]} @end{DiffWord2005} @LabeledSubClause{Conformity of an Implementation with the Standard} @begin{ImplReq} @Leading@Keepnext@Defn2{Term=[conformance],Sec=(of an implementation with the Standard)} A conforming implementation shall: @begin{Discussion} @Defn{implementation} The @i{implementation} is the software and hardware that implements the language. This includes compiler, linker, operating system, hardware, etc. We first define what it means to @lquotes@;conform@rquotes@; in general @em basically, the implementation has to properly implement the normative rules given throughout the standard. Then we define what it means to conform to a Specialized Needs Annex @em the implementation must support the core features plus the features of that Annex. Finally, we define what it means to @lquotes@;conform to the Standard@rquotes@; @em this requires support for the core language, and allows partial (but not conflicting) support for the Specialized Needs Annexes. @end{Discussion} @begin(Itemize) Translate and correctly execute legal programs written in Ada, provided that they are not so large as to exceed the capacity of the implementation; Identify all programs or program units that are so large as to exceed the capacity of the implementation (or raise an appropriate exception at run time); @ImplDef{Capacity limitations of the implementation.} Identify all programs or program units that contain errors whose detection is required by this International Standard; @begin{Discussion} Note that we no longer use the term @lquotes@;rejection@rquotes@; of programs or program units. We require that programs or program units with errors or that exceed some capacity limit be @lquotes@;identified@rquotes@;. The way in which errors or capacity problems are reported is not specified. An implementation is allowed to use standard error-recovery techniques. We do not disallow such techniques from being used across @nt{compilation_unit} or @nt{compilation} boundaries. See also the @ImplReqTitle of @RefSecNum{Program Execution}, which disallow the execution of illegal partitions. @end{Discussion} Supply all language-defined library units required by this International Standard; @begin{ImplNote} An implementation cannot add to or modify the visible part of a language-defined library unit, except where such permission is explicitly granted, unless such modifications are semantically neutral with respect to the client compilation units of the library unit. An implementation defines the contents of the private part and body of language-defined library units. An implementation can add @nt{with_clause}s and @nt{use_clause}s, since these modifications are semantically neutral to clients. (The implementation might need @nt{with_clause}s in order to implement the private part, for example.) Similarly, an implementation can add a private part even in cases where a private part is not shown in the standard. Explicit declarations can be provided implicitly or by renaming, provided the changes are semantically neutral. @Defn2{Term=[italics],Sec=(implementation-defined)} Wherever in the standard the text of a language-defined library unit contains an italicized phrase starting with @lquotes@;@i{implementation-defined}@rquotes@;, the implementation's version will replace that phrase with some implementation-defined text that is syntactically legal at that place, and follows any other applicable rules. Note that modifications are permitted, even if there are other tools in the environment that can detect the changes (such as a program library browser), so long as the modifications make no difference with respect to the static or dynamic semantics of the resulting programs, as defined by the standard. @end{ImplNote} Contain no variations except those explicitly permitted by this International Standard, or those that are impossible or impractical to avoid given the implementation's execution environment; @ImplDef{Variations from the standard that are impractical to avoid given the implementation's execution environment.} @begin{Reason} The @lquotes@;impossible or impractical@rquotes@; wording comes from AI-325. It takes some judgement and common sense to interpret this. Restricting compilation units to less than 4 lines is probably unreasonable, whereas restricting them to less than 4 billion lines is probably reasonable (at least given today's technology). We do not know exactly where to draw the line, so we have to make the rule vague. @end{Reason} Specify all such variations in the manner prescribed by this International Standard. @end(Itemize) @begin{WideAbove} @Leading@keepnext@Defn2{Term=[external effect], Sec=(of the execution of an Ada program)} @Defn2{Term=[effect], Sec=(external)} The @i(external effect) of the execution of an Ada program is defined in terms of its interactions with its external environment. @Defn{external interaction} The following are defined as @i(external interactions): @end{WideAbove} @begin(Itemize) Any interaction with an external file (see @RefSecNum(External Files and File Objects)); The execution of certain @nt<code_statement>s (see @RefSecNum{Machine Code Insertions}); which @nt{code_statement}s cause external interactions is implementation defined. @ImplDef{Which @nt{code_statement}s cause external interactions.} Any call on an imported subprogram (see @RefSecNum(Interface to Other Languages)), including any parameters passed to it; Any result returned or exception propagated from a main subprogram (see @RefSecNum(Program Execution)) or an exported subprogram (see @RefSecNum(Interface to Other Languages)) to an external caller; @begin{Discussion} By @lquotes@;result returned@rquotes@; we mean to include function results and values returned in [@key(in)] @key(out) parameters. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0094],ARef=[AI95-00119-01]} @Chg{Version=[1],New=[The lack of a result from a program that does not terminate is also included here.],Old=[]} @end{Discussion} @Redundant[Any read or update of an atomic or volatile object (see @RefSecNum(Shared Variable Control));] The values of imported and exported objects (see @RefSecNum(Interface to Other Languages)) at the time of any other interaction with the external environment. @begin{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Also other uses of imported and exported entities, as defined by the implementation, if the implementation supports such @Chg{Version=[3],New=[importing or exporting],Old=[@nt{pragma}s]}. @end{Honest} @end(Itemize) @begin{WideAbove} A conforming implementation of this International Standard shall produce for the execution of a given Ada program a set of interactions with the external environment whose order and timing are consistent with the definitions and requirements of this International Standard for the semantics of the given program. @end{WideAbove} @begin{Ramification} There is no need to produce any of the @lquotes@;internal effects@rquotes@; defined for the semantics of the program @em all of these can be optimized away @em so long as an appropriate sequence of external interactions is produced. @end{Ramification} @begin{Discussion} See also @RefSecNum(Exceptions and Optimization) which specifies various liberties associated with optimizations in the presence of language-defined checks, that could change the external effects that might be produced. These alternative external effects are still consistent with the standard, since @RefSecNum(Exceptions and Optimization) is part of the standard. Note also that we only require @lquotes@;@i(an appropriate) sequence of external interactions@rquotes@; rather than @lquotes@;@i(the same) sequence...@rquotes@; An optimizer may cause a different sequence of external interactions to be produced than would be produced without the optimizer, so long as the new sequence still satisfies the requirements of the standard. For example, optimization might affect the relative rate of progress of two concurrent tasks, thereby altering the order in which two external interactions occur. @ChgRef{Version=[2],Kind=[Revised]} Note that @Chg{Version=[2],New=[the Ada 83 RM],Old=[RM83]} explicitly mentions the case of an @lquotes@;exact effect@rquotes@; of a program, but since so few programs have their effects defined that exactly, we don't even mention this @lquotes@;special@rquotes@; case. In particular, almost any program that uses floating point or tasking has to have some level of inexactness in the specification of its effects. And if one includes aspects of the timing of the external interactions in the external effect of the program (as is appropriate for a real-time language), no @lquotes@;exact effect@rquotes@; can be specified. For example, if two external interactions initiated by a single task are separated by a @lquotes@;@key(delay) 1.0;@rquotes@; then the language rules imply that the two external interactions have to be separated in time by at least one second, as defined by the clock associated with the @nt<delay_relative_statement>. This in turn implies that the time at which an external interaction occurs is part of the characterization of the external interaction, at least in some cases, again making the specification of the required @lquotes@;exact effect@rquotes@; impractical. @end{Discussion} An implementation that conforms to this Standard shall support each capability required by the core language as specified. In addition, an implementation that conforms to this Standard may conform to one or more Specialized Needs Annexes (or to none). Conformance to a Specialized Needs Annex means that each capability required by the Annex is provided as specified. @begin{Discussion} The last sentence defines what it means to say that an implementation conforms to a Specialized Needs Annex, namely, only by supporting all capabilities required by the Annex. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation conforming to this International Standard may provide additional @Chg{Version=[3],New=[aspects, ],Old=[]}attributes, library units, and pragmas. However, it shall not provide any @Chg{Version=[3],New=[aspect, ],Old=[]}attribute, library unit, or pragma having the same name as an @Chg{Version=[3],New=[aspect, ],Old=[]}attribute, library unit, or pragma (respectively) specified in a Specialized Needs Annex unless the provided construct is either as specified in the Specialized Needs Annex or is more limited in capability than that required by the Annex. A program that attempts to use an unsupported capability of an Annex shall either be identified by the implementation before run time or shall raise an exception at run time. @begin{Discussion} The last sentence of the preceding paragraph defines what an implementation is allowed to do when it does not "conform" to a Specialized Needs Annex. In particular, the sentence forbids implementations from providing a construct with the same name as a corresponding construct in a Specialized Needs Annex but with a different syntax (e.g., an extended syntax) or quite different semantics. The phrase concerning "more limited in capability" is intended to give permission to provide a partial implementation, such as not implementing a subprogram in a package or having a restriction not permitted by an implementation that conforms to the Annex. For example, a partial implementation of the package Ada.Decimal might have Decimal.Max_Decimal_Digits as 15 (rather than the required 18). This allows a partial implementation to grow to a fully conforming implementation. A restricted implementation might be restricted by not providing some subprograms specified in one of the packages defined by an Annex. In this case, a program that tries to use the missing subprogram will usually fail to compile. Alternatively, the implementation might declare the subprogram as abstract, so it cannot be called. Alternatively, a subprogram body might be implemented just to raise Program_Error. The advantage of this approach is that a program to be run under a fully conforming Annex implementation can be checked syntactically and semantically under an implementation that only partially supports the Annex. Finally, an implementation might provide a package declaration without the corresponding body, so that programs can be compiled, but partitions cannot be built and executed. To ensure against wrong answers being delivered by a partial implementation, implementers are required to raise an exception when a program attempts to use an unsupported capability and this can be detected only at run time. For example, a partial implementation of Ada.Decimal might require the length of the Currency string to be 1, and hence, an exception would be raised if a subprogram were called in the package Edited_Output with a length greater than 1. @end{Discussion} @end{ImplReq} @begin{DocReq} @Defn{implementation defined} @Defn{unspecified} @Defn{specified (not!)} @IndexSee{Term=[implementation-dependent],See=(unspecified)} @Defn{documentation (required of an implementation)} Certain aspects of the semantics are defined to be either @i{implementation defined} or @i{unspecified}. In such cases, the set of possible effects is specified, and the implementation may choose any effect in the set. Implementations shall document their behavior in implementation-defined situations, but documentation is not required for unspecified situations. The implementation-defined characteristics are summarized in @RefSecNum{Implementation-Defined Characteristics}. @begin{Discussion} We used to use the term @lquotes@;implementation dependent@rquotes@; instead of @lquotes@;unspecified@rquotes@;. However, that sounded too much like @lquotes@;implementation defined@rquotes@;. Furthermore, the term @lquotes@;unspecified@rquotes@; is used in the ANSI C and POSIX standards for this purpose, so that is another advantage. We also use @lquotes@;not specified@rquotes@; and @lquotes@;not specified by the language@rquotes@; as synonyms for @lquotes@;unspecified.@rquotes@; The documentation requirement is the only difference between implementation defined and unspecified. Note that the @lquotes@;set of possible effects@rquotes@; can be @lquotes@;all imaginable effects@rquotes@;, as is the case with erroneous execution. @end{Discussion} The implementation may choose to document implementation-defined behavior either by documenting what happens in general, or by providing some mechanism for the user to determine what happens in a particular case. @begin(Discussion) For example, if the standard says that library unit elaboration order is implementation defined, the implementation might describe (in its user's manual) the algorithm it uses to determine the elaboration order. On the other hand, the implementation might provide a command that produces a description of the elaboration order for a partition upon request from the user. It is also acceptable to provide cross references to existing documentation (for example, a hardware manual), where appropriate. Note that dependence of a program on implementation-defined or unspecified functionality is not defined to be an error; it might cause the program to be less portable, however. @end(Discussion) @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The behavior of implementations in implementation-defined situations shall be documented @em see @RefSec{Implementation-Defined Characteristics} for a listing.]}]} @end{DocReq} @begin{ImplAdvice} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If an implementation detects the use of an unsupported Specialized Needs Annex feature at run time, it should raise Program_Error if feasible. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Program_Error should be raised when an unsupported Specialized Needs Annex feature is used at run time.]}]} @begin{Reason} The reason we don't @i{require} Program_Error is that there are situations where other exceptions might make sense. For example, if the Real Time Systems Annex requires that the range of System.Priority include at least 30 values, an implementation could conform to the Standard (but not to the Annex) if it supported only 12 values. Since the rules of the language require Constraint_Error to be raised for out-of-range values, we cannot require Program_Error to be raised instead. @end{Reason} If an implementation wishes to provide implementation-defined extensions to the functionality of a language-defined library unit, it should normally do so by adding children to the library unit. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined extensions to the functionality of a language-defined library unit should be provided by adding children to the library unit.]}]} @begin(ImplNote) If an implementation has support code (@lquotes@;run-time system code@rquotes@;) that is needed for the execution of user-defined code, it can put that support code in child packages of System. Otherwise, it has to use some trick to avoid polluting the user's namespace. It is important that such tricks not be available to user-defined code (not in the standard mode, at least) @em that would defeat the purpose. @end(ImplNote) @end{ImplAdvice} @begin{Notes} The above requirements imply that an implementation conforming to this Standard may support some of the capabilities required by a Specialized Needs Annex without supporting all required capabilities. @begin{Discussion} A conforming implementation can partially support a Specialized Needs Annex. Such an implementation does not conform to the Annex, but it does conform to the Standard. @end{Discussion} @end{Notes} @LabeledSubClause{Method of Description and Syntax Notation} @begin{Intro} The form of an Ada program is described by means of a context-free syntax together with context-dependent requirements expressed by narrative rules. The meaning of Ada programs is described by means of narrative rules defining both the effects of each construct and the composition rules for constructs. @Leading@keepnext@;@Defn2{Term=[syntax], Sec=(notation)} @Defn2{Term=[grammar], Sec=(notation)} @Defn2{Term=[context free grammar], Sec=(notation)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(notation)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(notation)} The context-free syntax of the language is described using a simple variant of Backus-Naur Form. In particular: @begin(Itemize) @leading@keepnext@;Lower case words in a sans-serif font, some containing embedded underlines, are used to denote syntactic categories, for example: @begin(Display) @nt<case_statement> @end(Display) @leading@keepnext@;Boldface words are used to denote reserved words, for example: @begin(Display) @key(array) @end(Display) @leading@keepnext@;Square brackets enclose optional items. Thus the two following rules are equivalent. @begin(Display) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]}@Chg{Version=[2],New=[@nt<simple_return_statement>],Old=[@nt<return_statement>]} ::= @key(return) [@nt<expression>]; @Chg{Version=[2],New=[@nt<simple_return_statement>],Old=[@nt<return_statement>]} ::= @key(return); | @key(return) @nt<expression>; @end(Display) @leading@keepnext@;Curly brackets enclose a repeated item. The item may appear zero or more times; the repetitions occur from left to right as with an equivalent left-recursive rule. Thus the two following rules are equivalent. @begin(Display) @nt<term> ::= @nt<factor> {@nt<multiplying_operator> @nt<factor>} @nt<term> ::= @nt<factor> | @nt<term> @nt<multiplying_operator> @nt<factor> @end(Display) @leading@keepnext@;A vertical line separates alternative items unless it occurs immediately after an opening curly bracket, in which case it stands for itself: @begin(Display) @nt<constraint> ::= @nt<scalar_constraint> | @nt<composite_constraint> @nt<discrete_choice_list> ::= @nt<discrete_choice> {| @nt<discrete_choice>} @end(Display) @Defn2{Term=[italics],Sec=(syntax rules)} If the name of any syntactic category starts with an italicized part, it is equivalent to the category name without the italicized part. The italicized part is intended to convey some semantic information. For example @i(subtype_)@nt<name> and @i(task_)@nt<name> are both equivalent to @nt<name> alone. @end(Itemize) @begin(Discussion) @Defn{LR(1)} @Defn{ambiguous grammar} @Defn2{Term=[grammar],Sec=(resolution of ambiguity)} @Defn2{Term=[grammar],Sec=(ambiguous)} The grammar given in @Chg{Version=[2],New=[this International Standard], old=[the RM95]} is not LR(1). In fact, it is ambiguous; the ambiguities are resolved by the overload resolution rules (see @RefSecNum{The Context of Overload Resolution}). We often use @lquotes@;if@rquotes@; to mean @lquotes@;if and only if@rquotes@; in definitions. For example, if we define @lquotes@;photogenic@rquotes@; by saying, @lquotes@;A type is photogenic if it has the following properties...,@rquotes@; we mean that a type is photogenic if @i{and only if} it has those properties. It is usually clear from the context, and adding the @lquotes@;and only if@rquotes@; seems too cumbersome. When we say, for example, @lquotes@;a @nt{declarative_item} of a @nt{declarative_part}@rquotes@;, we are talking about a @nt{declarative_item} immediately within that @nt{declarative_part}. When we say @lquotes@;a @nt{declarative_item} in, or within, a @nt{declarative_part}@rquotes@;, we are talking about a @nt{declarative_item} anywhere in the @nt{declarative_part}, possibly deeply nested within other @nt{declarative_part}s. (This notation doesn't work very well for @nt{name}s, since the name @lquotes@;of@rquotes@; something also has another meaning.) When we refer to the name of a language-defined entity (for example, Duration), we mean the language-defined entity even in programs where the declaration of the language-defined entity is hidden by another declaration. For example, when we say that the expected type for the @nt<expression> of a @nt<delay_relative_statement> is Duration, we mean the language-defined type Duration that is declared in Standard, not some type Duration the user might have declared. @end(Discussion) @begin{WideAbove} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0004-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The delimiters, compound delimiters, reserved words, and @nt{numeric_literal}s are exclusively made of the characters whose code @Chg{Version=[3],New=[point],Old=[position]} is between 16#20# and 16#7E#, inclusively. The special characters for which names are defined in this International Standard (see @RefSecNum{Character Set}) belong to the same range. @Redundant[For example, the character E in the definition of @Chg{Version=[3], New=[@nt{exponent}],Old=[exponent]} is the character whose name is @lquotes@;LATIN CAPITAL LETTER E@rquotes@;, not @lquotes@;GREEK CAPITAL LETTER EPSILON@rquotes@;.]]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This just means that programs can be written in plain ASCII characters; no characters outside of the 7-bit range are required.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0227-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[When this International Standard mentions the conversion of some character or sequence of characters to upper case, it means the character or sequence of characters obtained by using @Chg{Version=[3],New=[simple upper case mapping],Old=[locale-independent full case folding]}, as defined by documents referenced in the note in @Chg{Version=[3],New=[Clause],Old=[section]} 1 of ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedAdded]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Unless otherwise specified for sequences of characters, case folding is applied to the sequence, not to individual characters. It sometimes can make a difference.]}]} @end{Discussion} @end{WideAbove} @begin{WideAbove} @Defn{syntactic category} A @i{syntactic category} is a nonterminal in the grammar defined in BNF under @lquotes@;@SyntaxTitle.@rquotes@; Names of syntactic categories are set in a different font, @ntf{like_this}. @end{WideAbove} @ToGlossaryAlso{Term=<Construct>, Text=<A @i(construct) is a piece of text (explicit or implicit) that is an instance of a syntactic category defined under @lquotes@;@SyntaxTitle@rquotes@;.>} @begin{Ramification} For example, an @nt{expression} is a construct. A declaration is a construct, whereas the thing declared by a declaration is an @lquotes@;entity.@rquotes@; @end{Ramification} @begin{Discussion} @lquotes@;Explicit@rquotes@; and @lquotes@;implicit@rquotes@; don't mean exactly what you might think they mean: The text of an instance of a generic is considered explicit, even though it does not appear explicitly (in the nontechnical sense) in the program text, and even though its meaning is not defined entirely in terms of that text. @end{Discussion} @Defn2{term=<constituent>, Sec=<of a construct>} A @i{constituent} of a construct is the construct itself, or any construct appearing within it. @Defn{arbitrary order} Whenever the run-time semantics defines certain actions to happen in an @i{arbitrary order}, this means that the implementation shall arrange for these actions to occur in a way that is equivalent to some sequential order, following the rules that result from that sequential order. When evaluations are defined to happen in an arbitrary order, with conversion of the results to some subtypes, or with some run-time checks, the evaluations, conversions, and checks may be arbitrarily interspersed, so long as each expression is evaluated before converting or checking its value. @PDefn2{Term=[type conversion],Sec=(arbitrary order)} @PDefn2{Term=[conversion],Sec=(arbitrary order)} @Redundant[Note that the effect of a program can depend on the order chosen by the implementation. This can happen, for example, if two actual parameters of a given call have side effects.] @begin{Discussion} Programs will be more portable if their external effect does not depend on the particular order chosen by an implementation. @end{Discussion} @begin{Ramification} Additional reordering permissions are given in @RefSec(Exceptions and Optimization). There is no requirement that the implementation always choose the same order in a given kind of situation. In fact, the implementation is allowed to choose a different order for two different executions of the same construct. However, we expect most implementations will behave in a relatively predictable manner in most situations. @end{Ramification} @begin{Reason} The @lquotes@;sequential order@rquotes@; wording is intended to allow the programmer to rely on @lquotes@;benign@rquotes@; side effects. For example, if F is a function that returns a unique integer by incrementing some global and returning the result, a call such as P(F, F) is OK if the programmer cares only that the two results of F are unique; the two calls of F cannot be executed in parallel, unless the compiler can prove that parallel execution is equivalent to some sequential order. @end{Reason} @end{Intro} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @begin{Notes} The syntax rules describing structured constructs are presented in a form that corresponds to the recommended paragraphing. For example, an @nt{if_statement} is defined as: @begin(Example) @nt<if_statement> ::= @key(if) @nt<condition> @key(then) @nt<sequence_of_statements> {@key(elsif) @nt<condition> @key(then) @nt<sequence_of_statements>} [@key(else) @nt<sequence_of_statements>] @key(end if); @end(Example) The line breaks and indentation in the syntax rules indicate the recommended line breaks and indentation in the corresponding constructs. The preferred places for other line breaks are after semicolons. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We now explicitly say that the lexical elements of the language (with a few exceptions) are made up of characters in the lower half of the Latin-1 character set. This is needed to avoid confusion given the new capability to use most ISO 10646 characters in identifiers and strings.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[We now explicitly define what the Standard means by upper case, as there are many possibilities for ISO 10646 characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The example for square brackets has been changed as there is no longer a @ntf{return_statement} syntax rule.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0227-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Upper case is defined by "simple upper case mapping", because "full case folding" is a mapping (mostly) to lower case.]} @end{DiffWord2005} @LabeledSubClause{Classification of Errors} @begin{ImplReq} @Leading@Keepnext@;The language definition classifies errors into several different categories: @begin(Itemize) @Keepnext@;Errors that are required to be detected prior to run time by every Ada implementation; @NoPrefix@;These errors correspond to any violation of a rule given in this International Standard, other than those listed below. In particular, violation of any rule that uses the terms shall, allowed, permitted, legal, or illegal belongs to this category. Any program that contains such an error is not a legal Ada program; on the other hand, the fact that a program is legal does not mean, @i(per se), that the program is free from other forms of error. @NoPrefix@Defn{compile-time error} @Defn2{Term=[error], Sec=(compile-time)} @IndexSee{Term=[link-time error],See=(post-compilation error)} @Defn2{Term=[error], Sec=(link-time)} The rules are further classified as either compile time rules, or post compilation rules, depending on whether a violation has to be detected at the time a compilation unit is submitted to the compiler, or may be postponed until the time a compilation unit is incorporated into a partition of a program. @begin{Ramification} See, for example, @RefSec(Subunits of Compilation Units), for some errors that are detected only after compilation. Implementations are allowed, but not required, to detect post compilation rules at compile time when possible. @end{Ramification} @Keepnext@;Errors that are required to be detected at run time by the execution of an Ada program; @NoPrefix@Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} The corresponding error situations are associated with the names of the predefined exceptions. Every Ada compiler is required to generate code that raises the corresponding exception if such an error situation arises during program execution. @Redundant[If such an error situation is certain to arise in every execution of a construct, then an implementation is allowed (although not required) to report this fact at compilation time.] @Keepnext@;Bounded errors; @NoPrefix@;The language rules define certain kinds of errors that need not be detected either prior to or during run time, but if not detected, the range of possible effects shall be bounded. @Defn{bounded error} The errors of this category are called @i{bounded errors}. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible effects of a given bounded error are specified for each such error, but in any case one possible effect of a bounded error is the raising of the exception Program_Error. @Keepnext@;Erroneous execution. @NoPrefix@Defn{erroneous execution} In addition to bounded errors, the language rules define certain kinds of errors as leading to @i{erroneous execution}. Like bounded errors, the implementation need not detect such errors either prior to or during run time. Unlike bounded errors, there is no language-specified bound on the possible effect of erroneous execution; the effect is in general not predictable. @begin{Ramification} Executions are erroneous, not programs or parts of programs. Once something erroneous happens, the execution of the entire program is erroneous from that point on, and potentially before given possible reorderings permitted by @RefSecNum(Exceptions and Optimization) and elsewhere. We cannot limit it to just one partition, since partitions are not required to live in separate address spaces. (But implementations are encouraged to limit it as much as possible.) Suppose a program contains a pair of things that will be executed @lquotes@;in an arbitrary order.@rquotes@; It is possible that one order will result in something sensible, whereas the other order will result in erroneous execution. If the implementation happens to choose the first order, then the execution is not erroneous. This may seem odd, but it is not harmful. Saying that something is erroneous is semantically equivalent to saying that the behavior is unspecified. However, @lquotes@;erroneous@rquotes@; has a slightly more disapproving flavor. @end{Ramification} @end(Itemize) @end{ImplReq} @begin{ImplPerm} @Redundant[@Defn2{Term={mode of operation}, Sec=(nonstandard)} @Defn{nonstandard mode}An implementation may provide @i(nonstandard modes) of operation. Typically these modes would be selected by a @nt<pragma> or by a command line switch when the compiler is invoked. When operating in a nonstandard mode, the implementation may reject @nt<compilation_unit>s that do not conform to additional requirements associated with the mode, such as an excessive number of warnings or violation of coding style guidelines. Similarly, in a nonstandard mode, the implementation may apply special optimizations or alternative algorithms that are only meaningful for programs that satisfy certain criteria specified by the implementation. @Defn2{Term={mode of operation}, Sec=(standard)} @Defn{standard mode} In any case, an implementation shall support a @i(standard) mode that conforms to the requirements of this International Standard; in particular, in the standard mode, all legal @nt<compilation_unit>s shall be accepted.] @begin{Discussion} These permissions are designed to authorize explicitly the support for alternative modes. Of course, nothing we say can prevent them anyway, but this (redundant) paragraph is designed to indicate that such alternative modes are in some sense @lquotes@;approved@rquotes@; and even encouraged where they serve the specialized needs of a given user community, so long as the standard mode, designed to foster maximum portability, is always available. @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If an implementation detects a bounded error or erroneous execution, it should raise Program_Error. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If a bounded error or erroneous execution is detected, Program_Error should be raised.]}]} @end{ImplAdvice} @begin{DiffWord83} Some situations that are erroneous in Ada 83 are no longer errors at all. For example, depending on the parameter passing mechanism when unspecified is possibly nonportable, but not erroneous. Other situations that are erroneous in Ada 83 are changed to be bounded errors. In particular, evaluating an uninitialized scalar variable is a bounded error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible results are to raise Program_Error (as always), or to produce a machine-representable value (which might not be in the subtype of the variable). @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Violating a Range_Check or Overflow_Check raises Constraint_Error, even if the value came from an uninitialized variable. This means that optimizers can no longer @lquotes@;assume@rquotes@; that all variables are initialized within their subtype's range. Violating a check that is suppressed remains erroneous. The @lquotes@;incorrect order dependences@rquotes@; category of errors is removed. All such situations are simply considered potential nonportabilities. This category was removed due to the difficulty of defining what it means for two executions to have a @lquotes@;different effect.@rquotes@; For example, if a function with a side effect is called twice in a single expression, it is not in principle possible for the compiler to decide whether the correctness of the resulting program depends on the order of execution of the two function calls. A compile time warning might be appropriate, but raising of Program_Error at run time would not be. @end{DiffWord83} @LabeledClause{Normative References} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{references} @Defn{bibliography} The following @Chg{Version=[3],New=[documents, in whole or in part, are normatively referenced in this document and are indispensable for its application. For dated references, only the edition cited applies. For undated references, the latest edition of the referenced document (including any amendments) applies.],Old=[standards contain provisions which, through reference in this text, constitute provisions of this International Standard. At the time of publication, the editions indicated were valid. All standards are subject to revision, and parties to agreements based on this International Standard are encouraged to investigate the possibility of applying the most recent editions of the standards indicated below. Members of IEC and ISO maintain registers of currently valid International Standards.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0127-2],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[@Defn{ISO 639-3:2007} @Defn{639-3:2007, ISO standard} @Defn{Language code standard} ISO 639-3:2007, @i{Codes for the representation of names of languages @em Part 3: Alpha-3 code for comprehensive coverage of languages}.]} @Defn{ISO/IEC 646:1991} @Defn{646:1991, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(7-bit)} ISO/IEC 646:1991, @i{Information technology @em ISO 7-bit coded character set for information interchange}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Chg{Version=[2],New=[@Defn{ISO/IEC 1539-1:2004} @Defn{1539-1:2004, ISO/IEC standard} @Defn{Fortran standard}], Old=[@Defn{ISO/IEC 1539:1991} @Defn{1539:1991, ISO/IEC standard} @Defn{FORTRAN standard}]} ISO/IEC @Chg{Version=[2],New=[1539-1:2004],Old=[1539:1991]}, @i{Information technology @em Programming languages @em @Chg{Version=[2], New=[Fortran @em Part 1: Base language],Old=[FORTRAN]}}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Chg{Version=[2],New=[@Defn{ISO 1989:2002} @Defn{1989:2002, ISO standard}],Old=[@Defn{ISO 1989:1985} @Defn{1989:1985, ISO standard}]} @Defn{COBOL standard} ISO@Chg{Version=[2],New=[/IEC],Old=[]} 1989:@Chg{Version=[2],New=[2002],Old=[1985]}, @i{@Chg{Version=[2],New=[Information technology @em ],Old=[]}Programming languages @em COBOL}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0127-2],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[@Defn{ISO/IEC 3166-1:2006} @Defn{3166-1:2006, ISO/IEC standard} @Defn{Country code standard} ISO/IEC 3166-1:2006, @i{Codes for the representation of names of countries and their subdivisions @em Part 1: Country Codes}.]} @Defn{ISO/IEC 6429:1992} @Defn{6429:1992, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(control functions)} ISO/IEC 6429:1992, @i{Information technology @em Control functions for coded graphic character sets}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[@Defn{ISO 8601:2004} @Defn{date and time formatting standard} ISO 8601:2004, @i{Data elements and interchange formats @em Information interchange @em Representation of dates and times}.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Chg{Version=[3],New=[@Defn{ISO/IEC 8859-1:1998} @Defn{8859-1:1998, ISO/IEC standard}],Old=[@Defn{ISO/IEC 8859-1:1987} @Defn{8859-1:1987, ISO/IEC standard}]} @Defn2{Term=[character set standard],Sec=(8-bit)} ISO/IEC 8859-1:@Chg{Version=[3],New=[1998],Old=[1987]}, @i{Information @Chg{Version=[3],New=[technology],Old=[processing]} @em 8-bit single-byte coded @Chg{Version=[3],New=[graphic ],Old=[]}character sets @em Part 1: Latin alphabet No. 1}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Chg{Version=[2],New=[@Chg{Version=[3],New=[@Defn{ISO/IEC 9899:2011} @Defn{9899:2011, ISO/IEC standard}],Old=[@Defn{ISO/IEC 9899:1999} @Defn{9899:1999, ISO/IEC standard}]}], Old=[@Defn{ISO/IEC 9899:1990} @Defn{9899:1990, ISO/IEC standard}]} @Defn{C standard} ISO/IEC 9899:@Chg{Version=[2],New=[@Chg{Version=[3],New=[2011],Old=[1999]}], Old=[1990]}, @i{@Chg{Version=[3],New=[Information technology @em ],Old=[]}Programming languages @em C}@Chg{Version=[2],New=[@Chg{Version=[3],New=[],Old=[, supplemented by Technical Corrigendum 1:2001 and Technical Corrigendum 2:2004]}],Old=[]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Unlike Fortran and COBOL, which added the @i{Information technology} prefix to the titles of their standard, C did not. This was confirmed in the list of standards titles on the ISO web site. No idea why ISO allowed that@Comment{, or whether C is planning to secede from SC22}.]}]} @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0001],ARef=[AI95-00124-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Chg{Version=[2],New=[@Chg{Version=[3],New=[@Defn{ISO/IEC 10646:2011} @Defn{10646:2011, ISO/IEC standard}],Old=[@Defn{ISO/IEC 10646:2003} @Defn{10646:2003, ISO/IEC standard}]} @Defn2{Term=[character set standard],Sec=(16 and 32-bit)} ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}, @i{Information technology @em Universal Multiple-Octet Coded Character Set (UCS)}.], Old=[@Defn{ISO/IEC 10646-1:1993} @Defn{10646-1:1993, ISO/IEC standard} @Defn2{Term=[character set standard],Sec=(16-bit)} ISO/IEC 10646-1:1993, @i{Information technology @em Universal Multiple-Octet Coded Character Set (UCS) @em Part 1: Architecture and Basic Multilingual Plane}@Chg{Version=[1],New=[, supplemented by Technical Corrigendum 1:1996], Old=[]}.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0001],ARef=[AI95-00124-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00285-01]} @ChgNote{This is of only historical interest, so it was deleted; we use the Unicode characterization now.} @ChgDeleted{Version=[2],Text=[ @Chg{Version=[1],New=[The Technical Corrigendum 1:1996 is needed so that character codes C6 and E6 (the ligatures @latin1(198) and @latin1(230)) are considered letters. These were named Latin Ligature AE in the original 1993 version, which would exclude them from being letters as defined in @RefSec{Character Set}.], Old=[]}]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00376-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@Defn{ISO/IEC 14882:2011} @Defn{14882:2011, ISO/IEC standard}],Old=[@Defn{ISO/IEC 14882:2003} @Defn{14882:2003, ISO/IEC standard}]} @Defn{C++ standard} ISO/IEC 14882:@Chg{Version=[3],New=[2011],Old=[2003]}, @i{@Chg{Version=[3],New=[Information technology @em ],Old=[]}Programming languages @em C++}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This title is also missing the @i{Information technology} part. That was confirmed in the list of standards titles on the ISO web site.]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{ISO/IEC TR 19769:2004} @Defn{19769:2004, ISO/IEC technical report} ISO/IEC TR 19769:2004, @i{Information technology @em Programming languages, their environments and system software interfaces @em Extensions for the programming language C to support new character data types}.]} @begin{Discussion} @Defn{POSIX} POSIX, @i{Portable Operating System Interface (POSIX) @em Part 1: System Application Program Interface (API) [C Language]}, The Institute of Electrical and Electronics Engineers, 1990. @end{Discussion} @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00376-01],ARef=[AI95-00415-01]} @ChgAdded{Version=[2],Text=[Updated references to the most recent versions of these standards. Added C++ and time standards. Added C character set technical report.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2]} @ChgAdded{Version=[3],Text=[Added language and country code standards for locale support.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[Updated references to the most recent versions of these standards.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[3],New=[Terms and Definitions],Old=[Definitions]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @Defn2{Term=[italics],Sec=(terms introduced or defined)} Terms are defined throughout this International Standard, indicated by @i(italic) type. Terms explicitly defined in this International Standard are not to be presumed to refer implicitly to similar terms defined elsewhere. @Chg{Version=[2],New=[Mathematical terms not defined in this International Standard are to be interpreted according to the @i<CRC Concise Encyclopedia of Mathematics, Second Edition>. Other terms],Old=[Terms]} not defined in this International Standard are to be interpreted according to the @i(Webster's Third New International Dictionary of the English Language). Informal descriptions of some terms are also given in @RefSec{Glossary}. @Comment{These are here to avoid a blank paragraph at the end, and because they have to be somewhere.} @SeeAlso{Primary=[library unit], Other=(language-defined library units)} @SeeOther{Primary=[predefined library unit], Other=(language-defined library units)} @SeeAlso{Primary=[type], Other=(language-defined types)} @SeeOther{Primary=[predefined type], Other=(language-defined types)} @begin{Discussion} The index contains an entry for every defined term. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00415-01]} @ChgAdded{Version=[2],Text=[The contents of the @i<CRC Concise Encyclopedia of Mathematics, Second Edition> can be accessed on @URLLink{URL=[http://www.mathworld.com],Text=[http://www.mathworld.com]}. The ISBN number of the book is ISBN 1584883472.]} @end{Discussion} @begin{GlossaryMarker} Each term defined in @RefSecNum{Glossary} is marked like this. @end{GlossaryMarker} @end{Intro} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} Here are some AARM-only definitions: @Defn{Ada Rapporteur Group (ARG)} @Defn(ARG) The Ada Rapporteur Group (ARG) interprets the @Chg{Version=[1],New=<Ada Reference Manual>,Old=<RM83>}. @Defn{Ada Issue (AI)} @Defn(AI) An Ada Issue (AI) is a numbered ruling from the ARG.@Chg{Version=[1],New=< Ada Issues created for Ada 83 are denoted as "AI83", while Ada Issues created for Ada 95 are denoted as "AI95" in this document.@Chg{Version=[3],New=< Similarly, Ada Issues created for Ada 2005 are denoted as "AI05">,Old=<>}>,Old=<>} @Defn{Ada Commentary Integration Document (ACID)} @Defn(ACID) The Ada Commentary Integration Document (ACID) is an edition of @Chg{Version=[2],New=[the Ada 83 RM],Old=[RM83]} in which clearly marked insertions and deletions indicate the effect of integrating the approved AIs. @Defn{Uniformity Rapporteur Group (URG)} @Defn(URG) The Uniformity Rapporteur Group (URG) @Chg{Version=[1],New=<issued>,Old=<issues>} recommendations intended to increase uniformity across Ada implementations. @Chg{Version=[1],New=<The functions of the URG have been assumed by the ARG.>,Old=<>} @Defn{Uniformity Issue (UI)} @Defn(UI) A Uniformity Issue (UI) @Chg{Version=[1],New=<was>,Old=<is>} a numbered recommendation from the URG. @Chg{Version=[1],New=<A Defect Report and Response is an official query to WG9 about an error in the standard. Defect Reports are processed by the ARG, and are referenced here by their ISO numbers: 8652/nnnn. Most changes to the Ada 95 standard include reference(s) to the Defect Report(s) that prompted the change.>,Old=<>} @Chg{Version=[1],New=[@PDefn2{Term=[ACVC],Sec=(Ada Compiler Validation Capability)} @PDefn2{Term=[Ada Compiler Validation Capability],Sec=(ACVC)} @PDefn2{Term=[ACATS],Sec=(Ada Conformity Assessment Test Suite)} @PDefn2{Term=[Ada Conformity Assessment Test Suite],Sec=(ACATS)} The @i<Ada Conformity Assessment Test Suite (ACATS)> is a set of tests intended to check the conformity of Ada implementations to this standard. This set of tests was previously known as the Ada Compiler Validation Capability (ACVC).],Old=[]} @end{Discussion} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/02.mss���������������������������������������������������������������0000755�0001752�0001001�00000261312�12066652506�016377� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(02, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:02 $} @LabeledSection{Lexical Elements} @Comment{$Source: e:\\cvsroot/ARM/Source/02.mss,v $} @Comment{$Revision: 1.85 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[The text of a program consists of the texts of one or more @nt<compilation>s. The text of a @nt<compilation> is a sequence of lexical elements, each composed of characters; the rules of composition are given in this @Chg{Version=[3],New=[clause],Old=[section]}. @nt{Pragma}s, which provide certain information for the compiler, are also described in this @Chg{Version=[3],New=[clause],Old=[section]}.] @end{Intro} @LabeledClause{Character Set} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Defn{character set} The @Chg{Version=[2],New=[character repertoire for the text of an Ada program consists of the entire coding space described by the ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} Universal Multiple-Octet Coded Character Set. This coding space is organized in @i<planes>, each plane comprising 65536 characters.@Defn2{Term=[plane],Sec=[character]} @Defn{character plane}],Old=[only characters allowed outside of @nt{comment}s are the @nt{graphic_character}s and @ntf{format_effector}s.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[Any character, including an @ntf<other_control_function>, is allowed in a comment.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]}@ChgNote{Moved below} @ChgDeleted{Version=[2],Text=[Note that this rule doesn't really have much force, since the implementation can represent characters in the source in any way it sees fit. For example, an implementation could simply define that what seems to be a nongraphic, non-format-effector character is actually a representation of the space character.]} @end{Ramification} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} It is our intent to follow the terminology of @Chg{Version=[2],New=[ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}],Old=[ISO 10646 BMP]} where appropriate, and to remain compatible with the character classifications defined in @RefSec{Character Handling}.@Chg{Version=[2], New=[],Old=[Note that our definition for @nt<graphic_character> is more inclusive than that of ISO 10646-1.]} @end(Discussion) @end{Intro} @begin{Syntax} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 and 3 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<character>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Syn2{graphic_character} | @Synf{format_effector} | @Synf{other_control_function}>}"} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<graphic_character>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Synf{identifier_letter} | @Synf{digit} | @Synf{space_character} | @Synf{special_character}>}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0266-1]} @ChgAdded{Version=[2],Text=[A @ntf{character} is defined by this International Standard for each cell in the coding space described by ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}, regardless of whether or not ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} allocates a character to that cell.]} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0079-1],ARef=[AI05-0262-1],ARef=[AI05-0266-1]} The@Chg{Version=[2],New=[],Old=[ character repertoire for the text of an Ada program consists of the collection of characters @Chg{Version=[2],New=[described by the ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}], Old=[called the Basic Multilingual Plane (BMP) of the ISO 10646]} Universal Multiple-Octet Coded Character Set, plus a set of @ntf<format_effector>s and, in comments only, a set of @ntf<other_control_function>s; the]} coded representation for @Chg{Version=[2],New=[],Old=[these ]}characters is implementation defined @Redundant[(it need not be a representation defined within @Chg{Version=[2],New=[ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}], Old=[ISO-10646-1]})].@Chg{Version=[2],New=[ A character whose relative code @Chg{Version=[3],New=[point],Old=[position]} in its plane is 16#FFFE# or 16#FFFF# is not allowed anywhere in the text of a program.],Old=[]}@Chg{Version=[3],New=[ The only characters allowed outside of comments are those in categories @ntf{other_format}, @ntf{format_effector}, and @ntf{graphic_character}.],Old=[]} @ImplDef{The coded representation for the text of an Ada program.} @begin{Ramification}@ChgNote{Moved from above} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Note that this rule doesn't really have much force, since the implementation can represent characters in the source in any way it sees fit. For example, an implementation could simply define that what seems to be an @ntf{other_private_use} character is actually a representation of the space character.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0266-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The semantics of an Ada program whose text is not in Normalization Form KC (as defined by @Chg{Version=[3],New=[Clause 21],Old=[section 24]} of ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}) is implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The semantics of an Ada program whose text is not in Normalization Form KC.]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1],ARef=[AI05-0299-1]} The description of the language definition in this International Standard uses the @Chg{Version=[2], New=[character properties General Category, Simple Uppercase Mapping, Uppercase Mapping, and Special Case Condition of the documents referenced by the note in @Chg{Version=[3],New=[Clause],Old=[section]} 1 of ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}],Old=[graphic symbols defined for Row 00: Basic Latin and Row 00: Latin-1 Supplement of the ISO 10646 BMP; these correspond to the graphic symbols of ISO 8859-1 (Latin-1); no graphic symbols are used in this International Standard for characters outside of Row 00 of the BMP]}. The actual set of graphic symbols used by an implementation for the visual representation of the text of an Ada program is not specified. @PDefn{unspecified} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Leading@keepnext@;@Chg{Version=[2],New=[Characters],Old=[The categories of characters]} are @Chg{Version=[2],New=[categorized],Old=[defined]} as follows: @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1],ARef=[AI05-0262-1],ARef=[AI05-0266-1]} @ChgAdded{Version=[2],Text=[Our character classification considers that the cells not allocated in ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} are graphic characters, except for those whose relative code @Chg{Version=[3],New=[point],Old=[position]} in their plane is 16#FFFE# or 16#FFFF#. This seems to provide the best compatibility with future versions of ISO/IEC 10646, as future characters can @Chg{Version=[3],New=[],Old=[be ]}already be used in Ada character and string literals.]} @end{Discussion} @begin{Description} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{identifier_letter}@ntf<identifier_letter>@\@ntf{upper_case_identifier_letter} | @ntf{lower_case_identifier_letter}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[We use @ntf<identifier_letter> instead of simply @ntf<letter> because ISO 10646 BMP includes many other characters that would generally be considered "letters."]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{letter_uppercase}@ntf{letter_uppercase}], Old=[@Defn{upper_case_identifier_letter}@ntf<upper_case_identifier_letter>]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Letter, Uppercase@rquotes@;], Old=[of Row 00 of ISO 10646 BMP whose name begins @lquotes@;Latin Capital Letter@rquotes@;]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{letter_lowercase}@ntf{letter_lowercase}], Old=[@Defn{lower_case_identifier_letter}@ntf<lower_case_identifier_letter>]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Letter, Lowercase@rquotes@;], Old=[of Row 00 of ISO 10646 BMP whose name begins @lquotes@;Latin Small Letter@rquotes@;]}. @begin{Honest} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0001],ARef=[AI95-00124-01]} @Comment{The change in subclause 1.3 for 8652/0001 handles this problem.} @ChgDeleted{Version=[1],Text=[The above rules do not include the ligatures @latin1(198) and @latin1(230). However, the intent is to include these characters as identifier letters. This problem was pointed out by a comment from the Netherlands.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_titlecase}@ntf{letter_titlecase}@\Any character whose General Category is defined to be @lquotes@;Letter, Titlecase@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_modifier}@ntf{letter_modifier}@\Any character whose General Category is defined to be @lquotes@;Letter, Modifier@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{letter_other}@ntf{letter_other}@\Any character whose General Category is defined to be @lquotes@;Letter, Other@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{mark_non_spacing}@ntf{mark_non_spacing}@\Any character whose General Category is defined to be @lquotes@;Mark, Non-Spacing@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{mark_non_spacing}@ntf{mark_spacing_combining}@\Any character whose General Category is defined to be @lquotes@;Mark, Spacing Combining@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{number_decimal}@ntf{number_decimal}], Old=[@Defn{digit}@nt{digit}]}@\@Chg{Version=[2],New=[Any character whose General Category is defined to be @lquotes@;Number, Decimal@rquotes@;], Old=[One of the characters 0, 1, 2, 3, 4, 5, 6, 7, 8, or 9]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{number_letter}@ntf{number_letter}@\Any character whose General Category is defined to be @lquotes@;Number, Letter@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{punctuation_connector}@ntf{punctuation_connector}@\Any character whose General Category is defined to be @lquotes@;Punctuation, Connector@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_format}@ntf{other_format}@\Any character whose General Category is defined to be @lquotes@;Other, Format@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{separator_space}@ntf<separator_space>], Old=[@Defn{space_character}@ntf{space_character}]}@\@Chg{Version=[2],New=[Any character whose General Category is defined to be @lquotes@;Separator, Space@rquotes@;.],Old=[The character of ISO 10646 BMP named @lquotes@;Space@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[@Defn{separator_line}@ntf{separator_line}], Old=[@Defn{special_character}@ntf{special_character}]}@\Any character @Chg{Version=[2],New=[whose General Category is defined to be @lquotes@;Separator, Line@rquotes@;.], Old=[of the ISO 10646 BMP that is not reserved for a control function, and is not the @ntf<space_character>, an @ntf<identifier_letter>, or a @ntf<digit>.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that the no break space and soft hyphen are @ntf<special_character>s, and therefore @nt<graphic_character>s. They are not the same characters as space and hyphen-minus.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{separator_paragraph}@ntf{separator_paragraph}@\Any character whose General Category is defined to be @lquotes@;Separator, Paragraph@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @Defn{format_effector}@ntf<format_effector>@\The @Chg{Version=[2],New=[characters whose code @Chg{Version=[3],New=[points],Old=[positions]} are 16#09# (CHARACTER TABULATION), 16#0A# (LINE FEED), 16#0B# (LINE TABULATION), 16#0C# (FORM FEED), 16#0D# (CARRIAGE RETURN), 16#85# (NEXT LINE), and the characters in categories @ntf{separator_line} and @ntf{separator_paragraph}], Old=[control functions of ISO 6429 called character tabulation (HT), line tabulation (VT), carriage return (CR), line feed (LF), and form feed (FF)]}. @IndexSeeAlso{Term=[control character],See=(format_effector)} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC 10646:2003 does not define the names of control characters, but rather refers to the names defined by ISO/IEC 6429:1992. These are the names that we use here.@Comment{10646:2011 gives a list of the long names from 6429:1992, so I'm not sure the above is true anymore. Best leave the old reference.}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_control}@ntf{other_control}@\Any character whose General Category is defined to be @lquotes@;Other, Control@rquotes@;, and which is not defined to be a @ntf<format_effector>.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_private_use}@ntf{other_private_use}@\Any character whose General Category is defined to be @lquotes@;Other, Private Use@rquotes@;.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{other_surrogate}@ntf{other_surrogate}@\Any character whose General Category is defined to be @lquotes@;Other, Surrogate@rquotes@;.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @Chg{Version=[2],New=[@Defn{graphic_character}@ntf{graphic_character}], Old=[@Defn{other_control_function}@ntf<other_control_function>]}@\@Chg{Version=[2], New=[Any character that is not in the categories @ntf{other_control}, @ntf{other_private_use}, @ntf{other_surrogate}, @ntf{format_effector}, and whose relative code @Chg{Version=[3],New=[point],Old=[position]} in its plane is neither 16#FFFE# nor 16#FFFF#.], Old=[Any control function, other than a @ntf<format_effector>, that is allowed in a comment; the set of @ntf<other_control_function>s allowed in comments is implementation defined. @IndexSeeAlso{Term=[control character],See=(other_control_function)}]} @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2],Text=[The control functions allowed in comments.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=`We considered basing the definition of lexical elements on Annex A of ISO/IEC TR 10176 (4th edition), which lists the characters which should be supported in identifiers for all programming languages, but we finally decided against this option. Note that it is not our intent to diverge from ISO/IEC TR 10176, except to the extent that ISO/IEC TR 10176 itself diverges from ISO/IEC 10646:2003 (which is the case at the time of this writing [January 2005]).'} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[More precisely, we intend to align strictly with ISO/IEC 10646:2003. It must be noted that ISO/IEC TR 10176 is a Technical Report while ISO/IEC 10646:2003 is a Standard. If one has to make a choice, one should conform with the Standard rather than with the Technical Report. And, it turns out that one @i<must> make a choice because there are important differences between the two:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC TR 10176 is still based on ISO/IEC 10646:2000 while ISO/IEC 10646:2003 has already been published for a year. We cannot afford to delay the adoption of our amendment until ISO/IEC TR 10176 has been revised.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are considerable differences between the two editions of ISO/IEC 10646, notably in supporting characters beyond the BMP (this might be significant for some languages, e.g. Korean).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO/IEC TR 10176 does not define case conversion tables, which are essential for a case-insensitive language like Ada. To get case conversion tables, we would have to reference either ISO/IEC 10646:2003 or Unicode, or we would have to invent our own.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For the purpose of defining the lexical elements of the language, we need character properties like categorization, as well as case conversion tables. These are mentioned in ISO/IEC 10646:2003 as useful for implementations, with a reference to Unicode. Machine-readable tables are available on the web at URLs:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@URLLink{URL=[http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt], Text=[http://www.unicode.org/Public/4.0-Update/UnicodeData-4.0.0.txt]} @URLLink{URL=[http://www.unicode.org/Public/4.0-Update/CaseFolding-4.0.0.txt], Text=[http://www.unicode.org/Public/4.0-Update/CaseFolding-4.0.0.txt]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[with an explanatory document found at URL:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@URLLink{URL=[http://www.unicode.org/Public/4.0-Update/UCD-4.0.0.html], Text=[http://www.unicode.org/Public/4.0-Update/UCD-4.0.0.html]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual text of the standard only makes specific references to the corresponding clauses of ISO/IEC 10646:2003, not to Unicode.]} @end{Discussion} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Leading@Chg{Version=[2],New=[],Old=[@Defn{names of @ntf{special_character}s} @Defn2{Term=[special_character],Sec=(names)}]}The following names are used when referring to certain @Chg{Version=[2],New=[characters (the first name is that given in ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]})],Old=[@ntf{special_character}s]}: @Defn{quotation mark} @Defn{number sign} @Defn{ampersand} @Defn{apostrophe} @Defn{tick} @Defn{left parenthesis} @Defn{right parenthesis} @Defn{asterisk} @Defn{multiply} @Defn{plus sign} @Defn{comma} @Defn{hyphen-minus} @Defn{minus} @Defn{full stop} @Defn{dot} @Defn{point} @Defn{solidus} @Defn{divide} @Defn{colon} @Defn{semicolon} @Defn{less-than sign} @Defn{equals sign} @Defn{greater-than sign} @Defn{low line} @Defn{underline} @Defn{vertical line} @Chg{Version=[2],New=[@Defn{exclamation point} @Defn{percent sign}], Old=[@Defn{left square bracket} @Defn{right square bracket} @Defn{left curly bracket} @Defn{right curly bracket}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0266-1]} @Chg{Version=[2],New=[@Defn{graphic symbols}@Defn{glyphs}This table serves to show the correspondence between ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} names and the graphic symbols (glyphs) used in this International Standard. These are the characters], Old=[These are the ones]} that play a special role in the syntax of Ada@Chg{Version=[2],New=[], Old=[ 95, or in the syntax rules; we don't bother to define names for all characters. The first name given is the name from ISO 10646-1; the subsequent names, if any, are those used within the standard, depending on context]}. @end{Discussion} @Comment{The original version follows here (commented out) @begin{Display} @TabClear()@TabSet(P9) @begin(TwoCol) @NoParanum@;symbol @\name @NoParanum@; " @\quotation mark # @\number sign & @\ampersand ' @\apostrophe, tick ( @\left parenthesis ) @\right parenthesis * @\asterisk, multiply + @\plus sign , @\comma @en@; @\hyphen-minus, minus . @\full stop, dot, point / @\solidus, divide @NewColumn @NoParanum@;symbol @\name @NoParanum@; : @\colon ; @\semicolon < @\less-than sign = @\equals sign > @\greater-than sign _ @\low line, underline | @\vertical line [ @\left square bracket ] @\right square bracket { @\left curly bracket } @\right curly bracket @end(TwoCol) @end{Display}} @Comment{We use this (weird) four column version to make the HTML look much better. WARNING: The items that go together are in separate columns!!} @begin(FourCol) @NoParanum@;@ @ @Chg{Version=[2],New=[graphic ],Old=[@ @ @ @ ]}symbol @NoParanum@;@ @ @ @ @ @ @ @ @ "@* @ @ @ @ @ @ @ @ @ #@* @ @ @ @ @ @ @ @ @ &@* @ @ @ @ @ @ @ @ @ '@* @ @ @ @ @ @ @ @ @ (@* @ @ @ @ @ @ @ @ @ )@* @ @ @ @ @ @ @ @ @ *@* @ @ @ @ @ @ @ @ @ +@* @ @ @ @ @ @ @ @ @ ,@* @ @ @ @ @ @ @ @ @ @en@;@* @ @ @ @ @ @ @ @ @ .@Chg{Version=[2],New=[],Old=[@*]}@Chg{Version=[2],New=[],Old=[@ @ @ @ @ @ @ @ @ /]}@ChgNote{Funny layout so HTML and RTF look right} @NewColumn @NoParanum@;name @NoParanum@;quotation mark@* number sign@* ampersand@* apostrophe, tick@* left parenthesis@* right parenthesis@* asterisk, multiply@* plus sign@* comma@* hyphen-minus, minus@* full stop, dot, point@Chg{Version=[2],New=[],Old=[@*]}@Chg{Version=[2],New=[],Old=[solidus, divide]}@ChgNote{Funny layout so HTML and RTF look right} @NewColumn @NoParanum@;@ @ @Chg{Version=[2],New=[graphic ],Old=[@ @ @ @ ]}symbol @NoParanum@;@ @ @ @ @ @ @ @ @ :@* @ @ @ @ @ @ @ @ @ ;@* @ @ @ @ @ @ @ @ @ <@* @ @ @ @ @ @ @ @ @ =@* @ @ @ @ @ @ @ @ @ >@* @ @ @ @ @ @ @ @ @ _@* @ @ @ @ @ @ @ @ @ |@* @ @ @ @ @ @ @ @ @ @Chg{Version=[2],New=[/],Old=<[>}@* @ @ @ @ @ @ @ @ @ @Chg{Version=[2],New=[!],Old=<]>}@* @ @ @ @ @ @ @ @ @ @Chg<Version=[2],New=[%],Old=<{>>@* @Chg<Version=[2],New=[],Old=<@ @ @ @ @ @ @ @ @ }>> @NewColumn @NoParanum@;name @NoParanum@;colon@* semicolon@* less-than sign@* equals sign@* greater-than sign@* low line, underline@* vertical line@* @Chg{Version=[2],New=[solidus, divide],Old=[left square bracket]}@* @Chg{Version=[2],New=[exclamation point],Old=[right square bracket]}@* @Chg{Version=[2],New=[percent sign],Old=[left curly bracket]}@* @Chg{Version=[2],New=[],Old=[right curly bracket]} @end(FourCol) @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[An Ada implementation shall accept Ada source code in UTF-8 encoding, with or without a BOM (see @RefSecNum{String Encoding}), where every character is represented by its code point. The character pair CARRIAGE RETURN/LINE FEED (code points 16#0D# 16#0A#) signifies a single end of line (see @RefSecNum{Lexical Elements, Separators, and Delimiters}); every other occurrence of a @ntf{format_effector} other than the character whose code point position is 16#09# (CHARACTER TABULATION) also signifies a single end of line.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0079-1],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[This is simply requiring that an Ada implementation be able to directly process the ACATS, which is provided in the described format. Note that files that only contain characters with code points in the first 128 (which is the majority of the ACATS) are represented in the same way in both UTF-8 and in "plain" string format. The ACATS includes a BOM in files that have any characters with code points greater than 127. Note that the BOM contains characters not legal in Ada source code, so an implementation can use that to automatically distinguish between files formatted as plain Latin-1 strings and UTF-8 with BOM.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We allow line endings to be both represented as the pair CR LF (as in Windows and the ACATS), and as single @ntf{format_effector} characters (usually LF, as in Linux), in order that files created by standard tools on most operating systems will meet the standard format. We specify how many line endings each represent so that compilers use the same line numbering for standard source files.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This requirement increases portability by having a format that is accepted by all Ada compilers. Note that implementations can support other source representations, including structured representations like a parse tree.]} @end{Reason} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @Chg{Version=[3],New=[The categories defined above, as well as case mapping and folding, may be based on an implementation-defined version of ISO/IEC 10646 (2003 edition or later).],Old=[@Chg{Version=[2],New=[],Old=[In a nonstandard mode, the implementation may support a different character repertoire@Redundant[; in particular, the set of characters that are considered @ntf<identifier_letter>s can be extended or changed to conform to local conventions].]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If an implementation supports other character sets, it defines which characters fall into each category, such as @lquotes@;@ntf{identifier_letter},@rquotes@; and what the corresponding rules of this section are, such as which characters are allowed in the text of a program.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=<The exact categories, case mapping, and case folding chosen affects identifiers, the result of '[[Wide_]Wide_]Image, and packages Wide_Characters.Handling and Wide_Wide_Characters.Handling.>} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This permission allows implementations to upgrade to using a newer character set standard whenever that makes sense, rather than having to wait for the next Ada Standard. But the character set standard used cannot be older than ISO/IEC 10646:2003 (which is essentially similar to Unicode 4.0).]} @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Chg{Version=[2],New=[The characters in categories @ntf{other_control}, @ntf{other_private_use}, and @ntf{other_surrogate} are only allowed in comments], Old=[Every code position of ISO 10646 BMP that is not reserved for a control function is defined to be a @nt<graphic_character> by this International Standard. This includes all code positions other than 0000 - 001F, 007F - 009F, and FFFE - FFFF]}. @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0286-1]} @ChgDeleted{Version=[3],Text=[The language does not specify the source representation of programs.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0286-1]} @ChgDeleted{Version=[3],Text=[Any source representation is valid so long as the implementer can produce an (information-preserving) algorithm for translating both directions between the representation and the standard character set. (For example, every character in the standard character set has to be representable, even if the output devices attached to a given computer cannot print all of those characters properly.) From a practical point of view, every implementer will have to provide some way to process the @Chg{Version=[2],New=[ACATS],Old=[ACVC]}. It is the intent to allow source representations, such as parse trees, that are not even linear sequences of characters. It is also the intent to allow different fonts: reserved words might be in bold face, and that should be irrelevant to the semantics.]} @end(Discussion) @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Ada 95 allows 8-bit and 16-bit characters, as well as implementation-specified character sets. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The syntax rules in this @Chg{Version=[3],New=[subclause],Old=[clause]} are modified to remove the emphasis on basic characters vs. others. (In this day and age, there is no need to point out that you can write programs without using (for example) lower case letters.) In particular, @ntf{character} (representing all characters usable outside comments) is added, and @ntf{basic_graphic_character}, @ntf{other_special_character}, and @ntf{basic_character} are removed. @ntf{Special_character} is expanded to include Ada 83's @ntf{other_special_character}, as well as new 8-bit characters not present in Ada 83.@Chg{Version=[2],New=[ Ada 2005 removes @ntf{special_character} altogether; we want to stick to ISO/IEC 10646:2003 character classifications.],Old=[]} Note that the term @lquotes@;basic letter@rquotes@; is used in @RefSec{Character Handling} to refer to letters without diacritical marks. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Character names now come from @Chg{Version=[2],New=[ISO/IEC 10646:2003],Old=[ISO 10646]}. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[We use @ntf<identifier_letter> rather than @ntf<letter> since ISO 10646 BMP includes many "letters' that are not permitted in identifiers (in the standard mode).]} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Program text can use most characters defined by ISO-10646:2003. This @Chg{Version=[3],New=[subclause],Old=[clause]} has been rewritten to use the categories defined in that Standard. This should ease programming in languages other than English.]} @end{Extend95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=<@Defn{inconsistencies with Ada 2005}An implementation is allowed (but not required) to use a newer character set standard to determine the categories, case mapping, and case folding. Doing so will change the results of attributes '[[Wide_]Wide_]Image and the packages [Wide_]Wide_Characters.Handling in the case of a few rarely used characters. (This also could make some identifiers illegal, for characters that are no longer classified as letters.) This is unlikely to be a problem in practice. Moreover, truly portable Ada 2012 programs should avoid using in these contexts any characters that would have different classifications in any character set standards issued since 10646:2003 (since the compiler can use any such standard as the basis for its classifications).>} @end{Inconsistent2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0079-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that only characters in the categories defined here are allowed in the source of an Ada program. This was clear in Ada 95, but Amendment 1 dropped the wording instead of correcting it.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[A standard source representation is defined that all compilers are expected to process. Since this is the same format as the ACATS, it seems unlikely that there are any implementations that don't meet this requirement. Moreover, other representations are still permitted, and the "impossible or impractical" loophole (see @RefSecnum{Conformity of an Implementation with the Standard}) can be invoked for any implementations that cannot directly process the ACATS.]} @end{Diffword2005} @LabeledClause{Lexical Elements, Separators, and Delimiters} @begin{StaticSem} @Defn{text of a program} The text of a program consists of the texts of one or more @nt<compilation>s. @Defn{lexical element} @IndexSee{Term=[token],See=(lexical element)} The text of each @nt<compilation> is a sequence of separate @i(lexical elements). Each lexical element is formed from a sequence of characters, and is either a delimiter, an @nt<identifier>, a reserved word, a @nt<numeric_literal>, a @nt<character_literal>, a @nt<string_literal>, or a comment. The meaning of a program depends only on the particular sequences of lexical elements that form its @nt{compilation}s, excluding @nt{comment}s. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} The text of a @nt<compilation> is divided into @Defn{line}@i{lines}. @Defn{end of a line} In general, the representation for an end of line is implementation defined. However, a sequence of one or more @ntf<format_effector>s other than @Chg{Version=[2],New=[the character whose code @Chg{Version=[3],New=[point],Old=[position]} is 16#09# (CHARACTER TABULATION)],Old=[character tabulation (HT)]} signifies at least one end of line. @ImplDef{The representation for an end of line.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@Defn{separator} @Redundant[In some cases an explicit @i(separator) is required to separate adjacent lexical elements.] A separator is any of a @Chg{Version=[2],New=[@ntf{separator_space}],Old=[space character]}, a @Chg{Version=[2],New=[@ntf{format_effector}],Old=[format effector]}, or the end of a line, as follows: @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[It might be useful to define @lquotes@;white space@rquotes@; and use it here.]}@ChgNote{No one can figure out why, and it wouldn't match the Unicode def of whitespace.} @end(Discussion) @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} A @Chg{Version=[2],New=[@ntf{separator_space}],Old=[space character]} is a separator except within a @nt{comment}, a @nt{string_literal}, or a @nt{character_literal}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @Chg{Version=[2],New=[The character whose code @Chg{Version=[3],New=[point],Old=[position]} is 16#09# (CHARACTER TABULATION)],Old=[Character tabulation (HT)]} is a separator except within a @nt{comment}. The end of a line is always a separator. @end{Itemize} One or more separators are allowed between any two adjacent lexical elements, before the first of each @nt{compilation}, or after the last. At least one separator is required between an @nt{identifier}, a reserved word, or a @nt{numeric_literal} and an adjacent @nt{identifier}, reserved word, or @nt{numeric_literal}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0079-1]} @ChgAdded{Version=[3],Text=[One or more @ntf{other_format} characters are allowed anywhere that a separator is@Redundant[; any such characters have no effect on the meaning of an Ada program].]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn{delimiter} A @i{delimiter} is either one of the following@Chg{Version=[2],New=[],Old=[ special]} characters@Chg{Version=[2],New=[:],Old=[]} @begin{Display} &@ @ @ @ '@ @ @ @ (@ @ @ @ )@ @ @ @ *@ @ @ @ +@ @ @ @ ,@ @ @ @ @en@ @ @ @ .@ @ @ @ /@ @ @ @ :@ @ @ @ ;@ @ @ @ <@ @ @ @ =@ @ @ @ >@ @ @ @ | @end{Display} @Defn{compound delimiter} or one of the following @i{compound delimiters} each composed of two adjacent special characters @begin{Display} =>@ @ @ @ ..@ @ @ @ **@ @ @ @ :=@ @ @ @ /=@ @ @ @ >=@ @ @ @ <=@ @ @ @ <<@ @ @ @ >>@ @ @ @ <> @end{Display} Each of the special characters listed for single character delimiters is a single delimiter except if this character is used as a character of a compound delimiter, or as a character of a @nt{comment}, @nt{string_literal}, @nt{character_literal}, or @nt{numeric_literal}. @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @Leading@keepnext@;The following names are used when referring to compound delimiters:@table{Columns=[2], Alignment=[Allleft],FirstColWidth=[1],LastColWidth=[4], NoBreak=[F],Border=[F],SmallSize=[F],Caption=[], Headers=[delimiter@ @\name], Body=[=>@\arrow ..@\double dot **@\double star, exponentiate :=@\assignment (pronounced: @lquotes@;becomes@rquotes@;) /=@\inequality (pronounced: @lquotes@;not equal@rquotes@;) >=@\greater than or equal <=@\less than or equal <<@\left label bracket >>@\right label bracket <>@\box]} @end{StaticSem} @begin{ImplReq} An implementation shall support lines of at least 200 characters in length, not counting any characters used to signify the end of a line. An implementation shall support lexical elements of at least 200 characters in length. The maximum supported line length and lexical element length are implementation defined. @ImplDef{Maximum supported line length and lexical element length.} @begin{Discussion} From URG recommendation. @end{Discussion} @end{ImplReq} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The wording was updated to use the new character categories defined in the preceding @Chg{Version=[3],New=[subclause],Old=[clause]}.]} @end{Diffword95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0079-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Clarified that @ntf{other_format} characters are allowed anywhere that separators are allowed. This was intended in Ada 2005, but didn't actually make it into the wording.]} @end{Extend2005} @LabeledClause{Identifiers} @begin{Intro} @nt<Identifier>s are used as names. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Syn{lhs=<identifier>,rhs=" @Chg{Version=[2],New=<@Syn2{identifier_start} {@Syn2{identifier_start} | @Syn2{identifier_extend}}>, Old=<@Synf{identifier_letter} {[@Synf{underline}] @Syn2{letter_or_digit}}>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Syn{lhs=<@Chg{Version=[2],New=<identifier_start>,Old=<letter_or_digit>}>, rhs="@Chg{Version=[2],New=< @Synf{letter_uppercase} | @Synf{letter_lowercase} | @Synf{letter_titlecase} | @Synf{letter_modifier} | @Synf{letter_other} | @Synf{number_letter}>,Old=<@Synf{identifier_letter} | @Synf{digit}>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0091-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<identifier_extend>,Old=<>}>, rhs="@Chg{Version=[2],New=< @Synf{mark_non_spacing} | @Synf{mark_spacing_combining} | @Synf{number_decimal} | @Synf{punctuation_connector}@Chg{Version=[3],New=<>,Old=< | @Synf{other_format}>}>,Old=<>}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0091-1]} @Chg{Version=[2],New=[@Chg{Version=[3],New=[An],Old=[After eliminating the characters in category @ntf{other_format}, an]} @nt{identifier} shall not contain two consecutive characters in category @Chg{Version=[3],New=[@ntf{punctuation_connector}],Old=[punctuation_connector]}, or end with a character in that category.],Old=[An @nt{identifier} shall not be a reserved word.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[This rule was stated in the syntax in Ada 95, but that has gotten too complex in Ada 2005.@Chg{Version=[3],New=[], Old=[ Since @ntf{other_format} characters usually do not display, we do not want to count them as separating two underscores.]}]} @end{Reason} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0091-1],ARef=[AI05-0227-1],ARef=[AI05-0266-1],ARef=[AI05-0299-1]} @Comment{Removed the "Type=[Leading]" along with the bullets. Don't have a way to make it doubly conditional (only in Version=[2]), and since it is mainly for spacing, we just forget it.} @ChgAdded{Version=[2],Text=[Two @nt{identifier}s are ]}@Chg{Version=[2], New=[considered the same if they consist of the same sequence of characters after applying @Chg{Version=[3],New=[locale-independent simple case folding, as defined by documents referenced in the note in Clause 1 of ISO/IEC 10646:2011.@Defn{case insensitive}],Old=[the following transformations (in this order):]}],Old=[All characters of an @nt{identifier} are significant, including any underline character. @Defn{case insensitive} @nt{Identifier}s differing only in the use of corresponding upper and lower case letters are considered the same.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0091-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The characters in category @ntf{other_format} are eliminated.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0091-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The remaining sequence of characters is converted to upper case. @Defn{case insensitive}]}]} @end{Itemize} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0227-1]} @Chg{Version=[3],New=[Simple case folding is a mapping to lower case, so this is matching the defining (lower case) version of a reserved word. We could have mentioned case folding of the reserved words, but as that is an identity function, it would have no effect.],Old=[@Chg{Version=[2],New=[],Old=[Two of the letters of ISO 8859-1 appear only as lower case, "sharp s" and "y with diaeresis." These two letters have no corresponding upper case letter (in particular, they are not considered equivalent to one another).]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0227-1]} @ChgAdded{Version=[3],Text=[The @ldquote@;documents referenced@rdquote means Unicode. Note that simple case folding is supposed to be compatible between Unicode versions, so the Unicode version used doesn't matter.]} @end(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0091-1],ARef=[AI05-0227-1]} @ChgAdded{Version=[2],Text=[After applying @Chg{Version=[3],New=[simple case folding],Old=[these transformations]}, an @nt{identifier} shall not be identical to a reserved word@Chg{Version=[3],New=[],Old=[ (in upper case)]}.]} @begin(ImplNote) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[We match the reserved words after @Chg{Version=[3],New=[applying case folding],Old=[doing these transformations]} so that the rules for @nt{identifier}s and reserved words are the same. @Chg{Version=[3],New=[],Old=[(This allows @ntf{other_format} characters, which usually don't display, in a reserved word without changing it to an @nt{identifier}.) ]}Since a compiler usually will lexically process @nt{identifier}s and reserved words the same way (often with the same code), this will prevent a lot of headaches.]} @end(ImplNote) @begin(Ramification) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0227-1]} @ChgAdded{Version=[2],Text=[The rules for reserved words differ in one way: they define case conversion on letters rather than sequences. This means that @Chg{Version=[3],New=[it is possible that there exist ],Old=[]}some unusual sequences @Chg{Version=[3],New=[that ],Old=[]}are neither @nt{identifier}s nor reserved words. @Chg{Version=[3],New=[We are not aware of any such sequences so long as we use simple case folding (as opposed to full case folding), but we have defined the rules in case any are introduced in future character set standards. This originally was a problem when converting to upper case:],Old=[For instance,]} @lquotes@;@smldotlessi@;f@rquotes@; and @lquotes@;acce@latin1(223)@rquotes@; have upper case conversions of @lquotes@;IF@rquotes@; and @lquotes@;ACCESS@rquotes@; respectively. @Chg{Version=[3],New=[We would not want these to be treated as reserved words. But neither of these cases exist when using simple case folding.], Old=[These are not @nt{identifier}s, because the transformed values are identical to a reserved word. But they are not reserved words, either, because the original values do not match any reserved word as defined or with any number of characters of the reserved word in upper case. Thus, these odd constructions are just illegal, and should not appear in the source of a program.]}]} @end(Ramification) @end{StaticSem} @begin{ImplPerm} In a nonstandard mode, an implementation may support other upper/lower case equivalence rules for @nt<identifier>s@Redundant[, to accommodate local conventions]. @end{ImplPerm} @begin(Discussion) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0227-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[For instance, in most languages, the @Chg{Version=[3],New=[simple case folded],Old=[uppercase]} equivalent of LATIN @Chg{Version=[3],New=[CAPITAL],Old=[SMALL]} LETTER I (@Chg{Version=[3],New=[an upper],Old=[a lower]} case letter @Chg{Version=[3],New=[without],Old=[with]} a dot above) is LATIN @Chg{Version=[3],New=[SMALL],Old=[CAPITAL]} LETTER I (@Chg{Version=[3],New=[a lower],Old=[an upper]} case letter @Chg{Version=[3],New=[with],Old=[without]} a dot above). In Turkish, though, LATIN @Chg{Version=[3],New=[CAPITAL],Old=[SMALL]} LETTER I and LATIN @Chg{Version=[3],New=[CAPITAL],Old=[SMALL]} LETTER @Chg{Version=[3],New=[],Old=[DOTLESS ]}I@Chg{Version=[3],New=[ WITH DOT ABOVE],Old=[]} are two distinct letters, so the @Chg{Version=[3],New=[case folded],Old=[upper case]} equivalent of LATIN @Chg{Version=[3],New=[CAPITAL],Old=[SMALL]} LETTER I is LATIN @Chg{Version=[3],New=[SMALL],Old=[CAPITAL]} LETTER @Chg{Version=[3],New=[DOTLESS ],Old=[]}I@Chg{Version=[3],New=[],Old=[ WITH DOT ABOVE]}, and the @Chg{Version=[3],New=[case folded],Old=[upper case]} equivalent of LATIN @Chg{Version=[3],New=[CAPITAL],Old=[SMALL]} LETTER @Chg{Version=[3],New=[],Old=[DOTLESS ]}I@Chg{Version=[3],New=[ WITH DOT ABOVE],Old=[]} is LATIN @Chg{Version=[3],New=[SMALL],Old=[CAPITAL]} LETTER I. Take for instance the following identifier (which is the name of a city on the Tigris river in Eastern Anatolia):]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[D@capdottedi@;YARBAKIR],Old=[diyarbak@smldotlessi@;r]} -- @RI[The first i is dotted, the second isn't.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[A Turkish reader would expect that the above identifier is equivalent to],Old=[Locale-independent conversion to upper case results in]}:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[diyarbak@smldotlessi@;r],Old=[DIYARBAKIR -- @RI[Both Is are dotless.]]}]} @end{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Leading],Text=[However, locale-independent simple case folding (and thus Ada) maps this to:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[d@capdottedi@;yarbakir]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[which is different from any of the following identifiers],Old=[This means that the four following sequences of characters represent the same identifier, even though for a locutor of Turkish they would probably be considered distinct words]}:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[diyarbakir diyarbak@smldotlessi@;r d@smldotlessi@;yarbakir d@smldotlessi@;yarbak@smldotlessi@;r]} @end{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=<including the @ldquote@;correct@rdquote matching identifier for Turkish. Upper case conversion (used in '[Wide_]Wide_Image) introduces additional problems.>} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @Comment{Removed the "Type=[Leading]" along with the example. Don't have a way to make it doubly conditional (only in Version=[2]), and since it is mainly for spacing, we just forget it.} @ChgAdded{Version=[2],Text=[An implementation targeting the Turkish market is allowed (in fact, expected) to provide a nonstandard mode where case folding is appropriate for Turkish.@Chg{Version=[3],New=[],Old=[ This would cause the original identifier to be converted to:]}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[D@capdottedi@;YARBAKIR -- @RI[The first I is dotted, the second isn't.]]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[and the four sequences of characters shown above would represent four distinct identifiers.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Lithuanian and Azeri are two other languages that present similar idiosyncrasies.]} @end{Discussion} @begin{Notes} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@nt{Identifier}s differing only in the use of corresponding upper and lower case letters are considered the same.]} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of identifiers:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote{Old version:@begin{Display} Count X Get_Symbol Ethelyn Marion @Comment{Blank line} Snobol_4 X1 Page_Count Store_Next_Item @end{Display}} @begin{Example} Count X Get_Symbol Ethelyn Marion Snobol_4 X1 Page_Count Store_Next_Item@Chg{Version=[2],New=[ @unicode(928)@unicode(955)@unicode(940)@unicode(964)@unicode(969)@unicode(957) --@RI[ Plato] @unicode(1063)@unicode(1072)@unicode(1081)@unicode(1082)@unicode(1086)@unicode(1074)@unicode(1089)@unicode(1082)@unicode(1080)@unicode(1081) --@RI[ Tchaikovsky] @unicode(952) @unicode(966) --@RI[ Angles]],Old=[]} @end{Example} @end{Examples} @begin{DiffWord83} We no longer include reserved words as @nt<identifier>s. This is not a language change. In Ada 83, @nt{identifier} included reserved words. However, this complicated several other rules (for example, regarding implementation-defined attributes and pragmas, etc.). We now explicitly allow certain reserved words for attribute designators, to make up for the loss. @begin{Ramification} Because syntax rules are relevant to overload resolution, it means that if it looks like a reserved word, it is not an @nt<identifier>. As a side effect, implementations cannot use reserved words as implementation-defined attributes or pragma names. @end{Ramification} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{identifier} can use any letter defined by ISO-10646:2003, along with several other categories. This should ease programming in languages other than English.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0091-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@B<Correction:> @ntf{other_format} characters were removed from identifiers as the Unicode recommendations have changed. This change can only affect programs written for the original Ada 2005, so there should be few such programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0227-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> We now specify simple case folding rather than full case folding. That potentially could change identifier equivalence, although it is more likely that identifiers that are considered the same in original Ada 2005 will now be considered different. This change was made because the original Ada 2005 definition was incompatible (and even inconsistent in unusual cases) with the Ada 95 identifier equivalence rules. As such, the Ada 2005 rules were rarely fully implemented, and in any case, only Ada 2005 identifiers containing wide characters could be affected.]} @end{Incompatible2005} @LabeledClause{Numeric Literals} @begin{Intro} @Defn2{Term=[literal], Sec=(numeric)} There are two kinds of @nt<numeric_literal>s, @i(real literals) and @i(integer literals). @Defn{real literal} A real literal is a @nt{numeric_literal} that includes a point; @Defn{integer literal} an integer literal is a @nt{numeric_literal} without a point. @end{Intro} @begin{Syntax} @Syn{lhs=<numeric_literal>,rhs="@Syn2{decimal_literal} | @Syn2{based_literal}"} @end{Syntax} @begin{Notes} The type of an integer literal is @i{universal_integer}. The type of a real literal is @i{universal_real}. @end{Notes} @LabeledSubClause{Decimal Literals} @begin{Intro} @Defn2{Term=[literal], Sec=(decimal)} A @nt<decimal_literal> is a @nt<numeric_literal> in the conventional decimal notation (that is, the base is ten). @end{Intro} @begin{Syntax} @Syn{lhs=<decimal_literal>,rhs="@Syn2{numeral} [.@Syn2{numeral}] [@Syn2{exponent}]"} @Syn{lhs=<numeral>,rhs="@Syn2{digit} {[@Synf{underline}] @Syn2{digit}}"} @Syn{lhs=<exponent>,rhs="E [+] @Syn2{numeral} | E @en@; @Syn2{numeral}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<digit>,Old=<>}>, rhs="@Chg{Version=[2],New=<0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9>,Old=<>}"} @begin{SyntaxText} An @nt{exponent} for an integer literal shall not have a minus sign. @begin{Ramification} Although this rule is in this subclause, it applies also to the next subclause. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{StaticSem} An underline character in a @nt{numeric_literal} does not affect its meaning. The letter E of an @nt{exponent} can be written either in lower case or in upper case, with the same meaning. @begin{Ramification} Although these rules are in this subclause, they apply also to the next subclause. @end{Ramification} An @nt{exponent} indicates the power of ten by which the value of the @nt{decimal_literal} without the @nt{exponent} is to be multiplied to obtain the value of the @nt{decimal_literal} with the @nt{exponent}. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of decimal literals:} @ChgNote{ Old version: @begin{Display} @tabclear()@tabset(P31) 12 0 1E6 123_456 @\--@i{ integer literals} @Comment{Blank line} 12.0 0.0 0.456 3.14159_26 @\--@i{ real literals} @end{Display}} @begin{Example} 12 0 1E6 123_456 --@RI{ integer literals} @Comment{Blank line} 12.0 0.0 0.456 3.14159_26 --@RI{ real literals} @end{Example} @end{Examples} @begin{DiffWord83} We have changed the syntactic category name @ntf{integer} to be @nt{numeral}. We got this idea from ACID. It avoids the confusion between this and integers. (Other places don't offer similar confusions. For example, a @nt{string_literal} is different from a string.) @end{DiffWord83} @LabeledSubClause{Based Literals} @begin{Intro} @Redundant[ @Defn2{Term=[literal], Sec=(based)} @Defn{binary literal} @Defn{base 2 literal} @Defn2{Term=[binary], Sec=(literal)} @Defn{octal literal} @Defn{base 8 literal} @Defn2{Term=[octal], Sec=(literal)} @Defn{hexadecimal literal} @Defn{base 16 literal} @Defn2{Term=[hexadecimal], Sec=(literal)} A @nt<based_literal> is a @nt<numeric_literal> expressed in a form that specifies the base explicitly.] @end{Intro} @begin{Syntax} @Syn{lhs=<based_literal>,rhs=" @Syn2{base} # @Syn2{based_numeral} [.@Syn2{based_numeral}] # [@Syn2{exponent}]"} @Syn{lhs=<base>,rhs="@Syn2{numeral}"} @Syn{lhs=<based_numeral>,rhs=" @Syn2{extended_digit} {[@Synf{underline}] @Syn2{extended_digit}}"} @Syn{lhs=<extended_digit>,rhs="@Syn2{digit} | A | B | C | D | E | F"} @end{Syntax} @begin{Legality} @Defn{base} The @i(base) (the numeric value of the decimal @nt<numeral> preceding the first #) shall be at least two and at most sixteen. The @nt{extended_digit}s A through F represent the digits ten through fifteen, respectively. The value of each @nt{extended_digit} of a @nt{based_literal} shall be less than the base. @end{Legality} @begin{StaticSem} The conventional meaning of based notation is assumed. An @nt{exponent} indicates the power of the base by which the value of the @nt{based_literal} without the @nt{exponent} is to be multiplied to obtain the value of the @nt{based_literal} with the @nt{exponent}. The @nt{base} and the @nt{exponent}, if any, are in decimal notation. The @nt{extended_digit}s A through F can be written either in lower case or in upper case, with the same meaning. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of based literals:} @ChgNote{ Old version: @begin{Display} @tabclear()@tabset(P16, P45) 2#1111_1111# @\16#FF# 016#0ff# @\--@i{ integer literals of value 255} 16#E#E1 @\2#1110_0000# @\--@i{ integer literals of value 224} 16#F.FF#E+2 @\2#1.1111_1111_1110#E11 @\--@i{ real literals of value 4095.0} @end{Display}} @begin{Example} 2#1111_1111# 16#FF# 016#0ff# --@RI{ integer literals of value 255} 16#E#E1 2#1110_0000# --@RI{ integer literals of value 224} 16#F.FF#E+2 2#1.1111_1111_1110#E11 --@RI{ real literals of value 4095.0} @end{Example} @end{Examples} @begin{DiffWord83} The rule about which letters are allowed is now encoded in BNF, as suggested by Mike Woodger. This is clearly more readable. @end{DiffWord83} @LabeledClause{Character Literals} @begin{Intro} @Redundant[A @nt<character_literal> is formed by enclosing a graphic character between two apostrophe characters.] @end{Intro} @begin{Syntax} @Syn{lhs=<character_literal>,rhs="@SingleQuote@Synf{graphic_character}@SingleQuote"} @end{Syntax}@Comment{graphic_character is defined syntactically in Ada 95, but not in Ada 2007} @begin{Notes} A @nt{character_literal} is an enumeration literal of a character type. See @RefSecNum(Character Types). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of character literals:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote{ Orginal version: @begin{Display} 'A'@ @ @ @ @ '*'@ @ @ @ @ '''@ @ @ @ @ '@ ' @end{Display}} @begin{Example} 'A' '*' ''' ' '@Chg{Version=[2],New=[ 'L' '@Unicode(1051)' '@Unicode(923)' --@RI[ Various els.] '@Unicode(8734)' '@Unicode(1488)' --@RI[ Big numbers - infinity and aleph.]],Old=[]} @end{Example} @end{Examples} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The definitions of the values of literals are in @Chg{Version=[3],New=[Clauses],Old=[Sections]} 3 and 4, rather than here, since it requires knowledge of types. @end{DiffWord83} @LabeledClause{String Literals} @begin{Intro} @redundant[A @nt<string_literal> is formed by a sequence of graphic characters (possibly none) enclosed between two quotation marks used as string brackets. They are used to represent @nt<operator_symbol>s (see @RefSecNum(Subprogram Declarations)), values of a string type (see @RefSecNum(Literals)), and array subaggregates (see @RefSecNum(Array Aggregates)). @IndexSee{Term=[quoted string],See=(string_literal)}] @end{Intro} @begin{Syntax} @Syn{lhs=<string_literal>,rhs=<"{@Syn2{string_element}}">} @Syn{lhs=<string_element>, rhs=<"" | @SynI{non_quotation_mark_}@Synf{graphic_character}>} @begin{SyntaxText} A @nt{string_element} is either a pair of quotation marks (""), or a single @ntf{graphic_character} other than a quotation mark. @end{SyntaxText} @end{Syntax} @begin{StaticSem} @Defn2{Term=[sequence of characters], Sec=(of a @nt<string_literal>)} The @i(sequence of characters) of a @nt<string_literal> is formed from the sequence of @nt<string_element>s between the bracketing quotation marks, in the given order, with a @nt<string_element> that is "" becoming a single quotation mark in the sequence of characters, and any other @nt<string_element> being reproduced in the sequence. @Defn{null string literal} A @i(null string literal) is a @nt<string_literal> with no @nt<string_element>s between the quotation marks. @end{StaticSem} @begin{Notes} An end of line cannot appear in a @nt{string_literal}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[No transformation is performed on the sequence of characters of a @nt{string_literal}.]} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of string literals:} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgNote< Original version: @begin{Display} @tabclear()@tabset(P16) "Message of the day:" @comment{Blank line} "" @\--@i{ a null string literal} "@ " "A" """" @\--@i{ three string literals of length 1} @comment{Blank line} "Characters such as $, %, and } are allowed in string literals" @end{Display}> @begin{Example} "Message of the day:" @comment{Blank line} "" --@RI{ a null string literal} " " "A" """" --@RI{ three string literals of length 1} @comment{Blank line} "Characters such as $, %, and } are allowed in string literals" @Chg{Version=[2],New=["Archimedes said ""@unicode(917)@unicode(973)@unicode(961)@unicode(951)@unicode(954)@unicode(945)""" "Volume of cylinder (@pi@;r@latin1(178)h) = "],Old=[]} @end{Example} @end{Examples} @begin{DiffWord83} The wording has been changed to be strictly lexical. No mention is made of string or character values, since @nt<string_literal>s are also used to represent @nt<operator_symbol>s, which don't have a defined value. The syntax is described differently. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[We explicitly say that the characters of a @nt{string_literal} should be used as is. In particular, no normalization or folding should be performed on a @nt{string_literal}.]} @end{DiffWord95} @LabeledClause{Comments} @begin{Intro} A @nt{comment} starts with two adjacent hyphens and extends up to the end of the line. @end{Intro} @begin{Syntax} @Syn{lhs=<comment>, rhs=<--{@SynI{non_end_of_line_}@Synf{character}}>}@Comment{character is defined syntactically in Ada 95, but not in Ada 2007. We assume the worst here.} @begin{SyntaxText} A @nt{comment} may appear on any line of a program. @end{SyntaxText} @end{Syntax} @begin{StaticSem} The presence or absence of @nt{comment}s has no influence on whether a program is legal or illegal. Furthermore, @nt{comment}s do not influence the meaning of a program; their sole purpose is the enlightenment of the human reader. @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of comments:} @ChgNote{Original version: @begin{Display} --@i{ the last sentence above echoes the Algol 68 report } @comment{Blank line} @key[end]; --@i{ processing of Line is complete } @comment{Blank line} --@i{ a long comment may be split onto} --@i{ two or more consecutive lines } @comment{Blank line} ----------------@i{ the first two hyphens start the comment } @end{Display}} @begin{Example} --@RI[ the last sentence above echoes the Algol 68 report ] @comment{Blank line} @key[end]; --@RI[ processing of Line is complete ] @comment{Blank line} --@RI[ a long comment may be split onto] --@RI[ two or more consecutive lines ] @comment{Blank line} ----------------@RI[ the first two hyphens start the comment ] @end{Example} @end{Examples} @LabeledClause{Pragmas} @begin{Intro} @ToGlossaryAlso{Term=<Pragma>, Text=<A pragma is a compiler directive. There are language-defined pragmas that give instructions for optimization, listing control, etc. An implementation may support additional (implementation-defined) pragmas.>} @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0100-1],ARef=[AI05-0163-1]} @ChgAdded{Version=[3],Text=[In general, if all @nt{pragma}s are treated as unrecognized @nt{pragma}s, the program should remain both syntactically and semantically legal. There are a few exceptions to this general principle (for example, @nt{pragma} Import can eliminate the need for a completion), but the principle remains, and is strictly true at the syntactic level. Certainly any implementation-defined @nt{pragma}s should obey this principle both syntactically and semantically, so that if the @nt{pragma}s are not recognized by some other implementation, the program will remain legal.]} @end{MetaRules} @begin{Syntax} @Syn{lhs=<pragma>,rhs=" @key{pragma} @Syn2{identifier} [(@Syn2{pragma_argument_association} {, @Syn2{pragma_argument_association}})];"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @Syn{lhs=<pragma_argument_association>,rhs=" [@SynI{pragma_argument_}@Syn2{identifier} =>] @Syn2{name} | [@SynI{pragma_argument_}@Syn2{identifier} =>] @Syn2{expression}@Chg{Version=[3],New=[ | @SynI{pragma_argument_}@Syn2{aspect_mark} => @Syn2{name} | @SynI{pragma_argument_}@Syn2{aspect_mark} => @Syn2{expression}],Old=[]}"} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} In a @nt<pragma>, any @nt<pragma_argument_association>s without a @SynI{pragma_argument_}@nt<identifier> @Chg{Version=[3],New=[or @SynI{pragma_argument_}@nt<aspect_mark> ],Old=[]}shall precede any associations with a @i{pragma_argument_}@nt<identifier>@Chg{Version=[3],New=[ or @SynI{pragma_argument_}@nt<aspect_mark>],Old=[]}. @Leading@keepnext@nt{Pragma}s are only allowed at the following places in a program: @begin{Itemize} After a semicolon delimiter, but not within a @nt{formal_part} or @nt{discriminant_part}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0100-1],ARef=[AI05-0163-1]} At any place where the syntax rules allow a construct defined by a syntactic category whose name ends with @ldquote@ntf{declaration}@rdquote, @Chg{Version=[3],New=[@ldquote@ntf{item}@rdquote, ],Old=[]}@ldquote@ntf{statement}@rdquote, @ldquote@ntf{clause}@rdquote, or @ldquote@ntf{alternative}@rdquote, or one of the syntactic categories @nt{variant} or @nt{exception_handler}; but not in place of such a construct@Chg{Version=[3],New=[ if the construct is required, or is part of a list that is required to have at least one such construct],Old=[. Also at any place where a @nt{compilation_unit} would be allowed]}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0163-1]} @ChgAdded{Version=[3],Text=[In place of a @nt{statement} in a @nt{sequence_of_statements}.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0100-1]} @ChgAdded{Version=[3],Text=[At any place where a @nt{compilation_unit} is allowed.]} @end{Itemize} Additional syntax rules and placement restrictions exist for specific pragmas. @end{SyntaxText} @begin{Discussion} The above rule is written in text, rather than in BNF; the syntactic category @nt{pragma} is not used in any BNF syntax rule. @end{Discussion} @begin{Ramification} A @nt{pragma} is allowed where a @nt<generic_formal_parameter_declaration> is allowed. @end{Ramification} @end{Syntax} @begin{Intro} @Defn2{Term=[name], Sec=(of a @nt{pragma})} @Defn{pragma name} The @i{name} of a @nt{pragma} is the identifier following the reserved word @key{pragma}. @Defn{pragma argument} @Defn{argument of a pragma} The @nt{name} or @nt{expression} of a @nt{pragma_argument_association} is a @i{pragma argument}. @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[For compatibility with Ada 83, the name of a @nt{pragma} may also be @lquotes@key{interface}@rquotes@;, which is not an identifier (because it is a reserved word). See @RefSecNum{Pragma Interface}.]} @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0272-1]} @Defn{identifier specific to a pragma} @Defn{pragma, identifier specific to} An @i{identifier specific to a pragma} is an identifier @Chg{Version=[3],New=[or reserved word ],Old=[]}that is used in a pragma argument with special meaning for that pragma. @begin{Honest} Whenever the syntax rules for a given pragma allow "@nt{identifier}" as an argument of the @nt{pragma}, that @nt{identifier} is an identifier specific to that pragma. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[In a few cases, a reserved word is allowed as "an identifier specific to a pragma". Even in these cases, the syntax still is written as @nt{identifier} (the reserved word(s) are not shown). For example, the restriction No_Use_Of_Attribute (see @RefSecNum{Language-Defined Restrictions and Profiles}) allows the reserved words which can be attribute designators, but the syntax for a restriction does not include these reserved words.]} @end{Honest} @end{Intro} @begin{StaticSem} If an implementation does not recognize the name of a @nt{pragma}, then it has no effect on the semantics of the program. Inside such a @nt{pragma}, the only rules that apply are the @SyntaxName@;s. @begin{Honest} This rule takes precedence over any other rules that imply otherwise. @end{Honest} @begin{Ramification} Note well: this rule applies only to @nt{pragma}s whose name is not recognized. If anything else is wrong with a @nt{pragma} (at compile time), the @nt{pragma} is illegal. This is true whether the @nt{pragma} is language defined or implementation defined. For example, an expression in an unrecognized @nt{pragma} does not cause freezing, even though the rules in @RefSec{Freezing Rules} say it does; the above rule overrules those other rules. On the other hand, an expression in a recognized @nt{pragma} causes freezing, even if this makes something illegal. For another example, an expression that would be ambiguous is not illegal if it is inside an unrecognized @nt{pragma}. Note, however, that implementations have to recognize @key[pragma] Inline(Foo) and freeze things accordingly, even if they choose to never do inlining. Obviously, the contradiction needs to be resolved one way or the other. The reasons for resolving it this way are: The implementation is simple @em the compiler can just ignore the @nt{pragma} altogether. The interpretation of constructs appearing inside implementation-defined @nt{pragma}s is implementation defined. For example: @lquotes@;@key[pragma] Mumble(X);@rquotes@;. If the current implementation has never heard of Mumble, then it doesn't know whether X is a name, an expression, or an identifier specific to the pragma Mumble. @end{Ramification} @begin{Honest} The syntax of individual pragmas overrides the general syntax for @nt{pragma}. @end{Honest} @begin{Ramification} Thus, an identifier specific to a @nt{pragma} is not a @nt{name}, syntactically; if it were, the visibility rules would be invoked, which is not what we want. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} This also implies that named associations do not allow one to give the arguments in an arbitrary order @em the order given in the syntax rule for each individual pragma must be obeyed. However, it is generally possible to leave out earlier arguments when later ones are given; for example, this is allowed by the syntax rule for pragma Import (see @Chg{Version=[3],New=[@RefSec{Interfacing Pragmas}], Old=[@RefSec{Interfacing Aspects}]}). As for subprogram calls, positional notation precedes named notation. Note that Ada 83 had no pragmas for which the order of named associations mattered, since there was never more than one argument that allowed named associations. @end{Ramification} @begin{Honest} The interpretation of the arguments of implementation-defined pragmas is implementation defined. However, the syntax rules have to be obeyed. @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(pragma)} @PDefn2{Term=[elaboration], Sec=(pragma)} Any @nt{pragma} that appears at the place of an executable construct is executed. Unless otherwise specified for a particular pragma, this execution consists of the evaluation of each evaluable pragma argument in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Ramification} For a @nt{pragma} that appears at the place of an elaborable construct, execution is elaboration. An identifier specific to a pragma is neither a @nt{name} nor an @nt{expression} @em such identifiers are not evaluated (unless an implementation defines them to be evaluated in the case of an implementation-defined @nt{pragma}). The @lquotes@;unless otherwise specified@rquotes@; part allows us (and implementations) to make exceptions, so a @nt{pragma} can contain an expression that is not evaluated. Note that @nt{pragma}s in @nt{type_definition}s may contain expressions that depend on discriminants. When we wish to define a pragma with some run-time effect, we usually make sure that it appears in an executable context; otherwise, special rules are needed to define the run-time effect and when it happens. @end{Ramification} @end{RunTime} @begin{ImplReq} The implementation shall give a warning message for an unrecognized pragma name. @begin{Ramification} An implementation is also allowed to have modes in which a warning message is suppressed, or in which the presence of an unrecognized @nt{pragma} is a compile-time error. @end{Ramification} @end{ImplReq} @begin{ImplPerm} An implementation may provide implementation-defined pragmas; the name of an implementation-defined pragma shall differ from those of the language-defined pragmas. @ImplDef{Implementation-defined pragmas.} @begin{Ramification} The semantics of implementation-defined pragmas, and any associated rules (such as restrictions on their placement or arguments), are, of course, implementation defined. Implementation-defined pragmas may have run-time effects. @end{Ramification} An implementation may ignore an unrecognized pragma even if it violates some of the @SyntaxName@;s, if detecting the syntax error is too complex. @begin{Reason} Many compilers use extra post-parsing checks to enforce the syntax rules, since the Ada syntax rules are not LR(k) (for any k). (The grammar is ambiguous, in fact.) This paragraph allows them to ignore an unrecognized pragma, without having to perform such post-parsing checks. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0163-1]} Normally, implementation-defined pragmas should have no semantic effect for error-free programs; that is, if the implementation-defined pragmas @Chg{Version=[3],New=[in a working program are replaced with unrecognized pragmas],Old=[are removed from a working program]}, the program should still be legal, and should still have the same semantics. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined pragmas should have no semantic effect for error-free programs.]}]} @begin{Ramification} Note that @lquotes@;semantics@rquotes@; is not the same as @lquotes@;effect;@rquotes@; as explained in @RefSecNum{Conformity of an Implementation With the Standard}, the semantics defines a set of possible effects. Note that adding a @nt{pragma} to a program might cause an error (either at compile time or at run time). On the other hand, if the language-specified semantics for a feature are in part implementation defined, it makes sense to support pragmas that control the feature, and that have real semantics; thus, this paragraph is merely a recommendation. @end{Ramification} @Leading@;Normally, an implementation should not define pragmas that can make an illegal program legal, except as follows: @begin(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} A @nt<pragma> used to complete a declaration@Chg{Version=[3],New=[],Old=[, such as a @nt{pragma} Import]}; @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[There are no language-defined pragmas which can be completions; @nt{pragma} Import was defined this way in Ada 95 and Ada 2005, but in Ada 2012 @nt{pragma} Import just sets aspect Import which disallows having any completion.]} @end{Discussion} A @nt<pragma> used to configure the environment by adding, removing, or replacing @nt{library_item}s. @end(Itemize) @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined pragmas should not make an illegal program legal, unless they complete a declaration or configure the @nt{library_item}s in an environment.]}]} @begin(Ramification) For example, it is OK to support Interface, System_Name, Storage_Unit, and Memory_Size @nt{pragma}s for upward compatibility reasons, even though all of these @nt{pragma}s can make an illegal program legal. (The latter three can affect legality in a rather subtle way: They affect the value of named numbers in System, and can therefore affect the legality in cases where static expressions are required.) On the other hand, adding implementation-defined pragmas to a legal program can make it illegal. For example, a common kind of implementation-defined pragma is one that promises some property that allows more efficient code to be generated. If the promise is a lie, it is best if the user gets an error message. @end(Ramification) @end{ImplAdvice} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 83, @lquotes@;bad@rquotes@; @nt{pragma}s are ignored. In Ada 95, they are illegal, except in the case where the name of the @nt{pragma} itself is not recognized by the implementation. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Implementation-defined @nt{pragma}s may affect the legality of a program. @end{Extend83} @begin{DiffWord83} Implementation-defined @nt{pragma}s may affect the run-time semantics of the program. This was always true in Ada 83 (since it was not explicitly forbidden by RM83), but it was not clear, because there was no definition of @lquotes@;executing@rquotes@; or @lquotes@;elaborating@rquotes@; a @nt{pragma}. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0163-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Allow @nt{pragma}s in place of a @nt{statement}, even if there are no other @nt{statement}s in a @nt{sequence_of_statements}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[Identifiers specific to a pragma can be reserved words.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Pragma arguments can be identified with @nt{aspect_mark}s; this allows @nt{identifier}'Class in this context. As usual, this is only allowed if specifically allowed by a particular pragma.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0100-1]} @ChgAdded{Version=[3],Text=[@b{Correction:} Clarified where @nt{pragma}s are (and are not) allowed.]} @end{DiffWord2005} @begin{Syntax} @Leading@keepnext@;The forms of List, Page, and Optimize @nt{pragma}s are as follows: @PragmaSyn`@key{pragma} @prag(List)(@Syn2{identifier});' @PragmaSyn`@key{pragma} @prag(Page);' @PragmaSyn`@key{pragma} @prag(Optimize)(@Syn2{identifier});' @begin{SyntaxText} @Redundant[Other pragmas are defined throughout this International Standard, and are summarized in @RefSecNum{Language-Defined Pragmas}.] @begin{Ramification} The language-defined pragmas are supported by every implementation, although @lquotes@;supporting@rquotes@; some of them (for example, Inline) requires nothing more than checking the arguments, since they act only as advice to the implementation. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{StaticSem} A @nt{pragma} List takes one of the @nt{identifier}s On or Off as the single argument. This pragma is allowed anywhere a @nt{pragma} is allowed. It specifies that listing of the compilation is to be continued or suspended until a List @nt{pragma} with the opposite argument is given within the same compilation. The @nt{pragma} itself is always listed if the compiler is producing a listing. A @nt{pragma} Page is allowed anywhere a @nt{pragma} is allowed. It specifies that the program text which follows the @nt{pragma} should start on a new page (if the compiler is currently producing a listing). A @nt{pragma} Optimize takes one of the @nt{identifier}s Time, Space, or Off as the single argument. This @nt{pragma} is allowed anywhere a @nt<pragma> is allowed, and it applies until the end of the immediately enclosing declarative region, or for a @nt{pragma} at the place of a @nt{compilation_unit}, to the end of the @nt<compilation>. It gives advice to the implementation as to whether time or space is the primary optimization criterion, or that optional optimizations should be turned off. @Redundant[It is implementation defined how this advice is followed.] @ImplDef{Effect of pragma Optimize.} @begin{Discussion} For example, a compiler might use Time vs. Space to control whether generic instantiations are implemented with a macro-expansion model, versus a shared-generic-body model. We don't define what constitutes an @lquotes@;optimization@rquotes@; @em in fact, it cannot be formally defined in the context of Ada. One compiler might call something an optional optimization, whereas another compiler might consider that same thing to be a normal part of code generation. Thus, the programmer cannot rely on this pragma having any particular portable effect on the generated code. Some compilers might even ignore the pragma altogether. @end{Discussion} @end{StaticSem} @begin{Examples} @Leading@keepnext@i{Examples of pragmas:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[pragma] List(Off); -- @Examcom{turn off listing generation} @key[pragma] Optimize(Off); -- @Examcom{turn off optional optimizations} @Chg{Version=[3],New=[@key[pragma] Pure(Rational_Numbers); -- @Examcom{set categorization for package} @key[pragma] Assert(Exists(File_Name), Message => "Nonexistent file"); -- @Examcom{assert file exists}], Old=[@key[pragma] Inline(Set_Mask); --@Examcom{ generate code for Set_Mask inline} @Chg{Version=[2],New=[@key[pragma] Import(C, Put_Char, External_Name => "putchar"); --@Examcom{ import C putchar function}], Old=[@key[pragma] Suppress(Range_Check, On => Index); -- @Examcom{turn off range checking on Index}]}]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The Optimize @nt<pragma> now allows the identifier Off to request that normal optimization be turned off. An Optimize @nt<pragma> may appear anywhere pragmas are allowed. @end{Extend83} @begin{DiffWord83} We now describe the pragmas Page, List, and Optimize here, to act as examples, and to remove the normative material from @RefSec{Language-Defined Pragmas}, so it can be entirely an informative annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[Updated the example of named pragma parameters, because the second parameter of @nt{pragma} Suppress is obsolescent.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Updated the example of pragmas, because both @nt{pragma}s Inline and Import are obsolescent.]} @end{DiffWord2005} @LabeledClause{Reserved Words} @begin{Syntax} @begin{Bundle} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Type=[Leading],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00284-02],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0091-1]} @ChgNote{The table of words has no paragraph number, so we need to put the change here} @Leading @Defn{reserved word} The following are the @i{reserved words}@Chg{Version=[2],New=[. Within a program, some or all of the letters of a reserved word may be in upper case@Chg{Version=[3],New=[],Old=[, and one or more characters in category @ntf{other_format} may be inserted within or at the end of the reserved word]}.],Old=[ (ignoring upper/lower case distinctions):]} @begin{Discussion} Reserved words have special meaning in the syntax. In addition, certain reserved words are used as attribute names. The syntactic category @nt{identifier} no longer allows reserved words. We have added the few reserved words that are legal explicitly to the syntax for @nt{attribute_reference}. Allowing identifier to include reserved words has been a source of confusion for some users, and differs from the way they are treated in the C and Pascal language definitions. @end{Discussion} @* @begin{Display} @begin{FourCol} @noparanum@key{abort} @key{abs} @key{abstract} @key{accept} @key{access} @key{aliased} @key{all} @key{and} @key{array} @key{at} @noparanum@key{begin} @key{body} @noparanum@key{case} @key{constant} @noparanum@key{declare} @key{delay} @key{delta} @key{digits} @key{do} @NewColumn @noparanum@key{else} @key{elsif} @key{end} @key{entry} @key{exception} @key{exit} @noparanum@key{for} @key{function} @noparanum@key{generic} @key{goto} @noparanum@key{if} @key{in} @Chg{Version=[2],New=[@key{interface}],Old=[]} @key{is} @noparanum@key{limited} @key{loop} @noparanum@key{mod} @NewColumn @noparanum@key{new} @key{not} @key{null} @noparanum@key{of} @key{or} @key{others} @key{out} @Chg{Version=[2],New=[@key{overriding}],Old=[]} @noparanum@key{package} @key{pragma} @key{private} @key{procedure} @key{protected} @noparanum@key{raise} @key{range} @key{record} @key{rem} @key{renames} @key{requeue} @NewColumn @noparanum@key{return} @key{reverse} @noparanum@key{select} @key{separate} @Chg{Version=[3],New=[@key{some}],Old=[]} @key{subtype} @Chg{Version=[2],New=[@key{synchronized}],Old=[]} @noparanum@key{tagged} @key{task} @key{terminate} @key{then} @key{type} @noparanum@key{until} @key{use} @noparanum@key{when} @key{while} @key{with} @noparanum@key{xor} @end{FourCol} @end{Display} @end{Bundle} @end{Syntax} @begin{Notes} The reserved words appear in @key{lower case boldface} in this International Standard, except when used in the @nt{designator} of an attribute (see @RefSecNum(Attributes)). Lower case boldface is also used for a reserved word in a @nt{string_literal} used as an @nt{operator_symbol}. This is merely a convention @em programs may be written in whatever typeface is desired and available. @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The following words are not reserved in Ada 83, but are reserved in Ada 95: @key{abstract}, @key{aliased}, @key{protected}, @key{requeue}, @key{tagged}, @key{until}. @end{Incompatible83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The @Chg{Version=[3],New=[subclause],Old=[clause]} entitled @lquotes@;Allowed Replacements of Characters@rquotes@; has been moved to @RefSec(Obsolescent Features). @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The following words are not reserved in Ada 95, but are reserved in Ada 2005: @key{interface}, @key{overriding}, @key{synchronized}. A special allowance is made for @key{pragma} Interface (see @RefSecNum{Pragma Interface}). Uses of these words as identifiers will need to be changed, but we do not expect them to be common.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The definition of upper case equivalence has been modified to allow identifiers using all of the characters of ISO 10646. This change has no effect on the character sequences that are reserved words, but does make some unusual sequences of characters illegal.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0091-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Removed @ntf{other_format} characters from reserved words in order to be compatible with the latest Unicode recommendations. This change can only affect programs written for original Ada 2005, and there is little reason to put @ntf{other_format} characters into reserved words in the first place, so there should be very few such programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[The following word is not reserved in Ada 2005, but is reserved in Ada 2012: @key{some}. Uses of this word as an identifier will need to be changed, but we do not expect them to be common.]} @end{Incompatible2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/03a.mss��������������������������������������������������������������0000755�0001752�0001001�00001167152�12066652506�016551� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:02 $} @LabeledSection{Declarations and Types} @Comment{$Source: e:\\cvsroot/ARM/Source/03a.mss,v $} @Comment{$Revision: 1.122 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[clause],Old=[section]} describes the types in the language and the rules for declaring constants, variables, and named numbers. @end{Intro} @LabeledClause{Declarations} @begin{Intro} @PDefn{entity} The language defines several kinds of named @i(entities) that are declared by declarations. @PDefn{name} The entity's @i(name) is defined by the declaration, usually by a @nt<defining_@!identifier>, but sometimes by a @nt{defining_@!character_@!literal} or @nt{defining_@!operator_@!symbol}. There are several forms of declaration. A @nt<basic_declaration> is a form of declaration defined as follows. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} @Syn{tabs=[P27], lhs=<basic_declaration>,rhs=" @Syn2{type_declaration}@\| @Syn2{subtype_declaration} | @Syn2{object_declaration}@\| @Syn2{number_declaration} | @Syn2{subprogram_declaration}@\| @Syn2{abstract_subprogram_declaration} | @Chg{Version=[2],New=[@Syn2{null_procedure_declaration}@\| @Chg{Version=<3>,New=<@Syn2{expression_function_declaration} | >,Old=<>}],Old=[]}@Syn2{package_declaration}@Chg{Version=[2],New=[@Chg{Version=[3],New=[@\|],Old=[ |]}],Old=[@\|]} @Syn2{renaming_declaration}@Chg{Version=[2],New=[@Chg{Version=[3],New=[ | ],Old=[@\|]}],Old=[ | ]}@Syn2{exception_declaration}@Chg{Version=[2],New=[@Chg{Version=[3],New=[@\|],Old=[ |]}],Old=[@\|]} @Syn2{generic_declaration}@Chg{Version=[2],New=[@Chg{Version=[3],New=[ | ],Old=[@\|]}],Old=[ | ]}@Syn2{generic_instantiation}"} @Syn{lhs=<defining_identifier>,rhs="@Syn2{identifier}"} @end{Syntax} @begin{StaticSem} @ToGlossaryAlso{Term=<Declaration>, Text=<A @i(declaration) is a language construct that associates a name with (a view of) an entity. @Defn(explicit declaration) @Defn(implicit declaration) A declaration may appear explicitly in the program text (an @i(explicit) declaration), or may be supposed to occur at a given place in the text as a consequence of the semantics of another construct (an @i(implicit) declaration).>} @begin{Discussion} An implicit declaration generally declares a predefined or inherited operation associated with the definition of a type. This term is used primarily when allowing explicit declarations to override implicit declarations, as part of a type declaration. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0255-1],ARef=[AI05-0277-1]} @Defn{declaration} Each of the following is defined to be a declaration: any @nt{basic_@!declaration}; an @nt{enumeration_@!literal_@!specification}; a @nt{discriminant_@!specification}; a @nt{component_@!declaration}; a @nt{loop_@!parameter_@!specification};@Chg{Version=[3],New=[ an @nt{iterator_@!specification};],Old=[]} a @nt{parameter_@!specification}; a @nt{subprogram_@!body};@Chg{Version=[3],New=[ an @nt{extended_@!return_@!object_@!declaration};],Old=[]} an @nt{entry_@!declaration}; an @nt{entry_@!index_@!specification}; a @nt{choice_@!parameter_@!specification}; a @nt{generic_@!formal_@!parameter_@!declaration}.@Chg{Version=[3],New=[],Old=[@Chg{Version=[2],New=[ In addition, an @nt{extended_return_statement} is a declaration of its @nt{defining_identifier}.],Old=[]}]} @begin(Discussion) This list (when @nt<basic_declaration> is expanded out) contains all syntactic categories that end in "_declaration" or "_specification", except for program unit _specifications. Moreover, it contains @nt{subprogram_body}. A @nt{subprogram_body} is a declaration, whether or not it completes a previous declaration. This is a bit strange, @nt{subprogram_body} is not part of the syntax of @nt{basic_declaration} or @nt{library_unit_declaration}. A renaming-as-body is considered a declaration. An @nt{accept_statement} is not considered a declaration. Completions are sometimes declarations, and sometimes not. @end(Discussion) @Defn(view)@Defn(definition) All declarations contain a @i(definition) for a @i(view) of an entity. A view consists of an identification of the entity (the entity @i(of) the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a @nt(renaming_declaration) is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity (see @RefSecNum(Renaming Declarations))). @ChgToGlossary{Version=[2],Kind=[Revised],Term=<View>, Text=<@Chg{Version=[2],New=[A view of an entity reveals some or all of the properties of the entity. A single entity may have multiple views.], Old=[(See @b[Definition].)]}>} @begin{Discussion} Most declarations define a view (of some entity) whose view-specific characteristics are unchanging for the life of the view. However, subtypes are somewhat unusual in that they inherit characteristics from whatever view of their type is currently visible. Hence, a subtype is not a @i(view) of a type; it is more of an indirect reference. By contrast, a private type provides a single, unchanging (partial) view of its full type. @end{Discussion} @ChgToGlossary{Version=[2],Kind=[Deleted],Term=<Definition>, Text=<@ChgDeleted{Version=[2],Text=[@Defn(view) All declarations contain a @i(definition) for a @i(view) of an entity. A view consists of an identification of the entity (the entity @i(of) the view), plus view-specific characteristics that affect the use of the entity through that view (such as mode of access to an object, formal parameter names and defaults for a subprogram, or visibility to components of a type). In most cases, a declaration also contains the definition for the entity itself (a @nt(renaming_declaration) is an example of a declaration that does not define a new entity, but instead defines a view of an existing entity (see @RefSecNum(Renaming Declarations))).]}>} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0080-1]} @ChgAdded{Version=[3],Text=[When it is clear from context, the term @i<object> is used in place of @i<view of an object>. Similarly, the terms @i<type> and @i<subtype> are used in place of @i<view of a type> and @i<view of a subtype>, respectively.@Defn2{Term=[view],Sec=[of an object (implied)]}@Defn2{Term=[view], Sec=[of a type (implied)]}@Defn2{Term=[view],Sec=[of a subtype (implied)]}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Rules interpreted at compile time generally refer to views of entities, rather than the entities themselves. This is necessary to preserve privacy; characteristics that are not visible should not be used in compile-time rules. Thus, @StaticSemTitle and @LegalityTitle generally implicitly have @ldquote@;view of@rdquote. @LegalityTitle that need to look into the private part are the exception to this interpretation.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[On the other hand, run-time rules can work either way, so @ldquote@;view of@rdquote should not be assumed in @RunTimeTitle rules.]} @end{Discussion} @PDefn2{Term=[scope], Sec=(informal definition)} For each declaration, the language rules define a certain region of text called the @i(scope) of the declaration (see @RefSecNum(Scope of Declarations)). Most declarations associate an @nt<identifier> with a declared entity. Within its scope, and only there, there are places where it is possible to use the @nt<identifier> to refer to the declaration, the view it defines, and the associated entity; these places are defined by the visibility rules (see @RefSecNum(Visibility)). @Defn2{Term=[name], Sec={of (a view of) an entity}} At such places the @nt<identifier> is said to be a @i(name) of the entity (the @nt<direct_name> or @nt<selector_name>); @PDefn2{Term=[denote], Sec={informal definition}} the name is said to @i(denote) the declaration, the view, and the associated entity (see @RefSecNum{The Context of Overload Resolution}). @Defn{declare} The declaration is said to @i(declare) the name, the view, and in most cases, the entity itself. As an alternative to an @nt<identifier>, an enumeration literal can be declared with a @nt<character_literal> as its name (see @RefSecNum(Enumeration Types)), and a function can be declared with an @nt<operator_symbol> as its name (see @RefSecNum(Subprogram Declarations)). @Defn{defining name} The syntax rules use the terms @nt<defining_identifier>, @nt<defining_@!character_@!literal>, and @nt<defining_@!operator_@!symbol> for the defining occurrence of a name; these are collectively called @i(defining names). @Defn{usage name} The terms @nt<direct_name> and @nt<selector_name> are used for usage occurrences of @nt<identifier>s, @nt<character_literal>s, and @nt<operator_symbol>s. These are collectively called @i(usage names). @begin(Honest) The terms @nt<identifier>, @nt<character_literal>, and @nt<operator_symbol> are used directly in contexts where the normal visibility rules do not apply (such as the @nt<identifier> that appears after the @key(end) of a @nt<task_body>). Analogous conventions apply to the use of @nt<designator>, which is the collective term for @nt<identifier> and @nt<operator_symbol>. @end(Honest) @end{StaticSem} @begin{RunTime} @RootDefn{execution} The process by which a construct achieves its run-time effect is called @i(execution). @RootDefn{elaboration} @RootDefn{evaluation} This process is also called @i(elaboration) for declarations and @i(evaluation) for expressions. One of the terms execution, elaboration, or evaluation is defined by this International Standard for each construct that has a run-time effect. @ToGlossary{Term=<Execution>, Text=<The process by which a construct achieves its run-time effect is called @i(execution). @Defn(elaboration) @Defn(evaluation) Execution of a declaration is also called @i(elaboration). Execution of an expression is also called @i(evaluation).>} @begin{Honest} The term elaboration is also used for the execution of certain constructs that are not declarations, and the term evaluation is used for the execution of certain constructs that are not expressions. For example, @nt{subtype_indication}s are elaborated, and @nt{range}s are evaluated. For bodies, execution and elaboration are both explicitly defined. When we refer specifically to the execution of a body, we mean the explicit definition of execution for that kind of body, not its elaboration. @end{Honest} @begin(Discussion) Technically, "the execution of a declaration" and "the elaboration of a declaration" are synonymous. We use the term "elaboration" of a construct when we know the construct is elaborable. When we are talking about more arbitrary constructs, we use the term "execution". For example, we use the term "erroneous execution", to refer to any erroneous execution, including erroneous elaboration or evaluation. When we explicitly define evaluation or elaboration for a construct, we are implicitly defining execution of that construct. We also use the term "execution" for things like @nt{statement}s, which are executable, but neither elaborable nor evaluable. We considered using the term "execution" only for nonelaborable, nonevaluable constructs, and defining the term "action" to mean what we have defined "execution" to mean. We rejected this idea because we thought three terms that mean the same thing was enough @em four would be overkill. Thus, the term "action" is used only informally in the standard (except where it is defined as part of a larger term, such as "protected action"). @end(Discussion) @ChgToGlossary{Version=[2],Kind=[Added],Term=<Elaboration>, Text=<@ChgAdded{Version=[2],Text=[The process by which a declaration achieves its run-time effect is called elaboration. Elaboration is one of the forms of execution.]}>} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Evaluation>, Text=<@ChgAdded{Version=[2],Text=[The process by which an expression achieves its run-time effect is called evaluation. Evaluation is one of the forms of execution.]}>} @begin{Honest} @Defn{elaborable} A construct is @i(elaborable) if elaboration is defined for it. @Defn{evaluable} A construct is @i(evaluable) if evaluation is defined for it. @Defn{executable} A construct is @i(executable) if execution is defined for it. @end{Honest} @begin(Discussion) Don't confuse @lquotes@;elaborable@rquotes@; with @lquotes@;preelaborable@rquotes@; (defined in @RefSecNum(Elaboration Control)). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Evaluation of an evaluable construct produces a result that is either a value, a denotation, or a range. The following are evaluable: expression; @nt{name} @nt{prefix}; @nt{range}; @Chg{Version=[2],New=[@nt{entry_index_specification}],Old=[@ntf{entry_list_iterator}]}; and possibly @nt{discrete_range}. The last one is curious @em RM83 uses the term @lquotes@;evaluation of a @nt{discrete_range},@rquotes@; but never defines it. One might presume that the evaluation of a @nt{discrete_range} consists of the evaluation of the @nt{range} or the @nt{subtype_indication}, depending on what it is. But @nt{subtype_indication}s are not evaluated; they are elaborated. Intuitively, an @i(executable) construct is one that has a defined run-time effect (which may be null). Since execution includes elaboration and evaluation as special cases, all elaborable and all evaluable constructs are also executable. Hence, most constructs in Ada are executable. An important exception is that the constructs inside a generic unit are not executable directly, but rather are used as a template for (generally) executable constructs in instances of the generic. @end(Discussion) @end{RunTime} @begin{Notes} @Defn{declare} At compile time, the declaration of an entity @i(declares) the entity. @Defn{create} At run time, the elaboration of the declaration @i(creates) the entity. @begin{Ramification} Syntactic categories for declarations are named either @i(entity_)@ntf<declaration> (if they include a trailing semicolon) or @i(entity_)@ntf<specification> (if not). @Defn{entity} The various kinds of named entities that can be declared are as follows: an object (including components and parameters), a named number, a type (the name always refers to its first subtype), a subtype, a subprogram (including enumeration literals and operators), a single entry, an entry family, a package, a protected or task unit (which corresponds to either a type or a single object), an exception, a generic unit, a label, and the name of a statement. Identifiers are also associated with names of pragmas, arguments to pragmas, and with attributes, but these are not user-definable. @end{Ramification} @end{Notes} @begin{DiffWord83} The syntax rule for @nt{defining_identifier} is new. It is used for the defining occurrence of an @nt{identifier}. Usage occurrences use the @nt{direct_name} or @nt{selector_name} syntactic categories. @Leading@;Each occurrence of an @nt{identifier} (or @ntf{simple_name}), @nt{character_literal}, or @nt{operator_symbol} in the Ada 83 syntax rules is handled as follows in Ada 95: @begin{itemize} It becomes a @nt{defining_identifier}, @nt{defining_character_literal}, or @nt{defining_operator_symbol} (or some syntactic category composed of these), to indicate a defining occurrence; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} It becomes a @nt{direct_name}, in usage occurrences where the usage is required (in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules}) to be directly visible; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} It becomes a @nt{selector_name}, in usage occurrences where the usage is required (in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules}) to be visible but not necessarily directly visible; It remains an @nt{identifier}, @nt{character_literal}, or @nt{operator_symbol}, in cases where the visibility rules do not apply (such as the @nt{designator} that appears after the @key{end} of a @nt{subprogram_body}). @end{itemize} For declarations that come in @lquotes@;two parts@rquotes@; (program unit declaration plus body, private or incomplete type plus full type, deferred constant plus full constant), we consider both to be defining occurrences. Thus, for example, the syntax for @nt{package_body} uses @nt{defining_identifier} after the reserved word @key{body}, as opposed to @nt{direct_name}. The defining occurrence of a statement name is in its implicit declaration, not where it appears in the program text. Considering the statement name itself to be the defining occurrence would complicate the visibility rules. The phrase @lquotes@;visible by selection@rquotes@; is not used in Ada 95. It is subsumed by simply @lquotes@;visible@rquotes@; and the Name Resolution Rules for @nt<selector_name>s. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} (Note that in Ada 95, a declaration is visible at all places where one could have used a @nt{selector_name}, not just at places where a @nt{selector_name} was actually used. Thus, the places where a declaration is directly visible are a subset of the places where it is visible. See @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules} for details.) We use the term @lquotes@;declaration@rquotes@; to cover @ntf<_specification>s that declare (views of) objects, such as @nt<parameter_specification>s. In Ada 83, these are referred to as a @lquotes@;form of declaration,@rquotes@; but it is not entirely clear that they are considered simply @lquotes@;declarations.@rquotes@; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} RM83 contains an incomplete definition of "elaborated" in this @Chg{Version=[3],New=[subclause],Old=[clause]}: it defines "elaborated" for declarations, @nt{declarative_part}s, @nt{declarative_item}s and @nt{compilation_unit}s, but "elaboration" is defined elsewhere for various other constructs. To make matters worse, Ada 95 has a different set of elaborable constructs. Instead of correcting the list, it is more maintainable to refer to the term "elaborable," which is defined in a distributed manner. RM83 uses the term @lquotes@;has no other effect@rquotes@; to describe an elaboration that doesn't do anything except change the state from not-yet-elaborated to elaborated. This was a confusing wording, because the answer to @lquotes@;other than what?@rquotes@; was to be found many pages away. In Ada 95, we change this wording to @lquotes@;has no effect@rquotes@; (for things that truly do nothing at run time), and @lquotes@;has no effect other than to establish that so-and-so can happen without failing the Elaboration_Check@rquotes@; (for things where it matters). We make it clearer that the term "execution" covers elaboration and evaluation as special cases. This was implied in RM83. For example, "erroneous execution" can include any execution, and RM83-9.4(3) has, "The task designated by any other task object depends on the master whose execution creates the task object;" the elaboration of the master's @nt{declarative_part} is doing the task creation. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Added @nt{extended_return_statement} to the list of declarations.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Added null procedures (see @RefSecNum{Null Procedures}) to the syntax.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Added expression functions (see @RefSecNum{Expression Functions}) to the syntax.]} @end{DiffWord2005} @LabeledClause{Types and Subtypes} @begin{StaticSem} @Defn{type} @PDefn{primitive operation} A @i(type) is characterized by a set of values, and a set of @i(primitive operations) which implement the fundamental aspects of its semantics. @PDefn{object} An @i(object) of a given type is a run-time entity that contains (has) a value of the type. @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Type>, Text=<Each object has a type. A @i(type) has an associated set of values, and a set of @i(primitive operations) which implement the fundamental aspects of its semantics. Types are grouped into @Chg{Version=[2],New=[@i(categories)], Old=[@i(classes)]}. @Chg{Version=[2],New=[Most language-defined categories of types are also @i<classes> of types],Old=[The types of a given class share a set of primitive operations. @Defn(closed under derivation) Classes are closed under derivation; that is, if a type is in a class, then all of its derivatives are in that class]}.>} @ChgToGlossary{Version=[3],Kind=[Revised],Term=<Subtype>, Text=<A subtype is a type together with @Chg{Version=[3],New=[optional constraints, null exclusions, and predicates], Old=[a constraint@Chg{Version=[2],New=[ or null exclusion],Old=[]}]}, which @Chg{Version=[3],New=[constrain],Old=[constrains]} the values of the subtype to satisfy @Chg{Version=[3],New=[],Old=[a ]}certain @Chg{Version=[3],New=[conditions],Old=[condition]}. The values of a subtype are a subset of the values of its type.>} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[@Defn2{Term=[category], Sec=(of types)}], Old=[]}@Defn2{Term=[class], Sec=(of types)} Types are grouped into @Chg{Version=[2],New=[@i(categories)], Old=[@i(classes)]} of types@Chg{Version=[2],New=[],Old=[, reflecting the similarity of their values and primitive operations]}. @Defn2{Term=[language-defined class], Sec=(of types)} There exist several @i(language-defined @Chg{Version=[2],New=[categories], Old=[classes]}) of types (see NOTES below)@Chg{Version=[2],New=[, reflecting the similarity of their values and primitive operations],Old=[]}.@Chg{Version=[2], New=[@Defn2{Term=[language-defined category], Sec=(of types)} @Redundant[Most categories of types form @i(classes) of types.]],Old=[]} @Defn{elementary type} @i(Elementary) types are those whose values are logically indivisible; @Defn{composite type} @Defn{component} @i(composite) types are those whose values are composed of @i(component) values. @IndexSeeAlso{Term={aggregate},See=(composite type)} @begin{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The formal definition of @i<category> and @i<class> is found in @RefSecNum{Derived Types and Classes}.]} @end{TheProof} @ChgNote<The following ought to have the Term be: Class@Chg{Version=[2],New=[ (of types)],Old=[]} but that doesn't index properly and it is too much work to fix. See if anyone complains.> @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Class (of types)>, Text=<@Defn(closed under derivation) A class is a set of types that is closed under derivation, which means that if a given type is in the class, then all types derived from that type are also in the class. The set of types of a class share common properties, such as their primitive operations.>} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Category (of types)>, Text=<@ChgAdded{Version=[2],Text=[A category of types is a set of types with one or more common properties, such as primitive operations. A category of types that is closed under derivation is also known as a @i<class>.]}>} @ToGlossary{Term=<Elementary type>, Text=<An elementary type does not have components.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Composite type>, Text=<A composite type @Chg{Version=[2],New=[may have],Old=[has]} components.>} @ToGlossary{Term=<Scalar type>, Text=<A scalar type is either a discrete type or a real type.>} @ToGlossary{Term=<Access type>, Text=<An access type has values that designate aliased objects. Access types correspond to @lquotes@;pointer types@rquotes@; or @lquotes@;reference types@rquotes@; in some other languages.>} @ToGlossary{Term=<Discrete type>, Text=<A discrete type is either an integer type or an enumeration type. Discrete types may be used, for example, in @nt(case_statement)s and as array indices.>} @ToGlossary{Term=<Real type>, Text=<A real type has values that are approximations of the real numbers. Floating point and fixed point types are real types.>} @ToGlossary{Term=<Integer type>, Text=<Integer types comprise the signed integer types and the modular types. A signed integer type has a base range that includes both positive and negative numbers, and has operations that may raise an exception when the result is outside the base range. A modular type has a base range whose lower bound is zero, and has operations with @lquotes@;wraparound@rquotes@; semantics. Modular types subsume what are called @lquotes@;unsigned types@rquotes@; in some other languages.>} @ToGlossary{Term=<Enumeration type>, Text=<An enumeration type is defined by an enumeration of its values, which may be named by identifiers or character literals.>} @ToGlossary{Term=<Character type>, Text=<A character type is an enumeration type whose values include characters.>} @ToGlossary{Term=<Record type>, Text=<A record type is a composite type consisting of zero or more named components, possibly of different types.>} @ToGlossary{Term=<Record extension>, Text=<A record extension is a type that extends another type by adding additional components.>} @ToGlossary{Term=<Array type>, Text=<An array type is a composite type whose components are all of the same type. Components are selected by indexing.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Task type>, Text=<A task type is a composite type @Chg{Version=[2],New=[used to represent], Old=[whose values are tasks, which are]} active entities @Chg{Version=[2],New=[which],Old=[that may]} execute concurrently @Chg{Version=[2],New=[and which can communicate via queued task entries], Old=[with other tasks]}. The top-level task of a partition is called the environment task.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Protected type>, Text=<A protected type is a composite type whose components are @Chg{Version=[2],New=[accessible only through one of its protected operations which synchronize], Old=[protected from]} concurrent access by multiple tasks.>} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Private type>, Text=<A private type @Chg{Version=[2],New=[gives a],Old=[is a partial]} view of a type @Chg{Version=[2],New=[that reveals only some of its properties. The remaining properties are provided by the],Old=[whose]} full view @Chg{Version=[2],New=[given elsewhere. Private types can be used for defining abstractions that hide unnecessary details],Old=[is hidden]} from @Chg{Version=[2],New=[their],Old=[its]} clients.>}@ChgNote{This was changed to parallel "incomplete type"} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Private extension>, Text=<A private extension is @Chg{Version=[2],New=[a type that extends another type, with the additional properties],Old=[like a record extension, except that the components of the extension part are]} hidden from its clients.>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Incomplete type>, Text=<@ChgAdded{Version=[2],Text=[An incomplete type gives a view of a type that reveals only some of its properties. The remaining properties are provided by the full view given elsewhere. Incomplete types can be used for defining recursive data structures.]}>} @Defn{scalar type} The elementary types are the @i(scalar) types (@i(discrete) and @i(real)) and the @i(access) types (whose values provide access to objects or subprograms). @Defn{discrete type} @Defn{enumeration type} Discrete types are either @i(integer) types or are defined by enumeration of their values (@i(enumeration) types). @Defn{real type} Real types are either @i(floating point) types or @i(fixed point) types. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00326-01]} The composite types are the @i(record) types, @i(record extensions), @i(array) types, @Chg{Version=[2],New=[@i(interface) types, ],Old=[]}@i(task) types, and @i(protected) types.@Chg{Version=[2], New=[], Old=[@Defn{private type} @Defn{private extension} A @i(private) type or @i(private extension) represents a partial view (see @RefSecNum{Private Types and Private Extensions}) of a type, providing support for data abstraction. A partial view is a composite type.]} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00442-01]} @ChgDeleted{Version=[2],Text=[The set of all record types do not form a class (because tagged record types can have private extensions), though the set of untagged record types do. In any case, what record types had in common in Ada 83 (component selection) is now a property of the composite class, since all composite types (other than array types) can have discriminants. Similarly, the set of all private types do not form a class (because tagged private types can have record extensions), though the set of untagged private types do. Nevertheless, the set of untagged private types is not particularly @lquotes@;interesting@rquotes@; @em more interesting is the set of all nonlimited types, since that is what a generic formal (nonlimited) private type matches.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incomplete type} @Defn{private type} @Defn{private extension} There can be multiple views of a type with varying sets of operations. @Redundant[An @i(incomplete) type represents an incomplete view (see @RefSecNum{Incomplete Type Declarations}) of a type with a very restricted usage, providing support for recursive data structures. A @i(private) type or @i(private extension) represents a partial view (see @RefSecNum{Private Types and Private Extensions}) of a type, providing support for data abstraction. The full view (see @RefSecNum{Type Declarations}) of a type represents its complete definition.] An incomplete or partial view is considered a composite type@Redundant[, even if the full view is not].]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The real definitions of the views are in the referenced @Chg{Version=[3],New=[subclauses],Old=[clauses]}.]} @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Defn{discriminant} Certain composite types (and@Chg{Version=[2],New=[],Old=[ partial]} views thereof) have special components called @i(discriminants) whose values affect the presence, constraints, or initialization of other components. Discriminants can be thought of as parameters of the type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @Defn{subcomponent} The term @i(subcomponent) is used in this International Standard in place of the term component to indicate either a component, or a component of another subcomponent. Where other subcomponents are excluded, the term component is used instead. @Defn2{Term=[part], Sec=(of an object or value)} Similarly, a @i(part) of an object or value is used to mean the whole object or value, or any set of its subcomponents.@Chg{Version=[2], New=[ The terms component, subcomponent, and part are also applied to a type meaning the component, subcomponent, or part of objects and values of the type.@Defn2{Term=[part], Sec=(of a type)}@Defn2{Term=[component], Sec=(of a type)}],Old=[]} @begin{Discussion} The definition of @lquotes@;part@rquotes@; here is designed to simplify rules elsewhere. By design, the intuitive meaning of @lquotes@;part@rquotes@; will convey the correct result to the casual reader, while this formalistic definition will answer the concern of the compiler-writer. We use the term @lquotes@;part@rquotes@; when talking about the parent part, ancestor part, or extension part of a type extension. In contexts such as these, the part might represent an empty set of subcomponents (e.g. in a null record extension, or a nonnull extension of a null record). We also use @lquotes@;part@rquotes@; when specifying rules such as those that apply to an object with a @lquotes@;controlled part@rquotes@; meaning that it applies if the object as a whole is controlled, or any subcomponent is. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @PDefn{constraint} The set of possible values for an object of a given type can be subjected to a condition that is called a @i(constraint) @Defn{null constraint} (the case of a @i(null constraint) that specifies no restriction is also included)@Redundant[; the rules for which values satisfy a given kind of constraint are given in @RefSecNum(Scalar Types) for @nt<range_constraint>s, @RefSecNum(Index Constraints and Discrete Ranges) for @nt<index_constraint>s, and @RefSecNum(Discriminant Constraints) for @nt<discriminant_constraint>s].@Chg{Version=[2],New=[ The set of possible values for an object of an access type can also be subjected to a condition that excludes the null value (see @RefSecNum{Access Types}).],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00415-01]} @Defn{subtype} A @i(subtype) of a given type is a combination of the type, a constraint on values of the type, and certain attributes specific to the subtype. The given type is called the @Chg{Version=[2],New=[@i(type of the subtype)], Old=[type @i(of) the subtype]}.@Chg{Version=[2],New=[@Defn2{Term=[type], Sec=(of a subtype)} @Defn2{Term=[subtype], Sec=(type of)}],Old=[]} Similarly, the associated constraint is called the @Chg{Version=[2],New=[@i(constraint of the subtype)], Old=[constraint @i(of) the subtype]}.@Chg{Version=[2],New=[@Defn2{Term=[constraint], Sec=(of a subtype)} @Defn2{Term=[subtype], Sec=(constraint of)}],Old=[]} The set of values of a subtype consists of the values of its type that satisfy its constraint@Chg{Version=[2],New=[ and any exclusion of the null value], Old=[]}. @Defn2{Term=[belong], Sec=(to a subtype)} Such values @i(belong) to the subtype.@Chg{Version=[2],New=[@Defn2{Term=[values], Sec=(belonging to a subtype)} @Defn2{Term=[subtype], Sec=(values belonging to)}],Old=[]} @begin{Discussion} We make a strong distinction between a type and its subtypes. In particular, a type is @i(not) a subtype of itself. There is no constraint associated with a type (not even a null one), and type-related attributes are distinct from subtype-specific attributes. @end{Discussion} @begin{Discussion} We no longer use the term "base type." All types were "base types" anyway in Ada 83, so the term was redundant, and occasionally confusing. In the RM95 we say simply "the type @i(of) the subtype" instead of "the base type of the subtype." @end{Discussion} @begin{Ramification} The value subset for a subtype might be empty, and need not be a proper subset. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Any name of a @Chg{Version=[2],New=[category],Old=[class]} of types (such as @lquotes@;discrete@rquotes@;@Chg{Version=[2],New=[, ],Old=[ or]} @lquotes@;real@rquotes@;@Chg{Version=[2],New=[, or],Old=[), or other category of types (such as]} @lquotes@;limited@rquotes@;@Chg{Version=[2],New=[], Old=[ or @lquotes@;incomplete@rquotes@;]}) is also used to qualify its subtypes, as well as its objects, values, declarations, and definitions, such as an @lquotes@;integer type declaration@rquotes@; or an @lquotes@;integer value.@rquotes@; In addition, if a term such as @lquotes@;parent subtype@rquotes@; or @lquotes@;index subtype@rquotes@; is defined, then the corresponding term for the type of the subtype is @lquotes@;parent type@rquotes@; or @lquotes@;index type.@rquotes@; @end{Honest} @begin{Discussion} We use these corresponding terms without explicitly defining them, when the meaning is obvious. @end{Discussion} @Defn{constrained} @Defn{unconstrained} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A subtype is called an @i(unconstrained) subtype if its type has unknown discriminants, or if its type allows range, index, or discriminant constraints, but the subtype does not impose such a constraint; otherwise, the subtype is called a @i(constrained) subtype (since it has no unconstrained characteristics). @begin{Discussion} In an earlier version of Ada 9X, "constrained" meant "has a nonnull constraint." However, we changed to this definition since we kept having to special case composite non-array/nondiscriminated types. It also corresponds better to the (now obsolescent) attribute 'Constrained. For scalar types, @lquotes@;constrained@rquotes@; means @lquotes@;has a nonnull constraint@rquotes@;. For composite types, in implementation terms, @lquotes@;constrained@rquotes@; means that the size of all objects of the subtype is the same, assuming a typical implementation model. Class-wide subtypes are always unconstrained. @end{Discussion} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[Any set of types can be called a @lquotes@;category@rquotes@; of types, and any],Old=[Any]} set of types that is closed under derivation (see @RefSecNum(Derived Types and Classes)) can be called a @lquotes@;class@rquotes@; of types. However, only certain @Chg{Version=[2],New=[categories and ],Old=[]}classes are used in the description of the rules of the language @em generally those that have their own particular set of primitive operations (see @RefSecNum(Classification of Operations)), or that correspond to a set of types that are matched by a given kind of generic formal type (see @RefSecNum(Formal Types)). @PDefn{language-defined class} The following are examples of @lquotes@;interesting@rquotes@; @i(language-defined classes): elementary, scalar, discrete, enumeration, character, boolean, integer, signed integer, modular, real, floating point, fixed point, ordinary fixed point, decimal fixed point, numeric, access, access-to-object, access-to-subprogram, composite, array, string, (untagged) record, tagged, task, protected, nonlimited. Special syntax is provided to define types in each of these classes.@Chg{Version=[2],New=[ In addition to these classes, the following are examples of @lquotes@;interesting@rquotes@; @i(language-defined categories): @PDefn{language-defined categories} abstract, incomplete, interface, limited, private, record.],Old=[]} @begin{Discussion} @Defn{value} A @i(value) is a run-time entity with a given type which can be assigned to an object of an appropriate subtype of the type. @Defn{operation} An @i(operation) is a program entity that operates on zero or more operands to produce an effect, or yield a result, or both. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Note that a type's @Chg{Version=[2],New=[category (and ],Old=[]}class@Chg{Version=[2],New=[)],Old=[]} depends on the place of the reference @em a private type is composite outside and possibly elementary inside. It's really the @i{view} that is elementary or composite. Note that although private types are composite, there are some properties that depend on the corresponding full view @em for example, parameter passing modes, and the constraint checks that apply in various places. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[Every property of types forms a category, but not], Old=[Not]} every property of types represents a class. For example, the set of all abstract types does not form a class, because this set is not closed under derivation.@Chg{Version=[2],New=[ Similarly, the set of all interface types does not form a class.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The set of limited types @Chg{Version=[2],New=[does not form a class (since nonlimited types can inherit from limited interfaces), but the set of nonlimited types does. The set of tagged record types and the set of tagged private types do not form a class (because each of them can be extended to create a type of the other category); that implies that the set of record types and the set of private types also do not form a class (even though untagged record types and untagged private types do form a class). In all of these cases, we can talk about the category of the type; for instance, we can talk about the @lquotes@;category of limited types@rquotes.], Old=[forms a class in the sense that it is closed under derivation, but the more interesting class, from the point of generic formal type matching, is the set of all types, limited and nonlimited, since that is what matches a generic formal @lquotes@;limited@rquotes@; private type. Note also that a limited type can @lquotes@;become nonlimited@rquotes@; under certain circumstances, which makes @lquotes@;limited@rquotes@; somewhat problematic as a class of types]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Normatively, the @i<language-defined classes> are those that are defined to be inherited on derivation by @RefSecNum{Derived Types and Classes}; other properties either aren't interesting or form categories, not classes.]} @end{Ramification} @noprefix@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} These language-defined @Chg{Version=[2],New=[categories],Old=[classes]} are organized like this: @begin{Display} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @TabClear{} @TabSet{3, 6, 9, 12, 15, 18, 21} all types @\elementary @\@\scalar @\@\@\discrete @\@\@\@\enumeration @\@\@\@\@\character @\@\@\@\@\boolean @\@\@\@\@\other enumeration @\@\@\@\integer @\@\@\@\@\signed integer @\@\@\@\@\modular integer @\@\@\real @\@\@\@\floating point @\@\@\@\fixed point @\@\@\@\@\ordinary fixed point @\@\@\@\@\decimal fixed point @\@\access @\@\@\access-to-object @\@\@\access-to-subprogram @\composite@Chg{Version=[2],New=[ @\@\untagged],Old=[]} @Chg{Version=[2],New=[@\],Old=[]}@\@\array @Chg{Version=[2],New=[@\],Old=[]}@\@\@\string @Chg{Version=[2],New=[@\],Old=[]}@\@\@\other array @\@\@Chg{Version=[2],New=[@\],Old=[untagged ]}record@Chg{Version=[2],New=[],Old=[ @\@\tagged]} @Chg{Version=[2],New=[@\],Old=[]}@\@\task @Chg{Version=[2],New=[@\],Old=[]}@\@\protected@Chg{Version=[2],New=[ @\@\tagged (including interfaces) @\@\@\nonlimited tagged record @\@\@\limited tagged @\@\@\@\limited tagged record @\@\@\@\synchronized tagged @\@\@\@\@\tagged task @\@\@\@\@\tagged protected],Old=[]} @end{Display} @noprefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[There are other categories, such as],Old=[The classes]} @lquotes@;numeric@rquotes@; and @lquotes@;@Chg{Version=[2],New=[discriminated],Old=[nonlimited]}@rquotes@;@Chg{Version=[2], New=[, which],Old=[]} represent other @Chg{Version=[2],New=[categorization],Old=[classification]} dimensions@Chg{Version=[2],New=[, but], Old=[ and]} do not fit into the above strictly hierarchical picture. @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Note that this is also true for some categories mentioned in the chart. The category @lquotes@;task@rquotes@; includes both untagged tasks and tagged tasks. Similarly for @lquotes@;protected@rquotes@;, @lquotes@;limited@rquotes@;, and @lquotes@;nonlimited@rquotes@; (note that limited and nonlimited are not shown for untagged composite types).]} @end{Discussion} @end{Notes} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause and its subclauses]} now @Chg{Version=[3],New=[precedes],Old=[precede]} the @Chg{Version=[3],New=[],Old=[clause and ]}subclauses on objects and named numbers, to cut down on the number of forward references. We have dropped the term "base type" in favor of simply "type" (all types in Ada 83 were "base types" so it wasn't clear when it was appropriate/necessary to say "base type"). Given a subtype S of a type T, we call T the "type of the subtype S." @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a mention of null exclusions when we're talking about constraints (these are not constraints, but they are similar).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Defined an interface type to be a composite type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Revised the wording so that it is clear that an incomplete view is similar to a partial view in terms of the language.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Added a definition of component of a type, subcomponent of a type, and part of a type. These are commonly used in the standard, but they were not previously defined.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[Reworded most of this @Chg{Version=[3],New=[subclause],Old=[clause]} to use category rather than class, since so many interesting properties are not, strictly speaking, classes. Moreover, there was no normative description of exactly which properties formed classes, and which did not. The real definition of class, along with a list of properties, is now in @RefSecNum{Derived Types and Classes}.]} @end{DiffWord95} @LabeledSubClause{Type Declarations} @begin{Intro} A @nt<type_declaration> declares a type and its first subtype. @end{Intro} @begin{Syntax} @Syn{lhs=<type_declaration>,rhs=" @Syn2{full_type_declaration} | @Syn2{incomplete_type_declaration} | @Syn2{private_type_declaration} | @Syn2{private_extension_declaration}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<full_type_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}] @key{is} @Syn2{type_definition}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @Syn2{task_type_declaration} | @Syn2{protected_type_declaration}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Syn{tabs=[P29], lhs=<type_definition>,rhs=" @Syn2{enumeration_type_definition}@\| @Syn2{integer_type_definition} | @Syn2{real_type_definition}@\| @Syn2{array_type_definition} | @Syn2{record_type_definition}@\| @Syn2{access_type_definition} | @Syn2{derived_type_definition}@Chg{Version=[2],New=[@\| @Syn2{interface_type_definition}],Old=[]}"} @end{Syntax} @begin{Legality} A given type shall not have a subcomponent whose type is the given type itself. @end{Legality} @begin{StaticSem} @Defn{first subtype} The @nt{defining_@!identifier} of a @nt{type_@!declaration} denotes the @i(first subtype) of the type. The @nt<known_@!discriminant_@!part>, if any, defines the discriminants of the type (see @RefSec(Discriminants)). The remainder of the @nt<type_@!declaration> defines the remaining characteristics of (the view of) the type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{named type} A type defined by a @nt<type_@!declaration> is a @i(named) type; such a type has one or more nameable subtypes. @Defn{anonymous type} Certain other forms of declaration also include type definitions as part of the declaration for an object@Chg{Version=[2],New=[], Old=[ (including a parameter or a discriminant)]}. The type defined by such a declaration is @i(anonymous) @em it has no nameable subtypes. @Defn2{Term=[italics],Sec=(pseudo-names of anonymous types)} For explanatory purposes, this International Standard sometimes refers to an anonymous type by a pseudo-name, written in italics, and uses such pseudo-names at places where the syntax normally requires an @nt<identifier>. For a named type whose first subtype is T, this International Standard sometimes refers to the type of T as simply @lquotes@;the type T@rquotes@;. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The only user-defined types that can be anonymous in the above sense are array, access, task, and protected types. An anonymous array, task, or protected type can be defined as part of an @nt{object_declaration}. An anonymous access type can be defined as part of @Chg{Version=[2],New=[numerous other constructs],Old=[a parameter or discriminant specification]}. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00326-01]} @Defn{full type} A named type that is declared by a @nt<full_type_@!declaration>, or an anonymous type that is defined @Chg{Version=[2],New=[by an @nt{access_definition} or ],Old=[]}as part of declaring an object of the type, is called a @i(full type).@Defn{full type definition} @Chg{Version=[2],New=[The declaration of a full type also declares the @i<full view> of the type.@Defn2{Term=[full view],Sec=(of a type)} ],Old=[]}The @nt<type_@!definition>, @nt<task_@!definition>, @nt<protected_@!definition>, or @nt<access_@!definition> that defines a full type is called a @i(full type definition). @redundant[Types declared by other forms of @nt<type_@!declaration> are not separate types; they are partial or incomplete views of some full type.] @begin{Honest} Class-wide, universal, and root numeric types are full types. @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[We need to mention @nt{access_definition} separately, as it may occur in renames, which do not declare objects.]} @end{Reason} @PDefn{predefined operator} The definition of a type implicitly declares certain @i(predefined operators) that operate on the type, according to what classes the type belongs, as specified in @RefSec(Operators and Expression Evaluation). @begin{Discussion} We no longer talk about the implicit declaration of basic operations. These are treated like an @nt{if_statement} @em they don't need to be declared, but are still applicable to only certain classes of types. @end{Discussion} @Defn{predefined type} The @i{predefined types} @Redundant[(for example the types Boolean, Wide_Character, Integer, @i{root_integer}, and @i{universal_integer})] are the types that are defined in @Redundant[a predefined library package called] Standard@Redundant[; this package also includes the @Redundant{(implicit)} declarations of their predefined operators]. @Redundant[The package Standard is described in @RefSecNum{The Package Standard}.] @begin{Ramification} We use the term @lquotes@;predefined@rquotes@; to refer to entities declared in the visible part of Standard, to implicitly declared operators of a type whose semantics are defined by the language, to Standard itself, and to the @lquotes@;predefined environment@rquotes@;. We do not use this term to refer to library packages other than Standard. For example Text_IO is a language-defined package, not a predefined package, and Text_IO.Put_Line is not a predefined operation. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(full_type_declaration)} The elaboration of a @nt{full_type_declaration} consists of the elaboration of the full type definition. @PDefn2{Term=[elaboration], Sec=(full type definition)} Each elaboration of a full type definition creates a distinct type and its first subtype. @begin{Reason} The creation is associated with the type @i(definition), rather than the type @i(declaration), because there are types that are created by full type definitions that are not immediately contained within a type declaration (e.g. an array object declaration, a singleton task declaration, etc.). @end{Reason} @begin{Ramification} Any implicit declarations that occur immediately following the full type definition are elaborated where they (implicitly) occur. @end{Ramification} @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of type definitions:) @begin(Example) (White, Red, Yellow, Green, Blue, Brown, Black) @key(range) 1 .. 72 @key(array)(1 .. 10) @key(of) Integer @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of type declarations:) @end{WideAbove} @begin(Example) @key(type) Color @key(is) (White, Red, Yellow, Green, Blue, Brown, Black); @key(type) Column @key(is) @key(range) 1 .. 72; @key(type) Table @key(is) @key(array)(1 .. 10) @key(of) Integer; @end(Example) @end{Examples} @begin{Notes} Each of the above examples declares a named type. The identifier given denotes the first subtype of the type. Other named subtypes of the type can be declared with @nt<subtype_declaration>s (see @RefSecNum{Subtype Declarations}). Although names do not directly denote types, a phrase like @lquotes@;the type Column@rquotes@; is sometimes used in this International Standard to refer to the type of Column, where Column denotes the first subtype of the type. For an example of the definition of an anonymous type, see the declaration of the array Color_Table in @RefSecNum{Object Declarations}; its type is anonymous @em it has no nameable subtypes. @end{Notes} @begin{DiffWord83} The syntactic category @nt{full_type_declaration} now includes task and protected type declarations. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We have generalized the concept of first-named subtype (now called simply @lquotes@;first subtype@rquotes@;) to cover all kinds of types, for uniformity of description elsewhere. RM83 defined first-named subtype in Section 13. We define first subtype here, because it is now a more fundamental concept. We renamed the term, because in Ada 95 some first subtypes have no name. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} We no longer elaborate @nt{discriminant_part}s, because there is nothing to do, and it was complex to say that you only wanted to elaborate it once for a private or incomplete type. This is also consistent with the fact that subprogram specifications are not elaborated (neither in Ada 83 nor in Ada 95). Note, however, that an @nt<access_definition> appearing in a @nt<discriminant_part> is elaborated@Chg{Version=[2],New=[ at the @nt{full_type_declaration} (for a nonlimited type) or],Old=[]} when an object with such a discriminant is created@Chg{Version=[2],New=[ (for a limited type)],Old=[]}. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Added wording so that anonymous access types are always full types, even if they appear in renames.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added interface types (see @RefSecNum{Interface Types}) to the syntax.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Added a definition of full view, so that all types have a well-defined full view.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{full_type_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Subtype Declarations} @begin{Intro} A @nt<subtype_declaration> declares a subtype of some previously declared type, as defined by a @nt<subtype_indication>. @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<subtype_declaration>,rhs=" @key{subtype} @Syn2{defining_identifier} @key{is} @Syn2{subtype_indication}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<subtype_indication>,rhs=" @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [@Syn2{constraint}]"} @Syn{lhs=<subtype_mark>,rhs="@SynI{subtype_}@Syn2{name}"} @begin{Ramification} Note that @nt{name} includes @nt{attribute_reference}; thus, S'Base can be used as a @nt{subtype_mark}. @end{Ramification} @begin{Reason} We considered changing @nt{subtype_mark} to @ntf{subtype_name}. However, existing users are used to the word "mark," so we're keeping it. @end{Reason} @Syn{lhs=<constraint>,rhs="@Syn2<scalar_constraint> | @Syn2<composite_constraint>"} @Syn{lhs=<scalar_constraint>,rhs=" @Syn2{range_constraint} | @Syn2{digits_constraint} | @Syn2{delta_constraint}"} @Syn{lhs=<composite_constraint>,rhs=" @Syn2{index_constraint} | @Syn2{discriminant_constraint}"} @end{Syntax} @begin{Resolution} A @nt{subtype_mark} shall resolve to denote a subtype. @Defn2{Term=[determines], Sec=(a type by a @nt{subtype_mark})} The type @i(determined by) a @nt<subtype_mark> is the type of the subtype denoted by the @nt{subtype_mark}. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Types are never directly named; all @nt{subtype_mark}s denote subtypes @em possibly an unconstrained (base) subtype, but never the type. When we use the term @i(anonymous type) we really mean a type with no @Chg{Version=[3],New=[nameable],Old=[namable]} subtypes. @end{Ramification} @end{Resolution} @begin{RunTime} @Leading@PDefn2{Term=[elaboration], Sec=(subtype_declaration)} The elaboration of a @nt{subtype_declaration} consists of the elaboration of the @nt{subtype_indication}. @PDefn2{Term=[elaboration], Sec=(subtype_indication)} The elaboration of a @nt{subtype_indication} creates a new subtype. If the @nt{subtype_indication} does not include a @nt<constraint>, the new subtype has the same (possibly null) constraint as that denoted by the @nt{subtype_mark}. The elaboration of a @nt{subtype_indication} that includes a @nt<constraint> proceeds as follows: @begin{itemize} The @nt<constraint> is first elaborated. @IndexCheck{Range_Check} A check is then made that the @nt<constraint> is @i(compatible) with the subtype denoted by the @nt{subtype_mark}. @begin{Ramification} The checks associated with constraint compatibility are all Range_Checks. Discriminant_Checks and Index_Checks are associated only with checks that a value satisfies a constraint. @end{Ramification} @end{itemize} The condition imposed by a @nt<constraint> is the condition obtained after elaboration of the @nt<constraint>. @RootDefn2{Term=[compatibility], Sec=(constraint with a subtype)} The rules defining compatibility are given for each form of @nt<constraint> in the appropriate subclause. These rules are such that if a @nt<constraint> is @i(compatible) with a subtype, then the condition imposed by the @nt<constraint> cannot contradict any condition already imposed by the subtype on its values. @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if any check of compatibility fails. @begin{Honest} The condition imposed by a @nt<constraint> is named after it @em a @nt<range_constraint> imposes a range constraint, etc. @end{Honest} @begin{Ramification} A @nt<range_constraint> causes freezing of its type. Other @nt<constraint>s do not. @end{Ramification} @end{RunTime} @begin{Notes} A @nt<scalar_constraint> may be applied to a subtype of an appropriate scalar type (see @RefSecNum{Scalar Types}, @RefSecNum{Fixed Point Types}, and @RefSecNum{Reduced Accuracy Subtypes}), even if the subtype is already constrained. On the other hand, a @nt<composite_constraint> may be applied to a composite subtype (or an access-to-composite subtype) only if the composite subtype is unconstrained (see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Discriminant Constraints}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of subtype declarations:) @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(subtype) Rainbow @key(is) Color @key(range) Red .. Blue; --@RI[ see @RefSecNum(Type Declarations)] @key(subtype) Red_Blue @key(is) Rainbow; @key(subtype) Int @key(is) Integer; @key(subtype) Small_Int @key(is) Integer @key(range) -10 .. 10; @key(subtype) Up_To_K @key(is) Column @key(range) 1 .. K; --@RI[ see @RefSecNum(Type Declarations)] @key(subtype) Square @key(is) Matrix(1 .. 10, 1 .. 10); --@RI[ see @RefSecNum(Array Types)] @key(subtype) Male @key(is) Person(Sex => M); --@RI[ see @RefSecNum(Incomplete Type Declarations)]@Chg{Version=[2],New=[ @key(subtype) Binop_Ref @key(is not null) Binop_Ptr; --@RI[ see @RefSecNum(Access Types)]],Old=[]} @end(Example) @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 95, all @nt<range_constraint>s cause freezing of their type. Hence, a type-related representation item for a scalar type has to precede any @nt<range_constraint>s whose type is the scalar type. @end{Incompatible83} @begin{DiffWord83} @nt{Subtype_mark}s allow only subtype names now, since types are never directly named. There is no need for RM83-3.3.2(3), which says a @nt{subtype_mark} can denote both the type and the subtype; in Ada 95, you denote an unconstrained (base) subtype if you want, but never the type. The syntactic category @ntf{type_mark} is now called @nt{subtype_mark}, since it always denotes a subtype. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An optional @nt{null_exclusion} can be used in a @nt{subtype_indication}. This is described in @RefSecNum{Access Types}.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{subtype_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Classification of Operations} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{operates on a type} An operation @i(operates on a type) @i(T) if it yields a value of type @i(T), if it has an operand whose expected type (see @RefSecNum{The Context of Overload Resolution}) is @i(T), or if it has an access parameter@Chg{Version=[2],New=[ or access result type],Old=[]} (see @RefSecNum(Subprogram Declarations)) designating @i(T). @Defn2{Term=[predefined operation], Sec=(of a type)} A predefined operator, or other language-defined operation such as assignment or a membership test, that operates on a type, is called a @i(predefined operation) of the type. @Defn2{Term=[primitive operations], Sec=(of a type)} The @i(primitive operations) of a type are the predefined operations of the type, plus any user-defined primitive subprograms. @ToGlossary{Term=<Primitive operations>, Text=<The primitive operations of a type are the operations (such as subprograms) declared together with the type declaration. They are inherited by other types in the same class of types. For a tagged type, the primitive subprograms are dispatching subprograms, providing run-time polymorphism. A dispatching subprogram may be called with statically tagged operands, in which case the subprogram body invoked is determined at compile time. Alternatively, a dispatching subprogram may be called using a dispatching call, in which case the subprogram body invoked is determined at run time.>} @begin{Honest} Protected subprograms are not considered to be @lquotes@;primitive subprograms,@rquotes@; even though they are subprograms, and they are inherited by derived types. @end{Honest} @begin{Discussion} We use the term @lquotes@;primitive subprogram@rquotes@; in most of the rest of the manual. The term @lquotes@;primitive operation@rquotes@; is used mostly in conceptual discussions. @end{Discussion} @Leading@Defn2{Term=[primitive subprograms], Sec=(of a type)} The @i(primitive subprograms) of a specific type are defined as follows: @begin{Itemize} The predefined operators of the type (see @RefSecNum{Operators and Expression Evaluation}); For a derived type, the inherited (see @RefSecNum{Derived Types and Classes}) user-defined subprograms; For an enumeration type, the enumeration literals (which are considered parameterless functions @em see @RefSecNum{Enumeration Types}); For a specific type declared immediately within a @nt<package_specification>, any subprograms (in addition to the enumeration literals) that are explicitly declared immediately within the same @nt<package_specification> and that operate on the type; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0128-1]} @ChgAdded{Version=[3],Text=[For a specific type with an explicitly declared primitive "=" operator whose result type is Boolean, the corresponding "/=" operator (see @RefSecNum{Overloading of Operators});]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00200-01]} @Defn2{Term=[override], Sec=(a primitive subprogram)} @Chg{Version=[2],New=[For a nonformal type, any],Old=[Any]} subprograms not covered above @Redundant[that are explicitly declared immediately within the same declarative region as the type] and that override (see @RefSecNum{Visibility}) other implicitly declared primitive subprograms of the type. @end{Itemize} @begin{Discussion} In Ada 83, only subprograms declared in the visible part were @lquotes@;primitive@rquotes@; (i.e. derivable). In Ada 95, mostly because of child library units, we include all operations declared in the private part as well, and all operations that override implicit declarations. @end{Discussion} @begin{Ramification} It is possible for a subprogram to be primitive for more than one type, though it is illegal for a subprogram to be primitive for more than one tagged type. See @RefSecNum(Tagged Types and Type Extensions). @end{Ramification} @begin(Discussion) The order of the implicit declarations when there are both predefined operators and inherited subprograms is described in @RefSec(Derived Types and Classes). @end(Discussion) @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00200-01]} @ChgAdded{Version=[2],Text=[Subprograms declared in a generic package specification are never primitive for a formal type, even if they happen to override an operation of the formal type. This includes formal subprograms, which are never primitive operations (that's true even for an abstract formal subprogram).]} @end{Ramification} @Defn2{Term=[primitive operator], Sec=(of a type)} A primitive subprogram whose designator is an @nt<operator_symbol> is called a @i(primitive operator). @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The attribute S'Base is no longer defined for nonscalar subtypes. Since this was only permitted as the prefix of another attribute, and there are no interesting nonscalar attributes defined for an unconstrained composite or access subtype, this should not affect any existing programs. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The primitive subprograms (derivable subprograms) include subprograms declared in the private part of a package specification as well, and those that override implicitly declared subprograms, even if declared in a body. @end{Extend83} @begin{DiffWord83} We have dropped the confusing term @i<operation of a type> in favor of the more useful @i<primitive operation of a type> and the phrase @i<operates on a type>. The description of S'Base has been moved to @RefSec{Scalar Types} because it is now defined only for scalar types. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00200-01]} @ChgAdded{Version=[2],Text=[Clarified that a formal subprogram that happens to override a primitive operation of a formal type is not a primitive operation (and thus not a dispatching operation) of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added wording to include access result types in the kinds of operations that operate on a type T.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0128-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The implicitly declared "/=" for a primitive "=" operator is also primitive; this makes it eligible to be made visible by a @key[use type] clause.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Subtype Predicates]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0269-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[The language-defined @i{predicate aspects} Static_Predicate and Dynamic_Predicate may be used to define properties of subtypes. A @i{predicate specification} is an @nt{aspect_specification} for one of the two predicate aspects.@Defn{predicate aspect}@Defn{predicate specification}@PDefn2{Term=[aspect],Sec=(predicate)}@AspectDefn{Static_Predicate}@AspectDefn{Dynamic_Predicate} General rules for aspects and @nt{aspect_specification}s are found in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Representation Issues} (@RefSecNum{Operational and Representation Aspects} and @RefSecNum{Aspect Specifications} respectively).]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Static_Predicate], Text=[@ChgAdded{Version=[3],Text=[Condition that must hold true for objects of a given subtype; the subtype may be static.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Dynamic_Predicate], Text=[@ChgAdded{Version=[3],Text=[Condition that must hold true for objects of a given subtype; the subtype is not static.]}]} @end{Intro} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[The expected type for a predicate aspect @nt{expression} is any boolean type.@PDefn2{Term=[expected type],Sec=[@nt{expression} of a predicate aspect]}]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[A predicate specification may be given on a @nt{type_declaration} or a @nt{subtype_declaration}, and applies to the declared subtype. In addition, predicate specifications apply to certain other subtypes:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For a (first) subtype defined by a derived type declaration, the predicates of the parent subtype and the progenitor subtypes apply.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For a subtype created by a @nt{subtype_indication}, the predicate of the subtype denoted by the @nt{subtype_mark} applies.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[The @i<predicate> of a subtype consists of all predicate specifications that apply, and-ed together; if no predicate specifications apply, the predicate is True @Redundant[(in particular, the predicate of a base subtype is True)].@Defn2{Term=[Predicate],Sec=(of a subtype)}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Predicate checks are defined to be @i<enabled> or @i<disabled> for a given subtype as follows:@Defn2{Term=[enabled],Sec=[predicate checks]}@Defn2{Term=[disabled],Sec=[predicate checks]}@Defn2{Term=[predicate check],Sec=[enabled]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[If a subtype is declared by a @nt{type_declaration} or @nt{subtype_declaration} that includes a predicate specification, then:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if performing checks is required by the Static_Predicate assertion policy (see @RefSecNum{Pragmas Assert and Assertion_Policy}) and the declaration includes a Static_Predicate specification, then predicate checks are enabled for the subtype;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if performing checks is required by the Dynamic_Predicate assertion policy (see @RefSecNum{Pragmas Assert and Assertion_Policy}) and the declaration includes a Dynamic_Predicate specification, then predicate checks are enabled for the subtype;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[otherwise, predicate checks are disabled for the subtype@Redundant[, regardless of whether predicate checking is enabled for any other subtypes mentioned in the declaration];]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If a subtype is defined by a derived type declaration that does not include a predicate specification, then predicate checks are enabled for the subtype if and only if predicate checks are enabled for at least one of the parent subtype and the progenitor subtypes;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If a subtype is created by a @nt{subtype_indication} other than in one of the previous cases, then predicate checks are enabled for the subtype if and only if predicate checks are enabled for the subtype denoted by the @nt{subtype_mark};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Otherwise, predicate checks are disabled for the given subtype.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In this case, no predicate specifications can apply to the subtype and so it doesn't typically matter whether predicate checks are enabled. This rule does make a difference, however, when determining whether predicate checks are enabled for another type when this type is one of multiple progenitors. See the @ldquote@;derived type declaration@rdquote wording above.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Even when predicate checks are disabled, a predicate cam affect various @LegalityTitle, the results of membership tests, the items in a @key[for] loop, and the result of the Valid attribute.]} @end{Discussion} @end{Itemize} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The @nt{expression} of a Static_Predicate specification shall be @i<predicate-static>; that is, one of the following:@Defn{predicate-static}@Defn2{Term=[expression],Sec=[predicate-static]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a static expression;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a membership test whose @nt{simple_expression} is the current instance, and whose @nt{membership_choice_list} meets the requirements for a static membership test (see @RefSecNum{Static Expressions and Static Subtypes});]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a @nt{case_expression} whose @SynI{selecting_}@nt{expression} is the current instance, and whose @SynI{dependent_}@nt{expression}s are static expressions;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a call to a predefined equality or ordering operator, where one operand is the current instance, and the other is a static expression;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[a call to a predefined boolean logical operator, where each operand is predicate-static;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[a short-circuit control form where both operands are predicate-static; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a parenthesized predicate-static @nt{expression}.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A predicate shall not be specified for an incomplete subtype.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The expression of such a predicate could not depend on the properties of the value of the type (since it doesn't have any), so it is useless and we don't want to require the added complexity needed to support it.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0287-1]} @ChgAdded{Version=[3],Text=[If a predicate applies to a subtype, then that predicate shall not mention any other subtype to which the same predicate applies.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This is intended to prevent recursive predicates, which cause definitional problems for static predicates. Inside of the predicate, the subtype name refers to the current instance of the subtype, which is an object, so a direct use of the subtype name cannot be recursive. But other subtypes naming the same type might:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] Really_Ugly @key[is private]; @key[private] @key[subtype] Ugly @key[is] Really_Ugly; @key[type] Really_Ugly @key[is new] Integer @key[with] Static_Predicate => Really_Ugly @key[not in] Ugly; --@ExamCom{ Illegal!}]} @end{Example} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[An index subtype, @nt{discrete_range} of an @nt{index_constraint} or @nt{slice}, or a @nt{discrete_subtype_definition} of a @nt{constrained_array_definition}, @nt{entry_declaration}, or @nt{entry_index_specification} shall not denote a subtype to which predicate specifications apply.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[The @nt{prefix} of an @nt{attribute_reference} whose @nt{attribute_designator} is First, Last, or Range shall not denote a scalar subtype to which predicate specifications apply.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0297-1]} @ChgAdded{Version=[3],Text=[This is to prevent confusion about whether the First value is the lowest value of the subtype (which does not depend on the predicate) or the lowest value of the subtype which meets the predicate. (For a dynamic predicate, determining this latter value is expensive as it would usually require a loop.) For a static subtype that has a static predicate, the First_Valid and Last_Valid attributes (see @RefSecNum{Operations of Discrete Types}) can be used instead.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0262-1],ARef=[AI05-0287-1]} @ChgAdded{Version=[3],Text=[The @nt{discrete_subtype_definition} of a @nt{loop_parameter_specification} shall not denote a nonstatic subtype to which predicate specifications apply or any subtype to which Dynamic_Predicate specifications apply.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The @nt{discrete_choice} of a @nt{named_array_aggregate} shall not denote a nonstatic subtype to which predicate specifications apply.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[This rule prevents noncontiguous dynamically bounded array aggregates, which could be expensive to check for. (Array aggregates have rules to prevent problems with static subtypes.) We define this rule here so that the runtime generic body check applies.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.@PDefn{generic contract issue}]} @end{Legality} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If predicate checks are enabled for a given subtype, then:]} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@Redundant[On every subtype conversion, the predicate of the target subtype is evaluated, and a check is performed that the predicate is True. This includes all parameter passing, except for certain parameters passed by reference, which are covered by the following rule: ] After normal completion and leaving of a subprogram, for each @key[in out] or @key[out] parameter that is passed by reference, the predicate of the subtype of the actual is evaluated, and a check is performed that the predicate is True. For an object created by an @nt{object_declaration} with no explicit initialization @nt{expression}, or by an uninitialized @nt{allocator}, if any subcomponents have @nt{default_expression}s, the predicate of the nominal subtype of the created object is evaluated, and a check is performed that the predicate is True. Assertions.Assertion_Error is raised if any of these checks fail.@Defn2{Term=[predicate check], Sec=[@key[in out] parameters]}@Defn2{Term=[predicate check], Sec=[@nt{object_declaration}]}@Defn2{Term=[predicate check], Sec=[@nt{allocator}]}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}@Defn2{Term=(Assertion_Error), Sec=(raised by failure of run-time check)}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=<Predicates are not evaluated at the point of the (sub)type declaration.>} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Static_Predicate checks can be removed even in the presence of potentially invalid values, just as constraint checks can be removed.]} @end{ImplNote} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A value @i<satisfies> a predicate if the predicate is True for that value.@PDefn2{Term=[satisfies], Sec=(a subtype predicate)}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0276-1]} @ChgAdded{Version=[3],Text=[If any of the above @LegalityTitle is violated in an instance of a generic unit, Program_Error is raised at the point of the violation.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is the usual way around the contract model; this applies even in instance bodies. Note that errors in instance specifications will be detected at compile-time by the "re-check" of the specification, only errors in the body should raise Program_Error.]} @end{Discussion} @end{Runtime} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[A predicate specification does not cause a subtype to be considered constrained.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[A Static_Predicate, like a constraint, always remains True for all objects of the subtype, except in the case of uninitialized variables and other invalid values. A Dynamic_Predicate, on the other hand, is checked as specified above, but can become False at other times. For example, the predicate of a record subtype is not checked when a subcomponent is modified.]} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0262-1],ARef=[AI05-0276-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Predicate aspects are new in Ada 2012.]} @end{Extend2005} @LabeledClause{Objects and Named Numbers} @begin{Intro} @redundant[Objects are created at run time and contain a value of a given type. @Defn2{Term=[creation], Sec=(of an object)} An object can be created and initialized as part of elaborating a declaration, evaluating an @nt<allocator>, @nt<aggregate>, or @nt<function_call>, or passing a parameter by copy. Prior to reclaiming the storage for an object, it is finalized if necessary (see @RefSecNum(Completion and Finalization)).] @end{Intro} @begin{StaticSem} @Leading@keepnext@Defn{object} All of the following are objects: @ToGlossary{Term=<Object>, Text=<An object is either a constant or a variable. An object contains a value. An object is created by an @nt(object_declaration) or by an @nt(allocator). A formal parameter is (a view of) an object. A subcomponent of an object is an object.>} @begin(itemize) the entity declared by an @nt<object_declaration>; a formal parameter of a subprogram, entry, or generic subprogram; a generic formal object; a loop parameter; a choice parameter of an @nt<exception_handler>; an entry index of an @nt<entry_body>; the result of dereferencing an access-to-object value (see @RefSecNum{Names}); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0015-1]} the @Chg{Version=[2],New=[return object ],Old=[]}@Chg{Version=[3], New=[of a function],Old=[@Chg{Version=[2],New=[created as the ],Old=[]}result of evaluating a @nt<function_call> (or the equivalent operator invocation @em see @RefSecNum{Overloading of Operators})]}; the result of evaluating an @nt<aggregate>; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[a @nt{qualified_expression} whose operand denotes an object;]} a component, slice, or view conversion of another object. @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0054-2]} @Defn{constant} @Defn{variable} @Defn{constant object} @Defn{variable object} @Defn{constant view} @Defn{variable view} An object is either a @i(constant) object or a @i(variable) object.@Chg{Version=[3],New=[],Old=[ The value of a constant object cannot be changed between its initialization and its finalization, whereas the value of a variable object can be changed.]} Similarly, a view of an object is either a @i(constant) or a @i(variable). All views of a constant @Chg{Version=[3],New=[elementary ],Old=[]}object are constant. @Chg{Version=[3],New=[All views of a constant composite object are constant, except for parts that are of controlled or immutably limited types; variable views of those parts and their subcomponents may exist. In this sense, objects of controlled and immutably limited types are @i<inherently mutable>@Defn{inherently mutable object}. ],Old=[]}A constant view of @Chg{Version=[3],New=[an],Old=[a variable]} object cannot be used to modify @Chg{Version=[3],New=[its value],Old=[the value of the variable]}. The terms constant and variable by themselves refer to constant and variable views of objects. @Defn2{Term=[read], Sec=(the value of an object)} The value of an object is @i(read) when the value of any part of the object is evaluated, or when the value of an enclosing object is evaluated. @Defn2{Term=[update], Sec=(the value of an object)} The value of a variable is @i(updated) when an assignment is performed to any part of the variable, or when an assignment is performed to an enclosing object. @begin{Ramification} Reading and updating are intended to include read/write references of any kind, even if they are not associated with the evaluation of a particular construct. Consider, for example, the expression @lquotes@;X.@key[all](F)@rquotes@;, where X is an access-to-array object, and F is a function. The implementation is allowed to first evaluate @lquotes@;X.@key[all]@rquotes@; and then F. Finally, a read is performed to get the value of the F'th component of the array. Note that the array is not necessarily read as part of the evaluation of @lquotes@;X.@key[all]@rquotes@;. This is important, because if F were to free X using Unchecked_Deallocation, we want the execution of the final read to be erroneous. @end{Ramification} @Leading@;Whether a view of an object is constant or variable is determined by the definition of the view. The following (and no others) represent constants: @begin(itemize) an object declared by an @nt<object_declaration> with the reserved word @key(constant); @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[We mean the word @key{constant} as defined by the grammar for @nt{object_declaration}, not some random word @key{constant}. Thus,]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[X : @key{access constant} T;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[is not a constant.]} @end{Honest} a formal parameter or generic formal object of mode @key(in); a discriminant; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[a loop parameter unless specified to be a variable for a generalized loop (see @RefSecNum{Generalized Loop Iteration});]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} a @Chg{Version=[3],New=[],Old=[loop parameter, ]}choice parameter@Chg{Version=[3],New=[],Old=[,]} or entry index; the dereference of an access-to-constant value; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0015-1]} @ChgAdded{Version=[3],Text=[the return object declared by an @nt{extended_return_statement} with the reserved word @key[constant];]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0015-1]} the @Chg{Version=[3],New=[object denoted by],Old=[result of evaluating]} a @nt<function_call> or an @nt<aggregate>; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[the result of evaluating a @nt{qualified_expression};]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0120-1]} @ChgAdded{Version=[3],Text=[within the body of a protected function (or a function declared immediately within a @nt{protected_body}), the current instance of the enclosing protected unit;]} a @nt<selected_component>, @nt<indexed_component>, @nt<slice>, or view conversion of a constant. @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00114-01]} @ChgNote{This is just wrong, even for Ada 95.} @ChgDeleted{Version=[2],Text=[A noninvertible view conversion to a general access type is also defined to be a constant @em see @RefSecNum(Type Conversions).]} @end{Honest} @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn{nominal subtype} At the place where a view of an object is defined, a @i(nominal subtype) is associated with the view. @Defn{actual subtype} @IndexSee{Term=[subtype (of an object)],See=(actual subtype of an object)} The object's @i(actual subtype) (that is, its subtype) can be more restrictive than the nominal subtype of the view; it always is if the nominal subtype is an @i(indefinite subtype). @Defn{indefinite subtype} @Defn{definite subtype} A subtype is an indefinite subtype if it is an unconstrained array subtype, or if it has unknown discriminants or unconstrained discriminants without defaults (see @RefSecNum(Discriminants)); otherwise@Chg{Version=[3],New=[,],Old=[]} the subtype is a @i{definite} subtype @Redundant[(all elementary subtypes are definite subtypes)]. @redundant[A class-wide subtype is defined to have unknown discriminants, and is therefore an indefinite subtype. An indefinite subtype does not by itself provide enough information to create an object; an additional @nt<constraint> or explicit initialization @nt<expression> is necessary (see @RefSecNum(Object Declarations)). A component cannot have an indefinite nominal subtype.] @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[A view of a composite object is @i<known to be constrained> if:@Defn{known to be constrained}@Defn2{Term=[constrained],Sec=[known to be]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[its nominal subtype is constrained, and is not an untagged partial view; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[its nominal subtype is indefinite; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0008-1],ARef=[AI05-0093-1]} @ChgAdded{Version=[3],Text=[its type is immutably limited (see @RefSecNum{Limited Types}); or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[it is part of a stand-alone constant (including a generic formal object of mode @key[in]); or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[it is part of a formal parameter of mode @key[in]; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[it is part of the object denoted by a @nt{function_call} or @nt{aggregate}; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[it is part of a constant return object of an @nt{extended_return_statement}; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0008-1],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Text=[it is a dereference of a pool-specific access type, and there is no ancestor of its type that has a constrained partial view.]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not include dereferences of general access types because they might denote stand-alone aliased unconstrained variables. That's true even for access-to-constant types (the denoted object does not have to be a constant).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[There are other cases that could have been included in this definition (view conversions, the current instance of a type, objects of a formal discriminated private type), but these are not relevant to the places this term is used, so they were not included. If this term is used in additional places, the definition should be checked to see if any of these additional cases are relevant and appropriate wording added if necessary.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0008-1],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[For the purposes of determining within a generic body whether an object is known to be constrained:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[if a subtype is a descendant of an untagged generic formal private or derived type, and the subtype is not an unconstrained array subtype, it is not considered indefinite and is considered to have a constrained partial view;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[if a subtype is a descendant of a formal access type, it is not considered pool-specific.]} @end{Itemize} @Defn{named number} A @i(named number) provides a name for a numeric value known at compile time. It is declared by a @nt<number_declaration>. @end{StaticSem} @begin{Notes} A constant cannot be the target of an assignment operation, nor be passed as an @key(in) @key(out) or @key(out) parameter, between its initialization and finalization, if any. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0054-2]} @ChgAdded{Version=[3],Text=[The value of a constant object cannot be changed after its initialization, except in some cases where the object has a controlled or immutably limited part (see @RefSecNum{Limited Types}, @RefSecNum{Assignment and Finalization}, and @RefSecNum{Data Validity}).]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} The nominal and actual subtypes of an elementary object are always the same. For a discriminated or array object, if the nominal subtype is constrained@Chg{Version=[3],New=[,],Old=[]} then so is the actual subtype. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} There are additional kinds of objects (choice parameters and entry indices of entry bodies). The result of a function and of evaluating an aggregate are considered (constant) objects. This is necessary to explain the action of finalization on such things. Because a @nt<function_call> is also syntactically a @nt<name> (see @RefSecNum(Names)), the result of a @nt{function_call} can be renamed, thereby allowing repeated use of the result without calling the function again. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause and its subclauses]} now @Chg{Version=[3],New=[follows],Old=[follow]} the @Chg{Version=[3],New=[],Old=[clause and ]}subclauses on types and subtypes, to cut down on the number of forward references. The term nominal subtype is new. It is used to distinguish what is known at compile time about an object's constraint, versus what its "true" run-time constraint is. The terms definite and indefinite (which apply to subtypes) are new. They are used to aid in the description of generic formal type matching, and to specify when an explicit initial value is required in an @nt<object_declaration>. We have moved the syntax for @nt<object_declaration> and @nt<number_declaration> down into their respective subclauses, to keep the syntax close to the description of the associated semantics. We talk about variables and constants here, since the discussion is not specific to @nt<object_declaration>s, and it seems better to have the list of the kinds of constants juxtaposed with the kinds of objects. We no longer talk about indirect updating due to parameter passing. Parameter passing is handled in 6.2 and 6.4.1 in a way that there is no need to mention it here in the definition of read and update. Reading and updating now includes the case of evaluating or assigning to an enclosing object. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Clarified that the return object is the object created by a function call.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0015-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added wording to allow return objects to be declared as constants, and corrected the definition of return objects as objects.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1],ARef=[AI05-0041-1],ARef=[AI05-0093-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a definition of @i<known to be constrained>, for use in other rules.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0054-2]} @ChgAdded{Version=[3],Text=[@b<Correction:> We now recognize the fact that not all declared constant objects are immutable; for those that a variable view can be constructed, they can be changed via that view.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0120-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added the current instance of a protected object to the list of constant views; since the list claims to include all possibilities, it had better include that one.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[The result of a @nt{qualified_expression} is defined to be a constant view and is defined to be an object if the operand of the @nt{qualified_expression} is an object. These definitions, combined with some grammar changes, allow @nt{qualified_expression}s to be used in more places. See @RefSecNum{Names} for details.]}@ChgNote{This is defined an extension in @RefSecNum{Names}.} @end{DiffWord2005} @LabeledSubClause{Object Declarations} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @RootDefn{stand-alone object} @Defn{explicit initial value} @Defn{initialization expression} An @nt<object_declaration> declares a @i(stand-alone) object with a given nominal subtype and, optionally, an explicit initial value given by an initialization expression. @Defn{anonymous array type} @Defn{anonymous task type} @Defn{anonymous protected type} For an array, @Chg{Version=[3],New=[access, ],Old=[]}task, or protected object, the @nt<object_declaration> may include the definition of the (anonymous) type of the object. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01],ARef=[AI95-00406-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<object_declaration>,rhs=" @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{subtype_indication} [:= @Syn2{expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};@Chg{Version=[2],New=< | @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{access_definition} [:= @Syn2{expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>} | @Syn2{defining_identifier_list} : [@key{aliased}] [@key{constant}] @Syn2{array_type_definition} [:= @Syn2{expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @Syn2{single_task_declaration} | @Syn2{single_protected_declaration}"} @Syn{lhs=<defining_identifier_list>,rhs=" @Syn2{defining_identifier} {, @Syn2{defining_identifier}}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(object_declaration initialization expression)} For an @nt<object_declaration> with an @nt<expression> following the compound delimiter :=, the type expected for the @nt<expression> is that of the object. @Defn{initialization expression} This @nt<expression> is called the @i(initialization expression). @IndexSee{Term=[constructor],See=[initialization expression]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} An @nt<object_declaration> without the reserved word @key(constant) declares a variable object. If it has a @nt<subtype_indication> or an @nt<array_type_definition> that defines an indefinite subtype, then there shall be an initialization expression.@Chg{Version=[2],New=[],Old=[ An initialization expression shall not be given if the object is of a limited type.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1],ARef=[AI05-0299-1]} An @nt<object_declaration> with the reserved word @key(constant) declares a constant object. @Defn{full constant declaration} If it has an initialization expression, then it is called a @i(full constant declaration). @Defn{deferred constant declaration} Otherwise@Chg{Version=[3],New=[,],Old=[]} it is called a @i(deferred constant declaration). The rules for deferred constant declarations are given in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Deferred Constants). The rules for full constant declarations are given in this subclause. Any declaration that includes a @nt{defining_identifier_list} with more than one @nt{defining_identifier} is equivalent to a series of declarations each containing one @nt{defining_identifier} from the list, with the rest of the text of the declaration copied for each declaration in the series, in the same order as the list. The remainder of this International Standard relies on this equivalence; explanations are given for declarations with a single @nt<defining_identifier>. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} @Defn{nominal subtype} The @nt<subtype_indication>@Chg{Version=[2],New=[, @nt{access_definition},],Old=[]} or full type definition of an @nt<object_declaration> defines the nominal subtype of the object. The @nt<object_declaration> declares an object of the type of the nominal subtype. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The phrase @lquotes@;full type definition@rquotes@; here includes the case of an anonymous array, @Chg{Version=[2],New=[access, ],Old=[]}task, or protected type. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[@Defn{requires late initialization} A component of an object is said to @i{require late initialization} if it has an access discriminant value constrained by a per-object expression, or if it has an initialization expression that includes a name denoting the current instance of the type or denoting an access discriminant.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such components can depend on the values of other components of the object. We want to initialize them as late and as reproducibly as possible.]} @end{Reason} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @Defn2{Term=[constraint], Sec=(of an object)} If a composite object declared by an @nt{object_declaration} has an unconstrained nominal subtype, then if this subtype is indefinite or the object is constant @Chg{Version=[2],New=[], Old=[or aliased (see @RefSecNum(Access Types)) ]}the actual subtype of this object is constrained. The constraint is determined by the bounds or discriminants (if any) of its initial value; @Defn{constrained by its initial value} the object is said to be @i(constrained by its initial value). @Defn2{Term=[actual subtype], Sec=(of an object)} @IndexSee{Term=[subtype (of an object)],See=(actual subtype of an object)} @Chg{Version=[2],New=[], Old=[@Redundant[In the case of an aliased object, this initial value may be either explicit or implicit; in the other cases, an explicit initial value is required.] ]}When not constrained by its initial value, the actual and nominal subtypes of the object are the same. @Defn2{Term=[constrained], Sec=(object)} @Defn2{Term=[unconstrained], Sec=(object)} If its actual subtype is constrained, the object is called a @i(constrained object). @Leading@Defn2{Term=[implicit initial values], Sec=(for a subtype)} For an @nt<object_declaration> without an initialization expression, any initial values for the object or its subcomponents are determined by the @i(implicit initial values) defined for its nominal subtype, as follows: @begin(itemize) The implicit initial value for an access subtype is the null value of the access type. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[The implicit initial value for a scalar subtype that has the Default_Value aspect specified is the value of that aspect converted to the nominal subtype (which might raise Constraint_Error @em see @RefSec{Type Conversions});@PDefn2{Term=[implicit subtype conversion], Sec=(default value of a scalar)}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[This is a @RuntimeTitle rule, so the visibility of the @nt{aspect_specification} is not relevant @em if the full type for a private type has the Default_Value aspect specified, partial views of the type also have this implicit initial value.]} @end{Ramification} The implicit initial (and only) value for each discriminant of a constrained discriminated subtype is defined by the subtype. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0228-1]} For a (definite) composite subtype, the implicit initial value of each component with a @nt<default_expression> is obtained by evaluation of this expression and conversion to the component's nominal subtype (which might raise Constraint_Error@Chg{Version=[3],New=[],Old=[ @em see @RefSec{Type Conversions}]}), unless the component is a discriminant of a constrained subtype (the previous case), or is in an excluded @nt<variant> (see @RefSecNum(Variant Parts and Discrete Choices)). @PDefn2{Term=[implicit subtype conversion],Sec=(component defaults)} For each component that does not have a @nt<default_expression>, @Chg{Version=[3],New=[if the composite subtype has the Default_Component_Value aspect specified, the implicit initial value is the value of that aspect converted to the component's nominal subtype; otherwise, ],Old=[]}any implicit initial values are those determined by the component's nominal subtype. For a protected or task subtype, there is an implicit component (an entry queue) corresponding to each entry, with its implicit initial value being an empty queue. @begin(ImplNote) The implementation may add implicit components for its own use, which might have implicit initial values. For a task subtype, such components might represent the state of the associated thread of control. For a type with dynamic-sized components, such implicit components might be used to hold the offset to some explicit component. @end(ImplNote) @end(itemize) @Leading@PDefn2{Term=[elaboration], Sec=(object_declaration)} The elaboration of an @nt{object_declaration} proceeds in the following sequence of steps: @begin(enumerate) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The @nt{subtype_@!indication},@Chg{Version=[2],New=[ @nt{access_@!definition},],Old=[]} @nt<array_@!type_@!definition>, @nt{single_@!task_@!declaration}, or @nt{single_@!protected_@!declaration} is first elaborated. This creates the nominal subtype (and the anonymous type in the @Chg{Version=[2],New=[last four],Old=[latter three]} cases). If the @nt<object_declaration> includes an initialization expression, the (explicit) initial value is obtained by evaluating the expression and converting it to the nominal subtype (which might raise Constraint_Error @em see @RefSecNum(Type Conversions)). @PDefn2{Term=[implicit subtype conversion],Sec=(initialization expression)} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} The object is created, and, if there is not an initialization expression, @Chg{Version=[2],New=[the object is @i{initialized by default}. @Defn{initialized by default}When an object is initialized by default, ],Old=[]}any per-object @Chg{New=[constraints],Old=[expressions]} (see @RefSecNum(Record Types)) are @Chg{New=[elaborated], Old=[evaluated]} and any implicit initial values for the object or for its subcomponents are obtained as determined by the nominal subtype.@Chg{Version=[2],New=[ @Defn2{Term=[initialization], Sec=(of an object)} @Defn2{Term=[assignment operation], Sec=(during elaboration of an @nt{object_declaration})} Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in @RefSecNum{Assignment Statements} and @RefSecNum{Assignment and Finalization}, Initialize and Adjust procedures can be called. @IndexSee{Term=[constructor],See=[initialization]}],Old=[]} @begin(Discussion) For a per-object constraint that contains some per-object expressions and some non-per-object expressions, the values used for the constraint consist of the values of the non-per-object expressions evaluated at the point of the @nt{type_declaration}, and the values of the per-object expressions evaluated at the point of the creation of the object. The elaboration of per-object constraints was presumably performed as part of the dependent compatibility check in Ada 83. If the object is of a limited type with an access discriminant, the @nt<access_definition> is elaborated at this time (see @RefSecNum(Discriminants)). @end(Discussion) @begin{Reason} The reason we say that evaluating an explicit initialization expression happens before creating the object is that in some cases it is impossible to know the size of the object being created until its initial value is known, as in @lquotes@;X: String := Func_Call(...);@rquotes@;. The implementation can create the object early in the common case where the size can be known early, since this optimization is semantically neutral. @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00373-01]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[initialization], Sec=(of an object)} @Defn2{Term=[assignment operation], Sec=(during elaboration of an @nt{object_declaration})} Any initial values (whether explicit or implicit) are assigned to the object or to the corresponding subcomponents. As described in @RefSecNum{Assignment Statements} and @RefSecNum{Assignment and Finalization}, Initialize and Adjust procedures can be called. @IndexSee{Term=[constructor],See=[initialization]}]} @begin(Ramification) Since the initial values have already been converted to the appropriate nominal subtype, the only Constraint_Errors that might occur as part of these assignments are for values outside their base range that are used to initialize unconstrained numeric subcomponents. See @RefSecNum{Scalar Types}. @end(Ramification) @end(enumerate) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Just to get conditional Leading here.} For the third step above, @Chg{Version=[2],New=[],Old=[the object creation and any elaborations and ]}evaluations @Chg{Version=[2],New=[and assignments ],Old=[]}are performed in an arbitrary order@Chg{Version=[2],New=[ subject to the following restrictions:],Old=[, except that if the @nt<default_expression> for a discriminant is evaluated to obtain its initial value, then this evaluation is performed before that of the @nt<default_expression> for any component that depends on the discriminant, and also before that of any @nt<default_expression> that includes the name of the discriminant. The evaluations of the third step and the assignments of the fourth step are performed in an arbitrary order, except that each evaluation is performed before the resulting value is assigned.]}@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Assignment to any part of the object is preceded by the evaluation of the value that is to be assigned.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Duh. But we ought to say it. Note that, like any rule in the International Standard, it doesn't prevent an @lquotes@;as-if@rquotes optimization; as long as the semantics as observed from the program are correct, the compiler can generate any code it wants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The evaluation of a @nt{default_expression} that includes the name of a discriminant is preceded by the assignment to that discriminant.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Duh again. But we have to say this, too. It's odd that Ada 95 only required the default expressions to be evaluated before the discriminant is used; it says nothing about discriminant values that come from @nt{subtype_indication}s.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The evaluation of the @nt{default_expression} for any component that depends on a discriminant is preceded by the assignment to that discriminant.]} @begin{Reason} @Leading@keepnext@;For example: @begin{Example} @key[type] R(D : Integer := F) @key[is] @key[record] S : String(1..D) := (@key[others] => G); @key[end] @key[record]; X : R; @end{Example} For the elaboration of the declaration of X, it is important that F be evaluated before the aggregate. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00373-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[The assignments to any components, including implicit components, not requiring late initialization @Chg{Version=[3],New=[],Old=[must ]}precede the initial value evaluations for any components requiring late initialization; if two components both require late initialization, then assignments to parts of the component occurring earlier in the order of the component declarations @Chg{Version=[3],New=[],Old=[must ]}precede the initial value evaluations of the component occurring later.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Components that require late initialization can refer to the entire object during their initialization. We want them to be initialized as late as possible to reduce the chance that their initialization depends on uninitialized components. For instance:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} T (D : Natural) @key{is} @key{limited record} C1 : T1 (T'Access); C2 : Natural := F (D); C3 : String (1 .. D) := (others => ' '); @key{end record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Component C1 requires late initialization. The initialization could depend on the values of any component of T, including D, C2, or C3. Therefore, we want to it to be initialized last. Note that C2 and C3 do not require late initialization; they only have to be initialized after D.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is possible for there to be more than one component that requires late initialization. In this case, the language can't prevent problems, because all of the components can't be the last one initialized. In this case, we specify the order of initialization for components requiring late initialization; by doing so, programmers can arrange their code to avoid accessing uninitialized components, and such arrangements are portable. Note that if the program accesses an uninitialized component, @RefSecNum{Data Validity} defines the execution to be erroneous.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0228-1]} @Redundant[There is no implicit initial value defined for a scalar subtype@Chg{Version=[3],New=[ unless the Default_Value aspect has been specified for the type],Old=[]}.] @PDefn{uninitialized variables} In the absence of an explicit initialization@Chg{Version=[3],New=[ or the specification of the Default_Value aspect],Old=[]}, a newly created scalar object might have a value that does not belong to its subtype (see @RefSecNum{Data Validity} and @RefSecNum{Pragma Normalize_Scalars}). @begin{Honest} It could even be represented by a bit pattern that doesn't actually represent any value of the type at all, such as an invalid internal code for an enumeration type, or a NaN for a floating point type. It is a generally a bounded error to reference scalar objects with such @lquotes@;invalid representations@rquotes@;, as explained in @RefSec{Data Validity}. @end{Honest} @begin{Ramification} There is no requirement that two objects of the same scalar subtype have the same implicit initial @lquotes@;value@rquotes@; (or representation). It might even be the case that two elaborations of the same @nt{object_declaration} produce two different initial values. However, any particular uninitialized object is default-initialized to a single value (or invalid representation). Thus, multiple reads of such an uninitialized object will produce the same value each time (if the implementation chooses not to detect the error). @end{Ramification} @end{RunTime} @begin{Notes} Implicit initial values are not defined for an indefinite subtype, because if an object's nominal subtype is indefinite, an explicit initial value is required. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1],ARef=[AI05-0255-1]} @Defn{stand-alone constant} @Defn{stand-alone variable} As indicated above, a stand-alone object is an object declared by an @nt<object_declaration>. Similar definitions apply to @lquotes@;stand-alone constant@rquotes@; and @lquotes@;stand-alone variable.@rquotes@; A subcomponent of an object is not a stand-alone object, nor is an object that is created by an @nt<allocator>. An object declared by a @nt<loop_parameter_specification>, @Chg{Version=[3],New=[@nt{iterator_specification}, ],Old=[]}@nt<parameter_specification>, @nt<entry_index_specification>, @nt<choice_parameter_specification>, @Chg{Version=[3],New=[@nt{extended_return_statement}, ],Old=[]}or a @nt{formal_object_declaration} @Chg{Version=[3],New=[of mode @key[in out] ],Old=[]}is not @Chg{Version=[3],New=[considered],Old=[called]} a stand-alone object. The type of a stand-alone object cannot be abstract (see @RefSecNum{Abstract Types and Subprograms}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a multiple object declaration:) @begin(Example) --@RI[ the multiple object declaration ] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} John, Paul : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); --@RI[ see @RefSecNum(Incomplete Type Declarations)] --@RI[ is equivalent to the two single object declarations in the order given] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} John : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); Paul : @Chg{Version=[2],New=[@key{not null} ],Old=[]}Person_Name := @key(new) Person(Sex => M); @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of variable declarations:) @end{WideAbove} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Count, Sum : Integer; Size : Integer @key(range) 0 .. 10_000 := 0; Sorted : Boolean := False; Color_Table : @key(array)(1 .. Max) @key(of) Color; Option : Bit_Vector(1 .. 10) := (@key(others) => True); Hello : @Chg{Version=[2],New=[@key(aliased)],Old=[@key(constant)]} String := "Hi, world.";@Chg{Version=[2],New=[ @unicode(952), @unicode(966) : Float @b<range> -@pi .. +@pi;],Old=[]} @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of constant declarations:) @end{WideAbove} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Limit : @key(constant) Integer := 10_000; Low_Limit : @key(constant) Integer := Limit/10; Tolerance : @key(constant) Real := Dispersion(1.15);@Chg{Version=[2],New=[ Hello_Msg : @key(constant access) String := Hello'Access; --@RI[ see @RefSecNum{Operations of Access Types}]],Old=[]} @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{object_declaration} is modified to allow the @key{aliased} reserved word. A variable declared by an @nt<object_declaration> can be constrained by its initial value; that is, a variable of a nominally unconstrained array subtype, or discriminated type without defaults, can be declared so long as it has an explicit initial value. In Ada 83, this was permitted for constants, and for variables created by allocators, but not for variables declared by @nt<object_declaration>s. This is particularly important for tagged class-wide types, since there is no way to constrain them explicitly, and so an initial value is the only way to provide a constraint. It is also important for generic formal private types with unknown discriminants. We now allow an @nt{unconstrained_array_definition} in an @nt{object_declaration}. This allows an object of an anonymous array type to have its bounds determined by its initial value. This is for uniformity: If one can write @lquotes@;X: @key[constant] @key[array](Integer @key[range] 1..10) @key[of] Integer := ...;@rquotes@; then it makes sense to also allow @lquotes@;X: @key[constant] @key[array](Integer @key[range] <>) @key[of] Integer := ...;@rquotes@;. (Note that if anonymous array types are ever sensible, a common situation is for a table implemented as an array. Tables are often constant, and for constants, there's usually no point in forcing the user to count the number of elements in the value.) @end{Extend83} @begin{DiffWord83} We have moved the syntax for @nt{object_declaration}s into this subclause. Deferred constants no longer have a separate syntax rule, but rather are incorporated in @nt<object_declaration> as constants declared without an initialization expression. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Unconstrained aliased objects of types with discriminants with defaults are no longer constrained by their initial values. This means that a program that raised Constraint_Error from an attempt to change the discriminants will no longer do so. The change only affects programs that depended on the raising of Constraint_Error in this case, so the inconsistency is unlikely to occur outside of the ACATS. This change may however cause compilers to implement these objects differently, possibly taking additional memory or time. This is unlikely to be worse than the differences caused by any major compiler upgrade.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A constant may have a limited type; the initialization @nt{expression} has to be built-in-place (see @RefSecNum{Limited Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01],ARef=[AI95-00406-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A stand-alone object may have an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected wording to say that per-object constraints are elaborated (not evaluated).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[The rules for evaluating default initialization have been tightened. In particular, components whose default initialization can refer to the rest of the object are required to be initialized last.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[Added examples of various new constructs.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in an @nt{object_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[Implicit initial values can now be given for scalar types and for scalar array components, using the Default_Value (see @RefSecNum{Scalar Types}) and Default_Component_Value (see @RefSecNum{Array Types}) aspects; the extension is documented there.]} @end{DiffWord2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledSubClause{Number Declarations} @begin{Intro} A @nt<number_declaration> declares a named number. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{static} If a value or other property of a construct is required to be @i(static) that means it is required to be determined prior to execution. A @i(static) expression is an expression whose value is computed at compile time and is usable in contexts where the actual value might affect the legality of the construct. This is fully defined in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Static Expressions and Static Subtypes). @end{Discussion} @end{Intro} @begin{Syntax} @Syn{lhs=<number_declaration>,rhs=" @Syn2{defining_identifier_list} : @key{constant} := @SynI{static_}@Syn2{expression};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(number_declaration expression)} The @SynI(static_)@nt{expression} given for a @nt{number_declaration} is expected to be of any numeric type. @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The @i(static_)@nt{expression} given for a number declaration shall be a static expression, as defined by @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Static Expressions and Static Subtypes). @end{Legality} @begin{StaticSem} The named number denotes a value of type @i(universal_integer) if the type of the @i(static_)@!@nt{expression} is an integer type. The named number denotes a value of type @i(universal_real) if the type of the @i(static_)@!@nt{expression} is a real type. The value denoted by the named number is the value of the @i(static_)@nt{expression}, converted to the corresponding universal type. @PDefn2{Term=[implicit subtype conversion],Sec=(named number value)} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(number_declaration)} The elaboration of a @nt<number_declaration> has no effect. @begin(TheProof) Since the @i(static_)@nt<expression> was evaluated at compile time. @end(TheProof) @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of number declarations:) @begin(Example) Two_Pi : @key(constant) := 2.0*Ada.Numerics.Pi; --@RI[ a real number (see @RefSecNum{The Numerics Packages})] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Max : @key(constant) := 500; --@RI[ an integer number] Max_Line_Size : @key(constant) := Max/6@Chg{Version=[2],New=[;],Old=[ ]} --@RI[ the integer 83] Power_16 : @key(constant) := 2**16; --@RI[ the integer 65_536] One, Un, Eins : @key(constant) := 1; --@RI[ three different names for 1] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now allow a static expression of any numeric type to initialize a named number. For integer types, it was possible in Ada 83 to use 'Pos to define a named number, but there was no way to use a static expression of some nonuniversal real type to define a named number. This change is upward compatible because of the preference rule for the operators of the root numeric types. @end{Extend83} @begin{DiffWord83} We have moved the syntax rule into this subclause. AI83-00263 describes the elaboration of a number declaration in words similar to that of an @nt{object_declaration}. However, since there is no expression to be evaluated and no object to be created, it seems simpler to say that the elaboration has no effect. @end{DiffWord83} @LabeledClause{Derived Types and Classes} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @Defn{derived type} A @nt<derived_type_definition> defines a @Chg{Version=[2], New=[@i{derived type}],Old=[new type]} (and its first subtype) whose characteristics are @i(derived) from those of a @Chg{Version=[2],New=[parent type, and possibly from progenitor types], Old=[@i(parent type)]}. @IndexSee{Term=[inheritance],See=[derived types and classes]} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Derived type>, Text=<A derived type is a type defined in terms of @Chg{Version=[2], New=[one or more other types given in a derived type definition. The first of those types],Old=[another type, which]} is the parent type of the derived type@Chg{Version=[2],New=[ and any others are progenitor types],Old=[]}. Each class containing the parent type @Chg{Version=[2],New=[or a progenitor type ],Old=[]}also contains the derived type. The derived type inherits properties such as components and primitive operations from the parent@Chg{Version=[2],New=[ and progenitors],Old=[]}. A type together with the types derived from it (directly or indirectly) form a derivation class.>} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[class],Sec=[of types]} @Defn2{Term=[category],Sec=[of types]} A @i<class of types> is a set of types that is closed under derivation; that is, if the parent or a progenitor type of a derived type belongs to a class, then so does the derived type. By saying that a particular group of types forms a class, we are saying that all derivatives of a type in the set inherit the characteristics that define that set. The more general term @i<category of types> is used for a set of types whose defining characteristics are not necessarily inherited by derivatives; for example, limited, abstract, and interface are all categories of types, but not classes of types.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A class of types is also a category of types.]} @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01]} @Syn{lhs=<derived_type_definition>,rhs="@Chg{Version=[2],New=< >,Old=<>}[@key{abstract}] @Chg{Version=[2],New=<[@key{limited}] >,Old=<>}@key{new} @SynI{parent_}@Syn2{subtype_indication} [@Chg{Version=[2],New=<[@key{and} @Syn2{interface_list}] >,Old=<>}@Syn2{record_extension_part}]"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @Defn{parent subtype} @Defn{parent type} The @Syni(parent_)@nt<subtype_indication> defines the @i(parent subtype); its type is the @Chg{Version=[2],New=[@i(parent type)],Old=[parent type]}. @Chg{Version=[2],New=[The @nt{interface_list} defines the progenitor types (see @RefSecNum{Interface Types}). A derived type has one parent type and zero or more progenitor types.],Old=[]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Parent>, Text=<@ChgAdded{Version=[2],Text=[The parent of a derived type is the first type given in the definition of the derived type. The parent can be almost any kind of type, including an interface type.]}>} A type shall be completely defined (see @RefSecNum(Completions of Declarations)) prior to being specified as the parent type in a @nt<derived_type_definition> @em @Redundant[the @nt<full_type_declaration>s for the parent type and any of its subcomponents have to precede the @nt<derived_type_definition>.] @begin{Discussion} This restriction does not apply to the ancestor type of a private extension @em see @RefSecNum(Private Types and Private Extensions); such a type need not be completely defined prior to the @nt<private_extension_declaration>. However, the restriction does apply to record extensions, so the ancestor type will have to be completely defined prior to the @nt<full_type_declaration> corresponding to the @nt<private_extension_declaration>. @end{Discussion} @begin{Reason} We originally hoped we could relax this restriction. However, we found it too complex to specify the rules for a type derived from an incompletely defined limited type that subsequently became nonlimited. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @Defn{record extension} If there is a @nt<record_extension_part>, the derived type is called a @i(record extension) of the parent type. A @nt<record_extension_part> shall be provided if and only if the parent type is a tagged type.@Chg{Version=[2],New=[ @Redundant[An @nt{interface_list} shall be provided only if the parent type is a tagged type.]],Old=[]} @begin(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[The syntax only allows an @nt{interface_list} to appear with a @nt{record_extension_part}, and a @nt{record_extension_part} can only be provided if the parent type is a tagged type. We give the last sentence anyway for completeness.]} @end(TheProof) @begin(ImplNote) We allow a record extension to inherit discriminants; an early version of Ada 9X did not. If the parent subtype is unconstrained, it can be implemented as though its discriminants were repeated in a new @nt{known_discriminant_part} and then used to constrain the old ones one-for-one. However, in an extension aggregate, the discriminants in this case do not appear in the component association list. @end(ImplNote) @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Conditional leading} This rule needs to be rechecked in the visible part of an instance of a generic unit@Chg{Version=[2],New=[ because of the @lquotes@;only if@rquotes@; part of the rule. For example:],Old=[]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T @key{is private}; @key{package} P @key{is} @key{type} Der @key{is new} T; @key{end} P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} I @key{is new} P (Some_Tagged_Type); -- @RI[illegal]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[The instantiation is illegal because a tagged type is being extended in the visible part without a @nt{record_extension_part}. Note that this is legal in the private part or body of an instance, both to avoid a contract model violation, and because no code that can see that the type is actually tagged can also see the derived type declaration.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[No recheck is needed for derived types with a @nt{record_extension_part}, as that has to be derived from something that is known to be tagged (otherwise the template is illegal).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0096-1]} @ChgAdded{Version=[2],Text=[If the reserved word @key{limited} appears in a @nt{derived_type_definition}, the parent type shall be a limited type.@Chg{Version=[3],New=[ If the parent type is a tagged formal type, then in addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.@PDefn{generic contract issue}],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow @key{limited} because we don't inherit limitedness from interfaces, so we must have a way to derive a limited type from interfaces. The word @key{limited} has to be legal when the parent @i{could be} an interface, and that includes generic formal abstract types. Since we have to allow it in this case, we might as well allow it everywhere as documentation, to make it explicit that the type is limited.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[However, we do not want to allow @key{limited} when the parent is nonlimited: limitedness cannot change in a derivation tree.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the parent type is an untagged limited formal type with an actual type that is nonlimited, we allow derivation as a limited type in the private part or body as no place could have visibility on the resulting type where it was known to be nonlimited (outside of the instance). (See the previous paragraph's annotations for an explanation of this.) However, if the parent type is a tagged limited formal type with an actual type that is nonlimited, it would be possible to pass a value of the limited type extension to a class-wide type of the parent, which would be nonlimited. That's too weird to allow (even though all of the extension components would have to be nonlimited because the rules of @RefSecNum{Type Extensions} are rechecked), so we have a special rule to prevent that in the private part (type extension from a formal type is illegal in a generic package body).]} @end{Reason} @end{Legality} @begin{StaticSem} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} The first subtype of the derived type is unconstrained if a @nt{known_discriminant_part} is provided in the declaration of the derived type, or if the parent subtype is unconstrained. @Defn{corresponding constraint} Otherwise, the constraint of the first subtype @i(corresponds) to that of the parent subtype in the following sense: it is the same as that of the parent subtype except that for a range constraint (implicit or explicit), the value of each bound of its range is replaced by the corresponding value of the derived type. @begin(Discussion) A @nt<digits_constraint> in a @nt<subtype_indication> for a decimal fixed point subtype always imposes a range constraint, implicitly if there is no explicit one given. See @RefSec(Fixed Point Types). @end(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[The first subtype of the derived type excludes null (see @RefSecNum{Access Types}) if and only if the parent subtype excludes null.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0110-1]} @Leading@keepnext@;The @Chg{Version=[3],New=[@i{characteristics}@PDefn{characteristics} and implicitly declared primitive subprograms],Old=[characteristics]} of the derived type are defined as follows: @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0110-1]} @ChgAdded{Version=[3],Text=[The characteristics of a type do not include its primitive subprograms (primitive subprograms include predefined operators). The rules governing availability/visibility and inheritance of characteristics are separate from those for primitive subprograms.]} @end{Ramification} @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00442-01]} @Chg{Version=[2],New=[@Redundant[If the parent type or a progenitor type belongs to a class of types, then the derived type also belongs to that class.] The following sets of types, as well as any higher-level sets composed from them, are classes in this sense@Redundant[, and hence the characteristics defining these classes are inherited by derived types from their parent or progenitor types]: signed integer, modular integer, ordinary fixed, decimal fixed, floating point, enumeration, boolean, character, access-to-constant, general access-to-variable, pool-specific access-to-variable, access-to-subprogram, array, string, non-array composite, nonlimited, untagged record, tagged, task, protected, and synchronized tagged], Old=[Each class of types that includes the parent type also includes the derived type]}. @begin{Discussion} This is inherent in our notion of a @lquotes@;class@rquotes@; of types. It is not mentioned in the initial definition of @lquotes@;class@rquotes@; since at that point type derivation has not been defined. In any case, this rule ensures that every class of types is closed under derivation. @end{Discussion} If the parent type is an elementary type or an array type, then the set of possible values of the derived type is a copy of the set of possible values of the parent type. For a scalar type, the base range of the derived type is the same as that of the parent type. @begin{Discussion} The base range of a type defined by an @nt<integer_type_definition> or a @nt<real_type_definition> is determined by the @ntf<_definition>, and is not necessarily the same as that of the corresponding root numeric type from which the newly defined type is implicitly derived. Treating numerics types as implicitly derived from one of the two root numeric types is simply to link them into a type hierarchy; such an implicit derivation does not follow all the rules given here for an explicit @nt<derived_type_definition>. @end{Discussion} If the parent type is a composite type other than an array type, then the components, protected subprograms, and entries that are declared for the derived type are as follows: @begin(inneritemize) The discriminants specified by a new @nt{known_discriminant_part}, if there is one; otherwise, each discriminant of the parent type (implicitly declared in the same order with the same specifications) @em @Defn{inherited discriminant} @Defn{inherited component} in the latter case, the discriminants are said to be @i(inherited), or if unknown in the parent, are also unknown in the derived type; Each nondiscriminant component, entry, and protected subprogram of the parent type, implicitly declared in the same order with the same declarations; @Defn{inherited component} @Defn{inherited protected subprogram} @Defn{inherited entry} these components, entries, and protected subprograms are said to be @i(inherited); @begin{Ramification} The profiles of entries and protected subprograms do not change upon type derivation, although the type of the @lquotes@;implicit@rquotes@; parameter identified by the @nt<prefix> of the @nt<name> in a call does.@end{ramification} @begin{Honest} Any name in the parent @nt{type_declaration} that denotes the current instance of the type is replaced with a name denoting the current instance of the derived type, converted to the parent type. @end{Honest} Each component declared in a @nt<record_extension_part>, if any. @end(inneritemize) @noprefix@;Declarations of components, protected subprograms, and entries, whether implicit or explicit, occur immediately within the declarative region of the type, in the order indicated above, following the parent @nt<subtype_indication>. @begin(Discussion) The order of declarations within the region matters for @nt{record_aggregate}s and @nt<extension_aggregate>s. @end(Discussion) @begin{Ramification} In most cases, these things are implicitly declared @i{immediately} following the parent @nt<subtype_indication>. However, @RefSec{Private Operations} defines some cases in which they are implicitly declared later, and some cases in which the are not declared at all. @end{Ramification} @begin{Discussion} The place of the implicit declarations of inherited components matters for visibility @em they are not visible in the @nt<known_discriminant_part> nor in the parent @nt<subtype_indication>, but are usually visible within the @nt<record_extension_part>, if any (although there are restrictions on their use). Note that a discriminant specified in a new @nt<known_discriminant_part> is not considered @lquotes@;inherited@rquotes@; even if it has the same name and subtype as a discriminant of the parent type. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00419-01]} @ChgDeleted{Version=[2],Text=[The derived type is limited if and only if the parent type is limited.]} @ChgNote{This rule is normatively in @RefSecNum{Limited Types}, and we don't want it scattered everywhere.} @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00419-01]} @ChgDeleted{Version=[2],Text=[The derived type can become nonlimited if the derivation takes place in the visible part of a child package, and the parent type is nonlimited as viewed from the private part of the child package @em see @RefSecNum(Limited Types).]} @end{Honest} @Redundant[For each predefined operator of the parent type, there is a corresponding predefined operator of the derived type.] @begin(TheProof) This is a ramification of the fact that each class that includes the parent type also includes the derived type, and the fact that the set of predefined operators that is defined for a type, as described in @RefSecNum(Operators and Expression Evaluation), is determined by the classes to which it belongs. @end(TheProof) @begin(Reason) Predefined operators are handled separately because they follow a slightly different rule than user-defined primitive subprograms. In particular the systematic replacement described below does not apply fully to the relational operators for Boolean and the exponentiation operator for Integer. The relational operators for a type derived from Boolean still return Standard.Boolean. The exponentiation operator for a type derived from Integer still expects Standard.Integer for the right operand. In addition, predefined operators "reemerge" when a type is the actual type corresponding to a generic formal type, so they need to be well defined even if hidden by user-defined primitive subprograms. @end(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @Defn{inherited subprogram} For each user-defined primitive subprogram (other than a user-defined equality operator @em see below) of the parent type@Chg{Version=[2],New=[ or of a progenitor type],Old=[]} that already exists at the place of the @nt{derived_type_definition}, there exists a corresponding @i(inherited) primitive subprogram of the derived type with the same defining name. @Defn2{Term=[equality operator],Sec=(special inheritance rule for tagged types)} Primitive user-defined equality operators of the parent type@Chg{Version=[2],New=[ and any progenitor types],Old=[]} are also inherited by the derived type, except when the derived type is a nonlimited record extension, and the inherited operator would have a profile that is type conformant with the profile of the corresponding predefined equality operator; in this case, the user-defined equality operator is not inherited, but is rather incorporated into the implementation of the predefined equality operator of the record extension (see @RefSecNum(Relational Operators and Membership Tests)). @PDefn{type conformance} @begin{Ramification} We say @lquotes@;...already exists...@rquotes@; rather than @lquotes@;is visible@rquotes@; or @lquotes@;has been declared@rquotes@; because there are certain operations that are declared later, but still exist at the place of the @nt{derived_type_definition}, and there are operations that are never declared, but still exist. These cases are explained in @RefSecNum{Private Operations}. Note that nonprivate extensions can appear only after the last primitive subprogram of the parent @em the freezing rules ensure this. @end{Ramification} @begin{Reason} A special case is made for the equality operators on nonlimited record extensions because their predefined equality operators are already defined in terms of the primitive equality operator of their parent type (and of the tagged components of the extension part). Inheriting the parent's equality operator as is would be undesirable, because it would ignore any components of the extension part. On the other hand, if the parent type is limited, then any user-defined equality operator is inherited as is, since there is no predefined equality operator to take its place. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Because user-defined equality operators are not inherited by @Chg{Version=[2],New=[nonlimited ],Old=[]}record extensions, the formal parameter names of = and /= revert to Left and Right, even if different formal parameter names were used in the user-defined equality operators of the parent type. @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[This rule only describes what operations are inherited; the rules that describe what happens when there are conflicting inherited subprograms are found in @RefSecNum{Visibility}.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0164-1],ARef=[AI05-0240-1]} @noprefix@;The profile of an inherited subprogram (including an inherited enumeration literal) is obtained from the profile of the corresponding (user-defined) primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type, after systematic replacement of each subtype of its profile (see @RefSecNum{Subprogram Declarations}) that is of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type@Chg{Version=[3],New=[, other than those subtypes found in the designated profile of an @nt{access_definition},],Old=[]} with a @i(corresponding subtype) of the derived type. @Defn{corresponding subtype} For a given subtype of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type, the corresponding subtype of the derived type is defined as follows: @begin(inneritemize) If the declaration of the derived type has neither a @nt<known_discriminant_part> nor a @nt<record_extension_part>, then the corresponding subtype has a constraint that corresponds (as defined above for the first subtype of the derived type) to that of the given subtype. If the derived type is a record extension, then the corresponding subtype is the first subtype of the derived type. If the derived type has a new @nt<known_discriminant_part> but is not a record extension, then the corresponding subtype is constrained to those values that when converted to the parent type belong to the given subtype (see @RefSecNum(Type Conversions)). @PDefn2{Term=[implicit subtype conversion],Sec=(derived type discriminants)} @begin{Reason} An inherited subprogram of an untagged type has an Intrinsic calling convention, which precludes the use of the Access attribute. We preclude 'Access because correctly performing all required constraint checks on an indirect call to such an inherited subprogram was felt to impose an undesirable implementation burden. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0164-1]} @ChgAdded{Version=[3],Text=[Note that the exception to substitution of the parent or progenitor type applies only in the profiles of anonymous access-to-subprogram types. The exception is necessary to avoid calling an access-to-subprogram with types and/or constraints different than expected by the actual routine.]} @end{Reason} @end(inneritemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @noprefix@;The same formal parameters have @nt<default_expression>s in the profile of the inherited subprogram. @Redundant[Any type mismatch due to the systematic replacement of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type by the derived type is handled as part of the normal type conversion associated with parameter passing @em see @RefSecNum(Parameter Associations).] @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} We don't introduce the type conversion explicitly here since conversions to record extensions or on access parameters are not generally legal. Furthermore, any type conversion would just be "undone" since the @Chg{Version=[2],New=[],Old=[parent's ]}subprogram @Chg{Version=[2],New=[of the parent or progenitor ],Old=[]}is ultimately being called anyway.@Chg{Version=[2],New=[ (Null procedures can be inherited from a progenitor without being overridden, so it is possible to call subprograms of an interface.)],Old=[]} @end(Reason) @end(itemize) @Comment{end of characteristics of derived type} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} If a primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor], Old=[]} type is visible at the place of the @nt{derived_type_definition}, then the corresponding inherited subprogram is implicitly declared immediately after the @nt{derived_type_definition}. Otherwise, the inherited subprogram is implicitly declared later or not at all, as explained in @RefSecNum{Private Operations}. @PDefn{derived type} A derived type can also be defined by a @nt<private_@!extension_@!declaration> (see @RefSecNum(Private Types and Private Extensions)) or a @nt<formal_@!derived_@!type_@!definition> (see @RefSecNum(Formal Private and Derived Types)). Such a derived type is a partial view of the corresponding full or actual type. All numeric types are derived types, in that they are implicitly derived from a corresponding root numeric type (see @RefSecNum(Integer Types) and @RefSecNum(Real Types)). @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(derived_type_definition)} The elaboration of a @nt<derived_type_definition> creates the derived type and its first subtype, and consists of the elaboration of the @nt<subtype_@!indication> and the @nt<record_@!extension_@!part>, if any. If the @nt{subtype_@!indication} depends on a discriminant, then only those expressions that do not depend on a discriminant are evaluated. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[We don't mention the @nt{interface_list}, because it does not need elaboration (see @RefSecNum{Interface Types}). This is consistent with the handling of @nt{discriminant_part}s, which aren't elaborated either.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01],ARef=[AI95-00401-01]} @PDefn2{Term=[execution], Sec=(call on an inherited subprogram)} For the execution of a call on an inherited subprogram, a call on the corresponding primitive subprogram of the parent@Chg{Version=[2],New=[ or progenitor],Old=[]} type is performed; the normal conversion of each actual parameter to the subtype of the corresponding formal parameter (see @RefSecNum(Parameter Associations)) performs any necessary type conversion as well. If the result type of the inherited subprogram is the derived type, the result of calling the @Chg{Version=[2],New=[],Old=[parent's ]}subprogram@Chg{Version=[2], New=[ of the parent or progenitor],Old=[]} is converted to the derived type@Chg{Version=[2],New=[, or in the case of a null extension, extended to the derived type using the equivalent of an @nt{extension_aggregate} with the original result as the @nt{ancestor_part} and @key{null record} as the @nt{record_component_association_list}],Old=[]}. @PDefn2{Term=[implicit subtype conversion],Sec=(result of inherited function)} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01]} If an inherited function returns the derived type, and the type is a @Chg{Version=[2],New=[nonnull ],Old=[]}record extension, then the inherited function @Chg{Version=[2],New=[shall be overridden, unless the type is abstract (in which case the function ],Old=[]}is abstract, and (unless overridden) cannot be called except via a dispatching call@Chg{Version=[2],New=[)],Old=[]}. See @RefSecNum(Abstract Types and Subprograms). @end(Discussion) @end{RunTime} @begin{Notes} @Defn{closed under derivation} Classes are closed under derivation @em any class that contains a type also contains its derivatives. Operations available for a given class of types are available for the derived types in that class. Evaluating an inherited enumeration literal is equivalent to evaluating the corresponding enumeration literal of the parent type, and then converting the result to the derived type. This follows from their equivalence to parameterless functions. @PDefn2{Term=[implicit subtype conversion],Sec=(inherited enumeration literal)} A generic subprogram is not a subprogram, and hence cannot be a primitive subprogram and cannot be inherited by a derived type. On the other hand, an instance of a generic subprogram can be a primitive subprogram, and hence can be inherited. If the parent type is an access type, then the parent and the derived type share the same storage pool; there is a @key{null} access value for the derived type and it is the implicit initial value for the type. See @RefSecNum(Access Types). If the parent type is a boolean type, the predefined relational operators of the derived type deliver a result of the predefined type Boolean (see @RefSecNum(Relational Operators and Membership Tests)). If the parent type is an integer type, the right operand of the predefined exponentiation operator is of the predefined type Integer (see @RefSecNum(Highest Precedence Operators)). Any discriminants of the parent type are either all inherited, or completely replaced with a new set of discriminants. For an inherited subprogram, the subtype of a formal parameter of the derived type need not have any value in common with the first subtype of the derived type. @begin(TheProof) @Leading@;This happens when the parent subtype is constrained to a range that does not overlap with the range of a subtype of the parent type that appears in the profile of some primitive subprogram of the parent type. For example: @begin(example) @key(type) T1 @key(is range) 1..100; @key(subtype) S1 @key(is) T1 @key(range) 1..10; @key(procedure) P(X : @key[in] S1); @RI{-- P is a primitive subprogram} @key(type) T2 @key(is new) T1 @key(range) 11..20; @RI(-- implicitly declared:) @RI{-- @key(procedure) P(X : @key[in] T2'Base @key(range) 1..10);} @RI{-- X cannot be in T2'First .. T2'Last} @end(example) @end(TheProof) If the reserved word @key{abstract} is given in the declaration of a type, the type is abstract (see @RefSecNum{Abstract Types and Subprograms}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[An interface type that has a progenitor type @lquotes@;is derived from@rquotes@; that type. A @nt{derived_type_definition}, however, never defines an interface type.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[It is illegal for the parent type of a @nt{derived_type_definition} to be a synchronized tagged type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@RefSecNum{Type extensions} prohibits record extensions whose parent type is a synchronized tagged type, and this @Chg{Version=[3],New=[subclause],Old=[clause]} requires tagged types to have a record extension. Thus there are no legal derivations. Note that a synchronized interface can be used as a progenitor in an @nt{interface_type_definition} as well as in task and protected types, but we do not allow concrete extensions of any synchronized tagged type.]} @end{TheProof} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of derived type declarations:) @begin(Example) @key(type) Local_Coordinate @key(is) @key(new) Coordinate; --@RI[ two different types] @key(type) Midweek @key(is) @key(new) Day @key(range) Tue .. Thu; --@RI[ see @RefSecNum(Enumeration Types)] @key(type) Counter @key(is) @key(new) Positive; --@RI[ same range as Positive ] @key(type) Special_Key @key(is) @key(new) Key_Manager.Key; --@RI[ see @RefSecNum(Private Operations)] --@RI[ the inherited subprograms have the following specifications: ] --@RI[ procedure Get_Key(K : out Special_Key);] --@RI[ function "<"(X,Y : Special_Key) return Boolean;] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, if a predefined operator had been overridden prior to the derivation, the derived type will inherit the user-defined operator rather than the predefined operator. The work-around (if the new behavior is not the desired behavior) is to move the definition of the derived type prior to the overriding of any predefined operators. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} @Leading@;When deriving from a (nonprivate, nonderived) type in the same visible part in which it is defined, a primitive subprogram of the parent type declared before the derived type will be inherited by the derived type. This can cause upward incompatibilities in cases like this: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] (A, B, C, D); @key[function] F( X : T := A ) @key[return] Integer; @key[type] NT @key[is] @key[new] T; --@RI{ inherits F as} --@RI{ function F( X : NT := A ) return Integer;} --@RI{ in Ada 95 only} ... @key[end] P; ... @key[use] P; --@RI{ Only one declaration of F from P is use-visible in} --@RI{ Ada 83; two declarations of F are use-visible in} --@RI{ Ada 95.} @key[begin] ... @key[if] F > 1 @key[then] ... --@RI{ legal in Ada 83, ambiguous in Ada 95} @end{Example} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{derived_type_definition} is amended to include an optional @nt{record_extension_part} (see @RefSecNum(Type Extensions)). A derived type may override the discriminants of the parent by giving a new @nt{discriminant_part}. The parent type in a @nt<derived_type_definition> may be a derived type defined in the same visible part. When deriving from a type in the same visible part in which it is defined, the primitive subprograms declared prior to the derivation are inherited as primitive subprograms of the derived type. See @RefSecNum(Classification of Operations). @end{Extend83} @begin{DiffWord83} We now talk about the classes to which a type belongs, rather than a single class. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1]}@ChgNote{Irrelevant here, and broken since 7.6.1 defined "collection"} @ChgDeleted{Version=[3],Text=[As explained in Section 13, the concept of "storage pool" replaces the Ada 83 concept of "collection." These concepts are similar, but not the same.]} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A derived type may inherit from multiple (interface) progenitors, as well as the parent type @em see @RefSec{Interface Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A derived type may specify that it is a limited type. This is required for interface ancestors (from which limitedness is not inherited), but it is generally useful as documentation of limitedness.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[Defined the result of functions for null extensions (which we no longer require to be overridden - see @RefSecNum{Abstract Types and Subprograms}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[Defined the term @lquotes@;category of types@rquotes and used it in wording elsewhere; also specified the language-defined categories that form classes of types (this was never normatively specified in Ada 95).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0096-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added a (re)check that limited type extensions never are derived from nonlimited types in generic private parts. This is disallowed as it would make it possible to pass a limited object to a nonlimited class-wide type, which could then be copied. This is only possible using Ada 2005 syntax, so examples in existing programs should be rare.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0110-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to clarify that the characteristics of derived types are formally defined here. (This is the only place in the Standard that actually spells out what sorts of things are actually characteristics, which is rather important.)]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0164-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to ensure that anonymous access-to-subprogram types don't get modified on derivation.]} @end{DiffWord2005} @LabeledSubClause{Derivation Classes} @begin{Intro} In addition to the various language-defined classes of types, types can be grouped into @i(derivation classes). @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @Defn2{Term=[derived from], Sec=(directly or indirectly)} A derived type is @i(derived from) its parent type @i(directly); it is derived @i(indirectly) from any type from which its parent type is derived.@Chg{Version=[2], New=[ A derived type, interface type, type extension, task type, protected type, or formal derived type is also derived from every ancestor of each of its progenitor types, if any.],Old=[]} @Defn2{Term=[derivation class], Sec=(for a type)} @Defn2{Term=[root type], Sec=(of a class)} @Defn{rooted at a type} The derivation class of types for a type @i(T) (also called the class @i(rooted) at @i(T)) is the set consisting of @i(T) (the @i(root type) of the class) and all types derived from @i(T) (directly or indirectly) plus any associated universal or class-wide types (defined below). @begin{Discussion} Note that the definition of @lquotes@;derived from@rquotes@; is a recursive definition. We don't define a root type for all interesting language-defined classes, though presumably we could. @end{Discussion} @begin{Honest} By the class-wide type @lquotes@;associated@rquotes@; with a type @i(T), we mean the type @i(T)'Class. Similarly, the universal type associated with @i{root_integer}, @i{root_real}, and @i{root_fixed} are @i{universal_integer}, @i{universal_real}, and @i{universal_fixed}, respectively. @end{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} Every type is either a @i(specific) type, a @i(class-wide) type, or a @i(universal) type. @Defn{specific type} A specific type is one defined by a @nt<type_declaration>, a @nt<formal_type_declaration>, or a full type definition embedded in @Chg{Version=[2],New=[another construct],Old=[a declaration for an object]}. Class-wide and universal types are implicitly defined, to act as representatives for an entire class of types, as follows: @begin(Honest) The root types @i(root_integer), @i(root_real), and @i(root_fixed) are also specific types. They are declared in the specification of package Standard. @end(Honest) @begin(Description) @Defn{class-wide type}Class-wide types @\Class-wide types are defined for @Redundant[(and belong to)] each derivation class rooted at a tagged type (see @RefSecNum(Tagged Types and Type Extensions)). Given a subtype S of a tagged type @i(T), S'Class is the @nt<subtype_mark> for a corresponding subtype of the tagged class-wide type @i(T)'Class. Such types are called @lquotes@;class-wide@rquotes@; because when a formal parameter is defined to be of a class-wide type @i(T)'Class, an actual parameter of any type in the derivation class rooted at @i(T) is acceptable (see @RefSecNum(The Context of Overload Resolution)). @NoPrefix@Defn{first subtype} The set of values for a class-wide type @i(T)'Class is the discriminated union of the set of values of each specific type in the derivation class rooted at @i(T) (the tag acts as the implicit discriminant @em see @RefSecNum(Tagged Types and Type Extensions)). Class-wide types have no primitive subprograms of their own. However, as explained in @RefSecNum(Dispatching Operations of Tagged Types), operands of a class-wide type @i(T)'Class can be used as part of a dispatching call on a primitive subprogram of the type @i(T). The only components @Redundant[(including discriminants)] of @i(T)'Class that are visible are those of @i(T). If S is a first subtype, then S'Class is a first subtype. @begin{Reason} We want S'Class to be a first subtype when S is, so that an @nt{attribute_@!definition_@!clause} like @lquotes@key[for] S'Class'Output @key[use] ...;@rquotes@; will be legal. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{universal type}Universal types @\Universal types are defined for @Redundant[(and belong to)] the integer, real, @Chg{Version=[2],New=[],Old=[and ]}fixed point@Chg{Version=[2], New=[, and access],Old=[]} classes, and are referred to in this standard as respectively, @i(universal_integer), @i(universal_real), @Chg{Version=[2],New=[], Old=[and ]}@i(universal_fixed)@Chg{Version=[2], New=[, and @i(universal_access)@Chg{Version=[3], New=[@PDefn{universal_integer}@PDefn{universal_real}@PDefn{universal_fixed}@PDefn{universal_access}],Old=[]}],Old=[]}. These are analogous to class-wide types for these language-defined @Chg{Version=[2],New=[elementary],Old=[numeric]} classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real @nt<numeric_literal>@Chg{Version=[2],New=[, or the literal @key{null}],Old=[]}) is @lquotes@;universal@rquotes@; in that it is acceptable where some particular type in the class is expected (see @RefSecNum(The Context of Overload Resolution)). @NoPrefix@;The set of values of a universal type is the undiscriminated union of the set of values possible for any definable type in the associated class. Like class-wide types, universal types have no primitive subprograms of their own. However, their @lquotes@;universality@rquotes@; allows them to be used as operands with the primitive subprograms of any type in the corresponding class. @begin(Discussion) A class-wide type is only class-wide in one direction, from specific to class-wide, whereas a universal type is class-wide (universal) in both directions, from specific to universal and back. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} We considered defining class-wide or perhaps universal types for all derivation classes, not just tagged classes and these @Chg{Version=[2], New=[four elementary],Old=[three numeric]} classes. However, this was felt to overly weaken the strong-typing model in some situations. Tagged types preserve strong type distinctions thanks to the run-time tag. Class-wide or universal types for untagged types would weaken the compile-time type distinctions without providing a compensating run-time-checkable distinction. We considered defining standard names for the universal numeric types so they could be used in formal parameter specifications. However, this was felt to impose an undue implementation burden for some implementations. @end(Discussion) @begin(Honest) Formally, the set of values of a universal type is actually a @i(copy) of the undiscriminated union of the values of the types in its class. This is because we want each value to have exactly one type, with explicit or implicit conversion needed to go between types. An alternative, consistent model would be to associate a class, rather than a particular type, with a value, even though any given expression would have a particular type. In that case, implicit type conversions would not generally need to change the value, although an associated subtype conversion might need to. @end(Honest) @end(Description) @PDefn{root_integer} @PDefn{root_real} The integer and real numeric classes each have a specific root type in addition to their universal type, named respectively @i(root_integer) and @i(root_real). @Defn2{Term=[cover], Sec=(a type)} A class-wide or universal type is said to @i(cover) all of the types in its class. A specific type covers only itself. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @Defn2{Term=[descendant], Sec=(of a type)} A specific type @i(T2) is defined to be a @i(descendant) of a type @i(T1) if @i(T2) is the same as @i(T1), or if @i(T2) is derived (directly or indirectly) from @i(T1). A class-wide type @i(T2)'Class is defined to be a descendant of type @i(T1) if @i(T2) is a descendant of @i(T1). Similarly, the @Chg{Version=[2],New=[numeric ],Old=[]}universal types are defined to be descendants of the root types of their classes. @Defn2{Term=[ancestor], Sec=(of a type)} If a type @i(T2) is a descendant of a type @i(T1), then @i(T1) is called an @i(ancestor) of @i(T2). @Defn2{Term=[ultimate ancestor], Sec=(of a type)} @Defn2{Term=[ancestor], Sec=(ultimate)} @Chg{Version=[2],New=[An],Old=[The]} @i(ultimate ancestor) of a type is @Chg{Version=[2],New=[an],Old=[the]} ancestor of @Chg{Version=[2],New=[that],Old=[the]} type that is not @Chg{Version=[2],New=[itself ],Old=[]}a descendant of any other type.@Chg{Version=[2],New=[ Every untagged type has a unique ultimate ancestor.],Old=[]} @begin{Ramification} A specific type is a descendant of itself. Class-wide types are considered descendants of the corresponding specific type, and do not have any descendants of their own. A specific type is an ancestor of itself. The root of a derivation class is an ancestor of all types in the class, including any class-wide types in the class. @end{Ramification} @begin(Discussion) @Leading@keepnext@;The terms root, parent, ancestor, and ultimate ancestor are all related. For example: @begin(Itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Each type has at most one parent, and one or more ancestor types; each @Chg{Version=[2],New=[untagged ],Old=[]}type has exactly one ultimate ancestor. In Ada 83, the term @lquotes@;parent type@rquotes@; was sometimes used more generally to include any ancestor type (e.g. RM83-9.4(14)). In Ada 95, we restrict parent to mean the immediate ancestor. A class of types has at most one root type; a derivation class has exactly one root type. The root of a class is an ancestor of all of the types in the class (including itself). The type @i(root_integer) is the root of the integer class, and is the ultimate ancestor of all integer types. A similar statement applies to @i(root_real). @end(Itemize) @end(Discussion) @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Ancestor>, Text=<@ChgAdded{Version=[2],Text=[An ancestor of a type is the type itself or, in the case of a type derived from other types, its parent type or one of its progenitor types or one of their ancestors. Note that ancestor and descendant are inverse relationships.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Descendant>, Text=<@ChgAdded{Version=[2],Text=[A type is a descendant of itself, its parent and progenitor types, and their ancestors. Note that descendant and ancestor are inverse relationships.]}>} @Defn2{Term=[inherited], Sec=(from an ancestor type)} An inherited component @Redundant[(including an inherited discriminant)] of a derived type is inherited @i(from) a given ancestor of the type if the corresponding component was inherited by each derived type in the chain of derivations going back to the given ancestor. @end{StaticSem} @begin{Notes} Because operands of a universal type are acceptable to the predefined operators of any type in their class, ambiguity can result. For @i(universal_integer) and @i(universal_real), this potential ambiguity is resolved by giving a preference (see @RefSecNum{The Context of Overload Resolution}) to the predefined operators of the corresponding root types (@i(root_integer) and @i(root_real), respectively). Hence, in an apparently ambiguous expression like @begin(Display) 1 + 4 < 7 @end(Display) @NoPrefix@;where each of the literals is of type @i(universal_integer), the predefined operators of @i(root_integer) will be preferred over those of other specific integer types, thereby resolving the ambiguity. @begin(Ramification) Except for this preference, a root numeric type is essentially like any other specific type in the associated numeric class. In particular, the result of a predefined operator of a root numeric type is not @lquotes@;universal@rquotes@; (implicitly convertible) even if both operands were. @end(Ramification) @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Updated the wording to define the @i{universal_access} type. This was defined to make @key{null} for anonymous access types sensible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[The definitions of ancestors and descendants were updated to allow multiple ancestors (necessary to support interfaces).]} @end{DiffWord95} @LabeledClause{Scalar Types} @begin{Intro} @Defn{scalar type} @i(Scalar) types comprise enumeration types, integer types, and real types. @Defn{discrete type} Enumeration types and integer types are called @i(discrete) types; @Defn{position number} each value of a discrete type has a @i(position number) which is an integer value. @Defn{numeric type} Integer types and real types are called @i(numeric) types. @Redundant[All scalar types are ordered, that is, all relational operators are predefined for their values.] @end{Intro} @begin{Syntax} @Syn{lhs=<range_constraint>,rhs=" @key{range} @Syn2{range}"} @Syn{lhs=<range>,rhs=" @Syn2{range_attribute_reference} | @Syn2{simple_expression} .. @Syn2{simple_expression}"} @end{Syntax} @begin(Discussion) These need to be @nt<simple_expression>s rather than more general @nt<expression>s because ranges appear in membership tests and other contexts where @nt<expression> .. @nt<expression> would be ambiguous. @end(Discussion) @begin{Intro} @Defn{range} @Defn2{Term=[lower bound], Sec=(of a range)} @Defn2{Term=[upper bound], Sec=(of a range)} @Defn{type of a range} A @i(range) has a @i(lower bound) and an @i(upper bound) and specifies a subset of the values of some scalar type (the @i(type of the range)). A range with lower bound L and upper bound R is described by @lquotes@;L .. R@rquotes@;. @Defn{null range} If R is less than L, then the range is a @i(null range), and specifies an empty set of values. Otherwise, the range specifies the values of the type from the lower bound to the upper bound, inclusive. @Defn2{Term=[belong], Sec=(to a range)} A value @i(belongs) to a range if it is of the type of the range, and is in the subset of values specified by the range. @PDefn2{Term=[satisfies], Sec=(a range constraint)} A value @i(satisfies) a range constraint if it belongs to the associated range. @Defn2{Term=[included], Sec=(one range in another)} One range is @i(included) in another if all values that belong to the first range also belong to the second. @end{Intro} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(range_constraint range)} For a @nt<subtype_indication> containing a @nt<range_constraint>, either directly or as part of some other @nt<scalar_constraint>, the type of the @nt<range> shall resolve to that of the type determined by the @nt<subtype_mark> of the @nt<subtype_indication>. @PDefn2{Term=[expected type], Sec=(range simple_expressions)} For a @nt<range> of a given type, the @nt<simple_expression>s of the @nt<range> (likewise, the @nt<simple_expression>s of the equivalent @nt<range> for a @nt<range_attribute_reference>) are expected to be of the type of the @nt<range>. @begin(Discussion) In Ada 95, @nt<constraint>s only appear within @nt<subtype_indication>s; things that look like constraints that appear in type declarations are called something else like @nt<real_range_specification>s. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We say "the expected type is ..." or "the type is expected to be ..." depending on which reads better. They are fundamentally equivalent, and both feed into the type resolution rules of @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(The Context of Overload Resolution). In some cases, it doesn't work to use expected types. For example, in the above rule, we say that the @lquotes@;type of the @nt<range> shall resolve to ...@rquotes@; rather than @lquotes@;the expected type for the @nt<range> is ...@rquotes@;. We then use @lquotes@;expected type@rquotes@; for the bounds. If we used @lquotes@;expected@rquotes@; at both points, there would be an ambiguity, since one could apply the rules of @RefSecNum{The Context of Overload Resolution} either on determining the type of the range, or on determining the types of the individual bounds. It is clearly important to allow one bound to be of a universal type, and the other of a specific type, so we need to use @lquotes@;expected type@rquotes@; for the bounds. Hence, we used @lquotes@;shall resolve to@rquotes@; for the type of the range as a whole. There are other situations where @lquotes@;expected type@rquotes@; is not quite right, and we use @lquotes@;shall resolve to@rquotes@; instead. @end(Discussion) @end{Resolution} @begin{StaticSem} @RootDefn2{Term=[base range], Sec=(of a scalar type)} The @i(base range) of a scalar type is the range of finite values of the type that can be represented in every unconstrained object of the type; it is also the range supported at a minimum for intermediate values during the evaluation of expressions involving predefined operators of the type. @begin{ImplNote} Note that in some machine architectures intermediates in an expression (particularly if static), and register-resident variables might accommodate a wider range. The base range does not include the values of this wider range that are not assignable without overflow to memory-resident objects.@end{implnote} @begin(Ramification) @PDefn2{Term=[base range], Sec=(of an enumeration type)} The base range of an enumeration type is the range of values of the enumeration type. @end(Ramification) @begin{Reason} If the representation supports infinities, the base range is nevertheless restricted to include only the representable finite values, so that 'Base'First and 'Base'Last are always guaranteed to be finite.@end{reason} @begin(Honest) By a "value that can be assigned without overflow" we don't mean to restrict ourselves to values that can be represented exactly. Values between machine representable values can be assigned, but on subsequent reading, a slightly different value might be retrieved, as (partially) determined by the number of digits of precision of the type. @end(Honest) @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} @Redundant[A constrained scalar subtype is one to which a range constraint applies.] @Defn2{Term=[range], Sec=(of a scalar subtype)} The @i(range) of a constrained scalar subtype is the range associated with the range constraint of the subtype. The @i(range) of an unconstrained scalar subtype is the base range of its type. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(range with a scalar subtype)} A range is @i(compatible) with a scalar subtype if and only if it is either a null range or each bound of the range belongs to the range of the subtype. @PDefn2{Term=[compatibility], Sec=(range_constraint with a scalar subtype)} A @nt<range_constraint> is @i(compatible) with a scalar subtype if and only if its range is compatible with the subtype. @begin(Ramification) Only @nt<range_constraint>s (explicit or implicit) impose conditions on the values of a scalar subtype. The other @nt<scalar_constraint>s, @nt<digits_constraint>s and @nt<delta_constraint>s impose conditions on the subtype denoted by the @nt<subtype_mark> in a @nt<subtype_indication>, but don't impose a condition on the values of the subtype being defined. Therefore, a scalar subtype is not called @i(constrained) if all that applies to it is a @nt<digits_constraint>. Decimal subtypes are subtle, because a @nt<digits_constraint> without a @nt<range_constraint> nevertheless includes an implicit @nt<range_constraint>. @end(Ramification) @PDefn2{Term=[elaboration], Sec=(range_constraint)} The elaboration of a @nt{range_constraint} consists of the evaluation of the @nt{range}. @PDefn2{Term=[evaluation], Sec=(range)} The evaluation of a @nt{range} determines a lower bound and an upper bound. If @nt<simple_expression>s are given to specify bounds, the evaluation of the @nt<range> evaluates these @nt<simple_expression>s in an arbitrary order, and converts them to the type of the @nt<range>.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a range)} If a @nt<range_attribute_reference> is given, the evaluation of the @nt<range> consists of the evaluation of the @nt<range_attribute_reference>. @keepnext@i(Attributes) @Leading@keepnext@;For @PrefixType{every scalar subtype S}, the following attributes are defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<First>, Text=[S'First denotes the lower bound of the range of S. The value of this attribute is of the type of S.]} @begin{Ramification} Evaluating S'First never raises Constraint_Error.@end{ramification} @Attribute{Prefix=<S>, AttrName=<Last>, Text=[S'Last denotes the upper bound of the range of S. The value of this attribute is of the type of S.]} @begin{Ramification} Evaluating S'Last never raises Constraint_Error.@end{ramification} @Attribute{Prefix=<S>, AttrName=<Range>, Text=[S'Range is equivalent to the @nt<range> S'First .. S'Last.]} @Attribute{Prefix=<S>, AttrName=<Base>, Text=[S'Base denotes an unconstrained subtype of the type of S. This unconstrained subtype is called the @i(base subtype) of the type. ]}@Defn2{Term=(base subtype), Sec=(of a type)} @AttributeLeading{Prefix=<S>, AttrName=<Min>, Text=[S'Min denotes a function with the following specification: @begin(Descexample) @b(function) S'Min(@RI(Left), @RI(Right) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the lesser of the values of the two parameters.]} @begin{Discussion} @Defn2{Term=[italics],Sec=(formal parameters of attribute functions)} The formal parameter names are italicized because they cannot be used in calls @em see @RefSecNum{Subprogram Calls}. Such a specification cannot be written by the user because an @nt<attribute_reference> is not permitted as the designator of a user-defined function, nor can its formal parameters be anonymous. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Max>, Text=[S'Max denotes a function with the following specification: @begin(Descexample) @b(function) S'Max(@RI(Left), @RI(Right) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the greater of the values of the two parameters.]} @AttributeLeading{Prefix=<S>, AttrName=<Succ>, Text=[S'Succ denotes a function with the following specification: @begin(Descexample) @b(function) S'Succ(@RI(Arg) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one more than that of the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of adding one to the value of @i(Arg). For a fixed point type, the function returns the result of adding @i(small) to the value of @i(Arg). For a floating point type, the function returns the machine number (as defined in @RefSecNum(Floating Point Types)) immediately above the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such machine number.]} @begin{Ramification} S'Succ for a modular integer subtype wraps around if the value of @i(Arg) is S'Base'Last. S'Succ for a signed integer subtype might raise Constraint_Error if the value of @i(Arg) is S'Base'Last, or it might return the out-of-base-range value S'Base'Last+1, as is permitted for all predefined numeric operations.@end{ramification} @AttributeLeading{Prefix=<S>, AttrName=<Pred>, Text=[S'Pred denotes a function with the following specification: @begin(Descexample) @b(function) S'Pred(@RI(Arg) : S'Base) @b(return) S'Base @end(Descexample) @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For an enumeration type, the function returns the value whose position number is one less than that of the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such value of the type. For an integer type, the function returns the result of subtracting one from the value of @i(Arg). For a fixed point type, the function returns the result of subtracting @i(small) from the value of @i(Arg). For a floating point type, the function returns the machine number (as defined in @RefSecNum(Floating Point Types)) immediately below the value of @i(Arg); @IndexCheck{Range_Check} Constraint_Error is raised if there is no such machine number.]} @begin{Ramification} S'Pred for a modular integer subtype wraps around if the value of @i(Arg) is S'Base'First. S'Pred for a signed integer subtype might raise Constraint_Error if the value of @i(Arg) is S'Base'First, or it might return the out-of-base-range value S'Base'First@en@;1, as is permitted for all predefined numeric operations.@end{ramification} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Image>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Image denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@b(function) S'Wide_Wide_Image(@RI(Arg) : S'Base) @b(return) Wide_Wide_String]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=[image], Sec=(of a value)} The function returns an @i(image) of the value of @i(Arg), that is, a sequence of characters representing the value in display form.]}]}@Comment{End of Annex text here.} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The lower bound of the result is one.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ If the machine supports negative zeros for signed integer types, it is not specified whether "@ 0" or "@en@;0" should be returned for negative zero. We don't have enough experience with such machines to know what is appropriate, and what other languages do. In any case, the implementation should be consistent.]} @end{implnote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn{nongraphic character} The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a @i(nongraphic character) (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined name in upper case (for example, the image of the nongraphic character identified as @i(nul) is @lquotes@;NUL@rquotes@; @em the quotes are not part of the image).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ For an enumeration type T that has @lquotes@;holes@rquotes@; (caused by an @nt{enumeration_@!representation_@!clause}), @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things).]} @end{ImplNote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits@en@;1 (see @RefSecNum(Operations of Floating Point Types)) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or @en), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Leading zeros are present in the exponent only if necessary to make the exponent at least two digits.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see @RefSecNum(Operations of Fixed Point Types)) digits after the decimal point.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Fixed_IO.Put.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For a machine that supports negative zeros, it is not specified whether "@ 0.000" or "@en@;0.000" is returned. See corresponding comment above about integer types with signed zeros.]} @end{implnote} @AttributeLeading{Prefix=<S>, AttrName=<Wide_Image>, Text=[S'Wide_Image denotes a function with the following specification: @begin(Descexample) @b(function) S'Wide_Image(@RI(Arg) : S'Base) @b(return) Wide_String @end(Descexample) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1],ARef=[AI05-0264-1]} @NoPrefix@Defn2{Term=[image], Sec=(of a value)} The function returns an @Chg{Version=[2],New=[image],Old=[@i(image)]} of the value of @i(Arg)@Chg{Version=[2],New=[ as a Wide_String],Old=[, that is, a sequence of characters representing the value in display form]}.]} The lower bound of the result is one.@Chg{Version=[2], New=[ The image has the same sequence of @Chg{Version=[3],New=[graphic characters],Old=[character]} as defined for S'Wide_Wide_Image if all the graphic characters are defined in Wide_Character; otherwise@Chg{Version=[3],New=[,],Old=[]} the sequence of characters is implementation defined (but no shorter than that of S'Wide_Wide_Image for the same value of Arg).],Old=[]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The sequence of characters of the value returned by S'Wide_Image when some of the graphic characters of S'Wide_Wide_Image are not defined in Wide_Character.]}]} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 31 through 34 were moved to Wide_Wide_Image.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of an integer value is the corresponding decimal literal, without underlines, leading zeros, exponent, or trailing spaces, but with a single leading character that is either a minus sign or a space.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[ If the machine supports negative zeros for signed integer types, it is not specified whether "@en@;0" or " 0" should be returned for negative zero. We don't have enough experience with such machines to know what is appropriate, and what other languages do. In any case, the implementation should be consistent.]} @end{implnote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn{nongraphic character} The image of an enumeration value is either the corresponding identifier in upper case or the corresponding character literal (including the two apostrophes); neither leading nor trailing spaces are included. For a @i(nongraphic character) (a value of a character type that has no enumeration literal associated with it), the result is a corresponding language-defined or implementation-defined name in upper case (for example, the image of the nongraphic character identified as @i(nul) is @lquotes@;NUL@rquotes@; @em the quotes are not part of the image).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[For an enumeration type T that has @lquotes@;holes@rquotes@; (caused by an @nt{enumeration_representation_clause}), @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} T'Wide_Image should raise Program_Error if the value is one of the holes (which is a bounded error anyway, since holes can be generated only via uninitialized variables and similar things).]} @end{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of a floating point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, a single digit (that is nonzero unless the value is zero), a decimal point, S'Digits@en@;1 (see @RefSecNum(Operations of Floating Point Types)) digits after the decimal point (but one if S'Digits is one), an upper case E, the sign of the exponent (either + or @en), and two or more digits (with leading zeros if necessary) representing the exponent. If S'Signed_Zeros is True, then the leading character is a minus sign for a negatively signed zero.]} @begin{Honest} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Leading zeros are present in the exponent only if necessary to make the exponent at least two digits.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Float_IO.Put in its default format.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The image of a fixed point value is a decimal real literal best approximating the value (rounded away from zero if halfway between) with a single leading character that is either a minus sign or a space, one or more digits before the decimal point (with no redundant leading zeros), a decimal point, and S'Aft (see @RefSecNum(Operations of Fixed Point Types)) digits after the decimal point.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This image is intended to conform to that produced by Text_IO.Fixed_IO.Put.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The rounding direction is specified here to ensure portability of output results.]} @end{implnote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[For a machine that supports negative zeros, it is not specified whether "@en@;0.000" or " 0.000" is returned. See corresponding comment above about integer types with signed zeros.]} @end{implnote} @AttributeLeading{Prefix=<S>, AttrName=<Image>, Text=[S'Image denotes a function with the following specification: @begin(Descexample) @b(function) S'Image(@RI(Arg) : S'Base) @b(return) String @end(Descexample) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @NoPrefix@;The function returns an image of the value of @i(Arg) as a String.]} The lower bound of the result is one. The image has the same sequence of graphic characters as that defined for S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} if all the graphic characters are defined in Character; otherwise@Chg{Version=[3],New=[,],Old=[]} the sequence of characters is implementation defined (but no shorter than that of S'@Chg{Version=[2],New=[Wide_Wide_Image], Old=[Wide_Image]} for the same value of @i(Arg)). @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0],Text=[The sequence of characters of the value returned by S'Image when some of the graphic characters of S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} are not defined in Character.]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Width>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Width denotes the maximum length of a Wide_Wide_String returned by S'Wide_Wide_Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).],Old=[]}]} @Attribute{Prefix=<S>, AttrName=<Wide_Width>, Text=[S'Wide_Width denotes the maximum length of a Wide_String returned by S'Wide_Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).]} @Attribute{Prefix=<S>, AttrName=<Width>, Text=[S'Width denotes the maximum length of a String returned by S'Image over all values of the subtype S. It denotes zero for a subtype that has a null range. Its type is @i(universal_integer).]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Wide_Wide_Value>, ARef=[AI95-00285-01], Text=[@Chg{Version=[2],New=[S'Wide_Wide_Value denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@b(function) S'Wide_Wide_Value(@RI(Arg) : Wide_Wide_String) @b(return) S'Base]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[This function returns a value given an image of the value as a Wide_Wide_String, ignoring any leading or trailing spaces.]}]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@PDefn2{Term=[evaluation], Sec=(Wide_Wide_Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Wide_Image for a nongraphic character of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise@Chg{Version=[3],New=[,],Old=[]} Constraint_Error is raised.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check.]} @end{discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[Added],Ref=[8652/0096],ARef=[AI95-00053-01]} @ChgAdded{Version=[2],Text=[A sequence of characters corresponds to the result of S'Wide_Wide_Image if it is the same ignoring case. Thus, the case of an image of a nongraphic character does not matter. For example, Character'Wide_Wide_Value("nul") does not raise Constraint_Error, even though Character'Wide_Wide_Image returns "NUL" for the nul character.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Wide_Value for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise@Chg{Version=[3],New=[,],Old=[]} Constraint_Error is raised.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error. However, we currently require (see @RefSecNum(Static Expressions and Static Subtypes)) in an @nt{assignment_statement} like "X := <numeric_literal>;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types).]} @end(Discussion) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Type=[Leading],Text=[For the evaluation of a call on S'Wide_Wide_Value for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:]} @begin[itemize] @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@nt[numeric_literal]]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[numeral].[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<.@nt[numeral][@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[base]#@nt[based_numeral].#[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=<@nt[base]#.@nt[based_numeral]#[@nt[exponent]]>} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise@Chg{Version=[3],New=[,],Old=[]} Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Wide_Value>, Text=[S'Wide_Value denotes a function with the following specification: @begin(Descexample) @b(function) S'Wide_Value(@RI(Arg) : Wide_String) @b(return) S'Base @end(Descexample) @NoPrefix@;This function returns a value given an image of the value as a Wide_String, ignoring any leading or trailing spaces.]}@Comment{This marks the end of the Annex text.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @NoPrefix@PDefn2{Term=[evaluation], Sec=(Wide_Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Wide_Image for a @Chg{Version=[2],New=[value],Old=[nongraphic character]} of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise@Chg{Version=[3],New=[,],Old=[]} Constraint_Error is raised. @Chg{Version=[2],New=[For a numeric subtype S, the evaluation of a call on S'Wide_Value with @i(Arg) of type Wide_String is equivalent to a call on S'Wide_Wide_Value for a corresponding @i(Arg) of type Wide_Wide_String.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[It's not crystal clear that Range_Check is appropriate here, but it doesn't seem worthwhile to invent a whole new check name just for this weird case, so we decided to lump it in with Range_Check.]} @end{discussion} @begin{Honest} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0096],ARef=[AI95-00053-01]} @ChgRef{Version=[2],Kind=[DeletedAdded]} @ChgDeleted{Version=[2],Text=[ @Chg{Version=[1],New=[A sequence of characters corresponds to the result of S'Wide_Image if it is the same ignoring case. Thus, the case of an image of a nongraphic character does not matter. For example, Character'Wide_Value("nul") does not raise Constraint_Error, even though Character'Wide_Image returns "NUL" for the nul character.],Old=[]}]} @end{Honest} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[S'Wide_Value is subtly different from S'Wide_Wide_Value for enumeration subtypes since S'Wide_Image might produce a different sequence of characters than S'Wide_Wide_Image if the enumeration literal uses characters outside of the predefined type Wide_Character. That is why we don't just define S'Wide_Value in terms of S'Wide_Wide_Value for enumeration subtypes. S'Wide_Value and S'Wide_Wide_Value for numeric subtypes yield the same result given the same sequence of characters.]} @end(Reason) @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 44 through 51 were moved to Wide_Wide_Value.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Wide_Value (or S'Value) for an integer subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an integer literal, with an optional leading sign character (plus or minus for a signed type; only plus for a modular type), and the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[We considered allowing 'Value to return a representable but out-of-range value without a Constraint_Error. However, we currently require (see @RefSecNum(Static Expressions and Static Subtypes)) in an @nt{assignment_statement} like "X := <numeric_literal>;" that the value of the numeric-literal be in X's base range (at compile time), so it seems unfriendly and confusing to have a different range allowed for 'Value. Furthermore, for modular types, without the requirement for being in the base range, 'Value would have to handle arbitrarily long literals (since overflow never occurs for modular types).]} @end(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],NoPrefix=[T],Type=[Leading],Text=[For the evaluation of a call on S'Wide_Value (or S'Value) for a real subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of one of the following:]} @begin[itemize] @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[numeric_literal]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[numeral].[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<.@nt[numeral][@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<@nt[base]#@nt[based_numeral].#[@nt[exponent]]>} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@nt[base]#.@nt[based_numeral]#[@nt[exponent]]]} @end{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=(Constraint_Error), Sec=(raised by failure of run-time check)} with an optional leading sign character (plus or minus), and if the corresponding numeric value belongs to the base range of the type of S, then that value is the result; @IndexCheck{Range_Check} otherwise Constraint_Error is raised. The sign of a zero value is preserved (positive if none has been specified) if S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Value>, Text=[S'Value denotes a function with the following specification: @begin(Descexample) @b(function) S'Value(@RI(Arg) : String) @b(return) S'Base @end(Descexample) @NoPrefix@;This function returns a value given an image of the value as a String, ignoring any leading or trailing spaces.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @NoPrefix@PDefn2{Term=[evaluation], Sec=(Value)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For the evaluation of a call on S'Value for an enumeration subtype S, if the sequence of characters of the parameter (ignoring leading and trailing spaces) has the syntax of an enumeration literal and if it corresponds to a literal of the type of S (or corresponds to the result of S'Image for a value of the type), the result is the corresponding enumeration value; @IndexCheck{Range_Check} otherwise@Chg{Version=[3],New=[,],Old=[]} Constraint_Error is raised. For a numeric subtype S, the evaluation of a call on S'Value with @i(Arg) of type String is equivalent to a call on S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} for a corresponding @i(Arg) of type @Chg{Version=[2],New=[Wide_Wide_String],Old=[Wide_String]}. @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} S'Value is subtly different from S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} for enumeration subtypes@Chg{Version=[2],New=[; see the discussion under S'Wide_Value], Old=[since S'Image might produce a different sequence of characters than S'Wide_Image if the enumeration literal uses characters outside of the predefined type Character. That is why we don't just define S'Value in terms of S'Wide_Value for enumeration subtypes. S'Value and S'Wide_Value for numeric subtypes yield the same result given the same sequence of characters]}. @end(Reason) @end(description) @EndPrefixType{} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} An implementation may extend the @Chg{Version=[2],New=[Wide_Wide_Value, ], Old=[Wide_Value, ]} @Redundant[@Chg{Version=[2],New=[Wide_Value, ],Old=[]}Value, @Chg{Version=[2],New=[Wide_Wide_Image, ], Old=[]}Wide_Image, and Image] attributes of a floating point type to support special values such as infinities and NaNs. @begin{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The permission is really only necessary for @Chg{Version=[2],New=[Wide_Wide_Value], Old=[Wide_Value]}, because Value @Chg{Version=[2],New=[and Wide_Value are],Old=[is]} defined in terms of @Chg{Version=[2],New=[Wide_Wide_Value], Old=[Wide_Value]}, and because the behavior of @Chg{Version=[2],New=[Wide_Wide_Image, ], Old=[]}Wide_Image@Chg{Version=[2],New=[,],Old=[]} and Image is already unspecified for things like infinities and NaNs. @end{TheProof} @begin{Reason} This is to allow implementations to define full support for IEEE arithmetic. See also the similar permission for Get in @RefSecNum{Input-Output for Real Types}. @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0182-1],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[An implementation may extend the Wide_Wide_Value, Wide_Value, and Value attributes of a character type to accept strings of the form @ldquote@;Hex_@i<hhhhhhhh>@rdquote (ignoring case) for any character (not just the ones for which Wide_Wide_Image would produce that form @em see @RefSecNum{Character Types}), as well as three-character strings of the form @ldquote@;'@i<X>'@rdquote, where @i<X> is any character, including nongraphic characters.]} @end{ImplPerm} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a scalar type, the following language-defined representation aspect may be specified with an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}):]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Default_Value@\This aspect shall be specified by a static expression, and that expression shall be explicit, even if the aspect has a boolean type. Default_Value shall be specified only on a @nt{full_type_declaration}.@AspectDefn{Default_Value}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The part about requiring an explicit expression is to disallow omitting the value for this aspect, which would otherwise be allowed by the rules of @RefSecNum{Aspect Specifications}.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a representation aspect in order to disallow specifying it on a derived type that has inherited primitive subprograms; that is necessary as the sizes of @key[out] parameters could be different whether or not a Default_Value is specified (see @RefSecNum{Parameter Associations}).]} @end{Reason} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Default_Value], Text=[@ChgAdded{Version=[3],Text=[Default value for a scalar subtype.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[If a derived type with no primitive subprograms inherits a boolean Default_Value aspect, the aspect may be specified to have any value for the derived type.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This overrides the @RefSecNum{Aspect Specifications} rule that says that a boolean aspect with a value True cannot be changed.]} @end{Reason} @end{StaticSem} @begin{Resolution} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} specified for the Default_Value aspect is the type defined by the @nt{full_type_declaration} on which it appears.@PDefn2{Term=[expected type],Sec=[@nt{expression} of a Default_Value aspect]}]} @end{Resolution} @begin{Notes} The evaluation of S'First or S'Last never raises an exception. If a scalar subtype S has a nonnull range, S'First and S'Last belong to this range. These values can, for example, always be assigned to a variable of subtype S. @begin(Discussion) This paragraph addresses an issue that came up with Ada 83, where for fixed point types, the end points of the range specified in the type definition were not necessarily within the base range of the type. However, it was later clarified (and we reconfirm it in @RefSec(Fixed Point Types)) that the First and Last attributes reflect the true bounds chosen for the type, not the bounds specified in the type definition (which might be outside the ultimately chosen base range). @end(Discussion) For a subtype of a scalar type, the result delivered by the attributes Succ, Pred, and Value might not belong to the subtype; similarly, the actual parameters of the attributes Succ, Pred, and Image need not belong to the subtype. For any value V (including any nongraphic character) of an enumeration subtype S, S'Value(S'Image(V)) equals V, as @Chg{Version=[2],New=[do],Old=[does]} S'Wide_Value(S'Wide_Image(V))@Chg{Version=[2], New=[ and S'Wide_Wide_Value(S'Wide_Wide_Image(V))],Old=[]}. @Chg{Version=[2],New=[None of these expressions],Old=[Neither expression]} ever @Chg{Version=[2],New=[raise],Old=[raises]} Constraint_Error. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of ranges:) @begin{Example} -10 .. 10 X .. X + 1 0.0 .. 2.0*Pi Red .. Green --@RI[ see @RefSecNum{Enumeration Types}] 1 .. 0 --@RI[ a null range] Table'Range --@RI[ a range attribute reference (see @RefSecNum{Array Types})] @end{Example} @Leading@keepnext@i(Examples of range constraints:) @begin{Example} @key(range) -999.0 .. +999.0 @key(range) S'First+1 .. S'Last-1 @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Defn{incompatibilities with Ada 83} S'Base is no longer defined for nonscalar types. One conceivable existing use of S'Base for nonscalar types is S'Base'Size where S is a generic formal private type. However, that is not generally useful because the actual subtype corresponding to S might be a constrained array or discriminated type, which would mean that S'Base'Size might very well overflow (for example, S'Base'Size where S is a constrained subtype of String will generally be 8 * (Integer'Last + 1)). For derived discriminated types that are packed, S'Base'Size might not even be well defined if the first subtype is constrained, thereby allowing some amount of normally required @lquotes@;dope@rquotes@; to have been squeezed out in the packing. Hence our conclusion is that S'Base'Size is not generally useful in a generic, and does not justify keeping the attribute Base for nonscalar types just so it can be used as a @Chg{New=[@nt{prefix}],Old=[prefix]}. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The attribute S'Base for a scalar subtype is now permitted anywhere a @nt{subtype_mark} is permitted. S'Base'First .. S'Base'Last is the base range of the type. Using an @nt{attribute_@!definition_@!clause}, one cannot specify any subtype-specific attributes for the subtype denoted by S'Base (the base subtype). The attribute S'Range is now allowed for scalar subtypes. The attributes S'Min and S'Max are now defined, and made available for all scalar types. The attributes S'Succ, S'Pred, S'Image, S'Value, and S'Width are now defined for real types as well as discrete types. Wide_String versions of S'Image and S'Value are defined. These are called S'Wide_Image and S'Wide_Value to avoid introducing ambiguities involving uses of these attributes with string literals. @end{Extend83} @begin{DiffWord83} We now use the syntactic category @nt<range_attribute_reference> since it is now syntactically distinguished from other attribute references. The definition of S'Base has been moved here from 3.3.3 since it now applies only to scalar types. More explicit rules are provided for nongraphic characters. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The attributes Wide_Wide_Image, Wide_Wide_Value, and Wide_Wide_Width are new. Note that Wide_Image and Wide_Value are now defined in terms of Wide_Wide_Image and Wide_Wide_Value, but the image of types other than characters have not changed.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ The Wide_Image and Wide_Value attributes are now defined in terms of Wide_Wide_Image and Wide_Wide_Value, but the images of numeric types have not changed.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0181-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Soft hyphen (code point 173) is nongraphic in ISO/IEC 10646:2011 (and also in the 2003 version of that standard). Thus, we have given it the language-defined name @i{soft_hyphen}. This changes the result of Character'Image (and all of the related types and Image attributes) for this character, and changes the behavior of Character'Value (and all of the related types and Value attributes) for this character, and (in unusual circumstances), changes the result for Character'Width (and all of the related types and Width attributes). The vast majority of programs won't see any difference, as they are already prepared to handle nongraphic characters.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0182-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added an @ImplPermTitle to let Wide_Wide_Value, Wide_Value, and Value accept strings in the form of literals containing nongraphic characters and "Hex_hhhhhhhh" for Latin-1 and graphic characters. These were required to raise Constraint_Error in Ada 2005. Since these attributes aren't very useful, implementations were inconsistent as to whether these were accepted, and since code that would care why the attribute failed seems unlikely, this should not be a problem in practice.]} @end{Inconsistent2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The new aspect Default_Value allows defining implicit initial values (see @RefSecNum{Object Declarations}) for scalar types.]} @end{Extend2005} @LabeledSubClause{Enumeration Types} @begin{Intro} @Redundant[@Defn{enumeration type} An @nt<enumeration_type_definition> defines an enumeration type.] @end{Intro} @begin{Syntax} @Syn{lhs=<enumeration_type_definition>,rhs=" (@Syn2{enumeration_literal_specification} {, @Syn2{enumeration_literal_specification}})"} @Syn{lhs=<enumeration_literal_specification>, rhs=" @Syn2{defining_identifier} | @Syn2{defining_character_literal}"} @Syn{lhs=<defining_character_literal>,rhs="@Syn2{character_literal}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0227-1],ARef=[AI05-0299-1]} The @nt<defining_identifier>s@Chg{Version=[3],New=[ in upper case],Old=[]} @Redundant[and@Chg{Version=[3],New=[ the],Old=[]} @nt<defining_character_literal>s] listed in an @nt<enumeration_type_definition> shall be distinct. @begin{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0227-1]} @Chg{Version=[3],New=[For character literals, this],Old=[This]} is a ramification of the normal disallowance of homographs explicitly declared immediately in the same declarative region. @end{TheProof} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0227-1]} @ChgAdded{Version=[3],Text=[To ease implementation of the attribute Wide_Wide_Value, we require that all enumeration literals have distinct images.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0006-1]} @Defn{enumeration literal} Each @nt<enumeration_literal_specification> is the explicit declaration of the corresponding @i(enumeration literal): it declares a parameterless function, whose defining name is the @nt<defining_@!identifier> or @nt<defining_@!character_@!literal>, and whose result @Chg{Version=[3],New=[subtype is the base subtype of],Old=[type is]} the enumeration type. @begin{Reason} This rule defines the profile of the enumeration literal, which is used in the various types of conformance. @end{Reason} @begin{Ramification} The parameterless function associated with an enumeration literal is fully defined by the @nt<enumeration_type_definition>; a body is not permitted for it, and it never fails the Elaboration_Check when called. @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0006-1]} @ChgAdded{Version=[3],Text=[The result subtype is primarily a concern when an enumeration literal is used as the @nt{expression} of a case statement, due to the full coverage requirement based on the nominal subtype.]} @end{Discussion} Each enumeration literal corresponds to a distinct value of the enumeration type, and to a distinct position number. @PDefn2{Term=[position number], Sec=(of an enumeration value)} The position number of the value of the first listed enumeration literal is zero; the position number of the value of each subsequent enumeration literal is one more than that of its predecessor in the list. @redundant[The predefined order relations between values of the enumeration type follow the order of corresponding position numbers.] @redundant[@PDefn2{Term=[overloaded], Sec=(enumeration literal)} If the same @nt<defining_identifier> or @nt<defining_character_literal> is specified in more than one @nt<enumeration_@!type_@!definition>, the corresponding enumeration literals are said to be @i(overloaded). At any place where an overloaded enumeration literal occurs in the text of a program, the type of the enumeration literal has to be determinable from the context (see @RefSecNum(The Context of Overload Resolution)).] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(enumeration_type_definition)} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} The elaboration of an @nt<enumeration_type_definition> creates the enumeration type and its first subtype, which is constrained to the base range of the type. @begin{Ramification} The first subtype of a discrete type is always constrained, except in the case of a derived type whose parent subtype is Whatever'Base. @end{Ramification} When called, the parameterless function associated with an enumeration literal returns the corresponding value of the enumeration type. @end{RunTime} @begin{Notes} If an enumeration literal occurs in a context that does not otherwise suffice to determine the type of the literal, then qualification by the name of the enumeration type is one way to resolve the ambiguity (see @RefSecNum(Qualified Expressions)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of enumeration types and subtypes: ) @begin(Example) @key(type) Day @key(is) (Mon, Tue, Wed, Thu, Fri, Sat, Sun); @key(type) Suit @key(is) (Clubs, Diamonds, Hearts, Spades); @key(type) Gender @key(is) (M, F); @key(type) Level @key(is) (Low, Medium, Urgent); @key(type) Color @key(is) (White, Red, Yellow, Green, Blue, Brown, Black); @key(type) Light @key(is) (Red, Amber, Green); --@RI[ Red and Green are overloaded] @key(type) Hexa @key(is) ('A', 'B', 'C', 'D', 'E', 'F'); @key(type) Mixed @key(is) ('A', 'B', '*', B, None, '?', '%'); @key(subtype) Weekday @key(is) Day @key(range) Mon .. Fri; @key(subtype) Major @key(is) Suit @key(range) Hearts .. Spades; @key(subtype) Rainbow @key(is) Color @key(range) Red .. Blue; --@RI[ the Color Red, not the Light] @end(Example) @end{Examples} @begin{DiffWord83} The syntax rule for @nt{defining_character_literal} is new. It is used for the defining occurrence of a @nt{character_literal}, analogously to @nt{defining_identifier}. Usage occurrences use the @nt{name} or @nt{selector_name} syntactic categories. We emphasize the fact that an enumeration literal denotes a function, which is called to produce a value. @end{DiffWord83} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0227-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Required that all enumeration literals in a type have distinct images; this might not be the case since upper case conversion can map distinct characters to the same upper case character. This can only happen for identifiers using Unicode characters first allowed by Ada 2005; moreover, the original definition of Ada 2005 was confused and appeared to require inconsistent results from the Image attribute, so implementations that allowed problematic cases are rare; the problematic cases are very rare; so it is expected that this change would only affect test programs.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0006-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined the result subtype of an enumeration literal to close a minor language hole.]} @end{DiffWord2005} @LabeledSubClause{Character Types} @begin{StaticSem} @Defn{character type} An enumeration type is said to be a @i(character type) if at least one of its enumeration literals is a @nt<character_literal>. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0181-1],ARef=[AI05-0262-1],ARef=[AI05-0266-1]} @Defn{Latin-1} @Defn{BMP} @Chg{Version=[2],New=[@Chg{Version=[3],New=[@Defn{ISO/IEC 10646:2011}], Old=[@Defn{ISO/IEC 10646:2003}]}],Old=[@Defn{ISO 10646}]} @Defn{Character} The predefined type Character is a character type whose values correspond to the 256 code @Chg{Version=[3],New=[points],Old=[positions]} of Row 00 (also known as Latin-1) of the @Chg{Version=[2],New=[ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}],Old=[ISO 10646]} Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding @nt<character_literal> in Character. Each of the nongraphic @Chg{Version=[3],New=[characters],Old=[positions]} of Row 00@Chg{Version=[3],New=[],Old=[ (0000-001F and 007F-009F)]} has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes @Chg{Version=[2],New=[Image, Wide_Image, Wide_Wide_Image, Value, Wide_Value, and Wide_Wide_Value], Old=[(Wide_)Image and (Wide_)Value]}; these names are given in the definition of type Character in @RefSec{The Package Standard}, but are set in @i{italics}. @Defn2{Term=[italics],Sec=(nongraphic characters)} @Chg{Version=[3],New=[@PDefn2{Term=[code point],Sec=[for characters]}],Old=[]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@i{Code point} is defined in ISO/IEC 10646:2011.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @Defn{Wide_Character} @Defn{BMP} @Chg{Version=[2],New=[@Chg{Version=[3],New=[@Defn{ISO/IEC 10646:2011}], Old=[@Defn{ISO/IEC 10646:2003}]}],Old=[@Defn{ISO 10646}]} The predefined type Wide_Character is a character type whose values correspond to the 65536 code @Chg{Version=[3],New=[points],Old=[positions]} of the @Chg{Version=[2], New=[ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]}],Old=[ISO 10646]} Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding @nt<character_literal> in Wide_Character. The first 256 values of Wide_Character have the same @nt<character_literal> or language-defined name as defined for Character. @Chg{Version=[2],New=[Each of the @ntf{graphic_character}s has],Old=[The last 2 values of Wide_Character correspond to the nongraphic positions FFFE and FFFF of the BMP, and are assigned the language-defined names @i(FFFE) and @i(FFFF). As with the other language-defined names for nongraphic characters, the names @i(FFFE) and @i(FFFF) are usable only with the attributes (Wide_)Image and (Wide_)Value; they are not usable as enumeration literals. All other values of Wide_Character are considered graphic characters, and have]} a corresponding @nt<character_literal>. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Defn{Wide_Wide_Character} @Chg{Version=[2],New=[@Chg{Version=[3],New=[@Defn{ISO/IEC 10646:2011}], Old=[@Defn{ISO/IEC 10646:2003}]}],Old=[@Defn{ISO 10646}]} The predefined type Wide_Wide_Character is a character type whose values correspond to the 2147483648 code @Chg{Version=[3],New=[points],Old=[positions]} of the ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} character set. Each of the @ntf{graphic_character}s has a corresponding @nt{character_literal} in Wide_Wide_Character. The first 65536 values of Wide_Wide_Character have the same @nt{character_literal} or language-defined name as defined for Wide_Character.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The characters whose code @Chg{Version=[3],New=[point],Old=[position]} is larger than 16#FF# and which are not @ntf{graphic_character}s have language-defined names which are formed by appending to the string "Hex_" the representation of their code @Chg{Version=[3],New=[point],Old=[position]} in hexadecimal as eight extended digits. As with other language-defined names, these names are usable only with the attributes (Wide_)Wide_Image and (Wide_)Wide_Value; they are not usable as enumeration literals.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The language-defined names are not usable as enumeration literals to avoid "polluting" the name space. Since Wide_Character @Chg{Version=[2],New=[and Wide_Wide_Character ],Old=[]}are defined in Standard, if the @Chg{Version=[2],New=[language-defined ], Old=[]}names @Chg{Version=[2],New=[],Old=[FFFE and FFFF ]}were usable as enumeration literals, they would hide other nonoverloadable declarations with the same names in @key[use]-d packages.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[ISO 10646 has not defined the meaning of all of the code positions from 0100 through FFFD, but they are all considered graphic characters by Ada to simplify the implementation, and to allow for revisions to ISO 10646. In ISO 10646, FFFE and FFFF are special, and will never be associated with graphic characters in any revision.]} @end{Reason} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{localization} In a nonstandard mode, an implementation may provide other interpretations for the predefined types Character and Wide_Character@Redundant[, to conform to local conventions].]} @end{ImplPerm} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 6 and 7 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[@Defn{localization} If an implementation supports a mode with alternative interpretations for Character and Wide_Character, the set of graphic characters of Character should nevertheless remain a proper subset of the set of graphic characters of Wide_Character. Any character set @lquotes@;localizations@rquotes@; should be reflected in the results of the subprograms defined in the language-defined package Characters.Handling (see @RefSecNum{Character Handling}) available in such a mode. In a mode with an alternative interpretation of Character, the implementation should also support a corresponding change in what is a legal @ntf<identifier_letter>.]} @ChgNote{We won't add an ChgImplAdvice here, because we would need to add and remove it in the same command.} @end{ImplAdvice} @begin{Notes} The language-defined library package Characters.Latin_1 (see @RefSecNum(The Package Characters.Latin_1)) includes the declaration of constants denoting control characters, lower case characters, and special characters of the predefined type Character. @begin{Honest} The package ASCII does the same, but only for the first 128 characters of Character. Hence, it is an obsolescent package, and we no longer mention it here. @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} A conventional character set such as @i(EBCDIC) can be declared as a character type; the internal codes of the characters can be specified by an @nt<enumeration_representation_clause> as explained in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Enumeration Representation Clauses). @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a character type: ) @begin(Example) @key(type) Roman_Digit @key(is) ('I', 'V', 'X', 'L', 'C', 'D', 'M'); @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The declaration of Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the unlikely event that an Ada 83 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Character, the meaning of the program will be different. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The presence of Wide_Character in package Standard means that an expression such as @begin(Example) 'a' = 'b' @end(Example) is ambiguous in Ada 95, whereas in Ada 83 both literals could be resolved to be of type Character. The change in visibility rules (see @RefSecNum(Literals)) for character literals means that additional qualification might be necessary to resolve expressions involving overloaded subprograms and character literals. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The type Character has been extended to have 256 positions, and the type Wide_Character has been added. Note that this change was already approved by the ARG for Ada 83 conforming compilers. The rules for referencing character literals are changed (see @RefSecNum(Literals)), so that the declaration of the character type need not be directly visible to use its literals, similar to @b(null) and string literals. Context is used to resolve their type. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Ada 95 defined most characters in Wide_Character to be graphic characters, while Ada 2005 uses the categorizations from ISO-10646:2003. It also provides language-defined names for all nongraphic characters. That means that in Ada 2005, Wide_Character'Wide_Value will raise Constraint_Error for a string representing a @nt{character_literal} of a nongraphic character, while Ada 95 would have accepted it. Similarly, the result of Wide_Character'Wide_Image will change for such nongraphic characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The language-defined names FFFE and FFFF were replaced by a consistent set of language-defined names for all nongraphic characters with @Chg{Version=[3],New=[code points],Old=[positions]} greater than 16#FF#. That means that in Ada 2005, Wide_Character'Wide_Value("FFFE") will raise Constraint_Error while Ada 95 would have accepted it. Similarly, the result of Wide_Character'Wide_Image will change for the position numbers 16#FFFE# and 16#FFFF#. It is very unlikely that this will matter in practice, as these names do not represent @Chg{Version=[3],New=[usable],Old=[useable]} characters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Because of the previously mentioned changes to the Wide_Character'Wide_Image of various character values, the value of attribute Wide_Width will change for some subtypes of Wide_Character. However, the new language-defined names were chosen so that the value of Wide_Character'Wide_Width itself does not change.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The declaration of Wide_Wide_Character in package Standard hides use-visible declarations with the same defining identifier. In the (very) unlikely event that an Ada 95 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Wide_Character, the meaning of the program will be different.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The type Wide_Wide_Character is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Characters are now defined in terms of the entire ISO/IEC 10646:2003 character set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[We dropped the @ImplAdviceTitle for @Chg{Version=[3],New=[nonstandard],Old=[non-standard]} interpretation of character sets; an implementation can do what it wants in a @Chg{Version=[3],New=[nonstandard],Old=[non-standard]} mode, so there isn't much point to any advice.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0181-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Removed the position numbers of nongraphic characters from the text, as it is wrong and thus misleading.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Changed "code position" to "code point" consistently throughout the standard, as ISO/IEC 10646:2011 prefers "code point" and we are referring to the definition in that Standard. This change also reduces confusion between "code point" and "position number"; while these have the same values for the predefined character types, there is no required relationship for other character types.@PDefn2{Term=[code point],Sec=[for characters]}]} @end{DiffWord2005} @LabeledSubClause{Boolean Types} @begin{StaticSem} @Defn{Boolean} There is a predefined enumeration type named Boolean, @Redundant[declared in the visible part of package Standard]. @Defn{False} @Defn{True} It has the two enumeration literals False and True ordered with the relation False < True. @Defn{boolean type} Any descendant of the predefined type Boolean is called a @i(boolean) type. @begin{ImplNote} An implementation is not required to support enumeration representation clauses on boolean types that impose an unacceptable implementation burden. See @RefSec(Enumeration Representation Clauses). However, it is generally straightforward to support representations where False is zero and True is 2**n @en@; 1 for some n. @end{ImplNote} @end{StaticSem} @LabeledSubClause{Integer Types} @begin{Intro} @Defn{integer type} @Defn{signed integer type} @Defn{modular type} An @nt<integer_type_definition> defines an integer type; it defines either a @i(signed) integer type, or a @i(modular) integer type. The base range of a signed integer type includes at least the values of the specified range. A modular type is an integer type with all arithmetic modulo a specified positive @i(modulus); such a type corresponds to an unsigned type with wrap-around semantics. @IndexSee{Term=[unsigned type],See=(modular type)} @end{Intro} @begin{Syntax} @Syn{lhs=<integer_type_definition>, rhs="@Syn2{signed_integer_type_definition} | @Syn2{modular_type_definition}"} @Syn{lhs=<signed_integer_type_definition>, rhs="@key(range) @SynI{static_}@Syn2{simple_expression} .. @SynI{static_}@Syn2{simple_expression}"} @begin{Discussion} We don't call this a @nt<range_constraint>, because it is rather different @em not only is it required to be static, but the associated overload resolution rules are different than for normal range constraints. A similar comment applies to @nt{real_range_specification}. This used to be @ntf<integer_range_specification> but when we added support for modular types, it seemed overkill to have three levels of syntax rules, and just calling these @ntf<signed_integer_range_specification> and @ntf<modular_range_specification> loses the fact that they are defining different classes of types, which is important for the generic type matching rules. @end{Discussion} @Syn{lhs=<modular_type_definition>, rhs="@key(mod) @SynI{static_}@Syn2{expression}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(signed_integer_type_definition simple_expression)} Each @nt<simple_expression> in a @nt<signed_integer_type_definition> is expected to be of any integer type; they need not be of the same type. @PDefn2{Term=[expected type], Sec=(modular_type_definition expression)} The @nt<expression> in a @nt<modular_type_definition> is likewise expected to be of any integer type. @end{Resolution} @begin{Legality} The @nt<simple_expression>s of a @nt<signed_integer_type_definition> shall be static, and their values shall be in the range System.Min_Int .. System.Max_Int. @Defn2{Term=[modulus], Sec=(of a modular type)} @Defn{Max_Binary_Modulus} @Defn{Max_Nonbinary_Modulus} The @nt<expression> of a @nt<modular_type_definition> shall be static, and its value (the @i(modulus)) shall be positive, and shall be no greater than System.Max_Binary_Modulus if a power of 2, or no greater than System.Max_Nonbinary_Modulus if not. @begin(Reason) For a 2's-complement machine, supporting nonbinary moduli greater than System.Max_Int can be quite difficult, whereas essentially any binary moduli are straightforward to support, up to 2*System.Max_Int+2, so this justifies having two separate limits. @end(Reason) @end{Legality} @begin{StaticSem} The set of values for a signed integer type is the (infinite) set of mathematical integers@Redundant[, though only values of the base range of the type are fully supported for run-time operations]. The set of values for a modular integer type are the values from 0 to one less than the modulus, inclusive. @PDefn2{Term=[base range], Sec=(of a signed integer type)} A @nt<signed_integer_type_definition> defines an integer type whose base range includes at least the values of the @nt<simple_expression>s and is symmetric about zero, excepting possibly an extra negative value. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<signed_integer_type_definition> also defines a constrained first subtype of the type, with a range whose bounds are given by the values of the @nt<simple_expression>s, converted to the type being defined. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The base range of a signed integer type might be much larger than is necessary to satisfy the @Chg{Version=[2],New=[above],Old=[aboved]} requirements. @end{ImplNote} @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of signed integer type)}]} @end{Honest} @PDefn2{Term=[base range], Sec=(of a modular type)} A @nt<modular_type_definition> defines a modular type whose base range is from zero to one less than the given modulus. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<modular_type_definition> also defines a constrained first subtype of the type with a range that is the same as the base range of the type. @Defn{Integer} There is a predefined signed integer subtype named Integer@Redundant[, declared in the visible part of package Standard]. It is constrained to the base range of its type. @begin{Reason} Integer is a constrained subtype, rather than an unconstrained subtype. This means that on assignment to an object of subtype Integer, a range check is required. On the other hand, an object of subtype Integer'Base is unconstrained, and no range check (only overflow check) is required on assignment. For example, if the object is held in an extended-length register, its value might be outside of Integer'First .. Integer'Last. All parameter and result subtypes of the predefined integer operators are of such unconstrained subtypes, allowing extended-length registers to be used as operands or for the result. In an earlier version of Ada 95, Integer was unconstrained. However, the fact that certain Constraint_Errors might be omitted or appear elsewhere was felt to be an undesirable upward inconsistency in this case. Note that for Float, the opposite conclusion was reached, partly because of the high cost of performing range checks when not actually necessary. Objects of subtype Float are unconstrained, and no range checks, only overflow checks, are performed for them. @end{Reason} @Leading@Defn{Natural} @Defn{Positive} Integer has two predefined subtypes, @Redundant[declared in the visible part of package Standard:] @begin{Example} @key[subtype] Natural @key[is] Integer @key[range] 0 .. Integer'Last; @key[subtype] Positive @key[is] Integer @key[range] 1 .. Integer'Last; @end{Example} @Defn{root_integer} @Defn{Min_Int} @Defn{Max_Int} A type defined by an @nt<integer_type_definition> is implicitly derived from @i(root_integer), an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_Int. However, the base range of the new type is not inherited from @i{root_integer}, but is instead determined by the range or modulus specified by the @nt{integer_type_definition}. @PDefn{universal_integer} @Defn{integer literals} @Redundant[Integer literals are all of the type @i(universal_integer), the universal type (see @RefSecNum(Derivation Classes)) for the class rooted at @i(root_integer), allowing their use with the operations of any integer type.] @begin{Discussion} This implicit derivation is not considered exactly equivalent to explicit derivation via a @nt<derived_type_definition>. In particular, integer types defined via a @nt<derived_type_definition> inherit their base range from their parent type. A type defined by an @nt<integer_type_definition> does not necessarily inherit its base range from @i(root_integer). It is not specified whether the implicit derivation from @i(root_integer) is direct or indirect, not that it really matters. All we want is for all integer types to be descendants of @i(root_integer). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0099],ARef=[AI95-00152-01]} @Chg{New=[Note that this derivation does not imply any inheritance of subprograms. Subprograms are inherited only for types derived by a @nt{derived_@!type_@!definition} (see @RefSecNum{Derived Types and Classes}), or a @nt{private_@!extension_@!declaration} (see @RefSecNum{Private Types and Private Extensions}, @RefSecNum{Private Operations}, and @RefSecNum{Formal Private and Derived Types}).],Old=[]} @end{Discussion} @begin{ImplNote} It is the intent that even nonstandard integer types (see below) will be descendants of @i(root_integer), even though they might have a base range that exceeds that of @i(root_integer). This causes no problem for static calculations, which are performed without range restrictions (see @RefSecNum(Static Expressions and Static Subtypes)). However for run-time calculations, it is possible that Constraint_Error might be raised when using an operator of @i(root_integer) on the result of 'Val applied to a value of a nonstandard integer type. @end{ImplNote} @PDefn2{Term=[position number], Sec=(of an integer value)} The @i(position number) of an integer value is equal to the value. @begin{WideAbove} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00340-01]} @Leading@keepnext@;For @PrefixType{every modular subtype S}, the following @Chg{Version=[2],New=[attributes are],Old=[attribute is]} defined: @end{WideAbove} @begin(description) @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Mod>, ARef=[AI95-00340-01], Text=[@Chg{Version=[2],New=[S'Mod denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key{function} S'Mod (@RI{Arg} : @RI{universal_integer}) @key{return} S'Base]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[This function returns @i{Arg} @key{mod} S'Modulus, as a value of the type of S.]}]}@Comment{end attribute Mod} @Attribute{Prefix=<S>, AttrName=<Modulus>, Text=[S'Modulus yields the modulus of the type of S, as a value of the type @i(universal_integer).]} @end(description) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(integer_type_definition)} The elaboration of an @nt<integer_type_definition> creates the integer type and its first subtype. For a modular type, if the result of the execution of a predefined operator (see @RefSecNum(Operators and Expression Evaluation)) is outside the base range of the type, the result is reduced modulo the modulus of the type to a value that is within the base range of the type. @IndexCheck{Overflow_Check} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For a signed integer type, the exception Constraint_Error is raised by the execution of an operation that cannot deliver the correct result because it is outside the base range of the type. @redundant[@IndexCheck{Division_Check} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For any integer type, Constraint_Error is raised by the operators "/", "@key(rem)", and "@key(mod)" if the right operand is zero.] @end{RunTime} @begin{ImplReq} @Defn{Integer} In an implementation, the range of Integer shall include the range @en@;2**15+1 .. +2**15@en@;1. @Defn{Long_Integer} If Long_Integer is predefined for an implementation, then its range shall include the range @en@;2**31+1 .. +2**31@en@;1. System.Max_Binary_Modulus shall be at least 2**16. @end{ImplReq} @begin{ImplPerm} For the execution of a predefined operation of a signed integer type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced. @begin{Discussion} Constraint_Error is never raised for operations on modular types, except for divide-by-zero (and @key[rem]/@key[mod]-by-zero). @end{Discussion} @Defn{Long_Integer} @Defn{Short_Integer} An implementation may provide additional predefined signed integer types@Redundant[, declared in the visible part of Standard], whose first subtypes have names of the form Short_Integer, Long_Integer, Short_Short_Integer, Long_Long_Integer, etc. Different predefined integer types are allowed to have the same base range. However, the range of Integer should be no wider than that of Long_Integer. Similarly, the range of Short_Integer (if provided) should be no wider than Integer. Corresponding recommendations apply to any other predefined integer types. There need not be a named integer type corresponding to each distinct base range supported by an implementation. The range of each first subtype should be the base range of its type. @ImplDef{The predefined integer types declared in Standard.} @Defn{nonstandard integer type} An implementation may provide @i(nonstandard integer types), descendants of @i(root_integer) that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by an @nt<integer_type_definition>. For example, a nonstandard integer type might have an asymmetric base range or it might not be allowed as an array or loop index (a very long integer). Any type descended from a nonstandard integer type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for @lquotes@;any integer type@rquotes@; are defined for a particular nonstandard integer type. @Redundant[In any case, such types are not permitted as @nt{explicit_generic_actual_parameter}s for formal scalar types @em see @RefSecNum(Formal Scalar Types).] @ImplDef{Any nonstandard integer types and the operators defined for them.} @PDefn2{Term=[one's complement], Sec=(modular types)} For a one's complement machine, the high bound of the base range of a modular type whose modulus is one less than a power of 2 may be equal to the modulus, rather than one less than the modulus. It is implementation defined for which powers of 2, if any, this permission is exercised. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0003],ARef=[AI95-00095-01]} @Chg{New=[For a one's complement machine, implementations may support nonbinary modulus values greater than System.Max_Nonbinary_Modulus. It is implementation defined which specific values greater than System.Max_Nonbinary_Modulus, if any, are supported.],Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[On a one's complement machine, the natural full word type would have a modulus of 2**Word_Size@en@;1. However, we would want to allow the all-ones bit pattern (which represents negative zero as a number) in logical operations. These permissions are intended to allow that and the natural modulus value without burdening implementations with supporting expensive modulus values.]} @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @Defn{Long_Integer} An implementation should support Long_Integer in addition to Integer if the target machine supports 32-bit (or longer) arithmetic. No other named integer subtypes are recommended for package Standard. Instead, appropriate named integer subtypes should be provided in the library package Interfaces (see @RefSecNum{The Package Interfaces}). @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Long_Integer should be declared in Standard if the target supports 32-bit arithmetic. No other named integer subtypes should be declared in Standard.]}]} @begin{ImplNote} To promote portability, implementations should explicitly declare the integer (sub)types Integer and Long_Integer in Standard, and leave other predefined integer types anonymous. For implementations that already support Byte_Integer, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Integer_8, Integer_16, etc. See @RefSecNum(The Package Interfaces). In any case, if the user declares a subtype (first or not) whose range fits in, for example, a byte, the implementation can store variables of the subtype in a single byte, even if the base range of the type is wider. @end{ImplNote} @PDefn2{Term=[two's complement],Sec=(modular types)} An implementation for a two's complement machine should support modular types with a binary modulus up to System.Max_Int*2+2. An implementation should support a nonbinary modulus up to Integer'Last. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For a two's complement target, modular types with a binary modulus up to System.Max_Int*2+2 should be supported. A nonbinary modulus up to Integer'Last should be supported.]}]} @begin{Reason} Modular types provide bit-wise "@key{and}", "@key{or}", "@key{xor}", and "@key{not}" operations. It is important for systems programming that these be available for all integer types of the target hardware. @end{Reason} @begin{Ramification} Note that on a one's complement machine, the largest supported modular type would normally have a nonbinary modulus. On a two's complement machine, the largest supported modular type would normally have a binary modulus. @end{Ramification} @begin{ImplNote} Supporting a nonbinary modulus greater than Integer'Last can impose an undesirable implementation burden on some machines. @end{ImplNote} @end{ImplAdvice} @begin{Notes} @PDefn{universal_integer} @Defn{integer literals} Integer literals are of the anonymous predefined integer type @i(universal_integer). Other integer types have no literals. However, the overload resolution rules (see @RefSec(The Context of Overload Resolution)) allow expressions of the type @i(universal_integer) whenever an integer type is expected. The same arithmetic operators are predefined for all signed integer types defined by a @nt<signed_integer_type_definition> (see @RefSec(Operators and Expression Evaluation)). For modular types, these same operators are predefined, plus bit-wise logical operators (@key(and), @key(or), @key(xor), and @key(not)). In addition, for the unsigned types declared in the language-defined package Interfaces (see @RefSecNum(The Package Interfaces)), functions are defined that provide bit-wise shifting and rotating. Modular types match a @nt{generic_formal_parameter_declaration} of the form "@key(type) T @key(is mod) <>;"; signed integer types match "@key(type) T @key(is range) <>;" (see @RefSecNum{Formal Scalar Types}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of integer types and subtypes: ) @begin(Example) @key(type) Page_Num @key(is) @key(range) 1 .. 2_000; @key(type) Line_Size @key(is) @key(range) 1 .. Max_Line_Size; @key(subtype) Small_Int @key(is) Integer @key(range) -10 .. 10; @key(subtype) Column_Ptr @key(is) Line_Size @key(range) 1 .. 10; @key(subtype) Buffer_Size @key(is) Integer @key(range) 0 .. Max; @key(type) Byte @key(is) @key(mod) 256; --@RI[ an unsigned byte] @key(type) Hash_Index @key(is) @key(mod) 97; --@RI[ modulus is prime] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} An implementation is allowed to support any number of distinct base ranges for integer types, even if fewer integer types are explicitly declared in Standard. Modular (unsigned, wrap-around) types are new. @end{Extend83} @begin{DiffWord83} Ada 83's integer types are now called "signed" integer types, to contrast them with "modular" integer types. Standard.Integer, Standard.Long_Integer, etc., denote constrained subtypes of predefined integer types, consistent with the Ada 95 model that only subtypes have names. We now impose minimum requirements on the base range of Integer and Long_Integer. We no longer explain integer type definition in terms of an equivalence to a normal type derivation, except to say that all integer types are by definition implicitly derived from @i(root_integer). This is for various reasons. First of all, the equivalence with a type derivation and a subtype declaration was not perfect, and was the source of various AIs (for example, is the conversion of the bounds static? Is a numeric type a derived type with respect to other rules of the language?) Secondly, we don't want to require that every integer size supported shall have a corresponding named type in Standard. Adding named types to Standard creates nonportabilities. Thirdly, we don't want the set of types that match a formal derived type "type T is new Integer;" to depend on the particular underlying integer representation chosen to implement a given user-defined integer type. Hence, we would have needed anonymous integer types as parent types for the implicit derivation anyway. We have simply chosen to identify only one anonymous integer type @em @i(root_integer), and stated that every integer type is derived from it. Finally, the @lquotes@;fiction@rquotes@; that there were distinct preexisting predefined types for every supported representation breaks down for fixed point with arbitrary smalls, and was never exploited for enumeration types, array types, etc. Hence, there seems little benefit to pushing an explicit equivalence between integer type definition and normal type derivation. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00340-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Mod attribute is new. It eases mixing of signed and unsigned values in an expression, which can be difficult as there may be no type which can contain all of the values of both of the types involved.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0003],ARef=[AI95-00095-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Added additional permissions for modular types on one's complement machines.],Old=[]} @end{DiffWord95} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Operations of Discrete Types} @begin{StaticSem} @Leading@;For @PrefixType{every discrete subtype S}, the following attributes are defined: @begin(description) @AttributeLeading{Prefix=<S>, AttrName=<Pos>, Text=[S'Pos denotes a function with the following specification: @begin(Descexample) @b(function) S'Pos(@RI(Arg) : S'Base) @b(return) @RI(universal_integer) @end(Descexample) @NoPrefix@;This function returns the position number of the value of @i(Arg), as a value of type @i(universal_integer).]} @AttributeLeading{Prefix=<S>, AttrName=<Val>, Text=[S'Val denotes a function with the following specification: @begin(Descexample) @b(function) S'Val(@RI(Arg) : @RI(universal_integer)) @b(return) S'Base @end(Descexample) @NoPrefix@PDefn2{Term=(evaluation), Sec=(Val)} @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} This function returns a value of the type of S whose position number equals the value of @i(Arg).]} @IndexCheck{Range_Check} For the evaluation of a call on S'Val, if there is no value in the base range of its type with the given position number, Constraint_Error is raised. @begin{Ramification} By the overload resolution rules, a formal parameter of type @i(universal_integer) allows an actual parameter of any integer type.@end{ramification} @begin{Reason} We considered allowing S'Val for a signed integer subtype S to return an out-of-range value, but since checks were required for enumeration and modular types anyway, the allowance didn't seem worth the complexity of the rule.@end{reason} @end(description) @EndPrefixType{} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0297-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For @PrefixType{every static discrete subtype S for which there exists at least one value belonging to S that satisfies any predicate of S}, the following attributes are defined:]} @begin(Description) @ChgAttribute{Version=[3],Kind=[Added],ChginAnnex=[T], Leading=<F>, Prefix=<S>, AttrName=<First_Valid>, ARef=[AI05-0297-1], Text=[@Chg{Version=[3],New=[S'First_Valid denotes the smallest value that belongs to S and satisfies the predicate of S. The value of this attribute is of the type of S.],Old=[]}]} @ChgAttribute{Version=[3],Kind=[Added],ChginAnnex=[T], Leading=<F>, Prefix=<S>, AttrName=<Last_Valid>, ARef=[AI05-0297-1], Text=[@Chg{Version=[3],New=[S'Last_Valid denotes the largest value that belongs to S and satisfies the predicate of S. The value of this attribute is of the type of S.],Old=[]}]} @end(Description) @EndPrefixType{} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0297-1]} @ChgAdded{Version=[3],Text=[@Redundant[First_Valid and Last_Valid @nt{attribute_reference}s are always static expressions. Any explicit predicate of S can only have been specified by a Static_Predicate aspect.]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An @nt{attribute_reference} is static if the prefix is a static subtype (see @RefSecNum{Static Expressions and Static Subtypes}), (true by definition) and any arguments are static (there are none). Similarly, a dynamic predicate always makes a subtype nonstatic. QED.]} @end{TheProof} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We require there to be at least one value so that these are always values of the subtype. (This sidesteps the question of what to return for a subtype with no values.)]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These attributes are intended primarily for use in the case where the Static_Predicate aspect of S has been specified; First and Last are equivalent if these are allowed and there is no predicate.]} @end{Discussion} @end{StaticSem} @begin{ImplAdvice} For the evaluation of a call on S'Pos for an enumeration subtype, if the value of the operand does not correspond to the internal code for any enumeration literal of its type @Redundant[(perhaps due to an uninitialized variable)], then the implementation should raise Program_Error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This is particularly important for enumeration types with noncontiguous internal codes specified by an @nt<enumeration_@!representation_@!clause>. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Program_Error should be raised for the evaluation of S'Pos for an enumeration type, if the value of the operand does not correspond to the internal code for any enumeration literal of the type.]}]} @begin{Reason} We say Program_Error here, rather than Constraint_Error, because the main reason for such values is uninitialized variables, and the normal way to indicate such a use (if detected) is to raise Program_Error. (Other reasons would involve the misuse of low-level features such as Unchecked_Conversion.) @end{Reason} @end{ImplAdvice} @begin{Notes} Indexing and loop iteration use values of discrete types. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @PDefn2{Term=[predefined operations],Sec=(of a discrete type)} The predefined operations of a discrete type include the assignment operation, qualification, the membership tests, and the relational operators; for a boolean type they include the short-circuit control forms and the logical operators; for an integer type they include type conversion to and from other numeric types, as well as the binary and unary adding operators @en@; and +, the multiplying operators, the unary operator @key(abs), and the exponentiation operator. The assignment operation is described in @RefSecNum(Assignment Statements). The other predefined operations are described in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Names and Expressions}. As for all types, objects of a discrete type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). @Leading@;For a subtype of a discrete type, the result delivered by the attribute Val might not belong to the subtype; similarly, the actual parameter of the attribute Pos need not belong to the subtype. The following relations are satisfied (in the absence of an exception) by these attributes: @begin(Example) S'Val(S'Pos(X)) = X S'Pos(S'Val(N)) = N @end(Example) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of attributes of discrete subtypes: ) @begin(Example) --@RI[ For the types and subtypes declared in subclause @RefSecNum(Enumeration Types) the following hold: ] -- Color'First = White, Color'Last = Black -- Rainbow'First = Red, Rainbow'Last = Blue -- Color'Succ(Blue) = Rainbow'Succ(Blue) = Brown -- Color'Pos(Blue) = Rainbow'Pos(Blue) = 4 -- Color'Val(0) = Rainbow'Val(0) = White @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The attributes S'Succ, S'Pred, S'Width, S'Image, and S'Value have been generalized to apply to real types as well (see @RefSec{Scalar Types}). @end{Extend83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0297-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The attributes S'First_Valid and S'Last_Valid are new.]} @end{Extend2005} @LabeledSubClause{Real Types} @begin{Intro} @Defn{real type} Real types provide approximations to the real numbers, with relative bounds on errors for floating point types, and with absolute bounds for fixed point types. @end{Intro} @begin{Syntax} @Syn{lhs=<real_type_definition>,rhs=" @Syn2{floating_point_definition} | @Syn2{fixed_point_definition}"} @end{Syntax} @begin{StaticSem} @Defn{root_real} A type defined by a @nt<real_type_definition> is implicitly derived from @i(root_real), an anonymous predefined (specific) real type. @Redundant[Hence, all real types, whether floating point or fixed point, are in the derivation class rooted at @i(root_real).] @begin{Ramification} It is not specified whether the derivation from @i(root_real) is direct or indirect, not that it really matters. All we want is for all real types to be descendants of @i(root_real). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0099],ARef=[AI95-00152-01]} @Chg{New=[Note that this derivation does not imply any inheritance of subprograms. Subprograms are inherited only for types derived by a @nt{derived_@!type_@!definition} (see @RefSecNum{Derived Types and Classes}), or a @nt{private_@!extension_@!declaration} (see @RefSecNum{Private Types and Private Extensions}, @RefSecNum{Private Operations}, and @RefSecNum{Formal Private and Derived Types}).],Old=[]} @end{Ramification} @redundant[@PDefn{universal_real} @Defn{real literals} Real literals are all of the type @i(universal_real), the universal type (see @RefSecNum(Derivation Classes)) for the class rooted at @i(root_real), allowing their use with the operations of any real type. @PDefn{universal_fixed} Certain multiplying operators have a result type of @i(universal_fixed) (see @RefSecNum{Multiplying Operators}), the universal type for the class of fixed point types, allowing the result of the multiplication or division to be used where any specific fixed point type is expected.] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(real_type_definition)} The elaboration of a @nt<real_type_definition> consists of the elaboration of the @nt<floating_point_definition> or the @nt<fixed_point_definition>. @end{RunTime} @begin{ImplReq} An implementation shall perform the run-time evaluation of a use of a predefined operator of @i(root_real) with an accuracy at least as great as that of any floating point type definable by a @nt<floating_point_definition>. @begin{Ramification} Static calculations using the operators of @i(root_real) are exact, as for all static calculations. See @RefSecNum(Static Expressions and Static Subtypes). @end{Ramification} @begin(ImplNote) The Digits attribute of the type used to represent @i(root_real) at run time is at least as great as that of any other floating point type defined by a @nt<floating_point_definition>, and its safe range includes that of any such floating point type with the same Digits attribute. On some machines, there might be real types with less accuracy but a wider range, and hence run-time calculations with @i(root_real) might not be able to accommodate all values that can be represented at run time in such floating point or fixed point types. @end(ImplNote) @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @Redundant[For the execution of a predefined operation of a real type, the implementation need not raise Constraint_Error if the result is outside the base range of the type, so long as the correct result is produced, or the Machine_Overflows attribute of the type is @Chg{Version=[2], New=[False],Old=[false]} (see @RefSecNum{Numeric Performance Requirements}).] @Defn{nonstandard real type} An implementation may provide @i(nonstandard real types), descendants of @i(root_real) that are declared outside of the specification of package Standard, which need not have all the standard characteristics of a type defined by a @nt<real_type_definition>. For example, a nonstandard real type might have an asymmetric or unsigned base range, or its predefined operations might wrap around or @lquotes@;saturate@rquotes@; rather than overflow (modular or saturating arithmetic), or it might not conform to the accuracy model (see @RefSecNum{Numeric Performance Requirements}). Any type descended from a nonstandard real type is also nonstandard. An implementation may place arbitrary restrictions on the use of such types; it is implementation defined whether operators that are predefined for @lquotes@;any real type@rquotes@; are defined for a particular nonstandard real type. @Redundant[In any case, such types are not permitted as @nt{explicit_generic_actual_parameter}s for formal scalar types @em see @RefSecNum(Formal Scalar Types).] @ImplDef{Any nonstandard real types and the operators defined for them.} @end{ImplPerm} @begin{Notes} As stated, real literals are of the anonymous predefined real type @i(universal_real). Other real types have no literals. However, the overload resolution rules (see @RefSecNum(The Context of Overload Resolution)) allow expressions of the type @i(universal_real) whenever a real type is expected. @end{Notes} @begin{DiffWord83} The syntax rule for @nt{real_type_definition} is modified to use the new syntactic categories @nt{floating_point_definition} and @nt{fixed_point_definition}, instead of @ntf{floating_point_constraint} and @ntf{fixed_point_constraint}, because the semantics of a type definition are significantly different than the semantics of a constraint. All discussion of model numbers, safe ranges, and machine numbers is moved to @RefSecNum{Floating Point Types}, @RefSecNum{Operations of Floating Point Types}, and @RefSecNum{Numeric Performance Requirements}. Values of a fixed point type are now described as being multiples of the @i(small) of the fixed point type, and we have no need for model numbers, safe ranges, etc. for fixed point types. @end{DiffWord83} @LabeledSubClause{Floating Point Types} @begin{Intro} @Defn{floating point type} For floating point types, the error bound is specified as a relative precision by giving the required minimum number of significant decimal digits. @end{Intro} @begin{Syntax} @Syn{lhs=<floating_point_definition>,rhs=" @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{real_range_specification}]"} @Syn{lhs=<real_range_specification>,rhs=" @key{range} @SynI{static_}@Syn2{simple_expression} .. @SynI{static_}@Syn2{simple_expression}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[requested decimal precision], Sec=(of a floating point type)} The @i(requested decimal precision), which is the minimum number of significant decimal digits required for the floating point type, is specified by the value of the @nt<expression> given after the reserved word @key(digits). @PDefn2{Term=[expected type], Sec=(requested decimal precision)} This @nt<expression> is expected to be of any integer type. @PDefn2{Term=[expected type], Sec=(real_range_specification bounds)} Each @nt<simple_expression> of a @nt<real_range_specification> is expected to be of any real type@Redundant[; the types need not be the same]. @end{Resolution} @begin{Legality} @Defn{Max_Base_Digits} The requested decimal precision shall be specified by a static @nt<expression> whose value is positive and no greater than System.Max_Base_Digits. Each @nt<simple_expression> of a @nt<real_range_specification> shall also be static. @Defn{Max_Digits} If the @nt<real_range_specification> is omitted, the requested decimal precision shall be no greater than System.Max_Digits. @begin(Reason) We have added Max_Base_Digits to package System. It corresponds to the requested decimal precision of @i(root_real). System.Max_Digits corresponds to the maximum value for Digits that may be specified in the absence of a @nt<real_range_specification>, for upward compatibility. These might not be the same if @i<root_real> has a base range that does not include @PorM 10.0**(4*Max_Base_Digits). @end(Reason) A @nt<floating_point_definition> is illegal if the implementation does not support a floating point type that satisfies the requested decimal precision and range. @ImplDef{What combinations of requested decimal precision and range are supported for floating point types.} @end{Legality} @begin{StaticSem} The set of values for a floating point type is the (infinite) set of rational numbers. @Defn2{Term=[machine numbers], Sec=(of a floating point type)} The @i(machine numbers) of a floating point type are the values of the type that can be represented exactly in every unconstrained variable of the type. @PDefn2{Term=[base range], Sec=(of a floating point type)} The base range (see @RefSecNum{Scalar Types}) of a floating point type is symmetric around zero, except that it can include some extra negative values in some implementations.@begin{ImplNote} For example, if a 2's complement representation is used for the mantissa rather than a sign-mantissa or 1's complement representation, then there is usually one extra negative machine number.@end{implnote} @begin{Honest} If the Signed_Zeros attribute is True, then minus zero could in a sense be considered a value of the type. However, for most purposes, minus zero behaves the same as plus zero. @end{Honest} @Defn2{Term=[base decimal precision], Sec=(of a floating point type)} The @i(base decimal precision) of a floating point type is the number of decimal digits of precision representable in objects of the type. @Defn2{Term=[safe range], Sec=(of a floating point type)} The @i(safe range) of a floating point type is that part of its base range for which the accuracy corresponding to the base decimal precision is preserved by all predefined operations. @begin{ImplNote} In most cases, the safe range and base range are the same. However, for some hardware, values near the boundaries of the base range might result in excessive inaccuracies or spurious overflows when used with certain predefined operations. For such hardware, the safe range would omit such values.@end{implnote} @PDefn2{Term=[base decimal precision], Sec=(of a floating point type)} A @nt<floating_point_definition> defines a floating point type whose base decimal precision is no less than the requested decimal precision. @PDefn2{Term=[safe range], Sec=(of a floating point type)} @PDefn2{Term=[base range], Sec=(of a floating point type)} If a @nt<real_range_specification> is given, the safe range of the floating point type (and hence, also its base range) includes at least the values of the simple expressions given in the @nt<real_range_specification>. If a @nt<real_range_specification> is not given, the safe (and base) range of the type includes at least the values of the range @en@;10.0**(4*D) .. +10.0**(4*D) where D is the requested decimal precision. @Redundant[The safe range might include other values as well. The attributes Safe_First and Safe_Last give the actual bounds of the safe range.] A @nt<floating_point_definition> also defines a first subtype of the type. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} If a @nt<real_range_specification> is given, then the subtype is constrained to a range whose bounds are given by a conversion of the values of the @nt<simple_expression>s of the @nt<real_range_specification> to the type being defined. Otherwise, the subtype is unconstrained. @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a floating point type)}]} @end{Honest} @Defn{Float} There is a predefined, unconstrained, floating point subtype named Float@Redundant[, declared in the visible part of package Standard]. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(floating_point_definition)} @Redundant[The elaboration of a @nt<floating_point_definition> creates the floating point type and its first subtype.] @end{RunTime} @begin{ImplReq} @Defn{Float} In an implementation that supports floating point types with 6 or more digits of precision, the requested decimal precision for Float shall be at least 6. @Defn{Long_Float} If Long_Float is predefined for an implementation, then its requested decimal precision shall be at least 11. @end{ImplReq} @begin{ImplPerm} @Defn{Short_Float} @Defn{Long_Float} An implementation is allowed to provide additional predefined floating point types@Redundant[, declared in the visible part of Standard], whose (unconstrained) first subtypes have names of the form Short_Float, Long_Float, Short_Short_Float, Long_Long_Float, etc. Different predefined floating point types are allowed to have the same base decimal precision. However, the precision of Float should be no greater than that of Long_Float. Similarly, the precision of Short_Float (if provided) should be no greater than Float. Corresponding recommendations apply to any other predefined floating point types. There need not be a named floating point type corresponding to each distinct base decimal precision supported by an implementation. @ImplDef{The predefined floating point types declared in Standard.} @end{ImplPerm} @begin{ImplAdvice} @Defn{Long_Float} An implementation should support Long_Float in addition to Float if the target machine supports 11 or more digits of precision. No other named floating point subtypes are recommended for package Standard. Instead, appropriate named floating point subtypes should be provided in the library package Interfaces (see @RefSecNum(The Package Interfaces)). @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Long_Float should be declared in Standard if the target supports 11 or more digits of precision. No other named float subtypes should be declared in Standard.]}]} @begin{ImplNote} To promote portability, implementations should explicitly declare the floating point (sub)types Float and Long_Float in Standard, and leave other predefined float types anonymous. For implementations that already support Short_Float, etc., upward compatibility argues for keeping such declarations in Standard during the transition period, but perhaps generating a warning on use. A separate package Interfaces in the predefined environment is available for pre-declaring types such as Float_32, IEEE_Float_64, etc. See @RefSecNum(The Package Interfaces). @end{ImplNote} @end{ImplAdvice} @begin{Notes} If a floating point subtype is unconstrained, then assignments to variables of the subtype involve only Overflow_Checks, never Range_Checks. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of floating point types and subtypes:) @begin(Example) @key(type) Coefficient @key(is) @key(digits) 10 @key(range) -1.0 .. 1.0; @key(type) Real @key(is) @key(digits) 8; @key(type) Mass @key(is) @key(digits) 7 @key(range) 0.0 .. 1.0E35; @key(subtype) Probability @key(is) Real @key(range) 0.0 .. 1.0; --@RI[ a subtype with a smaller range] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} No Range_Checks, only Overflow_Checks, are performed on variables (or parameters) of an unconstrained floating point subtype. This is upward compatible for programs that do not raise Constraint_Error. For those that do raise Constraint_Error, it is possible that the exception will be raised at a later point, or not at all, if extended range floating point registers are used to hold the value of the variable (or parameter). @begin(Reason) This change was felt to be justified by the possibility of improved performance on machines with extended-range floating point registers. An implementation need not take advantage of this relaxation in the range checking; it can hide completely the use of extended range registers if desired, presumably at some run-time expense. @end(Reason) @end{Inconsistent83} @begin{DiffWord83} The syntax rules for @ntf{floating_point_constraint} and @ntf{floating_accuracy_definition} are removed. The syntax rules for @nt{floating_point_definition} and @nt{real_range_specification} are new. A syntax rule for @nt<digits_constraint> is given in @RefSec{Fixed Point Types}. In @RefSecNum{Reduced Accuracy Subtypes} we indicate that a @nt<digits_constraint> may be applied to a floating point @nt<subtype_mark> as well (to be compatible with Ada 83's @ntf<floating_point_constraint>). Discussion of model numbers is postponed to @RefSecNum{Operations of Floating Point Types} and @RefSecNum{Numeric Performance Requirements}. The concept of safe numbers has been replaced by the concept of the safe range of values. The bounds of the safe range are given by T'Safe_First .. T'Safe_Last, rather than -T'Safe_Large .. T'Safe_Large, since on some machines the safe range is not perfectly symmetric. The concept of machine numbers is new, and is relevant to the definition of Succ and Pred for floating point numbers. @end{DiffWord83} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Operations of Floating Point Types} @begin{StaticSem} @Leading@;The following attribute is defined for @PrefixType{every floating point subtype S}: @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<Digits>, Ref=[8652/0004], ARef=[AI95-00203-01], Text=[S'Digits denotes the requested decimal precision for the subtype S. The value of this attribute is of the type @i(universal_integer).]} The requested decimal precision of the base subtype of a floating point type @i{T} is defined to be the largest value of @i{d} for which @chg{New=[@*],Old=[]} ceiling(@i{d} * log(10) / log(T'Machine_Radix)) + @Chg{New=[@i{g}],Old=[1]} <= T'Model_Mantissa@Chg{New=[@* where g is 0 if Machine_Radix is a positive power of 10 and 1 otherwise],Old=[]}. @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} @PDefn2{Term=[predefined operations],Sec=(of a floating point type)} The predefined operations of a floating point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators @en@; and +, certain multiplying operators, the unary operator @key(abs), and the exponentiation operator. As for all types, objects of a floating point type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). Other attributes of floating point types are defined in @RefSecNum{Attributes of Floating Point Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0004],ARef=[AI95-00203-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the formula for Digits when the Machine_Radix is 10.]} @end{DiffWord95} @LabeledSubClause{Fixed Point Types} @begin{Intro} @Defn{fixed point type} @Defn{ordinary fixed point type} @Defn{decimal fixed point type} A fixed point type is either an ordinary fixed point type, or a decimal fixed point type. @Defn2{Term=[delta], Sec=(of a fixed point type)} The error bound of a fixed point type is specified as an absolute value, called the @i(delta) of the fixed point type. @end{Intro} @begin{Syntax} @Syn{lhs=<fixed_point_definition>,rhs="@Syn2{ordinary_fixed_point_definition} | @Syn2{decimal_fixed_point_definition}"} @Syn{lhs=<ordinary_fixed_point_definition>,rhs=" @key{delta} @SynI{static_}@Syn2{expression} @Syn2{real_range_specification}"} @Syn{lhs=<decimal_fixed_point_definition>,rhs=" @key{delta} @SynI{static_}@Syn2{expression} @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{real_range_specification}]"} @Syn{lhs=<digits_constraint>,rhs=" @key{digits} @SynI{static_}@Syn2{expression} [@Syn2{range_constraint}]"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(fixed point type delta)} For a type defined by a @nt<fixed_point_definition>, the @i(delta) of the type is specified by the value of the @nt<expression> given after the reserved word @key(delta); this @nt<expression> is expected to be of any real type. @PDefn2{Term=[expected type], Sec=(decimal fixed point type digits)} @Defn2{Term=[digits], Sec=(of a decimal fixed point subtype)} @Defn{decimal fixed point type} For a type defined by a @nt<decimal_fixed_point_definition> (a @i(decimal) fixed point type), the number of significant decimal digits for its first subtype (the @i(digits) of the first subtype) is specified by the @nt<expression> given after the reserved word @key(digits); this @nt<expression> is expected to be of any integer type. @end{Resolution} @begin{Legality} In a @nt<fixed_point_definition> or @nt<digits_constraint>, the @nt<expression>s given after the reserved words @key(delta) and @key(digits) shall be static; their values shall be positive. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00100-01]} @Defn2{Term=[small], Sec=(of a fixed point type)} The set of values of a fixed point type comprise the integral multiples of a number called the @i(small) of the type.@Chg{Version=[2],New=[@PDefn2{Term=[machine numbers],Sec=[of a fixed point type]} The @i{machine numbers} of a fixed point type are the values of the type that can be represented exactly in every unconstrained variable of the type.],Old=[]} @Defn{ordinary fixed point type} For a type defined by an @nt<ordinary_fixed_point_definition> (an @i(ordinary) fixed point type), the @i(small) may be specified by an @nt<attribute_@!definition_@!clause> (see @RefSecNum{Operational and Representation Attributes}); if so specified, it shall be no greater than the @i(delta) of the type. If not specified, the @i(small) of an ordinary fixed point type is an implementation-defined power of two less than or equal to the @i(delta). @ImplDef{The @i(small) of an ordinary fixed point type.} For a decimal fixed point type, the @i(small) equals the @i(delta); the @i(delta) shall be a power of 10. If a @nt<real_range_specification> is given, both bounds of the range shall be in the range @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). A @nt<fixed_point_definition> is illegal if the implementation does not support a fixed point type with the given @i(small) and specified range or @i(digits). @ImplDef{What combinations of @i(small), range, and @i(digits) are supported for fixed point types.} For a @nt<subtype_indication> with a @nt<digits_constraint>, the @nt<subtype_mark> shall denote a decimal fixed point subtype. @begin(Honest) Or, as an obsolescent feature, a floating point subtype is permitted @em see @RefSecNum(Reduced Accuracy Subtypes). @end(Honest) @end{Legality} @begin{StaticSem} @PDefn2{Term=[base range], Sec=(of a fixed point type)} The base range (see @RefSecNum{Scalar Types}) of a fixed point type is symmetric around zero, except possibly for an extra negative value in some implementations. @Leading@PDefn2{Term=[base range], Sec=(of an ordinary fixed point type)} An @nt<ordinary_fixed_point_definition> defines an ordinary fixed point type whose base range includes at least all multiples of @i(small) that are between the bounds specified in the @nt<real_range_specification>. The base range of the type does not necessarily include the specified bounds themselves. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} An @nt<ordinary_@!fixed_@!point_@!definition> also defines a constrained first subtype of the type, with each bound of its range given by the closer to zero of: @begin(itemize) the value of the conversion to the fixed point type of the corresponding @nt<expression> of the @nt<real_range_specification>; @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a fixed point type)} @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a fixed point type)}]} @end{Honest} the corresponding bound of the base range. @end(itemize) @PDefn2{Term=[base range], Sec=(of a decimal fixed point type)} A @nt<decimal_fixed_point_definition> defines a decimal fixed point type whose base range includes at least the range @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt<decimal_fixed_point_definition> also defines a constrained first subtype of the type. If a @nt<real_range_specification> is given, the bounds of the first subtype are given by a conversion of the values of the @nt<expression>s of the @nt<real_range_specification>. @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a decimal fixed point type)} Otherwise, the range of the first subtype is @en@;(10**@i(digits)@en@;1)*@i(delta) .. +(10**@i(digits)@en@;1)*@i(delta). @begin{Honest} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{This is discussed in AC-00002, which we can't reference here} @ChgAdded{Version=[1],Text=[The conversion mentioned above is not an @i{implicit subtype conversion} (which is something that happens at overload resolution, see @RefSecNum{Type Conversions}), although it happens implicitly. Therefore, the freezing rules are not invoked on the type (which is important so that representation items can be given for the type). @PDefn2{Term=[subtype conversion],Sec=(bounds of a decimal fixed point type)}]} @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(fixed_point_definition)} The elaboration of a @nt<fixed_point_definition> creates the fixed point type and its first subtype. For a @nt<digits_constraint> on a decimal fixed point subtype with a given @i(delta), if it does not have a @nt<range_constraint>, then it specifies an implicit range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta), where @i(D) is the value of the @nt<expression>. @Defn2{Term=[compatibility], Sec=(digits_constraint with a decimal fixed point subtype)} A @nt<digits_constraint> is @i(compatible) with a decimal fixed point subtype if the value of the @nt<expression> is no greater than the @i(digits) of the subtype, and if it specifies (explicitly or implicitly) a range that is compatible with the subtype. @begin(Discussion) Except for the requirement that the @i(digits) specified be no greater than the @i(digits) of the subtype being constrained, a @nt<digits_constraint> is essentially equivalent to a @nt<range_constraint>. @Leading@keepnext@;Consider the following example: @begin{Example} @key[type] D @key[is] @key[delta] 0.01 @key[digits] 7 @key[range] -0.00 .. 9999.99; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00008} The compatibility rule implies that the @nt{digits_constraint} "@key[digits] 6" specifies an implicit range of "@en@;@Chg{New=[9999.99],Old=[99.9999]} .. @Chg{New=[9999.99],Old=[99.9999]}". Thus, "@key[digits] 6" is not compatible with the constraint of D, but "@key[digits] 6 range 0.00 .. 9999.99" is compatible. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A value of a scalar type belongs to a constrained subtype of the type if it belongs to the range of the subtype. Attributes like Digits and Delta have no @Chg{Version=[2],New=[effect],Old=[affect]} on this fundamental rule. So the obsolescent forms of @nt<digits_constraint>s and @nt<delta_constraint>s that are called @lquotes@;accuracy constraints@rquotes@; in RM83 don't really represent constraints on the values of the subtype, but rather primarily affect compatibility of the @lquotes@;constraint@rquotes@; with the subtype being @lquotes@;constrained.@rquotes@; In this sense, they might better be called @lquotes@;subtype assertions@rquotes@; rather than @lquotes@;constraints.@rquotes@; Note that the @nt<digits_constraint> on a decimal fixed point subtype is a combination of an assertion about the @i(digits) of the subtype being further constrained, and a constraint on the range of the subtype being defined, either explicit or implicit. @end(Discussion) @PDefn2{Term=[elaboration], Sec=(digits_constraint)} The elaboration of a @nt<digits_constraint> consists of the elaboration of the @nt<range_constraint>, if any. @IndexCheck{Range_Check} If a @nt<range_constraint> is given, a check is made that the bounds of the range are both in the range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta), where @i(D) is the value of the (static) @nt<expression> given after the reserved word @key(digits). @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If this check fails, Constraint_Error is raised. @end{RunTime} @begin{ImplReq} The implementation shall support at least 24 bits of precision (including the sign bit) for fixed point types. @begin{Reason} This is sufficient to represent Standard.Duration with a @i(small) no more than 50 milliseconds. @end{Reason} @end{ImplReq} @begin{ImplPerm} Implementations are permitted to support only @i(small)s that are a power of two. In particular, all decimal fixed point type declarations can be disallowed. Note however that conformance with the Information Systems Annex requires support for decimal @i(small)s, and decimal fixed point type declarations with @i(digits) up to at least 18. @begin{ImplNote} The accuracy requirements for multiplication, division, and conversion (see @RefSec{Model of Floating Point Arithmetic}) are such that support for arbitrary @i(small)s should be practical without undue implementation effort. Therefore, implementations should support fixed point types with arbitrary values for @i(small) (within reason). One reasonable limitation would be to limit support to fixed point types that can be converted to the most precise floating point type without loss of precision (so that Fixed_IO is implementable in terms of Float_IO). @end{ImplNote} @end{ImplPerm} @begin{Notes} @Leading@;The base range of an ordinary fixed point type need not include the specified bounds themselves so that the range specification can be given in a natural way, such as: @leading@begin(Example) @b(type) Fraction @b(is delta) 2.0**(-15) @b(range) -1.0 .. 1.0; @end(Example) @NoPrefix@;With 2's complement hardware, such a type could have a signed 16-bit representation, using 1 bit for the sign and 15 bits for fraction, resulting in a base range of @en@;1.0 .. 1.0@en@;2.0**(@en@;15). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of fixed point types and subtypes:) @begin(Example) @key(type) Volt @key(is) @key(delta) 0.125 @key(range) 0.0 .. 255.0; -- @RI[A pure fraction which requires all the available] -- @RI[space in a word can be declared as the type Fraction:] @key(type) Fraction @key(is) @key(delta) System.Fine_Delta @key(range) -1.0 .. 1.0; -- @RI[Fraction'Last = 1.0 @en System.Fine_Delta] @key(type) Money @key(is) @key(delta) 0.01 @key(digits) 15; -- @RI[decimal fixed point] @key(subtype) Salary @key(is) Money @key(digits) 10; -- @RI[Money'Last = 10.0**13 @en 0.01, Salary'Last = 10.0**8 @en 0.01] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} In Ada 95, S'Small always equals S'Base'Small, so if an implementation chooses a @i(small) for a fixed point type smaller than required by the @i(delta), the value of S'Small in Ada 95 might not be the same as it was in Ada 83. @end{Inconsistent83} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @Defn{extensions to Ada 83} Decimal fixed point types are new, though their capabilities are essentially similar to that available in Ada 83 with a fixed point type whose @i(small) equals its @i(delta) @Chg{Version=[3],New=[and both are],Old=[equals]} a power of 10. However, in the Information Systems Annex, additional requirements are placed on the support of decimal fixed point types (e.g. a minimum of 18 digits of precision). @end{Extend83} @begin{DiffWord83} The syntax rules for @ntf{fixed_point_constraint} and @ntf{fixed_accuracy_definition} are removed. The syntax rule for @nt{fixed_point_definition} is new. A syntax rule for @nt<delta_constraint> is included in the Obsolescent features (to be compatible with Ada 83's @ntf<fixed_point_constraint>). @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00100-01]} @ChgAdded{Version=[2],Text=[Added wording to define the machine numbers of fixed point types; this is needed by the static evaluation rules.]} @end{DiffWord95} @LabeledSubClause{Operations of Fixed Point Types} @begin{StaticSem} @Leading@;The following attributes are defined for @PrefixType{every fixed point subtype S}: @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<Small>, Ref=[8652/0005], ARef=[AI95-00054-01], Text=[S'Small denotes the @i(small) of the type of S. The value of this attribute is of the type @i(universal_real).]} @PDefn2{Term=[specifiable], Sec=(of Small for fixed point types)} @Defn{Small clause} Small may be specified for nonderived@Chg{New=[ ordinary],Old=[]} fixed point types via an @nt{attribute_@!definition_@!clause} (see @RefSecNum{Operational and Representation Attributes}); the expression of such a clause shall be static.@Chg{Version=[3],New=[@AspectDefn{Small}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Small], Text=[@ChgAdded{Version=[3],Text=[Scale factor for a fixed point type.]}]} @Attribute{Prefix=<S>, AttrName=<Delta>, Text=[S'Delta denotes the @i(delta) of the fixed point subtype S. The value of this attribute is of the type @i(universal_real).]} @begin{Reason} The @i(delta) is associated with the @i(sub)type as opposed to the type, because of the possibility of an (obsolescent) @nt<delta_constraint>.@end{reason} @Attribute{Prefix=<S>, AttrName=<Fore>, Text=[S'Fore yields the minimum number of characters needed before the decimal point for the decimal representation of any value of the subtype S, assuming that the representation does not include an exponent, but includes a one-character prefix that is either a minus sign or a space. (This minimum number does not include superfluous zeros or underlines, and is at least 2.) The value of this attribute is of the type @i(universal_integer).]} @Attribute{Prefix=<S>, AttrName=<Aft>, Text=<S'Aft yields the number of decimal digits needed after the decimal point to accommodate the @i(delta) of the subtype S, unless the @i(delta) of the subtype S is greater than 0.1, in which case the attribute yields the value one. @Redundant[(S'Aft is the smallest positive integer N for which (10**N)*S'Delta is greater than or equal to one.)] The value of this attribute is of the type @i(universal_integer).>} @end(description) @EndPrefixType{} @begin{WideAbove} @Leading@;The following additional attributes are defined for @PrefixType{every decimal fixed point subtype S}: @end{WideAbove} @begin(description) @Attribute{Prefix=<S>, AttrName=<Digits>, Text=[S'Digits denotes the @i(digits) of the decimal fixed point subtype S, which corresponds to the number of decimal digits that are representable in objects of the subtype. The value of this attribute is of the type @i(universal_integer).]} Its value is determined as follows: @Defn2{Term=[digits], Sec=(of a decimal fixed point subtype)} @begin(itemize) For a first subtype or a subtype defined by a @nt<subtype_indication> with a @nt<digits_constraint>, the digits is the value of the expression given after the reserved word @key(digits); For a subtype defined by a @nt<subtype_indication> without a @nt<digits_constraint>, the digits of the subtype is the same as that of the subtype denoted by the @nt<subtype_mark> in the @nt<subtype_indication>. @begin(ImplNote) Although a decimal subtype can be both range-constrained and digits-constrained, the digits constraint is intended to control the Size attribute of the subtype. For decimal types, Size can be important because input/output of decimal types is so common. @end(ImplNote) The digits of a base subtype is the largest integer @i(D) such that the range @en@;(10**@i(D)@en@;1)*@i(delta) .. +(10**@i(D)@en@;1)*@i(delta) is included in the base range of the type. @end(itemize) @Attribute{Prefix=<S>, AttrName=<Scale>, Text=[S'Scale denotes the @i(scale) of the subtype S, defined as the value N such that S'Delta = 10.0**(@en@;N). @Defn2{Term=[scale], Sec=(of a decimal fixed point subtype)} @Redundant{The scale indicates the position of the point relative to the rightmost significant digits of values of subtype S.} The value of this attribute is of the type @i{universal_integer}.]} @begin{Ramification} S'Scale is negative if S'Delta is greater than one. By contrast, S'Aft is always positive. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Round>, Text=[S'Round denotes a function with the following specification: @begin(Descexample) @b(function) S'Round(@RI(X) : @RI(universal_real)) @b(return) S'Base @end(Descexample) @NoPrefix@;The function returns the value obtained by rounding X (away from 0, if X is midway between two values of the type of S).]} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} All subtypes of a fixed point type will have the same value for the Delta attribute, in the absence of @nt<delta_constraint>s (see @RefSecNum(Reduced Accuracy Subtypes)). S'Scale is not always the same as S'Aft for a decimal subtype; for example, if S'Delta = 1.0 then S'Aft is 1 while S'Scale is 0. @PDefn2{Term=[predefined operations],Sec=(of a fixed point type)} The predefined operations of a fixed point type include the assignment operation, qualification, the membership tests, and explicit conversion to and from other numeric types. They also include the relational operators and the following predefined arithmetic operators: the binary and unary adding operators @en@; and +, multiplying operators, and the unary operator @key(abs). As for all types, objects of a fixed point type have Size and Address attributes (see @RefSecNum(Operational and Representation Attributes)). Other attributes of fixed point types are defined in @RefSecNum{Attributes of Fixed Point Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0005],ARef=[AI95-00054-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that @i<small> may be specified only for ordinary fixed point types.]} @end{DiffWord95} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/03b.mss��������������������������������������������������������������0000755�0001752�0001001�00000354004�12066652506�016543� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:02 $} @Comment{$Source: e:\\cvsroot/ARM/Source/03b.mss,v $} @Comment{$Revision: 1.101 $} @LabeledClause{Array Types} @begin{Intro} @Defn{array} @Defn{array type} An @i(array) object is a composite object consisting of components which all have the same subtype. The name for a component of an array uses one or more index values belonging to specified discrete types. The value of an array object is a composite value consisting of the values of the components. @end{Intro} @begin{Syntax} @Syn{lhs=<array_type_definition>,rhs=" @Syn2{unconstrained_array_definition} | @Syn2{constrained_array_definition}"} @Syn{lhs=<unconstrained_array_definition>,rhs=" @key{array}(@Syn2{index_subtype_definition} {, @Syn2{index_subtype_definition}}) @key{of} @Syn2{component_definition}"} @Syn{lhs=<index_subtype_definition>,rhs="@Syn2{subtype_mark} @key{range} <>"} @Syn{lhs=<constrained_array_definition>,rhs=" @key{array} (@Syn2{discrete_subtype_definition} {, @Syn2{discrete_subtype_definition}}) @key{of} @Syn2{component_definition}"} @Syn{lhs=<discrete_subtype_definition>,rhs="@SynI{discrete_}@Syn2{subtype_indication} | @Syn2{range}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00406-01]} @Syn{lhs=<component_definition>,rhs="@Chg{Version=[2],New=< >,Old=<>}[@key{aliased}] @Syn2{subtype_indication}@Chg{Version=[2],New=< | [@key{aliased}] @Syn2{access_definition}>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(discrete_subtype_definition range)} For a @nt<discrete_subtype_definition> that is a @nt<range>, the @nt<range> shall resolve to be of some specific discrete type@Redundant[; which discrete type shall be determined without using any context other than the bounds of the @nt<range> itself (plus the preference for @i(root_integer) @em see @RefSecNum(The Context of Overload Resolution)).] @end{Resolution} @begin{Legality} @Defn{index subtype} Each @nt{index_subtype_definition} or @nt{discrete_subtype_definition} in an @nt{array_type_definition} defines an @i(index subtype); @Defn{index type} its type (the @i(index type)) shall be discrete. @begin{Discussion} @Defn2{Term=[index], Sec=(of an array)} An @i(index) is a discrete quantity used to select along a given dimension of an array. A component is selected by specifying corresponding values for each of the indices. @end{Discussion} @Defn{component subtype} The subtype defined by the @nt<subtype_indication> of a @nt<component_definition> (the @i(component subtype)) shall be a definite subtype. @begin{Ramification} This applies to all uses of @nt<component_definition>, including in @nt<record_type_definition>s and @nt<protected_definition>s.@end{ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[Within the definition of a nonlimited composite type (or a limited composite type that later in its immediate scope becomes nonlimited @em see @RefSecNum{Private Operations} and @RefSecNum{Limited Types}), if a @nt{component_definition} contains the reserved word @key[aliased] and the type of the component is discriminated, then the nominal subtype of the component shall be constrained.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgNote{The rule's gone, we might as well clobber all the notes.} @ChgDeleted{Version=[2],Text=[If we allowed the subtype to be unconstrained, then the discriminants might change because of an assignment to the containing (nonlimited) object, thus causing a potential violation of an access subtype constraint of an access value designating the aliased component.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that the rule elsewhere defining all aliased discriminated objects to be constrained does not help @em that rule prevents assignments to the component itself from doing any harm, but not assignments to the containing object.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Type=[Leading],Text=[We allow this for components within limited types since assignment to the enclosing object is not a problem. Furthermore, it is important to be able to use a default expression for a discriminant in arrays of limited components, since that is the only way to give the components different values for their discriminants. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@key[protected] @key[type] Counter_Type(Initial_Value : Integer := 1) @key[is] @key[procedure] Get_Next(Next_Value : @key[out] Integer); --@RI{ Returns the next value on each call, bumping Count} --@RI{ before returning.} @key[private] Count : Integer := Initial_Value; @key[end] Counter_Type; @key[protected] @key[body] Counter_Type @key[is] ...]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@key[function] Next_Id(Counter : @key[access] Counter_Type) @key[return] Integer @key[is] Result : Integer; @key[begin] Counter.Get_Next(Result); @key[return] Result; @key[end] Next_Id;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[C : @key[aliased] Counter_Type; @key[task] @key[type] T(Who_Am_I : Integer := Next_Id(C'Access)); @key[task] @key[body] T @key[is] ...]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Task_Array : @key[array](1..100) @key[of] @key[aliased] T; --@RI{ Array of task elements, each with its own unique ID.} --@RI{ We specify "aliased" so we can use Task_Array(I)'Access.} --@RI{ This is safe because Task_Array is of a limited type,} --@RI{ so there is no way an assignment to it could change} --@RI{ the discriminants of one of its components.}]} @end{Example} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that this rule applies to array components and record components, but not to protected type components (since they are always limited).]} @end{Ramification} @end{Legality} @begin{StaticSem} @Defn2{Term=[dimensionality], Sec=(of an array)} @Defn{one-dimensional array} @Defn{multi-dimensional array} An array is characterized by the number of indices (the @i(dimensionality) of the array), the type and position of each index, the lower and upper bounds for each index, and the subtype of the components. The order of the indices is significant. A one-dimensional array has a distinct component for each possible index value. A multidimensional array has a distinct component for each possible sequence of index values that can be formed by selecting one value for each index position (in the given order). The possible values for a given index are all the values between the lower and upper bounds, inclusive; @Defn{index range} this range of values is called the @i(index range). @Defn2{Term=[bounds], Sec=(of an array)} The @i(bounds) of an array are the bounds of its index ranges. @Defn2{Term=[length], Sec=(of a dimension of an array)} The @i(length) of a dimension of an array is the number of values of the index range of the dimension (zero for a null range). @Defn2{Term=[length], Sec=(of a one-dimensional array)} The @i(length) of a one-dimensional array is the length of its only dimension. An @nt<array_type_definition> defines an array type and its first subtype. For each object of this array type, the number of indices, the type and position of each index, and the subtype of the components are as in the type definition@Redundant[; the values of the lower and upper bounds for each index belong to the corresponding index subtype of its type, except for null arrays (see @RefSecNum(Index Constraints and Discrete Ranges))]. @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} An @nt{unconstrained_array_definition} defines an array type with an unconstrained first subtype. Each @nt{index_@!subtype_@!definition} defines the corresponding index subtype to be the subtype denoted by the @nt{subtype_@!mark}. @redundant[@PDefn2{Term=[box], Sec=(compound delimiter)} The compound delimiter <> (called a @i(box)) of an @nt<index_subtype_definition> stands for an undefined range (different objects of the type need not have the same bounds).] @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A @nt{constrained_array_definition} defines an array type with a constrained first subtype. Each @nt{discrete_@!subtype_@!definition} defines the corresponding index subtype, as well as the corresponding index range for the constrained first subtype. @PDefn2{Term=[constraint], Sec=(of a first array subtype)} The @i(constraint) of the first subtype consists of the bounds of the index ranges. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Although there is no @Chg{Version=[3],New=[nameable],Old=[namable]} unconstrained array subtype in this case, the predefined slicing and concatenation operations can operate on and yield values that do not necessarily belong to the first array subtype. This is also true for Ada 83. @end{Discussion} @Leading@;The discrete subtype defined by a @nt{discrete_@!subtype_@!definition} is either that defined by the @nt{subtype_@!indication}, or a subtype determined by the @nt{range} as follows: @begin(itemize) If the type of the @nt{range} resolves to @i(root_integer), then the @nt{discrete_subtype_definition} defines a subtype of the predefined type Integer with bounds given by a conversion to Integer of the bounds of the @nt<range>; @PDefn2{Term=[implicit subtype conversion],Sec=(bounds of a range)} @begin{Reason} This ensures that indexing over the discrete subtype can be performed with regular Integers, rather than only @i(universal_integer)s. @end{Reason} @begin{Discussion} We considered doing this by simply creating a @lquotes@;preference@rquotes@; for Integer when resolving the @nt<range>. @PDefn{Beaujolais effect} However, this can introduce @i(Beaujolais) effects when the @nt<simple_expression>s involve calls on functions visible due to @key(use) clauses. @end{Discussion} Otherwise, the @nt{discrete_subtype_definition} defines a subtype of the type of the @nt{range}, with the bounds given by the @nt<range>. @end(itemize) @PDefn2{Term=[nominal subtype], Sec=(of a component)} The @nt{component_definition} of an @nt<array_type_definition> defines the nominal subtype of the components. If the reserved word @key(aliased) appears in the @nt{component_definition}, then each component of the array is aliased (see @RefSecNum{Access Types}). @begin(Ramification) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See @RefSecNum{Record Types}.]} @end(Ramification) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(array_type_definition)} The elaboration of an @nt{array_type_definition} creates the array type and its first subtype, and consists of the elaboration of any @nt{discrete_@!subtype_@!definition}s and the @nt{component_@!definition}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @PDefn2{Term=[elaboration], Sec=(discrete_subtype_definition)} The elaboration of a @nt{discrete_subtype_definition} @Chg{New=[that does not contain any per-object expressions],Old=[]} creates the discrete subtype, and consists of the elaboration of the @nt{subtype_@!indication} or the evaluation of the @nt{range}. @Chg{New=[The elaboration of a @nt{discrete_subtype_definition} that contains one or more per-object expressions is defined in @RefSecNum{Record Types}.],Old=[]} @PDefn2{Term=[elaboration], Sec=(component_definition)} The elaboration of a @nt{component_@!definition} in an @nt{array_@!type_@!definition} consists of the elaboration of the @nt{subtype_@!indication}@Chg{Version=[2],New=[ or @nt{access_definition}],Old=[]}. The elaboration of any @nt{discrete_@!subtype_@!definition}s and the elaboration of the @nt{component_@!definition} are performed in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @end{RunTime} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For an array type with a scalar component type, the following language-defined representation aspect may be specified with an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}):]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Default_Component_Value@\This aspect shall be specified by a static expression, and that expression shall be explicit, even if the aspect has a boolean type. Default_Component_Value shall be specified only on a @nt{full_type_declaration}.@AspectDefn{Default_Component_Value}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The part about requiring an explicit expression is to disallow omitting the value for this aspect, which would otherwise be allowed by the rules of @RefSecNum{Aspect Specifications}.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a representation attribute in order to disallow specifying it on a derived type that has inherited primitive subprograms; that is necessary as the sizes of @key[out] parameters could be different whether or not a Default_Value is specified (see @RefSecNum{Parameter Associations}).]} @end{Reason} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Default_Component_Value], Text=[@ChgAdded{Version=[3],Text=[Default value for the components of an array-of-scalar subtype.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[If a derived type with no primitive subprograms inherits a boolean Default_Component_Value aspect, the aspect may be specified to have any value for the derived type.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This overrides the @RefSecNum{Aspect Specifications} rule that says that a boolean aspect with a value True cannot be changed.]} @end{Reason} @end{StaticSem} @begin{Resolution} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} specified for the Default_Component_Value aspect is the component type of the array type defined by the @nt{full_type_declaration} on which it appears.@PDefn2{Term=[expected type],Sec=[@nt{expression} of a Default_Component_Value aspect]}]} @end{Resolution} @begin{Notes} All components of an array have the same subtype. In particular, for an array of components that are one-dimensional arrays, this means that all components have the same bounds and hence the same length. Each elaboration of an @nt<array_type_definition> creates a distinct array type. A consequence of this is that each object whose @nt<object_declaration> contains an @nt<array_type_definition> is of its own unique type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of type declarations with unconstrained array definitions: ) @begin(Example) @key(type) Vector @key(is) @key(array)(Integer @key(range) <>) @key(of) Real; @key(type) Matrix @key(is) @key(array)(Integer @key(range) <>, Integer @key(range) <>) @key(of) Real; @key(type) Bit_Vector @key(is) @key(array)(Integer @key(range) <>) @key(of) Boolean; @key(type) Roman @key(is) @key(array)(Positive @key(range) <>) @key(of) Roman_Digit; --@RI[ see @RefSecNum(Character Types)] @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of type declarations with constrained array definitions: ) @end{WideAbove} @begin(Example) @key(type) Table @key(is) @key(array)(1 .. 10) @key(of) Integer; @key(type) Schedule @key(is) @key(array)(Day) @key(of) Boolean; @key(type) Line @key(is) @key(array)(1 .. Max_Line_Size) @key(of) Character; @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of object declarations with array type definitions: ) @end{WideAbove} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Grid @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(1 .. 80, 1 .. 100) @key(of) Boolean; Mix @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(Color @key(range) Red .. Green) @key(of) Boolean;@Chg{Version=[2],New=[ Msg_Table : @key(constant array)(Error_Code) @key(of access constant) String := (Too_Big => @key(new) String'("Result too big"), Too_Small => ...);],Old=[]} Page @Chg{Version=[2],New=[ ],Old=[]}: @key(array)(Positive @key(range) <>) @key(of) Line := --@RI[ an array of arrays] (1 | 50 => Line'(1 | Line'Last => '+', @key(others) => '-'), --@RI[ see @RefSecNum(Array Aggregates)] 2 .. 49 => Line'(1 | Line'Last => '|', @key(others) => ' ')); --@RI[ Page is constrained by its initial value to (1..50)] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{component_definition} is modified to allow the reserved word @key{aliased}. The syntax rules for @nt{unconstrained_array_definition} and @nt{constrained_array_definition} are modified to use @nt{component_definition} (instead of @i(component_)@nt{subtype_indication}). The effect of this change is to allow the reserved word @key{aliased} before the component @nt{subtype_indication}. A @nt{range} in a @nt{discrete_subtype_definition} may use arbitrary universal expressions for each bound (e.g. @en@;1 .. 3+5), rather than strictly "implicitly convertible" operands. The subtype defined will still be a subtype of Integer. @end{Extend83} @begin{DiffWord83} We introduce a new syntactic category, @nt{discrete_subtype_definition}, as distinct from @nt{discrete_range}. These two constructs have the same syntax, but their semantics are quite different (one defines a subtype, with a preference for Integer subtypes, while the other just selects a subrange of an existing subtype). We use this new syntactic category in @key(for) loops and entry families. The syntax for @nt{index_constraint} and @nt{discrete_range} have been moved to their own subclause, since they are no longer used here. The syntax rule for @nt{component_definition} (formerly @ntf<component_subtype_definition>) is moved here from RM83-3.7. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00406-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Array components can have an anonymous access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[The prohibition against unconstrained discriminated aliased components has been lifted. It has been replaced by a prohibition against the actual troublemakers: general access discriminant constraints (see @RefSecNum{Discriminant Constraints}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to allow the elaboration of per-object constraints for constrained arrays.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The new aspect Default_Component_Value allows defining implicit initial values (see @RefSecNum{Object Declarations}) for arrays of scalar types.]} @end{Extend2005} @LabeledSubClause{Index Constraints and Discrete Ranges} @begin{Intro} An @nt<index_constraint> determines the range of possible values for every index of an array subtype, and thereby the corresponding array bounds. @end{Intro} @begin{Syntax} @Syn{lhs=<index_constraint>,rhs=" (@Syn2{discrete_range} {, @Syn2{discrete_range}})"} @Syn{lhs=<discrete_range>,rhs="@SynI{discrete_}@Syn2{subtype_indication} | @Syn2{range}"} @end{Syntax} @begin{Resolution} @Defn{type of a @nt{discrete_range}} The type of a @nt<discrete_range> is the type of the subtype defined by the @nt<subtype_indication>, or the type of the @nt<range>. @PDefn2{Term=[expected type], Sec=(index_constraint discrete_range)} For an @nt{index_constraint}, each @nt{discrete_range} shall resolve to be of the type of the corresponding index. @begin(Discussion) In Ada 95, @nt{index_constraint}s only appear in a @nt{subtype_indication}; they no longer appear in @nt<constrained_array_definition>s. @end(Discussion) @end{Resolution} @begin{Legality} An @nt{index_constraint} shall appear only in a @nt{subtype_indication} whose @nt{subtype_mark} denotes either an unconstrained array subtype, or an unconstrained access subtype whose designated subtype is an unconstrained array subtype; in either case, the @nt{index_constraint} shall provide a @nt{discrete_range} for each index of the array type. @end{Legality} @begin{StaticSem} @Defn2{Term=[bounds], Sec=(of a @nt<discrete_range>)} A @nt{discrete_range} defines a range whose bounds are given by the @nt{range}, or by the range of the subtype defined by the @nt{subtype_indication}. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(index constraint with a subtype)} An @nt{index_constraint} is @i(compatible) with an unconstrained array subtype if and only if the index range defined by each @nt{discrete_range} is compatible (see @RefSecNum(Scalar Types)) with the corresponding index subtype. @Defn{null array} If any of the @nt<discrete_range>s defines a null range, any array thus constrained is a @i(null array), having no components. @PDefn2{Term=[satisfies], Sec=(an index constraint)} An array value @i(satisfies) an @nt{index_constraint} if at each index position the array value and the @nt{index_constraint} have the same index bounds. @begin{Ramification} There is no need to define compatibility with a constrained array subtype, because one is not allowed to constrain it again.@end{ramification} @PDefn2{Term=[elaboration], Sec=(index_constraint)} The elaboration of an @nt{index_constraint} consists of the evaluation of the @nt{discrete_range}(s), in an arbitrary order. @PDefn2{Term=[evaluation], Sec=(discrete_range)} The evaluation of a @nt{discrete_range} consists of the elaboration of the @nt{subtype_indication} or the evaluation of the @nt{range}. @end{RunTime} @begin{Notes} The elaboration of a @nt<subtype_indication> consisting of a @nt<subtype_mark> followed by an @nt<index_constraint> checks the compatibility of the @nt<index_constraint> with the @nt<subtype_mark> (see @RefSecNum(Subtype Declarations)). Even if an array value does not satisfy the index constraint of an array subtype, Constraint_Error is not raised on conversion to the array subtype, so long as the length of each dimension of the array value and the array subtype match. See @RefSecNum(Type Conversions). @end{Notes} @begin{Examples} @leading@keepnext@i(Examples of array declarations including an index constraint: ) @begin(Example) Board : Matrix(1 .. 8, 1 .. 8); --@RI[ see @RefSecNum(Array Types)] Rectangle : Matrix(1 .. 20, 1 .. 30); Inverse : Matrix(1 .. N, 1 .. N); --@RI[ N need not be static ] Filter : Bit_Vector(0 .. 31); @end(Example) @begin{WideAbove} @leading@keepnext@i(Example of array declaration with a constrained array subtype: ) @end{WideAbove} @begin(Example) My_Schedule : Schedule; --@RI[ all arrays of type Schedule have the same bounds] @end(Example) @begin{WideAbove} @leading@keepnext@i(Example of record type with a component that is an array: ) @end{WideAbove} @begin(Example) @key(type) Var_Line(Length : Natural) @key(is) @key(record) Image : String(1 .. Length); @key(end) @key(record); Null_Line : Var_Line(0); --@RI[ Null_Line.Image is a null array] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We allow the declaration of a variable with a nominally unconstrained array subtype, so long as it has an initialization expression to determine its bounds. @end{Extend83} @begin{DiffWord83} We have moved the syntax for @nt{index_constraint} and @nt{discrete_range} here since they are no longer used in @nt{constrained_array_definition}s. We therefore also no longer have to describe the (special) semantics of @nt{index_constraint}s and @nt{discrete_range}s that appear in @nt{constrained_array_definition}s. The rules given in RM83-3.6.1(5,7-10), which define the bounds of an array object, are redundant with rules given elsewhere, and so are not repeated here. RM83-3.6.1(6), which requires that the (nominal) subtype of an array variable be constrained, no longer applies, so long as the variable is explicitly initialized. @end{DiffWord83} @LabeledSubClause{Operations of Array Types} @begin{Legality} @Redundant[The argument N used in the @nt<attribute_designator>s for the N-th dimension of an array shall be a static @nt<expression> of some integer type.] The value of N shall be positive (nonzero) and no greater than the dimensionality of the array. @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0006],ARef=[AI95-00030-01]} The following attributes are defined for @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}], Old=[prefix]} A that is of an array type @Redundant[(after any implicit dereference)], or denotes a constrained array subtype]}: @begin{Ramification} These attributes are not defined if A is a subtype-mark for an access-to-array subtype. They are defined (by implicit dereference) for access-to-array values.@end{ramification} @begin(description) @Attribute{Prefix=<A>, AttrName=<First>, Text=[A'First denotes the lower bound of the first index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<First(N)>, Text=[A'First(N) denotes the lower bound of the N-th index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Last>, Text=[A'Last denotes the upper bound of the first index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Last(N)>, Text=[A'Last(N) denotes the upper bound of the N-th index range; its type is the corresponding index type.]} @Attribute{Prefix=<A>, AttrName=<Range>, Text=[A'Range is equivalent to the range A'First .. A'Last, except that the @nt<prefix> A is only evaluated once.]} @Attribute{Prefix=<A>, AttrName=<Range(N)>, Text=[A'Range(N) is equivalent to the range A'First(N) .. A'Last(N), except that the @nt<prefix> A is only evaluated once.]} @Attribute{Prefix=<A>, AttrName=<Length>, Text=[A'Length denotes the number of values of the first index range (zero for a null range); its type is @i(universal_integer).]} @Attribute{Prefix=<A>, AttrName=<Length(N)>, Text=[A'Length(N) denotes the number of values of the N-th index range (zero for a null range); its type is @i(universal_integer).]} @end(description) @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation should normally represent multidimensional arrays in row-major order, consistent with the notation used for multidimensional array aggregates (see @RefSecNum(Array Aggregates)). However, if @Chg{Version=[3],New=[convention ],Old=[a @key<pragma> Convention(]}Fortran@Chg{Version=[3],New=[ is specified for],Old=[, ...) applies to]} a multidimensional array type, then column-major order should be used instead (see @RefSec{Interfacing with Fortran}). @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Multidimensional arrays should be represented in row-major order, unless the array has convention Fortran.]}]} @end{ImplAdvice} @begin{Notes} @Leading@;The @nt<attribute_reference>s A'First and A'First(1) denote the same value. A similar relation exists for the @nt<attribute_reference>s A'Last, A'Range, and A'Length. The following relation is satisfied (except for a null array) by the above attributes if the index type is an integer type: @begin(example) A'Length(N) = A'Last(N) - A'First(N) + 1 @end(example) An array type is limited if its component type is limited (see @RefSecNum(Limited Types)). @PDefn2{Term=[predefined operations],Sec=(of an array type)} The predefined operations of an array type include the membership tests, qualification, and explicit conversion. If the array type is not limited, they also include assignment and the predefined equality operators. For a one-dimensional array type, they include the predefined concatenation operators (if nonlimited) and, if the component type is discrete, the predefined relational operators; if the component type is boolean, the predefined logical operators are also included. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A component of an array can be named with an @nt<indexed_component>. A value of an array type can be specified with an @nt<array_aggregate>@Chg{Version=[2],New=[],Old=[, unless the array type is limited]}. For a one-dimensional array type, a slice of the array can be named; also, string literals are defined if the component type is a character type. @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples (using arrays declared in the examples of subclause @RefSecNum(Index Constraints and Discrete Ranges)):} @begin(Example) -- Filter'First = 0 Filter'Last = 31 Filter'Length = 32 -- Rectangle'Last(1) = 20 Rectangle'Last(2) = 30 @end(Example) @end{Examples} @LabeledSubClause{String Types} @begin{StaticSem} @Defn{string type} A one-dimensional array type whose component type is a character type is called a @i(string) type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Leading@redundant[There are @Chg{Version=[2],New=[three],Old=[two]} predefined string types, String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2],New=[, and Wide_Wide_String],Old=[]}, each indexed by values of the predefined subtype Positive; these are declared in the visible part of package Standard:] @begin(example) @redundant[@key(subtype) Positive @key(is) Integer @key(range) 1 .. Integer'Last; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @key(type) String @key(is) @key(array)(Positive @key(range) <>) @key(of) Character; @key(type) Wide_String @key(is) @key(array)(Positive @key(range) <>) @key(of) Wide_Character; @Chg{Version=[2],New=[@key(type) Wide_Wide_String @key(is) @key(array)(Positive @key(range) <>) @key(of) Wide_Wide_Character;],Old=[]} ]@end(example) @end{StaticSem} @begin{Notes} String literals (see @RefSecNum(String Literals) and @RefSecNum(Literals)) are defined for all string types. The concatenation operator & is predefined for string types, as for all nonlimited one-dimensional array types. The ordering operators <, <=, >, and >= are predefined for string types, as for all one-dimensional discrete array types; these ordering operators correspond to lexicographic order (see @RefSecNum(Relational Operators and Membership Tests)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of string objects:) @begin(Example) @TabClear()@TabSet(P50) Stars : String(1 .. 120) := (1 .. 120 => '*' ); Question : @key(constant) String := "How many characters?"; @\--@RI[ Question'First = 1, Question'Last = 20] @\--@RI[ Question'Length = 20 (the number of characters)] Ask_Twice : String := Question & Question;@\--@RI[ constrained to (1..40)] Ninety_Six : @key(constant) Roman := "XCVI";@\--@RI[ see @RefSecNum(Character Types) and @RefSecNum(Array Types)] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The declaration of Wide_String in Standard hides a use-visible declaration with the same @nt<defining_identifier>. In rare cases, this might result in an inconsistency between Ada 83 and Ada 95. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Because both String and Wide_String are always directly visible, an expression like @begin(Example) "a" < "bc" @end(Example) is now ambiguous, whereas in Ada 83 both string literals could be resolved to type String. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The type Wide_String is new (though it was approved by ARG for Ada 83 compilers as well). @end{Extend83} @begin{DiffWord83} We define the term @i(string type) as a natural analogy to the term @i(character type). @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} The declaration of Wide_Wide_String in Standard hides a use-visible declaration with the same @nt<defining_identifier>. In the (very) unlikely event that an Ada 95 program had depended on such a use-visible declaration, and the program remains legal after the substitution of Standard.Wide_Wide_String, the meaning of the program will be different.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The type Wide_Wide_String is new.]} @end{Extend95} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Discriminants} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00326-01]} @redundant[@Defn{discriminant} @IndexSee{Term=[type parameter],See=(discriminant)} @IndexSeeAlso{Term=[parameter],See=(discriminant)} A composite type (other than an array@Chg{Version=[2],New=[ or interface],Old=[]} type) can have discriminants, which parameterize the type. A @nt<known_discriminant_part> specifies the discriminants of a composite type. A discriminant of an object is a component of the object, and is either of a discrete type or an access type. An @nt<unknown_discriminant_part> in the declaration of a@Chg{Version=[2],New=[],Old=[ partial]} view of a type specifies that the discriminants of the type are unknown for the given view; all subtypes of such a@Chg{Version=[2],New=[],Old=[ partial]} view are indefinite subtypes.] @ChgRef{Version=[2],Kind=[Revised]} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Discriminant>, Text=<A discriminant is a parameter @Chg{Version=[2],New=[for],Old=[of]} a composite type. It can control, for example, the bounds of a component of the type if @Chg{Version=[2],New=[the component is],Old=[that type is]} an array@Chg{Version=[2],New=[],Old=[ type]}. A discriminant @Chg{Version=[2],New=[for],Old=[of]} a task type can be used to pass data to a task of the type upon creation.>} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @PDefn{unknown discriminants} @PDefn2{Term=[discriminants], Sec=(unknown)} A @Chg{Version=[2],New=[view of a ],Old=[]}type, and all @Chg{Version=[2],New=[], Old=[of its ]}subtypes@Chg{Version=[2],New=[ of the view],Old=[]}, have @i(unknown discriminants) when the number or names of the discriminants, if any, are unknown at the point of the type declaration@Chg{Version=[2],New=[ for the view],Old=[]}. A @nt<discriminant_part> of (<>) is used to indicate unknown discriminants. @end{Discussion} @end{Intro} @begin{Metarules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00402-01]} @ChgAdded{Version=[2],Text=[When an access discriminant is initialized at the time of object creation with an allocator of an anonymous type, the allocated object and the object with the discriminant are tied together for their lifetime. They should be allocated out of the same storage pool, and then at the end of the lifetime of the enclosing object, finalized and reclaimed together. In this case, the allocated object is called a coextension (see @RefSecNum{Operations of Access Types}).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above principle when applied to a nonlimited type implies that such an object may be copied only to a shorter-lived object, because attempting to assign it to a longer-lived object would fail because the access discriminants would not match. In a copy, the lifetime connection between the enclosing object and the allocated object does not exist. The allocated object is tied in the above sense only to the original object. Other copies have only secondary references to it.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that when an @nt{allocator} appears as a constraint on an access discriminant in a @nt{subtype_indication} that is elaborated independently from object creation, no such connection exists. For example, if a named constrained subtype is declared via "@key{subtype} Constr @key{is} Rec(Acc_Discrim => @key{new} T);" or if such an @nt{allocator} appears in the @nt{subtype_indication} for a component, the allocator is evaluated when the @nt{subtype_indication} is elaborated, and hence its lifetime is typically longer than the objects or components that will later be subject to the constraint. In these cases, the allocated object should not be reclaimed until the @nt{subtype_indication} goes out of scope.]} @end{Discussion} @end{Metarules} @begin{Syntax} @Syn{lhs=<discriminant_part>,rhs="@Syn2{unknown_discriminant_part} | @Syn2{known_discriminant_part}"} @Syn{lhs=<unknown_discriminant_part>,rhs="(<>)"} @Syn{lhs=<known_discriminant_part>,rhs=" (@Syn2{discriminant_specification} {; @Syn2{discriminant_specification}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<discriminant_specification>,rhs=" @Syn2{defining_identifier_list} : @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [:= @Syn2{default_expression}] | @Syn2{defining_identifier_list} : @Syn2{access_definition} [:= @Syn2{default_expression}]"} @Syn{lhs=<default_expression>,rhs="@Syn2{expression}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(discriminant default_expression)} The expected type for the @nt{default_expression} of a @nt{discriminant_specification} is that of the corresponding discriminant. @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0007],ARef=[AI95-00098-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} A @Chg{New=[@nt{discriminant_part}],Old=[@nt{known_discriminant_part}]} is only permitted in a declaration for a composite type that is not an array@Chg{Version=[2],New=[ or interface],Old=[]} type @Redundant[(this includes generic formal types)]@Chg{New=[. A],Old=[; a]} type declared with a @nt<known_discriminant_part> is called a @i(discriminated) type,@Defn{discriminated type} as is a type that inherits (known) discriminants. @begin{ImplNote} Discriminants on array types were considered, but were omitted to ease (existing) implementations. @end{implnote} @begin(Discussion) Note that the above definition for @lquotes@;discriminated type@rquotes@; does not include types declared with an @nt<unknown_discriminant_part>. This seems consistent with Ada 83, where such types (in a generic formal part) would not be considered discriminated types. Furthermore, the full type for a type with unknown discriminants need not even be composite, much less have any discriminants. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0007],ARef=[AI95-00098-01]} @Chg{New=[On the other hand, @nt<unknown_discriminant_part>s cannot be applied to type declarations that cannot have a @nt<known_discriminant_part>. There is no point in having unknown discriminants on a type that can never have discriminants (for instance, a formal modular type), even when these are allowed syntactically.],Old=[]} @end(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} The subtype of a discriminant may be defined by@Chg{Version=[2],New=[ an optional @nt{null_exclusion} and],Old=[]} a @nt<subtype_mark>, in which case the @nt<subtype_mark> shall denote a discrete or access subtype, or it may be defined by an @nt<access_definition>@Chg{Version=[2],New=[],Old=[ @Redundant[(in which case the @nt<subtype_mark> of the @nt<access_definition> may denote any kind of subtype)]]}. @Defn{access discriminant} A discriminant that is defined by an @nt<access_definition> is called an @i(access discriminant) and is of an anonymous @Chg{Version=[2],New=[access], Old=[general access-to-variable]} type@Chg{Version=[2],New=[],Old=[ whose designated subtype is denoted by the @nt<subtype_mark> of the @nt<access_definition>]}. @begin(Reason) @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgNote{It still does cause complexities. :-)}@ChgNote{We don't want to delete "Reason:" here, thus we use @Chg and not @ChgDeleted} @Chg{Version=[2],New=[],Old=[In an early version of Ada 9X, we allowed access discriminants on nonlimited types, but this created unpleasant complexities. It turned out to be simpler and more uniform to allow discriminants of a named access type on any discriminated type, and keep access discriminants just for limited types.]} Note that discriminants of a named access type are not considered @lquotes@;access discriminants.@rquotes@; Similarly, @lquotes@;access parameter@rquotes@; only refers to a formal parameter defined by an @nt<access_definition>. @end(Reason) @ChgNote{This paragraph is just moved up} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00402-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0214-1]} @ChgAdded{Version=[2],Text=[@nt{Default_expression}s shall be provided either for all or for none of the discriminants of a @nt{known_@!discriminant_@!part}. No @nt<default_@!expression>s are permitted in a @nt<known_@!discriminant_@!part> in a declaration of a @Chg{Version=[3],New=[nonlimited ],Old=[]}tagged type @Redundant[or a generic formal type].]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The all-or-none rule is related to the rule that a discriminant constraint shall specify values for all discriminants. One could imagine a different rule that allowed a constraint to specify only some of the discriminants, with the others provided by default. Having defaults for discriminants has a special significance @em it allows objects of the type to be unconstrained, with the discriminants alterable as part of assigning to the object.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0214-1]} @ChgAdded{Version=[2],Text=[Defaults for discriminants of tagged types are disallowed so that every object of a @Chg{Version=[3],New=[nonlimited ],Old=[]}tagged type is constrained, either by an explicit constraint, or by its initial discriminant values. This substantially simplifies the semantic rules and the implementation of inherited dispatching operations. @Chg{Version=[3],New=[We don't need this rule for limited tagged types, as the discriminants of such objects cannot be changed after the object is created in any case @em no full-object assignment is supported, and that is required to change discriminant values. ],Old=[]}For generic formal types, the restriction simplifies the type matching rules. If one simply wants a "default" value for the discriminants, a constrained subtype can be declared for future use.]} @end(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00402-01],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0063-1]} A @nt<discriminant_specification> for an access discriminant @Chg{Version=[2],New=[may have a @nt{default_expression}],Old=[shall appear]} only in the declaration for @Chg{Version=[3],New=[an immutably limited type (see @RefSecNum{Limited Types})],Old=[a task or protected type, or for a type @Chg{Version=[2],New=[that is a descendant of an explicitly limited record type],Old=[with the reserved word @key[limited] in its @Redundant[(full)] definition or in that of one of its ancestors]}]}. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.@PDefn{generic contract issue} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} This rule implies that a type can have @Chg{Version=[2], New=[a default for ],Old=[]}an access discriminant if the type is limited, but not if the only reason it's limited is because of a limited component. Compare @Chg{Version=[3],New=[],Old=[with ]}the definition of limited type @Chg{Version=[3],New=[and immutably limited type ],Old=[]}in @RefSecNum{Limited Types}.@Chg{Version=[3],New=[],Old=[@Chg{Version=[2],New=[ Also, recall that a @ldquote@;descendant@rdquote includes the type itself, so an explicitly limited record type can have defaults.],Old=[]}]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} @ChgDeleted{Version=[2],Text=[It is a consequence of this rule that only a return-by-reference type can have an access discriminant (see @RefSecNum{Return Statements}). This is important to avoid dangling references to local variables.]} @ChgAdded{Version=[3],Text=[A (nonformal) limited private type can always have a default for an access discriminant, because having the default itself makes the type immutably limited. Such a private type must necessarily have a full type with the same access discriminant with a default, and thus the full type will always be immutably limited (if legal).]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Leading@Keepnext@;We @Chg{Version=[2],New=[],Old=[also ]}considered the following rules@Chg{Version=[2],New=[ for access discriminants],Old=[]}: @begin{Itemize} If a type has an access discriminant, this automatically makes it limited, just like having a limited component automatically makes a type limited. This was rejected because it decreases program readability, and because it seemed error prone (two bugs in a previous version of the RM9X were attributable to this rule). @ChgRef{Version=[2],Kind=[Revised]} A type with an access discriminant shall be limited. This is equivalent to the rule we actually chose@Chg{Version=[2],New=[ for Ada 95],Old=[]}, except that it allows a type to have an access discriminant if it is limited just because of a limited component. For example, any record containing a task would be allowed to have an access discriminant, whereas the actual rule requires @lquotes@key[limited] @key[record]@rquotes@;. This rule was also rejected due to readability concerns, and because would interact badly with the rules for limited types that @lquotes@;become nonlimited@rquotes@;. @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0063-1]} @ChgAdded{Version=[2],Text=[A type may have an access discriminant if it is @Chg{Version=[3],New=[an immutably limited],Old=[a limited partial view, or a task, protected, or explicitly limited record]} type. This was the rule chosen for Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant. For nonlimited type, there is no special accessibility for access discriminants; they're the same as any other anonymous access component. For a limited type, they have the special accessibility of Ada 95. However, this doesn't work because a limited partial view can have a nonlimited full view -- giving the two views different accessibility.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0063-1]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, as above. However, special accessibility rules only apply to types that are @Chg{Version=[3],New=[immutably],Old=[@lquotes@;really@rquotes@;]} limited (task, protected, and explicitly limited records). However, this breaks privacy; worse, @LegalityTitle depend on the definition of accessibility.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0063-1]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, as above. Limited types have special accessibility, while nonlimited types have normal accessibility. However, a limited partial view with an access discriminant can only be completed by @Chg{Version=[3],New=[an immutably limited],Old=[a task, protected, or explicitly limited record]} type. That prevents accessibility from changing. A runtime accessibility check is required on generic formal types with access discriminants. However, changing between limited and nonlimited types would have far-reaching consequences for access discriminants @em which is uncomfortable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant. All types have special accessibility. This was considered early during the Ada 9X process, but was dropped for @lquotes@;unpleasant complexities@rquotes@;, which unfortunately aren't recorded. It does seem that an accessibility check would be needed on assignment of such a type, to avoid copying an object with a discriminant pointing to a local object into a more global object (and thus creating a dangling pointer).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, but access discriminants cannot have defaults. All types have special accessibility. This gets rid of the problems on assignment (you couldn't change such a discriminant), but it would be horribly incompatible with Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0063-1]} @ChgAdded{Version=[2],Text=[Any type may have an access discriminant, but access discriminants may have defaults only if they are @Chg{Version=[3],New=[of an immutably], Old=[a @lquotes@;really@rquotes@;]} limited type. This is the rule chosen for Ada 2005, as it is not incompatible, and it doesn't require weird accessibility checks.]} @end{Itemize} @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00402-01]} @ChgDeleted{Version=[2],Text=[@nt{Default_expression}s shall be provided either for all or for none of the discriminants of a @nt{known_@!discriminant_@!part}. No @nt<default_@!expression>s are permitted in a @nt<known_@!discriminant_@!part> in a declaration of a tagged type @Redundant[or a generic formal type].]} @begin(Reason) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The all-or-none rule is related to the rule that a discriminant constraint shall specify values for all discriminants. One could imagine a different rule that allowed a constraint to specify only some of the discriminants, with the others provided by default. Having defaults for discriminants has a special significance @em it allows objects of the type to be unconstrained, with the discriminants alterable as part of assigning to the object.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Defaults for discriminants of tagged types are disallowed so that every object of a tagged type is constrained, either by an explicit constraint, or by its initial discriminant values. This substantially simplifies the semantic rules and the implementation of inherited dispatching operations. For generic formal types, the restriction simplifies the type matching rules. If one simply wants a "default" value for the discriminants, a constrained subtype can be declared for future use.]} @end(Reason) @Leading@;For a type defined by a @nt<derived_type_definition>, if a @nt<known_discriminant_part> is provided in its declaration, then: @begin{Itemize} The parent subtype shall be constrained; If the parent type is not a tagged type, then each discriminant of the derived type shall be used in the constraint defining the parent subtype;@begin{ImplNote} This ensures that the new discriminant can share storage with an existing discriminant.@end{implnote} If a discriminant is used in the constraint defining the parent subtype, the subtype of the discriminant shall be statically compatible (see @RefSecNum{Statically Matching Constraints and Subtypes}) with the subtype of the corresponding parent discriminant. @begin(Reason) This ensures that on conversion (or extension via an extension aggregate) to a distantly related type, if the discriminants satisfy the target type's requirements they satisfy all the intermediate types' requirements as well. @end(Reason) @begin(Ramification) There is no requirement that the new discriminant have the same (or any) @nt<default_expression> as the parent's discriminant. @end(Ramification) @end{Itemize} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0102-1]} @ChgDeleted{Version=[3],Text=[The type of the @nt<default_expression>, if any, for an access discriminant shall be convertible to the anonymous access type of the discriminant (see @RefSecNum{Type Conversions}). @PDefn2{Term=[convertible],Sec=(required)}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Deleted]} @ChgDeleted{Version=[3],Text=[This requires convertibility of the designated subtypes.]} @end{ramification} @end{Legality} @begin{StaticSem} A @nt{discriminant_specification} declares a discriminant; the @nt{subtype_mark} denotes its subtype unless it is an access discriminant, in which case the discriminant's subtype is the anonymous access-to-variable subtype defined by the @nt{access_definition}. @Redundant[For a type defined by a @nt<derived_type_definition>, each discriminant of the parent type is either inherited, constrained to equal some new discriminant of the derived type, or constrained to the value of an expression.] @Defn{corresponding discriminants} When inherited or constrained to equal some new discriminant, the parent discriminant and the discriminant of the derived type are said to @i(correspond). Two discriminants also correspond if there is some common discriminant to which they both correspond. A discriminant corresponds to itself as well. @Defn{specified discriminant} If a discriminant of a parent type is constrained to a specific value by a @nt<derived_type_definition>, then that discriminant is said to be @i(specified) by that @nt<derived_type_definition>. @begin{Ramification} The correspondence relationship is transitive, symmetric, and reflexive. That is, if A corresponds to B, and B corresponds to C, then A, B, and C each corresponds to A, B, and C in all combinations.@end{ramification} @Defn2{Term=[depend on a discriminant], Sec=(for a @nt<constraint> or @nt<component_definition>)} A @nt{constraint} that appears within the definition of a discriminated type @i(depends on a discriminant) of the type if it names the discriminant as a bound or discriminant value. A @nt{component_definition} depends on a discriminant if its @nt{constraint} depends on the discriminant, or on a discriminant that corresponds to it. @begin(Ramification) A @nt{constraint} in a @nt{task_body} is not considered to @i(depend) on a discriminant of the task type, even if it names it. It is only the @nt<constraint>s in the type definition itself that are considered dependents. Similarly for protected types. @end(Ramification) @Leading@keepnext@Defn2{Term=[depend on a discriminant], Sec=(for a component)} A component @i(depends on a discriminant) if: @begin(itemize) Its @nt{component_definition} depends on the discriminant; or @begin{Ramification} A component does @i(not) depend on a discriminant just because its @nt<default_expression> refers to the discriminant.@end{ramification} It is declared in a @nt{variant_part} that is governed by the discriminant; or It is a component inherited as part of a @nt<derived_type_definition>, and the @nt<constraint> of the @i(parent_)@nt<subtype_indication> depends on the discriminant; or @begin{Reason} When the parent subtype depends on a discriminant, the parent part of the derived type is treated like a discriminant-dependent component. @end{Reason} @begin{Ramification} Because of this rule, we don't really need to worry about @lquotes@;corresponding@rquotes@; discriminants, since all the inherited components will be discriminant-dependent if there is a new @nt<known_discriminant_part> whose discriminants are used to constrain the old discriminants. @end{Ramification} It is a subcomponent of a component that depends on the discriminant. @end(itemize) @begin{Reason} The concept of discriminant-dependent (sub)components is primarily used in various rules that disallow renaming or 'Access, or specify that certain discriminant-changing assignments are erroneous. The goal is to allow implementations to move around or change the size of discriminant-dependent subcomponents upon a discriminant-changing assignment to an enclosing object. The above definition specifies that all subcomponents of a discriminant-dependent component or parent part are themselves discriminant-dependent, even though their presence or size does not in fact depend on a discriminant. This is because it is likely that they will move in a discriminant-changing assignment if they are a component of one of several discriminant-dependent parts of the same record. @end{Reason} Each value of a discriminated type includes a value for each component of the type that does not depend on a discriminant@Redundant[; this includes the discriminants themselves]. The values of discriminants determine which other component values are present in the value of the discriminated type. @begin{Honest} Which values are present might depend on discriminants of some ancestor type that are constrained in an intervening @nt<derived_type_definition>. That's why we say "values of discriminants" instead of "values of @i(the) discriminants" @em a subtle point.@end{honest} @Defn{known discriminants} @Defn2{Term=[discriminants], Sec=(known)} @Defn2{Term=[constrained], Sec=(subtype)} @Defn2{Term=[unconstrained], Sec=(subtype)} A type declared with a @nt<known_discriminant_part> is said to have @i(known discriminants); its first subtype is unconstrained. @Defn{unknown discriminants} @Defn2{Term=[discriminants], Sec=(unknown)} A type declared with an @nt<unknown_discriminant_part> is said to have @i(unknown discriminants). A type declared without a @nt<discriminant_part> has no discriminants, unless it is a derived type; if derived, such a type has the same sort of discriminants (known, unknown, or none) as its parent (or ancestor) type. A tagged class-wide type also has unknown discriminants. @Defn{class-wide type} @Defn{indefinite subtype} @Redundant[Any subtype of a type with unknown discriminants is an unconstrained and indefinite subtype (see @RefSecNum{Types and Subtypes} and @RefSecNum{Objects and Named Numbers}).] @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An @nt<unknown_discriminant_part> @lquotes@;(<>)@rquotes@; is only permitted in the declaration of a (generic or nongeneric) private type, private extension, @Chg{Version=[2],New=[incomplete type, ],Old=[]}or formal derived type.@Comment{That was always intended, but 8652/0007 was needed to make it true.} Hence, only such types, descendants thereof, and class-wide types can have unknown discriminants. An @nt<unknown_discriminant_part> is used to indicate that the corresponding actual or full type might have discriminants without defaults, or be an unconstrained array subtype. Tagged class-wide types are also considered to have unknown discriminants because discriminants can be added by type extensions, so the total number of discriminants of any given value of a tagged class-wide type is not known at compile time. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A subtype with unknown discriminants is indefinite, and hence an object of such a subtype needs explicit initialization.@Chg{Version=[2],New=[],Old=[ If the subtype is limited, no (stand-alone) objects can be declared since initialization is not permitted (though formal parameters are permitted, and objects of the actual/full type will generally be declarable).]} A limited private type with unknown discriminants is @lquotes@;extremely@rquotes@; limited;@Chg{Version=[2],New=[ objects of],Old=[]} such a type @Chg{Version=[2],New=[ can be initialized only by subprograms (either procedures with a parameter of the type, or a function returning the type) declared in the package. Subprograms declared elsewhere can operate on and even return the type, but they can only initialize the object by calling (ultimately) a subprogram in the package declaring the type. Such a type],Old=[]} is useful for keeping complete control over object creation within the package declaring the type. A partial view of a type might have unknown discriminants, while the full view of the same type might have known, unknown, or no discriminants@Chg{New=[.],Old=[,]} @end(Discussion) @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[For an access discriminant, its], Old=[An]} @nt<access_definition> is elaborated when the value of @Chg{Version=[2],New=[the],Old=[a corresponding]} access discriminant is defined@Chg{Version=[2],New=[:],Old=[, either]} by evaluation of its @nt<default_expression>@Chg{Version=[2],New=[,],Old=[ or]} by elaboration of a @nt<discriminant_constraint>@Chg{Version=[2],New=[, or by an assignment that initializes the enclosing object.],Old=[. @Redundant[The elaboration of an @nt<access_definition> creates the anonymous access type. When the expression defining the access discriminant is evaluated, it is converted to this anonymous access type (see @RefSecNum{Type Conversions}).]]} @PDefn2{Term=[implicit subtype conversion],Sec=(access discriminant)} @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[The],Old=[This]} conversion@Chg{Version=[2],New=[ of the @nt{expression} defining the access discriminant to the anonymous access type],Old=[]} raises @Chg{Version=[2],New=[Program_Error], Old=[Constraint_Error if the initial value is @key(null), or,]} for an object created by an allocator of an access type T, if the initial value is an access parameter that designates a view whose accessibility level is deeper than that of T. @end(Ramification) @end{RunTime} @begin{Notes} If a discriminated type has @nt<default_expression>s for its discriminants, then unconstrained variables of the type are permitted, and the values of the discriminants can be changed by an assignment to such a variable. If defaults are not provided for the discriminants, then all variables of the type are constrained, either by explicit constraint or by their initial value; the values of the discriminants of such a variable cannot be changed after initialization. @begin(Discussion) This connection between discriminant defaults and unconstrained variables can be a source of confusion. For Ada 95, we considered various ways to break the connection between defaults and unconstrainedness, but ultimately gave up for lack of a sufficiently simple and intuitive alternative. @Defn{mutable} An unconstrained discriminated subtype with defaults is called a @i{mutable} subtype, and a variable of such a subtype is called a mutable variable, because the discriminants of such a variable can change. There are no mutable arrays (that is, the bounds of an array object can never change), because there is no way in the language to define default values for the bounds. Similarly, there are no mutable class-wide subtypes, because there is no way to define the default tag, and defaults for discriminants are not allowed in the tagged case. Mutable tags would also require a way for the maximum possible size of such a class-wide subtype to be known. (In some implementations, all mutable variables are allocated with the maximum possible size. This approach is appropriate for real-time applications where implicit use of the heap is inappropriate.) @end(Discussion) The @nt{default_expression} for a discriminant of a type is evaluated when an object of an unconstrained subtype of the type is created. Assignment to a discriminant of an object (after its initialization) is not allowed, since the name of a discriminant is a constant; neither @nt{assignment_statement}s nor assignments inherent in passing as an @key(in out) or @key(out) parameter are allowed. Note however that the value of a discriminant can be changed by assigning to the enclosing object, presuming it is an unconstrained variable. @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An @nt{unknown_discriminant_part} is permitted only in the declaration of a private type (including generic formal private), private extension, @Chg{Version=[2],New=[incomplete type, ],Old=[]}or generic formal derived type. These are the things that will have a corresponding completion or generic actual, which will either define the discriminants, or say there are none. The (<>) indicates that the actual/full subtype might be an indefinite subtype. An @nt{unknown_discriminant_part} is not permitted in a normal untagged derived type declaration, because there is no separate full type declaration for such a type. Note that (<>) allows unconstrained array bounds; those are somewhat like undefaulted discriminants. For a derived type, either the discriminants are inherited as is, or completely respecified in a new @nt<discriminant_part>. In this latter case, each discriminant of the parent type shall be constrained, either to a specific value, or to equal one of the new discriminants. Constraining a parent type's discriminant to equal one of the new discriminants is like a renaming of the discriminant, except that the subtype of the new discriminant can be more restrictive than that of the parent's one. In any case, the new discriminant can share storage with the parent's discriminant. @end(Discussion) A discriminant that is of a named access type is not called an access discriminant; that term is used only for discriminants defined by an @nt<access_definition>. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of discriminated types:) @begin(Example) @key(type) Buffer(Size : Buffer_Size := 100) @key(is) --@RI[ see @RefSecNum(Integer Types)] @key(record) Pos : Buffer_Size := 0; Value : String(1 .. Size); @key(end) @key(record); @key(type) Matrix_Rec(Rows, Columns : Integer) @key(is) @key(record) Mat : Matrix(1 .. Rows, 1 .. Columns); --@RI[ see @RefSecNum(Array Types)] @key(end) @key(record); @key(type) Square(Side : Integer) @key(is) @key(new) Matrix_Rec(Rows => Side, Columns => Side); @key(type) Double_Square(Number : Integer) @key(is) @key(record) Left : Square(Number); Right : Square(Number); @key(end) @key(record); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[2],New=[@key(task type) Worker(Prio : System.Priority; Buf : @key(access) Buffer)@Chg{Version=[3],New=[ @key(with) Priority => Prio @key(is) --@RI[ see @RefSecNum{Task Priorities}]],Old=[@key(is)]} --@RI[ discriminants used to parameterize the task type (see @RefSecNum{Task Units and Task Objects})]@Chg{Version=[3],New=[],Old=[ @key(pragma) Priority(Prio); --@RI[ see @RefSecNum{Task Priorities}]]} @key(entry) Fill; @key(entry) Drain; @key(end) Worker;],Old=[@key(type) Item(Number : Positive) @key(is) @key(record) Content : Integer; --@RI[ no component depends on the discriminant] @key(end) @key(record);]} @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{discriminant_specification} is modified to allow an @i{access discriminant}, with a type specified by an @nt{access_definition} (see @RefSecNum{Access Types}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Discriminants are allowed on all composite types other than array@Chg{Version=[2],New=[ and interface],Old=[]} types. Discriminants may be of an access type. @end{Extend83} @begin{DiffWord83} @nt{Discriminant_part}s are not elaborated, though an @nt<access_definition> is elaborated when the discriminant is initialized. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Access discriminants (anonymous access types used as a discriminant) can be used on any type allowing discriminants. Defaults aren't allowed on discriminants of nonlimited types, however, so that accessibility problems don't happen on assignment.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[ @nt{null_exclusion} can be used in the declaration of a discriminant.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0007],ARef=[AI95-00098-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was clarified so that types that cannot have discriminants cannot have an @nt{unknown_discriminant_part}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent interfaces from having discriminants. We don't want interfaces to have any components.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[Removed wording which implied or required an access discriminant to have an access-to-object type (anonymous access types can now be access-to-subprogram types as well).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[Fixed the wording of the introduction to this @Chg{Version=[3],New=[subclause],Old=[clause]} to reflect that both incomplete and partial views can have unknown discriminants. That was always true, but for some reason this wording specified partial views.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the new term @lquotes@;explicitly limited record@rquotes, which makes the intent much clearer (and eliminates confusion with derived types that happen to contain the reserved word @key[limited]).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0063-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Changed the rules for when access discriminants can have defaults to depend on the new definition for immutably limited types; this will help ensure that unusual corner cases are properly handled. Note that the Ada 2005 rule was unintentionally incompatible with the Ada 95 rule (as enforced by the ACATS); this change brings it back into alignment with actual practice. So there should be no practical incompatibility.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0214-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} A limited tagged type may now have defaults for its discriminants.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0102-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Moved implicit conversion @LegalityName to @RefSecNum{The Context of Overload Resolution}.]} @end{DiffWord2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledSubClause{Discriminant Constraints} @begin{Intro} A @nt<discriminant_constraint> specifies the values of the discriminants for a given discriminated type. @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The rules in this @Chg{Version=[3],New=[subclause],Old=[clause]} are intentionally parallel to those given in @RefSec{Record Aggregates}. @end{MetaRules} @begin{Syntax} @Syn{lhs=<discriminant_constraint>,rhs=" (@Syn2{discriminant_association} {, @Syn2{discriminant_association}})"} @Syn{lhs=<discriminant_association>,rhs=" [@SynI{discriminant_}@Syn2{selector_name} {| @SynI{discriminant_}@Syn2{selector_name}} =>] @Syn2{expression}"} @begin{SyntaxText} @Defn{named discriminant association} A @nt<discriminant_association> is said to be @i(named) if it has one or more @i(discriminant_)@nt<selector_name>s; @Defn{positional discriminant association} it is otherwise said to be @i(positional). In a @nt<discriminant_constraint>, any positional associations shall precede any named associations. @end{SyntaxText} @end{Syntax} @begin{Resolution} Each @nt<selector_name> of a named @nt<discriminant_@!association> shall resolve to denote a discriminant of the subtype being constrained; @Defn2{Term=[associated discriminants], Sec=(of a named @nt<discriminant_association>)} the discriminants so named are the @i(associated discriminants) of the named association. @Defn2{Term=[associated discriminants], Sec=(of a positional @nt<discriminant_association>)} For a positional association, the @i(associated discriminant) is the one whose @nt<discriminant_@!specification> occurred in the corresponding position in the @nt<known_@!discriminant_@!part> that defined the discriminants of the subtype being constrained. @PDefn2{Term=[expected type], Sec=(discriminant_association expression)} The expected type for the @nt{expression} in a @nt{discriminant_association} is that of the associated discriminant(s). @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0041-1]} A @nt{discriminant_constraint} is only allowed in a @nt{subtype_indication} whose @nt{subtype_mark} denotes either an unconstrained discriminated subtype, or an unconstrained access subtype whose designated subtype is an unconstrained discriminated subtype. @Chg{New=[However, in the case of @Chg{Version=[2],New=[an],Old=[a general]} access subtype, a @nt{discriminant_@!constraint} is @Chg{Version=[3],New=[legal only if any dereference of a value of the access type is known to be constrained (see @RefSecNum{Objects and Named Numbers})], Old=[illegal if @Chg{Version=[2],New=[the designated type has a partial view that is constrained or, for a general access subtype, has @nt{default_expression}s for its discriminants],Old=[]}]}], Old=[there is a place within the immediate scope of the designated subtype where the designated subtype's view is constrained]}. @Chg{Version=[2],New=[In addition to the places where @LegalityTitle@; normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.@PDefn{generic contract issue}],Old=[]}@Chg{Version=[3], New=[],Old=[@Chg{Version=[2], New=[ In a generic body, this rule is checked presuming all formal access types of the generic might be general access types, and all untagged discriminated formal types of the generic might have @nt{default_expression}s for their discriminants.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[@Chg{New=[The second rule is necessary to prevent assignments that change the discriminant of a constrained object. See the defect report for examples.],Old=[]}]} @end{Reason} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[The second rule is necessary to prevent objects from changing so that they no longer match their constraint. In Ada 95, we attempted to prevent this by banning every case where an aliased object could be unconstrained or be changed by an enclosing assignment. New ways to cause this problem were being discovered frequently, meaning that new rules had to be dreamed up to cover them. Meanwhile, aliased objects and components were getting more and more limited. In Ada 2005, we sweep away all of that cruft and replace it by a simple rule @lquotes@;thou shalt not create an access subtype that can point to an item whose discriminants can be changed by assignment@rquotes@;.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Text=[The second rule will only use the indefinite or dereference bullets in the definition of @ldquote@;known to be constrained@rdquote. The rule is worded in terms of @ldquote@;known to be constrained@rdquote in order to capture the special rules that apply in generic bodies (rather than repeating them and getting them subtly wrong).]} @end{Discussion} A named @nt<discriminant_association> with more than one @nt<selector_name> is allowed only if the named discriminants are all of the same type. A @nt<discriminant_constraint> shall provide exactly one value for each discriminant of the subtype being constrained. @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0102-1]} @ChgDeleted{Version=[3],Text=[The @nt<expression> associated with an access discriminant shall be of a type convertible to the anonymous access type. @PDefn2{Term=[convertible],Sec=(required)}]} @begin(Ramification) @ChgRef{Version=[3],Kind=[Revised]} @Chg{Version=[3],New=[In addition, @RefSecNum{The Context of Overload Resolution} requires that the @nt{expression} associated with an access discriminant is convertible (see @RefSecNum{Type Conversions}) to the anonymous access type. ],Old=[]}This implies both convertibility of designated types, and static accessibility. This implies that if an object of type T with an access discriminant is created by an allocator for an access type A, then it requires that the type of the @nt<expression> associated with the access discriminant have an accessibility level that is not statically deeper than that of A. This is to avoid dangling references. @end(Ramification) @end{Legality} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(discriminant constraint with a subtype)} A @nt{discriminant_constraint} is @i(compatible) with an unconstrained discriminated subtype if each discriminant value belongs to the subtype of the corresponding discriminant. @begin{Ramification} The "dependent compatibility check" has been eliminated in Ada 95. Any checking on subcomponents is performed when (and if) an object is created.@end{ramification} @begin{Discussion} There is no need to define compatibility with a constrained discriminated subtype, because one is not allowed to constrain it again.@end{discussion} @PDefn2{Term=[satisfies], Sec=(a discriminant constraint)} A composite value @i(satisfies) a discriminant constraint if and only if each discriminant of the composite value has the value imposed by the discriminant constraint. @PDefn2{Term=[elaboration], Sec=(discriminant_constraint)} For the elaboration of a @nt{discriminant_constraint}, the @nt{expression}s in the @nt{discriminant_association}s are evaluated in an arbitrary order and converted to the type of the associated discriminant (which might raise Constraint_Error @em see @RefSecNum{Type Conversions}); the @nt{expression} of a named association is evaluated (and converted) once for each associated discriminant. @PDefn2{Term=[implicit subtype conversion],Sec=(discriminant values)} The result of each evaluation and conversion is the value imposed by the constraint for the associated discriminant. @begin{Reason} We convert to the type, not the subtype, so that the definition of compatibility of discriminant constraints is not vacuous.@end{reason} @end{RunTime} @begin{Notes} The rules of the language ensure that a discriminant of an object always has a value, either from explicit or implicit initialization. @begin(Discussion) Although it is illegal to constrain a class-wide tagged subtype, it is possible to have a partially constrained class-wide subtype: If the subtype S is defined by T(A => B), then S'Class is partially constrained in the sense that objects of subtype S'Class have to have discriminants corresponding to A equal to B, but there can be other discriminants defined in extensions that are not constrained to any particular value. @end(Discussion) @end{Notes} @begin{Examples} @Leading@keepnext@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @i{Examples (using types declared above in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Discriminants)):} @begin(Example) Large : Buffer(200); --@RI[ constrained, always 200 characters] --@RI[ (explicit discriminant value)] Message : Buffer; --@RI[ unconstrained, initially 100 characters] --@RI[ (default discriminant value)] Basis : Square(5); --@RI[ constrained, always 5 by 5] Illegal : Square; --@RI[ illegal, a Square has to be constrained] @end(Example) @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Dependent compatibility checks are no longer performed on subtype declaration. Instead they are deferred until object creation (see @RefSecNum(Object Declarations)). This is upward compatible for a program that does not raise Constraint_Error. @end{Inconsistent83} @begin{DiffWord83} Everything in RM83-3.7.2(7-12), which specifies the initial values for discriminants, is now redundant with 3.3.1, 6.4.1, 8.5.1, and 12.4. Therefore, we don't repeat it here. Since the material is largely intuitive, but nevertheless complicated to state formally, it doesn't seem worth putting it in a "NOTE." @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0008],ARef=[AI95-00168-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The Corrigendum added a restriction on @nt{discriminant_constraint}s for general access subtypes. Such constraints are prohibited if the designated type can be treated as constrained somewhere in the program. Ada 2005 goes further and prohibits such @nt{discriminant_constraint}s if the designated type has (or might have, in the case of a formal type) defaults for its discriminants. The use of general access subtypes is rare, and this eliminates a boatload of problems that required many restrictions on the use of aliased objects and components (now lifted). Similarly, Ada 2005 prohibits @nt{discriminant_constraint}s on any access type whose designated type has a partial view that is constrained. Such a type will not be constrained in the heap to avoid privacy problems. Again, the use of such subtypes is rare (they can only happen within the package and its child units).]} @end{Incompatible95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the rules on access subtypes having discriminant constraints to depend on the @ldquote@;known to be constrained@rdquote rules. This centralizes the rules so that future fixes need to be made in only one place, as well as fixing bugs in obscure cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0102-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Moved implicit conversion @LegalityName to @RefSecNum{The Context of Overload Resolution}.]} @end{Diffword2005} @LabeledSubClause{Operations of Discriminated Types} @begin{Intro} @Redundant[If a discriminated type has @nt<default_expression>s for its discriminants, then unconstrained variables of the type are permitted, and the discriminants of such a variable can be changed by assignment to the variable. For a formal parameter of such a type, an attribute is provided to determine whether the corresponding actual parameter is constrained or unconstrained.] @end{Intro} @begin{StaticSem} @Leading@Keepnext@;For @PrefixType{a @nt<prefix> A that is of a discriminated type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @ChgAttribute{Version=[3], Kind=[Revised], ChginAnnex=[T], Leading=[F], Prefix=<A>, AttrName=<Constrained>, ARef=[AI05-0214-1], Text=[Yields the value True if A denotes a constant, a value, @Chg{Version=[3],New=[a tagged object, ],Old=[]}or a constrained variable, and False otherwise.]} @begin(ImplNote) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0214-1]} This attribute is primarily used on parameters, to determine whether the discriminants can be changed as part of an assignment. The Constrained attribute is statically True for @key(in) parameters. For @key(in out) and @key(out) parameters of a discriminated type, the value of this attribute needs to be passed as an implicit parameter, in general. However, if the type @Chg{Version=[3],New=[is tagged or ],Old=[]}does not have defaults for its discriminants, the attribute is statically True, so no implicit parameter is needed. Parameters of a limited @Chg{Version=[3],New=[untagged ],Old=[]}type with defaulted discriminants need this implicit parameter, unless there are no nonlimited views, because they might be passed to a subprogram whose body has visibility on a nonlimited view of the type, and hence might be able to assign to the object and change its discriminants. @end(ImplNote) @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0214-1]} @ChgAdded{Version=[3],Text=[All tagged objects are known to be constrained (as nonlimited tagged types cannot have discriminant defaults, and limited tagged objects are immutably limited), and are always considered constrained by this attribute to avoid distributed overhead for parameters of limited classwide types, as limited tagged objects may technically be unconstrained if they use defaulted discriminants. Such objects still cannot have their discriminants changed, as assignment is not supported for them, so there is no use for this attribute that would justify the overhead of passing it with all classwide parameters.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0214-1]} @ChgAdded{Version=[3],Text=[If the type of A is a type derived from an untagged partial view of a tagged type such that it is not a tagged type, then A is not considered a tagged object, and A'Constrained can return either True or False depending on the nature of the object.]} @end{Discussion} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} The execution of a construct is erroneous if the construct has a constituent that is a @nt<name> denoting a subcomponent that depends on discriminants, and the value of any of these discriminants is changed by this execution between evaluating the @nt<name> and the last use (within this execution) of the subcomponent denoted by the @nt<name>. @begin{Ramification} This rule applies to @nt<assignment_statement>s, calls (except when the discriminant-dependent subcomponent is an @key(in) parameter passed by copy), @nt<indexed_component>s, and @nt<slice>s. Ada 83 only covered the first two cases. AI83-00585 pointed out the situation with the last two cases. The cases of @nt<object_renaming_declaration>s and generic formal @key(in out) objects are handled differently, by disallowing the situation at compile time. @end{Ramification} @end{Erron} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Defn{extensions to Ada 83} For consistency with other attributes, we are allowing the @Chg{New=[@nt{prefix}],Old=[prefix]} of Constrained to be a value as well as an object of a discriminated type, and also an implicit dereference. These extensions are not important capabilities, but there seems no reason to make this attribute different from other similar attributes. We are curious what most Ada 83 compilers do with F(1).X'Constrained. We now handle in a general way the cases of erroneousness identified by AI83-00585, where the @nt<prefix> of an @nt<indexed_component> or @nt<slice> is discriminant-dependent, and the evaluation of the index or discrete range changes the value of a discriminant. @end{Extend83} @begin{DiffWord83} We have moved all discussion of erroneous use of @nt<name>s that denote discriminant-dependent subcomponents to this subclause. In Ada 83, it used to appear separately under @nt{assignment_statement}s and subprogram calls. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0214-1]} @ChgAdded{Version=[3],Text=[A'Constrained is now defined to return True for any A that is a tagged object. This doesn't change the result for any A allowed by previous versions of Ada; the change is necessary to avoid unnecessary overhead for limited tagged parameters.]} @end{DiffWord2005} @LabeledClause{Record Types} @begin{Intro} @Defn{record} @Defn{record type} A record object is a composite object consisting of named components. The value of a record object is a composite value consisting of the values of the components. @IndexSee{Term=[structure],See=(record type)} @end{Intro} @begin{Syntax} @Syn{lhs=<record_type_definition>,rhs="[[@key{abstract}] @key{tagged}] [@key{limited}] @Syn2{record_definition}"} @Syn{lhs=<record_definition>,rhs=" @key{record} @Syn2{component_list} @key{end} @key{record} | @key{null record}"} @Syn{lhs=<component_list>,rhs=" @Syn2{component_item} {@Syn2{component_item}} | {@Syn2{component_item}} @Syn2{variant_part} | @key{null};"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<component_item>,rhs="@Syn2{component_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<component_declaration>,rhs=" @Syn2{defining_identifier_list} : @Syn2{component_definition} [:= @Syn2{default_expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(component_declaration default_expression)} The expected type for the @nt<default_expression>, if any, in a @nt<component_declaration> is the type of the component. @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A @nt<default_expression> is not permitted if the component is of a limited type.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]}@ChgNote{This is not THE definition of component} @PDefn2{Term=[components], Sec=(of a record type)} Each @nt<component_declaration> declares a @Chg{Version=[2],New=[component],Old=[@i(component)]} of the record type. Besides components declared by @nt<component_declaration>s, the components of a record type include any components declared by @nt<discriminant_specification>s of the record type declaration. @Redundant[The identifiers of all components of a record type shall be distinct.] @begin{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The identifiers of all components of a record type have to be distinct because they are all declared immediately within the same declarative region. See @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules}. @end{theproof} Within a @nt{type_declaration}, a @nt{name} that denotes a component, protected subprogram, or entry of the type is allowed only in the following cases: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1],ARef=[AI05-0295-1]} A @nt{name} that denotes any component, protected subprogram, or entry is allowed within @Chg{Version=[3],New=[an @nt{aspect_specification}, an operational item, or ],Old=[]}a representation item that occurs within the declaration of the composite type. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} A @nt{name} that denotes a noninherited discriminant is allowed within the declaration of the type, but not within the @nt{discriminant_part}. If the discriminant is used to define the constraint of a component, the bounds of an entry family, or the constraint of the parent subtype in a @nt<derived_type_definition>@Chg{Version=[3],New=[,],Old=[]} then its name shall appear alone as a @nt<direct_name> (not as part of a larger expression or expanded name). A discriminant shall not be used to define the constraint of a scalar component.@Defn2{Term=[discriminant],Sec=[use in a record definition]}@ChgNote{New index entry} @begin{Reason} The penultimate restriction simplifies implementation, and allows the outer discriminant and the inner discriminant or bound to possibly share storage. @end{reason} @begin{Ramification} Other rules prevent such a discriminant from being an inherited one. @end{ramification} @begin{Reason} The last restriction is inherited from Ada 83. The restriction is not really necessary from a language design point of view, but we did not remove it, in order to avoid unnecessary changes to existing compilers. @end{Reason} @begin{Discussion} Note that a discriminant can be used to define the constraint for a component that is of an access-to-composite type. @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} The above rules, and a similar one in @RefSecNum{Subprogram Declarations} for formal parameters, are intended to allow initializations of components or parameters to occur in @Chg{Version=[2], New=[a (nearly)],Old=[an]} arbitrary order @em whatever order is most efficient@Chg{Version=[2],New=[ (subject to the restrictions of @RefSecNum{Object Declarations})],Old=[]}, since one @nt{default_expression} cannot depend on the value of another one. @Chg{Version=[2],New=[They],Old=[It]} also prevent circularities. @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} Inherited discriminants are not allowed to be denoted, except within @Chg{Version=[3],New=[@nt{aspect_specification}s and ],Old=[]}representation items. However, the @SynI{discriminant_}@nt{selector_name} of the parent @nt{subtype_indication} is allowed to denote a discriminant of the parent. @end{Ramification} @end{Itemize} If the name of the current instance of a type (see @RefSecNum{The Context of Overload Resolution}) is used to define the constraint of a component, then it shall appear as a @nt{direct_name} that is the @nt<prefix> of an @nt{attribute_reference} whose result is of an access type, and the @nt{attribute_reference} shall appear alone. @begin{Reason} This rule allows T'Access or T'Unchecked_Access, but disallows, for example, a range constraint (1..T'Size). Allowing things like (1..T'Size) would mean that a per-object constraint could affect the size of the object, which would be bad. @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[@Defn{explicitly limited record} @Defn2{Term=[record],Sec=(explicitly limited)} If a @Chg{Version=[3],New=[@nt{record_type_definition}],Old=[@ntf{record_type_declaration}]} includes the reserved word @key{limited}, the type is called an @i<explicitly limited record> type.]} @PDefn2{Term=[nominal subtype], Sec=(of a record component)} The @nt{component_definition} of a @nt<component_declaration> defines the (nominal) subtype of the component. If the reserved word @key(aliased) appears in the @nt{component_definition}, then the component is aliased (see @RefSecNum{Access Types}). @begin(Ramification) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In this case, the nominal subtype cannot be an unconstrained discriminated subtype. See @RefSecNum{Array Types}.]} @end(Ramification) @Defn{null record} If the @nt<component_list> of a record type is defined by the reserved word @key(null) and there are no discriminants, then the record type has no components and all records of the type are @i(null records). A @nt<record_definition> of @key{null record} is equivalent to @key{record null; end record}. @begin{Ramification} This short-hand is available both for declaring a record type and a record extension @em see @RefSecNum(Type Extensions). @end{ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(record_type_definition)} The elaboration of a @nt{record_type_definition} creates the record type and its first subtype, and consists of the elaboration of the @nt<record_definition>. @PDefn2{Term=[elaboration], Sec=(record_definition)} The elaboration of a @nt<record_definition> consists of the elaboration of its @nt{component_list}, if any. @PDefn2{Term=[elaboration], Sec=(component_list)} The elaboration of a @nt{component_list} consists of the elaboration of the @nt{component_item}s and @nt{variant_part}, if any, in the order in which they appear. @PDefn2{Term=[elaboration], Sec=(component_declaration)} The elaboration of a @nt{component_declaration} consists of the elaboration of the @nt{component_definition}. @begin(Discussion) If the @nt<defining_identifier_list> has more than one @nt<defining_identifier>, we presume here that the transformation explained in @RefSecNum(Object Declarations) has already taken place. Alternatively, we could say that the @nt<component_definition> is elaborated once for each @nt<defining_identifier> in the list. @end(Discussion) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Defn{per-object expression} @Defn{per-object constraint} @Defn{entry index subtype} Within the definition of a composite type, if a @nt<component_definition> or @nt<discrete_subtype_definition> (see @RefSecNum{Entries and Accept Statements}) includes a @nt<name> that denotes a discriminant of the type, or that is an @nt<attribute_reference> whose @nt<prefix> denotes the current instance of the type, the expression containing the @nt<name> is called a @i(per-object expression), and the @Chg{New=[@nt{constraint} or @nt{range}],Old=[constraint]} being defined is called a @i(per-object constraint). @PDefn2{Term=[elaboration], Sec=(component_definition)} For the elaboration of a @nt{component_definition} of a @nt<component_declaration>@Chg{New=[ or the @nt{discrete_@!subtype_@!definition} of an @nt{entry_@!declaration} for an entry family (see @RefSecNum{Entries and Accept Statements})],Old=[]},@Chg{Version=[2], New=[ if the component subtype is defined by an @nt{access_definition} or], Old=[]} if the @nt{constraint} @Chg{New=[or @nt{range}],Old=[]} of the @nt{subtype_indication} @Chg{New=[or @nt{discrete_@!subtype_@!definition}],Old=[]} is not a per-object constraint, then the@Chg{Version=[2],New=[ @nt{access_definition},],Old=[]} @nt{subtype_indication}@Chg{Version=[2],New=[,],Old=[]} @Chg{New=[or @nt{discrete_@!subtype_@!definition}],Old=[]} is elaborated. On the other hand, if the @nt{constraint} @Chg{New=[or @nt{range}],Old=[]} is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. @Chg{New=[Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant.],Old=[]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0002],ARef=[AI95-00171-01]} @Chg{New=[@PDefn2{Term=[Elaboration],Sec=(per-object constraint)}When a per-object constraint is elaborated @Redundant[(as part of creating an object)], each per-object expression of the constraint is evaluated. For other expressions, the values determined during the elaboration of the @nt{component_@!definition} or @nt{entry_@!declaration} are used. Any checks associated with the enclosing @nt{subtype_indication} or @nt{discrete_subtype_definition} are performed@Redundant[, including the subtype compatibility check (see @RefSecNum{Subtype Declarations}),] and the associated subtype is created.], Old=[]} @begin(Discussion) The evaluation of other expressions that appear in @nt<component_definition>s and @nt<discrete_subtype_definition>s is performed when the type definition is elaborated. The evaluation of expressions that appear as @nt<default_expression>s is postponed until an object is created. Expressions in representation items that appear within a composite type definition are evaluated according to the rules of the particular representation item. @end(Discussion) @end{RunTime} @begin{Notes} A @nt<component_declaration> with several identifiers is equivalent to a sequence of single @nt<component_declaration>s, as explained in @RefSecNum{Object Declarations}. The @nt<default_expression> of a record component is only evaluated upon the creation of a default-initialized object of the record type (presuming the object has the component, if it is in a @nt<variant_part> @em see @RefSecNum{Object Declarations}). The subtype defined by a @nt<component_definition> (see @RefSecNum(Array Types)) has to be a definite subtype. If a record type does not have a @nt<variant_part>, then the same components are present in all values of the type. A record type is limited if it has the reserved word @key[limited] in its definition, or if any of its components are limited (see @RefSecNum{Limited Types}). @PDefn2{Term=[predefined operations],Sec=(of a record type)} The predefined operations of a record type include membership tests, qualification, and explicit conversion. If the record type is nonlimited, they also include assignment and the predefined equality operators. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A component of a record can be named with a @nt<selected_component>. A value of a record can be specified with a @nt<record_aggregate>@Chg{Version=[2], New=[],Old=[, unless the record type is limited]}. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of record type declarations: ) @begin(Example) @key(type) Date @key(is) @key(record) Day : Integer @key(range) 1 .. 31; Month : Month_Name; Year : Integer @key(range) 0 .. 4000; @key(end) @key(record); @key(type) Complex @key(is) @key(record) Re : Real := 0.0; Im : Real := 0.0; @key(end) @key(record); @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of record variables: ) @end{WideAbove} @begin(Example) Tomorrow, Yesterday : Date; A, B, C : Complex; --@RI[ both components of A, B, and C are implicitly initialized to zero ] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt<component_declaration> is modified to use @nt<component_definition> (instead of @ntf<component_subtype_definition>). The effect of this change is to allow the reserved word @key(aliased) before the @ntf<component_subtype_definition>. A short-hand is provided for defining a null record type (and a null record extension), as these will be more common for abstract root types (and derived types without additional components). The syntax rule for @nt{record_type_definition} is modified to allow the reserved words @key{tagged} and @key{limited}. Tagging is new. Limitedness is now orthogonal to privateness. In Ada 83 the syntax implied that limited private was sort of more private than private. However, limitedness really has nothing to do with privateness; limitedness simply indicates the lack of assignment capabilities, and makes perfect sense for nonprivate types such as record types. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The syntax rules now allow @Chg{New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]} to appear in a @nt{record_definition}. This is not a language extension, because @LegalityName@;s prevent all language-defined representation clauses from appearing there. However, an implementation-defined @nt{attribute_definition_clause} could appear there. The reason for this change is to allow the rules for @Chg{New=[@nt{aspect_clause}s],Old=[@nt{representation_clause}s]} and representation pragmas to be as similar as possible. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Record components can have an anonymous access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Limited components can be initialized, so long as the expression is one that allows building the object in place (such as an @nt{aggregate} or @nt{function_call}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Improved the description of the elaboration of per-object constraints.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Defined @i{explicitly limited record} type to use in other rules.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{component_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Variant Parts and Discrete Choices} @begin{Intro} A record type with a @nt<variant_part> specifies alternative lists of components. Each @nt<variant> defines the components for the value or values of the discriminant covered by its @nt<discrete_choice_list>. @begin{Discussion} @RootDefn{cover a value} @nt{Discrete_choice_list}s and @nt{discrete_choice}s are said to @i(cover) values as defined below; which @nt{discrete_choice_list} covers a value determines which of various alternatives is chosen. These are used in @nt{variant_part}s, @nt{array_aggregate}s, and @nt{case_statement}s. @end{Discussion} @end{Intro} @begin{MetaRules} The definition of @lquotes@;cover@rquotes@; in this subclause and the rules about discrete choices are designed so that they are also appropriate for array aggregates and case statements. The rules of this subclause intentionally parallel those for case statements. @end{MetaRules} @begin{Syntax} @Syn{lhs=<variant_part>,rhs=" @key{case} @SynI{discriminant_}@Syn2{direct_name} @key{is} @Syn2{variant} {@Syn2{variant}} @key{end} @key{case};"} @Syn{lhs=<variant>,rhs=" @key{when} @Syn2{discrete_choice_list} => @Syn2{component_list}"} @Syn{lhs=<discrete_choice_list>,rhs="@Syn2{discrete_choice} {| @Syn2{discrete_choice}}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0158-1]} @Syn{lhs=<discrete_choice>,rhs="@Chg{Version=[3],New=[@Syn2{choice_expression}],Old=[@Syn2{expression}]} | @Chg{Version=[3],New=[@SynI{discrete_}@Syn2{subtype_indication} | @Syn2{range}],Old=[@Syn2{discrete_range}]} | @key{others}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[discriminant], Sec=(of a @nt<variant_part>)} The @i(discriminant_)@nt{direct_name} shall resolve to denote a discriminant (called the @i(discriminant of the @nt<variant_part>)) specified in the @nt{known_discriminant_part} of the @nt{full_type_declaration} that contains the @nt{variant_part}. @PDefn2{Term=[expected type], Sec=(variant_part discrete_choice)} The expected type for each @nt{discrete_choice} in a @nt<variant> is the type of the discriminant of the @nt{variant_part}. @begin{Ramification} A @nt<full_type_declaration> with a @nt<variant_part> has to have a (new) @nt<known_discriminant_part>; the discriminant of the @nt<variant_part> cannot be an inherited discriminant. @end{Ramification} @end{Resolution} @begin{Legality} The discriminant of the @nt{variant_part} shall be of a discrete type. @begin{Ramification} It shall not be of an access type, named or anonymous.@end{ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} The @Chg{Version=[3],New=[@nt{choice_expression}s, @nt{subtype_indication}s, and @nt{range}s],Old=[@nt{expression}s and @nt{discrete_range}s]} given as @nt{discrete_choice}s in a @nt{variant_part} shall be static. The @nt{discrete_choice} @key(others) shall appear alone in a @nt{discrete_choice_list}, and such a @nt{discrete_choice_list}, if it appears, shall be the last one in the enclosing construct. @Leading@PDefn2{Term=[cover a value], Sec=(by a @nt{discrete_choice})} A @nt<discrete_choice> is defined to @i(cover a value) in the following cases: @begin(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} A @nt{discrete_choice} that is @Chg{Version=[3],New=[a @nt{choice_expression}],Old=[an @nt{expression}]} covers a value if the value equals the value of the @Chg{Version=[3],New=[@nt{choice_expression}],Old=[@nt{expression}]} converted to the expected type. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0153-3],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A @nt{discrete_choice} that is a @nt{subtype_indication} covers all values (possibly none) that belong to the subtype and that satisfy the static predicate of the subtype (see @RefSecnum{Subtype Predicates}).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A dynamic predicate is never allowed in this case (for @nt{variant}s, @nt{case_statement}s, and @nt{case_expression}s, a subtype with a dynamic predicate isn't static and thus isn't allowed in a @nt{discrete_choice}, and for a choice in an @nt{array_aggregate}, a dynamic predicate is explicitly disallowed @em see @RefSecnum{Subtype Predicates}).]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} A @nt{discrete_choice} that is a @Chg{Version=[3],New=[@nt{range}],Old=[@nt{discrete_range}]} covers all values (possibly none) that belong to the range. The @nt{discrete_choice} @key{others} covers all values of its expected type that are not covered by previous @nt{discrete_choice_list}s of the same construct. @begin(Ramification) For @nt{case_statement}s, this includes values outside the range of the static subtype (if any) to be covered by the choices. It even includes values outside the base range of the case expression's type, since values of numeric types (and undefined values of any scalar type?) can be outside their base range. @end(Ramification) @end(itemize) @PDefn2{Term=[cover a value], Sec=(by a @nt{discrete_choice_list})} A @nt{discrete_choice_list} covers a value if one of its @nt{discrete_choice}s covers the value. @Leading@keepnext@;The possible values of the discriminant of a @nt{variant_part} shall be covered as follows: @begin{itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0188-1],ARef=[AI05-0262-1]} If the discriminant is of a static constrained scalar subtype@Chg{Version=[3],New=[],Old=[,]} then@Chg{Version=[3],New=[, except within an instance of a generic unit,],Old=[]} each non-@key{others} @nt{discrete_@!choice} shall cover only values in that subtype@Chg{Version=[3],New=[ that satisfy its predicate],Old=[]}, and each value of that subtype @Chg{Version=[3],New=[that satisfies its predicate ],Old=[]}shall be covered by some @nt{discrete_@!choice} @Redundant[(either explicitly or by @key<others>)]; @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The exemption for a discriminated type declared in an instance allows the following example:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[type] T @key[is new] Integer; @key[package] G @key[is] @key[type] Rec (Discrim : T) @key[is record] @key[case] Discrim @key[is] @key[when] -10 .. -1 => Foo : Float; @key[when others] => @key[null]; @key[end case]; @key[end record]; @key[end] G;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{package} I @key{is new} G (Natural); -- @Examcom{Legal}]} @end{Example} @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If the type of the discriminant is a descendant of a generic formal scalar type@Chg{Version=[3],New=[,],Old=[]} then the @nt{variant_part} shall have an @key{others} @nt{discrete_choice}; @begin{Reason} The base range is not known statically in this case. @end{Reason} Otherwise, each value of the base range of the type of the discriminant shall be covered @Redundant[(either explicitly or by @key<others>)]. @end{itemize} Two distinct @nt{discrete_choice}s of a @nt{variant_part} shall not cover the same value. @end{Legality} @begin{StaticSem} If the @nt{component_list} of a @nt{variant} is specified by @key(null), the variant has no components. @Defn{govern a @nt{variant_part}} @Defn{govern a @nt{variant}} The discriminant of a @nt<variant_part> is said to @i(govern) the @nt<variant_part> and its @nt<variant>s. In addition, the discriminant of a derived type governs a @nt<variant_part> and its @nt<variant>s if it corresponds (see @RefSecNum(Discriminants)) to the discriminant of the @nt<variant_part>. @end{StaticSem} @begin{RunTime} A record value contains the values of the components of a particular @nt{variant} only if the value of the discriminant governing the @nt<variant> is covered by the @nt{discrete_choice_list} of the @nt{variant}. This rule applies in turn to any further @nt{variant} that is, itself, included in the @nt{component_list} of the given @nt{variant}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[When an object of a discriminated type @i<T> is initialized by default, Constraint_Error is raised if no @nt{discrete_choice_list} of any @nt{variant} of a @nt{variant_part} of @i<T> covers the value of the discriminant that governs the @nt{variant_part}. When a @nt{variant_part} appears in the @nt{component_list} of another @nt{variant} @i<V>, this test is only applied if the value of the discriminant governing @i<V> is covered by the @nt{discrete_choice_list} of @i<V>.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is not a @ldquote@;check@rdquote; it cannot be suppressed. However, in most cases it is not necessary to generate any code to raise this exception. A test is needed (and can fail) in the case where the discriminant subtype has a Static_Predicate specified, it also has predicate checking disabled, and the discriminant governs a @nt{variant_part} which lacks a @key[when others] choice.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The test also could fail for a static discriminant subtype with range checking suppressed and the discriminant governs a @nt{variant_part} which lacks a @key[when others] choice. But execution is erroneous if a range check that would have failed is suppressed (see @RefSecNum{Suppressing Checks}), so an implementation does not have to generate code to check this case. (An unchecked failed predicate does not cause erroneous execution, so the test is required in that case.)]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Like the checks associated with a per-object constraint, this test is not made during the elaboration of a @nt{subtype_indication}.]} @end{ImplNote} @PDefn2{Term=[elaboration], Sec=(variant_part)} The elaboration of a @nt{variant_part} consists of the elaboration of the @nt{component_list} of each @nt{variant} in the order in which they appear. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Example of record type with a variant part: ) @begin(Example) @key(type) Device @key(is) (Printer, Disk, Drum); @key(type) State @key(is) (Open, Closed); @key(type) Peripheral(Unit : Device := Disk) @key(is) @key(record) Status : State; @key(case) Unit @key(is) @key(when) Printer => Line_Count : Integer @key(range) 1 .. Page_Size; @key(when) @key(others) => Cylinder : Cylinder_Index; Track : Track_Number; @key(end) @key(case); @key(end) @key(record); @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of record subtypes:) @end{WideAbove} @begin(Example) @key(subtype) Drum_Unit @key(is) Peripheral(Drum); @key(subtype) Disk_Unit @key(is) Peripheral(Disk); @end(Example) @begin{WideAbove} @leading@keepnext@i(Examples of constrained record variables:) @end{WideAbove} @begin(Example) Writer : Peripheral(Unit => Printer); Archive : Disk_Unit; @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, the discriminant of a @nt{variant_part} is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an @key{others} @nt{discrete_choice} is required in this case. @end{Extend83} @begin{DiffWord83} The syntactic category @ntf{choice} is removed. The syntax rules for @nt{variant}, @nt{array_aggregate}, and @nt{case_statement} now use @nt{discrete_choice_list} or @nt{discrete_choice} instead. The syntax rule for @nt{record_aggregate} now defines its own syntax for named associations. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We have added the term Discrete Choice to the title since this is where they are talked about. This is analogous to the name of the subclause "Index Constraints and Discrete Ranges" in the @Chg{Version=[3],New=[subclause],Old=[clause]} on Array Types. The rule requiring that the discriminant denote a discriminant of the type being defined seems to have been left implicit in RM83. @end{DiffWord83} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Membership tests are no longer allowed as a @nt{discrete_choice}, in order that those tests can be expanded to allow multiple tests in a single expression without ambiguity. Since a membership test has a boolean type, they are very unlikely to be used as a @nt{discrete_choice}.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Subtypes with static predicates can be used in @nt{discrete_choice}s, and the coverage rules are modified to respect the predicates.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[Variants in generic specifications are no longer rejected if the subtype of the actual type does not include all of the case choices. This probably isn't useful, but it is consistent with the treatment of @nt{case_expression}s.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Added a test that some @nt{variant} covers the value of a discriminant that governs a @nt{variant_part}. This is similar to the test that some case limb covers the value of the @SynI{Selecting_}@nt{expression} of a @nt{case_statement}. This test cannot change the behavior of any nonerroneous Ada 2005 program, so it is not an inconsistency.]} @end{DiffWord2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/03c.mss��������������������������������������������������������������0000755�0001752�0001001�00001136110�12066652506�016541� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(03, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @Comment{$Source: e:\\cvsroot/ARM/Source/03c.mss,v $} @Comment{$Revision: 1.128 $} @LabeledClause{Tagged Types and Type Extensions} @begin{Intro} @redundant[@PDefn{dispatching operation} @Defn{polymorphism} @IndexSee{Term=[dynamic binding],See=(dispatching operation)} @IndexSeeAlso{Term=[generic unit],See=(dispatching operation)} @IndexSeeAlso{Term=[variant],See=(tagged type)} Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via @i(dispatching operations). @IndexSee{Term=[object-oriented programming (OOP)],See=[tagged types and type extensions]} @IndexSee{Term=[OOP (object-oriented programming)],See=[tagged types and type extensions]} @IndexSeeAlso{Term=[inheritance],See=[tagged types and type extension]}] @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The intended implementation model is for @Chg{Version=[2],New=[the static portion of ],Old=[]}a tag to be represented as a pointer to a statically allocated and link-time initialized type descriptor. The type descriptor contains the address of the code for each primitive operation of the type. It probably also contains other information, such as might make membership tests convenient and efficient.@Chg{Version=[2],New=[ Tags for nested type extensions must also have a dynamic part that identifies the particular elaboration of the type.],Old=[]} The primitive operations of a tagged type are known at its first freezing point; the type descriptor is laid out at that point. It contains linker symbols for each primitive operation; the linker fills in the actual addresses. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Primitive operations of type extensions that are declared at a level deeper than the level of the ultimate ancestor from which they are derived can be represented by wrappers that use the dynamic part of the tag to call the actual primitive operation. The dynamic part would generally be some way to represent the static link or display necessary for making a nested call. One implementation strategy would be to store that information in the extension part of such nested type extensions, and use the dynamic part of the tag to point at it. (That way, the @lquotes@;dynamic@rquotes@; part of the tag could be static, at the cost of indirect access.)]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If the tagged type is descended from any interface types, it also will need to include @lquotes@;subtags@rquotes@; (one for each interface) that describe the mapping of the primitive operations of the interface to the primitives of the type. These subtags could directly reference the primitive operations (for faster performance), or simply provide the tag @lquotes@;slot@rquotes@; numbers for the primitive operations (for easier derivation). In either case, the subtags would be used for calls that dispatch through a class-wide type of the interface.]} Other implementation models are possible. The rules ensure that @lquotes@;dangling dispatching@rquotes@; is impossible; that is, when a dispatching call is made, there is always a body to execute. This is different from some other object-oriented languages, such as Smalltalk, where it is possible to get a run-time error from a missing method. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} Dispatching calls should be efficient, and should have a bounded worst-case execution time. This is important in a language intended for real-time applications. In the intended implementation model, a dispatching call involves calling indirect through the appropriate slot in the dispatch table. No complicated "method lookup" is involved@Chg{Version=[2],New=[ although a call which is dispatching on an interface may require a lookup of the appropriate interface subtag],Old=[]}. The programmer should have the choice at each call site of a dispatching operation whether to do a dispatching call or a statically determined call (i.e. whether the body executed should be determined at run time or at compile time). The same body should be executed for a call where the tag is statically determined to be T'Tag as for a dispatching call where the tag is found at run time to be T'Tag. This allows one to test a given tagged type with statically determined calls, with some confidence that run-time dispatching will produce the same behavior. All views of a type should share the same type descriptor and the same tag. The visibility rules determine what is legal at compile time; they have nothing to do with what bodies can be executed at run time. Thus, it is possible to dispatch to a subprogram whose declaration is not visible at the call site. In fact, this is one of the primary facts that gives object-oriented programming its power. The subprogram that ends up being dispatched to by a given call might even be designed long after the call site has been coded and compiled. Given that Ada has overloading, determining whether a given subprogram overrides another is based both on the names and the type profiles of the operations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} When a type extension is declared, if there is any place within its immediate scope where a certain subprogram of the parent @Chg{Version=[2],New=[or progenitor ],Old=[]}is visible, then a matching subprogram should override. If there is no such place, then a matching subprogram should be totally unrelated, and occupy a different slot in the type descriptor. This is important to preserve the privacy of private parts; when an operation declared in a private part is inherited, the inherited version can be overridden only in that private part, in the package body, and in any children of the package. If an implementation shares code for instances of generic bodies, it should be allowed to share type descriptors of tagged types declared in the generic body, so long as they are not extensions of types declared in the specification of the generic unit. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Defn{tagged type} A record type or private type that has the reserved word @key(tagged) in its declaration is called a @i(tagged) type.@Chg{Version=[2],New=[ In addition, an interface type is a tagged type, as is a task or protected type derived from an interface (see @RefSecNum{Interface Types}).],Old=[]} @Redundant[When deriving from a tagged type, @Chg{Version=[2],New=[as],Old=[additional components may be defined. As]} for any derived type, additional primitive subprograms may be defined, and inherited primitive subprograms may be overridden.] @Defn{type extension} @Defn2{Term=[extension], Sec=(of a type)} The derived type is called an @i(extension) of @Chg{Version=[2],New=[its],Old=[the]} ancestor @Chg{Version=[2],New=[types],Old=[type]}, or simply a @i(type extension).@Chg{Version=[2],New=[],Old=[ @Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is also a tagged type, and is either a @i(record extension) or a @i(private extension) of some other tagged type. A record extension is defined by a @nt<derived_type_definition> with a @nt<record_extension_part>. A private extension, which is a partial view of a record extension, can be declared in the visible part of a package (see @RefSecNum(Private Types and Private Extensions)) or in a generic formal part (see @RefSecNum(Formal Private and Derived Types)).]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is also a tagged type, and is a @i(record extension) or a @i(private extension) of some other tagged type, or a noninterface synchronized tagged type (see @RefSecNum{Interface Types}). A record extension is defined by a @nt<derived_type_definition> with a @nt<record_extension_part> (see @RefSecNum{Type Extensions})@Redundant[, which may include the definition of additional components]. A private extension, which is a partial view of a record extension or of a synchronized tagged type, can be declared in the visible part of a package (see @RefSecNum(Private Types and Private Extensions)) or in a generic formal part (see @RefSecNum(Formal Private and Derived Types)).]} @ToGlossary{Term=<Tagged type>, Text=<The objects of a tagged type have a run-time type tag, which indicates the specific type with which the object was originally created. An operand of a class-wide tagged type can be used in a dispatching call; the tag indicates which subprogram body to invoke. Nondispatching calls, in which the subprogram body to invoke is determined at compile time, are also allowed. Tagged types may be extended with additional components.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} If a tagged type is declared other than in a @nt{package_specification}, it is impossible to add new primitive subprograms for that type, although it can inherit primitive subprograms, and those can be overridden. If the user incorrectly thinks a certain subprogram is primitive when it is not, and tries to call it with a dispatching call, an error message will be given at the call site.@Chg{Version=[2],New=[ Similarly, by using an @nt{overriding_indicator} (see @RefSecNum{Subprogram Declarations}), the user can declare that a subprogram is intended to be overriding, and get an error message when they made a mistake. The use of @nt{overriding_indicator}s is highly recommended in new code that does not need to be compatible with Ada 95.],Old=[]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[Note that the accessibility rules imply that a tagged type declared in a library @nt{package_specification} cannot be extended in a nested subprogram or task body.]} @end{Ramification} @Defn{tag of an object} An object of a tagged type has an associated (run-time) @i(tag) that identifies the specific tagged type used to create the object originally. @Redundant[ The tag of an operand of a class-wide tagged type @i(T)'Class controls which subprogram body is to be executed when a primitive subprogram of type @i(T) is applied to the operand (see @RefSecNum(Dispatching Operations of Tagged Types)); @Defn{dispatching} using a tag to control which body to execute is called @i(dispatching).] @IndexSee{Term=[type tag],See=[tag]} @IndexSee{Term=[run-time type],See=[tag]} @IndexSeeAlso{Term=[type],See=[tag]} @IndexSeeAlso{Term=[class],See=[tag]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} The tag of a specific tagged type identifies the @nt<full_type_declaration> of the type@Chg{Version=[2],New=[, and for a type extension, is sufficient to uniquely identify the type among all descendants of the same ancestor],Old=[]}. If a declaration for a tagged type occurs within a @nt{generic_package_declaration}, then the corresponding type declarations in distinct instances of the generic package are associated with distinct tags. For a tagged type that is local to a generic package body@Chg{Version=[2], New=[ and with all of its ancestors (if any) also local to the generic body],Old=[]}, the language does not specify whether repeated instantiations of the generic body result in distinct tags.@PDefn{Unspecified} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[This eases generic code sharing.]} @end{reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[In most cases, a tag need only identify a particular tagged type declaration, and can therefore be a simple link-time-known address. However, for tag checks (see @RefSecNum{Dispatching Operations of Tagged Types}) it is essential that each descendant (that currently exists) of a given type have a unique tag. Hence, for types declared in shared generic bodies where an ancestor comes from outside the generic, or for types declared at a deeper level than an ancestor, the tag needs to be augmented with some kind of dynamic descriptor (which may be a static link, global display, instance descriptor pointer, or combination). This implies that type Tag may need to be two words, the second of which is normally null, but in these identified special cases needs to include a static link or equivalent. Within an object of one of these types with a two-word tag, the two parts of the tag would typically be separated, one part as the first word of the object, the second placed in the first extension part that corresponds to a type declared more nested than its parent or declared in a shared generic body when the parent is declared outside. Alternatively, by using an extra level of indirection, the type Tag could remain a single-word.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[For types that are not type extensions (even for ones declared in nested scopes), we do not require that], Old=[The language does not specify whether]} repeated elaborations of the same @nt<full_type_declaration> correspond to distinct tags. @Chg{Version=[2],New=[This was done so that Ada 2005 implementations of tagged types could maintain representation compatibility with Ada 95 implementations. Only type extensions that were not allowed in Ada 95 require additional information with the tag.], Old=[In most cases, we expect that all elaborations will correspond to the same tag, since the tag will frequently be the address (or index) of a statically allocated type descriptor. However, with shared generics, the type descriptor might have to be allocated on a per-instance basis, which in some implementation models implies per-elaboration of the instantiation.]} @end{implnote} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The wording @lquotes@;is sufficient to uniquely identify the type among all descendants of the same ancestor@rquotes@; only applies to types that currently exist. It is not necessary to distinguish between descendants that currently exist, and descendants of the same type that no longer exist. For instance, the address of the stack frame of the subprogram that created the tag is sufficient to meet the requirements of this rule, even though it is possible, after the subprogram returns, that a later call of the subprogram could have the same stack frame and thus have an identical tag.]} @end{Honest} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada],Child=[Tags]}@key[package] Ada.Tags @key[is] @Chg{Version=[2],New=[@key[pragma] Preelaborate(Tags); ],Old=[]}@key[type] @AdaTypeDefn{Tag} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Tag);],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Tag} : @key[constant] Tag;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} @key[function] @AdaSubDefn{Expanded_Name}(T : Tag) @key[return] String;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Expanded_Name}(T : Tag) @key[return] Wide_String; @key[function] @AdaSubDefn{Wide_Wide_Expanded_Name}(T : Tag) @key[return] Wide_Wide_String;],Old=[]} @key[function] @AdaSubDefn{External_Tag}(T : Tag) @key[return] String; @key[function] @AdaSubDefn{Internal_Tag}(External : String) @key[return] Tag; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Descendant_Tag}(External : String; Ancestor : Tag) @key[return] Tag; @key[function] @AdaSubDefn{Is_Descendant_At_Same_Level}(Descendant, Ancestor : Tag) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Parent_Tag} (T : Tag) @key[return] Tag;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[ @key[type] @AdaTypeDefn{Tag_Array} @key[is array] (Positive @key[range] <>) @key[of] Tag;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Interface_Ancestor_Tags} (T : Tag) @key[return] Tag_Array;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0173-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Abstract} (T : Tag) @key[return] Boolean;]} @AdaExcDefn{Tag_Error} : @key[exception]; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Tags; @end{Example} @begin{Reason} Tag is a nonlimited, definite subtype, because it needs the equality operators, so that tag checking makes sense. Also, equality, assignment, and object declaration are all useful capabilities for this subtype. For an object X and a type T, @lquotes@;X'Tag = T'Tag@rquotes@; is not needed, because a membership test can be used. However, comparing the tags of two objects cannot be done via membership. This is one reason to allow equality for type Tag. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[No_Tag is the default initial value of type Tag.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[This is similar to the requirement that all access values be initialized to @key[null].]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} The function @Chg{Version=[2],New=[Wide_@!Wide_@!Expanded_@!Name], Old=[Expanded_@!Name]} returns the full expanded name of the first subtype of the specific type identified by the tag, in upper case, starting with a root library unit. The result is implementation defined if the type is declared within an unnamed @nt{block_statement}. @begin{Honest} This name, as well as each @nt{prefix} of it, does not denote a @nt{renaming_declaration}. @end{Honest} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The result of @Chg{Version=[2], New=[Tags.Wide_@!Wide_@!Expanded_@!Name],Old=[Tags.Expanded_@!Name]} for types declared within an unnamed @nt{block_statement}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[The function Expanded_Name (respectively, Wide_Expanded_Name) returns the same sequence of graphic characters as that defined for Wide_Wide_Expanded_Name, if all the graphic characters are defined in Character (respectively, Wide_Character); otherwise, the sequence of characters is implementation defined, but no shorter than that returned by Wide_Wide_Expanded_Name for the same value of the argument.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[ The sequence of characters of the value returned by Tags.Expanded_Name (respectively, Tags.Wide_Expanded_Name) when some of the graphic characters of Tags.Wide_Wide_Expanded_Name are not defined in Character (respectively, Wide_Character).],Old=[]}]} The function External_Tag returns a string to be used in an external representation for the given tag. The call External_Tag(S'Tag) is equivalent to the @nt<attribute_reference> S'External_Tag (see @RefSecNum{Operational and Representation Attributes}). @begin{Reason} It might seem redundant to provide both the function External_Tag and the attribute External_Tag. The function is needed because the attribute can't be applied to values of type Tag. The attribute is needed so that it can be @Chg{Version=[2], New=[specified],Old=[specifiable]} via an @nt{attribute_definition_clause}. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=[The string returned by the functions Expanded_Name, Wide_@!Expanded_@!Name, Wide_Wide_@!Expanded_@!Name, and External_Tag has lower bound 1.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00279-01]} The function Internal_Tag returns @Chg{Version=[2],New=[a],Old=[the]} tag that corresponds to the given external tag, or raises Tag_Error if the given string is not the external tag for any specific type of the partition.@Chg{Version=[2],New=[ Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created (see @RefSecNum{Freezing Rules}).],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[The check for uncreated library-level types prevents a reference to the type before execution reaches the freezing point of the type. This is important so that T'Class'Input or an instance of Tags.Generic_Dispatching_Constructor do not try to create an object of a type that hasn't been frozen (which @Chg{Version=[3],New=[might],Old=[may]} not have yet elaborated its constraints). We don't require this behavior for non-library-level types as the tag can be created multiple times and possibly multiple copies can exist at the same time, making the check complex.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0113-1]} @ChgAdded{Version=[2],Text=[The function Descendant_Tag returns the (internal) tag for the type that corresponds to the given external tag and is both a descendant of the type identified by the Ancestor tag and has the same accessibility level as the identified ancestor. Tag_Error is raised if External is not the external tag for such a type. Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created@Chg{Version=[3],New=[, or if the given external tag identifies more than one type that has the appropriate Ancestor and accessibility level],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Descendant_Tag is used by T'Class'Input to identify the type identified by an external tag. Because there can be multiple elaborations of a given type declaration, Internal_Tag does not have enough information to choose a unique such type. Descendant_Tag does not return the tag for types declared at deeper accessibility levels than the ancestor because there could be ambiguity in the presence of recursion or multiple tasks. Descendant_Tag can be used in constructing a user-defined replacement for T'Class'Input.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0113-1]} @ChgAdded{Version=[3],Text=[Rules for specifying external tags will usually prevent an external tag from identifying more than one type. However, an external tag can identify multiple types if a generic body contains a derivation of a tagged type declared outside of the generic, and there are multiple instances at the same accessibility level as the type. (The Standard allows default external tags to not be unique in this case.)]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The function Is_Descendant_At_Same_Level returns True if the Descendant tag identifies a type that is both a descendant of the type identified by Ancestor and at the same accessibility level. If not, it returns False.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Is_Descendant_At_Same_Level (or something similar to it) is used by T'Class'Output to determine whether the item being written is at the same accessibility level as T. It may be used to determine prior to using T'Class'Output whether Tag_Error will be raised, and also can be used in constructing a user-defined replacement for T'Class'Output.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[For the purposes of the dynamic semantics of functions Descendant_Tag and Is_Descendant_At_Same_Level, a tagged type T2 is a @i<descendant> of a type T1 if it is the same as T1, or if its parent type or one of its progenitor types is a descendant of type T1 by this rule@Redundant[, even if at the point of the declaration of T2, one of the derivations in the chain is not visible].@Defn2{Term=[descendant],Sec=[at run-time]}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In other contexts, @ldquote@;descendant@rdquote is dependent on visibility, and the particular view a derived type has of its parent type. See @RefSecNum{Private Operations}.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Paragraph number changed} @ChgAdded{Version=[2],Text=[The function Parent_Tag returns the tag of the parent type of the type whose tag is T. If the type does not have a parent type (that is, it was not declared by a derived_type_declaration), then No_Tag is returned.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The parent type is always the parent of the full type; a private extension appears to define a parent type, but it does not (only the various forms of derivation do that). As this is a run-time operation, ignoring privateness is OK.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00405-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Paragraph number changed} @ChgAdded{Version=[2],Text=[The function Interface_Ancestor_Tags returns an array containing the tag of each interface ancestor type of the type whose tag is T, other than T itself. The lower bound of the returned array is 1, and the order of the returned tags is unspecified. Each tag appears in the result exactly once.@Redundant[ If the type whose tag is T has no interface ancestors, a null array is returned.]]}@PDefn{Unspecified} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The result of Interface_Ancestor_Tags includes the tag of the parent type, if the parent is an interface.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Indirect interface ancestors are included in the result of Interface_Ancestor_Tags. That's because where an interface appears in the derivation tree has no effect on the semantics of the type; the only interesting property is whether the type has an interface as an ancestor.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0173-1]} @ChgAdded{Version=[3],Text=[The function Is_Abstract returns True if the type whose tag is T is abstract, and False otherwise.]} For @PrefixType{every subtype S of a tagged type @i(T) (specific or class-wide)}, the following attributes are defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<Class>, Text=[S'Class denotes a subtype of the class-wide type (called @i(T)'Class in this International Standard) for the class rooted at @i(T) (or if S already denotes a class-wide subtype, then S'Class is the same as S). @Noprefix@Defn2{Term=[unconstrained], Sec=(subtype)} @Defn2{Term=[constrained], Sec=(subtype)} S'Class is unconstrained. However, if S is constrained, then the values of S'Class are only those that when converted to the type @i(T) belong to S.]} @begin{Ramification} This attribute is defined for both specific and class-wide subtypes. The definition is such that S'Class'Class is the same as S'Class. Note that if S is constrained, S'Class is only partially constrained, since there might be additional discriminants added in descendants of @i(T) which are not constrained. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} The Class attribute is not defined for untagged subtypes (except for incomplete types and private types whose full view is tagged @em see @Chg{Version=[2],New=[@RefSecNum{The Class Attribute of Untagged Incomplete Types}], Old=[@RefSecNum{Incomplete Type Declarations}]} and @RefSecNum{Private Operations}) so as to preclude implicit conversion in the absence of run-time type information. If it were defined for untagged subtypes, it would correspond to the concept of universal types provided for the predefined numeric classes. @end{Reason} @Attribute{Prefix=<S>, AttrName=<Tag>, Text=[S'Tag denotes the tag of the type @i(T) (or if @i(T) is class-wide, the tag of the root type of the corresponding class). The value of this attribute is of type Tag.]} @begin{Reason} S'Class'Tag equals S'Tag, to avoid generic contract model problems when S'Class is the actual type associated with a generic formal derived type.@end{reason} @end(description) @EndPrefixType{} Given @PrefixType{a @nt<prefix> X that is of a class-wide tagged type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @Attribute{Prefix=<X>, AttrName=<Tag>, Text=[X'Tag denotes the tag of X. The value of this attribute is of type Tag.]} @begin(Reason) X'Tag is not defined if X is of a specific type. This is primarily to avoid confusion that might result about whether the Tag attribute should reflect the tag of the type of X, or the tag of X. No such confusion is possible if X is of a class-wide type. @end(Reason) @end(description) @EndPrefixType{} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00441-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following language-defined generic function exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Tags],Child=[Generic_@!Dispatching_@!Constructor]}@key{generic} @key{type} T (<>) @key{is abstract tagged limited private}; @key{type} Parameters (<>) @key{is limited private}; @key{with function} Constructor (Params : @key{not null access} Parameters) @key{return} T @key{is abstract}; @key{function} Ada.Tags.Generic_Dispatching_Constructor (The_Tag : Tag; Params : @key{not null access} Parameters) @key{return} T'Class@Chg{Version=[3],New=[ @key{with} Convention => Intrinsic],Old=[]}; @key{pragma} Preelaborate(Generic_Dispatching_Constructor);@Chg{Version=[3],New=[],Old=[ @key{pragma} Convention(Intrinsic, Generic_Dispatching_Constructor);]}]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Tags.Generic_Dispatching_Constructor provides a mechanism to create an object of an appropriate type from just a tag value. The function Constructor is expected to create the object given a reference to an object of type Parameters.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This specification is designed to make it easy to create dispatching constructors for streams; in particular, this can be used to construct overridings for T'Class'Input.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that any tagged type will match T (see @RefSecNum{Formal Private and Derived Types}).]} @end{Discussion} @end{StaticSem} @begin{RunTime} @Leading@keepnext@;The tag associated with an object of a tagged type is determined as follows: @begin(Itemize) @PDefn2{Term=[tag of an object], Sec=(stand-alone object, component, or @nt<aggregate>)} The tag of a stand-alone object, a component, or an @nt<aggregate> of a specific tagged type @i(T) identifies @i(T). @begin{Discussion} The tag of a formal parameter of type @i(T) is not necessarily the tag of @i(T), if, for example, the actual was a type conversion. @end{Discussion} @PDefn2{Term=[tag of an object], Sec=(object created by an @nt<allocator>)} The tag of an object created by an allocator for an access type with a specific designated tagged type @i(T), identifies @i(T). @begin{Discussion} The tag of an object designated by a value of such an access type might not be @i(T), if, for example, the access value is the result of a type conversion.@end{discussion} @PDefn2{Term=[tag of an object], Sec=(class-wide object)} The tag of an object of a class-wide tagged type is that of its initialization expression. @begin{Ramification} The tag of an object (even a class-wide one) cannot be changed after it is initialized, since a @lquotes@;class-wide@rquotes@; @nt{assignment_statement} raises Constraint_Error if the tags don't match, and a @lquotes@;specific@rquotes@; @nt{assignment_statement} does not affect the tag. @end{Ramification} @PDefn2{Term=[tag of an object], Sec=(returned by a function)} The tag of the result returned by a function whose result type is a specific tagged type @i(T) identifies @i(T). @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For a limited tagged type, the return object is @lquotes@;built in place@rquotes in the ultimate result object with the appropriate tag.], Old=[This requires a run-time check for limited tagged types, since they are returned "by-reference."]} For a nonlimited type, a new anonymous object with the appropriate tag is created as part of the function return@Chg{Version=[2],New=[],Old=[, and then assigned the value of the return expression]}. See @RefSec{Return Statements}. @end{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @PDefn2{Term=[tag of an object], Sec=(returned by a function)} The tag of the result returned by a function with a class-wide result type is that of the return @Chg{Version=[2],New=[object],Old=[expression]}. @end(Itemize) @PDefn2{Term=[tag of an object], Sec=(preserved by type conversion and parameter passing)} The tag is preserved by type conversion and by parameter passing. The tag of a value is the tag of the associated object (see @RefSecNum{Formal Parameter Modes}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00344-01],ARef=[AI95-00405-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0092-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[Tag_Error is raised by a call of Descendant_Tag, Expanded_Name, External_Tag, @Chg{Version=[3],New=[Interface_@!Ancestor_@!Tags], Old=[Interface_Ancestor_Tag]},@Chg{Version=[3],New=[ Is_Abstract,],Old=[]} Is_Descendant_@!At_Same_Level, @Chg{Version=[3],New=[],Old=[or ]}Parent_Tag@Chg{Version=[3],New=[, Wide_Expanded_Name, or Wide_Wide_Expanded_Name],Old=[]} if any tag passed is No_Tag.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[An instance of Tags.Generic_Dispatching_Constructor raises Tag_Error if The_Tag does not represent a concrete descendant of T or if the innermost master (see @RefSecNum{Completion and Finalization}) of this descendant is not also a master of the instance. Otherwise, it dispatches to the primitive function denoted by the formal Constructor for the type identified by The_Tag, passing Params, and returns the result. Any exception raised by the function is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The tag check checks both that The_Tag is in T'Class, and that it is not abstract. These checks are similar to the ones required by streams for T'Class'Input (see @RefSecNum{Stream-Oriented Attributes}). In addition, there is a check that the tag identifies a type declared on the current dynamic call chain, and not a more nested type or a type declared by another task. This check is not necessary for streams, because the stream attributes are declared at the same dynamic level as the type used.]} @end{Ramification} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If an internal tag provided to an instance of Tags.Generic_Dispatching_Constructor or to any subprogram declared in package Tags identifies either a type that is not library-level and whose tag has not been created (see @RefSecNum{Freezing Rules}), or a type that does not exist in the partition at the time of the call, then execution is erroneous.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[One reason that a type might not exist in the partition is that the tag refers to a type whose declaration was elaborated as part of an execution of a @nt{subprogram_body} which has been left (see @RefSecNum{Completion and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We exclude tags of library-level types from the current execution of the partition, because misuse of such tags should always be detected. T'Tag freezes the type (and thus creates the tag), and Internal_Tag and Descendant_Tag cannot return the tag of a library-level type that has not been created. All ancestors of a tagged type must be frozen no later than the (full) declaration of a type that uses them, so Parent_Tag and Interface_Ancestor_Tags cannot return a tag that has not been created. Finally, library-level types never cease to exist while the partition is executing. Thus, if the tag comes from a library-level type, there cannot be erroneous execution (the use of Descendant_Tag rather than Internal_Tag can help ensure that the tag is of a library-level type). This is also similar to the rules for T'Class'Input (see @RefSecNum{Stream-Oriented Attributes}).]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Ada 95 allowed Tag_Error in this case, or expected the functions to work. This worked because most implementations used tags constructed at link-time, and each elaboration of the same @nt{type_declaration} produced the same tag. However, Ada 2005 requires at least part of the tags to be dynamically constructed for a type derived from a type at a shallower level. For dynamically constructed tags, detecting the error can be expensive and unreliable. To see this, consider a program containing two tasks. Task A creates a nested tagged type, passes the tag to task B (which saves it), and then terminates. The nested tag (if dynamic) probably will need to refer in some way to the stack frame for task A. If task B later tries to use the tag created by task A, the tag's reference to the stack frame of A probably is a dangling pointer. Avoiding this would require some sort of protected tag manager, which would be a bottleneck in a program's performance. Moreover, we'd still have a race condition; if task A terminated after the tag check, but before the tag was used, we'd still have a problem. That means that all of these operations would have to be serialized. That could be a significant performance drain, whether or not nested tagged types are ever used. Therefore, we allow execution to become erroneous as we do for other dangling pointers. If the implementation can detect the error, we recommend that Tag_Error be raised.]} @end{Discussion} @end{Erron} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00279-01]} The implementation of @Chg{Version=[2],New=[Internal_Tag and Descendant_Tag], Old=[the functions in Ada.Tags]} may raise Tag_Error if no specific type corresponding to the @Chg{Version=[2],New=[string External],Old=[tag]} passed as a parameter exists in the partition at the time the function is called@Chg{Version=[2],New=[, or if there is no such type whose innermost master is a master of the point of the function call],Old=[]}. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Locking would be required to ensure that the mapping of strings to tags never returned tags of types which no longer exist, because types can cease to exist (because they belong to another task, as described above) during the execution of these operations. Moreover, even if these functions did use locking, that would not prevent the type from ceasing to exist at the instant that the function returned. Thus, we do not require the overhead of locking;],Old=[In most implementations, repeated elaborations of the same @nt{type_declaration} will all produce the same tag. In such an implementation, Tag_Error will be raised in cases where the internal or external tag was passed from a different partition. However, some implementations might create a new tag value at run time for each elaboration of a @nt{type_declaration}. In that case, Tag_Error could also be raised if the created type no longer exists because the subprogram containing it has returned, for example. We don't require the latter behavior;]} hence the word @lquotes@;may@rquotes@; in this rule. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0113-1]} @ChgAdded{Version=[2],Text=[Internal_Tag should return the tag of a type@Chg{Version=[3],New=[, if one exists,],Old=[]} whose innermost master is @Chg{Version=[3],New=[a],Old=[the]} master of the point of the function call.]} @ChgImplAdvice{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@Chg{Version=[2], New=[Tags.Internal_Tag should return the tag of a type@Chg{Version=[3],New=[, if one exists,],Old=[]} whose innermost master is @Chg{Version=[3],New=[a],Old=[the]} master of the point of the function call.],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[It's not helpful if Internal_Tag returns the tag of some type in another task when one is available in the task that made the call. We don't require this behavior (because it requires the same implementation techniques we decided not to insist on previously), but encourage it.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0113-1]} @ChgAdded{Version=[3],Text=[There is no Advice for the result of Internal_Tag if no such type exists. In most cases, the @ImplPermName can be used to raise Tag_Error, but some other tag can be returned as well.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} A type declared with the reserved word @key[tagged] should normally be declared in a @nt{package_specification}, so that new primitive subprograms can be declared for it. Once an object has been created, its tag never changes. Class-wide types are defined to have unknown discriminants (see @RefSecNum(Discriminants)). This means that objects of a class-wide type have to be explicitly initialized (whether created by an @nt<object_declaration> or an @nt<allocator>), and that @nt<aggregate>s have to be explicitly qualified with a specific type when their expected type is class-wide. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[The capability provided by Tags.Generic_Dispatching_Constructor is sometimes known as a @i<factory>.@Defn{factory}@Defn{class factory}],Old=[If S denotes an untagged private type whose full type is tagged, then S'Class is also allowed before the full type definition, but only in the private part of the package in which the type is declared (see @RefSecNum(Private Operations)). Similarly, the Class attribute is defined for incomplete types whose full type is tagged, but only within the library unit in which the incomplete type is declared (see @RefSecNum(Incomplete Type Declarations)).]} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of tagged record types:) @begin(Example) @key(type) Point @key(is tagged) @key(record) X, Y : Real := 0.0; @key(end record); @key(type) Expression @key(is tagged null record); --@RI[ Components will be added by each extension] @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Tagged types are a new concept. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Added wording specifying that Internal_Tag must raise Tag_Error if the tag of a library-level type has not yet been created. Ada 95 gave an Implementation Permission to do this; we require it to avoid erroneous execution when streaming in an object of a library-level type that has not yet been elaborated. This is technically inconsistent; a program that used Internal_Tag outside of streaming and used a compiler that didn't take advantage of the Implementation Permission would not have raised Tag_Error, and may have returned a useful tag. (If the tag was used in streaming, the program would have been erroneous.) Since such a program would not have been portable to a compiler that did take advantage of the Implementation Permission, this is not a significant inconsistency.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=<We now define the lower bound of the string returned from [[Wide_]Wide_]Expanded_Name and External_Name. This makes working with the returned string easier, and is consistent with many other string-returning functions in Ada. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from one of these functions, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.>} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02],ARef=[AI95-00344-01],ARef=[AI95-00400-01],ARef=[AI95-00405-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Constant No_Tag, and functions Parent_Tag, Interface_Ancestor_Tags, Descendant_Tag, Is_Descendant_At_Same_Level, Wide_Expanded_Name, and Wide_Wide_Expanded_Name are @Chg{Version=[3],New=[],Old=[newly ]}added to Ada.Tags. If Ada.Tags is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Ada.Tags is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Ada.Tags is now defined to be preelaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Generic function Tags.Generic_Dispatching_Constructor is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[We talk about return objects rather than return expressions, as functions can return using an @nt{extended_return_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added wording to define that tags for all descendants of a tagged type must be distinct. This is needed to ensure that more nested type extensions will work properly. The wording does not require implementation changes for types that were allowed in Ada 95.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0113-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} @b[Correction:] Added wording specifying that Dependent_Tag must raise Tag_Error if there is more than one type which matches the requirements. If an implementation had returned a random tag of the matching types, a program may have worked properly. However, such a program would not be portable (another implementation may return a different tag) and the conditions that would cause the problem are unlikely (most likely, a tagged type extension declared in a generic body with multiple instances in the same scope).]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0173-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Function Is_Abstract is added to Ada.Tags. If Ada.Tags is referenced in a @nt{use_clause}, and an entity @i<E> with the @nt{defining_identifier} Is_Abstract is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> We explicitly define the meaning of "descendant" at runtime, so that it does not depend on visibility as does the usual meaning.]} @end{DiffWord2005} @LabeledSubClause{Type Extensions} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Redundant[@Defn{type extension} @Defn2{Term=[extension], Sec=(of a type)} @Defn{record extension} @Defn2{Term=[extension], Sec=(of a record type)} @Defn{private extension} @Defn2{Term=[extension], Sec=(of a private type)} Every type extension is a tagged type, and is @Chg{Version=[2],New=[],Old=[either ]}a @i(record extension) or a @i(private extension) of some other tagged type@Chg{Version=[2],New=[, or a noninterface synchronized tagged type],Old=[]}.] @end{Intro} @begin{MetaRules} We want to make sure that we can extend a generic formal tagged type, without knowing its discriminants. We don't want to allow components in an extension aggregate to depend on discriminants inherited from the parent value, since such dependence requires staticness in aggregates, at least for variants. @end{MetaRules} @begin{Syntax} @Syn{lhs=<record_extension_part>,rhs="@key(with) @Syn2{record_definition}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01],ARef=[AI95-00345-01],ARef=[AI95-00419-01]} The parent type of a record extension shall not be a class-wide type@Chg{Version=[2],New=[ nor shall it be a synchronized tagged type (see @RefSecNum{Interface Types})],Old=[]}. If the parent type@Chg{Version=[2],New=[ or any progenitor],Old=[]} is nonlimited, then each of the components of the @nt{record_extension_part} shall be nonlimited.@Chg{Version=[2],New=[],Old=[ @PDefn2{Term=[accessibility rule],Sec=(record extension)} The accessibility level (see @RefSecNum(Operations of Access Types)) of a record extension shall not be statically deeper than that of its parent type.]} @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit. @begin{Reason} If the parent is a limited formal type, then the actual might be nonlimited. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Ada 95 required the record extensions to be the same level as the parent type. Now we use accessibility checks on class-wide @nt{allocator}s and return statements to prevent objects from living longer than their type.], Old=[A similar accessibility rule is not needed for private extensions, because in a package, the rule will apply to the @nt{full_type_declaration}, and for a generic formal private extension, the actual is all that matters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Synchronized tagged types cannot be extended. We have this limitation so that all of the data of a task or protected type is defined within the type. Data defined outside of the type wouldn't be subject to the mutual exclusion properties of a protected type, and couldn't be used by a task, and thus doesn't seem to be worth the potential impact on implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[Within the body of a generic unit, or the body of any of its descendant library units, a tagged type],Old=[A type extension]} shall not be declared @Chg{Version=[2],New=[as a descendant of a formal type declared within the formal part of the generic unit], Old=[in a generic body if the parent type is declared outside that body]}. @begin{Reason} This paragraph ensures that a dispatching call will never attempt to execute an inaccessible subprogram body. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[The convoluted wording (@ldquote@;formal type declared within the formal part@rdquote@;) is necessary to include tagged types that are formal parameters of formal packages of the generic unit, as well as formal tagged and tagged formal derived types of the generic unit.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @ChgNote{This rule is only about generic bodies (and always was only about generic bodies. So we drop the extra text.} @Chg{Version=[2],New=[This rule],Old=[The part about generic bodies]} is necessary in order to preserve the contract model. @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI05-0005-1]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[If an ancestor],Old=[Since a generic unit can be instantiated at a deeper accessibility level than the generic unit, it is necessary to prevent type extensions whose parent is declared outside the generic unit. The same is true if the parent]} is a formal of the generic unit @Chg{Version=[2],New=[, we have a problem],Old=[. If the parent is declared in the @nt{generic_declaration} (but is not a formal), we don't run afoul of the accessibility rules, because we know that the instance declaration and body will be at the same accessibility level. However, we still have a problem in that case,]} because it might have an unknown number of@Chg{Version=[3],New=[],Old=[ abstract]} subprograms@Chg{Version=[3],New=[ that require overriding],Old=[]}, as in the following example: @begin{Example} @ChgRef{Version=[2],Kind=[Revised]} @key[package] P @key[is] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; @key[function] F @key[return] T; --@RI{ Inherited versions will @Chg{Version=[2],New=[require overriding],Old=[be abstract]}.} @key[end] P; @key[generic] @key[type] TT @key[is] @key[tagged] @key[private]; @key[package] Gp @key[is] @key[type] NT @key[is] @key[abstract new] TT @key[with] @key[null] @key[record]; @key[procedure] Q(X : @key[in] NT) @key[is abstract]; @key[end] Gp; @ChgRef{Version=[2],Kind=[Revised]} @key[package] @key[body] Gp @key[is] @key[type] NT2 @key[is] @key[new] NT @key[with] @key[null] @key[record]; --@RI{ Illegal!} @key[procedure] Q(X : @key[in] NT2) @key[is] @key[begin] @key[null]; @key[end] Q; --@RI{ Is this legal or not? Can't decide because} --@RI{ we don't know whether TT had any functions that @Chg{Version=[2],New=[require],Old=[go abstract]}} --@RI{ @Chg{Version=[2],New=[overriding ],Old=[]}on extension.} @key[end] Gp; @key[package] I @key[is] @key[new] Gp(TT => P.T); @end{Example} @ChgRef{Version=[2],Kind=[Revised]} I.NT is an abstract type with two abstract subprograms: F (inherited as abstract) and Q (explicitly declared as abstract). But the generic body doesn't know about F, so we don't know that it needs to be overridden to make a nonabstract extension of NT.@Chg{Version=[2],New=[],Old=[ Furthermore, a formal tagged limited private type can be extended with limited components, but the actual might not be limited, which would allow assignment of limited types, which is bad. ]}Hence, we have to disallow this case@Chg{Version=[2],New=[],Old=[ as well]}. @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Similarly, since the actual type for a formal tagged limited private type can be a nonlimited type, we would have a problem if a type extension of a limited private formal type could be declared in a generic body. Such an extension could have a task component, for example, and an object of that type could be passed to a dispatching operation of a nonlimited ancestor type. That operation could try to copy the object with the task component. That would be bad. So we disallow this as well.]} If TT were declared as abstract, then we could have the same problem with abstract procedures. We considered disallowing all tagged types in a generic body, for simplicity. We decided not to go that far, in order to avoid unnecessary restrictions. @PDefn2{Term=[accessibility rule],Sec=(not part of generic contract)} We also considered trying make the accessibility level part of the contract; i.e. invent some way of saying (in the @nt{generic_declaration}) @lquotes@;all instances of this generic unit will have the same accessibility level as the @nt{generic_declaration}.@rquotes@; Unfortunately, that doesn't solve the part of the problem having to do with abstract types. @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Children of generic units obviate the need for extension in the body somewhat.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344]} @ChgAdded{Version=[2],Text=[This rule applies to types with ancestors (directly or indirectly) of formal interface types (see @RefSecNum{Formal Interface Types}), formal tagged private types (see @RefSecNum{Formal Private and Derived Types}), and formal derived private types whose ancestor type is tagged (see @RefSecNum{Formal Private and Derived Types}).]} @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[@defn{null extension} A record extension is a @i{null extension} if its declaration has no @nt{known_discriminant_part} and its @nt{record_extension_part} includes no @nt{component_declaration}s.]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(record_extension_part)} The elaboration of a @nt{record_extension_part} consists of the elaboration of the @nt{record_definition}. @end{RunTime} @begin{Notes} The term @lquotes@;type extension@rquotes@; refers to a type as a whole. The term @lquotes@;extension part@rquotes@; refers to the piece of text that defines the additional components (if any) the type extension has relative to its specified ancestor type. @begin(Discussion) We considered other terminology, such as @lquotes@;extended type.@rquotes@; However, the terms @lquotes@;private extended type@rquotes@; and @lquotes@;record extended type@rquotes@; did not convey the proper meaning. Hence, we have chosen to uniformly use the term @lquotes@;extension@rquotes@; as the type resulting from extending a type, with @lquotes@;private extension@rquotes@; being one produced by privately extending the type, and @lquotes@;record extension@rquotes@; being one produced by extending the type with an additional record-like set of components. Note also that the term @lquotes@;type extension@rquotes@; refers to the result of extending a type in the language Oberon as well (though there the term @lquotes@;extended type@rquotes@; is also used, interchangeably, perhaps because Oberon doesn't have the concept of a @lquotes@;private extension@rquotes@;). @end(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @Chg{Version=[2],New=[],Old=[The accessibility rules imply that a tagged type declared in a library @nt{package_specification} can be extended only at library level or as a generic formal. ]}When @Chg{Version=[2],New=[an],Old=[the]} extension is declared immediately within a @Chg{Version=[2],New=[body],Old=[@nt{package_body}]}, primitive subprograms are inherited and are overridable, but new primitive subprograms cannot be added. A @nt<name> that denotes a component (including a discriminant) of the parent type is not allowed within the @nt{record_extension_part}. Similarly, a @nt<name> that denotes a component defined within the @nt{record_extension_part} is not allowed within the @nt{record_extension_part}. It is permissible to use a @nt<name> that denotes a discriminant of the record extension, providing there is a new @nt{known_discriminant_part} in the enclosing type declaration. (The full rule is given in @RefSecNum(Record Types).) @begin(Reason) The restriction against depending on discriminants of the parent is to simplify the definition of extension aggregates. The restriction against using parent components in other ways is methodological; it presumably simplifies implementation as well. @end(Reason) Each visible component of a record extension has to have a unique name, whether the component is (visibly) inherited from the parent type or declared in the @nt<record_extension_part> (see @RefSecNum{Visibility}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of record extensions (of types defined above in @RefSecNum(Tagged Types and Type Extensions)):} @begin(Example) @key(type) Painted_Point @key(is new) Point @key(with) @key(record) Paint : Color := White; @key(end record); --@RI[ Components X and Y are inherited] Origin : @key(constant) Painted_Point := (X | Y => 0.0, Paint => Black); @key(type) Literal @key(is new) Expression @key(with) @key(record) --@RI[ a leaf in an Expression tree] Value : Real; @key(end record); @key(type) Expr_Ptr @key(is access all) Expression'Class; --@RI[ see @RefSecNum(Access Types)] @key(type) Binary_Operation @key(is new) Expression @key(with) @key(record) --@RI[ an internal node in an Expression tree] Left, Right : Expr_Ptr; @key(end record); @key(type) Addition @key(is new) Binary_Operation @key(with null record); @key(type) Subtraction @key(is new) Binary_Operation @key(with null record); --@RI[ No additional components needed for these extensions] Tree : Expr_Ptr := --@RI[ A tree representation of @lquotes@;5.0 + (13.0@en@;7.0)@rquotes@;] @key(new) Addition'( Left => @key(new) Literal'(Value => 5.0), Right => @key(new) Subtraction'( Left => @key(new) Literal'(Value => 13.0), Right => @key(new) Literal'(Value => 7.0))); @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Type extension is a new concept. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Type extensions now can be declared in more nested scopes than their parent types. Additional accessibility checks on @nt{allocator}s and return statements prevent objects from outliving their type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent extending synchronized tagged types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[Defined null extension for use elsewhere.]} @end{DiffWord95} @LabeledSubClause{Dispatching Operations of Tagged Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00335-01]} @RootDefn{dispatching operation} @Defn2{Term=[dispatching call], Sec=(on a dispatching operation)} @Defn2{Term=[nondispatching call], Sec=(on a dispatching operation)} @Defn{statically determined tag} @Defn{dynamically determined tag} @Defn{polymorphism} @Defn{run-time polymorphism} @Defn2{Term=[controlling tag], Sec=(for a call on a dispatching operation)} The primitive subprograms of a tagged type@Chg{Version=[2],New=[, the subprograms declared by @nt{formal_@!abstract_@!subprogram_@!declaration}s, and the stream attributes of a specific tagged type that are available (see @RefSecNum{Stream-Oriented Attributes}) at the end of the declaration list where the type is declared],Old=[]} are called @i(dispatching operations). @Redundant[A dispatching operation can be called using a statically determined @i{controlling} tag, in which case the body to be executed is determined at compile time. Alternatively, the controlling tag can be dynamically determined, in which case the call @i{dispatches} to a body that is determined at run time;] such a call is termed a @i{dispatching call}. @Redundant[As explained below, the properties of the operands and the context of a particular call on a dispatching operation determine how the controlling tag is determined, and hence whether or not the call is a dispatching call. Run-time polymorphism is achieved when a dispatching operation is called by a dispatching call.] @IndexSee{Term=[object-oriented programming (OOP)],See=[dispatching operations of tagged types]} @IndexSee{Term=[OOP (object-oriented programming)],See=[dispatching operations of tagged types]} @IndexSee{Term=[message],See=[dispatching call]} @IndexSee{Term=[method],See=[dispatching subprogram]} @IndexSee{Term=[virtual function],See=[dispatching subprogram]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00335-01]} @ChgAdded{Version=[2],Text=[For the stream attributes of a type declared immediately within a @nt{package_specification} that has a partial view, the declaration list to consider is the visible part of the package. Stream attributes that are not available in the same declaration list are not dispatching as there is no guarantee that descendants of the type have available attributes (there is such a guarantee for visibly available attributes). If we allowed dispatching for any available attribute, then for attributes defined in the private part we could end up executing a nonexistent body.]} @end{Reason} @end{Intro} @begin{MetaRules} The controlling tag determination rules are analogous to the overload resolution rules, except they deal with run-time type identification (tags) rather than compile-time type resolution. As with overload resolution, controlling tag determination may depend on operands or result context. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0076-1]} @Defn{call on a dispatching operation} @Defn{dispatching operation} A @i{call on a dispatching operation} is a call whose @nt<name> or @nt<prefix> denotes the declaration of@Chg{Version=[2],New=[], Old=[ a primitive subprogram of a tagged type, that is,]} a dispatching operation. @Defn{controlling operand} A @i{controlling operand} in a call on a dispatching operation of a tagged type @i(T) is one whose corresponding formal parameter is of type @i(T) or is of an anonymous access type with designated type @i(T); @Defn{controlling formal parameter} the corresponding formal parameter is called a @i(controlling formal parameter). If the controlling formal parameter is an access parameter, the controlling operand is the object designated by the actual parameter, rather than the actual parameter itself. @Defn{controlling result}@Chg{Version=[3],New=[@Defn2{Term=[function],Sec=[with a controlling result]}],Old=[]} If the call is to a (primitive) function with result type @i(T)@Chg{Version=[3],New=[ (a @i{function with a controlling result})],Old=[]}, then the call has a @i(controlling result) @em the context of the call can control the dispatching.@Chg{Version=[2], New=[ Similarly, if the call is to a function with @Chg{Version=[3],New=[an ],Old=[]}access result type designating @i(T)@Chg{Version=[3],New=[ (a @i{function with a controlling access result})],Old=[]}, then the call has a @i(controlling access result), and the context can similarly control dispatching.],Old=[]}@Chg{Version=[3],New=[@Defn{controlling access result}@Defn2{Term=[function],Sec=[with a controlling access result]}],Old=[]} @begin{Ramification} This definition implies that a call through the dereference of an access-to-subprogram value is never considered a call on a dispatching operation. Note also that if the @nt{prefix} denotes a @nt{renaming_declaration}, the place where the renaming occurs determines whether it is primitive; the thing being renamed is irrelevant. @end{Ramification} @Leading@;A @nt<name> or expression of a tagged type is either @i(statically) tagged, @i(dynamically) tagged, or @i(tag indeterminate), according to whether, when used as a controlling operand, the tag that controls dispatching is determined statically by the operand's (specific) type, dynamically by its tag at run time, or from context. A @nt<qualified_expression> or parenthesized expression is statically, dynamically, or indeterminately tagged according to its operand. For other kinds of @nt<name>s and expressions, this is determined as follows: @begin(Itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{statically tagged} The @nt<name> or expression is @i(statically tagged) if it is of a specific tagged type and, if it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]}, it has at least one statically tagged controlling operand; @begin{Discussion} It is illegal to have both statically tagged and dynamically tagged controlling operands in the same call -- see below. @end{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{dynamically tagged} The @nt<name> or expression is @i(dynamically tagged) if it is of a class-wide type, or it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]} and at least one dynamically tagged controlling operand; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Defn{tag indeterminate} The @nt<name> or expression is @i(tag indeterminate) if it is a call with a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]}, all of whose controlling operands (if any) are tag indeterminate. @end(itemize) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @Redundant[A @nt<type_conversion> is statically or dynamically tagged according to whether the type determined by the @nt<subtype_mark> is specific or class-wide, respectively.] @Chg{New=[For an object that is designated by an expression whose expected type is an anonymous access-to-specific tagged type, the object is dynamically tagged if the expression, ignoring enclosing parentheses, is of the form X'Access, where X is of a class-wide type, or is of the form @key(new) T'(...), where T denotes a class-wide subtype. Otherwise, the object], Old=[For a controlling operand that is designated by an actual parameter, the controlling operand]} is statically or dynamically tagged according to whether the designated type @Chg{New=[of the type of the expression], Old=[of the actual parameter]} is specific or class-wide, respectively. @begin{Ramification} A @nt<type_conversion> is never tag indeterminate, even if its operand is. A designated object is never tag indeterminate. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[1],Text=[Allocators and access attributes of class-wide types can be used as the controlling parameters of dispatching calls.]} @end{Ramification} @end{StaticSem} @begin{Legality} A call on a dispatching operation shall not have both dynamically tagged and statically tagged controlling operands. @begin{Reason} This restriction is intended to minimize confusion between whether the dynamically tagged operands are implicitly converted to, or tag checked against the specific type of the statically tagged operand(s). @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} If the expected type for an expression or @nt<name> is some specific tagged type, then the expression or @nt<name> shall not be dynamically tagged unless it is a controlling operand in a call on a dispatching operation. Similarly, if the expected type for an expression is an anonymous access-to-specific tagged type, then the @Chg{New=[object designated by the expression shall not be dynamically tagged unless it is],Old=[expression shall not be of an access-to-class-wide type unless it designates]} a controlling operand in a call on a dispatching operation. @begin(Reason) This prevents implicit "truncation" of a dynamically-tagged value to the specific type of the target object/formal. An explicit conversion is required to request this truncation. @end(Reason) @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01]}@ChgNote{Add info about prefix calls} This rule applies to all expressions or @nt<name>s with a specific expected type, not just those that are actual parameters to a dispatching call. This rule does not apply to a membership test whose @nt<expression> is class-wide, since any type that covers the tested type is explicitly allowed. See @RefSecNum(Relational Operators and Membership Tests).@Chg{Version=[2], New=[ This rule also doesn't apply to a @nt{selected_component} whose @nt{selector_name} is a subprogram, since the rules explicitly say that the prefix may be class-wide (see @RefSecNum{Selected Components}).],Old=[]} @end(Ramification) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00430-01]} In the declaration of a dispatching operation of a tagged type, everywhere a subtype of the tagged type appears as a subtype of the profile (see @RefSecNum(Subprogram Declarations)), it shall statically match the first subtype of the tagged type. @PDefn2{Term=[statically matching],Sec=(required)} If the dispatching operation overrides an inherited subprogram, it shall be subtype conformant with the inherited subprogram. @Defn2{Term=[subtype conformance],Sec=(required)} @Chg{New=[The convention of an inherited @Chg{Version=[2],New=[], Old=[or overriding ]}dispatching operation is the convention of the corresponding primitive operation of the parent @Chg{Version=[2],New=[or progenitor ],Old=[]}type. @Chg{Version=[2],New=[The default convention of a dispatching operation that overrides an inherited primitive operation is the convention of the inherited operation; if the operation overrides multiple inherited operations, then they shall all have the same convention. ],Old=[]}An explicitly declared],Old=[A]} dispatching operation shall not be of convention Intrinsic.@Chg{New=[],Old=[ If a dispatching operation overrides the predefined equals operator, then it shall be of convention Ada @Redundant[(either explicitly or by default @em see @RefSecNum{Conformance Rules})].]} @begin{Reason} These rules ensure that constraint checks can be performed by the caller in a dispatching call, and parameter passing conventions match up properly. A special rule on aggregates prevents values of a tagged type from being created that are outside of its first subtype. @end{reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} The @nt<default_expression> for a controlling formal parameter of a dispatching operation shall be tag indeter@!minate.@Chg{Version=[2], New=[],Old=[ A controlling formal parameter that is an access parameter shall not have a @nt<default_expression>.]} @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[This rule],Old=[The first part]} ensures that the @nt{default_expression} always produces the "correct" tag when called with or without dispatching, or when inherited by a descendant. If it were statically tagged, the default would be useless for a dispatching call; if it were dynamically tagged, the default would be useless for a nondispatching call. @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00416-01]} @ChgDeleted{Version=[2],Text=[The second part is consistent with the first part, since designated objects are never tag-indeterminate.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00404-01]} @ChgAdded{Version=[2],Text=[If a dispatching operation is defined by a @nt{subprogram_renaming_declaration} or the instantiation of a generic subprogram, any access parameter of the renamed subprogram or the generic subprogram that corresponds to a controlling access parameter of the dispatching operation, shall have a subtype that excludes null.]} A given subprogram shall not be a dispatching operation of two or more distinct tagged types. @begin{Reason} This restriction minimizes confusion since multiple dispatching is not provided. The normal solution is to replace all but one of the tagged types with their class-wide types. @end{reason} @begin{ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0098],ARef=[AI95-00183-01]} @ChgAdded{Version=[1],Text=[This restriction applies even if the partial view (see @RefSecNum{Private Types and Private Extensions}) of one or both of the types is untagged. This follows from the definition of dispatching operation: the operation is a dispatching operation anywhere the full views of the (tagged) types are visible.]} @end{ramification} The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen (see @RefSecNum{Freezing Rules}). @Redundant[For example, new dispatching operations cannot be added after objects or values of the type exist, nor after deriving a record extension from it, nor after a body.] @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @begin{Discussion} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]} @end{Discussion}} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]}@ChgNote{Tags now have two parts, logically} This rule is needed because (1) we don't want people dispatching to things that haven't been declared yet, and (2) we want to allow @Chg{Version=[2],New=[the static part of ],Old=[]}tagged type descriptors to be static (allocated statically, and initialized to link-time-known symbols). Suppose T2 inherits primitive P from T1, and then overrides P. Suppose P is called @i{before} the declaration of the overriding P. What should it dispatch to? If the answer is the new P, we've violated the first principle above. If the answer is the old P, we've violated the second principle. (A call to the new one necessarily raises Program_Error, but that's beside the point.) Note that a call upon a dispatching operation of type @i(T) will freeze @i(T). We considered applying this rule to all derived types, for uniformity. However, that would be upward incompatible, so we rejected the idea. As in Ada 83, for an untagged type, the above call upon P will call the old P (which is arguably confusing). @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]}@ChgNote{We have tagged incomplete types now, and they don't freeze} Because of this rule, the type descriptor can be created (presumably containing linker symbols pointing at the not-yet-compiled bodies) at the first freezing point of the type. It also prevents, for a @Chg{Version=[2],New=[(nonincomplete) ],Old=[]}tagged type declared in a @nt{package_specification}, overriding in the body or by a child subprogram. @end{ImplNote} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]}@ChgNote{Interfaces cause this too} A consequence is that for a @Chg{Version=[2],New=[tagged type declaration], Old=[@ntf{derived_type_declaration}]} in a @nt{declarative_part}, only the @Chg{Version=[2],New=[last (overriding)],Old=[first]} primitive subprogram can be declared by a @nt{subprogram_body}.@Chg{Version=[2],New=[ (Other overridings must be provided by @nt{subprogram_declaration}s.)],Old=[]} @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0222-1]} @ChgAdded{Version=[3],Text=[This rule applies only to "original" declarations and not to the completion of a primitive subprogram, even though a completion is technically an explicit declaration, and it may declare a primitive subprogram.]} @end{Honest} @end{Legality} @begin{RunTime} @Leading@PDefn2{Term=[execution], Sec=(call on a dispatching operation)} @Defn{controlling tag value} For the execution of a call on a dispatching operation of a type @i(T), the @i(controlling tag value) determines which subprogram body is executed. The controlling tag value is defined as follows: @begin(itemize) @PDefn{statically determined tag} If one or more controlling operands are statically tagged, then the controlling tag value is @i(statically determined) to be the tag of @i(T). If one or more controlling operands are dynamically tagged, then the controlling tag value is not statically determined, but is rather determined by the tags of the controlling operands. @IndexCheck{Tag_Check} If there is more than one dynamically tagged controlling operand, a check is made that they all have the same tag. @Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If this check fails, Constraint_Error is raised unless the call is a @nt<function_call> whose @nt<name> denotes the declaration of an equality operator (predefined or user defined) that returns Boolean, in which case the result of the call is defined to indicate inequality, and no @nt<subprogram_body> is executed. This check is performed prior to evaluating any tag-indeterminate controlling operands. @begin(Reason) Tag mismatch is considered an error (except for "=" and "/=") since the corresponding primitive subprograms in each specific type expect all controlling operands to be of the same type. For tag mismatch with an equality operator, rather than raising an exception, "=" returns False and "/=" returns True. No equality operator is actually invoked, since there is no common tag value to control the dispatch. Equality is a special case to be consistent with the existing Ada 83 principle that equality comparisons, even between objects with different constraints, never raise Constraint_Error. @end(Reason) @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00196-01]} If all of the controlling operands @Chg{Version=[2],New=[(if any) ],Old=[]}are tag-indeterminate, then: @begin(inneritemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00239-01],ARef=[AI95-00416-01]} If the call has a controlling result@Chg{Version=[2],New=[ or controlling access result],Old=[]} and is itself@Chg{Version=[2],New=[, or designates,],Old=[]} a (possibly parenthesized or qualified) controlling operand of an enclosing call on a dispatching operation of @Chg{Version=[2],New=[a descendant of ],Old=[]}type @i(T), then its controlling tag value is determined by the controlling tag value of this enclosing call; @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00239-01]} @ChgAdded{Version=[2],Text=[For code that a user can write explicitly, the only contexts that can control dispatching of a function with a controlling result of type T are those that involve controlling operands of the same type T: if the two types differ there is an illegality and the dynamic semantics are irrelevant.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In the case of an inherited subprogram however, if a default expression is a function call, it may be of type T while the parameter is of a type derived from T. To cover this case, we talk about "a descendant of T" above. This is safe, because if the type of the parameter is descended from the type of the function result, it is guaranteed to inherit or override the function, and this ensures that there will be an appropriate body to dispatch to. Note that abstract functions are not an issue here because the call to the function is a dispatching call, so it is guaranteed to always land on a concrete body.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00196-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the call has a controlling result or controlling access result and (possibly parenthesized, qualified, or dereferenced) is the expression of an @nt{assignment_statement} whose target is of a class-wide type, then its controlling tag value is determined by the target;]} @PDefn{statically determined tag} Otherwise, the controlling tag value is statically determined to be the tag of type @i(T). @begin{Ramification} This includes the cases of a tag-indeterminate procedure call, and a tag-indeterminate @nt{function_call} that is used to initialize a class-wide formal parameter or class-wide object. @end{Ramification} @end(inneritemize) @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0126-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{Dummy add to allow conditional "leading"} For the execution of a call on a dispatching operation, the @Chg{Version=[2],New=[action performed is determined by the properties of the corresponding dispatching operation],Old=[body executed is the one for the corresponding primitive subprogram]} of the specific type identified by the controlling tag value@Chg{Version=[3],New=[:],Old=[. @Chg{Version=[2],New=[If the corresponding operation is],Old=[The body for an]} explicitly declared @Chg{Version=[2],New=[for this type, @Redundant[even if the declaration occurs in a private part], then the action comprises an invocation of the], Old=[dispatching operation is the corresponding]} explicit body for the @Chg{Version=[2],New=[operation. If the corresponding operation is implicitly declared for this type:],Old=[subprogram. The body for an implicitly declared dispatching operation that is overridden is the body for the overriding subprogram, @Redundant[even if the overriding occurs in a private part.] The body for an inherited dispatching operation that is not overridden is the body of the corresponding subprogram of the parent or ancestor type.]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0126-1]} @ChgAdded{Version=[3],Text=[if the corresponding operation is explicitly declared for this type, @Redundant[even if the declaration occurs in a private part], then the action comprises an invocation of the explicit body for the operation;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0126-1]} @ChgAdded{Version=[2],Text=[if the @Chg{Version=[3],New=[corresponding ],Old=[]}operation is @Chg{Version=[3],New=[implicitly declared for this type and is ],Old=[]}implemented by an entry or protected subprogram (see @RefSecNum{Task Units and Task Objects} and @RefSecNum{Protected Units and Protected Objects}), then the action comprises a call on this entry or protected subprogram, with the target object being given by the first actual parameter of the call, and the actual parameters of the entry or protected subprogram being given by the remaining actual parameters of the call, if any;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0197-1]} @ChgAdded{Version=[3],Text=[if the corresponding operation is a predefined operator then the action comprises an invocation of that operator;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0126-1],ARef=[AI05-0197-1],ARef=[AI05-0250-1],ARef=[AI05-0254-1]} @ChgAdded{Version=[2],Text=[otherwise, the action is the same as the action for the corresponding operation of the parent type@Chg{Version=[3],New=[ or progenitor type from which the operation was inherited except that additional invariant checks (see @RefSecnum{Type Invariants}) and class-wide postcondition checks (see @RefSecNum{Preconditions and Postconditions}) may apply. If there is more than one such corresponding operation, the action is that for the operation that is not a null procedure, if any; otherwise, the action is that of an arbitrary one of the operations],Old=[]}.]} @end{Itemize} @begin{Honest} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0126-1]} @ChgDeleted{Version=[3],Text=[In the unusual case in which a dispatching subprogram is explicitly declared (overridden) by a body (with no preceding @nt{subprogram_declaration}), the body for that dispatching subprogram is that body; that is, the @lquotes@;corresponding explicit body@rquotes@; in the above rule is the body itself.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0005-1],ARef=[AI05-0126-1]} @ChgAdded{Version=[3],Text=[@ldquote@;Corresponding dispatching operation@rdquote refers to the inheritance relationship between subprograms. Primitive operations are always inherited for a type T, but they might not be declared if the primitive operation is never visible within the immediate scope of the type T. If no corresponding operation is declared, the last bullet is used and the corresponding operation of the parent type is executed (an explicit body that happens to have the same name and profile is not called in that case).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0005-1],ARef=[AI05-0126-1]} @ChgAdded{Version=[3],Text=[We have to talk about progenitors in the last bullet in case the corresponding operation is a null procedure inherited from an interface. In that case, the parent type might not even have the operation in question.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0197-1]} @ChgAdded{Version=[3],Text=[For the last bullet, if there are multiple corresponding operations for the parent and progenitors, all but one of them have to be a null procedure. (If the progenitors declared abstract routines, there would have to be an explicit overriding of the operation, and then the first bullet would apply.) We call the nonnull routine if one exists.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0126-1]} @ChgAdded{Version=[3],Text=[Any explicit declaration for an inherited corresponding operation has to be an overriding routine. These rules mean that a dispatching call executes the overriding routine (if any) for the specific type.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @Leading@;The wording of the above @Chg{Version=[3],New=[rules],Old=[rule]} is intended to ensure that the same body is executed for a given tag, whether that tag is determined statically or dynamically. For a type declared in a package, it doesn't matter whether a given subprogram is overridden in the visible part or the private part, and it doesn't matter whether the call is inside or outside the package. For example: @begin{Example} @key[package] P1 @key[is] @key[type] T1 @key[is] @key[tagged] @key[null] @key[record]; @key[procedure] Op_A(Arg : @key[in] T1); @key[procedure] Op_B(Arg : @key[in] T1); @key[end] P1; @key[with] P1; @key[use] P1; @key[package] P2 @key[is] @key[type] T2 @key[is] @key[new] T1 @key[with] @key[null] @key[record]; @key[procedure] Op_A(Param : @key[in] T2); @key[private] @key[procedure] Op_B(Param : @key[in] T2); @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00009 & AI-00114} @key[with] P1; @key[with] P2; @key[procedure] Main @key[is] X : @Chg{New=[P2.],Old=[]}T2; Y : @Chg{New=[P1.],Old=[]}T1'Class := X; @key[begin] P2.Op_A(Param => X); --@RI{ Nondispatching call@Chg{New=[ to a dispatching operation],Old=[]}.} P1.Op_A(Arg => Y); --@RI{ Dispatching call.} P2.Op_B(Arg => X); --@RI{ Nondispatching call@Chg{New=[ to a dispatching operation],Old=[]}.} P1.Op_B(Arg => Y); --@RI{ Dispatching call.} @key[end] Main; @end{Example} The two calls to Op_A both execute the body of Op_A that has to occur in the body of package P2. Similarly, the two calls to Op_B both execute the body of Op_B that has to occur in the body of package P2, even though Op_B is overridden in the private part of P2. Note, however, that the formal parameter names are different for P2.Op_A versus P2.Op_B. The overriding declaration for P2.Op_B is not visible in Main, so the name in the call actually denotes the implicit declaration of Op_B inherited from T1. If a call occurs in the program text before an overriding, which can happen only if the call is part of a default expression, the overriding will still take effect for that call. @end{Reason} @begin{ImplNote} Even when a tag is not @i(statically determined), a compiler might still be able to figure it out and thereby avoid the overhead of run-time dispatching. @end{implnote} @end{RunTime} @begin{Notes} The body to be executed for a call on a dispatching operation is determined by the tag; it does not matter whether that tag is determined statically or dynamically, and it does not matter whether the subprogram's declaration is visible at the place of the call. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} This subclause covers calls on @Chg{Version=[2],New=[dispatching], Old=[primitive]} subprograms of a tagged type. Rules for tagged type membership tests are described in @RefSecNum(Relational Operators and Membership Tests). Controlling tag determination for an @nt{assignment_statement} is described in @RefSecNum(Assignment Statements). A dispatching call can dispatch to a body whose declaration is not visible at the place of the call. A call through an access-to-subprogram value is never a dispatching call, even if the access value designates a dispatching operation. Similarly a call whose @nt<prefix> denotes a @nt<subprogram_renaming_declaration> cannot be a dispatching call unless the renaming itself is the declaration of a primitive subprogram. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concept of dispatching operations is new. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00404-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} If a dispatching operation is defined by a @nt{subprogram_renaming_declaration}, and it has a controlling access parameter, Ada 2005 requires the subtype of the parameter to exclude null. The same applies to instantiations. This is required so that all calls to the subprogram operate the same way (controlling access parameters have to exclude null so that dispatching calls will work). Since Ada 95 didn't have the notion of access subtypes that exclude null, and all access parameters excluded null, it had no such rules. These rules will require the addition of an explicit @key{not null} on nondispatching operations that are later renamed to be dispatching, or on a generic that is used to define a dispatching operation.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Functions that have an access result type can be dispatching in the same way as a function that returns a tagged object directly.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:>@ChgNote{This is documented as an extension in the two @Chg{Version=[3],New=[clauses],Old=[sections]} referenced below.} Allocators and access attributes of objects of class-wide types can be used as the controlling parameter in a dispatching calls. This was an oversight in the definition of Ada 95. (See @RefSecNum{Operations of Access Types} and @RefSecNum{Allocators}).]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0011],ARef=[AI95-00117-01],ARef=[AI95-00430-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the conventions of dispatching operations. This is extended in Ada 2005 to cover operations inherited from progenitors, and to ensure that the conventions of all inherited operations are the same.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00196-01]} @ChgAdded{Version=[2],Text=[Clarified the wording to ensure that functions with no controlling operands are tag-indeterminate, and to describe that the controlling tag can come from the target of an @nt{assignment_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00239-01]} @ChgAdded{Version=[2],Text=[Fixed the wording to cover default expressions inherited by derived subprograms. A literal reading of the old wording would have implied that operations would be called with objects of the wrong type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[An abstract formal subprogram is a dispatching operation, even though it is not a primitive operation. See @RefSec{Formal Subprograms}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Dispatching calls include operations implemented by entries and protected operations, so we have to update the wording to reflect that.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00335-01]} @ChgAdded{Version=[2],Text=[A stream attribute of a tagged type is usually a dispatching operation, even though it is not a primitive operation. If they weren't dispatching, T'Class'Input and T'Class'Output wouldn't work.]} @end{Diffword95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0076-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined @ldquote@;function with a controlling result@rdquote, as it is used in @RefSecNum{Abstract Types and Subprograms}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0126-1],ARef=[AI05-0197-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected holes in the definition of dynamic dispatching: the behavior for operations that are never declared and/or inherited from a progenitor were not specified.]} @end{Diffword2005} @LabeledSubClause{Abstract Types and Subprograms} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @redundant[@Defn{abstract type} @IndexSeeAlso{Term=[abstract data type (ADT)],See=(abstract type)} @IndexSeeAlso{Term=[ADT (abstract data type)],See=(abstract type)} @IndexSee{Term=[concrete type],See=(nonabstract type)} An @i(abstract type) is a tagged type intended for use as @Chg{Version=[2],New=[an ancestor of other types],Old=[a parent type for type extensions]}, but which is not allowed to have objects of its own. @Defn{abstract subprogram} @IndexSee{Term=[concrete subprogram],See=(nonabstract subprogram)} An @i(abstract subprogram) is a subprogram that has no body, but is intended to be overridden at some point when inherited. Because objects of an abstract type cannot be created, a dispatching call to an abstract subprogram always dispatches to some overriding body.] @ChgToGlossary{Version=[2],Kind=[Added],Term=<Abstract type>, Text=<@ChgAdded{Version=[2],Text=[An abstract type is a tagged type intended for use as an ancestor of other types, but which is not allowed to have objects of its own.]}>} @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} An abstract subprogram has no body, so the rules in this @Chg{Version=[3],New=[subclause],Old=[clause]} are designed to ensure (at compile time) that the body will never be invoked. We do so primarily by disallowing the creation of values of the abstract type. Therefore, since type conversion and parameter passing don't change the tag, we know we will never get a class-wide value with a tag identifying an abstract type. This means that we only have to disallow nondispatching calls on abstract subprograms (dispatching calls will never reach them). @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00218-03],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<abstract_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] @Syn2{subprogram_specification} @key{is} @key{abstract}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @Chg{Version=[2],New=[@Defn{abstract type} @Defn2{Term=[type], Sec=(abstract)}Interface types (see @RefSecNum{Interface Types}) are abstract types. In addition, a tagged type that has the reserved word @key{abstract} in its declaration is an abstract type. The class-wide type (see @RefSecNum{Derivation Classes}) rooted at an abstract type is not itself an abstract type.],Old=[]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Chg{Version=[2],New=[Only a tagged type shall have],Old=[@Defn{abstract type} @Defn2{Term=[type], Sec=(abstract)} An @i{abstract type} is a specific type that has]} the reserved word @key{abstract} in its declaration.@Chg{Version=[2],New=[],Old=[Only a tagged type is allowed to be declared abstract.]} @begin{Ramification}@ChgNote{These AARM notes really belong on the Static Semantics paragraph, but I won't move them, as it's not worth the time.} Untagged types are never abstract, even though they can have primitive abstract subprograms. Such subprograms cannot be called, unless they also happen to be dispatching operations of some tagged type, and then only via a dispatching call. Class-wide types are never abstract. If T is abstract, then it is illegal to declare a stand-alone object of type T, but it is OK to declare a stand-alone object of type T'Class; the latter will get a tag from its initial value, and this tag will necessarily be different from T'Tag. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02],ARef=[AI95-00348-01]} @Defn{abstract subprogram} @Defn2{Term=[subprogram], Sec=(abstract)} A subprogram declared by an @nt{abstract_@!subprogram_@!declaration} @Chg{Version=[2],New=[or a @nt{formal_@!abstract_@!subprogram_@!declaration} (see @RefSecNum{Formal Subprograms})], Old=[(see @RefSecNum{Subprogram Declarations})]} is an @i{abstract subprogram}. If it is a primitive subprogram of a tagged type, then the tagged type shall be abstract. @begin{Ramification} @Leading@keepnext@;Note that for a private type, this applies to both views. The following is illegal: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[abstract] @key[tagged] @key[private]; @key[function] Foo (X : T) @key[return] Boolean @key[is] @key[abstract]; --@RI{ Illegal!} @key[private] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; --@RI{ Illegal!} X : T; Y : Boolean := Foo (T'Class (X)); @key[end] P; @end{Example} The full view of T is not abstract, but has an abstract operation Foo, which is illegal. The two lines marked "--@i{ Illegal!}" are illegal when taken together. @end{Ramification} @begin{Reason} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} We considered disallowing untagged types from having abstract primitive subprograms. However, we rejected that plan, because it introduced some silly anomalies, and because such subprograms are harmless@Chg{Version=[2], New=[],Old=[ (if not terribly useful)]}. For example: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00010} @key[package] P @key[is] @key[type] Field_Size @key[is] @key[range] 0..100; @key[type] T @key[is] @key[abstract tagged] @key[null] @key[record]; @key[procedure] Print(X : @key[in] T; F : @key[in] Field_Size := 0) @key[is] @Chg{New=[@key[abstract]],Old=[abstract]}; . . . @key[package] Q @key[is] @key[type] My_Field_Size @key[is] @key[new] Field_Size; --@RI{ implicit declaration of Print(X : T; F : My_Field_Size := 0) @Chg{New=[@key[is abstract]],Old=[is abstract]};} @key[end] Q; @end{Example} It seemed silly to make the derivative of My_Field_Size illegal, just because there was an implicitly declared abstract subprogram that was not primitive on some tagged type. Other rules could be formulated to solve this problem, but the current ones seem like the simplest. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[In Ada 2005, abstract primitive subprograms of an untagged type may be used to @lquotes@;undefine@rquotes@; an operation.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Note that the second sentence does not apply to abstract formal subprograms, as they are never primitive operations of a type.]} @end{Ramification} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00334-01],ARef=[AI95-00391-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0097-1],ARef=[AI05-0198-1]} @Chg{Version=[2],New=[If a type has an implicitly declared primitive subprogram that is inherited or is @Chg{Version=[3],New=[a],Old=[the]} predefined @Chg{Version=[3],New=[],Old=[equality ]}operator, and the corresponding primitive subprogram of],Old=[For a derived type, if]} the parent or ancestor type @Chg{Version=[2],New=[is abstract or is a function with a controlling access result, or if a type other than a @Chg{Version=[3],New=[nonabstract ],Old=[]}null extension inherits a], Old=[has an abstract primitive subprogram, or a primitive]} function with a controlling result, then: @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0068-1]} @ChgAdded{Version=[3],Text=[These rules apply to each view of the type individually. That is necessary to preserve privacy. For instance, in the following example:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] P @key[is] @key[type] I @key[is interface]; @key[procedure] Op (X : I) @key[is abstract]; @key[end] P;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] P; @key[package] Q @key[is] @key[type] T @key[is abstract new] P.I @key[with private]; -- @RI[Op inherited here.] @key[private] @key[type] T @key[is abstract new] P.I @key[with null record]; @key[procedure] Op (X : T) @key[is null]; @key[end] Q;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Q; @key[package] R @key[is] @key[type] T2 @key[is new] Q.T @key[with null record]; -- @RI[Illegal. Op inherited here, but requires overriding.] @key[end] R;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If this did not depend on the view, this would be legal. But in that case, the fact that Op is overridden in the private part would be visible; package R would have to be illegal if no overriding was in the private part.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that this means that whether an inherited subprogram is abstract or concrete depends on where it inherited. In the case of Q, Q.Op in the visible part is abstract, while Q.Op in the private part is concrete. That is, R is illegal since it is an unrelated unit (and thus it cannot see the private part), but if R had been a private child of Q, it would have been legal.]} @end{Ramification} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00334-01]} If the @Chg{Version=[2],New=[],Old=[derived ]}type is abstract or untagged, the @Chg{Version=[2],New=[implicitly declared],Old=[inherited]} subprogram is @i{abstract}. @begin{Ramification} Note that it is possible to override a concrete subprogram with an abstract one. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00391-01]} Otherwise, the subprogram shall be overridden with a nonabstract subprogram@Chg{Version=[2],New=[ or, in the case of a private extension inheriting a function with a controlling result, have a full type that is a null extension],Old=[]}@Redundant[; for a type declared in the visible part of a package, the overriding may be either in the visible or the private part]. @Chg{Version=[2],New=[Such a subprogram is said to @i{require overriding}.@Defn{require overriding} ],Old=[]}However, if the type is a generic formal type, the subprogram need not be overridden for the formal type itself; @Redundant[a nonabstract version will necessarily be provided by the actual type.] @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00228-01],ARef=[AI95-00391-01]} A function that returns the parent type @Chg{Version=[2],New=[requires overriding],Old=[becomes abstract]}@ChgNote{Can't leave this ancient and broken terminology around here!!} for @Chg{Version=[2],New=[a],Old=[an abstract]} type extension @Chg{Version=[2],New=[(or becomes abstract for an abstract type)], Old=[(if not overridden)]} because conversion from a parent type to a type extension is not defined, and function return semantics is defined in terms of conversion@Chg{Version=[2],New=[ (other than for a null extension; see below)],Old=[]}. (Note that parameters of mode @key{in out} or @key{out} do not have this problem, because the tag of the actual is not changed.) @Leading@keepnext@;Note that the overriding required above can be in the private part, which allows the following: @begin{Example} @key[package] Pack1 @key[is] @key[type] Ancestor @key[is] @key[abstract] ...; @key[procedure] Do_Something(X : @key[in] Ancestor) @key[is] @key[abstract]; @key[end] Pack1; @key[with] Pack1; @key[use] Pack1; @key[package] Pack2 @key[is] @key[type] T1 @key[is] @key[new] Ancestor @key[with] @key[record] ...; --@RI{ A concrete type.} @key[procedure] Do_Something(X : @key[in] T1); --@RI{ Have to override.} @key[end] Pack2; @key[with] Pack1; @key[use] Pack1; @key[with] Pack2; @key[use] Pack2; @key[package] Pack3 @key[is] @key[type] T2 @key[is] @key[new] Ancestor @key[with] @key[private]; --@RI{ A concrete type.} @key[private] @key[type] T2 @key[is] @key[new] T1 @key[with] --@RI{ Parent different from ancestor.} @key[record] ... @key[end] @key[record]; --@RI{ Here, we inherit Pack2.Do_Something.} @key[end] Pack3; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00011} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00228-01]} T2 inherits an abstract Do_Something, but @Chg{New=[T2],Old=[T]} is not abstract, so Do_Something has to be overridden. However, it is OK to override it in the private part. In this case, we override it by inheriting a concrete version from a different type. Nondispatching calls to Pack3.Do_Something are allowed both inside and outside package Pack3@Chg{Version=[2],New=[, as the client @lquotes@;knows@rquotes@; that the subprogram was necessarily overridden somewhere],Old=[]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[For a null extension, the result of a function with a controlling result is defined in terms of an @nt{extension_aggregate} with a @key{null record} extension part (see @RefSecNum{Derived Types and Classes}). This means that these restrictions on functions with a controlling result do not have to apply to null extensions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[However, functions with controlling access results still require overriding. Changing the tag in place might clobber a preexisting object, and allocating new memory would possibly change the pool of the object, leading to storage leaks. Moreover, copying the object isn't possible for limited types. We don't need to restrict functions that have an access return type of an untagged type, as derived types with primitive subprograms have to have the same representation as their parent type.]} @end{Reason} @end{Itemize} A call on an abstract subprogram shall be a dispatching call; @Redundant[nondispatching calls to an abstract subprogram are not allowed.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} If an abstract subprogram is not a dispatching operation of some tagged type, then it cannot be called at all.@Chg{Version=[2],New=[ In Ada 2005, such subprograms are not even considered by name resolution (see @RefSecNum{Subprogram Calls}).],Old=[]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0073-1],ARef=[AI05-0203-1]} The type of an @nt{aggregate}, or of an object created by an @nt{object_declaration} or an @nt{allocator}, or a generic formal object of mode @key[in], shall not be abstract. The type of the target of an assignment operation (see @RefSecNum{Assignment Statements}) shall not be abstract. The type of a component shall not be abstract. If the result type of a function is abstract, then the function shall be abstract.@Chg{Version=[3],New=[ If a function has an access result type designating an abstract type, then the function shall be abstract. The type denoted by a @nt{return_subtype_indication} (see @RefSecNum{Return Statements}) shall not be abstract. A generic function shall not have an abstract result type or an access result type designating an abstract type.],Old=[]} @begin{Reason} This ensures that values of an abstract type cannot be created, which ensures that a dispatching call to an abstract subprogram will not try to execute the nonexistent body. Generic formal objects of mode @key[in] are like constants; therefore they should be forbidden for abstract types. Generic formal objects of mode @key[in out] are like renamings; therefore, abstract types are OK for them, though probably not terribly useful. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0073-1]} @ChgAdded{Version=[3],Text=[Generic functions returning a formal abstract type are illegal because any instance would have to be instantiated with a nonabstract type in order to avoid violating the function rule (generic functions cannot be declared abstract). But that would be an implied contract; it would be better for the contract to be explicit by the formal type not being declared abstract. Moreover, the implied contract does not add any capability.]} @end{Reason} If a partial view is not abstract, the corresponding full view shall not be abstract. If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract. @begin{Discussion} By contrast, we allow the actual type to be nonabstract even if the formal type is declared abstract. Hence, the most general formal tagged type possible is "@key(type) T(<>) @key(is abstract tagged limited private);". For an abstract private extension declared in the visible part of a package, it is only possible for the full type to be nonabstract if the private extension has no abstract dispatching operations. @end{Discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00294-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the sentence about primitive subprograms above, there is some ambiguity as to what is meant by @lquotes@;corresponding@rquotes@; in the case where an inherited operation is overridden. This is best explained by an example, where the implicit declarations are shown as comments:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P1 @key{is} @key{type} T1 @key{is abstract tagged null record}; @key{procedure} P (X : T1); -- @RI[(1)] @key{end} P1;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P2 @key{is} @key{type} T2 @key{is abstract new} P1.T1 @key{with null record}; -- @RI[@key{procedure} P (X : T2); -- (2)] @key{procedure} P (X : T2) @key{is abstract}; -- (3) end P2;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} D @key{is abstract new} P1.T1 @key{with private}; -- @RI[@key{procedure} P (X : D); -- (4)] @key{procedure} G (X : D);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} I @key{is new} G (P2.T2); -- @RI[Illegal.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[Type T2 inherits a nonabstract procedure P (2) from the primitive procedure P (1) of T1. P (2) is overridden by the explicitly declared abstract procedure P (3). Type D inherits a nonabstract procedure P (4) from P (1). In instantiation I, the operation corresponding to P (4) is the one which is not overridden, that is, P (3): the overridden operation P (2) does not @lquotes@;reemerge@rquotes@;. Therefore, the instantiation is illegal.],Old=[]} @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0073-1]} For an abstract type declared in a visible part, an abstract primitive subprogram shall not be declared in the private part, unless it is overriding an abstract subprogram implicitly declared in the visible part. For a tagged type declared in a visible part, a primitive function with a controlling result@Chg{Version=[3],New=[ or a controlling access result],Old=[]} shall not be declared in the private part, unless it is overriding a function implicitly declared in the visible part. @begin{Reason} @Leading@;The @lquotes@;visible part@rquotes@; could be that of a package or a generic package. This rule is needed because a nonabstract type extension declared outside the package would not know about any abstract primitive subprograms or primitive functions with controlling results declared in the private part, and wouldn't know that they need to be overridden with nonabstract subprograms. The rule applies to a tagged record type or record extension declared in a visible part, just as to a tagged private type or private extension. The rule applies to explicitly and implicitly declared abstract subprograms: @begin{Example} @key[package] Pack @key[is] @key[type] T @key[is] @key[abstract] @key[new] T1 @key[with] @key[private]; @key[private] @key[type] T @key[is] @key[abstract] @key[new] T2 @key[with] @key[record] ... @key[end] @key[record]; ... @key[end] Pack; @end{Example} The above example would be illegal if T1 has a nonabstract primitive procedure P, but T2 overrides P with an abstract one; the private part should override P with a nonabstract version. On the other hand, if the P were abstract for both T1 and T2, the example would be legal as is. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} A generic actual subprogram shall not be an abstract subprogram @Chg{Version=[2],New=[unless the generic formal subprogram is declared by a @nt{formal_abstract_subprogram_declaration}],Old=[]}. The @nt{prefix} of an @nt{attribute_reference} for the Access, Unchecked_Access, or Address attributes shall not denote an abstract subprogram. @begin{Ramification} An @nt{abstract_subprogram_declaration} is not syntactically a @nt{subprogram_declaration}. Nonetheless, an abstract subprogram is a subprogram, and an @nt{abstract_subprogram_declaration} is a declaration of a subprogram. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} The part about generic actual subprograms includes those given by default.@Chg{Version=[2],New=[ Of course, an abstract formal subprogram's actual subprogram can be abstract.],Old=[]} @end{Ramification} @end{Legality} @begin{Runtime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[elaboration], Sec=(abstract_subprogram_declaration)} The elaboration of an @nt{abstract_subprogram_declaration} has no effect.]} @end{Runtime} @begin{Notes} Abstractness is not inherited; to declare an abstract type, the reserved word @key[abstract] has to be used in the declaration of the type extension. @begin{Ramification} A derived type can be abstract even if its parent is not. Similarly, an inherited concrete subprogram can be overridden with an abstract subprogram. @end{Ramification} A class-wide type is never abstract. Even if a class is rooted at an abstract type, the class-wide type for the class is not abstract, and an object of the class-wide type can be created; the tag of such an object will identify some nonabstract type in the class. @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of an abstract type representing a set of natural numbers:) @begin{Example} @key(package) Sets @key(is) @key(subtype) Element_Type @key(is) Natural; @key(type) Set @key(is abstract tagged null record); @key(function) Empty @key(return) Set @key(is abstract); @key(function) Union(Left, Right : Set) @key(return) Set @key(is abstract); @key(function) Intersection(Left, Right : Set) @key(return) Set @key(is abstract); @key(function) Unit_Set(Element : Element_Type) @key(return) Set @key(is abstract); @key(procedure) Take(Element : @key(out) Element_Type; From : @key(in out) Set) @key(is abstract); @key(end) Sets; @end{Example} @end{Examples} @begin{Notes} @i(Notes on the example:) Given the above abstract type, one could then derive various (nonabstract) extensions of the type, representing alternative implementations of a set. One might use a bit vector, but impose an upper bound on the largest element representable, while another might use a hash table, trading off space for flexibility. @begin{Discussion} One way to export a type from a package with some components visible and some components private is as follows: @begin{Example} @key[package] P @key[is] @key[type] Public_Part @key[is] @key[abstract] @key[tagged] @key[record] ... @key[end] @key[record]; @key[type] T @key[is] @key[new] Public_Part @key[with] @key[private]; ... @key[private] @key[type] T @key[is] @key[new] Public_Part @key[with] @key[record] ... @key[end] @key[record]; @key[end] P; @end{Example} The fact that Public_Part is abstract tells clients they have to create objects of type T instead of Public_Part. Note that the public part has to come first; it would be illegal to declare a private type Private_Part, and then a record extension T of it, unless T were in the private part after the full declaration of Private_Part, but then clients of the package would not have visibility to T. @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} It is not necessary to override functions with a controlling result for a null extension. This makes it easier to derive a tagged type to complete a private type.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect the addition of interface types (see @RefSecNum{Interface Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect the addition of abstract formal subprograms (see @RefSecNum{Formal Subprograms}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00334-01]} @ChgAdded{Version=[2],Text=[The wording of shall-be-overridden was clarified so that it clearly applies to abstract predefined equality.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Moved the syntax and elaboration rule for @nt{abstract_subprogram_declaration} here, so the syntax and most of the semantics are together (which is consistent with null procedures).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00391-01]} @ChgAdded{Version=[2],Text=[We define the term @i<require overriding> to make other wording easier to understand.]} @end{Diffword95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0073-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added rules to eliminate holes with controlling access results and generic functions that return abstract types. While these changes are technically incompatible, it is unlikely that they could be used in a program without violating some other rule of the use of abstract types.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0097-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected a minor glitch having to do with abstract null extensions. The Ada 2005 rule allowed such extensions to inherit concrete operations in some rare cases. It is unlikely that these cases exist in user code.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in an @nt{abstract_subprogram_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0198-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that the predefined operator corresponding to an inherited abstract operator is also abstract. The Ada 2005 rules caused the predefined operator and the inherited operator to override each other, which is weird. But the effect is the same either way (the operator is not considered for resolution).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0203-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to disallow abstract return objects. These were illegal in Ada 2005 by other rules; the extension to support class-wide type better opened a hole which has now been plugged.]} @end{Diffword2005} @LabeledAddedSubClause{Version=[2],Name=[Interface Types]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Redundant[An interface type is an abstract tagged type that provides a restricted form of multiple inheritance. A tagged type, task type, or protected type may have one or more interface types as ancestors.]]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Interface type>, Text=<@ChgAdded{Version=[2],Text=[An interface type is a form of abstract tagged type which has no components or concrete operations except possibly null procedures. Interface types are used for composing other interfaces and tagged types and thereby provide multiple inheritance. Only an interface type can be used as a progenitor of another type.]}>} @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The rules are designed so that an interface can be used as either a parent type or a progenitor type without changing the meaning. That's important so that the order that interfaces are specified in a @nt{derived_type_definition} is not significant. In particular, we want:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Con1 @key{is new} Int1 @key{and} Int2 @key{with null record}; @key{type} Con2 @key{is new} Int2 @key{and} Int1 @key{with null record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[to mean exactly the same thing.]} @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<interface_type_definition>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@key{limited} | @key{task} | @key{protected} | @key{synchronized}] @key{interface} [@key{and} @Syn2{interface_list}]>,Old=<>}"} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00419-01]} @Syn{lhs=<@Chg{Version=[2],New=<interface_list>,Old=<>}>, rhs="@Chg{Version=[2],New=<@SynI{interface_}@Syn2{subtype_mark} {@key{and} @SynI{interface_}@Syn2{subtype_mark}}>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[An interface type (also called an @i{interface}) is@RootDefn{interface}@PDefn2{Term=[interface],Sec=[type]} a specific abstract tagged type that is defined by an @nt{interface_type_definition}.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface with the reserved word @key{limited}, @key{task}, @key{protected}, or @key{synchronized} in its definition is termed, respectively, a @i{limited interface}, a @i{task interface}, a @i{protected interface}, or a @i{synchronized interface}. In addition,@PDefn2{Term=[interface],Sec=[synchronized]} @PDefn2{Term=[interface],Sec=[protected]} @PDefn2{Term=[interface],Sec=[task]} @PDefn2{Term=[interface],Sec=[limited]} @PDefn2{Term=[interface],Sec=[nonlimited]} @Defn{synchronized interface} @Defn{protected interface} @Defn{task interface} @Defn{limited interface} @Defn{nonlimited interface} all task and protected interfaces are synchronized interfaces, and all synchronized interfaces are limited interfaces.]} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Synchronized>, Text=<@ChgAdded{Version=[2],Text=[A synchronized entity is one that will work safely with multiple tasks at one time. A synchronized interface can be an ancestor of a task or a protected type. Such a task or protected type is called a synchronized tagged type.]}>} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[@Defn{synchronized tagged type} @PDefn2{Term=[type],Sec=[synchronized tagged]} @PDefn2{Term=[tagged type],Sec=[synchronized]} @PDefn2{Term=[tagged type],Sec=[task]} @PDefn2{Term=[tagged type],Sec=[protected]} @Defn{task tagged type} @Defn{protected tagged type} @Redundant[A task or protected type derived from an interface is a tagged type.] Such a tagged type is called a @i<synchronized> tagged type, as are synchronized interfaces and private extensions whose declaration includes the reserved word @b{synchronized}.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The full definition of tagged types given in @RefSecNum{Tagged Types and Type Extensions} includes task and protected types derived from interfaces.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The class-wide type associated with a tagged task type (including a task interface type) is a task type, because @lquotes@;task@rquotes is one of the language-defined classes of types (see @RefSecNum{Types and Subtypes}). However, the class-wide type associated with an interface is @i<not> an interface type, as @lquotes@;interface@rquotes is @i<not> one of the language-defined classes (as it is not closed under derivation). In this sense, @lquotes@;interface@rquotes is similar to @lquotes@;abstract@rquotes. The class-wide type associated with an interface is a concrete (nonabstract) indefinite tagged composite type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@lquotes@;Private extension@rquotes@; includes generic formal private extensions, as explained in @RefSecNum{Formal Private and Derived Types}.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A task interface is an @Redundant[abstract] task type. A protected interface is an @Redundant[abstract] protected type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;abstract@rquotes follows from the definition of an interface type.]} @end{TheProof} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that task operations (like abort and the Terminated attribute) can be applied to a task interface type and the associated class-wide type. While there are no protected type operations, we apply the same rule to protected interfaces for consistency.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[@Redundant[An interface type has no components.]],Old=[]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This follows from the syntax and the fact that discriminants are not allowed for interface types.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{progenitor subtype}@Defn{progenitor type} An @Syni(interface_)@nt{subtype_mark} in an @nt{interface_list} names a @i(progenitor subtype); its type is the @i(progenitor type). An interface type inherits user-defined primitive subprograms from each progenitor type in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}).]} @ChgToGlossary{Version=[2],Kind=[Added],Term=<Progenitor>, Text=<@ChgAdded{Version=[2],Text=[A progenitor of a derived type is one of the types given in the definition of the derived type other than the first. A progenitor is always an interface type. Interfaces, tasks, and protected types may also have progenitors.]}>} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[All user-defined primitive subprograms of an interface type shall be abstract subprograms or null procedures.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The type of a subtype named in an @nt{interface_list} shall be an interface type.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A type derived from a nonlimited interface shall be nonlimited.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a task interface shall include the reserved word @key{task} in its definition; any other type derived from a task interface shall be a private extension or a task type declared by a task declaration (see @RefSecNum{Task Units and Task Objects}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a protected interface shall include the reserved word @key{protected} in its definition; any other type derived from a protected interface shall be a private extension or a protected type declared by a protected declaration (see @RefSecNum{Protected Units and Protected Objects}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[An interface derived from a synchronized interface shall include one of the reserved words @key{task}, @key{protected}, or @key{synchronized} in its definition; any other type derived from a synchronized interface shall be a private extension, a task type declared by a task declaration, or a protected type declared by a protected declaration.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require that an interface descendant of a task, protected, or synchronized interface repeat the explicit kind of interface it will be, rather than simply inheriting it, so that a reader is always aware of whether the interface provides synchronization and whether it may be implemented only by a task or protected type. The only place where inheritance of the kind of interface might be useful would be in a generic if you didn't know the kind of the actual interface. However, the value of that is low because you cannot implement an interface properly if you don't know whether it is a task, protected, or synchronized interface. Hence, we require the kind of the actual interface to match the kind of the formal interface (see @RefSecNum{Formal Interface Types}).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[No type shall be derived from both a task interface and a protected interface.]} @begin{Reason} @ChgAdded{Version=[2],Text=[This prevents a single private extension from inheriting from both a task and a protected interface. For a private type, there can be no legal completion. For a generic formal derived type, there can be no possible matching type (so no instantiation could be legal). This rule provides early detection of the errors.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.@PDefn{generic contract issue}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This paragraph is intended to apply to all of the @LegalityTitle@; in this @Chg{Version=[3],New=[subclause],Old=[clause]}. We cannot allow interface types which do not obey these rules, anywhere. Luckily, deriving from a formal type (which might be an interface) is not allowed for any tagged types in a generic body. So checking in the private part of a generic covers all of the cases.]} @end{Ramification} @end{Legality} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0070-1]} @ChgAdded{Version=[2],Text=[The elaboration of an @nt{interface_type_definition} @Chg{Version=[3],New=[creates the interface type and its first subtype],Old=[has no effect]}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[There is no other effect. ],Old=[]}An @nt{interface_list} is made up of @nt{subtype_mark}s, which do not need to be elaborated, so the @nt{interface_list} does not either. This is consistent with the handling of @nt{discriminant_part}s.]} @end{Discussion} @end{Runtime} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00411-01]} @ChgAdded{Version=[2],Text=[Nonlimited interface types have predefined nonabstract equality operators. These may be overridden with user-defined abstract equality operators. Such operators will then require an explicit overriding for any nonabstract descendant of the interface.]} @end{Notes} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example of a limited interface and a synchronized interface extending it:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Queue @key{is limited interface}; @key{procedure} Append(Q : @key{in out} Queue; Person : @key{in} Person_Name) @key{is abstract}; @key{procedure} Remove_First(Q : @key{in out} Queue; Person : @key{out} Person_Name) @key{is abstract}; @key{function} Cur_Count(Q : @key{in} Queue) @key{return} Natural @key{is abstract}; @key{function} Max_Count(Q : @key{in} Queue) @key{return} Natural @key{is abstract}; -- @RI[See @RefSecNum{Incomplete Type Declarations} for Person_Name.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[Queue_Error : @key{exception}; --@RI[ Append raises Queue_Error if @Chg{Version=[3],New=[Cur_Count],Old=[Count]}(Q) = Max_Count(Q)] --@RI[ Remove_First raises Queue_Error if @Chg{Version=[3],New=[Cur_Count],Old=[Count]}(Q) = 0]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Synchronized_Queue @key{is synchronized interface and} Queue; --@RI[ see @RefSecNum{Example of Tasking and Synchronization}] @key{procedure} Append_Wait(Q : @key{in out} Synchronized_Queue; Person : @key{in} Person_Name) @key{is abstract}; @key{procedure} Remove_First_Wait(Q : @key{in out} Synchronized_Queue; Person : @key{out} Person_Name) @key{is abstract};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} Transfer(From : @key{in out} Queue'Class; To : @key{in out} Queue'Class; Number : @key{in} Natural := 1) @key{is} Person : Person_Name; @key{begin} @key{for} I @key{in} 1..Number @key{loop} Remove_First(From, Person); Append(To, Person); @key{end loop}; @key{end} Transfer;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This defines a Queue interface defining a queue of people. (A similar design could be created to define any kind of queue simply by replacing Person_Name by an appropriate type.) The Queue interface has four dispatching operations, Append, Remove_First, Cur_Count, and Max_Count. The body of a class-wide operation, Transfer is also shown. Every nonabstract extension of Queue must provide implementations for at least its four dispatching operations, as they are abstract. Any object of a type derived from Queue may be passed to Transfer as either the From or the To operand. The two operands need not be of the same type in any given call.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Synchronized_Queue interface inherits the four dispatching operations from Queue and adds two additional dispatching operations, which wait if necessary rather than raising the Queue_Error exception. This synchronized interface may only be implemented by a task or protected type, and as such ensures safe concurrent access.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example use of the interface:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[@key{type} Fast_Food_Queue @key{is new} Queue @key{with record} ...; @key{procedure} Append(Q : @key{in out} Fast_Food_Queue; Person : @key{in} Person_Name); @key{procedure} Remove_First(Q : @key{in out} Fast_Food_Queue; Person : @Chg{Version=[3],New=[@key{out}],Old=[@key{in}]} Person_Name); @key{function} Cur_Count(Q : @key{in} Fast_Food_Queue) @key{return} Natural; @key{function} Max_Count(Q : @key{in} Fast_Food_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Cashier, Counter : Fast_Food_Queue;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[... -- @RI[Add George (see @RefSecNum{Incomplete Type Declarations}) to the cashier's queue:] Append (Cashier, George); -- @RI[After payment, move George to the sandwich counter queue:] Transfer (Cashier, Counter); ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An interface such as Queue can be used directly as the parent of a new type (as shown here), or can be used as a progenitor when a type is derived. In either case, the primitive operations of the interface are inherited. For Queue, the implementation of the four inherited routines must be provided. Inside the call of Transfer, calls will dispatch to the implementations of Append and Remove_First for type Fast_Food_Queue.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@i{Example of a task interface:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Serial_Device @key{is task interface}; --@RI[ see @RefSecNum{Task Units and Task Objects}] @key{procedure} Read (Dev : @key{in} Serial_Device; C : @key{out} Character) @key{is abstract}; @key{procedure} Write(Dev : @key{in} Serial_Device; C : @key{in} Character) @key{is abstract};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Serial_Device interface has two dispatching operations which are intended to be implemented by task entries (see 9.1).]} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Interface types are new. They provide multiple inheritance of interfaces, similar to the facility provided in Java and other recent language designs.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0070-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the definition of elaboration for an @nt{interface_type_definition} to match that of other type definitions.]} @end{DiffWord2005} @LabeledClause{Access Types} @begin{Intro} @Defn{access type} @Defn{access value} @Defn{designate} A value of an access type (an @i(access value)) provides indirect access to the object or subprogram it @i(designates). Depending on its type, an access value can designate either subprograms, objects created by allocators (see @RefSecNum(Allocators)), or more generally @i(aliased) objects of an appropriate type. @IndexSee{Term=[pointer],See=(access value)} @IndexSee{Term=[pointer type],See=(access type)} @begin(Discussion) A @nt<name> @i(denotes) an entity; an access value @i(designates) an entity. The @lquotes@;dereference@rquotes@; of an access value X, written @lquotes@;X.@key[all]@rquotes@;, is a @nt<name> that denotes the entity designated by X. @end(Discussion) @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Access values should always be well defined (barring uses of certain unchecked features of @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Representation Issues}). In particular, uninitialized access variables should be prevented by compile-time rules. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @Syn{lhs=<access_type_definition>,rhs=" @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{access_to_object_definition} | @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{access_to_subprogram_definition}"} @Syn{lhs=<access_to_object_definition>,rhs=" @key{access} [@Syn2{general_access_modifier}] @Syn2{subtype_indication}"} @Syn{lhs=<general_access_modifier>,rhs="@key{all} | @key{constant}"} @Syn{lhs=<access_to_subprogram_definition>,rhs=" @key{access} [@key{protected}] @key{procedure} @Syn2{parameter_profile} | @key{access} [@key{protected}] @key{function} @Syn2{parameter_and_result_profile}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[null_exclusion],Old=[]}>, rhs="@Chg{Version=[2],New=[@key{not} @key{null}],Old=[]}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00404-01]} @Syn{lhs=<access_definition>,rhs="@Chg{Version=[2],New=< [@Syn2{null_exclusion}] @key{access} [@key{constant}] @Syn2{subtype_mark} | [@Syn2{null_exclusion}] @key{access} [@key{protected}] @key{procedure} @Syn2{parameter_profile} | [@Syn2{null_exclusion}] @key{access} [@key{protected}] @key{function} @Syn2{parameter_and_result_profile}>, Old=[@key{access} @Syn2{subtype_mark}]}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0012],ARef=[AI95-00062-01]} @Defn{access-to-object type} @Defn{access-to-subprogram type} @Defn{pool-specific access type} @Defn{general access type} There are two kinds of access types, @i{access-to-object} types, whose values designate objects, and @i(access-to-subprogram) types, whose values designate subprograms. @Defn{storage pool} Associated with an access-to-object type is a @i(storage pool); several access types may share the same storage pool. @Chg{New=[All descendants of an access type share the same storage pool.],Old=[]} @Defn{pool element} A storage pool is an area of storage used to hold dynamically allocated objects (called @i(pool elements)) created by allocators@Redundant[; storage pools are described further in @RefSec(Storage Management)]. @Defn{pool-specific access type} @Defn{general access type} Access-to-object types are further subdivided into @i(pool-specific) access types, whose values can designate only the elements of their associated storage pool, and @i(general) access types, whose values can designate the elements of any storage pool, as well as aliased objects created by declarations rather than allocators, and aliased subcomponents of other objects. @begin(ImplNote) The value of an access type will typically be a machine address. However, a value of a pool-specific access type can be represented as an offset (or index) relative to its storage pool, since it can point only to the elements of that pool. @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00225-01],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0053-1],ARef=[AI05-0142-4],ARef=[AI05-0277-1]} @Defn{aliased} A view of an object is defined to be @i(aliased) if it is defined by an @nt<object_@!declaration>@Chg{Version=[3],New=[,],Old=[ or]} @nt<component_@!definition>@Chg{Version=[3],New=[, @nt{parameter_@!specification}, or @nt{extended_return_object_declaration}],Old=[]} with the reserved word @key(aliased), or by a renaming of an aliased view. In addition, the dereference of an access-to-object value denotes an aliased view, as does a view conversion (see @RefSecNum{Type Conversions}) of an aliased view. @Chg{Version=[2],New=[The],Old=[Finally, the]} current instance of @Chg{Version=[3],New=[an immutably limited type (see @RefSecNum{Limited Types}) is],Old=[a limited@Chg{Version=[2],New=[ tagged],Old=[]} type, @Chg{Version=[2],New=[a protected type, a task type, or a type that has the reserved word @key{limited} in its full definition is also],Old=[]}]} @Chg{Version=[2],New=[defined to be aliased. Finally,],Old=[and]} a formal parameter or generic formal object of a tagged type @Chg{Version=[2],New=[is],Old=[are]} defined to be aliased. @Redundant[Aliased views are the ones that can be designated by an access value.] @Chg{Version=[2],New=[],Old=[@Defn2{Term=[constrained], Sec=(object)} @Defn2{Term=[unconstrained], Sec=(object)} @Defn{constrained by its initial value} If the view defined by an @nt{object_@!declaration} is aliased, and the type of the object has discriminants, then the object is constrained; if its nominal subtype is unconstrained, then the object is constrained by its initial value. @Redundant[Similarly, if the object created by an @nt<allocator> has discriminants, the object is constrained, either by the designated subtype, or by its initial value.]]} @ToGlossary{Term=<Aliased>, Text=<An aliased view of an object is one that can be designated by an access value. Objects allocated by allocators are aliased. Objects can also be explicitly declared as aliased with the reserved word @key(aliased). The Access attribute can be used to create an access value designating an aliased object.>} @begin(Ramification) The current instance of a nonlimited type is not aliased. The object created by an allocator is aliased, but not its subcomponents, except of course for those that themselves have @key(aliased) in their @nt<component_definition>. The renaming of an aliased object is aliased. Slices are never aliased. See @RefSecNum{Slices} for more discussion. @end(Ramification) @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00225-01]} The current instance of a limited type is defined to be aliased so that an access discriminant of a component can be initialized with T'Access inside the definition of T.@Chg{Version=[2],New=[ Note that we don't want this to apply to a type that could become nonlimited later within its immediate scope, so we require the full definition to be limited.],Old=[]} A formal parameter of a tagged type is defined to be aliased so that a (tagged) parameter X may be passed to an access parameter P by using P => X'Access. Access parameters are most important for tagged types because of dispatching-on-access-parameters (see @RefSecNum(Dispatching Operations of Tagged Types)). By restricting this to formal parameters, we minimize problems associated with allowing components that are not declared aliased to be pointed-to from within the same record. @Leading@;A view conversion of an aliased view is aliased so that the type of an access parameter can be changed without first converting to a named access type. For example: @begin{Example} @key(type) T1 @key(is tagged) ...; @key(procedure) P(X : @key(access) T1); @key(type) T2 @key(is new) T1 @key(with) ...; @key(procedure) P(X : @key(access) T2) @key(is) @key(begin) P(T1(X.@key(all))'Access); --@RI[ hand off to T1's P] . . . --@RI[ now do extra T2-specific processing] @key(end) P; @end{Example} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[The rule about objects with discriminants is necessary because values of a constrained access subtype can designate an object whose nominal subtype is unconstrained; without this rule, a check on every use of such values would be required to ensure that the discriminants of the object had not changed. With this rule (among others), we ensure that if there might exist aliased views of a discriminated object, then the object is necessarily constrained. Note that this rule is necessary only for untagged types, since a discriminant of a tagged type can't have a default, so all tagged discriminated objects are always constrained anyway.]} @ChgNote{This rule was a disaster, so it thankfully has been repealed. We instead make general access constrained subtypes illegal if the type allows unconstrained instances, see Discriminant Constraints.} @ChgRef{Version=[2],Kind=[Revised]}@ChgNote{Eilers reported double word} We considered making more kinds of objects aliased by default. In particular, any object of a by-reference type will pretty much have to be allocated at an addressable location, so it can be passed by reference without using bit-field pointers. Therefore, one might wish to allow the Access and @Chg{Version=[2],New=[],Old=[and ]}Unchecked_Access attributes for such objects. However, private parts are transparent to the definition of @lquotes@;by-reference type@rquotes@;, so if we made all objects of a by-reference type aliased, we would be violating the privacy of private parts. Instead, we would have to define a concept of @lquotes@;visibly by-reference@rquotes@; and base the rule on that. This seemed to complicate the rules more than it was worth, especially since there is no way to declare an untagged limited private type to be by-reference, since the full type might by nonlimited. @end(Reason) @begin{Discussion} Note that we do not use the term @lquotes@;aliased@rquotes@; to refer to formal parameters that are referenced through multiple access paths (see @RefSecNum{Formal Parameter Modes}). @end{Discussion} An @nt{access_to_object_definition} defines an access-to-object type and its first subtype; @Defn2{Term=[designated subtype], Sec=(of a named access type)} @Defn2{Term=[designated type], Sec=(of a named access type)} the @nt<subtype_@!indication> defines the @i(designated subtype) of the access type. If a @nt<general_@!access_@!modifier> appears, then the access type is a general access type. @Defn{access-to-constant type} If the modifier is the reserved word @key(constant), then the type is an @i(access-to-constant type)@Redundant[; a designated object cannot be updated through a value of such a type]. @Defn{access-to-variable type} If the modifier is the reserved word @key(all), then the type is an @i(access-to-variable type)@Redundant[; a designated object can be both read and updated through a value of such a type]. If no @nt<general_@!access_@!modifier> appears in the @nt<access_to_@!object_@!definition>, the access type is a pool-specific access-to-variable type. @begin{Honest} The type of the designated subtype is called the @i{designated type}. @end{Honest} @begin(Reason) The modifier @key(all) was picked to suggest that values of a general access type could point into @lquotes@;all@rquotes@; storage pools, as well as to objects declared aliased, and that @lquotes@;all@rquotes@; access (both read and update) to the designated object was provided. We couldn't think of any use for pool-specific access-to-constant types, so any access type defined with the modifier @key(constant) is considered a general access type, and can point into any storage pool or at other (appropriate) aliased objects. @end(Reason) @begin(ImplNote) The predefined generic Unchecked_Deallocation can be instantiated for any named access-to-variable type. There is no (language-defined) support for deallocating objects designated by a value of an access-to-constant type. Because of this, an allocator for an access-to-constant type can allocate out of a storage pool with no support for deallocation. Frequently, the allocation can be done at link-time, if the size and initial value are known then. @end(ImplNote) @begin(Discussion) For the purpose of generic formal type matching, the relevant subclasses of access types are access-to-subprogram types, access-to-constant types, and (named) access-to-variable types, with its subclass (named) general access-to-variable types. Pool-specific access-to-variable types are not a separately matchable subclass of types, since they don't have any @lquotes@;extra@rquotes@; operations relative to all (named) access-to-variable types. @end(Discussion) @Defn{access-to-subprogram type} An @nt{access_to_subprogram_definition} defines an access-to-subprogram type and its first subtype; @Defn2{Term=[designated profile], Sec=(of an access-to-subprogram type)} the @nt<parameter_profile> or @nt<parameter_and_result_profile> defines the @i(designated profile) of the access type. @Defn2{Term=[calling convention], Sec=(associated with a designated profile)} There is a @i(calling convention) associated with the designated profile@Redundant[; only subprograms with this calling convention can be designated by values of the access type.] By default, the calling convention is @lquotes@i(protected)@rquotes@; if the reserved word @key(protected) appears, and @lquotes@;Ada@rquotes@; otherwise. @Redundant[See @RefSecNum{Interface to Other Languages} for how to override this default.] @begin(Ramification) The calling convention @i(protected) is in italics to emphasize that it cannot be specified explicitly by the user. This is a consequence of it being a reserved word. @end(Ramification) @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} For @Chg{Version=[2],New=[a named],Old=[an]} access-to-subprogram type, the representation of an access value might include implementation-defined information needed to support up-level references @em for example, a static link. The accessibility rules (see @RefSecNum(Operations of Access Types)) ensure that in a "global-display-based" implementation model (as opposed to a static-link-based model), @Chg{Version=[2],New=[a named],Old=[an]} access-to-(unprotected)-subprogram value need consist only of the address of the subprogram. The global display is guaranteed to be properly set up any time the designated subprogram is called. Even in a static-link-based model, the only time a static link is definitely required is for an access-to-subprogram type declared in a scope nested at least two levels deep within subprogram or task bodies, since values of such a type might designate subprograms nested a smaller number of levels. For the normal case of @Chg{Version=[2],New=[a named],Old=[an]} access-to-subprogram type declared at the outermost (library) level, a code address by itself should be sufficient to represent the access value in many implementations. For access-to-protected-subprogram, the access values will necessarily include both an address (or other identification) of the code of the subprogram, as well as the address of the associated protected object. This could be thought of as a static link, but it will be needed even for global-display-based implementation models. It corresponds to the value of the @lquotes@;implicit parameter@rquotes@; that is passed into every call of a protected operation, to identify the current instance of the protected type on which they are to operate. Any Elaboration_Check is performed when a call is made through an access value, rather than when the access value is first "created" via a 'Access. For implementation models that normally put that check at the call-site, an access value will have to point to a separate entry point that does the check. Alternatively, the access value could point to a "subprogram descriptor" that consisted of two words (or perhaps more), the first being the address of the code, the second being the elaboration bit. Or perhaps more efficiently, just the address of the code, but using the trick that the descriptor is initialized to point to a Raise-Program-Error routine initially, and then set to point to the "real" code when the body is elaborated. For implementations that share code between generic instantiations, the extra level of indirection suggested above to support Elaboration_Checks could also be used to provide a pointer to the per-instance data area normally required when calling shared code. The trick would be to put a pointer to the per-instance data area into the subprogram descriptor, and then make sure that the address of the subprogram descriptor is loaded into a "known" register whenever an indirect call is performed. Once inside the shared code, the address of the per-instance data area can be retrieved out of the subprogram descriptor, by indexing off the "known" register. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00344-01]} @ChgNote{This is not remotely true with nested extensions and with interfaces. I don't much feel like trying to explain this properly.} @ChgDeleted{Version=[2],Text=[Essentially the same implementation issues arise for calls on dispatching operations of tagged types, except that the static link is always known "statically."]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} Note that access parameters of an anonymous access-to-subprogram type are @Chg{Version=[2],New=[],Old=[not ]}permitted. @Chg{Version=[2],New=[Such],Old=[If there were such]} parameters@Chg{Version=[2], New=[ represent],Old=[,]} full @lquotes@;downward@rquotes@; closures@Chg{Version=[2],New=[],Old=[would be required]}, meaning that in an implementation that uses a per-task (global) display, the display @Chg{Version=[2],New=[will],Old=[would]} have to be passed as a hidden parameter, and reconstructed at the point of call.@Chg{Version=[2],New=[], Old=[ This was felt to be an undue implementation burden, given that an equivalent (actually, more general) capability is available via formal subprogram parameters to a generic.]} @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn{anonymous access type} @Defn2{Term=[designated subtype], Sec=(of an anonymous access type)} @Defn2{Term=[designated type], Sec=(of an anonymous access type)} An @nt{access_definition} defines an anonymous general @Chg{Version=[2],New=[access type or an anonymous access-to-subprogram type. For a general access type,], Old=[access-to-variable type;]} the @nt<subtype_mark> denotes its @i(designated subtype)@Chg{Version=[2],New=[; if the @nt{general_@!access_@!modifier} @key{constant} appears, the type is an access-to-constant type; otherwise@Chg{Version=[3],New=[,],Old=[]} it is an access-to-variable type. For an access-to-subprogram type, the @nt{parameter_@!profile} or @nt{parameter_@!and_@!result_@!profile} denotes its @i{designated profile}.@Defn2{Term=[designated profile], Sec=(of an anonymous access type)}], Old=[. @Redundant[An @nt<access_definition> is used in the specification of an access discriminant (see @RefSecNum(Discriminants)) or an access parameter (see @RefSecNum(Subprogram Declarations)).]]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @Defn2{Term=[null value], Sec=(of an access type)} For each @Chg{Version=[2],New=[],Old=[(named) ]}access type, there is @Chg{Version=[2],New=[],Old=[a literal @key(null) which has ]}a null access value designating no entity at all@Chg{Version=[2],New=[, which can be obtained by (implicitly) converting the literal @key{null} to the access type],Old=[]}. @Redundant[The null value of @Chg{Version=[2],New=[an],Old=[a named]} access type is the default initial value of the type.] @Chg{Version=[2],New=[Nonnull],Old=[Other]} values of an access@Chg{Version=[2],New=[-to-object],Old=[]} type are obtained by evaluating @Chg{Version=[2],New=[],Old=[an @nt<attribute_reference> for the Access or Unchecked_Access attribute of an aliased view of an object or nonintrinsic subprogram, or, in the case of a named access-to-object type,]} an @nt<allocator>@Redundant[, which returns an access value designating a newly created object (see @RefSecNum(Operations of Access Types))]@Chg{Version=[2],New=[, or in the case of a general access-to-object type, evaluating an @nt{attribute_reference} for the Access or Unchecked_Access attribute of an aliased view of an object. Nonnull values of an access-to-subprogram type are obtained by evaluating an @nt{attribute_reference} for the Access attribute of a nonintrinsic subprogram],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[A value of an anonymous access type (that is, the value of an access parameter or access discriminant) cannot be null.]} @end{ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[Access parameters allow dispatching on the tag of the object designated by the actual parameter (which gets converted to the anonymous access type as part of the call). In order for dispatching to work properly, there had better be such an object. Hence, the type conversion will raise Constraint_Error if the value of the actual parameter is null.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[excludes null],Sec=[subtype]} A @nt{null_exclusion} in a construct specifies that the null value does not belong to the access subtype defined by the construct, that is, the access subtype @i{excludes null}. In addition, the anonymous access subtype defined by the @nt{access_definition} for a controlling access parameter (see @RefSecNum{Dispatching Operations of Tagged Types}) excludes null. Finally, for a @nt{subtype_indication} without a @nt{null_exclusion}, the subtype denoted by the @nt{subtype_indication} excludes null if and only if the subtype denoted by the @nt{subtype_mark} in the @nt{subtype_indication} excludes null.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[An @nt{access_definition} used in a controlling parameter excludes null because it is necessary to read the tag to dispatch, and null has no tag. We would have preferred to require @key{not null} to be specified for such parameters, but that would have been too incompatible with Ada 95 code to require.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Note that we considered imposing a similar implicit null exclusion for controlling access results, but chose not to do that, because there is no Ada 95 compatibility issue, and there is no automatic null check inherent in the use of a controlling access result. If a null check is necessary, it is because there is a dereference of the result, or because the value is passed to a parameter whose subtype excludes null. If there is no dereference of the result, a null return value is perfectly acceptable, and can be a useful indication of a particular status of the call.]} @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0013],ARef=[AI95-00012-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @PDefn2{Term=[constrained],Sec=(subtype)} @PDefn2{Term=[unconstrained],Sec=(subtype)} @Redundant[All subtypes of an access-to-subprogram type are constrained.] The first subtype of a type defined by an @Chg{New=[@nt<access_definition>],Old=[@nt<access_type_definition>]} or an @nt<access_to_object_definition> is unconstrained if the designated subtype is an unconstrained array or discriminated @Chg{New=[subtype],Old=[type]}; otherwise@Chg{Version=[3],New=[,],Old=[]} it is constrained. @begin(TheProof) The @LegalityTitle on @nt<range_constraint>s (see @RefSecNum(Scalar Types)) do not permit the @nt<subtype_mark> of the @nt<subtype_indication> to denote an access-to-scalar type, only a scalar type. The @LegalityTitle on @nt<index_constraint>s (see @RefSecNum(Index Constraints and Discrete Ranges)) and @nt<discriminant_constraint>s (see @RefSecNum(Discriminant Constraints)) both permit access-to-composite types in a @nt<subtype_indication> with such _@nt<constraint>s. Note that an access-to-access-to-composite is never permitted in a @nt<subtype_indication> with a @nt<constraint>. @end(TheProof) @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} Only @nt<composite_constraint>s are permitted for an access type, and only on access-to-composite types. A constraint on an access-to-scalar or access-to-access type might be violated due to assignments via other access paths that were not so constrained. By contrast, if the designated subtype is an array or discriminated type@Chg{Version=[2],New=[ without defaults],Old=[]}, the constraint could not be violated by unconstrained assignments, since array objects are always constrained, and @Chg{Version=[2],New=[],Old=[aliased]} discriminated objects are also constrained @Chg{Version=[2],New=[when the type does not have defaults for its discriminants. Constraints are not allowed on general access-to-unconstrained discriminated types if the type has defaults for its discriminants; constraints on pool-specific access types are usually allowed because allocated objects are usually constrained by their initial value.], Old=[(by fiat, see @StaticSemTitle).]} @end(Reason) @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If a @nt{subtype_@!indication}, @nt{discriminant_@!specification}, @nt{parameter_@!specification}, @nt{parameter_@!and_@!result_@!profile}, @nt{object_@!renaming_@!declaration}, or @nt{formal_@!object_@!declaration} has a @nt{null_@!exclusion}, the @nt{subtype_@!mark} in that construct shall denote an access subtype that does not exclude null.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[This means @lquotes@;directly allowed in@rquotes; we are not talking about a @nt{null_exclusion} that occurs in an @nt{access_definition} in one of these constructs (for an @nt{access_definition}, the @nt{subtype_mark} in such an @nt{access_definition} is not restricted).]} @end(Honest) @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[This is similar to doubly constraining a composite subtype, which we also don't allow.]} @end(Reason) @end{Legality} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @PDefn2{Term=[compatibility], Sec=(composite_constraint with an access subtype)} A @nt<composite_constraint> is @i(compatible) with an unconstrained access subtype if it is compatible with the designated subtype.@Chg{Version=[2],New=[ A @nt{null_exclusion} is compatible with any access subtype that does not exclude null.],Old=[]} @PDefn2{Term=[satisfies], Sec=(for an access value)} An access value @i(satisfies) a @nt<composite_constraint> of an access subtype if it equals the null value of its type or if it designates an object whose value satisfies the constraint.@Chg{Version=[2],New=[ An access value satisfies an exclusion of the null value if it does not equal the null value of its type.],Old=[]} @PDefn2{Term=[elaboration], Sec=(access_type_definition)} The elaboration of an @nt{access_type_definition} creates the access type and its first subtype. For an access-to-object type, this elaboration includes the elaboration of the @nt{subtype_indication}, which creates the designated subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00254-01]} @PDefn2{Term=[elaboration], Sec=(access_definition)} The elaboration of an @nt{access_definition} creates an anonymous@Chg{Version=[2],New=[],Old=[ general]} access@Chg{Version=[2], New=[],Old=[-to-variable]} type@Chg{Version=[2],New=[], Old=[ @Redundant[(this happens as part of the initialization of an access parameter or access discriminant)]]}. @end{RunTime} @begin{Notes} Access values are called @lquotes@;pointers@rquotes@; or @lquotes@;references@rquotes@; in some other languages. Each access-to-object type has an associated storage pool; several access types can share the same pool. An object can be created in the storage pool of an access type by an @nt{allocator} (see @RefSecNum{Allocators}) for the access type. A storage pool (roughly) corresponds to what some other languages call a @lquotes@;heap.@rquotes@; See @RefSecNum{Storage Management} for a discussion of pools. Only @nt<index_constraint>s and @nt<discriminant_constraint>s can be applied to access types (see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Discriminant Constraints}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of access-to-object types:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[type] Peripheral_Ref @key<is @Chg{Version=[2],New=[not null ],Old=[]}access> Peripheral; --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] @key[type] Binop_Ptr @key[is access all] Binary_Operation'Class; --@RI[ general access-to-class-wide, see @RefSecNum{Type Extensions}] @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of an access subtype:} @end{WideAbove} @begin{Example} @key[subtype] Drum_Ref @key[is] Peripheral_Ref(Drum); --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of an access-to-subprogram type:} @end{WideAbove} @begin{Example} @key[type] Message_Procedure @key[is] @key[access] @key[procedure] (M : @key[in] String := "Error!"); @key[procedure] Default_Message_Procedure(M : @key[in] String); Give_Message : Message_Procedure := Default_Message_Procedure'Access; ... @key[procedure] Other_Procedure(M : @key[in] String); ... Give_Message := Other_Procedure'Access; ... Give_Message("File not found."); --@RI{ call with parameter (.@key[all] is optional)} Give_Message.@key[all]; --@RI{ call with no parameters} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for @nt{access_type_definition} is changed to support general access types (including access-to-constants) and access-to-subprograms. The syntax rules for @nt{general_access_modifier} and @nt{access_definition} are new. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1]} We use the term "storage pool" to talk about the data area from which allocation takes place. The term "collection" is @Chg{Version=[3],New=[only used for finalization],Old=[no longer used]}. ("Collection" and "storage pool" are not the same thing because multiple unrelated access types can share the same storage pool; see @RefSecNum(Storage Management) for more discussion.) @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Access discriminants and noncontrolling access parameters no longer exclude null. A program which passed @key{null} to such an access discriminant or access parameter and expected it to raise Constraint_Error may fail @ChgNote{but not if the parameter is dereferenced in the subprogram or record }when compiled with Ada 2005. One hopes that there no such programs outside of the ACATS. (Of course, a program which actually wants to pass @key{null} will work, which is far more likely.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[Most unconstrained aliased objects with defaulted discriminants are no longer constrained by their initial values. This means that a program that raised Constraint_Error from an attempt to change the discriminants will no longer do so. The change only affects programs that depended on the raising of Constraint_Error in this case, so the inconsistency is unlikely to occur outside of the ACATS. This change may however cause compilers to implement these objects differently, possibly taking additional memory or time. This is unlikely to be worse than the differences caused by any major compiler upgrade.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00225-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] The rule defining when a current instance of a limited type is considered to be aliased has been tightened to apply only to types that cannot become nonlimited. A program that attempts to take 'Access of the current instance of a limited type that can become nonlimited will be illegal in Ada 2005. While original Ada 95 allowed the current instance of any limited type to be treated as aliased, this was inconsistently implemented in compilers, and was likely to not work as expected for types that are ultimately nonlimited.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @Chg{Version=[2],New=[@Defn{extensions to Ada 95}The @nt{null_exclusion} is new. It can be used in both anonymous and named access type definitions. It is most useful to declare that parameters cannot be @key{null}, thus eliminating the need for checks on use.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00404-01]} @Chg{Version=[2],New=[The kinds of anonymous access types allowed were increased by adding anonymous access-to-constant and anonymous access-to-subprogram types. Anonymous access-to-subprogram types used as parameters allow passing of subprograms at any level.],Old=[]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0012],ARef=[AI95-00062-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added accidentally-omitted wording that says that a derived access type shares its storage pool with its parent type. This was clearly intended, both because of a note in @RefSecNum{Derived Types and Classes}, and because anything else would have been incompatible with Ada 83.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0013],ARef=[AI95-00012-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed typographical errors in the description of when access types are constrained.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[The wording was fixed to allow @nt{allocator}s and the literal @key{null} for anonymous access types. The former was clearly intended by Ada 95; see the @ImplAdviceTitle in @RefSecNum{Storage Management}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[The rules about aliased objects being constrained by their initial values now apply only to allocated objects, and thus have been moved to @RefSec{Allocators}.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0053-1],ARef=[AI05-0277-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The rule about a current instance being aliased now is worded in terms of immutably limited types. Wording was also added to make extended return object declarations that have the keyword @key[aliased] be considered aliased. This latter was a significant oversight in Ada 2005 @em technically, the keyword @key[aliased] had no effect. But of course implementations followed the intent, not the letter of the Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}) are defined to be aliased.]} @end{DiffWord2005} @LabeledSubClause{Incomplete Type Declarations} @begin{Intro} There are no particular limitations on the designated type of an access type. In particular, the type of a component of the designated type can be another access type, or even the same access type. This permits mutually dependent and recursive access types. An @nt<incomplete_type_declaration> can be used to introduce a type to be used as a designated type, while deferring its full definition to a subsequent @nt<full_type_declaration>. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Syn{lhs=<incomplete_type_declaration>, rhs="@key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}]@Chg{Version=[2],New=< [@key{is tagged}]>,Old=<>};"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incomplete type}@Defn{incomplete view} An @nt{incomplete_type_declaration} declares an @i{incomplete view} of a type and its first subtype; the first subtype is unconstrained if a @nt<discriminant_part> appears. If the @nt{incomplete_@!type_@!declaration} includes the reserved word @key{tagged}, it declares a @i{tagged incomplete view}.@Defn2{Term=[incomplete view],Sec=[tagged]}@Defn{tagged incomplete view} @Redundant[An incomplete view of a type is a limited view of the type (see @RefSecNum{Limited Types}).]]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Given an access type @i{A} whose designated type @i{T} is an incomplete view, a dereference of a value of type @i{A} also has this incomplete view except when:]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0208-1]} @ChgAdded{Version=[3],Text=[Whether the designated type is an incomplete view (and thus whether this set of rules applies) is determined by the view of the type at the declaration of the access type; it does not change during the life of the type.]} @end{Discussion} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[it occurs within the immediate scope of the completion of @i{T}, or],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0208-1]} @ChgAdded{Version=[2],Text=[it occurs within the scope of a @nt{nonlimited_with_clause} that mentions a library package in whose visible part the completion of @i{T} is declared@Chg{Version=[3],New=[, or],Old=[.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0208-1]} @ChgAdded{Version=[3],Text=[it occurs within the scope of the completion of @i{T} and @i{T} is an incomplete view declared by an @nt{incomplete_type_declaration}.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0162-1]} @ChgAdded{Version=[2],Text=[In these cases, the dereference has the @Chg{Version=[3],New=[],Old=[full ]}view of @i{T}@Chg{Version=[3],New=[ visible at the point of the dereference],Old=[]}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[We need the @lquotes@;in whose visible part@rquotes@; rule so that the second rule doesn't trigger in the body of a package with a @key{with} of a child unit:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{package} P @Key{is} @Key{private} @Key{type} T; @Key{type} PtrT @Key{is access} T; @Key{end} P;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{private package} P.C @Key{is} Ptr : PtrT; @Key{end} P.C;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @Chg{Version=[2],New=[@Key{with} P.C; @Key{package body} P @Key{is} -- @RI{Ptr.all'Size is not legal here, but @Chg{Version=[3],New=[we are within],Old=[it is in]} the scope} -- @RI{of a @nt{nonlimited_with_clause} @RI{for P.}} @Key{type} T @Key{is} ... -- @RI{Ptr.all'Size is legal here.} @Key{end} P;],Old=[]} @end{Example} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00412-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0162-1],ARef=[AI05-0208-1]} @ChgAdded{Version=[2],Text=[Similarly, if a @nt{subtype_mark} denotes a @nt{subtype_declaration} defining a subtype of an incomplete view @i<T>, the @nt{subtype_mark} denotes an incomplete view except under the same @Chg{Version=[3],New=[three],Old=[two]} circumstances given above, in which case it denotes the @Chg{Version=[3],New=[],Old=[full ]}view of @i<T>@Chg{Version=[3],New=[ visible at the point of the @nt{subtype_mark}],Old=[]}.]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0162-1]} @PDefn2{Term=[requires a completion], Sec=(@nt<incomplete_type_declaration>)} An @nt{incomplete_@!type_@!declaration} requires a completion, which shall be a @Chg{Version=[3],New=[@nt{type_@!declaration} other than an @nt{incomplete_@!type_@!declaration}],Old=[@nt{full_@!type_@!declaration}]}. @Redundant[If the @nt{incomplete_@!type_@!declaration} occurs immediately within either the visible part of a @nt{package_@!specification} or a @nt<declarative_@!part>, then the @Chg{Version=[3],New=[@nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} shall occur later and immediately within this visible part or @nt<declarative_@!part>. If the @nt{incomplete_@!type_@!declaration} occurs immediately within the private part of a given @nt<package_@!specification>, then the @Chg{Version=[3],New=[@nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} shall occur later and immediately within either the private part itself, or the @nt{declarative_@!part} of the corresponding @nt{package_@!body}.] @begin{TheProof} This is implied by the next AARM-only rule, plus the rules in @RefSec{Completions of Declarations} which require a completion to appear later and immediately within the same declarative region. @end{TheProof} @begin{Honest} If the @nt{incomplete_type_declaration} occurs immediately within the visible part of a @nt{package_specification}, then the @Chg{Version=[3],New=[completing @nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} shall occur immediately within this visible part. @end{Honest} @begin(Honest) If the implementation supports it, an @nt{incomplete_type_declaration} can be @Chg{Version=[3],New=[imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no explicit completion is allowed],Old=[completed by a @nt{pragma} Import]}. @end(Honest) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0162-1]} @Chg{Version=[2],New=[If an @nt{incomplete_@!type_@!declaration} includes the reserved word @key{tagged}, then a @Chg{Version=[3],New=[@nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} that completes it shall declare a tagged type. ],Old=[]}If an @nt{incomplete_@!type_@!declaration} has a @nt{known_@!discriminant_@!part}, then a @Chg{Version=[3],New=[@nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} that completes it shall have a fully conforming (explicit) @nt{known_@!discriminant_@!part} (see @RefSecNum(Conformance Rules)). @Defn2{Term=[full conformance],Sec=(required)} @Redundant[If an @nt{incomplete_@!type_@!declaration} has no @nt<discriminant_part> (or an @nt<unknown_@!discriminant_@!part>), then a corresponding @Chg{Version=[3],New=[@nt{type_@!declaration}], Old=[@nt{full_@!type_@!declaration}]} is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.] @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[A],Old=[The only allowed uses of a]} @nt{name} that denotes an @Chg{Version=[2],New=[incomplete view of a type may be used], Old=[@nt{incomplete_type_declaration} are]} as follows: @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[No need to say "prior to the end of the @nt{full_type_declaration}" since the name would not denote the @nt{incomplete_type_declaration} after the end of the @nt{full_type_declaration}. Also, with child library units, it would not be well defined whether they come before or after the @nt<full_type_declaration> for deferred incomplete types.]} @end(Discussion) @begin(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0098-1]} as the @nt{subtype_mark} in the @nt{subtype_indication} of an @nt{access_to_@!object_@!definition}; @Redundant[the only form of @nt{constraint} allowed in this @nt{subtype_indication} is a @nt{discriminant_constraint}@Chg{Version=[3],New=[ @Redundant[(a @nt{null_exclusion} is not allowed)]],Old=[]};] @begin(ImplNote) We now allow @nt<discriminant_constraint>s even if the full type is deferred to the package body. However, there is no particular implementation burden because we have dropped the concept of the dependent compatibility check. In other words, we have effectively repealed AI83-00007. @end(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01],ARef=[AI95-00412-01]}@ChgNote{The old rule is moved} as the @nt{subtype_mark} @Chg{Version=[2],New=[in the @nt{subtype_indication} of a @nt{subtype_declaration}; the @nt{subtype_@!indication} shall not have a @nt{null_@!exclusion} or a @nt{constraint};],Old=[defining the subtype of a parameter or result of an @nt{access_to_@!subprogram_@!definition};]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00326-01]}@ChgNote{Really moved} @ChgDeleted{Version=[2],Text=[This allows, for example, a record to have a component designating a subprogram that takes that same record type as a parameter.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0151-1]} as the @nt<subtype_mark> in an @nt<access_definition>@Chg{Version=[2],New=[@Chg{Version=[3],New=[ for an access-to-object type;],Old=[.]}],Old=[;]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This does not mean any random @nt{subtype_mark} in a construct that makes up an @nt<access_definition>, such as a @nt<formal_part>, just the one given directly in the syntax of @nt<access_definition>.]} @end{Honest} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0151-1]} @ChgAdded{Version=[3],Text=[as the @nt{subtype_mark} defining the subtype of a parameter or result in a profile occurring within a @nt{basic_declaration};]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[But not in the profile for a body or entry.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[as a generic actual parameter whose corresponding generic formal parameter is a formal incomplete type (see @RefSecNum{Formal Private and Derived Types}).]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[If such a @nt{name} denotes a tagged incomplete view, it may also be used:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0151-1]} @ChgAdded{Version=[2],Text=[as the @nt{subtype_mark} defining the subtype of a parameter in @Chg{Version=[3],New=[the profile for a @nt{subprogram_body}, @nt{entry_body}, or @nt{accept_statement}],Old=[a @nt{formal_part}]};]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} as the @nt{prefix} of an @nt{attribute_reference} whose @nt{attribute_@!designator} is Class; such an @nt{attribute_@!reference} is @Chg{Version=[2],New=[],Old=[similarly ]}restricted to the uses allowed here; @Chg{Version=[2],New=[it denotes a tagged incomplete view], Old=[when used in this way, the corresponding @nt{full_type_@!declaration} shall declare a tagged type, and the @nt<attribute_@!reference> shall occur in the same library unit as the @nt<incomplete_@!type_@!declaration>]}. @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[This is to prevent children from imposing requirements on their ancestor library units for deferred incomplete types.]} @end{reason} @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0151-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[],Old=[If such a @nt{name} occurs within the declaration list containing the completion of the incomplete view, it may also be used:]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]}@ChgNote{Really moved} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0098-1],ARef=[AI05-0151-1]}@ChgNote{Now part of the next paragraph} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[as the @nt{subtype_mark} defining the subtype of a parameter or result of an @nt{access_to_@!subprogram_@!definition}.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This allows, for example, a record to have a component designating a subprogram that takes that same record type as a parameter.]}]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[If any of the above uses occurs as part of the declaration of a primitive subprogram of the incomplete view, and the declaration occurs immediately within the private part of a package, then the completion of the incomplete view shall also occur immediately within the private part; it shall not be deferred to the package body.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This fixes a hole in Ada 95 where a dispatching operation with an access parameter could be declared in a private part and a dispatching call on it could occur in a child even though there is no visibility on the full type, requiring access to the controlling tag without access to the representation of the type.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[No other uses of a @nt{name} that denotes an incomplete view of a type are allowed.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0151-1]} @Chg{Version=[2],New=[A @nt{prefix} that denotes an object], Old=[A dereference (whether implicit or explicit @em see @RefSecNum(Names))]} shall not be of an incomplete @Chg{Version=[2],New=[view],Old=[type]}.@Chg{Version=[3],New=[ An actual parameter in a call shall not be of an untagged incomplete view. The result object of a function call shall not be of an incomplete view. A @nt{prefix} shall not denote a subprogram having a formal parameter of an untagged incomplete view, nor a return type that is an incomplete view.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We used to disallow all dereferences of an incomplete type. Now we only disallow such dereferences when used as a @nt{prefix}. Dereferences used in other contexts do not pose a problem since normal type matching will preclude their use except when the full type is @lquotes@;nearby@rquotes@; as context (for example, as the expected type).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This also disallows @nt{prefix}es that are directly of an incomplete view. For instance, a parameter @i{P} can be declared of a tagged incomplete type, but we don't want to allow @i{P}'Size, @i{P}'Alignment, or the like, as representation values aren't known for an incomplete view.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We say @lquotes@;denotes an object@rquotes so that prefixes that directly name an incomplete view are not covered; the previous rules cover such cases, and we certainly don't want to ban Incomp'Class.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0151-1]} @ChgAdded{Version=[3],Text=[As subprogram profiles now may include any kind of incomplete type, we also disallow passing objects of untagged incomplete types in subprogram calls (as the parameter passing method is not known as it is for tagged types) and disallow returning any sort of incomplete objects (since we don't know how big they are).]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00326-01]} @ChgDeleted{Version=[2],Text=[@Defn{incomplete type} An @nt{incomplete_type_declaration} declares an incomplete type and its first subtype; the first subtype is unconstrained if a @nt<known_discriminant_part> appears.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If an @nt<unknown_discriminant_part> or no @nt{discriminant_part} appears, then the constrainedness of the first subtype doesn't matter for any other rules or semantics, so we don't bother defining it. The case with a @nt<known_discriminant_part> is the only case in which a constraint could later be given in a @nt{subtype_indication} naming the incomplete type.]} @end{Reason} @end{StaticSem} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraph 11 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(incomplete_type_declaration)} The elaboration of an @nt{incomplete_type_declaration} has no effect. @begin(Reason) An incomplete type has no real existence, so it doesn't need to be "created" in the usual sense we do for other types. It is roughly equivalent to a "forward;" declaration in Pascal. Private types are different, because they have a different set of characteristics from their full type. @end(Reason) @end{RunTime} @begin{Notes} @PDefn{completion legality} Within a @nt<declarative_part>, an @nt<incomplete_type_declaration> and a corresponding @nt<full_type_declaration> cannot be separated by an intervening body. This is because a type has to be completely defined before it is frozen, and a body freezes all types declared prior to it in the same @nt<declarative_part> (see @RefSecNum{Freezing Rules}). @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0151-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[A @nt{name} that denotes an object of an incomplete view is defined to be of a limited type. Hence, the target of an assignment statement cannot be of an incomplete view.]} @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a recursive type:) @begin(Example) @key(type) Cell; --@RI[ incomplete type declaration] @key(type) Link @key(is) @key(access) Cell; @key(type) Cell @key(is) @key(record) Value : Integer; Succ : Link; Pred : Link; @key(end) @key(record); Head : Link := @key(new) Cell'(0, @key(null), @key(null)); Next : Link := Head.Succ; @end(Example) @i(Examples of mutually dependent access types:) @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Person(<>); --@RI[ incomplete type declaration] @key(type) Car@Chg{Version=[2],New=[ @key{is tagged};],Old=[; ]} --@RI[ incomplete type declaration] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Person_Name @key(is) @key(access) Person; @key(type) Car_Name @key(is) @key(access) @key(all) Car@Chg{Version=[2],New=['Class],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(type) Car @key(is)@Chg{Version=[2],New=[ @key(tagged)],Old=[]} @key(record) Number : Integer; Owner : Person_Name; @key(end) @key(record); @key(type) Person(Sex : Gender) @key(is) @key(record) Name : String(1 .. 20); Birth : Date; Age : Integer @key(range) 0 .. 130; Vehicle : Car_Name; @key(case) Sex @key(is) @key(when) M => Wife : Person_Name(Sex => F); @key(when) F => Husband : Person_Name(Sex => M); @key(end) @key(case); @key(end) @key(record); My_Car, Your_Car, Next_Car : Car_Name := @key[new] Car; --@RI[ see @RefSecNum{Allocators}] George : Person_Name := @key[new] Person(M); ... George.Vehicle := Your_Car; @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{full_type_declaration} that completes an @nt{incomplete_type_declaration} may have a @nt{known_discriminant_part} even if the @nt{incomplete_type_declaration} does not. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00013} A @nt<discriminant_constraint> may be applied to an incomplete type, even if @Chg{New=[],Old=[it ]}its completion is deferred to the package body, because there is no @lquotes@;dependent compatibility check@rquotes@; required any more. Of course, the constraint can be specified only if a @nt<known_discriminant_part> was given in the @nt<incomplete_type_declaration>. As mentioned in the previous paragraph, that is no longer required even when the full type has discriminants. @end{Extend83} @begin{DiffWord83} @Leading@;Dereferences producing incomplete types were not explicitly disallowed in RM83, though AI83-00039 indicated that it was not strictly necessary since troublesome cases would result in Constraint_Error at run time, since the access value would necessarily be null. However, this introduces an undesirable implementation burden, as illustrated by Example 4 of AI83-00039: @begin{example} @key[package] Pack @key[is] @key[type] Pri @key[is] @key[private]; @key[private] @key[type] Sep; @key[type] Pri @key[is] @key[access] Sep; X : Pri; @key[end] Pack; @key[package] @key[body] Pack @key[is] --@RI{ Could be separately compiled!} @key[type] Sep @key[is] ...; X := @key[new] Sep; @key[end] Pack; @key[pragma] Elaborate(Pack); @key[private] @key[package] Pack.Child @key[is] I : Integer := X.@key{all}'Size; --@RI{ Legal, by AI-00039.} @key[end] Pack.Child; @end{example} Generating code for the above example could be a serious implementation burden, since it would require all aliased objects to store size dope, and for that dope to be in the same format for all kinds of types (or some other equivalently inefficient implementation). On the contrary, most implementations allocate dope differently (or not at all) for different designated subtypes. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} It is now illegal to use an incomplete view (type) as the parameter or result of an access-to-subprogram type unless the incomplete view is completed in the same declaration list as the use. This was allowed in Ada 95 for incomplete types where the completion was deferred to the body. By disallowing this rare use of incomplete views, we can allow the use of incomplete views in many more places, which is especially valuable for limited views.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[It is now illegal to use an incomplete view (type) in a primitive subprogram of the type unless the incomplete view is completed in the package specification. This was allowed in Ada 95 for incomplete types where the completion was deferred to the body (the use would have to be in an access parameter). This incompatibility was caused by the fix for the hole noted in @LegalityTitle above.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Tagged incomplete types are new. They are allowed in parameter declarations as well as the usual places, as tagged types are always by-reference types (and thus there can be no code generation issue).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[A @nt{subtype_declaration} can be used to give a new name to an incomplete view of a type. This is valuable to give shorter names to entities imported with a @nt{limited_with_clause}.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[The description of incomplete types as @i{incomplete views} is new. Ada 95 defined these as separate types, but neglected to give any rules for matching them with other types. Luckily, implementers did the right thing anyway. This change also makes it easier to describe the meaning of a limited view.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0098-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Fixed the definition so that an anonymous access-to-subprogram type can use an incomplete view in the same way that a named access-to-subprogram type can.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0151-1]} @ChgAdded{Version=[3],Text=[Incomplete types now can be used in subprogram declarations. The type has to be complete before any calls or the body is declared. This reduces the places where access types are required for types imported from limited views of packages.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0162-1]} @ChgAdded{Version=[3],Text=[Incomplete types now can be completed by private types and private extensions. Since this can already happen for limited views, there is no remaining reason to disallow it for explicitly declared incomplete types.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0208-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Changed the rules of uses of dereferences of incomplete views such that it does not introduce an unintentional incompatibility with Ada 83 and Ada 95.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[Incomplete types now can be used as actuals to formal incomplete types (see @RefSecNum{Formal Private and Derived Types}).]} @end{DiffWord2005} @LabeledSubClause{Operations of Access Types} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[The attribute Access is used to create access values designating aliased objects and nonintrinsic subprograms. The @lquotes@;accessibility@rquotes@; rules prevent dangling references (in the absence of uses of certain unchecked features @em see @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Representation Issues}).] @end{Intro} @begin{MetaRules} It should be possible for an access value to designate an object declared by an object declaration, or a subcomponent thereof. In implementation terms, this means pointing at stack-allocated and statically allocated data structures. However, dangling references should be prevented, primarily via compile-time rules, so long as features like Unchecked_Access and Unchecked_Deallocation are not used. In order to create such access values, we require that the access type be a general access type, that the designated object be aliased, and that the accessibility rules be obeyed. @end{MetaRules} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235-01]} @PDefn2{Term=[expected type], Sec=(access attribute_reference)} For an @nt<attribute_reference> with @nt<attribute_designator> Access (or Unchecked_Access @em see @RefSecNum(Unchecked Access Value Creation)), the expected type shall be a single access type@Chg{Version=[2],New=[ @i<A> such that:],Old=[@Redundant[; the @nt<prefix> of such an @nt<attribute_reference> is never interpreted as an @nt<implicit_dereference>]. @PDefn2{Term=[expected profile], Sec=(Access @nt<attribute_reference> @nt<prefix>)} If the expected type is an access-to-subprogram type, then the expected profile of the @nt<prefix> is the designated profile of the access type.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@i{A} is an access-to-object type with designated type @i{D} and the type of the @nt{prefix} is @i{D}'Class or is covered by @i{D}, or],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@i{A} is an access-to-subprogram type whose designated profile is type conformant with that of the prefix.],Old=[]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00235-01]} @Chg{Version=[2],New=[@Redundant[The @nt{prefix} of such an @nt{attribute_reference} is never interpreted as an @nt{implicit_dereference} or a parameterless @nt{function_call} (see @RefSecNum{Attributes}).] @PDefn2{Term=[expected profile], Sec=(Access @nt<attribute_reference> @nt<prefix>)} @PDefn2{Term=[expected type], Sec=(Access @nt<attribute_reference> @nt<prefix>)} The designated type or profile of the expected type of the @nt{attribute_reference} is the expected type or profile for the @nt{prefix}.],Old=[]} @begin(Discussion) Saying that the expected type shall be a "single access type" is our "new" way of saying that the type has to be determinable from context using only the fact that it is an access type. See @RefSecNum{Literals} and @RefSecNum{The Context of Overload Resolution}. Specifying the expected profile only implies type conformance. The more stringent subtype conformance is required by a Legality Rule. This is the only Resolution Rule that applies to the @nt<name> in a @nt{prefix} of an @nt{attribute_reference}. In all other cases, the @nt{name} has to be resolved without using context. See @RefSecNum{Attributes}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Saying @lquotes@;single access type@rquotes@; is a bit of a fudge. Both the context and the @nt{prefix} may provide both multiple types; @lquotes@;single@rquotes@; only means that a single, specific interpretation must remain after resolution. We say @lquotes@;single@rquotes@; here to trigger the @LegalityTitle of @RefSecNum{The Context of Overload Resolution}. The resolution of an access attribute is similar to that of an @nt{assignment_statement}. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Int_Ptr @key{is access all} Integer; @key{type} Char_Ptr @key{is access all} Character; @key{type} Float_Ptr @key{is access all} Float;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{function} Zap (Val : Int_Ptr) @key{return} Float; -- @RI[(1)] @key{function} Zap (Val : Float_Ptr) @key{return} Float; -- @RI[(2)] @key{function} Zop @key{return} Int_Ptr; -- @RI[(3)] @key{function} Zop @key{return} Char_Ptr; -- @RI[(4)]],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[Result : Float := Zap (Zop.@key{all}'Access); -- @RI[Resolves to Zap (1) and Zop (3).]],Old=[]} @end{Example} @end(Discussion) @end{Resolution} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @Defn{accessibility level} @Defn2{Term=[level],Sec=(accessibility)} @Defn2{Term=[deeper],Sec=(accessibility level)} @Defn2{Term=[depth],Sec=(accessibility level)} @Defn2{Term=[dangling references],Sec=(prevention via accessibility rules)} @Defn{lifetime} @Redundant[The accessibility rules, which prevent dangling references, are written in terms of @i{accessibility levels}, which reflect the run-time nesting of @i{masters}. As explained in @RefSecNum{Completion and Finalization}, a master is the execution of a @Chg{Version=[2],New=[certain construct, such as],Old=[,@nt{task_body}, a @nt{block_statement},]} a @nt{subprogram_body}@Chg{Version=[2],New=[],Old=[, an @nt{entry_body}, or an @nt{accept_statement}]}. An accessibility level is @i{deeper than} another if it is more deeply nested at run time. For example, an object declared local to a called subprogram has a deeper accessibility level than an object declared local to the calling subprogram. The accessibility rules for access types require that the accessibility level of an object designated by an access value be no deeper than that of the access type. This ensures that the object will live at least as long as the access type, which in turn ensures that the access value cannot later designate an object that no longer exists. The Unchecked_Access attribute may be used to circumvent the accessibility rules.] @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[The Unchecked_Access attribute acts as if the object was declared at library-level; this applies even when it is used as the value of anonymous access type. See @RefSecNum{Unchecked Access Value Creation}.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Subclause @RefSecNum{Operations of Access Types}, home of the accessibility rules, is informally known as the @ldquote@;Heart of Darkness@rdquote amongst the maintainers of Ada. Woe unto all who enter here (well, at least unto anyone that needs to understand any of these rules). @Defn{Heart of Darkness}@IndexSeeAlso{Term=[accessibility rules],See=[Heart of Darkness]}]} @end{Discussion} @Defn{statically deeper} @Defn2{Term=[deeper],Sec=(statically)} @Redundant[A given accessibility level is said to be @i{statically deeper} than another if the given level is known at compile time (as defined below) to be deeper than the other for all possible executions. In most cases, accessibility is enforced at compile time by @LegalityTitle. Run-time accessibility checks are also used, since the @LegalityTitle do not cover certain cases involving access parameters and generic packages.] @Leading@keepnext@;Each master, and each entity and view created by it, has an accessibility level: @begin{Itemize} The accessibility level of a given master is deeper than that of each dynamically enclosing master, and deeper than that of each master upon which the task executing the given master directly depends (see @RefSecNum{Task Dependence - Termination of Tasks}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0235-1]} An entity or view @Chg{Version=[2],New=[defined],Old=[created]} by a declaration@Chg{Version=[2],New=[ and created as part of its elaboration],Old=[]} has the same accessibility level as the innermost @Chg{Version=[2],New=[],Old=[enclosing ]}master @Chg{Version=[2],New=[of the declaration ],Old=[]}except in the cases of renaming and derived access types described below. @Chg{Version=[3],New=[Other than for an explicitly aliased parameter, a formal],Old=[A]} parameter of a @Chg{Version=[3],New=[callable entity],Old=[master]} has the same accessibility level as the master@Chg{Version=[3],New=[ representing the invocation of the entity],Old=[]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[This rule defines the @lquotes@;normal@rquotes accessibility of entities. In the absence of special rules below, we intend for this rule to apply.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[This rule defines the accessibility of all named access types, as well as the accessibility level of all anonymous access types other than those for access parameters and access discriminants. Special rules exist for the accessibility level of such anonymous types. Components, stand-alone objects, and function results whose (anonymous) type is defined by an @nt{access_definition} have accessibility levels corresponding to named access types defined at the same point.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Because accessibility level is determined by where the @nt{access_definition} is elaborated, for a type extension, the anonymous access types of components (other than access discriminants) inherited from the parent have the same accessibility as they did in the parent; those in the extension part have the accessibility determined by the scope where the type extension is declared. Similarly, the types of the nondiscriminant access components of a derived untagged type have the same accessibility as they did in the parent.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[We use "invocation of" in the parameter case as a master is formally an execution of something. But we mean this to be interpreted statically (for instance, as the body of the subprogram) for the purposes of computing "statically deeper than" (see below).]} @end{Honest} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[Note that accessibility can differ depending on the view of an object (for both static and dynamic accessibility). For instance, the accessibility level of a formal parameter may be different than the accessibility level of the corresponding actual parameter. This occurs in other cases as well.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[We define the (dynamic) accessibility of formal parameters in order that it does not depend on the parameter passing model (by-reference or by-copy) as that is implementation defined. Otherwise, there would be a portability issue.]} @end{Reason} The accessibility level of a view of an object or subprogram defined by a @nt{renaming_declaration} is the same as that of the renamed view. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} The accessibility level of a view conversion@Chg{Version=[2],New=[, @nt{qualified_expression}, or parenthesized expression,],Old=[]} is the same as that of the operand. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[The accessibility level of a @nt{conditional_expression} is the accessibility level of the evaluated @Syni{dependent_}@nt{expression}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0234-1]} @Chg{Version=[2],New=[The],Old=[For a function whose result type is a return-by-reference type, the accessibility level of the result object is the same as that of the master that elaborated the function body. For any other function, the]} accessibility level of @Chg{Version=[2],New=[an @nt{aggregate} @Chg{Version=[3],New=[],Old=[or the result of a function call @Redundant[(or equivalent use of an operator)] ]}that is used (in its entirety) to directly initialize part of an],Old=[the result]} object is that of the @Chg{Version=[2],New=[object being initialized. In other contexts, the accessibility level of an @nt{aggregate} @Chg{Version=[3],New=[],Old=[or the result of a function call ]}is that of the innermost master that evaluates the @nt{aggregate}@Chg{Version=[3],New=[],Old=[ or function call]}],Old=[execution of the called function]}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The accessibility level of the result of a function call is that of the @i<master of the function call>, which is determined by the point of call as follows:@Defn{master of a call}@Defn2{Term=[call],Sec=[master of]}@Defn2{Term=[function call],Sec=[master of]}]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the result is used (in its entirety) to directly initialize part of an object, the master is that of the object being initialized. In the case where the initialized object is a coextension (see below) that becomes a coextension of another object, the master is that of the eventual object to which the coextension will be transferred.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The first sentence is talking about a static use of the entire return object @em a slice that happens to be the entire return object doesn't count. On the other hand, this is intended to allow parentheses and @nt{qualified_expression}s.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0234-1]} @ChgAdded{Version=[2],Text=[If the function is used as a @nt{prefix}, @Chg{Version=[3],New=[this bullet does not apply],Old=[the second sentence applies]}. Similarly, an @nt{assignment_statement} is not an initialization of an object, so @Chg{Version=[3],New=[this bullet does not apply],Old=[the second sentence applies]}.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the result is of an anonymous access type and is the operand of an explicit conversion, the master is that of the target type of the conversion;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the result is of an anonymous access type and defines an access discriminant, the master is the same as that for an object created by an anonymous @nt{allocator} that defines an access discriminant (even if the access result is of an access-to-subprogram type).]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the call itself defines the result of a function to which one of the above rules applies, these rules are applied recursively;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In other cases, the master of the call is that of the innermost master that evaluates the function call.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The @lquotes@;innermost master which evaluated the function call@rquotes@; does not include the function call itself (which might be a master).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[We really mean the innermost master here, which could be a very short lifetime. Consider a function call used as a parameter of a procedure call. In this case the innermost master which evaluated the function call is the procedure call.]} @end{Ramification} @end{InnerItemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[These rules do not mention whether the result object is built-in-place (see @RefSecNum{Assignment and Finalization}). In particular, in the case where building in place is optional, the choice whether or not to build-in-place has no effect on masters, lifetimes, or accessibility.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[There are several cases where the implementation may have to pass in the accessibility level of the result object on a call, to support later rules where the accessibility level comes from the master of the call:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[when the function result may have a part with access discriminants;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[when the function result type is an anonymous access type;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[when the function result is built-in-place;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[when the function has an explicitly aliased parameter.]} @end{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In particular, this implies passing a level parameter when the result type is class-wide, since descendants may add access discriminants. For most implementations this will mean that functions with controlling results will also need a level parameter.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0284-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[In the case of a call to a function whose result type is an anonymous access type, the accessibility level of the type of the result of the function call is also determined by the point of call as described above.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Just because the paragraph number is changed} @ChgAdded{Version=[2],Text=[Within a return statement, the accessibility level of the return object is that of the execution of the return statement. If the return statement completes normally by returning from the function, then prior to leaving the function, the accessibility level of the return object changes to be a level determined by the point of call, as does the level of any coextensions (see below) of the return object.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We define the accessibility level of the return object during the return statement to be that of the return statement itself so that the object may be designated by objects local to the return statement, but not by objects outside the return statement. In addition, the intent is that the return object gets finalized if the return statement ends without actually returning (for example, due to propagating an exception, or a goto). For a normal return, of course, no finalization is done before returning.]} @end{Reason} The accessibility level of a derived access type is the same as that of its ultimate ancestor. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type defined by an @nt{access_definition} of an @nt{object_renaming_declaration} is the same as that of the renamed view.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgNote{Use ChgAdded below to get conditional Leading} @ChgAdded{Version=[2],Type=[Leading],Text=[]}The accessibility level of the anonymous access type of an access discriminant @Chg{Version=[2],New=[in the @nt{subtype_indication} or @nt{qualified_expression} of an @nt{allocator}, or in the @nt{expression} or @nt{return_@!subtype_@!indication} of a return statement is determined as follows:],Old=[is the same as that of the containing object or associated constrained subtype.]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If the value of the access discriminant is determined by a @nt{discriminant_association} in a @nt{subtype_indication}, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This deals with the following cases, when they occur in the context of an @nt{allocator} or return statement:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{extension_aggregate} where the @nt{ancestor_part} is a @nt{subtype_mark} denoting a constrained subtype;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An uninitialized @nt{allocator} where the @nt{subtype_indication} defines a constrained subtype;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A discriminant of an object with a constrained nominal subtype, including constrained components, the result of calling a function with a constrained result subtype, the dereference of an access-to-constrained subtype, etc.]} @end{InnerItemize} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0281-1]} @ChgAdded{Version=[3],Text=[The @nt{subtype_indication} mentioned in this bullet is not necessarily the one given in the @nt{allocator} or return statement that is determining the accessibility level; the constrained subtype might have been defined in an earlier declaration (as a named subtype).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[If the value for this rule and the next one is derived from an Unchecked_Access attribute, the accessibility is library-level no matter what the accessibility level of the object is (see @RefSecNum{Unchecked Access Value Creation}).]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[If the value of the access discriminant is determined by a @nt{default_expression} in the declaration of the discriminant, the level of the object or subprogram designated by the associated value (or library level if null);]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[This covers the case of an unconstrained subcomponent of a limited type with defaulted access discriminants.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[If the value of the access discriminant is determined by a @Chg{Version=[3],New=[@nt{record_component_association}], Old=[@ntf{component_association}]} in an @nt{aggregate}, the accessibility level of the object or subprogram designated by the associated value (or library level if the value is null);]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this bullet, the @nt{aggregate} has to occur in the context of an @nt{allocator} or return statement, while the @nt{subtype_indication} of the previous bullet can occur anywhere (it doesn't have to be directly given in the @nt{allocator} or return statement).]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Just because the paragraph number is changed} @ChgAdded{Version=[2],Text=[In other cases, where the value of the access discriminant is determined by an object with an unconstrained nominal subtype, the accessibility level of the object.]} @end{InnerItemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[In other words, if you know the value of the discriminant for an @nt{allocator} or return statement from a discriminant constraint or an @nt{aggregate} component association, then that determines the accessibility level; if you don't know it, then it is based on the object itself.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Just because the paragraph number is changed} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access discriminant in any other context is that of the enclosing object.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00254-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0270-1]} The accessibility level of the anonymous access type of an access parameter@Chg{Version=[2],New=[ specifying an access-to-object type],Old=[]} is the same as that of the view designated by the actual@Chg{Version=[3],New=[ (or library-level if the actual is null)],Old=[]}.@Chg{Version=[2],New=[],Old=[ If the actual is an @nt{allocator}, this is the accessibility level of the execution of the called subprogram.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[If the value of the actual is derived from an Unchecked_Access attribute, the accessibility is always library-level (see @RefSecNum{Unchecked Access Value Creation}).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access parameter specifying an access-to-subprogram type is deeper than that of any master; all such anonymous access types have this same level.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn{downward closure} @Defn2{Term=[closure],Sec=(downward)} These represent @lquotes@;downward closures@rquotes@; and thus require passing of static links or global display information (along with generic sharing information if the implementation does sharing) along with the address of the subprogram. We must prevent conversions of these to types with @lquotes@;normal@rquotes@; accessibility, as those typically don't include the extra information needed to make a call.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0148-1],ARef=[AI05-0240-1]} @ChgAdded{Version=[3],Text=[The accessibility level of the type of a stand-alone object of an anonymous access-to-object type is the same as the accessibility level of the type of the access value most recently assigned to the object@Redundant[; accessibility checks ensure that this is never deeper than that of the declaration of the stand-alone object].]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4],ARef=[AI05-0240-1]} @ChgAdded{Version=[3],Text=[The accessibility level of an explicitly aliased (see @RefSecNum{Subprogram Declarations}) formal parameter in a function body is determined by the point of call; it is the same level that the return object ultimately will have.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0051-1],ARef=[AI05-0253-1]} @ChgNote{Use ChgAdded below to get conditional Leading} @ChgAdded{Version=[2],Type=[Leading],Text=[]} The accessibility level of an object created by an @nt{allocator} is the same as that of the access type@Chg{Version=[2],New=[, except for an @nt{allocator} of an anonymous access type @Chg{Version=[3],New=[(an @i<anonymous allocator>) in @Defn{anonymous allocator}certain contexts, as follows: For an anonymous allocator that defines the result of a function with an access result, the accessibility level is determined as though the @nt{allocator} were in place of the call of the function; in the special case of a call that is the operand of a type conversion, the level is that of the target access type of the conversion],Old=[that defines the value of an access parameter or an access discriminant]}. For an @Chg{Version=[3],New=[anonymous allocator],Old=[@nt{allocator}]} defining the value of an access parameter, the accessibility level is that of the innermost master of the call. @Chg{Version=[3],New=[For an anonymous allocator whose type is that of a stand-alone object of an anonymous access-to-object type, the accessibility level is that of the declaration of the stand-alone object. ],Old=[]}For one defining an access discriminant, the accessibility level is determined as follows:],Old=[.]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0024-1]} @ChgAdded{Version=[2],Text=[for an @nt{allocator} used to define the @Chg{Version=[3],New=[discriminant of an object, the level of the object],Old=[constraint in a @nt{subtype_declaration}, the level of the @nt{subtype_declaration}]};]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0024-1]} @ChgAdded{Version=[2],Text=[for an @nt{allocator} used to define the constraint in a @Chg{Version=[3],New=[@nt{subtype_indication} in any other context, the level of the master that elaborates the @nt{subtype_indication}.],Old=[@nt{component_definition}, the level of the enclosing type;]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0024-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[for an @nt{allocator} used to define the discriminant of an object, the level of the object.]}]} @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0024-1],ARef=[AI05-0066-1]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[@Defn2{Term=[coextension],Sec=(of an object)} In @Chg{Version=[3],New=[the first],Old=[this last]} case, the allocated object is said to be a @i{coextension} of the object whose discriminant designates it, as well as of any object of which the discriminated object is itself a coextension or subcomponent.@Chg{Version=[3],New=[ If the allocated object is a coextension of an anonymous object representing the result of an aggregate or function call that is used (in its entirety) to directly initialize a part of an object, after the result is assigned, the coextension becomes a coextension of the object being initialized and is no longer considered a coextension of the anonymous object.],Old=[]} All coextensions of an object @Chg{Version=[3],New=[@Redundant[(which have not thus been transfered by such an initialization)] ],Old=[]}are finalized when the object is finalized (see @RefSecNum{Completion and Finalization}).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The rules of access discriminants are such that when the space for an object with a coextension is reclaimed, the space for the coextensions can be reclaimed. Hence, there is implementation advice (see 13.11) that an object and its coextensions all be allocated from the same storage pool (or stack frame, in the case of a declared object).]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0051-1]} @ChgAdded{Version=[3],Text=[Within a return statement, the accessibility level of the anonymous access type of an access result is that of the master of the call.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0014-1]} The accessibility level of a view of an object or subprogram @Chg{Version=[3],New=[designated by],Old=[denoted by a dereference of]} an access value is the same as that of the access type. @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0014-1]} @ChgAdded{Version=[3],Text=[This rule applies even when no dereference exists, for example when an access value is passed as an access parameter. This rule ensures that implementations are not required to include dynamic accessibility values with all access values.]} @end{Discussion} The accessibility level of a component, protected subprogram, or entry of (a view of) a composite object is the same as that of (the view of) the composite object. @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[In the above rules, the operand of a view conversion, parenthesized expression or @nt{qualified_expression} is considered to be used in a context if the view conversion, parenthesized expression or @nt{qualified_expression} itself is used in that context.@Chg{Version=[3],New=[ Similarly, a @SynI{dependent_}@nt{expression} of a @nt{conditional_expression} is considered to be used in a context if the @nt{conditional_expression} itself is used in that context.],Old=[]}]} @begin{WideAbove} @Leading@Defn{statically deeper} @Defn2{Term=[deeper],Sec=(statically)} One accessibility level is defined to be @i{statically deeper} than another in the following cases: @end{WideAbove} @begin{Itemize} For a master that is statically nested within another master, the accessibility level of the inner master is statically deeper than that of the outer master. @begin{Honest} Strictly speaking, this should talk about the @i{constructs} (such as @ntf{subprogram_bodies}) being statically nested within one another; the masters are really the @i{executions} of those constructs. @end{Honest} @begin{Honest} If a given accessibility level is statically deeper than another, then each level defined to be the same as the given level is statically deeper than each level defined to be the same as the other level. @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[The accessibility level of the anonymous access type of an access parameter specifying an access-to-subprogram type is statically deeper than that of any master; all such anonymous access types have this same level.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule means that it is illegal to convert an access parameter specifying an access to subprogram to a named access to subprogram type, but it is allowed to pass such an access parameter to another access parameter (the implicit conversion's accessibility will succeed).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0082-1]} The statically deeper relationship does not apply to the accessibility level of the anonymous type of an access parameter@Chg{Version=[2], New=[ specifying an access-to-object type],Old=[]}@Chg{Version=[3], New=[ nor does it apply to a descendant of a generic formal type],Old=[]}; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0148-1]} @ChgAdded{Version=[3],Text=[The statically deeper relationship does not apply to the accessibility level of the type of a stand-alone object of an anonymous access-to-object type; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In these cases, we use dynamic accessibility checks.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[Inside a return statement that applies to a function @i<F>, when determining whether the accessibility level of an explicitly aliased parameter of @i<F> is statically deeper than the level of the return object of @i<F>, the level of the return object is considered to be the same as that of the level of the explicitly aliased parameter; for statically comparing with the level of other entities, an explicitly aliased parameter of @i<F> is considered to have the accessibility level of the body of @i<F>.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0051-1],ARef=[AI05-0234-1],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[For determining whether a level is statically deeper than the level of the anonymous access type of an access result of a function, when within a return statement that applies to the function, the level of the master of the call is presumed to be the same as that of the level of the master that elaborated the function body.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[This rule has no effect if the previous bullet also applies (that is, the @ldquote@;a level@rdquote is of an explicitly aliased parameter).]} @end{Honest} @Redundant[For determining whether one level is statically deeper than another when within a generic package body, the generic package is presumed to be instantiated at the same level as where it was declared; run-time checks are needed in the case of more deeply nested instantiations.] @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0082-1]} @ChgAdded{Version=[3],Text=[A generic package does not introduce a new master, so it has the static level of its declaration; the rest follows from the other @ldquote@;statically deeper@rdquote rules.]} @end{TheProof} For determining whether one level is statically deeper than another when within the declarative region of a @nt{type_declaration}, the current instance of the type is presumed to be an object created at a deeper level than that of the type. @begin{Ramification} In other words, the rules are checked at compile time of the @nt{type_declaration}, in an assume-the-worst manner. @end{Ramification} @end{Itemize} @Defn{library level} @Defn2{Term=[level],Sec=(library)} The accessibility level of all library units is called the @i{library level}; a library-level declaration or entity is one whose accessibility level is the library level. @begin{Ramification} @nt{Library_unit_declaration}s are library level. Nested declarations are library level if they are nested only within packages (possibly more than one), and not within subprograms, tasks, etc. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised]} @Leading@;The definition of the accessibility level of the anonymous type of an access parameter@Chg{Version=[2],New=[ specifying an access-to-object type],Old=[]} cheats a bit, since it refers to the view designated by the actual, but access values designate objects, not views of objects. What we really mean is the view that @lquotes@;would be@rquotes@; denoted by an expression @lquotes@;X.@key[all]@rquotes@;, where X is the actual, even though such an expression is a figment of our imagination. The definition is intended to be equivalent to the following more verbose version: The accessibility level of the anonymous type of an access parameter is as follows: @begin{Itemize} if the actual is an expression of a named access type @em the accessibility level of that type; if the actual is an @nt{allocator} @em the accessibility level of the execution of the called subprogram; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} if the actual is a reference to the Access attribute @em the accessibility level of the view denoted by the @Chg{New=[@nt{prefix}],Old=[prefix]}; if the actual is a reference to the Unchecked_Access attribute @em library accessibility level; if the actual is an access parameter @em the accessibility level of its type. @end{Itemize} Note that the @nt{allocator} case is explicitly mentioned in the RM95, because otherwise the definition would be circular: the level of the anonymous type is that of the view designated by the actual, which is that of the access type. @end{Honest} @begin{Discussion} A deeper accessibility level implies a shorter maximum lifetime. Hence, when a rule requires X to have a level that is @lquotes@;not deeper than@rquotes@; Y's level, this requires that X has a lifetime at least as long as Y. (We say @lquotes@;maximum lifetime@rquotes@; here, because the accessibility level really represents an upper bound on the lifetime; an object created by an @nt{allocator} can have its lifetime prematurely ended by an instance of Unchecked_Deallocation.) Package elaborations are not masters, and are therefore invisible to the accessibility rules: an object declared immediately within a package has the same accessibility level as an object declared immediately within the declarative region containing the package. This is true even in the body of a package; it jibes with the fact that objects declared in a @nt{package_body} live as long as objects declared outside the package, even though the body objects are not visible outside the package. Note that the level of the @i{view} denoted by X.@key[all] can be different from the level of the @i{object} denoted by X.@key[all]. The former is determined by the type of X; the latter is determined either by the type of the @nt{allocator}, or by the master in which the object was declared. The former is used in several @LegalityTitle and run-time checks; the latter is used to define when X.@key[all] gets finalized. The level of a view reflects what we can conservatively @lquotes@;know@rquotes@; about the object of that view; for example, due to @nt{type_conversion}s, an access value might designate an object that was allocated by an @nt{allocator} for a different access type. Similarly, the level of the view denoted by X.@key[all].Comp can be different from the level of the object denoted by X.@key[all].Comp. If Y is statically deeper than X, this implies that Y will be (dynamically) deeper than X in all possible executions. @Leading@;Most accessibility checking is done at compile time; the rules are stated in terms of @lquotes@;statically deeper than@rquotes@;. The exceptions are: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised]} Checks involving access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}. The fact that @lquotes@;statically deeper than@rquotes@; is not defined for the anonymous access type of an access parameter implies that any rule saying @lquotes@;shall not be statically deeper than@rquotes@; does not apply to such a type, nor to anything defined to have @lquotes@;the same@rquotes@; level as such a type. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0082-1]} @ChgAdded{Version=[3],Text=[Checks involving generic formal types and their descendants. This is because the actual type can be more or less deeply nested than the generic unit. Note that this only applies to the generic unit itself, and not to the instance. Any static checks needed in the instance will be performed. Any other checks (such as those in the generic body) will require a run-time check of some sort (although implementations that macro-expand generics can determine the result of the check when the generic is expanded).]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0082-1]} Checks involving @Chg{Version=[3],New=[other ],Old=[]}entities and views within generic packages. This is because an instantiation can be at a level that is more deeply nested than the generic package itself. In implementations that use a macro-expansion model of generics, these violations can be detected at macro-expansion time. For implementations that share generics, run-time code is needed to detect the error. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} Checks during function return@Chg{Version=[2],New=[ and @nt{allocator}s, for nested type extensions and access discriminants],Old=[]}. @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Note that run-time checks are not required for access discriminants@Chg{Version=[3],New=[ (except during function returns and @nt{allocator}s)],Old=[]}, because their accessibility is determined statically by the accessibility level of the enclosing object. @ChgRef{Version=[2],Kind=[Revised]} @Chg{Version=[2],New=[],Old=[This ]}The accessibility level of the result object of a function reflects the time when that object will be finalized; we don't allow pointers to the object to survive beyond that time. We sometimes use the terms @lquotes@;accessible@rquotes@; and @lquotes@;inaccessible@rquotes@; to mean that something has an accessibility level that is not deeper, or deeper, respectively, than something else. @end{Discussion} @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} If an accessibility @LegalityName is satisfied, then the corresponding run-time check (if any) cannot fail (and a reasonable implementation will not generate any checking code) unless @Chg{Version=[2],New=[one of the cases requiring run-time checks mentioned previously is],Old=[access parameters or shared generic bodies are]} involved. Accessibility levels are defined in terms of the relations @lquotes@;the same as@rquotes@; and @lquotes@;deeper than@rquotes@;. To make the discussion more concrete, we can assign actual numbers to each level. Here, we assume that library-level accessibility is level 0, and each level defined as @lquotes@;deeper than@rquotes@; is one level deeper. Thus, a subprogram directly called from the environment task (such as the main subprogram) would be at level 1, and so on. @ChgRef{Version=[2],Kind=[Revised]} Accessibility is not enforced at compile time for access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}. The @lquotes@;obvious@rquotes@; implementation of the run-time checks would be inefficient, and would involve distributed overhead; therefore, an efficient method is given below. The @lquotes@;obvious@rquotes@; implementation would be to pass the level of the caller at each subprogram call, task creation, etc. This level would be incremented by 1 for each dynamically nested master. An Accessibility_Check would be implemented as a simple comparison @em checking that X is not deeper than Y would involve checking that X <= Y. A more efficient method is based on passing @i{static} nesting levels (within constructs that correspond at run time to masters @em packages don't count). Whenever an access parameter is passed, an implicit extra parameter is passed with it. The extra parameter represents (in an indirect way) the accessibility level of the anonymous access type, and, therefore, the level of the view denoted by a dereference of the access parameter. This is analogous to the implicit @lquotes@;Constrained@rquotes@; bit associated with certain formal parameters of an unconstrained but definite composite subtype. In this method, we avoid distributed overhead: it is not necessary to pass any extra information to subprograms that have no access parameters. For anything other than an access parameter and its anonymous type, the static nesting level is known at compile time, and is defined analogously to the RM95 definition of accessibility level (e.g. derived access types get their nesting level from their parent). Checking @lquotes@;not deeper than@rquotes@; is a "<=" test on the levels. @ChgRef{Version=[2],Kind=[Revised]} @Leading@keepnext@;For each access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, the static depth passed depends on the actual, as follows: @begin{Itemize} If the actual is an expression of a named access type, pass the static nesting level of that type. If the actual is an @nt{allocator}, pass the static nesting level of the caller, plus one. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} If the actual is a reference to the Access attribute, pass the level of the view denoted by the @Chg{New=[@nt{prefix}],Old=[prefix]}. If the actual is a reference to the Unchecked_Access attribute, pass 0 (the library accessibility level). @ChgRef{Version=[2],Kind=[Revised]} If the actual is an access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, usually just pass along the level passed in. However, if the static nesting level of the formal (access) parameter is greater than the static nesting level of the actual (access) parameter, the level to be passed is the minimum of the static nesting level of the access parameter and the actual level passed in. @end{Itemize} @ChgRef{Version=[2],Kind=[Revised]} For the Accessibility_Check associated with a @nt{type_conversion} of an access parameter@Chg{Version=[2],New=[ of an access-to-object type],Old=[]} of a given subprogram to a named access type, if the target type is statically nested within the subprogram, do nothing; the check can't fail in this case. Otherwise, check that the value passed in is <= the static nesting depth of the target type. The other Accessibility_Checks are handled in a similar manner. This method, using statically known values most of the time, is efficient, and, more importantly, avoids distributed overhead. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0148-1]} @ChgAdded{Version=[3],Text=[The implementation of accessibility checks for stand-alone objects of anonymous access-to-object types can be similar to that for anonymous access-to-object parameters. A static level suffices; it can be calculated using rules similar to those previously described for access parameters.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0148-1]} @ChgAdded{Version=[3],Text=[One important difference between the stand-alone access variables and access parameters is that one can assign a local access parameter to a more global stand-alone access variable. Similarly, one can assign a more global access parameter to a more local stand-alone access variable.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0148-1]} @ChgAdded{Version=[3],Text=[For these cases, it is important to note that the @ldquote@;correct@rdquote static accessibility level for an access parameter assigned to a stand-alone access object is the minimum of the passed in level and the static accessibility level of the stand-alone object itself. This is true since the static accessibility level passed in might be deeper than that of the stand-alone object, but the dynamic accessibility of the passed in object clearly must be shallower than the stand-alone object (whatever is passed in must live at least as long as the subprogram call). We do not need to keep a more local static level as accesses to objects statically deeper than the stand-alone object cannot be stored into the stand-alone object.]} @end(ImplNote) @begin{Discussion} @Leading@keepnext@;Examples of accessibility: @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]}@Comment{A1 is access-to-variable, X better be a variable} @key[package] @key[body] Lib_Unit @key[is] @key[type] T @key[is] @key[tagged] ...; @key[type] A0 @key[is] @key[access] @key[all] T; Global: A0 := ...; @key[procedure] P(X: @Chg{Version=[3],New=[@key[in out] ],Old=[]}T) @key[is] Y: @key[aliased] T; @key[type] A1 @key[is] @key[access] @key[all] T; Ptr0: A0 := Global; --@RI{ OK.} Ptr1: A1 := X'Access; --@RI{ OK.} @key[begin] Ptr1 := Y'Access; --@RI{ OK;} Ptr0 := A0(Ptr1); --@RI{ Illegal type conversion!} Ptr0 := X'Access; --@RI{ Illegal reference to Access attribute!} Ptr0 := Y'Access; --@RI{ Illegal reference to Access attribute!} Global := Ptr0; --@RI{ OK.} @key[end] P; @key[end] Lib_Unit; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The above illegal statements are illegal because the accessibility @Chg{Version=[3],New=[levels],Old=[level]} of X and Y are statically deeper than the accessibility level of A0. In every possible execution of any program including this library unit, if P is called, the accessibility level of X will be (dynamically) deeper than that of A0. Note that the accessibility levels of X and Y are the same. @ChgRef{Version=[2],Kind=[Revised]} @Leading@keepnext@;Here's an example involving access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}: @begin{Example} @key[procedure] Main @key[is] @key[type] Level_1_Type @key[is] @key[access] @key[all] Integer; @key[procedure] P(X: @key[access] Integer) @key[is] @key[type] Nested_Type @key[is] @key[access] @key[all] Integer; @key[begin] ... Nested_Type(X) ... --@RI{ (1)} ... Level_1_Type(X) ... --@RI{ (2)} @key[end] P; @key[procedure] Q(X: @key[access] Integer) @key[is] @key[procedure] Nested(X: @key[access] Integer) @key[is] @key[begin] P(X); @key[end] Nested; @key[begin] Nested(X); @key[end] Q; @key[procedure] R @key[is] Level_2: @key[aliased] Integer; @key[begin] Q(Level_2'Access); --@RI{ (3)} @key[end] R; Level_1: @key[aliased] Integer; @key[begin] Q(Level_1'Access); --@RI{ (4)} R; @key[end] Main; @end{Example} The run-time Accessibility_Check at (1) can never fail, and no code should be generated to check it. The check at (2) will fail when called from (3), but not when called from (4). @Leading@;Within a @nt{type_declaration}, the rules are checked in an assume-the-worst manner. For example: @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @key[package] P @key[is] @key[type] Int_Ptr @key[is] @key[access] @key[all] Integer; @key[type] Rec(D: @key[access] Integer) @key[is] @key[limited] @key[private]; @key[private] @key[type] Rec_Ptr @key[is] @key[access] @key[all] Rec; @key[function] F(X: Rec_Ptr) @key[return] Boolean; @key[function] G(X: @key[access] Rec) @key[return] Boolean; @key[type] Rec(D: @key[access] Integer) @key[is] @Chg{Version=[3],New=[@key[limited] ],Old=[]}@key[record] C1: Int_Ptr := Int_Ptr(D); --@RI{ Illegal!} C2: Rec_Ptr := Rec'Access; --@RI{ Illegal!} C3: Boolean := F(Rec'Access); --@RI{ Illegal!} C4: Boolean := G(Rec'Access); @key[end] @key[record]; @key[end] P; @end{Example} C1, C2, and C3 are all illegal, because one might declare an object of type Rec at a more deeply nested place than the declaration of the type. C4 is legal, but the accessibility level of the object will be passed to function G, and constraint checks within G will prevent it from doing any evil deeds. Note that we cannot defer the checks on C1, C2, and C3 until compile-time of the object creation, because that would cause violation of the privacy of private parts. Furthermore, the problems might occur within a task or protected body, which the compiler can't see while compiling an object creation. @end{Discussion} @begin{WideAbove} @Leading@;The following attribute is defined for @PrefixType{a @nt{prefix} X that denotes an aliased view of an object}: @end{WideAbove} @begin(description) @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<X>, AttrName=<Access>, Ref=[8652/0010], ARef=[AI95-00127-01], Text=<X'Access yields an access value that designates the object denoted by X. The type of X'Access is an access-to-object type, as determined by the expected type. The expected type shall be a general access type.>} @IndexSeeAlso{Term=[Unchecked_Access attribute],See=(Access attribute)} @EndPrefixType{} X shall denote an aliased view of an object@Redundant[, including possibly the current instance (see @RefSecNum{The Context of Overload Resolution}) of a limited type within its definition, or a formal parameter or generic formal object of a tagged type]. The view denoted by the @nt<prefix> X shall satisfy the following additional requirements, presuming the expected type for X'Access is the general access type @i(A)@Chg{New=[ with designated type @i(D)],Old=[]}: @begin(itemize) If @i(A) is an access-to-variable type, then the view shall be a variable; @Redundant[on the other hand, if @i(A) is an access-to-constant type, the view may be either a constant or a variable.] @begin{Discussion} The current instance of a limited type is considered a variable. @end{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0008-1],ARef=[AI05-0041-1]} The view shall not be a subcomponent that depends on discriminants of @Chg{Version=[3],New=[an object unless the object is known to be constrained],Old=[a variable whose nominal subtype is unconstrained, unless this subtype is indefinite, or the variable is @Chg{Version=[2],New=[constrained by its initial value], Old=[aliased]}]}. @begin(Discussion) @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} This restriction is intended to be similar to the restriction on renaming discriminant-dependent subcomponents. @end{Discussion} @begin{Reason} This prevents references to subcomponents that might disappear or move or change constraints after creating the reference. @end{Reason} @begin{ImplNote} @Leading@;There was some thought to making this restriction more stringent, roughly: "X shall not denote a subcomponent of a variable with discriminant-dependent subcomponents, if the nominal subtype of the variable is an unconstrained definite subtype." This was because in some implementations, it is not just the discriminant-dependent subcomponents that might move as the result of an assignment that changed the discriminants of the enclosing object. However, it was decided not to make this change because a reasonable implementation strategy was identified to avoid such problems, as follows: @begin(Itemize) Place non-discriminant-dependent components with any aliased parts at offsets preceding any discriminant-dependent components in a discriminated record type with defaulted discriminants. Preallocate the maximum space for unconstrained discriminated variables with aliased subcomponents, rather than allocating the initial size and moving them to a larger (heap-resident) place if they grow as the result of an assignment. @end(Itemize) Note that for objects of a by-reference type, it is not an error for a programmer to take advantage of the fact that such objects are passed by reference. Therefore, the above approach is also necessary for discriminated record types with components of a by-reference type. To make the above strategy work, it is important that a component of a derived type is defined to be discriminant-dependent if it is inherited and the parent subtype constraint is defined in terms of a discriminant of the derived type (see @RefSecNum(Discriminants)). @end{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} If @Chg{New=[@i(A) is a named access type and @i(D) is a tagged type], Old=[the designated type of @i(A) is tagged]}, then the type of the view shall be covered by @Chg{New=[@i(D)],Old=[the designated type]}; @Chg{New=[if @i(A) is anonymous and @i(D) is tagged, then the type of the view shall be either @i(D)'Class or a type covered by @Chg{Version=[2],New=[@i<D>],Old=[D]};],Old=[]} if @Chg{New=[@i(D) is untagged],Old=[@i(A)'s designated type is not tagged]}, then the type of the view shall be @Chg{New=[@i(D)],Old=[the same]}, and @Chg{Version=[2],New=[either:],Old=[@Chg{New=[],Old=[either ]}@i(A)'s designated subtype shall @Chg{New=[either ],Old=[]} statically match the nominal subtype of the view@Chg{New=[ or be], Old=[, or the designated subtype shall be]} discriminated and unconstrained; @PDefn2{Term=[statically matching],Sec=(required)}]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[the designated subtype of @i{A} shall statically match the nominal subtype of the view; or@PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0041-1]} @ChgAdded{Version=[2],Text=[@i{D} shall be discriminated in its full view and unconstrained in any partial view, and the designated subtype of @i{A} shall be unconstrained.@Chg{Version=[3],New=[ For the purposes of determining within a generic body whether @i{D} is unconstrained in any partial view, a discriminated subtype is considered to have a constrained partial view if it is a descendant of an untagged generic formal private or derived type.],Old=[]}]} @end{InnerItemize} @begin{ImplNote} This ensures that the dope for an aliased array object can always be stored contiguous with it, but need not be if its nominal subtype is constrained. @end{implnote} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @Chg{New=[An access attribute can be used as the controlling operand in a dispatching call; see @RefSecNum{Dispatching Operations of Tagged Types}.], Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[This does not require that types have a partial view in order to allow an access attribute of an unconstrained discriminated object, only that any partial view that does exist is unconstrained.],Old=[]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0041-1]} The accessibility level of the view shall not be statically deeper than that of the access type @i{A}.@Chg{Version=[3],New=[],Old=[ In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.@PDefn{generic contract issue}]} @PDefn2{Term=[accessibility rule],Sec=(Access attribute)} @begin(Ramification) In an instance body, a run-time check applies. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If @i(A) is an anonymous@Chg{Version=[2],New=[ access-to-object type of an access parameter],Old=[access type]}, then the view can never have a deeper accessibility level than @i(A)@Chg{Version=[2],New=[. The same is true for an anonymous access-to-object type of an access discriminant],Old=[]}, except when X'Access is used to initialize an access discriminant of an object created by an @nt<allocator>. The latter case is illegal if the accessibility level of X is statically deeper than that of the access type of the @nt<allocator>; a run-time check is needed in the case where the initial value comes from an access parameter.@Chg{Version=[2],New=[ Other anonymous access-to-object types have "normal" accessibility checks.],Old=[]} @end(Ramification) @end(itemize) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these requirements apply also in the private part of an instance of a generic unit.@PDefn{generic contract issue}]} @NoPrefix@IndexCheck{Accessibility_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} A check is made that the accessibility level of X is not deeper than that of the access type @i(A). If this check fails, Program_Error is raised. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised]} The check is needed for access parameters @Chg{Version=[2],New=[ of an access-to-object type],Old=[]} and in instance bodies. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0024-1]} @ChgAdded{Version=[3],Text=[Because there are no access parameters permitted for task entries, the accessibility levels are always comparable. We would have to switch to the terminology used in @RefSecNum{Allocators} and @RefSecNum{Return Statements} based on inclusion within masters if we relax this restriction. That might introduce unacceptable distributed overhead.]} @end{Ramification} @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0148-1]} This check requires that some indication of lifetime is passed as an implicit parameter along with access parameters@Chg{Version=[2], New=[ of an access-to-object type],Old=[]}.@Chg{Version=[3],New=[ A similar indication is required for stand-alone objects of anonymous access-to-object types.],Old=[]}No such requirement applies to @Chg{Version=[2],New=[other anonymous access types],Old=[access discriminants]}, since the checks associated with them are all compile-time checks. @end(ImplNote) @NoPrefix@PDefn2{Term=[implicit subtype conversion],Sec=(Access attribute)} If the nominal subtype of X does not statically match the designated subtype of @i(A), a view conversion of X to the designated subtype is evaluated (which might raise Constraint_Error @em see @RefSecNum(Type Conversions)) and the value of X'Access designates that view. @end(description) The following attribute is defined for @PrefixType{a @nt{prefix} P that denotes a subprogram}: @begin(description) @ChgAttribute{Version=[3],Kind=[Revised],ChginAnnex=[F], Leading=[F], Prefix=<P>, AttrName=<Access>,ARef=[AI95-00229-01], ARef=[AI95-00254-01],ARef=[AI05-0239-1], Text=<P'Access yields an access value that designates the subprogram denoted by P. The type of P'Access is an access-to-subprogram type (@i(S)), as determined by the expected type.>} @EndPrefixType{} @PDefn2{Term=[accessibility rule],Sec=(Access attribute)} The accessibility level of P shall not be statically deeper than that of @i{S}. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. The profile of P shall be @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]} with the designated profile of @i(S), and shall not be Intrinsic. @Defn2{Term=[subtype conformance],Sec=(required)} If the subprogram denoted by P is declared within a generic @Chg{Version=[2],New=[unit, and the expression P'Access occurs within the body of that generic unit or within the body of a generic unit declared within the declarative region of the generic unit, then the ultimate ancestor of @i{S} shall be either a nonformal type declared within the generic unit or an anonymous access type of an access parameter.], Old=[body, @i{S} shall be declared within the generic body.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00229-01]} The part about generic bodies is worded in terms of the denoted subprogram, not the denoted view; this implies that renaming is invisible to this part of the rule.@Chg{Version=[2],New=[ @lquotes@;Declared within the declarative region of the generic@rquotes@; is referring to child and nested generic units.],Old=[]}This rule is partly to prevent contract model problems with respect to the accessibility rules, and partly to ease shared-generic-body implementations, in which a subprogram declared in an instance needs to have a different calling convention from other subprograms with the same profile. @Comment{The change is from AI05-0239-1, just punctuation} Overload resolution ensures only that the profile is @Chg{Version=[3],New=[type conformant],Old=[type-conformant]}. This rule specifies that subtype conformance is required (which also requires matching calling conventions). P cannot denote an entry because access-to-subprogram types never have the @i(entry) calling convention. P cannot denote an enumeration literal or an attribute function because these have intrinsic calling conventions. @end(Discussion) @end(description) @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An @nt{expression} is said to have @i{distributed accessibility} if it is@Defn{distributed accessibility}@Defn2{Term=[accessibility],Sec=[distributed]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[a @nt{conditional_expression} (see @RefSecNum{Conditional Expressions}); or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[a view conversion, @nt{qualified_expression}, or parenthesized expression whose operand has distributed accessibility.]} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[The statically deeper relationship does not apply to the accessibility level of an @nt{expression} having distributed accessibility; that is, such an accessibility level is not considered to be statically deeper, nor statically shallower, than any other.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[Any static accessibility requirement that is imposed on an @nt{expression} that has distributed accessibility (or on its type) is instead imposed on the @SynI{dependent_}@nt{expression}s of the underlying @nt{conditional_expression}. This rule is applied recursively if a @SynI{dependent_}@nt{expression} also has distributed accessibility.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This means that any @LegalityName requiring that the accessibility level of an @nt{expression} (or that of the type of an @nt{expression}) shall or shall not be statically deeper than some other level also applies, in the case where the @nt{expression} has distributed accessibility, to each @SynI{dependent_}@nt{expression} of the underlying @nt{conditional_expression}.]} @end{Discussion} @end{Legality} @begin{Notes} The Unchecked_Access attribute yields the same result as the Access attribute for objects, but has fewer restrictions (see @RefSecNum{Unchecked Access Value Creation}). There are other predefined operations that yield access values: an @nt<allocator> can be used to create an object, and return an access value that designates it (see @RefSecNum(Allocators)); evaluating the literal @key(null) yields a null access value that designates no entity at all (see @RefSecNum(Literals)). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @PDefn2{Term=[predefined operations],Sec=(of an access type)} The predefined operations of an access type also include the assignment operation, qualification, and membership tests. Explicit conversion is allowed between general access types with matching designated subtypes; explicit conversion is allowed between access-to-subprogram types with subtype conformant profiles (see @RefSecNum{Type Conversions}). @PDefn{subtype conformance} Named access types have predefined equality operators; anonymous access types do not@Chg{Version=[2],New=[, but they can use the predefined equality operators for @i<universal_access> ],Old=[]}(see @RefSecNum{Relational Operators and Membership Tests}). @begin(Reason) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[Anonymous access types can use the universal access equality operators declared in Standard, while named access types cannot for compatibility reasons. ],Old=[]}By not having equality operators for anonymous access types, we eliminate the need to specify exactly where the predefined operators for anonymous access types would be defined, as well as the need for an implementer to insert an implicit declaration for "=", etc. at the appropriate place in their symbol table. Note that @Chg{Version=[2],New=[":=", ],Old=[]}'Access@Chg{Version=[2],New=[,],Old=[]} and ".@key[all]" are defined@Chg{Version=[2],New=[],Old=[, and ":=" is defined though useless since all instances are constant. The literal @key(null) is also defined for the purposes of overload resolution, but is disallowed by a @LegalityTitle of this subclause]}. @end(Reason) The object or subprogram designated by an access value can be named with a dereference, either an @nt<explicit_@!dereference> or an @nt<implicit_dereference>. See @RefSecNum{Names}. A call through the dereference of an access-to-subprogram value is never a dispatching call. @begin{TheProof} See @RefSecNum{Dispatching Operations of Tagged Types}. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} @Defn{downward closure} @Defn2{Term=[closure],Sec=(downward)} @Chg{Version=[2],New=[The],Old=[The accessibility rules imply that it is not possible to use the]} Access attribute@Chg{Version=[2],New=[ for subprograms and parameters of an anonymous access-to-subprogram type may together be used],Old=[]} to implement @lquotes@;downward closures@rquotes@; @em that is, to pass a more-nested subprogram as a parameter to a less-nested subprogram, as might be @Chg{Version=[2], New=[appropriate],Old=[desired for example]} for an iterator abstraction@Chg{Version=[2],New=[ or numerical integration. Downward],Old=[. Instead, downward]} closures can @Chg{Version=[2],New=[also ],Old=[]}be implemented using generic formal subprograms (see @RefSecNum{Formal Subprograms}). Note that Unchecked_Access is not allowed for subprograms. Note that using an access-to-class-wide tagged type with a dispatching operation is a potentially more structured alternative to using an access-to-subprogram type. An implementation may consider two access-to-subprogram values to be unequal, even though they designate the same subprogram. This might be because one points directly to the subprogram, while the other points to a special prologue that performs an Elaboration_Check and then jumps to the subprogram. See @RefSecNum(Relational Operators and Membership Tests). @begin{Ramification} If equality of access-to-subprogram values is important to the logic of a program, a reference to the Access attribute of a subprogram should be evaluated only once and stored in a global constant for subsequent use and equality comparison.@end{ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of use of the Access attribute:} @begin{Example} Martha : Person_Name := @key[new] Person(F); --@RI[ see @RefSecNum{Incomplete Type Declarations}] Cars : @key[array] (1..2) @key[of] @key[aliased] Car; ... Martha.Vehicle := Cars(1)'Access; George.Vehicle := Cars(2)'Access; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We no longer make things like 'Last and ".component" (basic) operations of an access type that need to be "declared" somewhere. Instead, implicit dereference in a @nt{prefix} takes care of them all. This means that there should never be a case when X.@key{all}'Last is legal while X'Last is not. See AI83-00154. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[@Leading@;@Defn{incompatibilities with Ada 95} Aliased variables are not necessarily constrained in Ada 2005 (see @RefSecNum{Array Types}). Therefore, a subcomponent of an aliased variable may disappear or change shape, and taking 'Access of such a subcomponent thus is illegal, while the same operation would have been legal in Ada 95. Note that most allocated objects are still constrained by their initial value (see @RefSecNum{Allocators}), and thus legality of 'Access didn't change for them. For example:],Old=[]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} T1 (D1 : Boolean := False) @key{is} @key{record} @key{case} D1 @key{is} @key{when} False => C1 : @key{aliased} Integer; @key{when} True => @key{null}; @key{end} @key{case}; @key{end} @key{record}; @key{type} Acc_Int @key{is access all} Integer;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[A_T : @key{aliased} T1; Ptr : Acc_Int := A_T.C1'Access; -- @RI[Illegal in Ada 2005, legal in Ada 95] A_T := (D1 => True); -- @RI[Raised Constraint_Error in Ada 95, but does not] -- @RI[in Ada 2005, so Ptr would become invalid when this] -- @RI[is assigned (thus Ptr is illegal).]],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[If a discriminated full type has a partial view (private type) that is constrained, we do not allow 'Access on objects to create a value of an object of an access-to-unconstrained type. Ada 95 allowed this attribute and various access subtypes, requiring that the heap object be constrained and thus making details of the implementation of the private type visible to the client of the private type. See @RefSecNum{Allocators} for more on this topic.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00229-01],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] Taking 'Access of a subprogram declared in a generic unit in the body of that generic is no longer allowed. Such references can easily be used to create dangling pointers, as @LegalityTitle are not rechecked in instance bodies. At the same time, the rules were loosened a bit where that is harmless, and also to allow any routine to be passed to an access parameter of an access-to-subprogram type. The now illegal uses of 'Access can almost always be moved to the private part of the generic unit, where they are still legal (and rechecked upon instantiation for possibly dangling pointers).]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> @Defn{extensions to Ada 95} Access attributes of objects of class-wide types can be used as the controlling parameter in a dispatching calls (see @RefSecNum{Dispatching Operations of Tagged Types}). This was an oversight in Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] The type of the prefix can now be used in resolving Access attributes. This allows more uses of the Access attribute to resolve. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Int_Ptr @key{is access all} Integer; @key{type} Float_Ptr @key{is access all} Float;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{function} Zap (Val : Int_Ptr) @key{return} Float; @key{function} Zap (Val : Float_Ptr) @key{return} Float;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Value : @key{aliased} Integer := 10;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Result1 : Float := Zap (Value'access); -- @RI[Ambiguous in Ada 95; resolves in Ada 2005.] Result2 : Float := Zap (Int_Ptr'(Value'access)); -- @RI[Resolves in Ada 95 and Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This change is upward compatible; any expression that does not resolve by the new rules would have failed a Legality Rule.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00162-01]} @ChgAdded{Version=[2],Text=[Adjusted the wording to reflect the fact that expressions and function calls are masters.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00254-01],ARef=[AI95-00318-02],ARef=[AI95-00385-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Defined the accessibility of the various new kinds and uses of anonymous access types.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Simplified the description of when a discriminant-dependent component is allowed as the prefix of 'Access to when the object is known to be constrained. This fixes a confusion as to whether a subcomponent of an object that is not certain to be constrained can be used as a prefix of 'Access. The fix introduces an incompatibility, as the rule did not apply in Ada 95 if the prefix was a constant; but it now applies no matter what kind of object is involved. The incompatibility is not too bad, since most kinds of constants are known to be constrained.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the checks for the constrainedness of the prefix of the Access attribute so that assume-the-worst is used in generic bodies. This may make some programs illegal, but those programs were at risk having objects disappear while valid access values still pointed at them.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0082-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Eliminated the static accessibility definition for generic formal types, as the actual can be more or less nested than the generic itself. This allows programs that were illegal for Ada 95 and for Ada 2005.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0148-1],ARef=[AI05-0253-1]} @ChgAdded{Version=[3],Text=[Eliminate the static accessibility definition for stand-alone objects of anonymous access-to-object types. This allows such objects to be used as temporaries without causing accessibility problems.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0014-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the rules so that the accessibility of the object designated by an access object is that of the access type, even when no dereference is given. The accessibility was not specified in the past. This correction applies to both Ada 95 and Ada 2005.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0024-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected accessibility rules for access discriminants so that no cases are omitted.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0051-1],ARef=[AI05-0234-1],ARef=[AI05-0235-1],ARef=[AI05-0284-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected accessibility rules for anonymous access return types and access discriminants in return statements.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0066-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Changed coextension rules so that coextensions that belong to an anonymous object are transfered to the ultimate object.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4],ARef=[AI05-0188-1],ARef=[AI05-0235-1]} @ChgAdded{Version=[3],Text=[Defined the accessibility of explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}) and @nt{conditional_expression}s (see @RefSecNum{Conditional Expressions}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined the term @ldquote@;master of the call@rdquote to simplify other wording, especially that for the accessibility checks associated with return statements and explicitly aliased parameters.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0270-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined the (omitted) accessibility level of null values when those are passed as the actual of an access-to-object parameter.]} @end{DiffWord2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Declarative Parts} @begin{Intro} @Redundant[A @nt<declarative_part> contains @nt<declarative_item>s (possibly none).] @end{Intro} @begin{Syntax} @Syn{lhs=<declarative_part>,rhs="{@Syn2{declarative_item}}"} @Syn{lhs=<declarative_item>,rhs=" @Syn2{basic_declarative_item} | @Syn2{body}"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<basic_declarative_item>,rhs=" @Syn2{basic_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]} | @Syn2{use_clause}"} @Syn{lhs=<body>,rhs="@Syn2{proper_body} | @Syn2{body_stub}"} @Syn{lhs=<proper_body>,rhs=" @Syn2{subprogram_body} | @Syn2{package_body} | @Syn2{task_body} | @Syn2{protected_body}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[The list of @nt{declarative_item}s of a @nt{declarative_part} is called the @i{declaration list} of the @nt{declarative_part}.@PDefn2{Term=[declaration list],Sec=[declarative_part]}]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(declarative_part)} The elaboration of a @nt{declarative_part} consists of the elaboration of the @nt{declarative_item}s, if any, in the order in which they are given in the @nt{declarative_part}. @Defn{elaborated} An elaborable construct is in the @i(elaborated) state after the normal completion of its elaboration. Prior to that, it is @i(not yet elaborated). @begin{Ramification} The elaborated state is only important for bodies; certain uses of a body raise an exception if the body is not yet elaborated. Note that "prior" implies before the start of elaboration, as well as during elaboration. The use of the term "normal completion" implies that if the elaboration propagates an exception or is aborted, the declaration is not elaborated. RM83 missed the aborted case. @end{Ramification} @IndexCheck{Elaboration_Check} For a construct that attempts to use a body, a check (Elaboration_Check) is performed, as follows: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014],ARef=[AI95-00064-01]} For a call to a (non-protected) subprogram that has an explicit body, a check is made that the @Chg{New=[body],Old=[@nt{subprogram_body}]} is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Discussion} AI83-00180 specifies that there is no elaboration check for a subprogram defined by a @nt{pragma} Interface (or equivalently, @nt{pragma} Import). AI83-00430 specifies that there is no elaboration check for an enumeration literal. AI83-00406 specifies that the evaluation of parameters and the elaboration check occur in an arbitrary order. AI83-00406 applies to generic instantiation as well (see below). @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0177-1]} @ChgAdded{Version=[1],Text=[A subprogram can be completed by a renaming-as-body@Chg{Version=[3],New=[, a @nt{null_procedure_declaration}, or an @nt{expression_function_declaration}],Old=[]}, and we need to make an elaboration check on such a body, so we use @lquotes@;body@rquotes@; rather than @nt{subprogram_body} above.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For a call to a protected operation of a protected type (that has a body @em no check is performed if @Chg{Version=[3],New=[],Old=[a @nt{pragma} Import applies to]} the protected type@Chg{Version=[3],New=[ is imported @em see @RefSecNum{Interfacing Aspects}],Old=[]}), a check is made that the @nt<protected_body> is already elaborated. This check and the evaluations of any actual parameters of the call are done in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Discussion} A protected type has only one elaboration @lquotes@;bit,@rquotes@; rather than one for each operation, because one call may result in evaluating the barriers of other entries, and because there are no elaborable declarations between the bodies of the operations. In fact, the elaboration of a @nt<protected_body> does not elaborate the enclosed bodies, since they are not considered independently elaborable. Note that there is no elaboration check when calling a task entry. Task entry calls are permitted even before the associated @nt<task_body> has been seen. Such calls are simply queued until the task is activated and reaches a corresponding @nt<accept_statement>. We considered a similar rule for protected entries @em simply queuing all calls until the @nt<protected_body> was seen, but felt it was not worth the possible implementation overhead, particularly given that there might be multiple instances of the protected type. @end{Discussion} For the activation of a task, a check is made by the activator that the @nt{task_body} is already elaborated. If two or more tasks are being activated together (see @RefSecNum{Task Execution - Task Activation}), as the result of the elaboration of a @nt{declarative_part} or the initialization for the object created by an allocator, this check is done for all of them before activating any of them. @begin{Reason} As specified by AI83-00149, the check is done by the activator, rather than by the task itself. If it were done by the task itself, it would be turned into a Tasking_Error in the activator, and the other tasks would still be activated. @end{Reason} For the instantiation of a generic unit that has a body, a check is made that this body is already elaborated. This check and the evaluation of any @nt{explicit_generic_actual_parameter}s of the instantiation are done in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @end{Itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if any of these checks fails. @end{RunTime} @begin{Extend83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @Defn{extensions to Ada 83} The syntax for @nt{declarative_part} is modified to remove the ordering restrictions of Ada 83; that is, the distinction between @nt{basic_declarative_item}s and @ntf{later_declarative_item}s within @nt{declarative_part}s is removed. This means that things like @nt{use_clause}s and @Chg{Version=[2],New=[@nt{object_declaration}s],Old=[@ntf{variable_declaration}s]} can be freely intermixed with things like bodies. The syntax rule for @nt{proper_body} now allows a @nt{protected_body}, and the rules for elaboration checks now cover calls on protected operations. @end{Extend83} @begin{DiffWord83} The syntax rule for @ntf{later_declarative_item} is removed; the syntax rule for @nt{declarative_item} is new. RM83 defines @lquotes@;elaborated@rquotes@; and @lquotes@;not yet elaborated@rquotes@; for @nt{declarative_item}s here, and for other things in @RefSec{Declarations}. That's no longer necessary, since these terms are fully defined in @RefSecNum{Declarations}. In RM83, all uses of @nt{declarative_part} are optional (except for the one in @nt{block_statement} with a @key(declare)) which is sort of strange, since a @nt{declarative_part} can be empty, according to the syntax. That is, @nt{declarative_part}s are sort of @lquotes@;doubly optional@rquotes@;. In Ada 95, these @nt{declarative_part}s are always required (but can still be empty). To simplify description, we go further and say (see @RefSec(Block Statements)) that a @nt<block_statement> without an explicit @nt<declarative_part> is equivalent to one with an empty one. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the elaboration check applies to all kinds of subprogram bodies.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[Defined @lquotes@;declaration list@rquotes to avoid confusion for various rules. Other kinds of declaration list are defined elsewhere.]} @end{DiffWord95} @LabeledSubClause{Completions of Declarations} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} Declarations sometimes come in two parts. @Defn{requires a completion} A declaration that requires a second part is said to @i(require completion). @Defn2{Term=[completion], Sec=(compile-time concept)} The second part is called the @i(completion) of the declaration (and of the entity declared), and is either another declaration, a body, or a @nt<pragma>. @Chg{New=[A @defn<body>@i<body> is a @nt<body>, an @nt<entry_body>,@Chg{Version=[3],New=[ a @nt{null_procedure_declaration} or an @nt{expression_function_declaration} that completes another declaration,],Old=[]} or a renaming-as-body (see @RefSecNum<Subprogram Renaming Declarations>).],Old=[]} @begin{Discussion} @Leading@keepnext@;Throughout the RM95, there are rules about completions that define the following: @begin{Itemize} Which declarations require a corresponding completion. Which constructs can only serve as the completion of a declaration. Where the completion of a declaration is allowed to be. What kinds of completions are allowed to correspond to each kind of declaration that allows one. @end{Itemize} Don't confuse this compile-time concept with the run-time concept of completion defined in @RefSecNum{Completion and Finalization}. Note that the declaration of a private type (if limited) can be completed with the declaration of a task type, which is then completed with a body. Thus, a declaration can actually come in @i{three} parts. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0162-1]} @Chg{Version=[2],New=[@Chg{Version=[3],New=[An incomplete type (whether declared in the limited view of a package or not) may be completed by a private type declaration],Old=[In Ada 2005 the limited view of the package contains an incomplete view of the private type]}, so we can @Chg{Version=[3],New=[in fact ],Old=[]}have @i{four} parts@Chg{Version=[3],New=[],Old=[ now]}.],Old=[]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[In Ada 2012, there are no language-defined pragmas that act as completions. Pragma Import (which is obsolescent) has the effect of setting aspect Import to True; such an aspect makes giving a completion illegal. The wording that allows pragmas as completions was left as it is harmless and appears in many places in this Standard.]} @end{Discussion} @end{Intro} @begin{Resolution} @Leading@keepnext@;A construct that can be a completion is interpreted as the completion of a prior declaration only if: @begin(itemize) The declaration and the completion occur immediately within the same declarative region; The defining name or @nt{defining_program_unit_name} in the completion is the same as in the declaration, or in the case of a @nt{pragma}, the @nt{pragma} applies to the declaration; If the declaration is overloadable, then the completion either has a type-conformant profile, or is a @nt{pragma}. @Defn2{Term=[type conformance],Sec=(required)} @end(itemize) @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implicit declaration shall not have a completion. @RootDefn{requires a completion} For any explicit declaration that is specified to @i(require completion), there shall be a corresponding explicit completion@Chg{Version=[3],New=[, unless the declared entity is imported (see @RefSecNum{Interfacing Aspects})],Old=[]}. @begin(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The implicit declarations occurring in a limited view do have a completion (the explicit declaration occurring in the full view) but that's a special case, since the implicit declarations are actually built from the explicit ones. So they do not @i{require} a completion, they have one by @i{fiat}.]} @end{Honest} @begin(Discussion) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The implicit declarations of predefined operators are not allowed to have a completion. Enumeration literals, although they are subprograms, are not allowed to have a corresponding @nt{subprogram_body}. That's because the completion rules are described in terms of constructs (@nt{subprogram_declaration}s) and not entities (subprograms). When a completion is required, it has to be explicit; the implicit null @nt{package_body} that @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Packages} talks about cannot serve as the completion of a @nt{package_declaration} if a completion is required. @end(Discussion) At most one completion is allowed for a given declaration. Additional requirements on completions appear where each kind of completion is defined. @begin{Ramification} A subunit is not a completion; the stub is. If the completion of a declaration is also a declaration, then @i{that} declaration might have a completion, too. For example, a limited private type can be completed with a task type, which can then be completed with a task body. This is not a violation of the @lquotes@;at most one completion@rquotes@; rule. @end{Ramification} @Defn{completely defined} A type is @i(completely defined) at a place that is after its full type definition (if it has one) and after all of its subcomponent types are completely defined. A type shall be completely defined before it is frozen (see @RefSecNum{Freezing Rules} and @RefSecNum{Private Types and Private Extensions}). @begin(Reason) @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} Index types are always completely defined @em no need to mention them. There is no way for a completely defined type to depend on the value of a (still) deferred constant. @end(Reason) @end{Legality} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Completions are in principle allowed for any kind of explicit declaration. However, for some kinds of declaration, the only allowed completion is @Chg{Version=[3],New=[an implementation-defined pragma], Old=[a @nt{pragma} Import]}, and implementations are not required to @Chg{Version=[3],New=[have any such pragmas],Old=[support @nt{pragma} Import for every kind of entity]}. @begin(Discussion) @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[In fact, we expect that implementations will @i{not} support pragma Import of things like types @em it's hard to even define the semantics of what it would mean. Therefore, in practice, @i{not} every explicit declaration can have a completion. In any case, if an implementation chooses to support pragma Import for, say, types, it can place whatever restrictions on the feature it wants to. For example, it might want the @nt{pragma} to be a freezing point for the type.]} @end(Discussion) There are rules that prevent premature uses of declarations that have a corresponding completion. The Elaboration_Checks of @RefSecNum{Declarative Parts} prevent such uses at run time for subprograms, protected operations, tasks, and generic units. The rules of @RefSec{Freezing Rules} prevent, at compile time, premature uses of other entities such as private types and deferred constants. @end{Notes} @begin{DiffWord83} This subclause is new. It is intended to cover all kinds of completions of declarations, be they a body for a spec, a full type for an incomplete or private type, a full constant declaration for a deferred constant declaration, or a @nt{pragma} Import for any kind of entity. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added a definition of @i{body}, which is different than @nt{body} or @key{body}.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0177-1]} @ChgAdded{Version=[3],Text=[Added null procedures and expression functions that are completions to the definition of @i<body>.]} @end{DiffWord2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/04a.mss��������������������������������������������������������������0000755�0001752�0001001�00000732667�12066652506�016562� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(04, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @LabeledSection{Names and Expressions} @Comment{$Source: e:\\cvsroot/ARM/Source/04a.mss,v $} @Comment{$Revision: 1.134 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[The rules applicable to the different forms of @nt<name> and expression, and to their evaluation, are given in this @Chg{Version=[3],New=[clause],Old=[section]}.] @end{Intro} @LabeledClause{Names} @begin{Intro} @redundant[@nt<Name>s can denote declared entities, whether declared explicitly or implicitly (see @RefSecNum(Declarations)). @nt<Name>s can also denote objects or subprograms designated by access values; the results of @nt<type_conversion>s or @nt<function_call>s; subcomponents and slices of objects and values; protected subprograms, single entries, entry families, and entries in families of entries. Finally, @nt<name>s can denote attributes of any of the foregoing.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0003-1],ARef=[AI05-0139-2]} @Syn{tabs=[P22], lhs=<name>,rhs=" @Syn2{direct_name}@\| @Syn2{explicit_dereference} | @Syn2{indexed_component}@\| @Syn2{slice} | @Syn2{selected_component}@\| @Syn2{attribute_reference} | @Syn2{type_conversion}@\| @Syn2{function_call} | @Syn2{character_literal}@Chg{Version=[3],New=[@\| @Syn2{qualified_expression} | @Syn2{generalized_reference}@\| @Syn2{generalized_indexing}],Old=[]}"} @Syn{lhs=<direct_name>, rhs="@Syn2{identifier} | @Syn2{operator_symbol}"} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @nt<character_literal> is no longer a @nt<direct_name>. @nt<character_literal>s are usable even when the corresponding @Chg{Version=[2],New=[enumeration type declaration],Old=[@ntf<enumeration_type_declaration>]} is not visible. See @RefSecNum(Literals). @end{Discussion} @Syn{lhs=<prefix>,rhs="@Syn2{name} | @Syn2{implicit_dereference}"} @Syn{lhs=<explicit_dereference>,rhs="@Syn2{name}.@key{all}"} @Syn{lhs=<implicit_dereference>,rhs="@Syn2{name}"} @end{Syntax} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @Redundant[Certain forms of @nt<name> (@nt<indexed_component>s, @nt<selected_component>s, @nt<slice>s, and @Chg{Version=[3],New=[@nt<attribute_reference>s],Old=[@ntf<attribute>s]}) include a @nt<prefix> that is either itself a @nt<name> that denotes some related entity, or an @nt<implicit_dereference> of an access value that designates some related entity.] @end{Intro} @begin{Resolution} @Defn{dereference} @PDefn2{Term=[expected type], Sec=(dereference @nt{name})} The @nt{name} in a @i(dereference) (either an @nt<implicit_dereference> or an @nt<explicit_dereference>) is expected to be of any access type. @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0008-1]} @PDefn2{Term=[nominal subtype], Sec=(associated with a dereference)} If the type of the @nt{name} in a dereference is some access-to-object type @i(T), then the dereference denotes a view of an object, the @i(nominal subtype) of the view being the designated subtype of @i(T).@Chg{Version=[3],New=[ If the designated subtype has unconstrained discriminants, the (actual) subtype of the view is constrained by the values of the discriminants of the designated object, except when there is a partial view of the type of the designated subtype that does not have discriminants, in which case the dereference is not constrained by its discriminant values.],Old=[]} @begin{Ramification} If the value of the @nt<name> is the result of an access type conversion, the dereference denotes a view created as part of the conversion. The nominal subtype of the view is not necessarily the same as that used to create the designated object. See @RefSecNum{Type Conversions}. @end{Ramification} @begin{Honest} @PDefn2{Term=[nominal subtype], Sec=(of a @nt<name>)} We sometimes refer to the nominal subtype of a particular kind of @nt<name> rather than the nominal subtype of the view denoted by the @nt<name> (presuming the @nt<name> denotes a view of an object). These two uses of nominal subtype are intended to mean the same thing. @end{Honest} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[The last sentence was not present in Ada 95; it is necessary in Ada 2005 because general access types can designate unconstrained objects, which was not possible in Ada 95. Thus, the rules that had this effect in Ada 95 (the object being constrained by its initial value) don't work in Ada 2005 and we have to say this explicitly.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[The @ldquote@;except@rdquote@; part of the last sentence prevents privacy @ldquote@;breaking@rdquote@;, so that if a private type has discriminants only in the full view, they don't interfere with freely interassigning values between objects of the type, even when the objects live in the heap.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[Since we don't depend on whether the designated object is constrained, it is not necessary to include a constrained bit in every object that could be designated by a general access type.]} @end{ImplNote} @PDefn2{Term=[profile], Sec=(associated with a dereference)} If the type of the @nt<name> in a dereference is some access-to-subprogram type @i(S), then the dereference denotes a view of a subprogram, the @i(profile) of the view being the designated profile of @i(S). @begin{Ramification} This means that the formal parameter names and default expressions to be used in a call whose @nt<name> or @nt<prefix> is a dereference are those of the designated profile, which need not be the same as those of the subprogram designated by the access value, since 'Access requires only subtype conformance, not full conformance. @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @PDefn2{Term=[evaluation], Sec=(name)} The evaluation of a @nt<name> determines the entity denoted by the @Chg{Version=[2],New=[@nt<name>],Old=[name]}. This evaluation has no other effect for a @nt<name> that is a @nt<direct_name> or a @nt<character_literal>. @PDefn2{Term=[evaluation], Sec=(name that has a prefix)} @Redundant[The evaluation of a @nt<name> that has a @nt<prefix> includes the evaluation of the @nt<prefix>.] @PDefn2{Term=[evaluation], Sec=(prefix)} The evaluation of a @nt{prefix} consists of the evaluation of the @nt{name} or the @nt{implicit_dereference}. The @nt{prefix} denotes the entity denoted by the @nt{name} or the @nt{implicit_dereference}. @PDefn2{Term=[evaluation], Sec=(dereference)} The evaluation of a dereference consists of the evaluation of the @nt{name} and the determination of the object or subprogram that is designated by the value of the @nt{name}. @IndexCheck{Access_Check} A check is made that the value of the @nt{name} is not the null access value. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. The dereference denotes the object or subprogram designated by the value of the @nt{name}. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of direct names:) @begin(Example) @tabclear()@tabset(P9, P47) Pi @\@RI(-- the direct name of a number) @\(see @RefSecNum(Number Declarations)) Limit @\@RI(-- the direct name of a constant) @\(see @RefSecNum(Object Declarations)) Count @\@RI(-- the direct name of a scalar variable) @\(see @RefSecNum(Object Declarations)) Board @\@RI(-- the direct name of an array variable) @\(see @RefSecNum(Index Constraints and Discrete Ranges)) Matrix @\@RI(-- the direct name of a type) @\(see @RefSecNum(Array Types)) Random @\@RI(-- the direct name of a function) @\(see @RefSecNum(Subprogram Declarations)) Error @\@RI(-- the direct name of an exception) @\(see @RefSecNum(Exception Declarations)) @end(Example) @begin{WideAbove} @leading@keepnext@i{Examples of dereferences:} @end{WideAbove} @begin{Example}@tabclear()@tabset(P19) Next_Car.@key[all]@\--@RI[ explicit dereference denoting the object designated by] @\--@RI[ the access variable Next_Car (see @RefSecNum{Incomplete Type Declarations})] Next_Car.Owner @\--@RI[ selected component with implicit dereference;] @\--@RI[ same as Next_Car.@key[all].Owner] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Type conversions and function calls are now considered names that denote the result of the operation. In the case of a type conversion used as an actual parameter or that is of a tagged type, the type conversion is considered a variable if the operand is a variable. This simplifies the description of "parameters of the form of a type conversion" as well as better supporting an important OOP paradigm that requires the combination of a conversion from a class-wide type to some specific type followed immediately by component selection. Function calls are considered names so that a type conversion of a function call and the function call itself are treated equivalently in the grammar. A function call is considered the name of a constant, and can be used anywhere such a name is permitted. See @RefSecNum(Return Statements). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} Type conversions of a tagged type are permitted anywhere their operand is permitted. That is, if the operand is a variable, then the type conversion can appear on the left-hand side of an @nt{assignment_statement}. If the operand is an object, then the type conversion can appear in an object renaming or as a @Chg{New=[@nt{prefix}],Old=[prefix]}. See @RefSecNum(Type Conversions). @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Everything of the general syntactic form @nt{name}(...) is now syntactically a @nt{name}. In any realistic parser, this would be a necessity since distinguishing among the various @nt{name}(...) constructs inevitably requires name resolution. In cases where the construct yields a value rather than an object, the name denotes @Chg{Version=[2],New=[a],Old=[the]} value rather than an object. Names already denote values in Ada 83 with named numbers, components of the result of a function call, etc. This is partly just a wording change, and partly an extension of functionality (see Extensions heading above). The syntax rule for @nt{direct_name} is new. It is used in places where direct visibility is required. It's kind of like Ada 83's @ntf{simple_name}, but @ntf{simple_name} applied to both direct visibility and visibility by selection, and furthermore, it didn't work right for @nt{operator_symbol}s. The syntax rule for @ntf{simple_name} is removed, since its use is covered by a combination of @nt{direct_name} and @nt{selector_name}. The syntactic categories @nt{direct_name} and @nt{selector_name} are similar; it's mainly the visibility rules that distinguish the two. The introduction of @nt{direct_name} requires the insertion of one new explicit textual rule: to forbid @nt<statement_identifier>s from being @nt<operator_symbol>s. This is the only case where the explicit rule is needed, because this is the only case where the declaration of the entity is implicit. For example, there is no need to syntactically forbid (say) @lquotes@;X: "Rem";@rquotes@;, because it is impossible to declare a type whose name is an @nt{operator_symbol} in the first place. The syntax rules for @nt{explicit_dereference} and @nt{implicit_dereference} are new; this makes other rules simpler, since dereferencing an access value has substantially different semantics from @nt{selected_component}s. We also use @nt{name} instead of @nt{prefix} in the @nt{explicit_dereference} rule since that seems clearer. Note that these rules rely on the fact that function calls are now names, so we don't need to use prefix to allow functions calls in front of .@key{all}. @begin{Discussion} Actually, it would be reasonable to allow any @nt{primary} in front of .@key{all}, since only the value is needed, but that would be a bit radical. @end{Discussion} We no longer use the term @i(appropriate for a type) since we now describe the semantics of a prefix in terms of implicit dereference. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}A @nt{qualified_expression} is now a @nt{name} denoting a constant view; this allows them to be used as a prefix and to be renamed as an object. They are often used to remove ambiguity from function calls, and there may be no other way to do that. Interestingly, a @nt{type_conversion} of a @nt{qualified_expression} is already legal in these contexts, so this change mainly reduces clutter by eliminating an otherwise unneeded @nt{type_conversion} from some expressions.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a missing rule so that most dereferences are assumed constrained (without determining whether the designated object is). This is just confirming the Ada 95 rules; Ada 2005 failed to ensure that this property was unchanged.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Added @nt{generalized_reference} and @nt{generalized_indexing} as types of @nt{name}; these are documented as extensions in the appropriate subclauses.]} @end{DiffWord2005} @LabeledSubClause{Indexed Components} @begin{Intro} @Redundant[An @nt<indexed_component> denotes either a component of an array or an entry in a family of entries. @IndexSee{Term=[array indexing],See=(indexed_component)}] @end{Intro} @begin{Syntax} @Syn{lhs=<indexed_component>,rhs="@Syn2{prefix}(@Syn2{expression} {, @Syn2{expression}})"} @end{Syntax} @begin{Resolution} The @nt{prefix} of an @nt{indexed_component} with a given number of @nt<expression>s shall resolve to denote an array (after any implicit dereference) with the corresponding number of index positions, or shall resolve to denote an entry family of a task or protected object (in which case there shall be only one @nt<expression>). @PDefn2{Term=[expected type], Sec=(indexed_component expression)} The expected type for each @nt{expression} is the corresponding index type. @end{Resolution} @begin{StaticSem} When the @nt<prefix> denotes an array, the @nt<indexed_component> denotes the component of the array with the specified index value(s). @PDefn2{Term=[nominal subtype], Sec=(associated with an @nt<indexed_component>)} The nominal subtype of the @nt<indexed_component> is the component subtype of the array type. @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[In the case of an array whose components are aliased, and of an unconstrained discriminated subtype, the components are constrained even though their nominal subtype is unconstrained. (This is because all aliased discriminated objects are constrained. See @RefSecNum(Operations of Access Types).) In all other cases, an array component is constrained if and only if its nominal subtype is constrained.]} @end{Ramification} When the @nt<prefix> denotes an entry family, the @nt<indexed_component> denotes the individual entry of the entry family with the specified index value. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(indexed_component)} For the evaluation of an @nt<indexed_component>, the @nt{prefix} and the @nt{expression}s are evaluated in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} The value of each @nt<expression> is converted to the corresponding index type. @PDefn2{Term=[implicit subtype conversion],Sec=(array index)} @IndexCheck{Index_Check} A check is made that each index value belongs to the corresponding index range of the array or entry family denoted by the @nt<prefix>. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of indexed components:) @begin{Example} @tabclear()@tabset(P64) My_Schedule(Sat) --@RI[ a component of a one-dimensional array @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Page(10) --@RI[ a component of a one-dimensional array @\(see @RefSecNum{Array Types})] Board(M, J + 1) --@RI[ a component of a two-dimensional array @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Page(10)(20) --@RI[ a component of a component @\(see @RefSecNum{Array Types})] Request(Medium) --@RI[ an entry in a family of entries @\(see @RefSecNum{Task Units and Task Objects})] Next_Frame(L)(M, N) --@RI[ a component of a function call @\(see @RefSecNum{Subprogram Declarations})] @end{Example} @end{Examples} @begin{Notes} @i(Notes on the examples:) Distinct notations are used for components of multidimensional arrays (such as Board) and arrays of arrays (such as Page). The components of an array of arrays are arrays and can therefore be indexed. Thus Page(10)(20) denotes the 20th component of Page(10). In the last example Next_Frame(L) is a function call returning an access value that designates a two-dimensional array. @end{Notes} @LabeledSubClause{Slices} @begin{Intro} @redundant[@Defn{array slice} A @nt<slice> denotes a one-dimensional array formed by a sequence of consecutive components of a one-dimensional array. A @nt<slice> of a variable is a variable; a @nt<slice> of a constant is a constant;] a @nt<slice> of a value is a value. @end{Intro} @begin{Syntax} @Syn{lhs=<slice>,rhs="@Syn2{prefix}(@Syn2{discrete_range})"} @end{Syntax} @begin{Resolution} The @nt{prefix} of a @nt{slice} shall resolve to denote a one-dimensional array (after any implicit dereference). @PDefn2{Term=[expected type], Sec=(slice discrete_range)} The expected type for the @nt{discrete_range} of a @nt<slice> is the index type of the array type. @end{Resolution} @begin{StaticSem} A @nt<slice> denotes a one-dimensional array formed by the sequence of consecutive components of the array denoted by the @nt<prefix>, corresponding to the range of values of the index given by the @nt<discrete_range>. The type of the @nt<slice> is that of the @nt<prefix>. Its bounds are those defined by the @nt{discrete_range}. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(slice)} For the evaluation of a @nt{slice}, the @nt{prefix} and the @nt{discrete_range} are evaluated in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @IndexCheck{Index_Check} @Defn{null slice} If the @nt{slice} is not a @i(null slice) (a @nt<slice> where the @nt<discrete_range> is a null range), then a check is made that the bounds of the @nt{discrete_range} belong to the index range of the array denoted by the @nt{prefix}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{RunTime} @begin{Notes} A @nt<slice> is not permitted as the @nt<prefix> of an Access @nt<attribute_reference>, even if the components or the array as a whole are aliased. See @RefSecNum(Operations of Access Types). @begin{TheProof} Slices are not aliased, by @RefSec{Access Types}. @end{TheProof} @begin(Reason) This is to ease implementation of general-access-to-array. If slices were aliased, implementations would need to store array dope with the access values, which is not always desirable given access-to-incomplete types completed in a package body. @end(Reason) For a one-dimensional array A, the @nt<slice> A(N .. N) denotes an array that has only one component; its type is the type of A. On the other hand, A(N) denotes a component of the array A and has the corresponding component type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of slices:) @begin{Example} @tabclear()@tabset(P58) Stars(1 .. 15) --@RI[ a slice of 15 characters @\(see @RefSecNum{String Types})] Page(10 .. 10 + Size) --@RI[ a slice of 1 + Size components @\(see @RefSecNum{Array Types})] Page(L)(A .. B) --@RI[ a slice of the array Page(L) @\(see @RefSecNum{Array Types})] Stars(1 .. 0) --@RI[ a null slice @\(see @RefSecNum{String Types})] My_Schedule(Weekday) --@RI[ bounds given by subtype @\(see @RefSecNum{Index Constraints and Discrete Ranges} and @RefSecNum{Enumeration Types})] Stars(5 .. 15)(K) --@RI[ same as Stars(K) @\(see @RefSecNum{String Types})] --@RI[ provided that K is in 5 .. 15] @end{Example} @end{Examples} @LabeledSubClause{Selected Components} @begin{Intro} @redundant[@nt{Selected_component}s are used to denote components (including discriminants), entries, entry families, and protected subprograms; they are also used as expanded names as described below. @IndexSee{Term=[dot selection],See=(selected_component)}] @end{Intro} @begin{Syntax} @Syn{lhs=<selected_component>,rhs="@Syn2{prefix} . @Syn2{selector_name}"} @Syn{lhs=<selector_name>,rhs="@Syn2{identifier} | @Syn2{character_literal} | @Syn2{operator_symbol}"} @end{Syntax} @begin{Resolution} @Defn{expanded name} A @nt<selected_component> is called an @i(expanded name) if, according to the visibility rules, at least one possible interpretation of its @nt<prefix> denotes a package or an enclosing named construct (directly, not through a @nt<subprogram_renaming_declaration> or @nt<generic_renaming_declaration>). @begin{Discussion} See AI83-00187. @end{Discussion} @Leading@;A @nt{selected_component} that is not an expanded name shall resolve to denote one of the following: @begin(Ramification) If the @nt<prefix> of a @nt<selected_component> denotes an enclosing named construct, then the @nt<selected_component> is interpreted only as an expanded name, even if the named construct is a function that could be called without parameters. @end(Ramification) @begin{Itemize} A component @Redundant[(including a discriminant)]: @NoPrefix@;The @nt{prefix} shall resolve to denote an object or value of some non-array composite type (after any implicit dereference). The @nt{selector_name} shall resolve to denote a @nt{discriminant_specification} of the type, or, unless the type is a protected type, a @nt<component_declaration> of the type. The @nt{selected_component} denotes the corresponding component of the object or value. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00015} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The components of a protected object cannot be named except by an expanded name, even from within the corresponding protected body. The protected body @Chg{Version=[3],New=[cannot],Old=[may not]} reference @Chg{New=[],Old=[the ]}the private components of some arbitrary object of the protected type; the protected body may reference components of the current instance only (by an expanded name or a @nt<direct_name>). @end{Reason} @begin{Ramification} Only the discriminants and components visible at the place of the @nt<selected_component> can be selected, since a @nt<selector_name> can only denote declarations that are visible (see @RefSecNum{Visibility}). @end{Ramification} A single entry, an entry family, or a protected subprogram: @NoPrefix@;The @nt{prefix} shall resolve to denote an object or value of some task or protected type (after any implicit dereference). The @nt{selector_name} shall resolve to denote an @nt{entry_declaration} or @nt{subprogram_declaration} occurring (implicitly or explicitly) within the visible part of that type. The @nt{selected_component} denotes the corresponding entry, entry family, or protected subprogram. @begin{Reason} This explicitly says @lquotes@;visible part@rquotes@; because even though the body has visibility on the private part, it cannot call the private operations of some arbitrary object of the task or protected type, only those of the current instance (and expanded name notation has to be used for that). @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[A view of a subprogram whose first formal parameter is of a tagged type or is an access parameter whose designated type is tagged:]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0090-1]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The @nt<prefix> (after any implicit dereference) shall resolve to denote an object or value of a specific tagged type @i<T> or class-wide type @i<T>'Class. The @nt<selector_name> shall resolve to denote a view of a subprogram declared immediately within the declarative region in which an ancestor of the type @i<T> is declared. The first formal parameter of the subprogram shall be of type @i<T>, or a class-wide type that covers @i<T>, or an access parameter designating one of these types. The designator of the subprogram shall not be the same as that of a component of the tagged type visible at the point of the @nt<selected_component>. @Chg{Version=[3],New=[The subprogram shall not be an implicitly declared primitive operation of type @i<T> that overrides an inherited subprogram implemented by an entry or protected subprogram visible at the point of the @nt{selected_component}. ],Old=[]}The @nt<selected_component> denotes a view of this subprogram that omits the first formal parameter. This view is called a @i{prefixed view} of the subprogram, and the @nt{prefix} of the @nt<selected_component> (after any implicit dereference) is called the @i<prefix> of the prefixed view. @Defn{prefixed view}@Defn2{Term=[prefix],Sec=[of a prefixed view]}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0090-1]} @ChgAdded{Version=[3],Text=[The part of the rule that excludes a primitive overriding subprogram as a selector applies only to the wrapper subprogram that is implicitly declared to override a subprogram inherited from a synchronized interface that is implemented by an operation of a task or protected type (see @RefSecNum{Task Units and Task Objects} and @RefSecNum{Protected Units and Protected Objects}). We don't want calls that use a prefixed view to be ambiguous between the wrapper subprogram and the implementing entry or protected operation. Note that it is illegal to declare an explicit primitive that has a prefixed view that is homographic with one of the type's operations, so in normal cases it isn't possible to have an ambiguity in a prefix call. However, a class-wide operation of an ancestor type that is declared in the same declaration list with the ancestor type is also considered, and that can still make a call ambiguous.]} @end{Discussion} @end{Itemize} @Leading@;An expanded name shall resolve to denote a declaration that occurs immediately within a named declarative region, as follows: @begin(itemize) The @nt<prefix> shall resolve to denote either a package @Redundant[(including the current instance of a generic package, or a rename of a package)], or an enclosing named construct. The @nt{selector_name} shall resolve to denote a declaration that occurs immediately within the declarative region of the package or enclosing construct @Redundant[(the declaration shall be visible at the place of the expanded name @em see @RefSecNum(Visibility))]. The expanded name denotes that declaration. @begin{Ramification} Hence, a library unit or subunit can use an expanded name to refer to the declarations within the private part of its parent unit, as well as to other children that have been mentioned in @nt<with_clause>s. @end{Ramification} If the @nt<prefix> does not denote a package, then it shall be a @nt<direct_name> or an expanded name, and it shall resolve to denote a program unit (other than a package), the current instance of a type, a @nt{block_statement}, a @nt{loop_statement}, or an @nt{accept_@!statement} (in the case of an @nt<accept_@!statement> or @nt<entry_@!body>, no family index is allowed); the expanded name shall occur within the declarative region of this construct. Further, if this construct is a callable construct and the @nt<prefix> denotes more than one such enclosing callable construct, then the expanded name is ambiguous, independently of the @nt<selector_name>. @end(itemize) @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[For a subprogram whose first parameter is an access parameter, the prefix of any prefixed view shall denote an aliased view of an object.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[For a subprogram whose first parameter is of mode @b<in out> or @b<out>, or of an anonymous access-to-variable type, the prefix of any prefixed view shall denote a variable.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We want calls through a prefixed view and through a normal view to have the same legality. Thus, the implicit 'Access in this new notation needs the same legality check that an explicit 'Access would have. Similarly, we need to prohibit the object from being constant if the first parameter of the subprogram is @key{in out}, because that is (obviously) prohibited for passing a normal parameter.]} @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(selected_component)} The evaluation of a @nt{selected_component} includes the evaluation of the @nt{prefix}. @IndexCheck{Discriminant_Check} For a @nt{selected_component} that denotes a component of a @nt{variant}, a check is made that the values of the discriminants are such that the value or object denoted by the @nt<prefix> has this component. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if this check fails. @end{RunTime} @begin{Examples} @Leading@keepnext@i(Examples of selected components:) @begin{Example} @tabclear()@tabset(P60) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} Tomorrow.Month --@RI[ a record component @\(see @RefSecNum{Record Types})] Next_Car.Owner --@RI[ a record component @\(see @RefSecNum{Incomplete Type Declarations})] Next_Car.Owner.Age --@RI[ a record component @\(see @RefSecNum{Incomplete Type Declarations})] --@RI[ the previous two lines involve implicit dereferences] Writer.Unit --@RI[ a record component (a discriminant) @\(see @RefSecNum{Variant Parts and Discrete Choices})] Min_Cell(H).Value --@RI[ a record component of the result @\(see @RefSecNum{Subprogram Declarations})] --@RI[ of the function call Min_Cell(H)] @Chg{Version=[2],New=< Cashier.Append --@RI[ a prefixed view of a procedure @\(see @RefSecNum{Interface Types})] >,Old=<>} Control.Seize --@RI[ an entry of a protected object @\(see @RefSecNum{Protected Units and Protected Objects})] Pool(K).Write --@RI[ an entry of the task Pool(K) @\(see @RefSecNum{Protected Units and Protected Objects})] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of expanded names:) @end{WideAbove} @begin{Example} @tabclear()@tabset(P67) Key_Manager."<" --@RI[ an operator of the visible part of a package @\(see @RefSecNum{Private Operations})] Dot_Product.Sum --@RI[ a variable declared in a function body @\(see @RefSecNum{Subprogram Declarations})] Buffer.Pool --@RI[ a variable declared in a protected unit @\(see @RefSecNum{Example of Tasking and Synchronization})] Buffer.Read --@RI[ an entry of a protected unit @\(see @RefSecNum{Example of Tasking and Synchronization})] Swap.Temp --@RI[ a variable declared in a block statement @\(see @RefSecNum{Block Statements})] Standard.Boolean --@RI[ the name of a predefined type @\(see @RefSecNum{The Package Standard})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now allow an expanded name to use a prefix that denotes a rename of a package, even if the selector is for an entity local to the body or private part of the package, so long as the entity is visible at the place of the reference. This eliminates a preexisting anomaly where references in a package body may refer to declarations of its visible part but not those of its private part or body when the prefix is a rename of the package. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{selector_name} is new. It is used in places where visibility, but not necessarily direct visibility, is required. See @RefSec{Names} for more information. The description of dereferencing an access type has been moved to @RefSec{Names}; @nt<name>.@key(all) is no longer considered a @nt<selected_component>. The rules have been restated to be consistent with our new terminology, to accommodate class-wide types, etc. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00252-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}The prefixed view notation for tagged objects is new. This provides a similar notation to that used in other popular languages, and also reduces the need for @nt{use_clause}s. This is sometimes known as @lquotes@;distinguished receiver notation@rquotes@;. @Defn{distinguished receiver notation}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Given the following definitions for a tagged type T:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{procedure} Do_Something (Obj : @key{in out} T; Count : @key{in} Natural); @key{procedure} Do_Something_Else (Obj : @key{access} T; Flag : @key{in} Boolean); My_Object : @key{aliased} T;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following calls are equivalent:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Do_Something (My_Object, Count => 10); My_Object.Do_Something (Count => 10);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[as are the following calls:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Do_Something_Else (My_Object'Access, Flag => True); My_Object.Do_Something_Else (Flag => True);]} @end{Example} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0090-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the definition of a prefixed view to ignore the implicit subprograms declared for @ldquote@;implemented by@rdquote entries and protected subprograms.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{Attributes} @begin{Intro} @Defn{attribute} @Redundant[An @i(attribute) is a characteristic of an entity that can be queried via an @nt{attribute_@!reference} or a @nt<range_@!attribute_@!reference>.] @end{Intro} @begin{Syntax} @Syn{lhs=<attribute_reference>, rhs="@Syn2{prefix}@SingleQuote@Syn2{attribute_designator}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI05-0004-1]} @Syn{lhs=<attribute_designator>,rhs=" @Syn2{identifier}[(@SynI{static_}@Syn2{expression})] | Access | Delta | Digits@Chg{Version=[3],New=[ | Mod],Old=[]}"} @Syn{lhs=<range_attribute_reference>, rhs="@Syn2{prefix}@SingleQuote@Syn2{range_attribute_designator}"} @Syn{lhs=<range_attribute_designator>, rhs="Range[(@SynI{static_}@Syn2{expression})]"} @end{Syntax} @begin{Resolution} In an @nt<attribute_reference>, if the @nt<attribute_designator> is for an attribute defined for (at least some) objects of an access type, then the @nt<prefix> is never interpreted as an @nt<implicit_dereference>; otherwise (and for all @nt<range_attribute_reference>s), if the type of the @nt<name> within the @nt<prefix> is of an access type, the @nt<prefix> is interpreted as an @nt<implicit_dereference>. Similarly, if the @nt{attribute_designator} is for an attribute defined for (at least some) functions, then the @nt<prefix> is never interpreted as a parameterless @nt{function_call}; otherwise (and for all @nt<range_attribute_reference>s), if the @nt<prefix> consists of a @nt<name> that denotes a function, it is interpreted as a parameterless @nt<function_call>. @begin{Discussion} The first part of this rule is essentially a "preference" against implicit dereference, so that it is possible to ask for, say, 'Size of an access object, without automatically getting the size of the object designated by the access object. This rule applies to 'Access, 'Unchecked_Access, 'Size, and 'Address, and any other attributes that are defined for at least some access objects. The second part of this rule implies that, for a parameterless function F, F'Address is the address of F, whereas F'Size is the size of the anonymous constant returned by F. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} We normally talk in terms of expected type or profile for name resolution rules, but we don't do this for attributes because certain attributes are legal independent of the type or the profile of the @Chg{New=[@nt{prefix}],Old=[prefix]}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Other than the rules given above, the @ResolutionName@;s for the @nt{prefix} of each attribute are defined as @ResolutionTitle for that attribute. If no such rules are defined, then no context at all should be used when resolving the @nt{prefix}. In particular, any knowledge about the kind of entities required must not be used for resolution unless that is required by @ResolutionTitle. This matters in obscure cases; for instance, given the following declarations:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] Get_It @key[return] Integer @key[is] ... -- @RI[(1)] @key[function] Get_It @key[return] Some_Record_Type @key[is] ... -- @RI[(2)]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following @nt{attribute_reference} cannot be resolved and is illegal:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[if] Get_It'Valid @key[then]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[even though the Valid attribute is only defined for objects of scalar types, and thus cannot be applied to the result of function (2). That information cannot be used to resolve the @nt{prefix}. The same would be true if (2) @Chg{Version=[3],New=[had],Old=[was]} been a procedure; even though the procedure does not denote an object, the @nt{attribute_reference} is still illegal.]} @end{Discussion} @PDefn2{Term=[expected type], Sec=(attribute_designator expression)} @PDefn2{Term=[expected type], Sec=(range_attribute_designator expression)} The @nt{expression}, if any, in an @nt{attribute_designator} or @nt{range_attribute_designator} is expected to be of any integer type. @end{Resolution} @begin{Legality} The @nt{expression}, if any, in an @nt{attribute_designator} or @nt{range_attribute_designator} shall be static. @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0006-1]} An @nt{attribute_reference} denotes a value, an object, a subprogram, or some other kind of program entity.@Chg{Version=[3],New=[ For an @nt{attribute_reference} that denotes a value or an object, if its type is scalar, then its nominal subtype is the base subtype of the type; if its type is tagged, its nominal subtype is the first subtype of the type; otherwise, its nominal subtype is a subtype of the type without any constraint or @nt{null_exclusion}. Similarly, unless explicitly specified otherwise, for an @nt{attribute_reference} that denotes a function, when its result type is scalar, its result subtype is the base subtype of the type, when its result type is tagged, the result subtype is the first subtype of the type, and when the result type is some other type, the result subtype is a subtype of the type without any constraint or @nt{null_exclusion}.],Old=[]} @begin{Ramification} The attributes defined by the language are summarized in @RefSecNum{Language-Defined Attributes}. Implementations can define additional attributes. @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0006-1]} @ChgAdded{Version=[3],Text=[The nominal subtype is primarily a concern when an @nt{attribute_reference}, or a call on an @nt{attribute_reference}, is used as the @nt{expression} of a case statement, due to the full coverage requirement based on the nominal subtype. For nondiscrete cases, we define the nominal subtype mainly for completeness. Implementations may specify otherwise for implementation-defined attribute functions.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The rule is written to match the meaning of the italicized @i{T} in the definition of attributes such as Input; see @RefSecNum{Logical Operators and Short-circuit Control Forms}.]} @end{Discussion} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0006-1]} @ChgAdded{Version=[3],Text=[We don't worry about the fact that @ldquote@;base subtype@rdquote is not explicitly defined for the universal types. Since it is not possible to constrain a universal numeric type, all subtypes are unconstrained, and hence can be considered base subtypes. The wording above could be altered to bypass this issue, but it doesn't seem necessary, since universal integer is handled specially in the rules for case expression full coverage, and we don't allow user-defined functions for attribute functions whose result type is universal.]} @end{Honest} @Redundant[A @nt{range_attribute_reference} X'Range(N) is equivalent to the @nt<range> X'First(N) .. X'Last(N), except that the @nt{prefix} is only evaluated once. Similarly, X'Range is equivalent to X'First .. X'Last, except that the @nt{prefix} is only evaluated once.] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(attribute_reference)} @PDefn2{Term=[evaluation], Sec=(range_attribute_reference)} The evaluation of an @nt{attribute_reference} (or @nt{range_attribute_reference}) consists of the evaluation of the @nt{prefix}. @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0015],ARef=[AI95-00093-01]} An implementation may provide implementation-defined attributes; the @nt{identifier} for an implementation-defined attribute shall differ from those of the language-defined attributes@Chg{New=[ unless supplied for compatibility with a previous edition of this International Standard],Old=[]}. @ImplDef{Implementation-defined attributes.} @begin{Ramification} They cannot be reserved words because reserved words are not legal identifiers. The semantics of implementation-defined attributes, and any associated rules, are, of course, implementation defined. For example, the implementation defines whether a given implementation-defined attribute can be used in a static expression. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0015],ARef=[AI95-00093-01]} @Chg{New=[Implementations are allowed to support the Small attribute for floating types, as this was defined in Ada 83, even though the name would conflict with a language-defined attribute.],Old=[]} @end{Ramification} @end{ImplPerm} @begin{Notes} Attributes are defined throughout this International Standard, and are summarized in @RefSecNum{Language-Defined Attributes}. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235]} In general, the @nt<name> in a @nt<prefix> of an @nt<attribute_reference> (or a @nt<range_attribute_reference>) has to be resolved without using any context. However, in the case of the Access attribute, the expected type for the @Chg{Version=[2],New=[@nt{attribute_reference}], Old=[@Chg{New=[@nt{prefix}],Old=[prefix]}]} has to be a single access type, and@Chg{Version=[2],New=[],Old=[ if it is an access-to-subprogram type (see @RefSecNum(Operations of Access Types)) then]} the resolution of the @nt<name> can use the fact that the@Chg{Version=[2],New=[ type of the object or the],Old=[]} profile of the callable entity denoted by the @nt<prefix> has to @Chg{Version=[2],New=[match the designated type or ],Old=[]}be type conformant with the designated profile of the access type. @Defn2{Term=[type conformance],Sec=(required)} @begin(TheProof) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00235]} In the general case, there is no @lquotes@;expected type@rquotes@; for the @nt<prefix> of an @nt<attribute_reference>. In the special case of 'Access, there is an @Chg{Version=[2],New=[@lquotes@;expected type@rquotes@; or ], Old=[]}@lquotes@;expected profile@rquotes@; for the @nt<prefix>. @end(TheProof) @begin(Reason) 'Access is a special case, because without it, it would be very difficult to take 'Access of an overloaded subprogram. @end(Reason) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of attributes:) @begin{Example} @tabclear()@tabset(P64) Color'First --@RI[ minimum value of the enumeration type Color @\(see @RefSecNum{Enumeration Types})] Rainbow'Base'First --@RI[ same as Color'First @\(see @RefSecNum{Enumeration Types})] Real'Digits --@RI[ precision of the type Real @\(see @RefSecNum{Floating Point Types})] Board'Last(2) --@RI[ upper bound of the second dimension of Board @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Board'Range(1) --@RI[ index range of the first dimension of Board @\(see @RefSecNum{Index Constraints and Discrete Ranges})] Pool(K)'Terminated --@RI[ True if task Pool(K) is terminated @\(see @RefSecNum{Task Units and Task Objects})] Date'Size --@RI[ number of bits for records of type Date @\(see @RefSecNum{Record Types})] Message'Address --@RI[ address of the record variable Message @\(see @RefSecNum{Discriminant Constraints})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} We now uniformly treat X'Range as X'First..X'Last, allowing its use with scalar subtypes. We allow any integer type in the @SynI{static_}@nt{expression} of an attribute designator, not just a value of @i(universal_integer). The preference rules ensure upward compatibility. @end{Extend83} @begin{DiffWord83} We use the syntactic category @nt{attribute_reference} rather than simply "attribute" to avoid confusing the name of something with the thing itself. The syntax rule for @nt{attribute_reference} now uses @nt{identifier} instead of @ntf{simple_name}, because attribute @nt{identifier}s are not required to follow the normal visibility rules. We now separate @nt{attribute_reference} from @nt{range_attribute_reference}, and enumerate the reserved words that are legal attribute or range attribute designators. We do this because @nt{identifier} no longer includes reserved words. The Ada 95 name resolution rules are a bit more explicit than in Ada 83. The Ada 83 rule said that the "meaning of the prefix of an attribute must be determinable independently of the attribute designator and independently of the fact that it is the prefix of an attribute." That isn't quite right since the meaning even in Ada 83 embodies whether or not the prefix is interpreted as a parameterless function call, and in Ada 95, it also embodies whether or not the prefix is interpreted as an implicit_dereference. So the attribute designator does make a difference @em just not much. Note however that if the attribute designator is Access, it makes a big difference in the interpretation of the prefix (see @RefSecNum(Operations of Access Types)). @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0015],ARef=[AI95-00093-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was changed to allow implementations to continue to implement the Ada 83 Small attribute. This was always intended to be allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00235-01]} @ChgAdded{Version=[2],Text=[The note about resolving prefixes of attributes was updated to reflect that the prefix of an Access attribute now has an expected type (see @RefSecNum{Operations of Access Types}).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0006-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined the nominal subtype of an @nt{attribute_reference} to close a minor language hole.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[User-Defined References]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[Given a discriminated type @i<T>, the following type-related operational aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Implicit_Dereference@\This aspect is specified by a @nt{name} that denotes an access discriminant declared for the type @i<T>.@AspectDefn{Implicit_Dereference}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Implicit_Dereference], Text=[@ChgAdded{Version=[3],Text=[Mechanism for user-defined implicit .@key[all].]}]} @end{Description} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[A (view of a) type with a specified Implicit_Dereference aspect is a @i{reference type}.@Defn{reference type} A @i{reference object} is an object of a reference type.@Defn{reference object} The discriminant named by the Implicit_Dereference aspect is the @i{reference discriminant} of the reference type or reference object.@Defn{reference discriminant} @Redundant[A @nt{generalized_reference} is a @nt{name} that identifies a reference object, and denotes the object or subprogram designated by the reference discriminant of the reference object.]]} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Reference type>, Text=<@ChgAdded{Version=[3],Text=[A reference type is one that has user-defined behavior for @ldquote.@key[all]@rdquote, defined by the Implicit_Dereference aspect.]}>} @end{StaticSem} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<generalized_reference>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI{reference_object_}@Syn2{name}>,Old=<>}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The expected type for the @SynI{reference_object_}@nt{name} in a @nt{generalized_reference} is any reference type.@PDefn2{Term=[expected type], Sec=(@SynI{reference_object_}@nt{name})}]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[A @nt{generalized_reference} denotes a view equivalent to that of a dereference of the reference discriminant of the reference object.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[Given a reference type @i<T>, the Implicit_Dereference aspect is inherited by descendants of type @i<T> if not overridden. If a descendant type constrains the value of the reference discriminant of @i<T> by a new discriminant, that new discriminant is the reference discriminant of the descendant. @Redundant[If the descendant type constrains the value of the reference discriminant of @i<T> by an @nt{expression} other than the @nt{name} of a new discriminant, a @nt{generalized_reference} that identifies an object of the descendant type denotes the object or subprogram designated by the value of this constraining expression.]]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[evaluation], Sec=(generalized_reference)} The evaluation of a @nt{generalized_reference} consists of the evaluation of the @SynI{reference_object_}@nt{name} and a determination of the object or subprogram designated by the reference discriminant of the named reference object. @IndexCheck{Access_Check} A check is made that the value of the reference discriminant is not the null access value. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. The @nt{generalized_reference} denotes the object or subprogram designated by the value of the reference discriminant of the named reference object.]} @end{RunTime} @begin{Examples} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[@key[type] Barrel @key[is tagged] ... -- @Examcom{holds objects of type Element}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0299-2]} @ChgAdded{Version=[3],Text=[@key[type] Ref_Element(Data : @key[access] Element) @key[is limited private] @key[with] Implicit_Dereference => Data; -- @Examcom{This Ref_Element type is a "reference" type.} -- @ExamCom{"Data" is its reference discriminant.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[@key[function] Find (B : @key[aliased in out] Barrel; Key : String) @key[return] Ref_Element; -- @Examcom{Return a reference to an element of a barrel.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1],ARef=[AI05-0299-2]} @ChgAdded{Version=[3],Text=[B: @key[aliased] Barrel;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[...]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[Find (B, "grape") := Element'(...); -- @Examcom{Assign through a reference.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[-- @Examcom{This is equivalent to:} Find (B, "grape").Data.@key[all] := Element'(...);]} @end{Example} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}The aspect Implicit_Dereference and the @nt{generalized_reference} are new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[User-Defined Indexing]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[Given a tagged type @i<T>, the following type-related, operational aspects may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Constant_Indexing@\This aspect shall be specified by a @nt{name} that denotes one or more functions declared immediately within the same declaration list in which @i<T> is declared. All such functions shall have at least two parameters, the first of which is of type @i<T> or @i<T>'Class, or is an access-to-constant parameter with designated type @i<T> or @i<T>'Class.@AspectDefn{Constant_Indexing}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Constant_Indexing], Text=[@ChgAdded{Version=[3],Text=[Defines function(s) to implement user-defined @nt{indexed_component}s.]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Variable_Indexing@\This aspect shall be specified by a @nt{name} that denotes one or more functions declared immediately within the same declaration list in which @i<T> is declared. All such functions shall have at least two parameters, the first of which is of type @i<T> or @i<T>'Class, or is an access parameter with designated type @i<T> or @i<T>'Class. All such functions shall have a return type that is a reference type (see @RefSecNum{User-Defined References}), whose reference discriminant is of an access-to-variable type.@AspectDefn{Variable_Indexing}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We require these functions to return a reference type so that the object returned from the function can act like a variable. We need no similar rule for Constant_Indexing, since all functions return constant objects.]} @end{Reason} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Variable_Indexing], Text=[@ChgAdded{Version=[3],Text=[Defines function(s) to implement user-defined @nt{indexed_component}s.]}]} @end{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These aspects are inherited by descendants of @i<T> (including the class-wide type @i<T>'Class). @Redundant[The aspects shall not be overridden, but the functions they denote may be.]]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Indexing can be provided for multiple index types by overloading routines with different parameter profiles. For instance, the map containers provide indexing on both cursors and keys by providing pairs of overloaded routines to the Constant_Indexing and Variable_Indexing aspects.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[An @i<indexable container type> is (a view of) a tagged type with at least one of the aspects Constant_Indexing or Variable_Indexing specified.@Defn{indexable container type} An @i<indexable container object> is an object of an indexable container type.@Defn{indexable container object} @Redundant[A @nt{generalized_indexing} is a @nt{name} that denotes the result of calling a function named by a Constant_Indexing or Variable_Indexing aspect.]]} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Indexable container type>, Text=<@ChgAdded{Version=[3],Text=[An indexable container type is one that has user-defined behavior for indexing, via the Constant_Indexing or Variable_Indexing aspects.]}>} @end{StaticSem} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[The Constant_Indexing or Variable_Indexing aspect shall not be specified:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[on a derived type if the parent type has the corresponding aspect specified or inherited; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[on a @nt{full_type_declaration} if the type has a tagged partial view.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In order to enforce these rules without breaking privacy, we cannot allow a tagged private type to have hidden indexing aspects. There is no problem if the private type is not tagged (as the indexing aspects cannot be specified on descendants in that case).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We don't need an assume-the-worst rule as deriving from formal tagged type is not allowed in generic bodies.]} @end{Ramification} @end{Legality} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<generalized_indexing>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI{indexable_container_object_}@Syn2{prefix} @Syn2{actual_parameter_part}>,Old=<>}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[The expected type for the @Syni{indexable_container_object_}@nt{prefix} of a @nt{generalized_indexing} is any indexable container type.@PDefn2{Term=[expected type], Sec=(@SynI{indexable_container_object_}@nt{prefix})}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If the Constant_Indexing aspect is specified for the type of the @SynI{indexable_container_object_}@nt{prefix} of a @nt{generalized_indexing}, then the @nt{generalized_indexing} is interpreted as a @i<constant indexing> under the following circumstances:@Defn{constant indexing}@Defn2{Term=[indexing],Sec=[constant]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[when the Variable_Indexing aspect is not specified for the type of the @SynI{indexable_container_object_}@nt{prefix};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[when the @SynI{indexable_container_object_}@nt{prefix} denotes a constant;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[when the @nt{generalized_indexing} is used within a @nt{primary} where a @nt{name} denoting a constant is permitted.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This means it is not interpreted as a constant indexing for the @SynI{variable_}@nt{name} in the LHS of an assignment (not inside a @nt{primary}), nor for the @nt{name} used for an @key[out] or @key[in out] parameter (not allowed to be a constant), nor for the @nt{name} in an object renaming (not inside a primary), unless there is no Variable_Indexing aspect defined.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Otherwise, the @nt{generalized_indexing} is interpreted as a @i{variable indexing}.@Defn{variable indexing}@Defn2{Term=[indexing],Sec=[variable]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[When a @nt{generalized_indexing} is interpreted as a constant (or variable) indexing, it is equivalent to a call on a prefixed view of one of the functions named by the Constant_Indexing (or Variable_Indexing) aspect of the type of the @Syni{indexable_container_object_}@nt{prefix} with the given @nt{actual_parameter_part}, and with the @Syni{indexable_container_object_}@nt{prefix} as the @nt{prefix} of the prefixed view.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[In other words, the @nt{generalized_indexing} is equivalent to:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@SynI{indexable_container_object_}@nt{prefix}.Indexing @nt{actual_parameter_part}]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[where Indexing is the name specified for the Constant_Indexing or Variable_Indexing aspect.]} @end{Ramification} @end{Resolution} @begin{Examples} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[@key[type] Indexed_Barrel @key[is tagged] ... @key[with] Variable_Indexing => Find; -- @Examcom{Indexed_Barrel is an indexable container type,} -- @Examcom{Find is the generalized indexing operation.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[@key[function] Find (B : @key[aliased in out] Indexed_Barrel; Key : String) @key[return] Ref_Element; -- @Examcom{Return a reference to an element of a barrel (see @RefSecNum{User-Defined References}).}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[IB: @key[aliased] Indexed_Barrel;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[-- @Examcom{All of the following calls are then equivalent:} Find (IB,"pear").Data.@key[all] := Element'(...); -- @Examcom{Traditional call} IB.Find ("pear").Data.@key[all] := Element'(...); -- @Examcom{Call of prefixed view} IB.Find ("pear") := Element'(...); -- @Examcom{Implicit dereference (see @RefSecNum{User-Defined References})} IB ("pear") := Element'(...); -- @Examcom{Implicit indexing and dereference} IB ("pear").Data.@key[all] := Element'(...); -- @Examcom{Implicit indexing only}]} @end{Example} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Aspects Constant_Indexing and Variable_Indexing, and the @nt{generalized_indexing} syntax are new.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Literals} @begin{Intro} @Redundant[@Defn{literal} A @i(literal) represents a value literally, that is, by means of notation suited to its kind.] A literal is either a @nt<numeric_literal>, a @nt<character_literal>, the literal @key(null), or a @nt<string_literal>. @IndexSeeAlso{Term=[constant],See=(literal)} @begin(Discussion) An enumeration literal that is an @nt<identifier> rather than a @nt<character_literal> is not considered a @i(literal) in the above sense, because it involves no special notation @lquotes@;suited to its kind.@rquotes@; It might more properly be called an @ntf<enumeration_identifier>, except for historical reasons. @end(Discussion) @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[expected type],Sec=(null literal)} The expected type for a literal @key(null) shall be a single access type.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This new wording ("expected type ... shall be a single ... type") replaces the old "shall be determinable" stuff. It reflects an attempt to simplify and unify the description of the rules for resolving aggregates, literals, type conversions, etc. See @RefSec{The Context of Overload Resolution} for the details.]} @end{Discussion} @PDefn2{Term=[expected type],Sec=(character_literal)} @PDefn2{Term=[expected profile],Sec=(character_literal)} For a @nt<name> that consists of a @nt<character_literal>, either its expected type shall be a single character type, in which case it is interpreted as a parameterless @nt<function_call> that yields the corresponding value of the character type, or its expected profile shall correspond to a parameterless function with a character result type, in which case it is interpreted as the name of the corresponding parameterless function declared as part of the character type's definition (see @RefSecNum(Enumeration Types)). In either case, the @nt{character_literal} denotes the @nt{enumeration_literal_specification}. @begin{Discussion} See @RefSecNum(Selected Components) for the resolution rules for a @nt<selector_name> that is a @nt<character_literal>. @end{Discussion} @PDefn2{Term=[expected type],Sec=(string_literal)} The expected type for a @nt{primary} that is a @nt<string_literal> shall be a single string type. @end{Resolution} @begin{Legality} A @nt{character_literal} that is a @nt<name> shall correspond to a @nt<defining_character_literal> of the expected type, or of the result type of the expected profile. For each character of a @nt{string_literal} with a given expected string type, there shall be a corresponding @nt<defining_character_literal> of the component type of the expected string type. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[A literal @s<null>@ChgNote{We use @S since this isn't a nonterminal, and since it is deleted we don't want to fix it.} shall not be of an anonymous access type@Redundant[, since such types do not have a null value (see @RefSecNum{Access Types})].]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This is a legality rule rather than an overloading rule, to simplify implementations.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} An integer literal is of type @i{universal_integer}. A real literal is of type @i{universal_real}.@Chg{Version=[2],New=[ The literal @key<null> is of type @i<universal_access>.@Chg{Version=[3], New=[@PDefn{universal_integer}@PDefn{universal_real}@PDefn{universal_access}],Old=[]}],Old=[]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(numeric literal)} @PDefn2{Term=[evaluation], Sec=(null literal)} @Defn{null access value} @IndexSee{Term=[null pointer],See=(null access value)} The evaluation of a numeric literal, or the literal @key(null), yields the represented value. @PDefn2{Term=[evaluation], Sec=(string_literal)} The evaluation of a @nt{string_literal} that is a @nt<primary> yields an array value containing the value of each character of the sequence of characters of the @nt<string_literal>, as defined in @RefSecNum{String Literals}. The bounds of this array value are determined according to the rules for @nt<positional_array_aggregate>s (see @RefSecNum{Array Aggregates}), except that for a null string literal, the upper bound is the predecessor of the lower bound. @IndexCheck{Range_Check} For the evaluation of a @nt<string_literal> of type @i(T), a check is made that the value of each character of the @nt<string_literal> belongs to the component subtype of @i(T). For the evaluation of a null string literal, a check is made that its lower bound is greater than the lower bound of the base range of the index type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if either of these checks fails. @begin{Ramification} The checks on the characters need not involve more than two checks altogether, since one need only check the characters of the string with the lowest and highest position numbers against the range of the component subtype. @end{Ramification} @end{RunTime} @begin{Notes} Enumeration literals that are @nt<identifier>s rather than @nt<character_literal>s follow the normal rules for @nt<identifier>s when used in a @nt<name> (see @RefSecNum{Names} and @RefSecNum{Selected Components}). @nt<Character_literal>s used as @nt<selector_name>s follow the normal rules for expanded names (see @RefSecNum{Selected Components}). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of literals:) @begin{Example} @tabclear()@tabset(P16) 3.14159_26536 @\--@RI[ a real literal] 1_345 @\--@RI[ an integer literal] 'A' @\--@RI[ a character literal] "Some Text" @\--@RI[ a string literal ] @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Because @nt<character_literal>s are now treated like other literals, in that they are resolved using context rather than depending on direct visibility, additional qualification might be necessary when passing a @nt<character_literal> to an overloaded subprogram. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} @nt<Character_literal>s are now treated analogously to @key(null) and @nt<string_literal>s, in that they are resolved using context, rather than their content; the declaration of the corresponding @nt<defining_character_literal> need not be directly visible. @end{Extend83} @begin{DiffWord83} Name Resolution rules for enumeration literals that are not @nt<character_literal>s are not included anymore, since they are neither syntactically nor semantically "literals" but are rather names of parameterless functions. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}@key{Null} now has type @i<universal_access>, which is similar to other literals. @key{Null} can be used with anonymous access types.]} @end{Extend95} @LabeledClause{Aggregates} @begin{Intro} @Redundant[@Defn{aggregate} An @i(aggregate) combines component values into a composite value of an array type, record type, or record extension.] @IndexSeeAlso{Term={literal},See=(aggregate)} @end{Intro} @begin{Syntax} @Syn{lhs=<aggregate>,rhs="@Syn2{record_aggregate} | @Syn2{extension_aggregate} | @Syn2{array_aggregate}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type],Sec=(aggregate)} The expected type for an @nt{aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}array type, record type, or record extension. @begin{Discussion} See @RefSec{The Context of Overload Resolution} for the meaning of @lquotes@;shall be a single ... type.@rquotes@; @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[There are additional rules for each kind of aggregate. These aggregate rules are additive; a legal expression needs to satisfy all of the applicable rules. That means the rule given here must be satisfied even when it is syntactically possible to tell which specific kind of aggregate is being used.]} @end{Ramification} @end{Resolution} @begin{Legality} An @nt{aggregate} shall not be of a class-wide type. @begin{Ramification} When the expected type in some context is class-wide, an aggregate has to be explicitly qualified by the specific type of value to be created, so that the expected type for the aggregate itself is specific. @end{Ramification} @begin{Discussion} We used to disallow @nt<aggregate>s of a type with unknown discriminants. However, that was unnecessarily restrictive in the case of an extension aggregate, and irrelevant to a record aggregate (since a type that is legal for a record aggregate could not possibly have unknown discriminants) and to an array aggregate (the only specific types that can have unknown discriminants are private types, private extensions, and types derived from them). @end{Discussion} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(aggregate)} For the evaluation of an @nt<aggregate>, an anonymous object is created and values for the components or ancestor part are obtained (as described in the subsequent subclause for each kind of the @nt<aggregate>) and assigned into the corresponding components or ancestor part of the anonymous object. @Defn2{Term=[assignment operation], Sec=(during evaluation of an @nt{aggregate})} Obtaining the values and the assignments occur in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} The value of the @nt{aggregate} is the value of this object. @begin{Discussion} The ancestor part is the set of components inherited from the ancestor type. The syntactic category @nt<ancestor_part> is the @nt<expression> or @nt<subtype_mark> that specifies how the ancestor part of the anonymous object should be initialized. @end{Discussion} @begin{Ramification} The assignment operations do the necessary value adjustment, as described in @RefSecNum{Assignment and Finalization}. Note that the value as a whole is not adjusted @em just the subcomponents (and ancestor part, if any). @RefSecNum{Assignment and Finalization} also describes when this anonymous object is finalized. If the @nt<ancestor_part> is a @nt<subtype_mark> the Initialize procedure for the ancestor type is applied to the ancestor part after default-initializing it, unless the procedure is abstract, as described in @RefSecNum{Assignment and Finalization}. The Adjust procedure for the ancestor type is not called in this case, since there is no assignment to the ancestor part as a whole. @end{Ramification} @IndexCheck{Discriminant_Check} If an @nt{aggregate} is of a tagged type, a check is made that its value belongs to the first subtype of the type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{Ramification} This check ensures that no values of a tagged type are ever outside the first subtype, as required for inherited dispatching operations to work properly (see @RefSecNum(Derived Types and Classes)). This check will always succeed if the first subtype is unconstrained. This check is not extended to untagged types to preserve upward compatibility. @end{Ramification} @end{RunTime} @begin{Extend83} @Defn{extensions to Ada 83} We now allow @nt{extension_aggregate}s. @end{Extend83} @begin{DiffWord83} We have adopted new wording for expressing the rule that the type of an aggregate shall be determinable from the outside, though using the fact that it is nonlimited record (extension) or array. An @nt{aggregate} now creates an anonymous object. This is necessary so that controlled types will work (see @RefSecNum{Assignment and Finalization}). @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} In Ada 95, a limited type is not considered when resolving an @nt{aggregate}. Since Ada 2005 now allows limited @nt{aggregate}s, we can have incompatibilities. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Lim @key{is} @key{limited} @key{record} Comp: Integer; @key{end} @key{record};],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{type} Not_Lim @key{is} @key{record} Comp: Integer; @key{end} @key{record};],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{procedure} P(X: Lim); @key{procedure} P(X: Not_Lim);],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[P((Comp => 123)); -- @RI[Illegal in Ada 2005, legal in Ada 95]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The call to P is ambiguous in Ada 2005, while it would not be ambiguous in Ada 95 as the @nt{aggregate} could not have a limited type. Qualifying the @nt{aggregate} will eliminate any ambiguity. This construction would be rather confusing to a maintenance programmer, so it should be avoided, and thus we expect it to be rare.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}@nt{Aggregate}s can be of a limited type.]} @end{Extend95} @LabeledSubClause{Record Aggregates} @begin{Intro} @Redundant[In a @nt<record_aggregate>, a value is specified for each component of the record or record extension value, using either a named or a positional association.] @end{Intro} @begin{Syntax} @Syn{lhs=<record_aggregate>,rhs="(@Syn2{record_component_association_list})"} @Syn{lhs=<record_component_association_list>,rhs=" @Syn2{record_component_association} {, @Syn2{record_component_association}} | @key<null record>"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<record_component_association>,rhs=" [@Syn2{component_choice_list} =>] @Syn2{expression}@Chg{Version=[2],New=[ | @Syn2{component_choice_list} => <>],Old=[]}"} @Syn{lhs=<component_choice_list>,rhs=" @SynI{component_}@Syn2{selector_name} {| @SynI{component_}@Syn2{selector_name}} | @key{others}"} @begin(SyntaxText) @Defn{named component association} A @nt<record_@!component_@!association> is a @i(named component association) if it has a @nt<component_choice_list>; @Defn{positional component association} otherwise, it is a @i(positional component association). Any positional component associations shall precede any named component associations. If there is a named association with a @nt<component_choice_list> of @key(others), it shall come last. @begin{Discussion} These rules were implied by the BNF in an early version of the RM9X, but it made the grammar harder to read, and was inconsistent with how we handle discriminant constraints. Note that for array aggregates we still express some of the rules in the grammar, but array aggregates are significantly different because an array aggregate is either all positional (with a possible @key(others) at the end), or all named. @end{Discussion} In the @nt<record_@!component_@!association_@!list> for a @nt<record_@!aggregate>, if there is only one association, it shall be a named association. @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Otherwise@Chg{Version=[3],New=[,],Old=[]} the construct would be interpreted as a parenthesized expression. This is considered a syntax rule, since it is relevant to overload resolution. We choose not to express it with BNF so we can share the definition of @nt<record_component_association_list> in both @nt<record_aggregate> and @nt<extension_aggregate>. @end{Reason} @begin{Ramification} The @nt<record_component_association_list> of an @nt<extension_aggregate> does not have such a restriction. @end{Ramification} @end(SyntaxText) @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type],Sec=(record_aggregate)} The expected type for a @nt{record_aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}record type or record extension. @begin{Ramification} This rule is used to resolve whether an @nt{aggregate} is an @nt{array_aggregate} or a @nt{record_aggregate}. The presence of a @key(with) is used to resolve between a @nt{record_aggregate} and an @nt{extension_aggregate}. @end{Ramification} @Defn2{Term=[needed component], Sec=(@nt<record_aggregate> @nt<record_component_association_list>)} For the @nt<record_@!component_@!association_@!list> of a @nt<record_@!aggregate>, all components of the composite value defined by the aggregate are @i(needed)@Redundant[; for the association list of an @nt<extension_aggregate>, only those components not determined by the ancestor expression or subtype are needed (see @RefSecNum{Extension Aggregates}).] Each @nt{selector_@!name} in a @nt{record_@!component_@!association} shall denote a needed component @Redundant[(including possibly a discriminant)]. @begin{Ramification} For the association list of a @nt{record_aggregate}, @lquotes@;needed components@rquotes@; includes every component of the composite value, but does not include those in unchosen @nt{variant}s (see AI83-309). If there are @nt<variant>s, then the value specified for the discriminant that governs them determines which @nt<variant> is chosen, and hence which components are needed. If an extension defines a new @nt{known_discriminant_part}, then all of its discriminants are needed in the component association list of an extension aggregate for that type, even if the discriminants have the same names and types as discriminants of the type of the ancestor expression. This is necessary to ensure that the positions in the @nt<record_@!component_@!association_@!list> are well defined, and that discriminants that govern @nt{variant_part}s can be given by static expressions. @end{Ramification} @Leading@Keepnext@PDefn2{Term=[expected type], Sec=(record_component_association expression)} The expected type for the @nt<expression> of a @nt<record_@!component_@!association> is the type of the @i(associated) component(s); @Defn2{Term=[associated components], Sec=(of a @nt<record_component_association>)} the associated component(s) are as follows: @begin(itemize) For a positional association, the component @Redundant[(including possibly a discriminant)] in the corresponding relative position (in the declarative region of the type), counting only the needed components; @begin{Ramification} This means that for an association list of an @nt<extension_aggregate>, only noninherited components are counted to determine the position. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[For a derived type (including type extensions), the order of declaration is defined in @RefSec{Derived Types and Classes}. In particular, all discriminants come first, regardless of whether they are defined for the parent type or are newly added to the derived type.]} @end{Ramification} For a named association with one or more @i(component_)@nt<selector_name>s, the named component(s); For a named association with the reserved word @key(others), all needed components that are not associated with some previous association. @end(itemize) @end{Resolution} @begin{Legality} If the type of a @nt{record_aggregate} is a record extension, then it shall be a descendant of a record type, through one or more record extensions (and no private extensions). @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0016-1]} @Chg{Version=[3],New=[The reserved words @key[null record] may appear only if], Old=[If]} there are no components needed in a given @nt<record_@!component_@!association_@!list>@Chg{Version=[3],New=[],Old=[, then the reserved words @key(null record) shall appear rather than a list of @nt<record_@!component_@!association>s]}. @begin{Ramification} For example, "(@key(null record))" is a @nt<record_aggregate> for a null record type. Similarly, "(T'(A) @key(with null record))" is an @nt<extension_aggregate> for a type defined as a null record extension of T. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0016-1]} @ChgAdded{Version=[3],Text=[If no components are needed and @key[null record] is not used, the @nt{record_@!component_@!association} must necessarily be @key[others] => <>, as that is the only @nt{record_@!component_@!association} that does not require an associated component.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0199-1]} Each @nt<record_component_association>@Chg{Version=[2],New=[ other than an @key{others} choice with a <>],Old=[]} shall have at least one associated component, and each needed component shall be associated with exactly one @nt<record_@!component_@!association>. If a @nt<record_@!component_@!association> @Chg{Version=[2],New=[with an @nt{expression} ],Old=[]}has two or more associated components, all of them shall be of the same type@Chg{Version=[3],New=[, or all of them shall be of anonymous access types whose subtypes statically match],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} These rules apply to an association with an @key(others) choice@Chg{Version=[2],New=[ with an expression. An @key(others) choice with a <> can match zero components or several components with different types],Old=[]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Without these rules, there would be no way to know what was the expected type for the @nt<expression> of the association. @Chg{Version=[2],New=[Note that some of the rules do not apply to <> associations, as we do not need to resolve anything. We allow @key{others} => <> to match no components as this is similar to array aggregates. That means that (@key{others} => <>) always represents a default-initialized record or array value.],Old=[]} @end{Reason} @begin{Discussion} AI83-00244 also requires that the @nt{expression} shall be legal for each associated component. This is because even though two components have the same type, they might have different subtypes. Therefore, the legality of the @nt<expression>, particularly if it is an array aggregate, might differ depending on the associated component's subtype. However, we have relaxed the rules on array aggregates slightly for Ada 95, so the staticness of an applicable index constraint has no effect on the legality of the array aggregate to which it applies. See @RefSecNum{Array Aggregates}. This was the only case (that we know of) where a subtype provided by context affected the legality of an @nt{expression}. @end{Discussion} @begin{Ramification} The rule that requires at least one associated component for each @nt<record_component_association> implies that there can be no extra associations for components that don't exist in the composite value, or that are already determined by the ancestor expression or subtype of an @nt<extension_aggregate>. The second part of the first sentence ensures that no needed components are left out, nor specified twice. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0220-1]} @Chg{Version=[3],New=[The],Old=[If the components of a @nt{variant_part} are needed, then the]} value of a discriminant that governs @Chg{Version=[3],New=[a],Old=[the]} @nt{variant_part} @Chg{Version=[3],New=[@i<P> ],Old=[]}shall be given by a static expression@Chg{Version=[3],New=[, unless @i<P> is nested within a @nt{variant} @i<V> that is not selected by the discriminant value governing the @nt{variant_part} enclosing @i<V>],Old=[]}. @begin{Ramification} This expression might either be given within the aggregate itself, or in a constraint on the parent subtype in a @nt<derived_type_definition> for some ancestor of the type of the aggregate. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[A @nt<record_component_association> for a discriminant without a @nt<default_expression> shall have an @nt<expression> rather than <>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A discriminant must always have a defined value, but <> means uninitialized for a discrete type unless the component has a default value.]} @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(record_aggregate)} The evaluation of a @nt<record_aggregate> consists of the evaluation of the @nt<record_@!component_@!association_@!list>. @PDefn2{Term=[evaluation], Sec=(record_component_association_list)} For the evaluation of a @nt{record_@!component_@!association_@!list}, any per-object constraints (see @RefSecNum(Record Types)) for components specified in the association list are elaborated and any @nt<expression>s are evaluated and converted to the subtype of the associated component. @PDefn2{Term=[implicit subtype conversion],Sec=(expressions in aggregate)} Any constraint elaborations and @nt{expression} evaluations (and conversions) occur in an arbitrary order, except that the @nt<expression> for a discriminant is evaluated (and converted) prior to the elaboration of any per-object constraint that depends on it, which in turn occurs prior to the evaluation and conversion of the @nt{expression} for the component with the per-object constraint.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Ramification} The conversion in the first rule might raise Constraint_Error. @end{Ramification} @begin{Discussion} This check in the first rule presumably happened as part of the dependent compatibility check in Ada 83. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[For a @nt<record_component_association> with an @nt<expression>, the @nt<expression> defines the value for the associated component(s). For a @nt<record_component_association> with <>, if the @nt<component_declaration> has a @nt<default_expression>, that @nt<default_expression> defines the value for the associated component(s); otherwise, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see @RefSecNum{Object Declarations}).]} The @nt<expression> of a @nt{record_component_association} is evaluated (and converted) once for each associated component. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[We don't need similar language for <>, as we're considering the value of <> for each individual component. Each component has its own default expression or its own default initialization (they can be different for each component; the components even could have different types), and each one has to be evaluated. So there is no need to repeat that.]} @end{Ramification} @end{RunTime} @begin{Notes} For a @nt<record_aggregate> with positional associations, expressions specifying discriminant values appear first since the @nt<known_discriminant_part> is given first in the declaration of the type; they have to be in the same order as in the @nt<known_discriminant_part>. @end{Notes} @begin{Examples} @Leading@keepnext@i(Example of a record aggregate with positional associations:) @begin{Example} (4, July, 1776) --@RI[ see @RefSecNum{Record Types} ] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of record aggregates with named associations:) @end{WideAbove} @begin{Example} (Day => 4, Month => July, Year => 1776) (Month => July, Day => 4, Year => 1776) (Disk, Closed, Track => 5, Cylinder => 12) --@RI[ see @RefSecNum{Variant Parts and Discrete Choices}] (Unit => Disk, Status => Closed, Cylinder => 9, Track => 1) @end{Example} @begin{WideAbove} @leading@keepnext@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @i(@Chg{Version=[2],New=[Examples],Old=[Example]} of component @Chg{Version=[2],New=[associations],Old=[association]} with several choices:) @end{WideAbove} @begin{Example} @tabclear()@tabset(P50) (Value => 0, Succ|Pred => @key(new) Cell'(0, @key(null), @key(null))) @\--@RI[ see @RefSecNum{Incomplete Type Declarations}] --@RI[ The allocator is evaluated twice: Succ and Pred designate different cells] @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[(Value => 0, Succ|Pred => <>) @\--@RI[ see @RefSecNum{Incomplete Type Declarations}]],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ --@RI[ Succ and Pred will be set to @key{null}]],Old=[]} @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of record aggregates for tagged types (see @RefSecNum(Tagged Types and Type Extensions) and @RefSecNum{Type Extensions}):} @end{WideAbove} @begin{Example} Expression'(@key{null record}) Literal'(Value => 0.0) Painted_Point'(0.0, Pi/2.0, Paint => Red) @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Null record aggregates may now be specified, via "(@key(null record))". However, this syntax is more useful for null record extensions in extension aggregates. @end{Extend83} @begin{DiffWord83} Various AIs have been incorporated (AI83-00189, AI83-00244, and AI83-00309). In particular, Ada 83 did not explicitly disallow extra values in a record aggregate. Now we do. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}<> can be used in place of an @nt{expression} in a @nt{record_aggregate}, default initializing the component.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{record_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0220-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Corrected wording so that the rule for discriminants governing @nt{variant_part}s was not effectively circular. The change makes a few @nt{aggregate}s where a nonstatic discriminant governs an empty @nt{variant_part} illegal. However, most Ada implementations already enforce some version of the new rule and already reject these @nt{aggregate}s. So it is unlikely that any incompatibility will be noticed in practice.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0016-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Fixed the wording so that @key[others] => <> can be used in place of @key[null record]. This is needed to avoid a generic contract issue for generic bodies: we do not want to have to assume the worst to disallow @key[others] => <> if the record type @i{might} be a null record.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0199-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> We now allow multiple components with anonymous access types to be specified with a single component association. This is to be consistent with the capabilities of a named access type.]} @end{Extend2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{Extension Aggregates} @begin{Intro} @Redundant[An @nt<extension_aggregate> specifies a value for a type that is a record extension by specifying a value or subtype for an ancestor of the type, followed by associations for any components not determined by the @nt<ancestor_part>.] @end{Intro} @begin{MetaRules} The model underlying this syntax is that a record extension can also be viewed as a regular record type with an ancestor "prefix." The @nt<record_@!component_@!association_@!list> corresponds to exactly what would be needed if there were no ancestor/prefix type. The @nt{ancestor_part} determines the value of the ancestor/prefix. @end{MetaRules} @begin{Syntax} @Syn{lhs=<extension_aggregate>,rhs=" (@Syn2{ancestor_part} @key(with) @Syn2{record_component_association_list})"} @Syn{lhs=<ancestor_part>, rhs="@Syn2{expression} | @Syn2{subtype_mark}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(extension_aggregate)} The expected type for an @nt{extension_aggregate} shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}type that is a record extension. @PDefn2{Term=[expected type], Sec=(extension_aggregate ancestor expression)} If the @nt<ancestor_part> is an @nt<expression>, it is expected to be of any @Chg{Version=[2],New=[],Old=[nonlimited ]}tagged type. @begin{Reason} We could have made the expected type @i(T')Class where @i(T) is the ultimate ancestor of the type of the aggregate, or we could have made it even more specific than that. However, if the overload resolution rules get too complicated, the implementation gets more difficult and it becomes harder to produce good error messages. @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This rule is additive with the rule given in @RefSecNum{Aggregates}. That means the @RefSecNum{Aggregates} rule must be satisfied even though it is always syntactically possible to tell that something is an extension aggregate rather than another kind of aggregate. Specifically, that means that an extension aggregate is ambiguous if the context is overloaded on array and/or untagged record types, even though those are never legal contexts for an extension aggregate. Thus, this rule acts more like a @LegalityTitle than a @ResolutionTitle.]} @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00306-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0115-1]} If the @nt<ancestor_part> is a @nt<subtype_mark>, it shall denote a specific tagged subtype. @Chg{Version=[2],New=[If the @nt{ancestor_part} is an @nt{expression}, it shall not be dynamically tagged. ],Old=[]} The type of the @nt{extension_aggregate} shall be @Chg{Version=[3],New=[a descendant of],Old=[derived from]} the type of the @nt<ancestor_part>@Chg{Version=[3],New=[ (the @i<ancestor> type)@Defn2{Term=[ancestor type], Sec=<of an @nt<extension_aggregate>>}],Old=[]}, through one or more record extensions (and no private extensions).@Chg{Version=[3],New=[ If the @nt{ancestor_part} is a @nt{subtype_mark}, the view of the ancestor type from which the type is descended (see @RefSecNum{Private Operations}) shall not have unknown discriminants.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00306-01]} @ChgAdded{Version=[2],Text=[The expression cannot be dynamically tagged to prevent implicit "truncation" of a dynamically-tagged value to the specific ancestor type. This is similar to the rules in @RefSecNum{Dispatching Operations of Tagged Types}.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0067-1],ARef=[AI05-0244-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If the type of the @nt{ancestor_part} is limited and at least one component is needed in the @nt{record_component_association_list}, then the @nt{ancestor_part} shall not be:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[a call to a function with an unconstrained result subtype; nor]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[a parenthesized or qualified expression whose operand would violate this rule; nor]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[a @nt{conditional_expression} having at least one @SynI{dependent_}@nt{expression} that would violate this rule.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1],ARef=[AI05-0244-1]} @ChgAdded{Version=[3],Text=[This restriction simplifies implementation, because it ensures that either the caller or the callee knows the size to allocate for the aggregate. Without this restriction, information from both caller and callee would have to be combined to determine the appropriate size.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[The (F(...) with null record) case is exempt from this rule, because such extension aggregates are created internally for inherited functions returning null-extension types @em we can't very well make those illegal. Moreover, we don't need the rule for null extensions, as the result can simply use the space returned by the function call.]} @end{Reason} @end{Legality} @begin{StaticSem} @Defn2{Term=[needed component], Sec=(@nt<extension_aggregate> @nt<record_component_association_list>)} For the @nt{record_@!component_@!association_@!list} of an @nt{extension_@!aggregate}, the only components @i(needed) are those of the composite value defined by the aggregate that are not inherited from the type of the @nt<ancestor_@!part>, plus any inherited discriminants if the @nt<ancestor_@!part> is a @nt<subtype_@!mark> that denotes an unconstrained subtype. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(extension_aggregate)} For the evaluation of an @nt{extension_aggregate}, the @nt{record_@!component_@!association_@!list} is evaluated. If the @nt<ancestor_part> is an @nt<expression>, it is also evaluated; if the @nt<ancestor_part> is a @nt<subtype_mark>, the components of the value of the aggregate not given by the @nt<record_@!component_@!association_@!list> are initialized by default as for an object of the ancestor type. Any implicit initializations or evaluations are performed in an arbitrary order, except that the @nt<expression> for a discriminant is evaluated prior to any other evaluation or initialization that depends on it.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0282-1]} @IndexCheck{Discriminant_Check} If the type of the @nt<ancestor_part> has discriminants @Chg{Version=[3],New=[and],Old=[that are not inherited by the type of the @nt{extension_aggregate}, then, unless]} the @nt<ancestor_part> is@Chg{Version=[3],New=[ not],Old=[]} a @nt<subtype_mark> that denotes an unconstrained subtype,@Chg{Version=[3],New=[ then],Old=[]} a check is made that each discriminant @Chg{Version=[3],New=[determined by the @nt{ancestor_part}],Old=[of the ancestor]} has the value specified for a corresponding discriminant,@Chg{Version=[3],New=[ if any,],Old=[]} either in the @nt{record_@!component_@!association_@!list}, or in the @nt<derived_type_definition> for some ancestor of the type of the @nt{extension_aggregate}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{Ramification} Corresponding and specified discriminants are defined in @RefSecNum{Discriminants}. The rules requiring static compatibility between new discriminants of a derived type and the parent discriminant(s) they constrain ensure that at most one check is required per discriminant of the ancestor expression. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0282-1]} @ChgAdded{Version=[3],Text=[The check needs to be made any time that the ancestor is constrained; the source of the discriminants or the constraints is irrelevant.]} @end{Ramification} @end{RunTime} @begin{Notes} If all components of the value of the @nt<extension_aggregate> are determined by the @nt<ancestor_part>, then the @nt<record_@!component_@!association_@!list> is required to be simply @key(null record). If the @nt<ancestor_part> is a @nt<subtype_mark>, then its type can be abstract. If its type is controlled, then as the last step of evaluating the aggregate, the Initialize procedure of the ancestor type is called, unless the Initialize procedure is abstract (see @RefSecNum{Assignment and Finalization}). @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of extension aggregates (for types defined in @RefSecNum{Type Extensions}):} @begin(example) Painted_Point'(Point @key{with} Red) (Point'(P) @key{with} Paint => Black) (Expression @key{with} Left => 1.2, Right => 3.4) Addition'(Binop @key{with null record}) --@RI[ presuming Binop is of type Binary_Operation] @end(example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The extension aggregate syntax is new. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00306-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Eliminated implicit @lquotes@;truncation@rquotes of a dynamically tagged value when it is used as an ancestor @nt{expression}. If an @nt{aggregate} includes such an @nt{expression}, it is illegal in Ada 2005. Such @nt{aggregate}s are thought to be rare; the problem can be fixed with a type conversion to the appropriate specific type if it occurs.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{extension_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0282-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b[Correction:] An @nt{extension_aggregate} with an @nt{ancestor_part} whose discriminants are constrained and inherited might now raise Constraint_Error if the @nt{aggregate}'s type is constrained, while it was OK in Ada 2005. In almost all cases, this will make no difference as the constraint will be checked by the immediately following use of the @nt{aggregate}, but it is possible to compare such an aggregate for equality; in this case, no exception would be raised by Ada 2005, while Ada 2012 will raise Constraint_Error. This should be very rare, and having the possibility means that the representation of the aggregate type has to be able to support unconstrained values of the type, even if the first subtype is constrained and no such objects can be created any other way.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b[Correction:] A limited unconstrained ancestor expression that is a function call is now illegal unless the extension part is null. Such @nt{aggregate}s were first introduced in Ada 2005 and are very complex to implement as they must be built-in-place with an unknown size; as such, it is unlikely that they are implemented correctly in existing compilers and thus not often used in existing code.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[@b[Correction:] An @nt{ancestor_part} that is a subtype with unknown discriminants is now explicitly illegal. Such a subtype should not be used to declare an object, and the @nt{ancestor_part} acts like an object. The Ada 95 rules did not disallow such cases, so it is possible that code exists that uses such an ancestor, but this should be rare.]} @end{Incompatible2005} @LabeledSubClause{Array Aggregates} @begin{Intro} @Redundant[In an @nt<array_aggregate>, a value is specified for each component of an array, either positionally or by its index.] For a @nt{positional_array_aggregate}, the components are given in increasing-index order, with a final @key[others], if any, representing any remaining components. For a @nt{named_array_aggregate}, the components are identified by the values covered by the @nt{discrete_choice}s. @end{Intro} @begin{MetaRules} @ChgRef{Version=[1],Kind=[Revised]} The rules in this subclause are based on terms and rules for @nt{discrete_choice_list}s defined in @RefSec{Variant Parts and Discrete Choices}. @Chg{New=[For example, the requirements that @key(others) come last and stand alone are found there.],Old=[]}@Comment{This question is asked periodically, so we answer it explicitly.} @end{MetaRules} @begin{Syntax} @Syn{lhs=<array_aggregate>,rhs=" @Syn2{positional_array_aggregate} | @Syn2{named_array_aggregate}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<positional_array_aggregate>,rhs=" (@Syn2{expression}, @Syn2{expression} {, @Syn2{expression}}) | (@Syn2{expression} {, @Syn2{expression}}, @key(others) => @Syn2{expression})@Chg{Version=[2],New=[ | (@Syn2{expression} {, @Syn2{expression}}, @key(others) => <>)],Old=[]}"} @Syn{lhs=<named_array_aggregate>,rhs=" (@Syn2{array_component_association} {, @Syn2{array_component_association}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Syn{lhs=<array_component_association>,rhs=" @Syn2{discrete_choice_list} => @Syn2{expression}@Chg{Version=[2],New=[ | @Syn2{discrete_choice_list} => <>],Old=[]}"} @end{Syntax} @begin{Intro} @Defn{n-dimensional @nt<array_aggregate>} An @i(n-dimensional) @nt<array_aggregate> is one that is written as n levels of nested @nt{array_aggregate}s (or at the bottom level, equivalent @nt{string_literal}s). @Defn2{Term=[subaggregate], Sec=(of an @nt{array_aggregate})} For the multidimensional case (n >= 2) the @nt<array_aggregate>s (or equivalent @nt<string_literal>s) at the n@en@;1 lower levels are called @i(subaggregate)s of the enclosing n-dimensional @nt<array_aggregate>. @Defn{array component expression} The @nt<expression>s of the bottom level subaggregates (or of the @nt<array_aggregate> itself if one-dimensional) are called the @i(array component expressions) of the enclosing n-dimensional @nt<array_aggregate>. @begin(Ramification) Subaggregates do not have a type. They correspond to part of an array. For example, with a matrix, a subaggregate would correspond to a single row of the matrix. The definition of "n-dimensional" @nt<array_aggregate> applies to subaggregates as well as @nt<aggregate>s that have a type. @end(Ramification) @begin(Honest) @Defn{others choice} An @i(@key(others) choice) is the reserved word @key(others) as it appears in a @nt{positional_array_aggregate} or as the @nt{discrete_choice} of the @nt{discrete_choice_list} in an @nt{array_component_association}. @end(Honest) @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(array_aggregate)} The expected type for an @nt{array_aggregate} (that is not a subaggregate) shall be a single @Chg{Version=[2],New=[],Old=[nonlimited ]}array type. @PDefn2{Term=[expected type], Sec=(array_aggregate component expression)} The component type of this array type is the expected type for each array component expression of the @nt<array_aggregate>. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} We already require a single array or record type or record extension for an @nt{aggregate}. The above rule requiring a single @Chg{Version=[2],New=[], Old=[nonlimited ]}array type (and similar ones for record and extension aggregates) resolves which kind of aggregate you have. @end{Ramification} @PDefn2{Term=[expected type], Sec=(array_aggregate discrete_choice)} The expected type for each @nt{discrete_choice} in any @nt{discrete_choice_list} of a @nt{named_array_aggregate} is the type of the @i(corresponding index); @Defn2{Term=[corresponding index], Sec=(for an @nt{array_aggregate})} the corresponding index for an @nt<array_aggregate> that is not a subaggregate is the first index of its type; for an (n@en@;m)-dimensional subaggregate within an @nt<array_aggregate> of an n-dimensional type, the corresponding index is the index in position m+1. @end{Resolution} @begin{Legality} An @nt<array_aggregate> of an n-dimensional array type shall be written as an n-dimensional @nt<array_aggregate>. @begin(Ramification) In an m-dimensional @nt<array_aggregate> @Redundant[(including a subaggregate)], where m >= 2, each of the @nt<expression>s has to be an (m@en@;1)-dimensional subaggregate. @end(Ramification) @Leading@;An @key(others) choice is allowed for an @nt<array_aggregate> only if an @i(applicable index constraint) applies to the @nt{array_aggregate}. @Defn{applicable index constraint} @Redundant[An applicable index constraint is a constraint provided by certain contexts where an @nt{array_aggregate} is permitted that can be used to determine the bounds of the array value specified by the aggregate.] Each of the following contexts (and none other) defines an applicable index constraint: @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} For an @nt{explicit_actual_parameter}, an @nt{explicit_generic_actual_parameter}, the @nt{expression} of a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}, the initialization expression in an @nt{object_@!declaration}, or a @nt{default_@!expression} @Redundant[(for a parameter or a component)], when the nominal subtype of the corresponding formal parameter, generic formal parameter, function @Chg{Version=[2],New=[return object],Old=[result]}, object, or component is a constrained array subtype, the applicable index constraint is the constraint of the subtype; For the @nt{expression} of an @nt{assignment_statement} where the @nt{name} denotes an array variable, the applicable index constraint is the constraint of the array variable; @begin{Reason} This case is broken out because the constraint comes from the actual subtype of the variable (which is always constrained) rather than its nominal subtype (which might be unconstrained). @end{Reason} For the operand of a @nt{qualified_expression} whose @nt{subtype_mark} denotes a constrained array subtype, the applicable index constraint is the constraint of the subtype; For a component @nt{expression} in an @nt{aggregate}, if the component's nominal subtype is a constrained array subtype, the applicable index constraint is the constraint of the subtype; @begin{Discussion} Here, the @nt{array_aggregate} with @key[others] is being used within a larger aggregate. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0147-1]} For a parenthesized @nt{expression}, the applicable index constraint is that, if any, defined for the @nt{expression}@Chg{Version=[3],New=[;],Old=[.]} @begin{Discussion} RM83 omitted this case, presumably as an oversight. We want to minimize situations where an @nt{expression} becomes illegal if parenthesized. @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[For a @nt{conditional_expression}, the applicable index constraint for each @SynI<dependent_>@nt{expression} is that, if any, defined for the @nt{conditional_expression}.]} @end(itemize) The applicable index constraint @i(applies) to an @nt{array_aggregate} that appears in such a context, as well as to any subaggregates thereof. In the case of an @nt<explicit_actual_parameter> (or @nt<default_expression>) for a call on a generic formal subprogram, no applicable index constraint is defined. @begin(Reason) This avoids generic contract model problems, because only mode conformance is required when matching actual subprograms with generic formal subprograms. @end(Reason) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} The @nt{discrete_choice_list} of an @nt{array_component_association} is allowed to have a @nt{discrete_choice} that is a nonstatic @Chg{Version=[3],New=[@nt<choice_expression>],Old=[@nt<expression>]} or that is a @Chg{Version=[3],New=[@nt{subtype_indication} or @nt{range}], Old=[@nt{discrete_range}]} that defines a nonstatic or null range, only if it is the single @nt{discrete_choice} of its @nt{discrete_choice_list}, and there is only one @nt{array_component_association} in the @nt<array_aggregate>. @begin{Discussion} We now allow a nonstatic @key(others) choice even if there are other array component expressions as well. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} In a @nt<named_array_aggregate> @Chg{Version=[3],New=[where all @nt{discrete_choice}s are static],Old=[with more than one @nt<discrete_choice>]}, no two @nt<discrete_choice>s are allowed to cover the same value (see @RefSecNum{Variant Parts and Discrete Choices}); if there is no @key[others] choice, the @nt<discrete_choice>s taken together shall exactly cover a contiguous sequence of values of the corresponding index type. @begin{Ramification} This implies that each component must be specified exactly once. See AI83-309. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[This has to apply even if there is only one static @nt{discrete_choice}; a single choice has to represent a contiguous range (a @nt{subtype_mark} with a static predicate might represent a discontiguous set of values). If the (single) choice is a dynamic subtype, we don't need to make this check as no predicates are allowed (see @RefSecNum{Subtype Predicates}) and thus the range has to be contiguous.]} @end{Reason} A bottom level subaggregate of a multidimensional @nt<array_aggregate> of a given array type is allowed to be a @nt<string_literal> only if the component type of the array type is a character type; each character of such a @nt{string_literal} shall correspond to a @nt<defining_character_literal> of the component type. @end{Legality} @begin{StaticSem} A subaggregate that is a @nt<string_literal> is equivalent to one that is a @nt<positional_array_aggregate> of the same length, with each @nt<expression> being the @nt<character_literal> for the corresponding character of the @nt<string_literal>. @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(array_aggregate)} The evaluation of an @nt{array_aggregate} of a given array type proceeds in two steps: @begin(enumerate) Any @nt{discrete_choice}s of this aggregate and of its subaggregates are evaluated in an arbitrary order, and converted to the corresponding index type;@PDefn2{Term=[arbitrary order],Sec=[allowed]} @PDefn2{Term=[implicit subtype conversion],Sec=(choices of aggregate)} The array component expressions of the aggregate are evaluated in an arbitrary order and their values are converted to the component subtype of the array type; an array component expression is evaluated once for each associated component. @PDefn2{Term=[implicit subtype conversion],Sec=(expressions of aggregate)} @PDefn2{Term=[arbitrary order],Sec=[allowed]} @end(enumerate) @begin(Ramification) Subaggregates are not separately evaluated. The conversion of the value of the component expressions to the component subtype might raise Constraint_Error. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[We don't need to say that <> is evaluated once for each component, as <> means that each component is @i{initialized by default}. That means that the actions defined for default initialization are applied to each component individually. Initializing one component by default and copying that to the others would be an incorrect implementation in general (although it might be OK if the default initialization is known to be constant).]} @end(Ramification) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Each @nt<expression> in an @nt<array_component_association> defines the value for the associated component(s). For an @nt<array_component_association> with <>, the associated component(s) are initialized by default as for a stand-alone object of the component subtype (see @RefSecNum{Object Declarations}).]} @Leading@Defn2{Term=[bounds], Sec=(of the index range of an @nt{array_aggregate})} The bounds of the index range of an @nt{array_aggregate} @Redundant[(including a subaggregate)] are determined as follows: @begin(itemize) For an @nt{array_aggregate} with an @key(others) choice, the bounds are those of the corresponding index range from the applicable index constraint; For a @nt{positional_array_aggregate} @Redundant[(or equivalent @nt<string_literal>)] without an @key(others) choice, the lower bound is that of the corresponding index range in the applicable index constraint, if defined, or that of the corresponding index subtype, if not; in either case, the upper bound is determined from the lower bound and the number of @nt<expression>s @Redundant[(or the length of the @nt<string_literal>)]; For a @nt{named_array_aggregate} without an @key(others) choice, the bounds are determined by the smallest and largest index values covered by any @nt{discrete_choice_list}. @begin{Reason} We don't need to say that each index value has to be covered exactly once, since that is a ramification of the general rule on @nt{aggregate}s that each component's value has to be specified exactly once. @end{Reason} @end(itemize) @IndexCheck{Range_Check} For an @nt<array_aggregate>, a check is made that the index range defined by its bounds is compatible with the corresponding index subtype. @begin{Discussion} In RM83, this was phrased more explicitly, but once we define "compatibility" between a range and a subtype, it seems to make sense to take advantage of that definition. @end{Discussion} @begin(Ramification) The definition of compatibility handles the special case of a null range, which is always compatible with a subtype. See AI83-00313. @end(Ramification) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0037-1]} @IndexCheck{Index_Check} For an @nt{array_aggregate} with an @key(others) choice, a check is made that no @nt<expression>@Chg{Version=[3],New=[ or <>],Old=[]} is specified for an index value outside the bounds determined by the applicable index constraint. @begin{Discussion} RM83 omitted this case, apparently through an oversight. AI83-00309 defines this as a dynamic check, even though other Ada 83 rules ensured that this check could be performed statically. We now allow an @key(others) choice to be dynamic, even if it is not the only choice, so this check now needs to be dynamic, in some cases. Also, within a generic unit, this would be a nonstatic check in some cases. @end{Discussion} @IndexCheck{Index_Check} For a multidimensional @nt{array_aggregate}, a check is made that all subaggregates that correspond to the same index have the same bounds. @begin{Ramification} No array bounds @lquotes@;sliding@rquotes@; is performed on subaggregates. @end{Ramification} @begin{Reason} If sliding were performed, it would not be obvious which subaggregate would determine the bounds of the corresponding index. @end{Reason} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if any of the above checks fail. @end{RunTime} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} In an @nt<array_aggregate>, positional notation may only be used with two or more @nt<expression>s; a single @nt<expression> in parentheses is interpreted as a @Chg{Version=[3],New=[parenthesized expression],Old=[@ntf{parenthesized_expression}]}. A @nt<named_array_aggregate>, such as (1 => X), may be used to specify an array with a single component. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of array aggregates with positional associations:) @begin{Example} (7, 9, 5, 1, 3, 2, 4, 8, 6, 0) Table'(5, 8, 4, 1, @key(others) => 0) --@RI[ see @RefSecNum{Array Types} ] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of array aggregates with named associations:) @end{WideAbove} @begin{Example} (1 .. 5 => (1 .. 8 => 0.0)) --@RI[ two-dimensional] (1 .. N => @key(new) Cell) --@RI[ N new cells, in particular for N = 0] Table'(2 | 4 | 10 => 1, @key(others) => 0) Schedule'(Mon .. Fri => True, @key(others) => False) --@RI[ see @RefSecNum{Array Types}] Schedule'(Wed | Sun => False, @key(others) => True) Vector'(1 => 2.5) --@RI[ single-component vector] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of two-dimensional array aggregates:) @end{WideAbove} @begin{Example} --@RI[ Three aggregates for the same value of subtype Matrix(1..2,1..3) (see @RefSecNum{Array Types}):] ((1.1, 1.2, 1.3), (2.1, 2.2, 2.3)) (1 => (1.1, 1.2, 1.3), 2 => (2.1, 2.2, 2.3)) (1 => (1 => 1.1, 2 => 1.2, 3 => 1.3), 2 => (1 => 2.1, 2 => 2.2, 3 => 2.3)) @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of aggregates as initial values:) @end{WideAbove} @begin{Example} A : Table := (7, 9, 5, 1, 3, 2, 4, 8, 6, 0); --@RI[ A(1)=7, A(10)=0] B : Table := (2 | 4 | 10 => 1, @key(others) => 0); --@RI[ B(1)=0, B(10)=1] C : @key(constant) Matrix := (1 .. 5 => (1 .. 8 => 0.0)); --@RI[ C'Last(1)=5, C'Last(2)=8] D : Bit_Vector(M .. N) := (M .. N => True); --@RI[ see @RefSecNum{Array Types}] E : Bit_Vector(M .. N) := (@key(others) => True); F : String(1 .. 1) := (1 => 'F'); --@RI[ a one component aggregate: same as "F"] @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T],Text=[@i{Example of an array aggregate with defaulted others choice and with an applicable index constraint provided by an enclosing record aggregate:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Buffer'(Size => 50, Pos => 1, Value => String'('x', @key(others) => <>)) --@RI[ see @RefSecNum{Discriminants}]]} @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @ChgAdded{Version=[1],Type=[Leading],Text=[@Defn{incompatibilities with Ada 83} In Ada 95, no applicable index constraint is defined for a parameter in a call to a generic formal subprogram; thus, some aggregates that are legal in Ada 83 are illegal in Ada 95. For example:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @Chg{New=[@key[subtype] S3 @key[is] String (1 .. 3); ... @key[generic] @key[with function] F (The_S3 : @key[in] S3) @key[return] Integer; @key[package] Gp @key[is] I : constant Integer := F ((1 => '!', others => '?')); -- @RI{The aggregate is legal in Ada 83, illegal in Ada 95.} @key[end] Gp;],Old=[]} @end{Example} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00016} @Chg{New=[This change eliminates generic contract model problems.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} We now allow "named with others" aggregates in all contexts where there is an applicable index constraint, effectively eliminating what was RM83-4.3.2(6). Sliding never occurs on an aggregate with others, because its bounds come from the applicable index constraint, and therefore already match the bounds of the target. The legality of an @key(others) choice is no longer affected by the staticness of the applicable index constraint. This substantially simplifies several rules, while being slightly more flexible for the user. It obviates the rulings of AI83-00244 and AI83-00310, while taking advantage of the dynamic nature of the "extra values" check required by AI83-00309. Named array aggregates are permitted even if the index type is descended from a formal scalar type. See @RefSecNum(Static Expressions and Static Subtypes) and AI83-00190. @end{Extend83} @begin{DiffWord83} We now separate named and positional array aggregate syntax, since, unlike other aggregates, named and positional associations cannot be mixed in array aggregates (except that an @key(others) choice is allowed in a positional array aggregate). We have also reorganized the presentation to handle multidimensional and one-dimensional aggregates more uniformly, and to incorporate the rulings of AI83-00019, AI83-00309, etc. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}<> can be used in place of an @nt{expression} in an @nt{array_aggregate}, default-initializing the component.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Limited @nt{array_aggregate}s are allowed (since all kinds of aggregates can now be limited, see @RefSecNum{Aggregates}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Fixed @nt{aggregate}s to use the subtype of the return object of a function, rather than the result subtype, because they can be different for an @nt{extended_return_statement}, and we want to use the subtype that's explicitly in the code at the point of the @nt{expression}.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0037-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Fixed so the check for components outside of the array applies to both @nt<expression>s and <>s. As <> was a new feature in Ada 2005, there should be little existing code that depends on a <> component that is specified outside of the array (and that is nonsense anyway, that a compiler is likely to detect even without an explicit language rule disallowing it).]} @end{Inconsistent2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[Added a definition of the applicable index constraint for @nt{conditional_expression}s (which are new).]} @end{DiffWord2005} @LabeledClause{Expressions} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0147-1],ARef=[AI05-0158-1],ARef=[AI05-0176-1]} @Defn{expression} An @i(expression) is a formula that defines the computation or retrieval of a value. In this International Standard, the term @lquotes@;expression@rquotes@; refers to a construct of the syntactic category @nt<expression> or of any of the @Chg{Version=[3],New=[following categories: @nt{choice_expression}, @nt{choice_relation}, @nt{relation}, @nt{simple_expression}, @nt{term}, @nt{factor}, @nt{primary}, @nt{conditional_expression}, @nt{quantified_expression}],Old=[other five syntactic categories defined below]}. @Defn{and operator}@Defn2{Term=[operator],Sec=(and)} @Defn{or operator}@Defn2{Term=[operator],Sec=(or)} @Defn{xor operator}@Defn2{Term=[operator],Sec=(xor)} @Defn{and then (short-circuit control form)} @Defn{or else (short-circuit control form)} @Defn{= operator}@Defn2{Term=[operator],Sec=(=)} @Defn{equal operator}@Defn2{Term=[operator],Sec=(equal)} @Defn{/= operator}@Defn2{Term=[operator],Sec=(/=)} @Defn{not equal operator}@Defn2{Term=[operator],Sec=(not equal)} @Defn{< operator}@Defn2{Term=[operator],Sec=(<)} @Defn{less than operator}@Defn2{Term=[operator],Sec=(less than)} @Defn{<= operator}@Defn2{Term=[operator],Sec=(<=)} @Defn{less than or equal operator}@Defn2{Term=[operator],Sec=(less than or equal)} @Defn{> operator}@Defn2{Term=[operator],Sec=(>)} @Defn{greater than operator}@Defn2{Term=[operator],Sec=(greater than)} @Defn{>= operator}@Defn2{Term=[operator],Sec=(>=)} @Defn{greater than or equal operator}@Defn2{Term=[operator],Sec=(greater than or equal)} @Defn{in (membership test)} @Defn{not in (membership test)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} @Defn{& operator}@Defn2{Term=[operator],Sec=(&)} @Defn{ampersand operator}@Defn2{Term=[operator],Sec=(ampersand)} @Defn{concatenation operator}@Defn2{Term=[operator],Sec=(concatenation)} @IndexSee{Term=[catenation operator],See=(concatenation operator)} @Defn{* operator}@Defn2{Term=[operator],Sec=(*)} @Defn{multiply operator}@Defn2{Term=[operator],Sec=(multiply)} @Defn{times operator}@Defn2{Term=[operator],Sec=(times)} @Defn{/ operator}@Defn2{Term=[operator],Sec=(/)} @Defn{divide operator}@Defn2{Term=[operator],Sec=(divide)} @Defn{mod operator}@Defn2{Term=[operator],Sec=(mod)} @Defn{rem operator}@Defn2{Term=[operator],Sec=(rem)} @Defn{** operator}@Defn2{Term=[operator],Sec=(**)} @Defn{exponentiation operator}@Defn2{Term=[operator],Sec=(exponentiation)} @Defn{abs operator}@Defn2{Term=[operator],Sec=(abs)} @Defn{absolute value} @Defn{not operator}@Defn2{Term=[operator],Sec=(not)} @end{Intro} @begin{Syntax} @Syn{tabs=[P23], lhs=<expression>,rhs=" @Syn2{relation} {@key{and} @Syn2{relation}} @\| @Syn2{relation} {@key{and} @key{then} @Syn2{relation}} | @Syn2{relation} {@key{or} @Syn2{relation}} @\| @Syn2{relation} {@key{or} @key{else} @Syn2{relation}} | @Syn2{relation} {@key{xor} @Syn2{relation}}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<choice_expression>,Old=<>}>, rhs="@Chg{Version=[3],New=< @Syn2[choice_relation] {@key[and] @Syn2[choice_relation]} | @Syn2[choice_relation] {@key[or] @Syn2[choice_relation]} | @Syn2[choice_relation] {@key[xor] @Syn2[choice_relation]} | @Syn2[choice_relation] {@key[and then] @Syn2[choice_relation]} | @Syn2[choice_relation] {@key[or else] @Syn2[choice_relation]}>,Old=<>}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<choice_relation>,Old=<>}>, rhs="@Chg{Version=[3],New=< @Syn2{simple_expression} [@Syn2{relational_operator} @Syn2{simple_expression}]>,Old=<>}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1]} @Syn{lhs=<relation>,rhs=" @Syn2{simple_expression} [@Syn2{relational_operator} @Syn2{simple_expression}] | @Syn2{simple_expression} [@key{not}] @key{in} @Chg{Version=[3],New=[@Syn2{membership_choice_list}],Old="@Syn2{range} | @Syn2{simple_expression} [@key{not}] @key{in} @Syn2{subtype_mark}"}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<membership_choice_list>,Old=<>}>, rhs="@Chg{Version=[3],New=<@Syn2{membership_choice} {| @Syn2{membership_choice}}>,Old=<>}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<membership_choice>,Old=<>}>, rhs="@Chg{Version=[3],New=<@Syn2{choice_expression} | @Syn2{range} | @Syn2{subtype_mark}>,Old=<>}"} @Syn{lhs=<simple_expression>,rhs="[@Syn2{unary_adding_operator}] @Syn2{term} {@Syn2{binary_adding_operator} @Syn2{term}}"} @Syn{lhs=<term>,rhs="@Syn2{factor} {@Syn2{multiplying_operator} @Syn2{factor}}"} @Syn{lhs=<factor>,rhs="@Syn2{primary} [** @Syn2{primary}] | @key{abs} @Syn2{primary} | @key{not} @Syn2{primary}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0003-1],ARef=[AI05-0147-1],ARef=[AI05-0176-1]} @Syn{lhs=<primary>,rhs=" @Syn2{numeric_literal} | @key{null} | @Syn2{string_literal} | @Syn2{aggregate} | @Syn2{name} | @Chg{Version=[3],New=[],Old=[@Syn2{qualified_expression} | ]}@Syn2{allocator} | (@Syn2{expression})@Chg{Version=[3],New=[ | (@Syn2{conditional_expression}) | (@Syn2{quantified_expression})],Old=[]}"} @end{Syntax} @begin{Resolution} A @nt<name> used as a @nt<primary> shall resolve to denote an object or a value. @begin{Discussion} This replaces RM83-4.4(3). We don't need to mention named numbers explicitly, because the name of a named number denotes a value. We don't need to mention attributes explicitly, because attributes now denote (rather than yield) values in general. Also, the new wording allows attributes that denote objects, which should always have been allowed (in case the implementation chose to have such a thing). @end{Discussion} @begin{Reason} It might seem odd that this is an overload resolution rule, but it is relevant during overload resolution. For example, it helps ensure that a @nt<primary> that consists of only the identifier of a parameterless function is interpreted as a @nt<function_call> rather than directly as a @nt<direct_name>. @end{Reason} @end{Resolution} @begin{StaticSem} Each expression has a type; it specifies the computation or retrieval of a value of that type. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(primary that is a name)} The value of a @nt<primary> that is a @nt{name} denoting an object is the value of the object. @end{RunTime} @begin{ImplPerm} @IndexCheck{Overflow_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} For the evaluation of a @nt<primary> that is a @nt<name> denoting an object of an unconstrained numeric subtype, if the value of the object is outside the base range of its type, the implementation may either raise Constraint_Error or return the value of the object. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This means that if extra-range intermediates are used to hold the value of an object of an unconstrained numeric subtype, a Constraint_Error can be raised on a read of the object, rather than only on an assignment to it. Similarly, it means that computing the value of an object of such a subtype can be deferred until the first read of the object (presuming no side effects other than failing an Overflow_Check are possible). This permission is over and above that provided by @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Exceptions and Optimization), since this allows the Constraint_Error to move to a different handler. @end{Ramification} @begin{Reason} This permission is intended to allow extra-range registers to be used efficiently to hold parameters and local variables, even if they might need to be transferred into smaller registers for performing certain predefined operations. @end{Reason} @begin{Discussion} There is no need to mention other kinds of @nt<primary>s, since any Constraint_Error to be raised can be @lquotes@;charged@rquotes@; to the evaluation of the particular kind of @nt<primary>. @end{Discussion} @end{ImplPerm} @begin{Examples} @Leading@keepnext@i(Examples of primaries:) @begin{Example} @Trailing@;4.0 --@RI[ real literal] Pi --@RI[ named number] (1 .. 10 => 0) --@RI[ array aggregate] Sum --@RI[ variable] Integer'Last --@RI[ attribute] Sine(X) --@RI[ function call] Color'(Blue) --@RI[ qualified expression] Real(M*N) --@RI[ conversion] (Line_Count + 10) --@RI[ parenthesized expression ] @end{Example} @leading@keepnext@i(Examples of expressions:) @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} Volume --@RI[ primary] @key(not) Destroyed --@RI[ factor] 2*Line_Count --@RI[ term] -4.0 --@RI[ simple expression] -4.0 + A --@RI[ simple expression] B**2 - 4.0*A*C --@RI[ simple expression]@Chg{Version=[2],New=[ R*Sin(@unicode<952>)*Cos(@unicode<966>) --@RI[ simple expression]],Old=[]} Password(1 .. 3) = "Bwv" --@RI[ relation] Count @key(in) Small_Int --@RI[ relation] Count @key(not) @key(in) Small_Int --@RI[ relation] Index = 0 @key(or) Item_Hit --@RI[ expression] (Cold @key(and) Sunny) @key(or) Warm --@RI[ expression (parentheses are required)] A**(B**C) --@RI[ expression (parentheses are required)] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, @key{out} parameters and their nondiscriminant subcomponents are not allowed as @ntf{primaries}. These restrictions are eliminated in Ada 95. In various contexts throughout the language where Ada 83 syntax rules had @nt<simple_expression>, the corresponding Ada 95 syntax rule has @nt<expression> instead. This reflects the inclusion of modular integer types, which makes the logical operators "@key[and]", "@key[or]", and "@key[xor]" more useful in expressions of an integer type. Requiring parentheses to use these operators in such contexts seemed unnecessary and potentially confusing. Note that the bounds of a @nt<range> still have to be specified by @nt<simple_expression>s, since otherwise @nt<expression>s involving membership tests might be ambiguous. Essentially, the operation ".." is of higher precedence than the logical operators, and hence uses of logical operators still have to be parenthesized when used in a bound of a range. @end{Extend83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[Moved @nt{qualified_expression} from @nt{primary} to @nt{name} (see @RefSecNum{Names}). This allows the use of @nt{qualified_expression}s in more places.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[Added @nt{conditional_expression} and @nt{quantified_expression} to @nt{primary}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[Expanded membership test syntax (see @RefSecNum{Relational Operators and Membership Tests}).]} @end{DiffWord2005} @LabeledClause{Operators and Expression Evaluation} @begin{Intro} @Redundant[@Defn{precedence of operators} @Defn{operator precedence} The language defines the following six categories of operators (given in order of increasing precedence). The corresponding @nt<operator_symbol>s, and only those, can be used as @nt<designator>s in declarations of functions for user-defined operators. See @RefSec(Overloading of Operators).] @end{Intro} @begin{Syntax} @Syn{tabs=[P36], lhs=<logical_operator>, rhs="@\ @key{and} | @key{or} | @key{xor}"} @Syn{tabs=[P36], lhs=<relational_operator>,rhs="@\ = | /= | < | <= | > | >="} @Syn{tabs=[P36], lhs=<binary_adding_operator>,rhs="@\ + | @en | &"} @Syn{tabs=[P36], lhs=<unary_adding_operator>,rhs="@\ + | @en"} @Syn{tabs=[P36], lhs=<multiplying_operator>,rhs="@\ * | / | @key{mod} | @key{rem}"} @Syn{tabs=[P36], lhs=<highest_precedence_operator>,rhs="@\ ** | @key{abs} | @key{not}"} @begin(Discussion) Some of the above syntactic categories are not used in other syntax rules. They are just used for classification. The others are used for both classification and parsing. @end(Discussion) @end{Syntax} @begin{StaticSem} For a sequence of operators of the same precedence level, the operators are associated with their operands in textual order from left to right. Parentheses can be used to impose specific associations. @begin{Discussion} The left-associativity is not directly inherent in the grammar of @RefSecNum{Expressions}, though in @RefSecNum{Method of Description and Syntax Notation} the definition of the metasymbols @b({}) implies left associativity. So this could be seen as redundant, depending on how literally one interprets the definition of the @b({}) metasymbols. See the Implementation Permissions below regarding flexibility in reassociating operators of the same precedence. @end{Discussion} @Defn{predefined operator}@Defn2{Term=[operator],Sec=(predefined)} For each form of type definition, certain of the above operators are @i(predefined); that is, they are implicitly declared immediately after the type definition. @Defn{binary operator}@Defn2{Term=[operator],Sec=(binary)} @Defn{unary operator}@Defn2{Term=[operator],Sec=(unary)} For each such implicit operator declaration, the parameters are called Left and Right for @i(binary) operators; the single parameter is called Right for @i(unary) operators. @redundant[An expression of the form X op Y, where op is a binary operator, is equivalent to a @nt<function_call> of the form "op"(X, Y). An expression of the form op Y, where op is a unary operator, is equivalent to a @nt<function_call> of the form "op"(Y). The predefined operators and their effects are described in subclauses @RefSecNum(Logical Operators and Short-Circuit Control Forms) through @RefSecNum(Highest Precedence Operators).] @end{StaticSem} @begin{RunTime} @redundant[@Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The predefined operations on integer types either yield the mathematically correct result or raise the exception Constraint_Error. For implementations that support the Numerics Annex, the predefined operations on real types yield results whose accuracy is defined in @RefSecNum(Numerics), or raise the exception Constraint_Error. ] @begin{Honest} Predefined operations on real types can @lquotes@;silently@rquotes@; give wrong results when the Machine_Overflows attribute is false, and the computation overflows. @end{Honest} @end{RunTime} @begin{ImplReq} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of a predefined operator that delivers a result of an integer or fixed point type may raise Constraint_Error only if the result is outside the base range of the result type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of a predefined operator that delivers a result of a floating point type may raise Constraint_Error only if the result is outside the safe range of the result type. @begin{Honest} An exception is made for exponentiation by a negative exponent in @RefSecNum{Highest Precedence Operators}. @end{Honest} @end{ImplReq} @begin{ImplPerm} For a sequence of predefined operators of the same precedence level (and in the absence of parentheses imposing a specific association), an implementation may impose any association of the operators with operands so long as the result produced is an allowed result for the left-to-right association, but ignoring the potential for failure of language-defined checks in either the left-to-right or chosen order of association. @begin{Discussion} Note that the permission to reassociate the operands in any way subject to producing a result allowed for the left-to-right association is not much help for most floating point operators, since reassociation may introduce significantly different round-off errors, delivering a result that is outside the model interval for the left-to-right association. Similar problems arise for division with integer or fixed point operands. Note that this permission does not apply to user-defined operators. @end{Discussion} @end{ImplPerm} @begin{Notes} The two operands of an expression of the form X op Y, where op is a binary operator, are evaluated in an arbitrary order, as for any @nt<function_call> (see @RefSecNum(Subprogram Calls)). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of precedence:) @begin{Example} @key(not) Sunny @key(or) Warm --@RI[ same as (not Sunny) or Warm] X > 4.0 @key(and) Y > 0.0 --@RI[ same as (X > 4.0) and (Y > 0.0)] -4.0*A**2 --@RI[ same as @en@;(4.0 * (A**2))] @key(abs)(1 + A) + B --@RI[ same as (abs (1 + A)) + B] Y**(-3) --@RI[ parentheses are necessary] A / B * C --@RI[ same as (A/B)*C] A + (B + C) --@RI[ evaluate B + C before adding it to A ] @end{Example} @end{Examples} @begin{DiffWord83} We don't give a detailed definition of precedence, since it is all implicit in the syntax rules anyway. The permission to reassociate is moved here from RM83-11.6(5), so it is closer to the rules defining operator association. @end{DiffWord83} @LabeledSubClause{Logical Operators and Short-circuit Control Forms} @begin{Resolution} @Defn{short-circuit control form} @Defn{and then (short-circuit control form)} @Defn{or else (short-circuit control form)} An @nt<expression> consisting of two @nt<relation>s connected by @key(and then) or @key(or else) (a @i(short-circuit control form)) shall resolve to be of some boolean type; @PDefn2{Term=[expected type],Sec=(short-circuit control form relation)} the expected type for both @nt<relation>s is that same boolean type. @begin(Reason) This rule is written this way so that overload resolution treats the two operands symmetrically; the resolution of overloading present in either one can benefit from the resolution of the other. Furthermore, the type expected by context can help. @end(Reason) @end{Resolution} @begin{StaticSem} @Leading@Defn{logical operator}@Defn2{Term=[operator],Sec=(logical)} @Defn{and operator}@Defn2{Term=[operator],Sec=(and)} @Defn{or operator}@Defn2{Term=[operator],Sec=(or)} @Defn{xor operator}@Defn2{Term=[operator],Sec=(xor)} The following logical operators are predefined for every boolean type @i(T), for every modular type @i(T), and for every one-dimensional array type @i(T) whose component type is a boolean type: @IndexSee{Term=[bit string],See=(logical operators on boolean arrays)} @begin{example} @tabclear() @key[function] "@key(and)"(Left, Right : @RI(T)) @key[return] @RI(T) @key[function] "@key(or)" (Left, Right : @RI(T)) @key[return] @RI(T) @key[function] "@key(xor)"(Left, Right : @RI(T)) @key[return] @RI(T) @end{example} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00145-01]} @ChgDeleted{Version=[2],Text=[For predefined operators, the parameter and result subtypes shown as @i(T) are actually the unconstrained subtype of the type.]} @ChgNote{Sorry, Bob, but there is no "honesty" issue here. And "unconstrained" is wrong.} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[For these operators, we are talking about the type without any (interesting) subtype, and not some subtype with a constraint or exclusion. Since it's possible that there is no name for the @lquotes@;uninteresting@rquotes subtype, we denote the type with an italicized @i(T). This applies to the italicized @i(T) in many other predefined operators and attributes as well.@Defn2{Term=[T],Sec=[italicized]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[In many cases, there is a subtype with the correct properties available. The italicized @i(T) means:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i(T)'Base, for scalars;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the first subtype of @i(T), for tagged types;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a subtype of the type @i(T) without any constraint or null exclusion, in other cases.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that @lquotes@;without a constraint@rquotes is not the same as unconstrained. For instance, a record type with no discriminant part is considered constrained; no subtype of it has a constraint, but the subtype is still constrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, the last case often is the same as the first subtype of @i(T), but that isn't the case for constrained array types (where the correct subtype is unconstrained) and for access types with a @nt{null_exclusion} (where the correct subtype does not exclude null).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This italicized @i(T) is used for defining operators and attributes of the language. The meaning is intended to be as described here.]} @end{Ramification} For boolean types, the predefined logical operators @key{and}, @key{or}, and @key{xor} perform the conventional operations of conjunction, inclusive disjunction, and exclusive disjunction, respectively. For modular types, the predefined logical operators are defined on a bit-by-bit basis, using the binary representation of the value of the operands to yield a binary representation for the result, where zero represents False and one represents True. If this result is outside the base range of the type, a final subtraction by the modulus is performed to bring the result into the base range of the type. The logical operators on arrays are performed on a component-by-component basis on matching components (as for equality @em see @RefSecNum{Relational Operators and Membership Tests}), using the predefined logical operator for the component type. The bounds of the resulting array are those of the left operand. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(short-circuit control form)} The short-circuit control forms @key{and then} and @key{or else} deliver the same result as the corresponding predefined @key{and} and @key{or} operators for boolean types, except that the left operand is always evaluated first, and the right operand is not evaluated if the value of the left operand determines the result. @IndexCheck{Length_Check} For the logical operators on arrays, a check is made that for each component of the left operand there is a matching component of the right operand, and vice versa. @IndexCheck{Range_Check} Also, a check is made that each component of the result belongs to the component subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if either of the above checks fails. @begin{Discussion} The check against the component subtype is per AI83-00535. @end{Discussion} @end{RunTime} @begin{Notes} @Leading@;The conventional meaning of the logical operators is given by the following truth table: @begin(Display) @TabClear() @TabSet(P4, P20, P36, P52, P68) @\@ @ A@\@ @ B@\(A @key(and) B)@\(A @key(or) B)@\(A @key(xor) B)@* @\True @\True @\True @\True @\False @\True @\False @\False @\True @\True @\False @\True @\False @\True @\True @\False @\False @\False @\False @\False @end(Display) @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of logical operators:) @begin{Example} Sunny @key(or) Warm Filter(1 .. 10) @key(and) Filter(15 .. 24) --@RI[ see @RefSecNum{Index Constraints and Discrete Ranges} ] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of short-circuit control forms:) @end{WideAbove} @begin{Example} Next_Car.Owner /= @key(null) @key(and) @key(then) Next_Car.Owner.Age > 25 --@RI[ see @RefSecNum{Incomplete Type Declarations}] N = 0 @key(or) @key(else) A(N) = Hit_Value @end{Example} @end{Examples} @LabeledSubClause{Relational Operators and Membership Tests} @begin{Intro} @redundant[@Defn{relational operator}@Defn2{Term=[operator],Sec=(relational)} @IndexSee{Term=[comparison operator],See=(relational operator)} @Defn{equality operator}@Defn2{Term=[operator],Sec=(equality)} The @i(equality operators) = (equals) and /= (not equals) are predefined for nonlimited types. @Defn{ordering operator}@Defn2{Term=[operator],Sec=(ordering)} The other @nt<relational_operator>s are the @i(ordering operators) < (less than), <= (less than or equal), > (greater than), and >= (greater than or equal). @Defn{= operator}@Defn2{Term=[operator],Sec=(=)} @Defn{equal operator}@Defn2{Term=[operator],Sec=(equal)} @Defn{/= operator}@Defn2{Term=[operator],Sec=(/=)} @Defn{not equal operator}@Defn2{Term=[operator],Sec=(not equal)} @Defn{< operator}@Defn2{Term=[operator],Sec=(<)} @Defn{less than operator}@Defn2{Term=[operator],Sec=(less than)} @Defn{<= operator}@Defn2{Term=[operator],Sec=(<=)} @Defn{less than or equal operator}@Defn2{Term=[operator],Sec=(less than or equal)} @Defn{> operator}@Defn2{Term=[operator],Sec=(>)} @Defn{greater than operator}@Defn2{Term=[operator],Sec=(greater than)} @Defn{>= operator}@Defn2{Term=[operator],Sec=(>=)} @Defn{greater than or equal operator}@Defn2{Term=[operator],Sec=(greater than or equal)} @Defn{discrete array type} The ordering operators are predefined for scalar types, and for @i(discrete array types), that is, one-dimensional array types whose components are of a discrete type. @begin{Ramification} The equality operators are not defined for @i{every} nonlimited type @em see below for the exact rule. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @Defn{membership test} @Defn{in (membership test)} @Defn{not in (membership test)} A @i(membership test), using @key(in) or @key(not in), determines whether or not a value belongs to @chg{Version=[3],New=[any],Old=[a]} given subtype or range, @chg{Version=[3],New=[is equal to any given value,],Old=[or]} has a tag that identifies a type that is covered by a given type@chg{Version=[3],New=[, or is convertible to and has an accessibility level appropriate for a given access type],Old=[]}. Membership tests are allowed for all types.] @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1]} @PDefn2{Term=[expected type], Sec=(membership test simple_expression)} @Defn2{Term=[tested type], Sec=(of a membership test)} The @i(tested type) of a membership test is@Chg{Version=[3],New=[],Old=[ the type of the @nt<range> or the type]} determined by the @Chg{Version=[3],New=[@nt<membership_choice>s of the @nt<membership_choice_list>. Either all @nt{membership_choice}s of the @nt{membership_choice_list} shall resolve to the same type, which is the tested type; or each @nt{membership_choice} shall be of an elementary type, and the tested type shall be covered by each of these elementary types.],Old=[@nt<subtype_mark>. If the tested type is tagged, then the @nt<simple_expression> shall resolve to be of a type that @Chg{Version=[2],New=[is convertible (see @RefSecNum{Type Conversions}) to],Old=[covers or is covered by]} the tested type; if untagged, the expected type for the @nt<simple_expression> is the tested type.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[If the tested type is tagged, then the @nt{simple_expression} shall resolve to be of a type that is convertible (see @RefSecNum{Type Conversions}) to the tested type; if untagged, the expected type for the @nt{simple_expression} is the tested type. The expected type of a @nt{choice_expression} in a @nt{membership_choice}, and of a @nt{simple_expression} of a @nt{range} in a @nt{membership_choice}, is the tested type of the membership operation.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The part of the rule for untagged types is stated in a way that ensures that operands like @Chg{Version=[2],New=[a string literal],Old=[@key(null)]} are still legal as operands of a membership test. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The significance of @lquotes@;@Chg{Version=[2],New=[is convertible to], Old=[covers or is covered by]}@rquotes@; is that we allow the @nt<simple_expression> to be of any class-wide type that @Chg{Version=[2], New=[could be converted to],Old=[covers]} the tested type, not just the one rooted at the tested type.@Chg{Version=[2],New=[ This includes any class-wide type that covers the tested type, along with class-wide interfaces in some cases.],Old=[]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[The special rule for determining the tested type for elementary types is to allow numeric literals in @nt{membership_choice_list}s. Without the rule, @exam{A @key[in] B | 1} would be illegal as B and 1 would have different types (the literal having type @i<universal integer>).]} @end{Reason} @end{Resolution} @begin{Legality} For a membership test, if the @nt<simple_expression> is of a tagged class-wide type, then the tested type shall be (visibly) tagged. @begin{Ramification} Untagged types covered by the tagged class-wide type are not permitted. Such types can exist if they are descendants of a private type whose full type is tagged. This rule is intended to avoid confusion since such derivatives don't have their @lquotes@;own@rquotes@; tag, and hence are indistinguishable from one another at run time once converted to a covering class-wide type. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[If a membership test includes one or more @nt{choice_expression}s and the tested type of the membership test is limited, then the tested type of the membership test shall have a visible primitive equality operator.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[A visible equality operator is required in order to avoid breaking privacy; that is, we don't want to depend on a hidden equality operator.]} @end{Reason} @end{Legality} @begin{StaticSem} The result type of a membership test is the predefined type Boolean. @Leading@;The equality operators are predefined for every specific type @i(T) that is not limited, and not an anonymous access type, with the following specifications: @begin(example) @key(function) "=" (Left, Right : @RI(T)) @key(return) Boolean @key(function) "/="(Left, Right : @RI(T)) @key(return) Boolean @end(example) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following additional equality operators for the @i<universal_access> type are declared in package Standard for use with anonymous access types:]} @begin(example) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> "=" (Left, Right : @i<universal_access>) @key<return> Boolean @key<function> "/="(Left, Right : @i<universal_access>) @key<return> Boolean]} @end(example) @Leading@;The ordering operators are predefined for every specific scalar type @i(T), and for every discrete array type @i(T), with the following specifications: @begin(example) @key(function) "<" (Left, Right : @RI(T)) @key(return) Boolean @key(function) "<="(Left, Right : @RI(T)) @key(return) Boolean @key(function) ">" (Left, Right : @RI(T)) @key(return) Boolean @key(function) ">="(Left, Right : @RI(T)) @key(return) Boolean @end(example) @end{StaticSem} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[At least one of the operands of an equality operator for @i<universal_access> shall be of a specific anonymous access type. Unless the predefined equality operator is identified using an expanded name with @nt{prefix} denoting the package Standard, neither operand shall be of an access-to-object type whose designated type is @i<D> or @i<D>'Class, where @i<D> has a user-defined primitive equality operator such that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[its result type is Boolean;]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0020-1]} @ChgAdded{Version=[2],Text=[it is declared immediately within the same declaration list as @i<D>@Chg{Version=[3],New=[ or any partial or incomplete view of @i<D>],Old=[]}; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[at least one of its operands is an access parameter with designated type @i<D>.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The first sentence prevents compatibility problems by ensuring that these operators are not used for named access types. Also, universal access types do not count for the purposes of this rule. Otherwise, equality expressions like (X = @key{null}) would be ambiguous for normal access types.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rest of the rule makes it possible to call (including a dispatching call) user-defined "=" operators for anonymous access-to-object types (they'd be hidden otherwise), and to write user-defined "=" operations for anonymous access types (by making it possible to see the universal operator using the Standard prefix).]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't need a similar rule for anonymous access-to-subprogram types because they can't be primitive for any type. Note that any nonprimitive user-defined equality operators still are hidden by the universal operators; they'll have to be called with a package prefix, but they are likely to be very uncommon.]} @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[At least one of the operands of the equality operators for @i<universal_access> shall be of type @i<universal_access>, or both shall be of access-to-object types, or both shall be of access-to-subprogram types. Further:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[When both are of access-to-object types, the designated types shall be the same or one shall cover the other, and if the designated types are elementary or array types, then the designated subtypes shall statically match;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[When both are of access-to-subprogram types, the designated profiles shall be subtype conformant.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't want to allow completely arbitrary comparisons, as we don't want to insist that all access types are represented in ways that are convertible to one another. For instance, a compiler could use completely separate address spaces or incompatible representations. Instead, we allow compares if there exists an access parameter to which both operands could be converted. Since the user could write such an subprogram, and any reasonable meaning for "=" would allow using it in such a subprogram, this doesn't impose any further restrictions on Ada implementations.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[If the profile of an explicitly declared primitive equality operator of an untagged record type is type conformant with that of the corresponding predefined equality operator, the declaration shall occur before the type is frozen. In addition, if the untagged record type has a nonlimited partial view, then the declaration shall occur in the visible part of the enclosing package. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @end{Legality} @begin{RunTime} For discrete types, the predefined relational operators are defined in terms of corresponding mathematical operations on the position numbers of the values of the operands. For real types, the predefined relational operators are defined in terms of the corresponding mathematical operations on the values of the operands, subject to the accuracy of the type. @begin{Ramification} For floating point types, the results of comparing @i(nearly) equal values depends on the accuracy of the implementation (see @RefSec{Model of Floating Point Arithmetic} for implementations that support the Numerics Annex). @end{Ramification} @begin{ImplNote} On a machine with signed zeros, if the generated code generates both plus zero and minus zero, plus and minus zero must be equal by the predefined equality operators. @end{ImplNote} Two access-to-object values are equal if they designate the same object, or if both are equal to the null value of the access type. Two access-to-subprogram values are equal if they are the result of the same evaluation of an Access @nt<attribute_reference>, or if both are equal to the null value of the access type. Two access-to-subprogram values are unequal if they designate different subprograms. @PDefn{unspecified} @Redundant[It is unspecified whether two access values that designate the same subprogram but are the result of distinct evaluations of Access @nt<attribute_reference>s are equal or unequal.] @begin{Reason} This allows each Access @nt<attribute_reference> for a subprogram to designate a distinct @lquotes@;wrapper@rquotes@; subprogram if necessary to support an indirect call. @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} @Defn2{Term=[equality operator],Sec=(special inheritance rule for tagged types)} For a type extension, predefined equality is defined in terms of the primitive @Redundant[(possibly user-defined)] equals operator @Chg{Version=[3],New=[for],Old=[of]} the parent type and @Chg{Version=[3],New=[for],Old=[of]} any @Chg{Version=[3],New=[],Old=[tagged ]}components @Chg{Version=[3],New=[that have a record type in],Old=[of]} the extension part, and predefined equality for any other components not inherited from the parent type. @begin{Ramification} Two values of a type extension are not equal if there is a @nt<variant_part> in the extension part and the two values have different @nt<variant>s present. This is a ramification of the requirement that a discriminant governing such a @nt<variant_part> has to be a @lquotes@;new@rquotes@; discriminant, and so has to be equal in the two values for the values to be equal. Note that @nt<variant_part>s in the parent part need not match if the primitive equals operator for the parent type considers them equal. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00349-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The full type extension's operation is used for a private extension. This follows as only full types have parent types; the type specified in a private extension is an ancestor, but not necessarily the parent type. For instance, in:]} @begin(Example) @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@key{with} Pak1; @key{package} Pak2 @key{is} @key{type} Typ3 @key{is} @key{new} Pak1.Typ1 @key{with} @key{private}; @key{private} @key{type} Typ3 @key{is} @key{new} Pak1.Typ2 @key{with} @key{null} @key{record}; @key{end} Pak2;],Old=[]} @end(Example) @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[the parent type is Pak1.Typ2, not Pak1.Typ1, and the equality operator of Pak1.Typ2 is used to create predefined equality for Typ3.],Old=[]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[For a derived type whose parent is an untagged record type, predefined equality is defined in terms of the primitive (possibly user-defined) equals operator of the parent type.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This prevents predefined equality from reemerging in generic units for untagged record types. For other uses the primitive equality is inherited and the inherited routine is primitive.]} @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} For a private type, if its full type is @Chg{Version=[3],New=[a record type],Old=[tagged]}, predefined equality is defined in terms of the primitive equals operator of the full type; @Chg{Version=[3],New=[otherwise],Old=[if the full type is untagged]}, predefined equality for the private type is that of its full type. @Leading@Defn{matching components} For other composite types, the predefined equality operators @Redundant[(and certain other predefined operations on composite types @em see @RefSecNum(Logical Operators and Short-circuit Control Forms) and @RefSecNum(Type Conversions))] are defined in terms of the corresponding operation on @i(matching components), defined as follows: @begin(itemize) For two composite objects or values of the same non-array type, matching components are those that correspond to the same @nt<component_declaration> or @nt<discriminant_specification>; For two one-dimensional arrays of the same type, matching components are those (if any) whose index values match in the following sense: the lower bounds of the index ranges are defined to match, and the successors of matching indices are defined to match; For two multidimensional arrays of the same type, matching components are those whose index values match in successive index positions. @end(itemize) The analogous definitions apply if the types of the two objects or values are convertible, rather than being the same. @begin{Discussion} Ada 83 seems to omit this part of the definition, though it is used in array type conversions. See @RefSecNum{Type Conversions}. @end{Discussion} @Leading@;Given the above definition of matching components, the result of the predefined equals operator for composite types (other than for those composite types covered earlier) is defined as follows: @begin(Itemize) If there are no components, the result is defined to be True; If there are unmatched components, the result is defined to be False; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} Otherwise, the result is defined in terms of the primitive equals operator for any matching @Chg{Version=[3],New=[],Old=[tagged ]}components@Chg{Version=[3],New=[ that are records],Old=[]}, and the predefined equals for any @Chg{Version=[3],New=[other ],Old=[]}matching @Chg{Version=[3],New=[],Old=[untagged ]}components. @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} This asymmetry between @Chg{Version=[3],New=[],Old=[tagged and untagged ]}components @Chg{Version=[3],New=[with and without a record type ],Old=[]}is necessary to preserve @Chg{Version=[3],New=[most ],Old=[]}upward compatibility and corresponds with the corresponding situation with generics, where the predefined operations @lquotes@;reemerge@rquotes@; in a generic for @Chg{Version=[3],New=[non-record],Old=[untagged]} types, but do not for @Chg{Version=[3],New=[record],Old=[tagged]} types. Also, only tagged types support user-defined assignment (see @RefSecNum{Assignment and Finalization}), so only tagged types can fully handle levels of indirection in the implementation of the type. For untagged types, one reason for a user-defined equals operator might be to allow values with different bounds or discriminants to compare equal in certain cases. When such values are matching components, the bounds or discriminants will necessarily match anyway if the discriminants of the enclosing values match. @end{Reason} @end(Itemize) @begin{Ramification} Two null arrays of the same type are always equal; two null records of the same type are always equal. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} Note that if a composite object has a component of a floating point type, and the floating point type has both a plus and minus zero, which are considered equal by the predefined equality, then a block compare cannot be used for the predefined composite equality. Of course, with user-defined equals operators for @Chg{Version=[3],New=[],Old=[tagged ]}components@Chg{Version=[3],New=[ that are records],Old=[]}, a block compare breaks down anyway, so this is not the only special case that requires component-by-component comparisons. On a one's complement machine, a similar situation might occur for integer types, since one's complement machines typically have both a plus and minus (integer) zero. @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For a component with an anonymous access type, @lquotes@;predefined equality@rquotes@; is that defined for the @i<universal_access> type (anonymous access types have no equality operators of their own).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} @ChgAdded{Version=[2],Text=[For a component with a @Chg{Version=[3],New=[record], Old=[tagged]} type @i{T}, @lquotes@;the primitive equals operator@rquotes@; is the one with two parameters of @i(T) which returns Boolean. We're not talking about some random other primitive function named "=".]} @end{Honest} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[If the primitive equals operator for an untagged record type is abstract, then Program_Error is raised at the point of any (implicit) call to that abstract subprogram.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An explicit call to an abstract subprogram is illegal. This rule is needed in order to define the effect of an implicit call such as a call that is part of the predefined equality operation for an enclosing composite type that has a component of an untagged record type that has an abstract primitive equals operator. For tagged types, an abstract primitive equals operator is only allowed for an abstract type, and abstract types cannot be components, so this case does not occur.]} @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0016],ARef=[AI95-00123-01]} @ChgAdded{Version=[1],Text=[For any composite type, the order in which "=" is called for components is unspecified. Furthermore, if the result can be determined before calling "=" on some components, it is unspecified whether "=" is called on those components.@PDefn{Unspecified}]} The predefined "/=" operator gives the complementary result to the predefined "=" operator. @begin{Ramification} Furthermore, if the user defines an "=" operator that returns Boolean, then a "/=" operator is implicitly declared in terms of the user-defined "=" operator so as to give the complementary result. See @RefSecNum(Overloading of Operators). @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn{lexicographic order} For a discrete array type, the predefined ordering operators correspond to @i(lexicographic order) using the predefined order relation of the component type: A null array is lexicographically less than any array having at least one component. In the case of nonnull arrays, the left operand is lexicographically less than the right operand if the first component of the left operand is less than that of the right; otherwise@Chg{Version=[3],New=[,],Old=[]} the left operand is lexicographically less than the right operand only if their first components are equal and the tail of the left operand is lexicographically less than that of the right (the @i(tail) consists of the remaining components beyond the first and can be null). @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[An @i<individual membership test> is the membership test of a single @nt{membership_choice}.@Defn{individual membership test}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1]} @PDefn2{Term=[evaluation], Sec=(membership test)} For the evaluation of a membership test@Chg{Version=[3],New=[ using @key[in] whose @nt{membership_choice_list} has a single @nt{membership_choice}],Old=[]}, the @nt<simple_expression> and the @Chg{Version=[3],New=[@nt{membership_choice}],Old=[@nt<range> (if any)]} are evaluated in an arbitrary order@Chg{Version=[3],New=[; the result is the result of the individual membership test for the @nt{membership_choice}],Old=[]}.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[For the evaluation of a membership test using @key[in] whose @nt{membership_choice_list} has more than one @nt{membership_choice}, the @nt{simple_expression} of the membership test is evaluated first and the result of the operation is equivalent to that of a sequence consisting of an individual membership test on each @nt{membership_choice} combined with the short-circuit control form @b[or else].]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[This equivalence includes the evaluation of the @nt{membership_choice}s; evaluation stops as soon as an individual choice evaluates to True.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1],ARef=[AI05-0269-1]} @Leading@;@Chg{Version=[3],New=[An individual membership test],Old=[A membership test using @key(in)]} yields the result True if: @begin(itemize) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[The @nt{membership_choice} is a @nt{choice_expression}, and the @nt{simple_expression} is equal to the value of the @nt{membership_choice}. If the tested type is a record type or a limited type, the test uses the primitive equality for the type; otherwise, the test uses predefined equality.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0153-3],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[The @nt{membership_choice} is a @nt{range} and the value of the @nt<simple_expression> belongs to the given @nt<range>.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0158-1]} @Chg{Version=[3],New=[The @nt{membership_choice} is a @nt{subtype_mark}, the],Old=[The]} tested type is scalar, @Chg{Version=[3],New=[],Old=[and ]}the value of the @nt<simple_expression> belongs to the @Chg{Version=[3],New=[],Old=[given @nt<range>, or the ]}range of the named subtype@Chg{Version=[3],New=[, and the predicate of the named subtype evaluates to True.@Defn2{Term=[predicate evaluated],Sec=[membership]}],Old=[; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} The scalar membership test only does a range check@Chg{Version=[3],New=[ and a predicate check],Old=[]}. It does not perform any other check, such as whether a value falls in a @lquotes@;hole@rquotes@; of a @lquotes@;holey@rquotes@; enumeration type. The Pos attribute function can be used for that purpose. Even though Standard.Float is an unconstrained subtype, the test @lquotes@;X in Float@rquotes@; will still return False (presuming the evaluation of X does not raise Constraint_Error) when X is outside Float'Range. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0158-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{To get conditional Leading} @Chg{Version=[3],New=[The @nt<membership_choice> is a @nt<subtype_mark>, the],Old=[The]} tested type is not scalar, @Chg{Version=[3],New=[],Old=[and ]} the value of the @nt<simple_expression> satisfies any constraints of the named subtype, @Chg{Version=[3],New=[the predicate of the named subtype evaluates to True, ],Old=[]}and@Chg{Version=[2],New=[:],Old=[, if the type of the @nt{simple_expression} is class-wide, the value has a tag that identifies a type covered by the tested type.]} @begin{Inneritemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[if the type of the @nt{simple_expression} is class-wide, the value has a tag that identifies a type covered by the tested type;]} @begin{Ramification} Note that the tag is not checked if the @nt{simple_expression} is of a specific type. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0149-1]} @ChgAdded{Version=[2],Text=[if the tested type is an access type and the named subtype excludes null, the value of the @nt{simple_expression} is not null@Chg{Version=[3],New=[;],Old=[.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[if the tested type is a general access-to-object type, the type of the @nt{simple_expression} is convertible to the tested type and its accessibility level is no deeper than that of the tested type; further, if the designated type of the tested type is tagged and the @nt{simple_expression} is nonnull, the tag of the object designated by the value of the @nt{simple_expression} is covered by the designated type of the tested type.]} @end{Inneritemize} @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Otherwise@Chg{Version=[3],New=[,],Old=[]} the test yields the result False. A membership test using @key(not in) gives the complementary result to the corresponding membership test using @key(in). @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[@exam{@i<X> @key[not in] @i<A> | @i<B> | @i<C>} is intended to be exactly equivalent to @exam{@key[not] (@i<X> @key[in] @i<A> | @i<B> | @i<C>)}, including the order of evaluation of the @nt{simple_expression} and @nt{membership_choice}s.]} @end{Honest} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0016],ARef=[AI95-00123-01]} @ChgAdded{Version=[1],Text=[For all nonlimited types declared in language-defined packages, the "=" and "/=" operators of the type shall behave as if they were the predefined equality operators for the purposes of the equality of composite types and generic formal types.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],ARef=[AI95-00123-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0123-1]} @ChgAdded{Version=[1],Text=[If any language-defined types are implemented with a user-defined "=" operator, then either the full type must be @Chg{Version=[3], New=[a record type],Old=[tagged]}, or the compiler must use @lquotes@;magic@rquotes@; to implement equality for this type. A normal user-defined "=" operator for @Chg{Version=[3],New=[a non-record],Old=[an untagged]} type does @i{not} meet this requirement.]} @end{Ramification} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00230-01]} @ChgDeleted{Version=[2],Text=[No exception is ever raised by a membership test, by a predefined ordering operator, or by a predefined equality operator for an elementary type, but an exception can be raised by the evaluation of the operands. A predefined equality operator for a composite type can only raise an exception if the type has a tagged part whose primitive equals operator propagates an exception.]} If a composite type has components that depend on discriminants, two values of this type have matching components if and only if their discriminants are equal. Two nonnull arrays have matching components if and only if the length of each dimension is the same for both. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving relational operators and membership tests:) @begin{Example} X /= Y "" < "A" @key(and) "A" < "Aa" --@RI[ True] "Aa" < "B" @key(and) "A" < "A " --@RI[ True] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} My_Car = @key(null) --@RI[ @Chg{Version=[3],New=[True],Old=[true]} if My_Car has been set to null (see @RefSecNum{Incomplete Type Declarations})] My_Car = Your_Car --@RI[ @Chg{Version=[3],New=[True],Old=[true]} if we both share the same car] My_Car.@key[all] = Your_Car.@key[all] --@RI[ @Chg{Version=[3],New=[True],Old=[true]} if the two cars are identical] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1]} N @key(not) @key(in) 1 .. 10 --@RI[ range membership test] Today @key(in) Mon .. Fri --@RI[ range membership test] Today @key(in) Weekday --@RI[ subtype membership test (see @RefSecNum{Enumeration Types})]@Chg{Version=[3],New=[ Card @key(in) Clubs | Spades --@RI[ list membership test (see @RefSecNum{Enumeration Types})]],Old=[]} Archive @key(in) Disk_Unit --@RI[ subtype membership test (see @RefSecNum{Variant Parts and Discrete Choices})] Tree.@key(all) @key(in) Addition'Class --@RI[ class membership test (see @RefSecNum{Type Extensions})] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Membership tests can be used to test the tag of a class-wide value. Predefined equality for a composite type is defined in terms of the primitive equals operator for tagged components or the parent part. @end{Extend83} @begin{DiffWord83} The term @lquotes@;membership test@rquotes@; refers to the @nt<relation> "X in S" rather to simply the reserved word @key(in) or @key(not in). We use the term @lquotes@;equality operator@rquotes@; to refer to both the = (equals) and /= (not equals) operators. Ada 83 referred to = as @i(the) equality operator, and /= as the inequality operator. The new wording is more consistent with the ISO 10646 name for "=" (equals sign) and provides a category similar to @lquotes@;ordering operator@rquotes@; to refer to both = and /=. We have changed the term @lquotes@;catenate@rquotes@; to @lquotes@;concatenate@rquotes@;. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}The @i{universal_access} equality operators are new. They provide equality operations (most importantly, testing against @key{null}) for anonymous access types.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0016],ARef=[AI95-00123-01]} @Chg{Version=[2],New=[@b<Corrigendum:> Wording was added to clarify that the order of calls (and whether the calls are made at all) on "=" for components is unspecified. Also clarified that "=" must compose properly for language-defined types.],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[Memberships were adjusted to allow interfaces which don't cover the tested type, in order to be consistent with type conversions.],Old=[]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} User-defined untagged record equality is now defined to compose and be used in generics. Any code which assumes that the predefined equality reemerges in generics and in predefined equals for composite types could fail. However, it is much more likely that this change will fix bugs, as the behavior that would be expected (the user-defined "=" is used) will be true in more cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[If a composite type contains a component of an untagged record type with an abstract equality operation, calling "=" on the composite type will raise Program_Error, while in the past a result will be returned using the predefined equality. This is quite possible in ASIS programs; it will detect a bug in such programs but of course the programs will need to be fixed before they will work.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Late and hidden overriding of equality for untagged record types is now prohibited. This is necessary to make composition of equality predictable. It should always be possible to move the overriding to an earlier spot where it will be legal.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Membership tests for valid accessibility levels and tag coverage by the designated type for general access types are new.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[Membership tests now include a predicate check.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[Membership tests now allow multiple choices.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0020-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Wording was added to clarify that @i{universal_access} "=" does not apply if an appropriate operator is declared for a partial or incomplete view of the designated type. Otherwise, adding a partial or incomplete view could make some "=" operators ambiguous.]} @end{DiffWord2005} @LabeledSubClause{Binary Adding Operators} @begin{StaticSem} @Leading@Defn{binary adding operator}@Defn2{Term=[operator],Sec=(binary adding)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} The binary adding operators + (addition) and @en (subtraction) are predefined for every specific numeric type @i(T) with their conventional meaning. They have the following specifications: @begin(example) @key(function) "+"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "-"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@Defn{& operator}@Defn2{Term=[operator],Sec=(&)} @Defn{ampersand operator}@Defn2{Term=[operator],Sec=(ampersand)} @Defn{concatenation operator}@Defn2{Term=[operator],Sec=(concatenation)} @IndexSee{Term=[catenation operator],See=(concatenation operator)} The concatenation operators & are predefined for every nonlimited, one-dimensional array type @i(T) with component type @i(C). They have the following specifications: @begin(example) @key(function) "&"(Left : @RI(T); Right : @RI(T)) @key(return) @RI(T) @key(function) "&"(Left : @RI(T); Right : @RI(C)) @key(return) @RI(T) @key(function) "&"(Left : @RI(C); Right : @RI(T)) @key(return) @RI(T) @key(function) "&"(Left : @RI(C); Right : @RI(C)) @key(return) @RI(T) @end(example) @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(concatenation)} For the evaluation of a concatenation with result type @i(T), if both operands are of type @i(T), the result of the concatenation is a one-dimensional array whose length is the sum of the lengths of its operands, and whose components comprise the components of the left operand followed by the components of the right operand. If the left operand is a null array, the result of the concatenation is the right operand. Otherwise, the lower bound of the result is determined as follows: @begin(Itemize) If the ultimate ancestor of the array type was defined by a @nt<constrained_array_definition>, then the lower bound of the result is that of the index subtype; @begin(Reason) This rule avoids Constraint_Error when using concatenation on an array type whose first subtype is constrained. @end(Reason) If the ultimate ancestor of the array type was defined by an @nt<unconstrained_array_definition>, then the lower bound of the result is that of the left operand. @end(Itemize) @Redundant[The upper bound is determined by the lower bound and the length.] @IndexCheck{Index_Check} A check is made that the upper bound of the result of the concatenation belongs to the range of the index subtype, unless the result is a null array. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. If either operand is of the component type @i(C), the result of the concatenation is given by the above rules, using in place of such an operand an array having this operand as its only component (converted to the component subtype) and having the lower bound of the index subtype of the array type as its lower bound. @PDefn2{Term=[implicit subtype conversion],Sec=(operand of concatenation)} @begin{Ramification} The conversion might raise Constraint_Error. The conversion provides @lquotes@;sliding@rquotes@; for the component in the case of an array-of-arrays, consistent with the normal Ada 95 rules that allow sliding during parameter passing. @end{Ramification} @Defn2{Term=[assignment operation], Sec=(during evaluation of concatenation)} The result of a concatenation is defined in terms of an assignment to an anonymous object, as for any function call (see @RefSecNum{Return Statements}). @begin{Ramification} This implies that value adjustment is performed as appropriate @em see @RefSecNum{Assignment and Finalization}. We don't bother saying this for other predefined operators, even though they are all function calls, because this is the only one where it matters. It is the only one that can return a value having controlled parts. @end{Ramification} @end{RunTime} @begin{Notes} As for all predefined operators on modular types, the binary adding operators + and @en on modular types include a final reduction modulo the modulus if the result is outside the base range of the type. @begin{ImplNote} A full "modulus" operation need not be performed after addition or subtraction of modular types. For binary moduli, a simple mask is sufficient. For nonbinary moduli, a check after addition to see if the value is greater than the high bound of the base range can be followed by a conditional subtraction of the modulus. Conversely, a check after subtraction to see if a "borrow" was performed can be followed by a conditional addition of the modulus. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving binary adding operators:) @begin{Example} Z + 0.1 --@RI[ Z has to be of a real type ] "A" & "BCD" --@RI[ concatenation of two string literals] 'A' & "BCD" --@RI[ concatenation of a character literal and a string literal] 'A' & 'A' --@RI[ concatenation of two character literals ] @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The lower bound of the result of concatenation, for a type whose first subtype is constrained, is now that of the index subtype. This is inconsistent with Ada 83, but generally only for Ada 83 programs that raise Constraint_Error. For example, the concatenation operator in @begin(Example) X : @key(array)(1..10) @key(of) Integer; @key(begin) X := X(6..10) & X(1..5); @end(Example) would raise Constraint_Error in Ada 83 (because the bounds of the result of the concatenation would be 6..15, which is outside of 1..10), but would succeed and swap the halves of X (as expected) in Ada 95. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Concatenation is now useful for array types whose first subtype is constrained. When the result type of a concatenation is such an array type, Constraint_Error is avoided by effectively first sliding the left operand (if nonnull) so that its lower bound is that of the index subtype. @end{Extend83} @LabeledSubClause{Unary Adding Operators} @begin{StaticSem} @Leading@Defn{unary adding operator}@Defn2{Term=[operator],Sec=(unary adding)} @Defn{+ operator}@Defn2{Term=[operator],Sec=(+)} @Defn{plus operator}@Defn2{Term=[operator],Sec=(plus)} @Defn{- operator}@Defn2{Term=[operator],Sec=(-)} @Defn{minus operator}@Defn2{Term=[operator],Sec=(minus)} The unary adding operators + (identity) and @en (negation) are predefined for every specific numeric type @i(T) with their conventional meaning. They have the following specifications: @begin(example) @key(function) "+"(Right : @RI(T)) @key(return) @RI(T) @key(function) "-"(Right : @RI(T)) @key(return) @RI(T) @end(example) @end{StaticSem} @begin{Notes} For modular integer types, the unary adding operator @en, when given a nonzero operand, returns the result of subtracting the value of the operand from the modulus; for a zero operand, the result is zero. @end{Notes} @LabeledSubClause{Multiplying Operators} @begin{StaticSem} @Leading@Defn{multiplying operator}@Defn2{Term=[operator],Sec=(multiplying)} @Defn{* operator}@Defn2{Term=[operator],Sec=(*)} @Defn{multiply operator}@Defn2{Term=[operator],Sec=(multiply)} @Defn{times operator}@Defn2{Term=[operator],Sec=(times)} @Defn{/ operator}@Defn2{Term=[operator],Sec=(/)} @Defn{divide operator}@Defn2{Term=[operator],Sec=(divide)} @Defn{mod operator}@Defn2{Term=[operator],Sec=(mod)} @Defn{rem operator}@Defn2{Term=[operator],Sec=(rem)} The multiplying operators * (multiplication), / (division), @key(mod) (modulus), and @key(rem) (remainder) are predefined for every specific integer type @i(T): @begin(example) @key(function) "*" (Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "/" (Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "@key(mod)"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "@key(rem)"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) Signed integer multiplication has its conventional meaning. @Leading@keepnext@;Signed integer division and remainder are defined by the relation: @begin(example) A = (A/B)*B + (A @key(rem) B) @end(example) @Leading@;where (A @key(rem) B) has the sign of A and an absolute value less than the absolute value of B. Signed integer division satisfies the identity: @begin(example) (-A)/B = -(A/B) = A/(-B) @end(example) @begin{WideAbove} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0260-1]} The signed integer modulus operator is defined such that the result of A @key(mod) B @Chg{Version=[3],New=[is either zero, or ],Old=[]}has the sign of B and an absolute value less than the absolute value of B; in addition, for some signed integer value N, this result satisfies the relation: @begin(example) A = B*N + (A @key(mod) B) @end(example) The multiplying operators on modular types are defined in terms of the corresponding signed integer operators@Redundant[, followed by a reduction modulo the modulus if the result is outside the base range of the type] @Redundant[(which is only possible for the "*" operator)]. @begin{Ramification} The above identity satisfied by signed integer division is not satisfied by modular division because of the difference in effect of negation. @end{Ramification} @end{WideAbove} @Leading@;Multiplication and division operators are predefined for every specific floating point type @i(T): @begin(example) @key(function) "*"(Left, Right : @RI(T)) @key(return) @RI(T) @key(function) "/"(Left, Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@;The following multiplication and division operators, with an operand of the predefined type Integer, are predefined for every specific fixed point type @i(T): @begin(example) @key(function) "*"(Left : @RI(T); Right : Integer) @key(return) @RI(T) @key(function) "*"(Left : Integer; Right : @RI(T)) @key(return) @RI(T) @key(function) "/"(Left : @RI(T); Right : Integer) @key(return) @RI(T) @end(example) @Leading@Redundant[All of the above multiplying operators are usable with an operand of an appropriate universal numeric type.] The following additional multiplying operators for @i(root_real) are predefined@Redundant[, and are usable when both operands are of an appropriate universal or root numeric type, and the result is allowed to be of type @i(root_real), as in a @nt<number_declaration>]: @begin{Ramification} These operators are analogous to the multiplying operators involving fixed or floating point types where @i(root_real) substitutes for the fixed or floating point type, and @i(root_integer) substitutes for Integer. Only values of the corresponding universal numeric types are implicitly convertible to these root numeric types, so these operators are really restricted to use with operands of a universal type, or the specified root numeric types. @end{Ramification} @begin(example) @key(function) "*"(Left, Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "/"(Left, Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "*"(Left : @RI(root_real); Right : @RI(root_integer)) @key(return) @RI(root_real) @key(function) "*"(Left : @RI(root_integer); Right : @RI(root_real)) @key(return) @RI(root_real) @key(function) "/"(Left : @RI(root_real); Right : @RI(root_integer)) @key(return) @RI(root_real) @end(example) @Leading@;Multiplication and division between any two fixed point types are provided by the following two predefined operators: @begin{Ramification} @i(Universal_fixed) is the universal type for the class of fixed point types, meaning that these operators take operands of any fixed point types (not necessarily the same) and return a result that is implicitly (or explicitly) convertible to any fixed point type. @end{Ramification} @begin(example) @key(function) "*"(Left, Right : @RI(universal_fixed)) @key(return) @RI(universal_fixed) @key(function) "/"(Left, Right : @RI(universal_fixed)) @key(return) @RI(universal_fixed) @end(example) @end{StaticSem} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The above two fixed-fixed multiplying operators shall not be used in a context where the expected type for the result is itself @i(universal_fixed) @Redundant[@em the context has to identify some other numeric type to which the result is to be converted, either explicitly or implicitly]. Unless the predefined universal operator is identified using an expanded name with @nt{prefix} denoting the package Standard, an explicit conversion is required on the result when using the above fixed-fixed multiplication operator if either operand is of a type having a user-defined primitive multiplication operator such that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0020-1],ARef=[AI05-0209-1]} @ChgAdded{Version=[2],Text=[it is declared immediately within the same declaration list as the type@Chg{Version=[3],New=[ or any partial or incomplete view thereof],Old=[]}; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[both of its formal parameters are of a fixed-point type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[A corresponding requirement applies to the universal fixed-fixed division operator.]} @begin(Discussion) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @i(small) of @i(universal_fixed) is infinitesimal; no loss of precision is permitted. However, fixed-fixed division is impractical to implement when an exact result is required, and multiplication will sometimes result in unanticipated overflows in such circumstances, so we require an explicit conversion to be inserted in expressions like A * B * C if A, B, and C are each of some fixed point type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[On the other hand, X := A * B; is permitted by this rule, even if X, A, and B are all of different fixed point types, since the expected type for the result of the multiplication is the type of X, which is necessarily not @i(universal_fixed).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[We have made these into Name Resolution rules to ensure that user-defined primitive fixed-fixed operators are not made unusable due to the presence of these universal fixed-fixed operators. But we do allow these operators to be used if prefixed by package Standard, so that they can be used in the definitions of user-defined operators.]} @end(Discussion) @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00364-01]} @ChgDeleted{Version=[2],Text=[The above two fixed-fixed multiplying operators shall not be used in a context where the expected type for the result is itself @i(universal_fixed) @em @Redundant[the context has to identify some other numeric type to which the result is to be converted, either explicitly or implicitly].]} @begin(Discussion) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The @i(small) of @i(universal_fixed) is infinitesimal; no loss of precision is permitted. However, fixed-fixed division is impractical to implement when an exact result is required, and multiplication will sometimes result in unanticipated overflows in such circumstances, so we require an explicit conversion to be inserted in expressions like A * B * C if A, B, and C are each of some fixed point type.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[On the other hand, X := A * B; is permitted by this rule, even if X, A, and B are all of different fixed point types, since the expected type for the result of the multiplication is the type of X, which is necessarily not @i(universal_fixed).]} @end(Discussion) @end{Legality} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraph 20 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{RunTime} The multiplication and division operators for real types have their conventional meaning. @redundant[For floating point types, the accuracy of the result is determined by the precision of the result type. For decimal fixed point types, the result is truncated toward zero if the mathematical result is between two multiples of the @i(small) of the specific result type (possibly determined by context); for ordinary fixed point types, if the mathematical result is between two multiples of the @i(small), it is unspecified which of the two is the result. @PDefn{unspecified}] @IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised by integer division, @key(rem), and @key(mod) if the right operand is zero. @Redundant[Similarly, for a real type @i(T) with @i(T')Machine_Overflows True, division by zero raises Constraint_Error.] @end{RunTime} @begin{Notes} @Leading@Keepnext@;For positive A and B, A/B is the quotient and A @key(rem) B is the remainder when A is divided by B. The following relations are satisfied by the rem operator: @begin{Example} A @key(rem) (-B) = A @key(rem) B (-A) @key(rem) B = -(A @key(rem) B) @end{Example} @Leading@keepnext@;For any signed integer K, the following identity holds: @begin{Example} A @key(mod) B = (A + K*B) @key(mod) B @end{Example} @begin{Bundle} @NoPrefix@Leading@;The relations between signed integer division, remainder, and modulus are illustrated by the following table: @begin{Example} A B A/B A @key(rem) B A @key(mod) B A B A/B A @key(rem) B A @key(mod) B 10 5 2 0 0 -10 5 -2 0 0 11 5 2 1 1 -11 5 -2 -1 4 12 5 2 2 2 -12 5 -2 -2 3 13 5 2 3 3 -13 5 -2 -3 2 14 5 2 4 4 -14 5 -2 -4 1 A B A/B A @key(rem) B A @key(mod) B A B A/B A @key(rem) B A @key(mod) B@* 10 -5 -2 0 0 -10 -5 2 0 0 11 -5 -2 1 -4 -11 -5 2 -1 -1 12 -5 -2 2 -3 -12 -5 2 -2 -2 13 -5 -2 3 -2 -13 -5 2 -3 -3 14 -5 -2 4 -1 -14 -5 2 -4 -4 @end{Example} @end{Bundle} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of expressions involving multiplying operators:) @begin{Example} I : Integer := 1; J : Integer := 2; K : Integer := 3; X : Real := 1.0; --@RI[ see @RefSecNum{Floating Point Types}] Y : Real := 2.0; F : Fraction := 0.25; --@RI[ see @RefSecNum{Fixed Point Types}] G : Fraction := 0.5; @end{Example} @begin{Example} @tabclear()@tabset(P19, P31) @RI(Expression) @\@RI(Value) @\@RI(Result Type)@* @R{I*J} @\@R{2} @\@RI(same as I and J, that is, Integer) @R{K/J} @\@R{1} @\@RI(same as K and J, that is, Integer) @R{K @key(mod) J} @\@R{1} @\@RI(same as K and J, that is, Integer)@* @R{X/Y} @\@R{0.5} @\@RI(same as X and Y, that is, Real) @R{F/2} @\@R{0.125} @\@RI(same as F, that is, Fraction)@* @R{3*F} @\@R{0.75} @\@RI(same as F, that is, Fraction) @R{0.75*G} @\@R{0.375} @\@RI(universal_fixed, implicitly convertible) @\ @\@RI(to any fixed point type) @R{Fraction(F*G)} @\@R{0.125} @\@RI(Fraction, as stated by the conversion) @R{Real(J)*Y} @\@R{4.0} @\@RI(Real, the type of both operands after) @\ @\@RI(conversion of J) @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00364-01],ARef=[AI95-00420-01]} @Chg{Version=[2],New=[@Defn{incompatibilities with Ada 83}The universal fixed-fixed multiplying operators are now directly available (see below). Any attempt to use user-defined fixed-fixed multiplying operators will be ambiguous with the universal ones. The only way to use the user-defined operators is to fully qualify them in a prefix call. This problem was not documented during the design of Ada 95, and has been mitigated by Ada 2005.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Explicit conversion of the result of multiplying or dividing two fixed point numbers is no longer required, provided the context uniquely determines some specific fixed point result type. This is to improve support for decimal fixed point, where requiring explicit conversion on every fixed-fixed multiply or divide was felt to be inappropriate. The type @i(universal_fixed) is covered by @i(universal_real), so real literals and fixed point operands may be multiplied or divided directly, without any explicit conversions required. @end{Extend83} @begin{DiffWord83} We have used the normal syntax for function definition rather than a tabular format. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00364-01]} @Chg{Version=[2],New=[@Defn{incompatibilities with Ada 95}We have changed the resolution rules for the universal fixed-fixed multiplying operators to remove the incompatibility with Ada 83 discussed above. The solution is to hide the universal operators in some circumstances. As a result, some legal Ada 95 programs will require the insertion of an explicit conversion around a fixed-fixed multiply operator. This change is likely to catch as many bugs as it causes, since it is unlikely that the user wanted to use predefined operators when they had defined user-defined versions.],Old=[]} @end{Incompatible95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0020-1],ARef=[AI05-0209-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Wording was added to clarify that @i{universal_fixed} "*" and "/" does not apply if an appropriate operator is declared for a partial (or incomplete) view of the designated type. Otherwise, adding a partial (or incomplete) view could make some "*" and "/" operators ambiguous.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0260-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The wording for the @key[mod] operator was corrected so that a result of 0 does not have to have "the sign of B" (which is impossible if B is negative).]} @end{DiffWord2005} @LabeledSubClause{Highest Precedence Operators} @begin{StaticSem} @Leading@Defn{highest precedence operator}@Defn2{Term=[operator],Sec=(highest precedence)} @Defn{abs operator}@Defn2{Term=[operator],Sec=(abs)} @Defn{absolute value} The highest precedence unary operator @key(abs) (absolute value) is predefined for every specific numeric type @i(T), with the following specification: @begin(example) @key(function) "@key(abs)"(Right : @RI(T)) @key(return) @RI(T) @end(example) @Leading@Defn{not operator}@Defn2{Term=[operator],Sec=(not)} @IndexSeeAlso{Term=[logical operator],See=(not operator)} The highest precedence unary operator @key(not) (logical negation) is predefined for every boolean type @i(T), every modular type @i(T), and for every one-dimensional array type @i(T) whose components are of a boolean type, with the following specification: @begin(example) @key(function) "@key(not)"(Right : @RI(T)) @key(return) @RI(T) @end(example) The result of the operator @key(not) for a modular type is defined as the difference between the high bound of the base range of the type and the value of the operand. @Redundant[For a binary modulus, this corresponds to a bit-wise complement of the binary representation of the value of the operand.] The operator @key(not) that applies to a one-dimensional array of boolean components yields a one-dimensional boolean array with the same bounds; each component of the result is obtained by logical negation of the corresponding component of the operand (that is, the component that has the same index value). @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} A check is made that each component of the result belongs to the component subtype; the exception Constraint_Error is raised if this check fails. @begin{Discussion} The check against the component subtype is per AI83-00535. @end{Discussion} @Leading@Defn{exponentiation operator}@Defn2{Term=[operator],Sec=(exponentiation)} @Defn{** operator}@Defn2{Term=[operator],Sec=(**)} The highest precedence @i(exponentiation) operator ** is predefined for every specific integer type @i(T) with the following specification: @begin(example) @key(function) "**"(Left : @RI(T); Right : Natural) @key(return) @RI(T) @end(example) @Leading@;Exponentiation is also predefined for every specific floating point type as well as @i{root_real}, with the following specification (where @i(T) is @i{root_real} or the floating point type): @begin(example) @key(function) "**"(Left : @RI(T); Right : Integer'Base) @key(return) @RI(T) @end(example) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0088-1]} @Defn{exponent} The right operand of an exponentiation is the @i(exponent). The @Chg{Version=[3],New=[value of],Old=[expression]} X**N with the value of the exponent N positive is @Chg{Version=[3],New=[the same as the value of], Old=[equivalent to the expression]} X*X*...X (with N@en@;1 multiplications) except that the multiplications are associated in an arbitrary order. With N equal to zero, the result is one. With the value of N negative @Redundant[(only defined for a floating point operand)], the result is the reciprocal of the result using the absolute value of N as the exponent. @begin{Ramification} The language does not specify the order of association of the multiplications inherent in an exponentiation. For a floating point type, the accuracy of the result might depend on the particular association order chosen. @end{Ramification} @end{StaticSem} @begin{ImplPerm} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The implementation of exponentiation for the case of a negative exponent is allowed to raise Constraint_Error if the intermediate result of the repeated multiplications is outside the safe range of the type, even though the final result (after taking the reciprocal) would not be. (The best machine approximation to the final result in this case would generally be 0.0.) @end{ImplPerm} @begin{Notes} @IndexCheck{Range_Check} As implied by the specification given above for exponentiation of an integer type, a check is made that the exponent is not negative. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @end{Notes} @begin{Inconsistent83} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0100],ARef=[AI95-00018-01]} @ChgAdded{Version=[1],Text=[@Defn{inconsistencies with Ada 83} The definition of "**" allows arbitrary association of the multiplications which make up the result. Ada 83 required left-to-right associations (confirmed by AI83-00137). Thus it is possible that "**" would provide a slightly different (and more potentially accurate) answer in Ada 95 than in the same Ada 83 program.]} @end{Inconsistent83} @begin{DiffWord83} We now show the specification for "**" for integer types with a parameter subtype of Natural rather than Integer for the exponent. This reflects the fact that Constraint_Error is raised if a negative value is provided for the exponent. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0088-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The equivalence definition for "**" was corrected so that it does not imply that the operands are evaluated multiple times.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[3],Name=[Conditional Expressions]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A @nt{conditional_expression} selects for evaluation at most one of the enclosed @SynI<dependent_>@nt{expression}s, depending on a decision among the alternatives. One kind of @nt{conditional_expression} is the @nt{if_expression}, which selects for evaluation a @SynI<dependent_>@nt{expression} depending on the value of one or more corresponding conditions. The other kind of @nt{conditional_expression} is the @nt{case_expression}, which selects for evaluation one of a number of alternative @SynI<dependent_>@nt{expression}s; the chosen alternative is determined by the value of a @SynI<selecting_>@nt{expression}.]} @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[As previously noted, there are two kinds of @nt{conditional_expression}, @nt{if_expression}s and @nt{case_expression}s. Whenever possible, we have written the rules in terms of @nt{conditional_expression}s to avoid duplication.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[The rules for @nt{conditional_expression}s have been designed as much as possible to work similarly to a parenthesized expression. The intent is that as much as possible, wherever a parenthesized expression would be allowed, a @nt{conditional_expression} would be allowed, and it should work the same way.]} @end{MetaRules} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<conditional_expression>,Old=<>}>, rhs="@Chg{Version=[3],New=<@Syn2{if_expression} | @Syn2{case_expression}>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<if_expression>,Old=<>}>, rhs=" @Chg{Version=[3],New=<@key[if] @Syn2{condition} @key[then] @SynI{dependent_}@Syn2{expression} {@key[elsif] @Syn2{condition} @key[then] @SynI{dependent_}@Syn2{expression}} [@key[else] @SynI{dependent_}@Syn2{expression}]>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<condition>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI{boolean_}@Syn2{expression}>,Old=<>}"} @Comment{Moved from "If Statements"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<case_expression>,Old=<>}>, rhs="@Chg{Version=[3],New=< @key[case] @SynI{selecting_}@Syn2{expression} @key[is] @Syn2[case_expression_alternative] {, @Syn2[case_expression_alternative]}>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<case_expression_alternative>,Old=<>}>, rhs="@Chg{Version=[3],New=[ @key[when] @Syn2{discrete_choice_list} => @SynI{dependent_}@Syn2{expression}],Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[Wherever the Syntax Rules allow an @nt{expression}, a @nt{conditional_expression} may be used in place of the @nt{expression}, so long as it is immediately surrounded by parentheses.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[The syntactic category @nt{conditional_expression} appears only as a primary that is parenthesized. The above rule allows it to additionally be used in other contexts where it would be directly surrounded by parentheses.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The grammar makes the following directly legal:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A := (@key[if] X @key[then] Y @key[else] Z); --@examcom{ parentheses required} A := B + (@key[if] X @key[then] Y @key[else] Z) + C; --@examcom{ parentheses required}]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following procedure calls are syntactically legal; the first uses the above rule to eliminate the redundant parentheses found in the second:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[P(@key[if] X @key[then] Y @key[else] Z); P((@key[if] X @key[then] Y @key[else] Z)); --@Examcom{ redundant parentheses}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[P((@key[if] X @key[then] Y @key[else] Z), Some_Other_Param); P(Some_Other_Param, (@key[if] X @key[then] Y @key[else] Z)); P(Formal => (@key[if] X @key[then] Y @key[else] Z));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[whereas the following are illegal:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[P(@key[if] X @key[then] Y @key[else] Z, Some_Other_Param); P(Some_Other_Param, @key[if] X @key[then] Y @key[else] Z); P(Formal => @key[if] X @key[then] Y @key[else] Z);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[because in these latter cases, the @nt{conditional_expression} is not immediately surrounded by parentheses (which means on both sides!).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The English-language rule applies in all places that could surround an expression with parentheses, including pragma arguments, type conversion and qualified expression operands, and array index expressions.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This English-language rule could have been implemented instead by adding a nonterminal @ntf{expression_within_parentheses}, which would consist of @nt{expression}s and @nt{conditional_expression}s. Then, that could be used in all of the syntax which could consist of parens directly around an @nt{expression}. We did not do that because of the large amount of change required. A complete grammar is given in @AILink{AI=[AI05-0147-1],Text=[AI05-0147-1]}.]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[Implementers are cautioned to consider error detection when implementing the syntax for @nt{conditional_expression}s. An @nt{if_expression} and an @nt{if_statement} are very similar syntactically, (as are a @nt{case_expression} and a @nt{case_statement}) and simple mistakes can appear to change one into the other, potentially causing errors to be moved far away from their actual location. The absence of @key[end if] to terminate an @nt{if_expression} (and @key[end case] for a @nt{case_expression}) also may make error handling harder.]} @end{ImplNote} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If a @nt{conditional_expression} is expected to be of a type @i<T>, then each @SynI{dependent_}@nt{expression} of the @nt{conditional_expression} is expected to be of type @i<T>. Similarly, if a @nt{conditional_expression} is expected to be of some class of types, then each @SynI{dependent_}@nt{expression} of the @nt{conditional_expression} is subject to the same expectation. If a @nt{conditional_expression} shall resolve to be of a type @i<T>, then each @SynI{dependent_}@nt{expression} shall resolve to be of type @i<T>.@PDefn2{Term=[expected type],Sec=[dependent_expression]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The possible types of a @nt{conditional_expression} are further determined as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{conditional_expression} is the operand of a type conversion, the type of the @nt{conditional_expression} is the target type of the conversion; otherwise,]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This rule distributes an enclosing type conversion to the @SynI{dependent_}@nt{expression}s. This means that]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[T(@key[if] C @key[then] A @key[else] B)]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[has the same semantics as]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[(@key[if] C @key[then] T(A) @key[else] T(B))]} @end{Example} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If all of the @SynI{dependent_}@nt{expression}s are of the same type, the type of the @nt{conditional_expression} is that type; otherwise,]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If a @SynI{dependent_}@nt{expression} is of an elementary type, the type of the @nt{conditional_expression} shall be covered by that type; otherwise,]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule supports the use of numeric literals and universal expressions within a @nt{conditional_expression}.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{conditional_expression} is expected to be of type @i<T> or shall resolve to type @i<T>, then the @nt{conditional_expression} is of type @i<T>.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the type of the @nt{conditional_expression} cannot be determined by one of these rules, then Name Resolution has failed for that expression, even if the @SynI{dependent_}@nt{expression}s would resolve individually.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[expected type], Sec=(condition)} A @nt{condition} is expected to be of any boolean type.]} @Comment{Moved from "If Statements"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[The expected type for the @SynI<selecting_>@nt{expression} and the @nt{discrete_choice}s are as for case statements (see @RefSecNum{Case Statements}).@PDefn2{Term=[expected type],Sec=[case_expression selecting_expression]} @PDefn2{Term=[expected type],Sec=[case_expression_alternative discrete_choice]} @PDefn2{Term=[expected type],Sec=[selecting_expression case_expression]}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[All of the @SynI{dependent_}@nt{expression}s shall be convertible (see @RefSecNum{Type Conversions}) to the type of the @nt{conditional_expression}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[If the expected type of a @nt{conditional_expression} is a specific tagged type, all of the @SynI{dependent_}@nt{expression}s of the @nt{conditional_expression} shall be dynamically tagged, or none shall be dynamically tagged. In this case, the @nt{conditional_expression} is dynamically tagged if all of the @SynI{dependent_}@nt{expression}s are dynamically tagged, is tag-indeterminate if all of the @SynI{dependent_}@nt{expression}s are tag-indeterminate, and is statically tagged otherwise.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[If there is no @key[else] @SynI{dependent_}@nt{expression}, the @nt{if_expression} shall be of a boolean type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[All @LegalityTitle that apply to the @nt{discrete_choice}s of a @nt{case_statement} (see @RefSecNum{Case Statements}) also apply to the @nt{discrete_choice}s of a @nt{case_expression} except within an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The exemption for a case expression that occurs in an instance allows the following example:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[with function] Int_Func @key[return] Integer; @key[package] G @key[is] X : Float := (@key[case] Int_Func @key[is] @key[when] Integer'First .. -1 => -1.0, @key[when] 0 => 0.0, @key[when] Positive => 1.0); @key[end] G;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] Nat_Func @key[return] Natural @key[is] (123);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] I @key[is new] G (Int_Func => Nat_Func); -- @Examcom{Legal}]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that the @LegalityTitle still apply in the generic unit itself; they are just not enforced in an instance of the unit.]} @end{Reason} @end{Legality} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[For the evaluation of an @nt{if_expression}, the @nt{condition} specified after @key[if], and any @nt{condition}s specified after @key[elsif], are evaluated in succession (treating a final @key[else] as @key[elsif] True @key[then]), until one evaluates to True or all @nt{condition}s are evaluated and yield False. If a @nt{condition} evaluates to True, the associated @synI{dependent_}@nt{expression} is evaluated, converted to the type of the @nt{if_expression}, and the resulting value is the value of the @nt{if_expression}. Otherwise (when there is no @key[else] clause), the value of the @nt{if_expression} is True.@PDefn2{Term=[evaluation],Sec=[if_expression]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[Else] is required unless the @nt{if_expression} has a boolean type, so the last sentence can only apply to @nt{if_expression}s with a boolean type.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[For the evaluation of a @nt{case_expression}, the @SynI<selecting_>@nt{expression} is first evaluated. If the value of the @SynI<selecting_>@nt{expression} is covered by the @nt{discrete_choice_list} of some @nt{case_expression_alternative}, then the @SynI<dependent_>@nt{expression} of the @nt{case_expression_alternative} is evaluated, converted to the type of the @nt{case_expression}, and the resulting value is the value of the @nt{case_expression}.@IndexCheck{Overflow_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Otherwise (the value is not covered by any @nt{discrete_choice_list}, perhaps due to being outside the base range), Constraint_Error is raised.@PDefn2{Term=[evaluation],Sec=[case_expression]}]} @end{Runtime} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}If expressions and case expressions are new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[Quantified Expressions]} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<quantified_expression>,Old=<>}>, rhs="@Chg{Version=[3],New=[@key[for] @Syn2{quantifier} @Syn2{loop_parameter_specification} => @Syn2{predicate} | @key[for] @Syn2{quantifier} @Syn2{iterator_specification} => @Syn2{predicate}],Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<quantifier>,Old=<>}>, rhs="@Chg{Version=[3],New=<@key[all] | @key[some]>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<predicate>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI<boolean_>@Syn2{expression}>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[Wherever the Syntax Rules allow an @nt{expression}, a @nt{quantified_expression} may be used in place of the @nt{expression}, so long as it is immediately surrounded by parentheses.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The syntactic category @nt{quantified_expression} appears only as a @nt{primary} that is parenthesized. The above rule allows it to additionally be used in other contexts where it would be directly surrounded by parentheses. This is the same rule that is used for @nt{conditional_expression}s; see @RefSecNum{Conditional Expressions} for a detailed discussion of the meaning and effects of this rule.]} @end{Discussion} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[expected type],Sec=[quantified_expression]} The expected type of a @nt{quantified_expression} is any Boolean type. The @nt{predicate} in a @nt{quantified_expression} is expected to be of the same type.@Defn{quantified expressions}]} @end{Resolution} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[For the evaluation of a @nt{quantified_expression}, the @nt{loop_parameter_specification} or @nt{iterator_specification} is first elaborated. The evaluation of a @nt{quantified_expression} then evaluates the @nt{predicate} for each value of the loop parameter. These values are examined in the order specified by the @nt{loop_parameter_specification} (see @RefSecNum{Loop Statements}) or @nt{iterator_specification} (see @RefSecNum{Generalized Loop Iteration}).@PDefn2{Term=[evaluation],Sec=[quantified_expression]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The value of the @nt{quantified_expression} is determined as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{quantifier} is @key[all], the expression is True if the evaluation of the @nt{predicate} yields True for each value of the loop parameter. It is False otherwise. Evaluation of the @nt{quantified_expression} stops when all values of the domain have been examined, or when the @nt{predicate} yields False for a given value. Any exception raised by evaluation of the @nt{predicate} is propagated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{expression} is True if the domain contains no values.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{quantifier} is @key[some], the expression is True if the evaluation of the @nt{predicate} yields True for some value of the loop parameter. It is False otherwise. Evaluation of the @nt{quantified_expression} stops when all values of the domain have been examined, or when the @nt{predicate} yields True for a given value. Any exception raised by evaluation of the @nt{predicate} is propagated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{expression} is False if the domain contains no values.]} @end{Ramification} @end{Itemize} @end{Runtime} @begin{Examples} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The postcondition for a sorting routine on an array A with an index subtype T can be written:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Post => (A'Length < 2 @key[or else] (@key[for all] I @key[in] A'First .. T'Pred(A'Last) => A (I) <= A (T'Succ (I))))]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The assertion that a positive number is composite (as opposed to prime) can be written:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[pragma] Assert (@key[for some] X @key[in] 2 .. N / 2 => N @key[mod] X = 0);]} @end{Example} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0176-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Quantified expressions are new.]} @end{Extend2005} �������������������������������������������������������������������������org.adaic.arm_form/source_2012/04b.mss��������������������������������������������������������������0000755�0001752�0001001�00000400004�12066652506�016534� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(04, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @Comment{$Source: e:\\cvsroot/ARM/Source/04b.mss,v $} @Comment{$Revision: 1.63 $} @LabeledClause{Type Conversions} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[Explicit type conversions, both value conversions and view conversions, are allowed between closely related types as defined below. This @Chg{Version=[3],New=[subclause],Old=[clause]} also defines rules for value and view conversions to a particular subtype of a type, both explicit ones and those implicit in other constructs. @IndexSee{Term=[subtype conversion],See=(type conversion)} @Defn{type conversion} @Defn{conversion} @IndexSee{Term=[cast],See=(type conversion)}] @IndexSeeAlso{Term=[subtype conversion],See=(implicit subtype conversion)} @IndexSee{Term=[type conversion, implicit],See=(implicit subtype conversion)} @end{Intro} @begin{Syntax} @Syn{lhs=<type_conversion>,rhs=" @Syn2{subtype_mark}(@Syn2{expression}) | @Syn2{subtype_mark}(@Syn2{name})"} @end{Syntax} @begin{Intro} @Defn2{Term=[target subtype], Sec=(of a @nt<type_conversion>)} The @i(target subtype) of a @nt<type_conversion> is the subtype denoted by the @nt{subtype_mark}. @Defn2{Term=[operand], Sec=(of a @nt<type_conversion>)} The @i(operand) of a @nt<type_conversion> is the @nt{expression} or @nt{name} within the parentheses; @Defn2{Term=[operand type], Sec=(of a @nt<type_conversion>)} its type is the @i(operand type). @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{convertible} One type is @i(convertible) to a second type if a @nt<type_conversion> with the first type as operand type and the second type as target type is legal according to the rules of this @Chg{Version=[3],New=[subclause],Old=[clause]}. Two types are convertible if each is convertible to the other. @begin{Ramification} Note that @lquotes@;convertible@rquotes@; is defined in terms of legality of the conversion. Whether the conversion would raise an exception at run time is irrelevant to this definition. @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00330-01]} @Defn{view conversion} @Defn2{Term=[conversion],Sec=(view)} A @nt{type_conversion} whose operand is the @nt<name> of an object is called a @i(view conversion) if @Chg{New=[both ],Old=[]}its target type @Chg{New=[and operand type are],Old=[is]} tagged, or if it appears@Chg{Version=[2],New=[ in a call],Old=[]} as an actual parameter of mode @key[out] or @key[in out]; @Defn{value conversion} @Defn2{Term=[conversion],Sec=(value)} other @nt<type_conversion>s are called @i(value conversions). @IndexSee{Term=[super],See=(view conversion)} @begin{Ramification} A view conversion to a tagged type can appear in any context that requires an object @nt<name>, including in an object renaming, the @nt<prefix> of a @nt<selected_component>, and if the operand is a variable, on the left side of an @nt<assignment_statement>. View conversions to other types only occur as actual parameters. Allowing view conversions of untagged types in all contexts seemed to incur an undue implementation burden. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00330-01]} @ChgAdded{Version=[2],Text=[A type conversion appearing as an @key{in out} parameter in a generic instantiation is not a view conversion; the second part of the rule only applies to subprogram calls, not instantiations.]} @end{Ramification} @end{Intro} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(type_conversion operand)} The operand of a @nt<type_conversion> is expected to be of any type. @begin{Discussion} This replaces the "must be determinable" wording of Ada 83. This is equivalent to (but hopefully more intuitive than) saying that the operand of a @nt<type_conversion> is a @lquotes@;complete context.@rquotes@; @end{Discussion} The operand of a view conversion is interpreted only as a @nt<name>; the operand of a value conversion is interpreted as an @nt<expression>. @begin{Reason} This formally resolves the syntactic ambiguity between the two forms of @nt<type_conversion>, not that it really matters. @end{Reason} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[In a view conversion for an untagged type, the target type shall be convertible (back) to the operand type.], Old=[@Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} If the target type is a numeric type, then the operand type shall be a numeric type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=<Untagged view conversions appear only as [@key{in}] @key{out} parameters. Hence, the reverse conversion must be legal as well. The forward conversion must be legal even for an @key{out} parameter, because (for example) actual parameters of an access type are always copied in anyway.>} @end{Reason} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 9 through 20 were reorganized and moved below.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The entire @LegalityTitle section has been reorganized to eliminate an unintentional incompatibility with Ada 83. In rare cases, a type conversion between two types related by derivation is not allowed by Ada 95, while it is allowed in Ada 83. The reorganization fixes this. Much of the wording of the legality section is unchanged, but it is reordered and reformatted. Because of the limitations of our tools, we had to delete and replace nearly the entire section. The text of Ada 95 paragraphs 8 through 12, 14, 15, 17, 19, 20, and 24 are unchanged (just moved); these are now 24.1 through 24.5, 24.12, 24.13, 24.17, 24.19, 24.20, and 8.]} @end{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} If the target type is an array type, then the operand type shall be an array type. Further:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The types shall have the same dimensionality;]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[Corresponding index types shall be convertible;@Chg{New=[],Old=[ and]} @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The component subtypes shall statically match@Chg{New=[; and],Old=[.]} @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@Chg{New=[In a view conversion, the target type and the operand type shall both or neither have aliased components.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[Without this rule, it is possible to violate the constrained status of aliased array components. Consider:],Old=[]}]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[@key[package] P @key[is] @key[type] T @key[is private]; A : @key[constant] T; @key[type] A1 @key[is array] (1 .. 10) @key[of aliased] T; @key[type] A2 @key[is array] (1 .. 10) @key[of] T; @key[private] @key[type] T (D : Integer := 0) @key[is null record]; A : @key[constant] T := (D => 1); @key[end] P;],Old=[]}]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@Chg{New=[@key[with] P; @key[procedure] Exam @key[is] X : P.A1; @key[procedure] S (Y : @key[in out] P.A2) @key[is] @key[begin] Y (1) := P.A; @key[end]; @key[begin] S (P.A2 (X)); -- This call will change the discriminant of X (1), -- so we cannot allow the conversion. @key[end];],Old=[]}]} @end{Example} @end{Reason} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is a general access type, then the operand type shall be an access-to-object type. Further:]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The @LegalityTitle and @RunTimeTitle are worded so that a @nt{type_conversion} T(X) (where T is an access type) is (almost) equivalent to the @nt{attribute_reference} X.@key[all]'Access, where the result is of type T. The @nt{type_conversion} accepts a null value, whereas the @nt{attribute_reference} would raise Constraint_Error.]} @end{Discussion} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target type is an access-to-variable type, then the operand type shall be an access-to-variable type;]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If the target type is an access-to-constant type, then the operand type can be access-to-constant or access-to-variable.]} @end{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target designated type is tagged, then the operand designated type shall be convertible to the target designated type; @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[If the target designated type is not tagged, then the designated types shall be the same, and either the designated subtypes shall statically match or the target designated subtype shall be discriminated and unconstrained; and @PDefn2{Term=[statically matching],Sec=(required)}]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[These rules are designed to ensure that aliased array objects only @i(need) "dope" if their nominal subtype is unconstrained, but they can always @i(have) dope if required by the run-time model (since no sliding is permitted as part of access type conversion). By contrast, aliased discriminated objects will always @i(need) their discriminants stored with them, even if nominally constrained. (Here, we are assuming an implementation that represents an access value as a single pointer.)]} @end{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The access parameter case is handled by a run-time check. Run-time checks are also done in instance bodies.]} @end{Ramification} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is an access-to-subprogram type, then the operand type shall be an access-to-subprogram type. Further:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[The designated profiles shall be subtype-conformant.@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00251-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. If the operand type is declared within a generic body, the target type shall be declared within the generic body.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The reason it is illegal to convert from an access-to-subprogram type declared in a generic body to one declared outside that body is that in an implementation that shares generic bodies, procedures declared inside the generic need to have a different calling convention @em they need an extra parameter pointing to the data declared in the current instance. For procedures declared in the spec, that's OK, because the compiler can know about them at compile time of the instantiation.]} @end{Reason} @end(itemize) @Comment{We start the new text here, so we can modify the handful of rules that are not reformatted. (Except the first rule is at the top.)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0115-1]} @Leading@Defn2{Term=[type conversion],sec=[composite (non-array)]} @Defn2{Term=[conversion],sec=[composite (non-array)]} @Chg{Version=[2],New=[If there is a type@Chg{Version=[3],New=[ (other than a root numeric type)],Old=[]} that is an ancestor of both the target type and the operand type, or both types are class-wide types, then at least one of the following rules shall apply:],Old=[@Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)} If the target type is not included in any of the above four cases, there shall be a type that is an ancestor of both the target type and the operand type. Further, if the target type is tagged, then either:]} @begin(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)}The target type shall be untagged; or]} The operand type shall be covered by or descended from the target type; or @begin{Ramification} This is a conversion toward the root, which is always safe. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The operand type shall be a class-wide type that covers the target type@Chg{Version=[2],New=[; or],Old=[.]} @begin{Ramification} This is a conversion of a class-wide type toward the leaves, which requires a tag check. See @RunTimeTitle. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} These two rules imply that a conversion from @Chg{Version=[2],New=[an ancestor],Old=[a parent]} type to a type extension is not permitted, as this would require specifying the values for additional components, in general, and changing the tag. An @nt<extension_aggregate> has to be used instead, constructing a new value, rather than converting an existing value. However, a conversion from the class-wide type rooted at @Chg{Version=[2],New=[an ancestor],Old=[the parent]} type is permitted; such a conversion just verifies that the operand's tag is a descendant of the target. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The operand and target types shall both be class-wide types and the specific type associated with at least one of them shall be an interface type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow converting any class-wide type T'Class to or from a class-wide interface type even if the specific type T does not have an appropriate interface ancestor, because some extension of T might have the needed ancestor. This is similar to a conversion of a class-wide type toward the leaves of the tree, and we need to be consistent. Of course, there is a run-time check that the actual object has the needed interface.]} @end{Ramification} @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0115-1]} @Chg{Version=[2],New=[If there is no type@Chg{Version=[3],New=[ (other than a root numeric type)],Old=[]} that is the ancestor of both the target type and the operand type, and they are not both class-wide types, one of the following rules shall apply:], Old=[In a view conversion for an untagged type, the target type shall be convertible (back) to the operand type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=<Untagged view conversions appear only as [in] out parameters. Hence, the reverse conversion must be legal as well. The forward conversion must be legal even if an out parameter, because actual parameters of an access type are always copied in anyway.>} @end{Reason} @begin(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} If the target type is a numeric type, then the operand type shall be a numeric type.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} If the target type is an array type, then the operand type shall be an array type. Further:]} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The types shall have the same dimensionality;],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[Corresponding index types shall be convertible; @PDefn2{Term=[convertible],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[The component subtypes shall statically match; @PDefn2{Term=[statically matching],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00392-01]} @Chg{Version=[2],New=[If the component types are anonymous access types, then the accessibility level of the operand type shall not be statically deeper than that of the target type; @PDefn2{Term=[accessibility rule],Sec=(type conversion, array components)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For unrelated array types, the component types could have different accessibility, and we had better not allow a conversion of a local type into a global type, in case the local type points at local objects. We don't need a check for other types of components; such components necessarily are for related types, and either have the same accessibility or (for access discriminants) cannot be changed so the discriminant check will prevent problems.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[Neither the target type nor the operand type shall be limited;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We cannot allow conversions between unrelated limited types, as they may have different representations, and (since the types are limited), a copy cannot be made to reconcile the representations.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If the target type of a view conversion has aliased components, then so shall the operand type; and]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[We cannot allow a view conversion from an object with unaliased components to an object with aliased components, because that would effectively allow pointers to unaliased components. This rule was missing from Ada 95.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00246-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The operand type of a view conversion shall not have a tagged, private, or volatile subcomponent.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[We cannot allow view conversions between unrelated might-be-by-reference types, as they may have different representations, and a copy cannot be made to reconcile the representations.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules only apply to unrelated array conversions; different (weaker) rules apply to conversions between related types.]} @end{Ramification} @end(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[If the target type is @i<universal_access>, then the operand type shall be an access type.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such a conversion cannot be written explicitly, of course, but it can be implicit (see below).]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)}If the target type is a general access-to-object type, then the operand type shall be @i<universal_@!access> or an access-to-object type. Further, if the operand type is not @i<universal_@!access>:]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @LegalityTitle and @RunTimeTitle are worded so that a @nt{type_conversion} T(X) (where T is an access type) is (almost) equivalent to the @nt{attribute_reference} X.@key[all]'Access, where the result is of type T. The only difference is that the @nt{type_conversion} accepts a null value, whereas the @nt{attribute_reference} would raise Constraint_Error.]} @end{Discussion} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[If the target type is an access-to-variable type, then the operand type shall be an access-to-variable type;],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target type is an access-to-constant type, then the operand type can be access-to-constant or access-to-variable.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If the target designated type is tagged, then the operand designated type shall be convertible to the target designated type; @PDefn2{Term=[convertible],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the target designated type is not tagged, then the designated types shall be the same, and either:]} @begin(innerinneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01]} @Chg{Version=[2],New=[the designated subtypes shall statically match; or@PDefn2{Term=[statically matching],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00363-01],ARef=[AI95-00384-01]} @Chg{Version=[2],New=[the designated type shall be discriminated in its full view and unconstrained in any partial view, and one of the designated subtypes shall be unconstrained;],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[This does not require that types have a partial view in order to allow the conversion, simply that any partial view that does exist is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00384-01]} @ChgAdded{Version=[2],Text=[This allows conversions both ways (either subtype can be unconstrained); while Ada 95 only allowed the conversion if the target subtype is unconstrained. We generally want type conversions to be symmetric; which type is the target shouldn't matter for legality.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If the visible partial view is constrained, we do not allow conversion between unconstrained and constrained subtypes. This means that whether the full type had discriminants is not visible to clients of the partial view.]} @end{Reason} @end(innerinneritemize) @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are designed to ensure that aliased array objects only @i(need) "dope" if their nominal subtype is unconstrained, but they can always @i(have) dope if required by the run-time model (since no sliding is permitted as part of access type conversion). By contrast, aliased discriminated objects will always @i(need) their discriminants stored with them, even if nominally constrained. (Here, we are assuming an implementation that represents an access value as a single pointer.)]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0148-1],ARef=[AI05-0248-1]} @Chg{Version=[2],New=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type@Chg{Version=[3],New=[, unless the target type is an anonymous access type of a stand-alone object. If the target type is that of such a stand-alone object, the accessibility level of the operand type shall not be statically deeper than that of the declaration of the stand-alone object],Old=[]}. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0148-1]} @ChgAdded{Version=[2],Text=[The access parameter case is handled by a run-time check. Run-time checks are also done in instance bodies@Chg{Version=[3], New=[, and for stand-alone objects of anonymous access types],Old=[]}.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[We prohibit storing accesses to objects deeper than a stand-alone object of an anonymous access-to-object (even while we allow storing all other accesses) in order to prevent dangling accesses.]} @end{Reason} @end(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)}If the target type is a pool-specific access-to-object type, then the operand type shall be @i<universal_access>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This allows @b<null> to be converted to pool-specific types. Without it, @b<null> could be converted to general access types but not pool-specific ones, which would be too inconsistent. Remember that these rules only apply to unrelated types, so we don't have to talk about conversions to derived or other related types.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} If the target type is an access-to-subprogram type, then the operand type shall be @i<universal_@!access> or an access-to-subprogram type. Further, if the operand type is not @i<universal_@!access>:]} @begin(inneritemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0239-1]} @Chg{Version=[2],New=[The designated profiles shall be @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]}. @Defn2{Term=[subtype conformance],Sec=(required)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @Chg{Version=[2],New=[@PDefn2{Term=[accessibility rule],Sec=(type conversion)} The accessibility level of the operand type shall not be statically deeper than that of the target type. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. If the operand type is declared within a generic body, the target type shall be declared within the generic body.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The reason it is illegal to convert from an access-to-subprogram type declared in a generic body to one declared outside that body is that in an implementation that shares generic bodies, procedures declared inside the generic need to have a different calling convention @em they need an extra parameter pointing to the data declared in the current instance. For procedures declared in the spec, that's OK, because the compiler can know about them at compile time of the instantiation.]} @end{Reason} @end(inneritemize) @end(itemize) @end{Legality} @begin{StaticSem} A @nt{type_conversion} that is a value conversion denotes the value that is the result of converting the value of the operand to the target subtype. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} A @nt{type_conversion} that is a view conversion denotes a view of the object denoted by the operand. This view is a variable of the target type if the operand denotes a variable; otherwise@Chg{Version=[3],New=[,],Old=[]} it is a constant of the target type. @PDefn2{Term=[nominal subtype], Sec=(associated with a @nt<type_conversion>)} The nominal subtype of a @nt<type_conversion> is its target subtype. @end{StaticSem} @begin{RunTime} @Leading@PDefn2{Term=[evaluation], Sec=(value conversion)} @Defn2{Term=[corresponding value], Sec=(of the target type of a conversion)} @Defn{conversion} For the evaluation of a @nt<type_conversion> that is a value conversion, the operand is evaluated, and then the value of the operand is @i(converted) to a @i(corresponding) value of the target type, if any. @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If there is no value of the target type that corresponds to the operand value, Constraint_Error is raised@Redundant[; this can only happen on conversion to a modular type, and only when the operand value is outside the base range of the modular type.] Additional rules follow: @begin(itemize) @Defn2{Term=[type conversion],sec=(numeric)} @Defn2{Term=[conversion],sec=(numeric)} Numeric Type Conversion @begin(inneritemize) If the target and the operand types are both integer types, then the result is the value of the target type that corresponds to the same mathematical integer as the operand. If the target type is a decimal fixed point type, then the result is truncated (toward 0) if the value of the operand is not a multiple of the @i{small} of the target type. @Defn{accuracy} If the target type is some other real type, then the result is within the accuracy of the target type (see @RefSec{Numeric Performance Requirements}, for implementations that support the Numerics Annex). @begin(Discussion) An integer type might have more bits of precision than a real type, so on conversion (of a large integer), some precision might be lost. @end(Discussion) If the target type is an integer type and the operand type is real, the result is rounded to the nearest integer (away from zero if exactly halfway between two integers). @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00267-01]} This was implementation defined in Ada 83. There seems no reason to preserve the nonportability in Ada 95. Round-away-from-zero is the conventional definition of rounding, and standard Fortran and COBOL both specify rounding away from zero, so for interoperability, it seems important to pick this. This is also the most easily @lquotes@;undone@rquotes@; by hand. Round-to-nearest-even is an alternative, but that is quite complicated if not supported by the hardware. In any case, this operation is not @Chg{Version=[2],New=[usually],Old=[expected to be]} part of an inner loop, so predictability and portability are judged most important. @Chg{Version=[2],New=[A],Old=[We anticipate that a]} floating point attribute function Unbiased_Rounding @Chg{Version=[2], New=[is],Old=[will be]} provided@Chg{Version=[2], New=[ (see @RefSecNum{Attributes of Floating Point Types})],Old=[]} for those applications that require round-to-nearest-even@Chg{Version=[2], New=[, and a floating point attribute function Machine_Rounding (also see @RefSecNum{Attributes of Floating Point Types}) is provided for those applications that require the highest possible performance], Old=[]}. @lquotes@;Deterministic@rquotes@; rounding is required for static conversions to integer as well. See @RefSecNum{Static Expressions and Static Subtypes}. @end{Discussion} @end(inneritemize) @Defn2{Term=[type conversion],sec=(enumeration)} @Defn2{Term=[conversion],sec=(enumeration)} Enumeration Type Conversion @begin(inneritemize) The result is the value of the target type with the same position number as that of the operand value. @end(inneritemize) @Defn2{Term=[type conversion],sec=(array)} @Defn2{Term=[conversion],sec=(array)} Array Type Conversion @begin(inneritemize) @IndexCheck{Length_Check} If the target subtype is a constrained array subtype, then a check is made that the length of each dimension of the value of the operand equals the length of the corresponding dimension of the target subtype. The bounds of the result are those of the target subtype. @IndexCheck{Range_Check} If the target subtype is an unconstrained array subtype, then the bounds of the result are obtained by converting each bound of the value of the operand to the corresponding index type of the target type. @PDefn2{Term=[implicit subtype conversion],Sec=(array bounds)} For each nonnull index range, a check is made that the bounds of the range belong to the corresponding index subtype. @begin(Discussion) Only nonnull index ranges are checked, per AI83-00313. @end(Discussion) In either array case, the value of each component of the result is that of the matching component of the operand value (see @RefSecNum{Relational Operators and Membership Tests}). @begin{Ramification} This applies whether or not the component is initialized. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00392-01]} @ChgAdded{Version=[2],Text=[If the component types of the array types are anonymous access types, then a check is made that the accessibility level of the operand type is not deeper than that of the target type. @IndexCheck{Accessibility_Check}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check is needed for operands that are access parameters and in instance bodies. Other cases are handled by the legality rule given previously.]} @end{Reason} @end(inneritemize) @Defn2{Term=[type conversion],sec=[composite (non-array)]} @Defn2{Term=[conversion],sec=[composite (non-array)]} Composite (Non-Array) Type Conversion @begin(inneritemize) The value of each nondiscriminant component of the result is that of the matching component of the operand value. @begin{Ramification} This applies whether or not the component is initialized. @end{Ramification} @Redundant[The tag of the result is that of the operand.] @IndexCheck{Tag_Check} If the operand type is class-wide, a check is made that the tag of the operand identifies a (specific) type that is covered by or descended from the target type. @begin{Ramification} This check is certain to succeed if the operand type is itself covered by or descended from the target type. @end{Ramification} @begin{TheProof} The fact that a @nt{type_conversion} preserves the tag is stated officially in @RefSec{Tagged Types and Type Extensions} @end{TheProof} For each discriminant of the target type that corresponds to a discriminant of the operand type, its value is that of the corresponding discriminant of the operand value; @IndexCheck{Discriminant_Check} if it corresponds to more than one discriminant of the operand type, a check is made that all these discriminants are equal in the operand value. For each discriminant of the target type that corresponds to a discriminant that is specified by the @nt<derived_type_definition> for some ancestor of the operand type (or if class-wide, some ancestor of the specific type identified by the tag of the operand), its value in the result is that specified by the @nt<derived_type_definition>. @begin{Ramification} It is a ramification of the rules for the discriminants of derived types that each discriminant of the result is covered either by this paragraph or the previous one. See @RefSecNum(Discriminants). @end{Ramification} @IndexCheck{Discriminant_Check} For each discriminant of the operand type that corresponds to a discriminant that is specified by the @nt<derived_type_definition> for some ancestor of the target type, a check is made that in the operand value it equals the value specified for it. @IndexCheck{Range_Check} For each discriminant of the result, a check is made that its value belongs to its subtype. @end(inneritemize) @Defn2{Term=[type conversion],sec=(access)} @Defn2{Term=[conversion],sec=(access)} Access Type Conversion @begin(inneritemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0148-1],ARef=[AI05-0248-1]} For an access-to-object type, a check is made that the accessibility level of the operand type is not deeper than that of the target type@Chg{Version=[3],New=[, unless the target type is an anonymous access type of a stand-alone object. If the target type is that of such a stand-alone object, a check is made that the accessibility level of the operand type is not deeper than that of the declaration of the stand-alone object@Redundant[; then if the check succeeds, the accessibility level of the target type becomes that of the operand type]],Old=[]}. @IndexCheck{Accessibility_Check} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0148-1]} This check is needed for operands that are access parameters@Chg{Version=[3],New=[, for stand-alone anonymous access objects,],Old=[]} and in instance bodies. Note that this check can never fail for the implicit conversion to the anonymous type of an access parameter that is done when calling a subprogram with an access parameter. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01]} If the @Chg{Version=[2],New=[],Old=[target type is an anonymous access type, a check is made that the value of the operand is not null; if the target is not an anonymous access type, then the result is null if the ]}operand value is null@Chg{Version=[2],New=[, the result of the conversion is the null value of the target type.],Old=[. @IndexCheck{Access_Check}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised]} A conversion to an anonymous access type happens implicitly as part of initializing @Chg{Version=[2],New=[or assigning to an anonymous access object], Old=[an access discriminant or access parameter]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00231-01]} @ChgDeleted{Version=[2],Text=[As explained in @RefSec{Access Types}, it is important that a value of an anonymous access type can never be null.]} @end{Reason} If the operand value is not null, then the result designates the same object (or subprogram) as is designated by the operand value, but viewed as being of the target designated subtype (or profile); any checks associated with evaluating a conversion to the target designated subtype are performed. @begin{Ramification} The checks are certain to succeed if the target and operand designated subtypes statically match. @end{Ramification} @end(inneritemize) @end(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0290-1]} @IndexCheck{Range_Check} @IndexCheck{Discriminant_Check} @IndexCheck{Index_Check} @Chg{Version=[2],New=[@IndexCheck{Access_Check}],Old=[]} After conversion of the value to the target type, if the target subtype is constrained, a check is performed that the value satisfies this constraint.@Chg{Version=[2], New=[ If the target subtype excludes null, then a check is made that the value is not null.],Old=[]}@Chg{Version=[3], New=[ If predicate checks are enabled for the target subtype (see @RefSecNum{Subtype Predicates}), a check is performed that the predicate of the target subtype is satisfied for the value.@Defn2{Term=[predicate check], Sec=[subtype conversion]}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} The @Chg{Version=[2],New=[first],Old=[above]} check @Chg{Version=[2],New=[above ],Old=[]}is a Range_Check for scalar subtypes, a Discriminant_Check or Index_Check for access subtypes, and a Discriminant_Check for discriminated subtypes. The Length_Check for an array conversion is performed as part of the conversion to the target type.@Chg{Version=[2], New=[ The check for exclusion of null is an Access_Check.],Old=[]} @end{Ramification} @PDefn2{Term=[evaluation], Sec=(view conversion)} For the evaluation of a view conversion, the operand @nt<name> is evaluated, and a new view of the object denoted by the operand is created, whose type is the target type; @IndexCheck{Length_Check} @IndexCheck{Tag_Check} @IndexCheck{Discriminant_Check} if the target type is composite, checks are performed as above for a value conversion. @Leading@;The properties of this new view are as follows: @begin(itemize) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} If the target type is composite, the bounds or discriminants (if any) of the view are as defined above for a value conversion; each nondiscriminant component of the view denotes the matching component of the operand object; the subtype of the view is constrained if either the target subtype or the operand object is constrained, @Chg{New=[or if the target subtype is indefinite,],Old=[]} or if the operand type is a descendant of the target type@Chg{New=[],Old=[,]} and has discriminants that were not inherited from the target type; If the target type is tagged, then an assignment to the view assigns to the corresponding part of the object denoted by the operand; otherwise, an assignment to the view assigns to the object, after converting the assigned value to the subtype of the object (which might raise Constraint_Error); @PDefn2{Term=[implicit subtype conversion],Sec=(assignment to view conversion)} Reading the value of the view yields the result of converting the value of the operand object to the target subtype (which might raise Constraint_Error), except if the object is of an access type and the view conversion is passed as an @key(out) parameter; in this latter case, the value of the operand object is used to initialize the formal parameter without checking against any constraint of the target subtype (see @RefSecNum(Parameter Associations)). @PDefn2{Term=[implicit subtype conversion],Sec=(reading a view conversion)} @begin(Reason) This ensures that even an @key(out) parameter of an access type is initialized reasonably. @end(Reason) @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)}@Chg{Version=[3],New=[ @Defn2{Term=(Assertion_Error),Sec=(raised by failure of run-time check)}],Old=[]} If an Accessibility_Check fails, Program_Error is raised. @Chg{Version=[3],New=[If a predicate check fails, Assertions.Assertion_Error is raised. ],Old=[]}Any other check associated with a conversion raises Constraint_Error if it fails. Conversion to a type is the same as conversion to an unconstrained subtype of the type. @begin{Reason} This definition is needed because the semantics of various constructs involves converting to a type, whereas an explicit @nt{type_conversion} actually converts to a subtype. For example, the evaluation of a @nt{range} is defined to convert the values of the expressions to the type of the range. @end{Reason} @begin{Ramification} A conversion to a scalar type, or, equivalently, to an unconstrained scalar subtype, can raise Constraint_Error if the value is outside the base range of the type. @end{Ramification} @end{RunTime} @begin{Notes} @RootDefn{implicit subtype conversion} In addition to explicit @nt<type_conversion>s, type conversions are performed implicitly in situations where the expected type and the actual type of a construct differ, as is permitted by the type resolution rules (see @RefSecNum(The Context of Overload Resolution)). For example, an integer literal is of the type @i(universal_integer), and is implicitly converted when assigned to a target of some specific integer type. Similarly, an actual parameter of a specific tagged type is implicitly converted when the corresponding formal parameter is of a class-wide type. @NoPrefix@;@RootDefn{implicit subtype conversion} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Even when the expected and actual types are the same, implicit subtype conversions are performed to adjust the array bounds (if any) of an operand to match the desired target subtype, or to raise Constraint_Error if the (possibly adjusted) value does not satisfy the constraints of the target subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} A ramification of the overload resolution rules is that the operand of an (explicit) @nt<type_conversion> cannot be @Chg{Version=[2],New=[],Old=[the literal @key(null), ]}an @nt<allocator>, an @nt<aggregate>, a @nt<string_literal>, a @nt<character_literal>, or an @nt<attribute_reference> for an Access or Unchecked_Access attribute. Similarly, such an @nt{expression} enclosed by parentheses is not allowed. A @nt<qualified_expression> (see @RefSecNum(Qualified Expressions)) can be used instead of such a @nt<type_conversion>. The constraint of the target subtype has no effect for a @nt<type_conversion> of an elementary type passed as an @key(out) parameter. Hence, it is recommended that the first subtype be specified as the target to minimize confusion (a similar recommendation applies to renaming and generic formal @key(in out) objects). @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of numeric type conversion:) @begin{Example} Real(2*J) @RI[-- value is converted to floating point] Integer(1.6) @RI[-- value is 2] Integer(-0.4) @RI[-- value is 0] @end{Example} @begin{WideAbove} @leading@keepnext@i(Example of conversion between derived types:) @end{WideAbove} @begin{Example} @key(type) A_Form @key(is) @key(new) B_Form; X : A_Form; Y : B_Form; X := A_Form(Y); Y := B_Form(X); @RI[-- the reverse conversion ] @end{Example} @begin{WideAbove} @leading@keepnext@i(Examples of conversions between array types:) @end{WideAbove} @begin{Example} @key(type) Sequence @key(is) @key(array) (Integer @key(range) <>) @key(of) Integer; @key(subtype) Dozen @key(is) Sequence(1 .. 12); Ledger : @key(array)(1 .. 100) @key(of) Integer; Sequence(Ledger) @RI[-- bounds are those of Ledger] Sequence(Ledger(31 .. 42)) @RI[-- bounds are 31 and 42] Dozen(Ledger(31 .. 42)) @RI[-- bounds are those of Dozen ] @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} A @nt<character_literal> is not allowed as the operand of a @nt<type_conversion>, since there are now two character types in package Standard. The component subtypes have to statically match in an array conversion, rather than being checked for matching constraints at run time. Because sliding of array bounds is now provided for operations where it was not in Ada 83, programs that used to raise Constraint_Error might now continue executing and produce a reasonable result. This is likely to fix more bugs than it creates. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} A @nt<type_conversion> is considered the name of an object in certain circumstances (such a @nt<type_conversion> is called a view conversion). In particular, as in Ada 83, a @nt<type_conversion> can appear as an @key(in out) or @key(out) actual parameter. In addition, if the target type is tagged and the operand is the @nt<name> of an object, then so is the @nt<type_conversion>, and it can be used as the @nt<prefix> to a @nt<selected_component>, in an @nt<object_renaming_declaration>, etc. We no longer require type-mark conformance between a parameter of the form of a type conversion, and the corresponding formal parameter. This had caused some problems for inherited subprograms (since there isn't really a type-mark for converted formals), as well as for renamings, formal subprograms, etc. See AI83-00245, AI83-00318, AI83-00547. We now specify @lquotes@;deterministic@rquotes@; rounding from real to integer types when the value of the operand is exactly between two integers (rounding is away from zero in this case). @lquotes@;Sliding@rquotes@; of array bounds (which is part of conversion to an array subtype) is performed in more cases in Ada 95 than in Ada 83. Sliding is not performed on the operand of a membership test, nor on the operand of a @nt{qualified_expression}. It wouldn't make sense on a membership test, and we wish to retain a connection between subtype membership and subtype qualification. In general, a subtype membership test returns True if and only if a corresponding subtype qualification succeeds without raising an exception. Other operations that take arrays perform sliding. @end{Extend83} @begin{DiffWord83} We no longer explicitly list the kinds of things that are not allowed as the operand of a @nt<type_conversion>, except in a NOTE. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The rules in this @Chg{Version=[3],New=[subclause],Old=[clause]} subsume the rules for "parameters of the form of a type conversion," and have been generalized to cover the use of a type conversion as a @nt<name>. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00246-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Conversions between unrelated array types that are limited or (for view conversions) might be by-reference types are now illegal. The representations of two such arrays may differ, making the conversions impossible. We make the check here, because legality should not be based on representation properties. Such conversions are likely to be rare, anyway. There is a potential that this change would make a working program illegal (if the types have the same representation).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If a discriminated full type has a partial view (private type) that is constrained, we do not allow conversion between access-to-unconstrained and access-to-constrained subtypes designating the type. Ada 95 allowed this conversion and the declaration of various access subtypes, requiring that the designated object be constrained and thus making details of the implementation of the private type visible to the client of the private type. See @RefSecNum{Allocators} for more on this topic.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Conversion rules for @i<universal_access> were defined. These allow the use of anonymous access values in equality tests (see @RefSecNum{Relational Operators and Membership Tests}), and also allow the use of @b<null> in type conversions and other contexts that do not provide a single expected type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00384-01]} @ChgAdded{Version=[2],Text=[A type conversion from an access-to-discriminated and unconstrained object to an access-to-discriminated and constrained one is allowed. Ada 95 only allowed the reverse conversion, which was weird and asymmetric. Of course, a constraint check will be performed for this conversion.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Wording was added to ensure that view conversions are constrained, and that a tagged view conversion has a tagged object. Both rules are needed to avoid having a way to change the discriminants of a constrained object.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0008],ARef=[AI95-00168-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Wording was added to ensure that the aliased status of array components cannot change in a view conversion. This rule was needed to avoid having a way to change the discriminants of an aliased object. This rule was repealed later, as Ada 2005 allows changing the discriminants of an aliased object.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Wording was added to check subtypes that exclude null (see @RefSecNum{Access Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The organization of the legality rules was changed, both to make it clearer, and to eliminate an unintentional incompatibility with Ada 83. The old organization prevented type conversions between some types that were related by derivation (which Ada 83 always allowed).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00330-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[Clarified that an untagged type conversion appearing as a generic actual parameter for a generic @key{in out} formal parameter is not a view conversion (and thus is illegal). This confirms the ACATS tests, so all implementations already follow this @Chg{Version=[3],New=[interpretation],Old=[intepretation]}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[Rules added by the Corrigendum to eliminate problems with discriminants of aliased components changing were removed, as we now generally allow discriminants of aliased components to be changed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00392-01]} @ChgAdded{Version=[2],Text=[Accessibility checks on conversions involving types with anonymous access components were added. These components have the level of the type, and conversions can be between types at different levels, which could cause dangling access values in the absence of such checks.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0148-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}A stand-alone object of an anonymous access-to-object type now has dynamic accessibility. Normally, this will make programs legal that were illegal in Ada 2005. However, it is possible that a program that previously raised Program_Error now will not. It is very unlikely that an existing program intentionally depends on the exception being raised; the change is more likely to fix bugs than introduce them.]} @end{Inconsistent2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that a root numeric type is not considered a common ancestor for a conversion.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Added rules so that predicate aspects (see @RefSecNum{Subtype Predicates}) are enforced on subtype conversion.]} @end{Diffword2005} @LabeledClause{Qualified Expressions} @begin{Intro} @Redundant[A @nt<qualified_expression> is used to state explicitly the type, and to verify the subtype, of an operand that is either an @nt<expression> or an @nt<aggregate>. @IndexSeeAlso{Term=[type conversion],See=(qualified_expression)}] @end{Intro} @begin{Syntax} @Syn{lhs=<qualified_expression>,rhs=" @Syn2{subtype_mark}@SingleQuote@;(@Syn2{expression}) | @Syn2{subtype_mark}@SingleQuote@Syn2{aggregate}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[operand], Sec=(of a @nt{qualified_expression})} The @i(operand) (the @nt{expression} or @nt{aggregate}) shall resolve to be of the type determined by the @nt{subtype_@!mark}, or a universal type that covers it. @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[@Redundant[If the operand of a @nt{qualified_expression} denotes an object, the @nt{qualified_expression} denotes a constant view of that object.] The nominal subtype of a @nt{qualified_expression} is the subtype denoted by the @nt{subtype_mark}.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[This is stated in @RefSecNum{Objects and Named Numbers}.]} @end{TheProof} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(qualified_expression)} @IndexCheck{Range_Check} @IndexCheck{Discriminant_Check} @IndexCheck{Index_Check} The evaluation of a @nt{qualified_expression} evaluates the operand (and if of a universal type, converts it to the type determined by the @nt{subtype_mark}) and checks that its value belongs to the subtype denoted by the @nt{subtype_mark}. @PDefn2{Term=[implicit subtype conversion],Sec=(qualified_expression)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised if this check fails. @begin{Ramification} This is one of the few contexts in Ada 95 where implicit subtype conversion is not performed prior to a constraint check, and hence no @lquotes@;sliding@rquotes@; of array bounds is provided. @end{Ramification} @begin{Reason} Implicit subtype conversion is not provided because a @nt<qualified_expression> with a constrained target subtype is essentially an assertion about the subtype of the operand, rather than a request for conversion. An explicit @nt<type_conversion> can be used rather than a @nt<qualified_expression> if subtype conversion is desired. @end{Reason} @end{RunTime} @begin{Notes} When a given context does not uniquely identify an expected type, a @nt<qualified_expression> can be used to do so. In particular, if an overloaded @nt<name> or @nt<aggregate> is passed to an overloaded subprogram, it might be necessary to qualify the operand to resolve its type. @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of disambiguating expressions using qualification:) @begin{Example} @key(type) Mask @key(is) (Fix, Dec, Exp, Signif); @key(type) Code @key(is) (Fix, Cla, Dec, Tnz, Sub); Print (Mask'(Dec)); @RI[-- Dec is of type Mask] Print (Code'(Dec)); @RI[-- Dec is of type Code ] @key(for) J @key(in) Code'(Fix) .. Code'(Dec) @key(loop) ... @RI[-- qualification needed for either Fix or Dec] @key(for) J @key(in) Code @key(range) Fix .. Dec @key(loop) ... @RI[-- qualification unnecessary] @key(for) J @key(in) Code'(Fix) .. Dec @key(loop) ... @RI[-- qualification unnecessary for Dec] Dozen'(1 | 3 | 5 | 7 => 2, @key(others) => 0) @RI[-- see @RefSecNum{Type Conversions} ] @end{Example} @end{Examples} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[Added a definition of the nominal subtype of a @nt{qualified_expression}.]} @end{DiffWord2005} @LabeledClause{Allocators} @begin{Intro} @Redundant[The evaluation of an @nt<allocator> creates an object and yields an access value that designates the object. @IndexSee{Term=[new],See=(allocator)} @IndexSee{Term=[malloc],See=(allocator)} @IndexSeeAlso{Term=[heap management],See=(allocator)}] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} @Syn{lhs=<allocator>,rhs=" @key{new} @Chg{Version=[3],New=<[@Syn2{subpool_specification}] >,Old=<>}@Syn2{subtype_indication}@Chg{Version=[3],New=< >,Old=<>} | @key{new} @Chg{Version=[3],New=<[@Syn2{subpool_specification}] >,Old=<>}@Syn2{qualified_expression}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0111-3]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<subpool_specification>,Old=<>}>, rhs="@Chg{Version=[3],New=<(@SynI{subpool_handle_}@Syn2{name})>,Old=<>}"} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0104-1]} @ChgAdded{Version=[3],Text=[For an @nt{allocator} with a @nt{subtype_indication}, the @nt{subtype_indication} shall not specify a @nt{null_exclusion}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Such an uninitialized @nt{allocator} would necessarily raise Constraint_Error, as the default value is @key[null]. Also note that the syntax does not allow a @nt{null_exclusion} in an initialized @nt{allocator}, so it makes sense to make the uninitialized case illegal as well.]} @end{Reason} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3],ARef=[AI05-0269-1]} @PDefn2{Term=[expected type],Sec=(allocator)} The expected type for an @nt<allocator> shall be a single access-to-object type @Chg{New=[with],Old=[whose]} designated type @Chg{New=[@i<D> such that either @i<D>],Old=[]} covers the type determined by the @nt<subtype_mark> of the @nt<subtype_@!indication> or @nt<qualified_@!expression>@Chg{New=[, or the expected type is anonymous and the determined type is @i<D>'Class],Old=[]}.@Chg{Version=[3],New=[ A @SynI{subpool_handle_}@nt{name} is expected to be of any type descended from Subpool_Handle, which is the type used to identify a subpool, declared in package System.Storage_Pools.Subpools (see @RefSecNum{Storage Subpools}).@PDefn2{Term=[expected type],Sec=(subpool_handle_name)}],Old=[]} @begin{Discussion} See @RefSec(The Context of Overload Resolution) for the meaning of @lquotes@;shall be a single ... type whose ...@rquotes@; @end{Discussion} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0010],ARef=[AI95-00127-01]} @Chg{New=[An @nt{allocator} is allowed as a controlling parameter of a dispatching call (see @RefSecNum{Dispatching Operations of Tagged Types}).],Old=[]} @end{Ramification} @end{Resolution} @begin{Legality} @Defn{initialized allocator} An @i(initialized) allocator is an @nt{allocator} with a @nt{qualified_expression}. @Defn{uninitialized allocator} An @i(uninitialized) allocator is one with a @nt{subtype_indication}. In the @nt<subtype_indication> of an uninitialized allocator, a @nt<constraint> is permitted only if the @nt<subtype_mark> denotes an @Redundant[unconstrained] composite subtype; if there is no @nt<constraint>, then the @nt<subtype_mark> shall denote a definite subtype. @IndexSee{Term=[constructor],See=[initialized allocator]} @begin{Ramification} For example, ... @key[new] S'Class ... (with no initialization expression) is illegal, but ... @key[new] S'Class'(X) ... is legal, and takes its tag and constraints from the initial value X. (Note that the former case cannot have a constraint.) @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} If the type of the @nt<allocator> is an access-to-constant type, the @nt<allocator> shall be an initialized allocator. @Chg{Version=[2],New=[],Old=[If the designated type is limited, the @nt<allocator> shall be an uninitialized allocator.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[For an access-to-constant type whose designated type is limited, @nt{allocator}s are illegal. The Access attribute is legal for such a type, however.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[If a @nt{subpool_specification} is given, the type of the storage pool of the access type shall be a descendant of Root_Storage_Pool_With_Subpools.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Because the paragraph numbers changed} @ChgAdded{Version=[2],Text=[If the designated type of the type of the @nt{allocator} is class-wide, the accessibility level of the type determined by the @nt{subtype_indication} or @nt{qualified_expression} shall not be statically deeper than that of the type of the @nt{allocator}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the allocated object from outliving its type.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0051-1]} @ChgAdded{Version=[2],Text=[If the @Chg{Version=[3],New=[subtype determined by the @nt{subtype_indication} or @nt{qualified_expression}],Old=[designated subtype of the type]} of the @nt{allocator} has one or more @Chg{Version=[3],New=[],Old=[unconstrained ]}access discriminants, then the accessibility level of the anonymous access type of each access discriminant@Chg{Version=[3],New=[],Old=[, as determined by the @nt{subtype_indication} or @nt{qualified_expression} of the @nt{allocator},]} shall not be statically deeper than that of the type of the @nt{allocator} (see @RefSecNum{Operations of Access Types}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the allocated object from outliving its discriminants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0052-1],ARef=[AI05-0157-1]} @ChgAdded{Version=[2],Text=[An @nt{allocator} shall not be of an access type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. @Chg{Version=[3],New=[], Old=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit. This rule does not apply in the body of a generic unit or within a body declared within the declarative region of a generic unit, if the type of the allocator is a descendant of a formal access type declared within the formal part of the generic unit.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An @nt{allocator} for an access type that has Storage_Size specified to be zero is required to raise Storage_Error anyway. It's better to detect the error at compile-time, as the @nt{allocator} might be executed infrequently. This also simplifies the rules for Pure units, where we do not want to allow any allocators for library-level access types, as they would represent state.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0157-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[We don't need a special rule to cover generic formals (unlike many other similar @LegalityTitle). There are only two cases of interest. For formal access types, the Storage_Size property is not known in the generic, and surely isn't static, so this @LegalityName can never apply. For a formal derived type, this @LegalityName can only be triggered by a parent type having one of the appropriate properties. But Storage_Size can never be specified for a derived access type, so it always has the same value for all child types; additionally, a type derived from a remote access type (which has Storage_Size defined to be zero) is also a remote access type. That means that any actual that would match the formal derived type necessarily has the same Storage_Size properties, so it is harmless (and preferable) to check them in the body - they are always known in that case. For other formal types,@nt{allocator}s are not allowed, so we don't need to consider them. So we don't need an assume-the-best rule here.],Old=[The last sentence covers the case of children of generics, and formal access types of formal packages of the generic unit.]}]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0052-1]} @ChgAdded{Version=[3],Text=[If the designated type of the type of the @nt{allocator} is limited, then the @nt{allocator} shall not be used to define the value of an access discriminant, unless the discriminated type is immutably limited (see @RefSecNum{Limited Types}).]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Because coextensions work very much like parts, we don't want users creating limited coextensions for nonlimited types. This would be similar to extending a nonlimited type with a limited component. We check this on the @nt{allocator}. Note that there is an asymmetry in what types are considered limited; this is required to preserve privacy. We have to assume that the designated type might be limited as soon as we see a limited partial view, but we want to ensure that the containing object is of a type that is always limited.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0052-1]} @ChgAdded{Version=[3],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This applies to all of the @LegalityTitle of this subclause.]} @end{Discussion} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0041-1]} If the designated type of the type of the @nt<allocator> is elementary, then the subtype of the created object is the designated subtype. If the designated type is composite, then the @Chg{Version=[2],New=[subtype of the ],Old=[]}created object is @Chg{Version=[2],New=[the designated subtype when the designated subtype is constrained or there is @Chg{Version=[3],New=[an ancestor of the designated type that has a constrained],Old=[a]} partial view@Chg{Version=[3],New=[],Old=[ of the designated type that is constrained]}; otherwise, the created],Old=[always constrained; if the designated subtype is constrained, then it provides the constraint of the created object; otherwise, the]} object is constrained by its initial value @Redundant[(even if the designated subtype is unconstrained with defaults)]. @PDefn{constrained by its initial value} @begin{Discussion} See AI83-00331. @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} All objects created by an @Chg{Version=[2],New=[@nt{allocator}],Old=[allocator]} are aliased, and @Chg{Version=[2],New=[most],Old=[all]} aliased composite objects need to be constrained so that access subtypes work reasonably. @Chg{Version=[2],New=[Problematic access subtypes are prohibited for types with a constrained partial view.],Old=[]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[If there is a constrained partial view of the type, this allows the objects to be unconstrained. This eliminates privacy breaking (we don't want the objects to act differently simply because they're allocated). Such a created object is effectively constrained by its initial value if the access type is an access-to-constant type, or the designated type is limited (in all views), but we don't need to state that here. It is implicit in other rules. Note, however, that a value of an access-to-constant type can designate a variable object via 'Access or conversion, and the variable object might be assigned by some other access path, and that assignment might alter the discriminants.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @PDefn2{Term=[evaluation], Sec=(allocator)} For the evaluation of an @Chg{Version=[2],New=[initialized allocator], Old=[@nt<allocator>]}, the @Chg{Version=[2],New=[],Old=[elaboration of the @nt<subtype_indication> or the ]}evaluation of the @nt<qualified_expression> is performed first. @PDefn2{Term=[evaluation], Sec=(initialized allocator)} @Defn2{Term=[assignment operation], Sec=(during evaluation of an initialized allocator)} @Chg{Version=[2],New=[An],Old=[For the evaluation of an initialized allocator, an]} object of the designated type is created and the value of the @nt<qualified_expression> is converted to the designated subtype and assigned to the object. @PDefn2{Term=[implicit subtype conversion],Sec=(initialization expression of allocator)} @begin{Ramification} The conversion might raise Constraint_Error. @end{Ramification} @PDefn2{Term=[evaluation], Sec=(uninitialized allocator)} @Leading@keepnext@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} For the evaluation of an uninitialized allocator@Chg{Version=[2],New=[, the elaboration of the @nt{subtype_indication} is performed first. Then],Old=[]}: @begin(itemize) @Defn2{Term=[assignment operation], Sec=(during evaluation of an uninitialized allocator)} If the designated type is elementary, an object of the designated subtype is created and any implicit initial value is assigned; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @Chg{Version=[2],New=[],Old=[@Defn2{Term=[assignment operation], Sec=(during evaluation of an uninitialized allocator)}]} If the designated type is composite, an object of the designated type is created with tag, if any, determined by the @nt<subtype_mark> of the @nt<subtype_indication>@Chg{Version=[2],New=[. This object is then initialized by default (see @RefSecNum{Object Declarations}) using],Old=[; any per-object constraints on subcomponents are elaborated @Chg{New=[(see @RefSecNum{Record Types}) ],Old=[]}and any implicit initial values for the subcomponents of the object are obtained as determined by]} the @nt<subtype_indication> @Chg{Version=[2],New=[to determine its nominal subtype], Old=[and assigned to the corresponding subcomponents]}. @IndexCheck{Index_Check} @IndexCheck{Discriminant_Check} A check is made that the value of the object belongs to the designated subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. This check and the initialization of the object are performed in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Discussion} AI83-00150. @end{Discussion} @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0024-1],ARef=[AI05-0051-1],ARef=[AI05-0234-1]} @ChgAdded{Version=[2],Text=[For any @nt{allocator}, if the designated type of the type of the @nt{allocator} is class-wide, then a check is made that the @Chg{Version=[3],New=[master], Old=[accessibility level]} of the type determined by the @nt{subtype_indication}, or by the tag of the value of the @nt{qualified_expression}, @Chg{Version=[3],New=[includes the elaboration], Old=[is not deeper than that]} of the type of the @nt{allocator}. If @Chg{Version=[3],New=[any part of ],Old=[]}the @Chg{Version=[3],New=[subtype determined by the @nt{subtype_indication} or @nt{qualified_expression}],Old=[designated subtype]} of the @nt{allocator} @Chg{Version=[3],New=[(or by the tag of the value if the type of the @nt{qualified_expression} is class-wide) ],Old=[]}has one or more @Chg{Version=[3],New=[],Old=[unconstrained ]}access discriminants, then a check is made that the accessibility level of the anonymous access type of each access discriminant is not deeper than that of the type of the @nt{allocator}. Program_Error is raised if either such check fails.@IndexCheck{Accessibility_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0024-1]} @ChgAdded{Version=[2],Text=[The @Chg{Version=[3],New=[master],Old=[accessibility]} check on class-wide types prevents the allocated object from outliving its type. We need the run-time check in instance bodies, or when the type of the @nt{qualified_expression} is class-wide (other cases are statically detected).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0024-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[We can't use the normal accessibility level @lquotes@;deeper than@rquotes@; check here because we may have @lquotes@;incomparable@rquotes@; levels if the appropriate master and the type declaration belong to two different tasks. This can happen when checking the master of the tag for an allocator initialized by a parameter passed in to an accept statement, if the type of the allocator is an access type declared in the enclosing task body. For example:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[task body] TT @key[is] @key[type] Acc_TC @key[is access] T'Class; P : Acc_TC; @key[begin] @key[accept] E(X : T'Class) @key[do] P := @key[new] T'Class'(X); @RI[-- Master check on tag of X.] @RI[-- Can't use "accessibility levels" since they might be incomparable.] @RI[-- Must revert to checking that the master of the type identified by] @RI[-- X'tag includes the elaboration of Acc_TC, so it is sure to outlive it.] @key[end] E;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The accessibility check on access discriminants prevents the allocated object from outliving its discriminants.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @Chg{Version=[2],New=[If the object to be created by an @nt<allocator> has a controlled or protected part, and the finalization of the collection of the type of the @nt{allocator} (see @RefSecNum{Completion and Finalization}) has started, Program_Error is raised.@IndexCheck{Allocation_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the object has a controlled or protected part, its finalization is likely to be nontrivial. If the allocation was allowed, we could not know whether the finalization would actually be performed. That would be dangerous to otherwise safe abstractions, so we mandate a check here. On the other hand, if the finalization of the object will be trivial, we do not require (but allow) the check, as no real harm could come from late allocation.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check can only fail if an @nt{allocator} is evaluated in code reached from a Finalize routine for a type declared in the same master. That's highly unlikely; Finalize routines are much more likely to be deallocating objects than allocating them.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @Chg{Version=[2],New=[If the object to be created by an @nt<allocator> contains any tasks, and the master of the type of the @nt<allocator> is completed, and all of the dependent tasks of the master are terminated (see @RefSecNum{Task Dependence - Termination of Tasks}), then Program_Error is raised.@IndexCheck{Allocation_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A task created after waiting for tasks has finished could depend on freed data structures, and certainly would never be awaited.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[If the @nt{allocator} includes a @SynI{subpool_handle_}@nt{name}, Constraint_Error is raised if the subpool handle is @key[null]. Program_Error is raised if the subpool does not @i<belong> (see @RefSecNum{Storage Subpools}) to the storage pool of the access type of the @nt{allocator}.@IndexCheck{Access_Check}@IndexCheck{Allocation_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This can be implemented by comparing the result of Pool_of_Subpool to a reference to the storage pool object. Pool_of_Subpool's parameter is @key[not null], so the check for null falls out naturally.]} @end{ImplNote} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This detects cases where the subpool belongs to another pool, or to no pool at all. This includes detecting dangling subpool handles so long as the subpool object (the object designated by the handle) still exists. (If the subpool object has been deallocated, execution is erroneous; it is likely that this check will still detect the problem, but there cannot be a guarantee.)]} @end{Reason} @Redundant[If the created object contains any tasks, they are activated (see @RefSecNum(Task Execution - Task Activation)).] Finally, an access value that designates the created object is returned. @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error if the finalization of the collection of the type (see @RefSecNum{Completion and Finalization}) of the @nt<allocator> has started. If the error is detected, Program_Error is raised. Otherwise, the allocation proceeds normally.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This check is required in some cases; see above.]} @end{Discussion} @end{Bounded} @begin{Notes} Allocators cannot create objects of an abstract type. See @RefSecNum{Abstract Types and Subprograms}. If any part of the created object is controlled, the initialization includes calls on corresponding Initialize or Adjust procedures. See @RefSecNum{Assignment and Finalization}. As explained in @RefSec{Storage Management}, the storage for an object allocated by an @nt{allocator} comes from a storage pool (possibly user defined). @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} The exception Storage_Error is raised by an @nt<allocator> if there is not enough storage. Instances of Unchecked_Deallocation may be used to explicitly reclaim storage. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Implementations are permitted, but not required, to provide garbage collection@Chg{Version=[3],New=[],Old=[ (see @RefSecNum{Default Storage Pools})]}. @begin{Ramification} Note that in an @nt<allocator>, the exception Constraint_Error can be raised by the evaluation of the @nt<qualified_expression>, by the elaboration of the @nt<subtype_indication>, or by the initialization. @end{Ramification} @begin{Discussion} By default, the implementation provides the storage pool. The user may exercise more control over storage management by associating a user-defined pool with an access type. @end{Discussion} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of allocators:} @begin{Example} @key(new) Cell'(0, @key(null), @key(null)) @RI[-- initialized explicitly, see @RefSecNum{Incomplete Type Declarations}] @key(new) Cell'(Value => 0, Succ => @key(null), Pred => @key(null)) @RI[-- initialized explicitly] @key(new) Cell @RI[-- not initialized] @key(new) Matrix(1 .. 10, 1 .. 20) @RI[-- the bounds only are given] @key(new) Matrix'(1 .. 10 => (1 .. 20 => 0.0)) @RI[-- initialized explicitly] @key(new) Buffer(100) @RI[-- the discriminant only is given] @key(new) Buffer'(Size => 80, Pos => 0, Value => (1 .. 80 => 'A')) @RI[-- initialized explicitly] Expr_Ptr'(@key(new) Literal) @RI[-- allocator for access-to-class-wide type, see @RefSecNum{Type Extensions}] Expr_Ptr'(@key(new) Literal'(Expression @key[with] 3.5)) @RI[-- initialized explicitly] @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00019} @Defn{incompatibilities with Ada 83} The @nt<subtype_indication> of an uninitialized allocator may not have an explicit @nt<constraint> if the designated type is an access type. In Ada 83, this was permitted even though the @nt<constraint> had no @Chg{New=[e],Old=[a]}ffect on the subtype of the created object. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Allocators creating objects of type @i(T) are now overloaded on access types designating @i(T')Class and all class-wide types that cover @i(T). Implicit array subtype conversion (sliding) is now performed as part of an initialized allocator. @end{Extend83} @begin{DiffWord83} We have used a new organization, inspired by the ACID document, that makes it clearer what is the subtype of the created object, and what subtype conversions take place. Discussion of storage management issues, such as garbage collection and the raising of Storage_Error, has been moved to @RefSec{Storage Management}. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95}If the designated type has a constrained partial view, the allocated object can be unconstrained. This might cause the object to take up a different amount of memory, and might cause the operations to work where they previously would have raised Constraint_Error. It's unlikely that the latter would actually matter in a real program (Constraint_Error usually indicates a bug that would be fixed, not left in a program.) The former might cause Storage_Error to be raised at a different time than in an Ada 95 program.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95}An @nt{allocator} for an access type that has Storage_Size specified to be zero is now illegal. Ada 95 allowed the @nt{allocator}, but it had to raise Storage_Error if executed. The primary impact of this change should be to detect bugs.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0010],ARef=[AI95-00127-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}@b<Corrigendum:> An @nt{allocator} can be a controlling parameter of a dispatching call. This was an oversight in Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Initialized @nt{allocator}s are allowed when the designated type is limited.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the elaboration of per-object constraints for an uninitialized allocator.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Program_Error is now raised if the @nt{allocator} occurs after the finalization of the collection or the waiting for tasks. This is not listed as an incompatibility as the Ada 95 behavior was unspecified, and Ada 95 implementations tend to generate programs that crash in this case.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to class-wide @nt{allocator}s. These checks could not fail in Ada 95 (as all of the designated types had to be declared at the same level, so the access type would necessarily have been at the same level or more nested than the type of allocated object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Revised the description of evaluation of uninitialized allocators to use @lquotes@;initialized by default@rquotes so that the ordering requirements are the same for all kinds of objects that are default-initialized.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to access discriminants of @nt{allocator}s. These checks could not fail in Ada 95 as the discriminants always have the accessibility of the object.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0052-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added a rule to prevent limited coextensions of nonlimited types. Allowing this would have far-reaching implementation costs. Because of those costs, it seems unlikely that any implementation ever supported it properly and thus it is unlikely that any existing code depends on this capability.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0104-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a rule to make @nt{null_exclusion}s illegal for uninitialized @nt{allocator}s, as such an @nt{allocator} would always raise Constraint_Error. Programs that depend on the unconditional raising of a predefined exception should be very rare.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Subpool handles (see @RefSecNum{Storage Subpools}) can be specified in an @nt{allocator}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0024-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the master check for tags since the masters may be for different tasks and thus incomparable.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0041-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the rules for when a designated object is constrained by its initial value so that types derived from a partial view are handled properly.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0051-1],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the accessibility check for access discriminants so that it does not depend on the designated type (which might not have discriminants when the allocated type does).]} @end{DiffWord2005} @LabeledClause{Static Expressions and Static Subtypes} @begin{Intro} Certain expressions of a scalar or string type are defined to be static. Similarly, certain discrete ranges are defined to be static, and certain scalar and string subtypes are defined to be static subtypes. @Redundant[@Defn{static} @i(Static) means determinable at compile time, using the declared properties or values of the program entities.] @IndexSeeAlso{Term=[constant],See=(static)} @begin{Discussion} As opposed to more elaborate data flow analysis, etc. @end{Discussion} @end{Intro} @begin{MetaRules} For an expression to be static, it has to be calculable at compile time. Only scalar and string expressions are static. To be static, an expression cannot have any nonscalar, nonstring subexpressions (though it can have nonscalar constituent @nt<name>s). A static scalar expression cannot have any nonscalar subexpressions. There is one exception @em a membership test for a string subtype can be static, and the result is scalar, even though a subexpression is nonscalar. The rules for evaluating static expressions are designed to maximize portability of static calculations. @end{MetaRules} @begin{Intro} @Leading@Defn2{Term=[static], Sec=(expression)} A static expression is @Redundant[a scalar or string expression that is] one of the following: @begin{Itemize} a @nt{numeric_literal}; @begin{Ramification} A @nt<numeric_literal> is always a static expression, even if its expected type is not that of a static subtype. However, if its value is explicitly converted to, or qualified by, a nonstatic subtype, the resulting expression is nonstatic. @end{Ramification} a @nt{string_literal} of a static string subtype; @begin(Ramification) That is, the constrained subtype defined by the index range of the string is static. Note that elementary values don't generally have subtypes, while composite values do (since the bounds or discriminants are inherent in the value). @end(Ramification) a @nt{name} that denotes the declaration of a named number or a static constant; @begin{Ramification} Note that enumeration literals are covered by the @nt{function_call} case. @end{Ramification} a @nt{function_call} whose @SynI{function_}@nt{name} or @SynI{function_}@nt{prefix} statically denotes a static function, and whose actual parameters, if any (whether given explicitly or by default), are all static expressions; @begin{Ramification} This includes uses of operators that are equivalent to @nt{function_call}s. @end{Ramification} an @nt{attribute_reference} that denotes a scalar value, and whose @nt{prefix} denotes a static scalar subtype; @begin{Ramification} Note that this does not include the case of an attribute that is a function; a reference to such an attribute is not even an expression. See above for function @i{calls}. An implementation may define the staticness and other properties of implementation-defined attributes. @end{Ramification} an @nt{attribute_reference} whose @nt{prefix} statically denotes a statically constrained array object or array subtype, and whose @nt<attribute_designator> is First, Last, or Length, with an optional dimension; a @nt{type_conversion} whose @nt{subtype_mark} denotes a static scalar subtype, and whose operand is a static expression; a @nt{qualified_expression} whose @nt{subtype_mark} denotes a static @Redundant[(scalar or string)] subtype, and whose operand is a static expression; @begin{Ramification} This rules out the @nt{subtype_mark}'@nt{aggregate} case. @end{Ramification} @begin{Reason} Adding qualification to an expression shouldn't make it nonstatic, even for strings. @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0158-1],ARef=[AI05-0269-1]} a membership test whose @nt{simple_expression} is a static expression, and whose @Chg{Version=[3],New=[@nt{membership_choice_list} consists only of @nt{membership_choice}s that are either static @nt{choice_expression}s, static @nt{range}s, or @nt{subtype_mark}s that denote],Old=[@nt{range} is a static range or whose @nt{subtype_mark} denotes]} a static @Redundant[(scalar or string)] subtype; @begin{Reason} Clearly, we should allow membership tests in exactly the same cases where we allow @nt{qualified_expression}s. @end{Reason} a short-circuit control form both of whose @nt{relation}s are static expressions; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[a @nt{conditional_expression} all of whose @nt{condition}s, @SynI{selecting_}@nt{expression}s, and @SynI{dependent_}@nt{expression}s are static expressions;]} a static expression enclosed in parentheses. @end{Itemize} @begin(Discussion) @Defn2{Term=[static], Sec=(value)} Informally, we talk about a @i(static value). When we do, we mean a value specified by a static expression. @end(Discussion) @begin{Ramification} The language requires a static expression in a @nt<number_declaration>, a numeric type definition, a @nt<discrete_choice> (sometimes), certain representation items, an @nt<attribute_designator>, and when specifying the value of a discriminant governing a @nt{variant_part} in a @nt<record_aggregate> or @nt<extension_aggregate>. @end{Ramification} @Leading@Defn2{Term=[statically], Sec=(denote)} A @nt{name} @i(statically denotes) an entity if it denotes the entity and: @begin(itemize) It is a @nt<direct_name>, expanded name, or @nt{character_literal}, and it denotes a declaration other than a @nt<renaming_declaration>; or It is an @nt{attribute_reference} whose @nt{prefix} statically denotes some entity; or It denotes a @nt<renaming_declaration> with a @nt<name> that statically denotes the renamed entity. @end(itemize) @begin{Ramification} @nt{Selected_component}s that are not expanded names and @nt{indexed_component}s do not statically denote things. @end{Ramification} @Leading@Defn2{Term=[static], Sec=(function)} A @i{static function} is one of the following: @begin{Ramification} These are the functions whose calls can be static expressions. @end{Ramification} @begin{Itemize} a predefined operator whose parameter and result types are all scalar types none of which are descendants of formal scalar types; a predefined concatenation operator whose result type is a string type; an enumeration literal; a language-defined attribute that is a function, if the @nt{prefix} denotes a static scalar subtype, and if the parameter and result types are scalar. @end{Itemize} In any case, a generic formal subprogram is not a static function. @Defn2{Term=[static], Sec=(constant)} A @i(static constant) is a constant view declared by a full constant declaration or an @nt<object_@!renaming_@!declaration> with a static nominal subtype, having a value defined by a static scalar expression or by a static string expression whose value has a length not exceeding the maximum length of a @nt{string_@!literal} in the implementation. @begin{Ramification} A deferred constant is not static; the view introduced by the corresponding full constant declaration can be static. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The reason for restricting the length of static string constants is so that compilers don't have to store giant strings in their symbol tables. Since most string constants will be initialized from @nt{string_literal}s, the length limit seems pretty natural. The reason for avoiding nonstring types is also to save symbol table space. We're trying to keep it cheap and simple (from the implementer's viewpoint), while still allowing, for example, the @Chg{Version=[3],New=[@nt{aspect_definition} for a Link_Name aspect], Old=[link name of a pragma Import]} to contain a concatenation. The length we're talking about is the maximum number of characters in the value represented by a @nt{string_literal}, not the number of characters in the source representation; the quotes don't count. @end{Reason} @Defn2{Term=[static], Sec=(range)} A @i(static range) is a @nt{range} whose bounds are static expressions, @Redundant[or a @nt<range_@!attribute_@!reference> that is equivalent to such a @nt<range>.] @Defn2{Term=[static], Sec=(discrete_range)} A @i(static @nt<discrete_@!range>) is one that is a static range or is a @nt<subtype_@!indication> that defines a static scalar subtype. The base range of a scalar type is a static range, unless the type is a descendant of a formal scalar type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00263-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} @Defn2{Term=[static], Sec=(subtype)} A @i(static subtype) is either a @i(static scalar subtype) or a @i(static string subtype). @Defn2{Term=[static], Sec=(scalar subtype)} A static scalar subtype is an unconstrained scalar subtype whose type is not a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, or a constrained scalar subtype formed by imposing a compatible static constraint on a static scalar subtype. @Defn2{Term=[static], Sec=(string subtype)} A static string subtype is an unconstrained string subtype whose index subtype and component subtype are static@Chg{Version=[2],New=[],Old=[ (and whose type is not a descendant of a formal array type)]}, or a constrained string subtype formed by imposing a compatible static constraint on a static string subtype. In any case, the subtype of a generic formal object of mode @key[in out], and the result subtype of a generic formal function, are not static.@Chg{Version=[3], New=[ Also, a subtype is not static if any Dynamic_Predicate specifications apply to it.],Old=[]} @begin{Ramification} String subtypes are the only composite subtypes that can be static. @end{Ramification} @begin{Reason} @Leading@;The part about generic formal objects of mode @key[in out] is necessary because the subtype of the formal is not required to have anything to do with the subtype of the actual. For example: @begin{Example} @key[subtype] Int10 @key[is] Integer @key[range] 1..10; @key[generic] F : @key[in] @key[out] Int10; @key[procedure] G; @key[procedure] G @key[is] @key[begin] @key[case] F @key[is] @key[when] 1..10 => @key[null]; --@RI{ Illegal!} @key[end] @key[case]; @key[end] G; X : Integer @key[range] 1..20; @key[procedure] I @key[is] @key[new] G(F => X); --@RI{ OK.} @end{Example} The @nt{case_statement} is illegal, because the subtype of F is not static, so the choices have to cover all values of Integer, not just those in the range 1..10. A similar issue arises for generic formal functions, now that function calls are object names. @end{Reason} @Leading@Defn2{Term=[static], Sec=(constraint)} The different kinds of @i(static constraint) are defined as follows: @begin(itemize) A null constraint is always static; @Defn2{Term=[static], Sec=(range constraint)} @Defn2{Term=[static], Sec=(digits constraint)} @Defn2{Term=[static], Sec=(delta constraint)} A scalar constraint is static if it has no @nt<range_constraint>, or one with a static range; @Defn2{Term=[static], Sec=(index constraint)} An index constraint is static if each @nt<discrete_range> is static, and each index subtype of the corresponding array type is static; @Defn2{Term=[static], Sec=(discriminant constraint)} A discriminant constraint is static if each @nt<expression> of the constraint is static, and the subtype of each discriminant is static. @end(itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00311-01]} @Chg{Version=[2],New=[In any case, the constraint of the first subtype of a scalar formal type is neither static nor null.],Old=[]} @Defn2{Term=[statically], Sec=(constrained)} A subtype is @i(statically constrained) if it is constrained, and its constraint is static. An object is @i(statically constrained) if its nominal subtype is statically constrained, or if it is a static string constant. @end{Intro} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An expression is @i<statically unevaluated> if it is part of:@Defn{statically unevaluated}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[the right operand of a static short-circuit control form whose value is determined by its left operand; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[a @SynI{dependent_}@nt{expression} of an @nt{if_expression} whose associated @nt{condition} is static and equals False; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[a @nt{condition} or @SynI{dependent_}@nt{expression} of an @nt{if_expression} where the @nt{condition} corresponding to at least one preceding @SynI{dependent_}@nt{expression} of the @nt{if_expression} is static and equals True; or]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[We need this bullet so that only a single @SynI{dependent_}@nt{expression} is evaluated in a static @nt{if_expression} if there is more than one @nt{condition} that evaluates to True. The part about @nt{condition}s makes]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[(@key[if] N = 0 @key[then] Min @key[elsif] 10_000/N > Min @key[then] 10_000/N @key[else] Min)]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[legal if N and Min are static and N = 0.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[We need the "of the @nt{if_expression}" here so there is no confusion for nested @nt{if_expression}s; this rule only applies to the @nt{condition}s and @Syni{dependent_}@nt{expression}s of a single @nt{if_expression}. Similar reasoning applies to the "of a @nt{case_expression}" of the last bullet.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0188-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[a @SynI{dependent_}@nt{expression} of a @nt{case_expression} whose @SynI{selecting_}@nt{expression} is static and whose value is not covered by the corresponding @nt{discrete_choice_list}; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[a @nt{choice_expression} (or a @nt{simple_expression} of a @nt{range} that occurs as a @nt{membership_choice} of a @nt{membership_choice_list}) of a static membership test that is preceded in the enclosing @nt{membership_choice_list} by another item whose individual membership test (see @RefSecNum{Relational Operators and Membership Tests}) statically yields True.]} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0147-1]} @Leading@;A static expression is evaluated at compile time except when it is @Chg{Version=[3],New=[statically unevaluated],Old=[part of the right operand of a static short-circuit control form whose value is determined by its left operand]}. @Chg{Version=[3],New=[The compile-time],Old=[This]} evaluation @Chg{Version=[3],New=[of a static expression ],Old=[]}is performed exactly, without performing Overflow_Checks. For a static expression that is evaluated: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} The expression is illegal if its evaluation fails a language-defined check other than Overflow_@!Check.@Chg{Version=[3],New=[ For the purposes of this evaluation, the assertion policy is assumed to be Check.],Old=[]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Assertion policies can control whether checks are made, but we don't want assertion policies to affect legality. For Ada 2012, subtype predicates are the only checks controlled by the assertion policy that can appear in static expressions.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} If the expression is not part of a larger static expression@Chg{Version=[2],New=[ and the expression is expected to be of a single specific type],Old=[]}, then its value shall be within the base range of its expected type. Otherwise, the value may be arbitrarily large or small. @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[If the expression is expected to be of a universal type, or of @lquotes@;any integer type@rquotes, there are no limits on the value of the expression.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} If the expression is of type @i<universal_real> and its expected type is a decimal fixed point type, then its value shall be a multiple of the @i<small> of the decimal type.@Chg{Version=[2],New=[ This restriction does not apply if the expected type is a descendant of a formal scalar type (or a corresponding actual type in an instance).],Old=[]} @begin{Ramification} This means that a @nt{numeric_literal} for a decimal type cannot have @lquotes@;extra@rquotes@; significant digits. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[The small is not known for a generic formal type, so we have to exclude formal types from this check.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} @Chg{Version=[2],New=[@PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), the above restrictions also apply in the private part of an instance of a generic unit.],Old=[The last two restrictions above do not apply if the expected type is a descendant of a formal scalar type (or a corresponding actual type in an instance).]} @begin{Discussion} Values outside the base range are not permitted when crossing from the @lquotes@;static@rquotes@; domain to the @lquotes@;dynamic@rquotes@; domain. This rule is designed to enhance portability of programs containing static expressions. Note that this rule applies to the exact value, not the value after any rounding or truncation. (See below for the rounding and truncation requirements.) @Leading@;Short-circuit control forms are a special case: @begin{Example} N: @key[constant] := 0.0; X: @key[constant] Boolean := (N = 0.0) @key[or] @key[else] (1.0/N > 0.5); --@RI{ Static.} @end{Example} The declaration of X is legal, since the divide-by-zero part of the expression is not evaluated. X is a static constant equal to True. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00269-01]} @ChgDeleted{Version=[2],Text=[There is no requirement to recheck these rules in an instance; the base range check will generally be performed at run time anyway.]} @end{Ramification} @end{Legality} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00268-01],ARef=[AI95-00269-01]} For a real static expression that is not part of a larger static expression, and whose expected type is not a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, the implementation shall round or truncate the value (according to the Machine_Rounds attribute of the expected type) to the nearest machine number of the expected type; if the value is exactly half-way between two machine numbers, @Chg{Version=[2],New=[the],Old=[any]} rounding @Chg{Version=[2],New=[],Old=[shall be ]}performed @Chg{Version=[2],New=[is implementation-defined],Old=[away from zero]}. If the expected type is a descendant of a formal @Chg{Version=[2],New=[],Old=[scalar ]}type, @Chg{Version=[2],New=[or if the static expression appears in the body of an instance of a generic unit and the corresponding expression is nonstatic in the corresponding generic body, then],Old=[]} no special rounding or truncating is required @em normal accuracy rules apply (see @RefSecNum(Numerics)). @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[Rounding of real static expressions which are exactly half-way between two machine numbers.],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00268-01]} Discarding extended precision enhances portability by ensuring that the value of a static constant of a real type is always a machine number of the type. @Chg{Version=[2],New=[],Old=[Deterministic rounding of exact halves also enhances portability.]} When the expected type is a descendant of a formal floating point type, extended precision (beyond that of the machine numbers) can be retained when evaluating a static expression, to ease code sharing for generic instantiations. For similar reasons, normal (nondeterministic) rounding or truncating rules apply for descendants of a formal fixed point type. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[There is no requirement for exact evaluation or special rounding in an instance body (unless the expression is static in the generic body). This eliminates a potential contract issue where the exact value of a static expression depends on the actual parameters (which could then affect the legality of other code).]} @end{Reason} @begin{ImplNote} Note that the implementation of static expressions has to keep track of plus and minus zero for a type whose Signed_Zeros attribute is True. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00100-01]} Note that the only @Chg{Version=[2],New=[machine numbers],Old=[values]} of a fixed point type are the multiples of the small, so a static conversion to a fixed-point type, or division by an integer, must do truncation to a multiple of small. It is not correct for the implementation to do all static calculations in infinite precision. @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[For a real static expression that is not part of a larger static expression, and whose expected type is not a descendant of a formal type, the rounding should be the same as the default rounding for the target system.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A real static expression with a nonformal type that is not part of a larger static expression should be rounded the same as the target system.]}]} @end{ImplAdvice} @begin{Notes} An expression can be static even if it occurs in a context where staticness is not required. @begin{Ramification} @Leading@keepnext@;For example: @begin{Example} X : Float := Float'(1.0E+400) + 1.0 - Float'(1.0E+400); @end{Example} The expression is static, which means that the value of X must be exactly 1.0, independent of the accuracy or range of the run-time floating point implementation. The following kinds of expressions are never static: @nt{explicit_dereference}, @nt{indexed_component}, @nt{slice}, @key{null}, @nt{aggregate}, @nt{allocator}. @end{Ramification} A static (or run-time) @nt<type_conversion> from a real type to an integer type performs rounding. If the operand value is exactly half-way between two integers, the rounding is performed away from zero. @begin{Reason} We specify this for portability. The reason for not choosing round-to-nearest-even, for example, is that this method is easier to undo. @end{Reason} @begin{Ramification} The attribute Truncation (see @RefSecNum{Attributes of Floating Point Types}) can be used to perform a (static) truncation prior to conversion, to prevent rounding. @end{Ramification} @begin{ImplNote} The value of the literal 0E999999999999999999999999999999999999999999999 is zero. The implementation must take care to evaluate such literals properly. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@keepnext@i(Examples of static expressions:) @begin{Example} 1 + 1 @RI[-- 2] @key(abs)(-10)*3 @RI[-- 30] Kilo : @key(constant) := 1000; Mega : @key(constant) := Kilo*Kilo; @RI[-- 1_000_000] Long : @key(constant) := Float'Digits*2; Half_Pi : @key(constant) := Pi/2; @RI[-- see @RefSecNum(Number Declarations)] Deg_To_Rad : @key(constant) := Half_Pi/90; Rad_To_Deg : @key(constant) := 1.0/Deg_To_Rad; @RI[-- equivalent to 1.0/((3.14159_26536/2)/90)] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The rules for static expressions and static subtypes are generalized to allow more kinds of compile-time-known expressions to be used where compile-time-known values are required, as follows: @begin(itemize) Membership tests and short-circuit control forms may appear in a static expression. The bounds and length of statically constrained array objects or subtypes are static. The Range attribute of a statically constrained array subtype or object gives a static range. A @nt{type_conversion} is static if the @nt{subtype_mark} denotes a static scalar subtype and the operand is a static expression. All numeric literals are now static, even if the expected type is a formal scalar type. This is useful in @nt{case_statement}s and @nt{variant_part}s, which both now allow a value of a formal scalar type to control the selection, to ease conversion of a package into a generic package. Similarly, named array aggregates are also permitted for array types with an index type that is a formal scalar type. @end(itemize) The rules for the evaluation of static expressions are revised to require exact evaluation at compile time, and force a machine number result when crossing from the static realm to the dynamic realm, to enhance portability and predictability. Exact evaluation is not required for descendants of a formal scalar type, to simplify generic code sharing and to avoid generic contract model problems. @Leading@;Static expressions are legal even if an intermediate in the expression goes outside the base range of the type. Therefore, the following will succeed in Ada 95, whereas it might raise an exception in Ada 83: @begin{Example} @key[type] Short_Int @key[is] @key[range] -32_768 .. 32_767; I : Short_Int := -32_768; @end{Example} This might raise an exception in Ada 83 because "32_768" is out of range, even though "@en@;32_768" is not. In Ada 95, this will always succeed. Certain expressions involving string operations (in particular concatenation and membership tests) are considered static in Ada 95. The reason for this change is to simplify the rule requiring compile-time-known string expressions as the link name in an interfacing pragma, and to simplify the preelaborability rules. @end{Extend83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} An Ada 83 program that uses an out-of-range static value is illegal in Ada 95, unless the expression is part of a larger static expression, or the expression is not evaluated due to being on the right-hand side of a short-circuit control form. @end{Incompatible83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} (and @RefSec{Multiplying Operators}) subsumes the RM83 section on Universal Expressions. The existence of static string expressions necessitated changing the definition of static subtype to include string subtypes. Most occurrences of "static subtype" have been changed to "static scalar subtype", in order to preserve the effect of the Ada 83 rules. This has the added benefit of clarifying the difference between "static subtype" and "statically constrained subtype", which has been a source of confusion. In cases where we allow static string subtypes, we explicitly use phrases like "static string subtype" or "static (scalar or string) subtype", in order to clarify the meaning for those who have gotten used to the Ada 83 terminology. @Leading@;In Ada 83, an expression was considered nonstatic if it raised an exception. Thus, for example: @begin{Example} Bad: @key[constant] := 1/0; --@RI{ Illegal!} @end{Example} was illegal because 1/0 was not static. In Ada 95, the above example is still illegal, but for a different reason: 1/0 is static, but there's a separate rule forbidding the exception raising. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Rounding of static real expressions is implementation-defined in Ada 2005, while it was specified as away from zero in (original) Ada 95. This could make subtle differences in programs. However, the original Ada 95 rule required rounding that (probably) differed from the target processor, thus creating anomalies where the value of a static expression was required to be different than the same expression evaluated at run-time.]} @end{Inconsistent95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00263-01],ARef=[AI95-00268-01]} @ChgAdded{Version=[2],Text=[The Ada 95 wording that defined static subtypes unintentionally failed to exclude formal derived types that happen to be scalar (these aren't formal scalar types); and had a parenthetical remark excluding formal string types - but that was neither necessary nor parenthetical (it didn't follow from other wording). This issue also applies to the rounding rules for real static expressions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[Ada 95 didn't clearly define the bounds of a value of a static expression for universal types and for "any integer/float/fixed type". We also make it clear that we do not intend exact evaluation of static expressions in an instance body if the expressions aren't static in the generic body.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00311-01]} @ChgAdded{Version=[2],Text=[We clarify that the first subtype of a scalar formal type has a nonstatic, nonnull constraint.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[Added wording to define staticness and the lack of evaluation for @nt{if_expression}s and @nt{case_expression}s. These are new and defined elsewhere.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[Added wording to prevent subtypes that have dynamic predicates (see @RefSecNum{Subtype Predicates}) from being static.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0158-1]} @ChgAdded{Version=[3],Text=[Revised wording for membership tests to allow for the new possibilities allowed by the @nt{membership_choice_list}.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Statically Matching Constraints and Subtypes} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00311-01]} @Defn2{Term=[statically matching], Sec=(for constraints)} A constraint @i(statically matches) another constraint if@Chg{Version=[2],New=[:],Old=[ both are null constraints, both are static and have equal corresponding bounds or discriminant values, or both are nonstatic and result from the same elaboration of a @nt<constraint> of a @nt<subtype_@!indication> or the same evaluation of a @nt<range> of a @nt<discrete_@!subtype_@!definition>.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are null constraints;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are static and have equal corresponding bounds or discriminant values;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[both are nonstatic and result from the same elaboration of a @nt<constraint> of a @nt<subtype_@!indication> or the same evaluation of a @nt<range> of a @nt<discrete_@!subtype_@!definition>; or],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00311-01]} @Chg{Version=[2],New=[both are nonstatic and come from the same @nt{formal_type_declaration}.],Old=[]} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} @Defn2{Term=[statically matching], Sec=(for subtypes)} A subtype @i(statically matches) another subtype of the same type if they have statically matching constraints@Chg{Version=[2],New=[, @Chg{Version=[3],New=[all predicate specifications that apply to them come from the same declarations, ],Old=[]}and, for access subtypes, either both or neither exclude null],Old=[]}. Two anonymous access@Chg{Version=[2],New=[-to-object],Old=[]} subtypes statically match if their designated subtypes statically match@Chg{Version=[2],New=[, and either both or neither exclude null, and either both or neither are access-to-constant. Two anonymous access-to-subprogram subtypes statically match if their designated profiles are subtype conformant, and either both or neither exclude null],Old=[]}. @begin{Ramification} Statically matching constraints and subtypes are the basis for subtype conformance of profiles (see @RefSecNum(Conformance Rules)). @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Even though anonymous access types always represent different types, they can statically match. That's important so that they can be used widely. For instance, if this wasn't true, access parameters and access discriminants could never conform, so they couldn't be used in separate specifications.]} @end{Reason} @Defn2{Term=[statically matching], Sec=(for ranges)} Two ranges of the same type @i{statically match} if both result from the same evaluation of a @nt{range}, or if both are static and have equal corresponding bounds. @begin{Ramification} The notion of static matching of ranges is used in @RefSec{Formal Array Types}; the index ranges of formal and actual constrained array subtypes have to statically match. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0086-1],ARef=[AI05-0153-3]} @Defn2{Term=[statically compatible], Sec=(for a constraint and a scalar subtype)} A constraint is @i(statically compatible) with a scalar subtype if it statically matches the constraint of the subtype, or if both are static and the constraint is compatible with the subtype. @Defn2{Term=[statically compatible], Sec=(for a constraint and an access or composite subtype)} A constraint is @i(statically compatible) with an access or composite subtype if it statically matches the constraint of the subtype, or if the subtype is unconstrained.@Chg{Version=[3],New=[],Old=[ @Defn2{Term=[statically compatible], Sec=(for two subtypes)} One subtype is @i(statically compatible) with a second subtype if the constraint of the first is statically compatible with the second subtype.]} @begin{Discussion} Static compatibility is required when constraining a parent subtype with a discriminant from a new @nt<discriminant_part>. See @RefSecNum{Discriminants}. Static compatibility is also used in matching generic formal derived types. Note that statically compatible with a subtype does not imply compatible with a type. It is OK since the terms are used in different contexts. @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[@Defn2{Term=[statically compatible], Sec=(for two subtypes)}Two statically matching subtypes are statically compatible with each other. In addition, a subtype @i<S1> is statically compatible with a subtype @i<S2> if:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the constraint of @i<S1> is statically compatible with @i<S2>, and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0086-1]} @ChgAdded{Version=[3],Text=[if @i<S2> excludes null, so does @i<S1>, and]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[either:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[all predicate specifications that apply to @i<S2> apply also to @i<S1>, or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[both subtypes are static, every value that satisfies the predicate of @i<S1> also satisfies the predicate of @i<S2>, and it is not the case that both types each have at least one applicable predicate specification, predicate checks are enabled (see @RefSecNum{Pragmas Assert and Assertion_Policy}) for @i<S2>, and predicate checks are not enabled for @i<S1>.]} @end{InnerItemize} @end{Itemize} @end{StaticSem} @begin{DiffWord83} This subclause is new to Ada 95. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[Added static matching rules for null exclusions and anonymous access-to-subprogram types; both of these are new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00311-01]} @ChgAdded{Version=[2],Text=[We clarify that the constraint of the first subtype of a scalar formal type statically matches itself.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0086-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Updated the statically compatible rules to take null exclusions into account. This is technically incompatible, as it could cause a legal Ada 2005 program to be rejected; however, such a program violates the intent of the rules (for instance, @RefSecNum{Discriminants}(15)) and this probably will simply detect bugs.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Modified static matching and static compatibility to take predicate aspects (see @RefSecNum{Subtype Predicates}) into account.]} @end{DiffWord2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/05.mss���������������������������������������������������������������0000755�0001752�0001001�00000216713�12066652506�016407� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(05, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @LabeledSection{Statements} @Comment{$Source: e:\\cvsroot/ARM/Source/05.mss,v $} @Comment{$Revision: 1.59 $} @begin{Intro} @Redundant[A @nt{statement} defines an action to be performed upon its execution.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[clause],Old=[section]} describes the general rules applicable to all @nt{statement}s. Some @nt{statement}s are discussed in later @Chg{Version=[3],New=[clauses],Old=[sections]}: @nt{Procedure_@!call_@!statement}s and @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} are described in @RefSec{Subprograms}. @nt{Entry_@!call_@!statement}s, @nt{requeue_@!statement}s, @nt{delay_@!statement}s, @nt{accept_@!statement}s, @nt{select_@!statement}s, and @nt{abort_@!statement}s are described in @RefSec{Tasks and Synchronization}. @nt{Raise_@!statement}s are described in @RefSec{Exceptions}, and @nt{code_@!statement}s in @RefSecNum{Representation Issues}. The remaining forms of @nt{statement}s are presented in this @Chg{Version=[3],New=[clause],Old=[section]}.] @end{Intro} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The description of @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} has been moved to @RefSec{Return Statements}, so that it is closer to the description of subprograms. @end{DiffWord83} @LabeledClause{Simple and Compound Statements - Sequences of Statements} @begin{Intro} @Redundant[A @nt<statement> is either simple or compound. A @nt<simple_statement> encloses no other @nt<statement>. A @nt<compound_statement> can enclose @nt<simple_statement>s and other @nt<compound_statement>s.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0179-1]} @Syn{lhs=<sequence_of_statements>,rhs="@Syn2{statement} {@Syn2{statement}}@Chg{Version=[3],New=[ {@Syn2{label}}],Old=[]}"} @Syn{lhs=<statement>,rhs=" {@Syn2{label}} @Syn2{simple_statement} | {@Syn2{label}} @Syn2{compound_statement}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{tabs=[P31], lhs=<simple_statement>,rhs="@Syn2{null_statement} | @Syn2{assignment_statement}@\| @Syn2{exit_statement} | @Syn2{goto_statement}@\| @Syn2{procedure_call_statement} | @Chg{Version=[2],New=[@Syn2{simple_return_statement}],Old=[@Syn2{return_statement}]}@\| @Syn2{entry_call_statement} | @Syn2{requeue_statement}@\| @Syn2{delay_statement} | @Syn2{abort_statement}@\| @Syn2{raise_statement} | @Syn2{code_statement}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{tabs=[P31], lhs=<compound_statement>,rhs=" @Syn2{if_statement}@\| @Syn2{case_statement} | @Syn2{loop_statement}@\| @Syn2{block_statement}@Chg{Version=[2],New=[ | @Syn2{extended_return_statement}],Old=[]} | @Syn2{accept_statement}@\| @Syn2{select_statement}"} @Syn{lhs=<null_statement>,rhs="@key{null};"} @Syn{lhs=<label>,rhs="<<@SynI{label_}@Syn2{statement_identifier}>>"} @Syn{lhs=<statement_identifier>,rhs="@Syn2{direct_name}"} @begin(SyntaxText) The @nt<direct_name> of a @nt<statement_identifier> shall be an @nt<identifier> (not an @nt<operator_symbol>). @end(SyntaxText) @end{Syntax} @begin{Resolution} The @nt<direct_name> of a @nt<statement_identifier> shall resolve to denote its corresponding implicit declaration (see below). @end{Resolution} @begin{Legality} Distinct @nt{identifier}s shall be used for all @nt<statement_identifier>s that appear in the same body, including inner @nt{block_statement}s but excluding inner program units. @end{Legality} @begin{StaticSem} For each @nt<statement_identifier>, there is an implicit declaration (with the specified @nt<identifier>) at the end of the @nt{declarative_part} of the innermost @nt{block_statement} or body that encloses the @nt{statement_identifier}. The implicit declarations occur in the same order as the @nt<statement_identifier>s occur in the source text. If a usage name denotes such an implicit declaration, the entity it denotes is the @nt<label>, @nt<loop_statement>, or @nt<block_statement> with the given @nt<statement_identifier>. @begin{Reason} We talk in terms of individual @nt<statement_identifier>s here rather than in terms of the corresponding statements, since a given @nt{statement} may have multiple @nt<statement_identifier>s. A @nt{block_statement} that has no explicit @nt{declarative_part} has an implicit empty @nt{declarative_part}, so this rule can safely refer to the @nt{declarative_part} of a @nt<block_statement>. The scope of a declaration starts at the place of the declaration itself (see @RefSecNum{Scope of Declarations}). In the case of a label, loop, or block name, it follows from this rule that the scope of the implicit declaration starts before the first explicit occurrence of the corresponding name, since this occurrence is either in a statement label, a @nt{loop_statement}, a @nt{block_statement}, or a @nt{goto_statement}. An implicit declaration in a @nt{block_statement} may hide a declaration given in an outer program unit or @nt{block_statement} (according to the usual rules of hiding explained in @RefSecNum{Visibility}). The syntax rule for @nt{label} uses @nt{statement_identifier} which is a @nt<direct_name> (not a @nt{defining_identifier}), because labels are implicitly declared. The same applies to loop and block names. In other words, the @nt{label} itself is not the defining occurrence; the implicit declaration is. @Leading@;We cannot consider the @nt{label} to be a defining occurrence. An example that can tell the difference is this: @begin{example} @key[declare] --@RI{ Label Foo is implicitly declared here.} @key[begin] @key[for] Foo @key[in] ... @key[loop] ... <<Foo>> --@RI{ Illegal.} ... @key[end] @key[loop]; @key[end]; @end{example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The label in this example is hidden from itself by the loop parameter with the same name; the example is illegal. We considered creating a new syntactic category name, separate from @nt{direct_name} and @nt{selector_name}, for use in the case of statement labels. However, that would confuse the rules in @Chg{Version=[3],New=[Clause],Old=[Section]} 8, so we didn't do it. @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0179-1]} @ChgAdded{Version=[3],Text=[If one or more @nt{label}s end a @nt{sequence_of_statements}, an implicit @nt{null_statement} follows the @nt{label}s before any following constructs.]} @begin{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The semantics of a @nt{goto_statement} is defined in terms of the statement having (following) that label. Thus we ensure that every label has a following statement, which might be implicit.]} @end{Reason} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(null_statement)} The execution of a @nt{null_statement} has no effect. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{transfer of control} A @i{transfer of control} is the run-time action of an @nt{exit_statement}, @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}, @nt{goto_statement}, or @nt{requeue_statement}, selection of a @nt{terminate_alternative}, raising of an exception, or an abort, which causes the next action performed to be one other than what would normally be expected from the other rules of the language. @Redundant[As explained in @RefSecNum{Completion and Finalization}, a transfer of control can cause the execution of constructs to be completed and then left, which may trigger finalization.] @PDefn2{Term=[execution], Sec=(sequence_of_statements)} The execution of a @nt{sequence_of_statements} consists of the execution of the individual @nt{statement}s in succession until the @ntf{sequence_} is completed. @begin{Ramification} It could be completed by reaching the end of it, or by a transfer of control. @end{Ramification} @end{RunTime} @begin{Notes} A @nt<statement_identifier> that appears immediately within the declarative region of a named @nt<loop_statement> or an @nt<accept_statement> is nevertheless implicitly declared immediately within the declarative region of the innermost enclosing body or @nt<block_statement>; in other words, the expanded name for a named statement is not affected by whether the statement occurs inside or outside a named loop or an @nt<accept_statement> @em only nesting within @nt<block_statement>s is relevant to the form of its expanded name. @begin{Discussion} @Leading@keepnext@;Each comment in the following example gives the expanded name associated with an entity declared in the task body: @begin{Example} @key(task body) Compute @key(is) Sum : Integer := 0; --@RI[ Compute.Sum] @key(begin) Outer: --@RI[ Compute.Outer] @key(for) I @key(in) 1..10 @key(loop) --@RI[ Compute.Outer.I] Blk: --@RI[ Compute.Blk] @key(declare) Sum : Integer := 0; --@RI[ Compute.Blk.Sum] @key(begin) @key(accept) Ent(I : out Integer; J : in Integer) @key(do) --@RI[ Compute.Ent.I, Compute.Ent.J] Compute.Ent.I := Compute.Outer.I; Inner: --@RI[ Compute.Blk.Inner] @key(for) J @key(in) 1..10 @key(loop) --@RI[ Compute.Blk.Inner.J] Sum := Sum + Compute.Blk.Inner.J * Compute.Ent.J; @key(end loop) Inner; @key(end) Ent; Compute.Sum := Compute.Sum + Compute.Blk.Sum; @key(end) Blk; @key(end loop) Outer; Record_Result(Sum); @key(end) Compute; @end{Example} @end{Discussion} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of labeled statements:} @begin{Example} <<Here>> <<Ici>> <<Aqui>> <<Hier>> @key[null]; <<After>> X := 1; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{requeue_statement} is new. @end{Extend83} @begin{DiffWord83} We define the syntactic category @nt<statement_identifier> to simplify the description. It is used for labels, loop names, and block names. We define the entity associated with the implicit declarations of statement names. Completion includes completion caused by a transfer of control, although RM83-5.1(6) did not take this view. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{extended_return_statement} is new (@nt{simple_return_statement} is merely renamed).]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0179-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} A @nt{label} can end a @nt{sequence_of_statements}, eliminating the requirement for having an explicit @key[null]; statement after an ending label (a common use).]} @end{Extend2005} @LabeledClause{Assignment Statements} @begin{Intro} @Redundant[An @nt{assignment_statement} replaces the current value of a variable with the result of evaluating an @nt<expression>.] @end{Intro} @begin{Syntax} @Syn{lhs=<assignment_statement>,rhs=" @SynI{variable_}@Syn2{name} := @Syn2{expression};"} @end{Syntax} @begin{Intro} The execution of an @nt<assignment_statement> includes the evaluation of the @nt<expression> and the @i(assignment) of the value of the @nt<expression> into the @i(target). @RootDefn{assignment operation} @IndexSee{Term=[assign], See=(assignment operation)} @Redundant[An assignment operation (as opposed to an @nt<assignment_@!statement>) is performed in other contexts as well, including object initialization and by-copy parameter passing.] @Defn2{Term=[target], Sec=(of an assignment operation)} @Defn2{Term=[target], Sec=(of an @nt{assignment_statement})} The @i{target} of an assignment operation is the view of the object to which a value is being assigned; the target of an @nt{assignment_@!statement} is the variable denoted by the @SynI{variable_}@nt{name}. @begin{Discussion} Don't confuse this notion of the @lquotes@;target@rquotes@; of an assignment with the notion of the @lquotes@;target object@rquotes@; of an entry call or requeue. Don't confuse the term @lquotes@;assignment operation@rquotes@; with the @nt{assignment_statement}. The assignment operation is just one part of the execution of an @nt{assignment_statement}. The assignment operation is also a part of the execution of various other constructs; see @RefSec{Completion and Finalization} for a complete list. Note that when we say, @lquotes@;such-and-such is assigned to so-and-so@rquotes@;, we mean that the assignment operation is being applied, and that so-and-so is the target of the assignment operation. @end{Discussion} @end{Intro} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @PDefn2{Term=[expected type], Sec=(assignment_statement variable_name)} The @i(variable_)@nt<name> of an @nt<assignment_statement> is expected to be of any @Chg{Version=[2],New=[],Old=[nonlimited ]}type. @PDefn2{Term=[expected type], Sec=(assignment_statement expression)} The expected type for the @nt<expression> is the type of the target. @begin{ImplNote} @Leading@keepnext@;An @nt<assignment_statement> as a whole is a "complete context," so if the @i{variable_}@nt<name> of an @nt<assignment_statement> is overloaded, the @nt<expression> can be used to help disambiguate it. For example: @begin{Example} @key[type] P1 @key[is access] R1; @key[type] P2 @key[is access] R2; @key[function] F return P1; @key[function] F return P2; X : R1; @key[begin] F.all := X; --@RI[ Right hand side helps resolve left hand side] @end{Example} @end{ImplNote} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} The target @Redundant[denoted by the @i(variable_)@nt<name>] shall be a variable@Chg{Version=[2],New=[ of a nonlimited type],Old=[]}. If the target is of a tagged class-wide type @i(T)'Class, then the @nt<expression> shall either be dynamically tagged, or of type @i(T) and tag-indeterminate (see @RefSecNum{Dispatching Operations of Tagged Types}). @begin{Reason} This is consistent with the general rule that a single dispatching operation shall not have both dynamically tagged and statically tagged operands. Note that for an object initialization (as opposed to the @nt{assignment_statement}), a statically tagged initialization expression is permitted, since there is no chance for confusion (or Tag_Check failure). Also, in an object initialization, tag-indeterminate expressions of any type covered by @i(T)'Class would be allowed, but with an @nt{assignment_statement}, that might not work if the tag of the target was for a type that didn't have one of the dispatching operations in the tag-indeterminate expression. @end{Reason} @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(assignment_statement)} For the execution of an @nt{assignment_statement}, the @i(variable_)@nt<name> and the @nt<expression> are first evaluated in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Ramification} Other rules of the language may require that the bounds of the variable be determined prior to evaluating the @nt<expression>, but that does not necessarily require evaluation of the @i(variable_)@nt<name>, as pointed out by the ACID. @end{Ramification} @Leading@keepnext@;When the type of the target is class-wide: @begin(itemize) @PDefn2{Term=[controlling tag value], Sec=(for the @nt{expression} in an @nt{assignment_statement})} If the @nt<expression> is tag-indeterminate (see @RefSecNum{Dispatching Operations of Tagged Types}), then the controlling tag value for the @nt<expression> is the tag of the target; @begin{Ramification} See @RefSec(Dispatching Operations of Tagged Types). @end{Ramification} @IndexCheck{Tag_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Otherwise @Redundant[(the @nt<expression> is dynamically tagged)], a check is made that the tag of the value of the @nt<expression> is the same as that of the target; if this check fails, Constraint_Error is raised. @end(itemize) The value of the @nt<expression> is converted to the subtype of the target. @Redundant[The conversion might raise an exception (see @RefSecNum{Type Conversions}).] @PDefn2{Term=[implicit subtype conversion],Sec=(assignment_statement)} @begin{Ramification} @RefSec(Type Conversions) defines what actions and checks are associated with subtype conversion. For non-array subtypes, it is just a constraint check presuming the types match. For array subtypes, it checks the lengths and slides if the target is constrained. @lquotes@;Sliding@rquotes@; means the array doesn't have to have the same bounds, so long as it is the same length. @end{Ramification} In cases involving controlled types, the target is finalized, and an anonymous object might be used as an intermediate in the assignment, as described in @RefSec{Completion and Finalization}. @Defn{assignment operation} @Defn2{Term=[assignment operation], Sec=(during execution of an @nt{assignment_statement})} In any case, the converted value of the @nt<expression> is then @i(assigned) to the target, which consists of the following two steps: @begin{Honest} @RefSecNum{Completion and Finalization} actually says that finalization happens always, but unless controlled types are involved, this finalization during an @nt{assignment_statement} does nothing. @end{Honest} @begin(itemize) The value of the target becomes the converted value. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} If any part of the target is controlled, its value is adjusted as explained in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Assignment and Finalization}. @PDefn2{Term=[adjustment], Sec=(as part of assignment)} @begin{Ramification} If any parts of the object are controlled, abort is deferred during the assignment operation itself, but not during the rest of the execution of an @nt<assignment_statement>. @end{Ramification} @end(itemize) @end{RunTime} @begin{Notes} The tag of an object never changes; in particular, an @nt{assignment_statement} does not change the tag of the target. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00363-01]} @ChgDeleted{Version=[2],Text=[The values of the discriminants of an object designated by an access value cannot be changed (not even by assigning a complete value to the object itself) since such objects are always constrained; however, subcomponents of such objects may be unconstrained.]} @begin{Ramification} The implicit subtype conversion described above for @nt{assignment_statement}s is performed only for the value of the right-hand side expression as a whole; it is not performed for subcomponents of the value. The determination of the type of the variable of an @nt{assignment_statement} may require consideration of the expression if the variable name can be interpreted as the name of a variable designated by the access value returned by a function call, and similarly, as a component or slice of such a variable (see @RefSec{The Context of Overload Resolution}). @end{Ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of assignment statements:} @begin{Example} Value := Max_Value - 1; Shade := Blue; Next_Frame(F)(M, N) := 2.5; --@RI{ see @RefSecNum{Indexed Components}} U := Dot_Product(V, W); --@RI{ see @RefSecNum{Subprogram Bodies}} Writer := (Status => Open, Unit => Printer, Line_Count => 60); --@RI{ see @RefSecNum{Variant Parts and Discrete Choices}} Next_Car.@key[all] := (72074, @key[null]); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @end{Example} @begin{WideAbove} @Leading@keepnext@i{Examples involving scalar subtype conversions:} @end{WideAbove} @begin{Example} I, J : Integer @key[range] 1 .. 10 := 5; K : Integer @key[range] 1 .. 20 := 15; ... I := J; --@RI{ identical ranges} K := J; --@RI{ compatible ranges} J := K; --@RI{ will raise Constraint_Error if K > 10} @end{Example} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @begin{WideAbove} @leading@keepnext@i{Examples involving array subtype conversions:} @end{WideAbove} @begin{Example} A : String(1 .. 31); B : String(3 .. 33); ... A := B; --@RI{ same number of components} A(1 .. 9) := "tar sauce"; A(4 .. 12) := A(1 .. 9); --@RI{ A(1 .. 12) = "tartar sauce"} @end{Example} @end{Examples} @begin{Notes} @i{Notes on the examples:} @nt{Assignment_statement}s are allowed even in the case of overlapping slices of the same array, because the @SynI{variable_}@nt{name} and @nt{expression} are both evaluated before copying the value into the variable. In the above example, an implementation yielding A(1 .. 12) = "tartartartar" would be incorrect. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} We now allow user-defined finalization and value adjustment actions as part of @nt{assignment_statement}s (see @RefSec{Assignment and Finalization}). @end{Extend83} @begin{DiffWord83} The special case of array assignment is subsumed by the concept of a subtype conversion, which is applied for all kinds of types, not just arrays. For arrays it provides @lquotes@;sliding@rquotes@;. For numeric types it provides conversion of a value of a universal type to the specific type of the target. For other types, it generally has no run-time effect, other than a constraint check. We now cover in a general way in @RefSecNum{Operations of Discriminated Types} the erroneous execution possible due to changing the value of a discriminant when the variable in an @nt<assignment_statement> is a subcomponent that depends on discriminants. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The change of the limited check from a resolution rule to a legality rule is not quite upward compatible. For example]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} AccNonLim @key{is} @key{access} NonLim; @key{function} Foo (Arg : in Integer) @key{return} AccNonLim; @key{type} AccLim @key{is} @key{access} Lim; @key{function} Foo (Arg : in Integer) @key{return} AccLim; Foo(2).@key{all} := Foo(1).@key{all};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[where NonLim is a nonlimited type and Lim is a limited type. The assignment is legal in Ada 95 (only the first Foo would be considered), and is ambiguous in Ada 2005. We made the change because we want limited types to be as similar to nonlimited types as possible. Limited expressions are now allowed in all other contexts (with a similar incompatibility), and it would be odd if assignments had different resolution rules (which would eliminate ambiguities in some cases). Moreover, examples like this one are rare, as they depend on assigning into overloaded function calls.]} @end{Incompatible95} @LabeledClause{If Statements} @begin{Intro} @Redundant[An @nt{if_statement} selects for execution at most one of the enclosed @ntf{sequences_of_statements}, depending on the (truth) value of one or more corresponding @nt{condition}s.] @end{Intro} @begin{Syntax} @Syn{lhs=<if_statement>,rhs=" @key{if} @Syn2{condition} @key{then} @Syn2{sequence_of_statements} {@key{elsif} @Syn2{condition} @key{then} @Syn2{sequence_of_statements}} [@key{else} @Syn2{sequence_of_statements}] @key{end} @key{if};"} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0147-1]} @DeletedSyn{Version=[3],LHS=<@Chg{Version=[3],New=[],Old=[condition]}>, RHS="@Chg{Version=[3],New=[],Old=[@SynI{boolean_}@Syn2{expression}]}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0147-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[expected type], Sec=(condition)} A @nt{condition} is expected to be of any boolean type.]} @end{Resolution} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 3 and 4 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @PDefn2{Term=[execution], Sec=(if_statement)} For the execution of an @nt{if_statement}, the @nt{condition} specified after @key{if}, and any @nt{condition}s specified after @key{elsif}, are evaluated in succession (treating a final @key{else} as @key{elsif} True @key{then}), until one evaluates to True or all @nt{condition}s are evaluated and yield False. If a @nt{condition} evaluates to True, then the corresponding @nt{sequence_of_statements} is executed; otherwise@Chg{Version=[3],New=[,],Old=[]} none of them is executed. @begin{Ramification} The part about all evaluating to False can't happen if there is an @key{else}, since that is herein considered equivalent to @key{elsif} True @key{then}. @end{Ramification} @end{RunTime} @begin{Examples} @Leading@keepnext@i{Examples of if statements:} @begin{Example} @key[if] Month = December @key[and] Day = 31 @key[then] Month := January; Day := 1; Year := Year + 1; @key[end] @key[if]; @key[if] Line_Too_Short @key[then] @key[raise] Layout_Error; @key[elsif] Line_Full @key[then] New_Line; Put(Item); @key[else] Put(Item); @key[end] @key[if]; @key[if] My_Car.Owner.Vehicle /= My_Car @key[then] --@RI{ see @RefSecNum{Incomplete Type Declarations}} Report ("Incorrect data"); @key[end] @key[if]; @end{Example} @end{Examples} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[Moved definition of @nt{condition} to @RefSecNum{Conditional Expressions} in order to eliminate a forward reference.]} @end{Diffword2005} @LabeledClause{Case Statements} @begin{Intro} @Redundant[A @nt{case_statement} selects for execution one of a number of alternative @ntf{sequences_of_statements}; the chosen alternative is defined by the value of an expression.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} @Syn{lhs=<case_statement>,rhs=" @key{case} @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@Syn2{expression} @key{is} @Syn2{case_statement_alternative} {@Syn2{case_statement_alternative}} @key{end} @key{case};"} @Syn{lhs=<case_statement_alternative>,rhs=" @key{when} @Syn2{discrete_choice_list} => @Syn2{sequence_of_statements}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} @Chg{Version=[3],New=[@PDefn2{Term=[expected type], Sec=(case_statement selecting_expression)} @PDefn2{Term=[expected type], Sec=(selecting_expression case_statement)}],Old=[@PDefn2{Term=[expected type], Sec=(case expression)}]} The @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is expected to be of any discrete type. @PDefn2{Term=[expected type], Sec=(case_statement_alternative discrete_choice)} The expected type for each @nt{discrete_choice} is the type of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression}. @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3]} The @Chg{Version=[3],New=[@nt{choice_expression}s, @nt{subtype_indication}s,],Old=[@nt{expression}s]} and @Chg{Version=[3],New=[@nt{range}s],Old=[@nt{discrete_range}s]} given as @nt{discrete_choice}s of a @nt{case_statement} shall be static. @Redundant[A @nt{discrete_choice} @key(others), if present, shall appear alone and in the last @nt{discrete_choice_list}.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1],ARef=[AI05-0240-1]} The possible values of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} shall be covered @Chg{Version=[3],New=[(see @RefSecNum{Variant Parts and Discrete Choices}) ], Old=[]}as follows: @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0240-1]} @ChgAdded{Version=[3],Text=[The meaning of "covered" here and in the following rules is that of the term "cover a value" that is defined in @RefSecNum{Variant Parts and Discrete Choices}.]} @end{Discussion} @begin{itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0003-1],ARef=[AI05-0153-3],ARef=[AI05-0188-1],ARef=[AI05-0262-1]} If the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is a @nt{name} @Redundant[(including a @nt<type_conversion>@Chg{Version=[3],New=[, @nt{qualified_expression},],Old=[]} or @Chg{Version=[3],New=[],Old=[a ]}@nt<function_call>)] having a static and constrained nominal subtype,@Chg{Version=[3],New=[],Old=[ or is a @nt{qualified_expression} whose @nt{subtype_mark} denotes a static and constrained scalar subtype,]} then each non-@key{others} @nt{discrete_choice} shall cover only values in that subtype@Chg{Version=[3],New=[ that satisfy its predicate (see @RefSecNum{Subtype Predicates})],Old=[]}, and each value of that subtype@Chg{Version=[3],New=[ that satisfies its predicate],Old=[]} shall be covered by some @nt{discrete_choice} @Redundant[(either explicitly or by @key(others))]. @begin{Ramification} Although not official @nt<name>s of objects, a value conversion still has a defined nominal subtype, namely its target subtype. See @RefSecNum{Type Conversions}. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} If the type of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is @i(root_integer), @i(universal_integer), or a descendant of a formal scalar type, then the @nt{case_statement} shall have an @key{others} @nt{discrete_choice}. @begin{Reason} This is because the base range is implementation defined for @i(root_integer) and @i(universal_integer), and not known statically in the case of a formal scalar type. @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} Otherwise, each value of the base range of the type of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} shall be covered @Redundant[(either explicitly or by @key(others))]. @end{itemize} Two distinct @nt{discrete_choice}s of a @nt{case_statement} shall not cover the same value. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} The goal of these coverage rules is that any possible value of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} of a @nt{case_statement} should be covered by exactly one @nt{discrete_choice} of the @nt{case_statement}, and that this should be checked at compile time. The goal is achieved in most cases, but there are two minor loopholes: @begin{Itemize} If the expression reads an object with an invalid representation (e.g. an uninitialized object), then the value can be outside the covered range. This can happen for static constrained subtypes, as well as nonstatic or unconstrained subtypes. It cannot, however, happen if the @nt{case_statement} has the @nt{discrete_choice} @key{others}, because @key{others} covers all values, even those outside the subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} If the compiler chooses to represent the value of an expression of an unconstrained subtype in a way that includes values outside the bounds of the subtype, then those values can be outside the covered range. For example, if X: Integer := Integer'Last;, and the case @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is X+1, then the implementation might choose to produce the correct value, which is outside the bounds of Integer. (It might raise Constraint_Error instead.) This case can only happen for nongeneric subtypes that are either unconstrained or non@Chg{Version=[2],New=[],Old=[-]}@ChgNote{Make spelling consistent}static (or both). It can only happen if there is no @key{others} @nt{discrete_choice}. @end{Itemize} In the uninitialized variable case, the value might be anything; hence, any alternative can be chosen, or Constraint_Error can be raised. (We intend to prevent, however, jumping to random memory locations and the like.) In the out-of-range case, the behavior is more sensible: if there is an @key{others}, then the implementation may choose to raise Constraint_Error on the evaluation of the @nt{expression} (as usual), or it may choose to correctly evaluate the @nt{expression} and therefore choose the @key{others} alternative. Otherwise (no @key{others}), Constraint_Error is raised either way @em on the @nt{expression} evaluation, or for the @nt{case_statement} itself. For an enumeration type with a discontiguous set of internal codes (see @RefSecNum{Enumeration Representation Clauses}), the only way to get values in between the proper values is via an object with an invalid representation; there is no @lquotes@;out-of-range@rquotes@; situation that can produce them. @end{Ramification} @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} @PDefn2{Term=[execution], Sec=(case_statement)} For the execution of a @nt{case_statement} the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is first evaluated. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0188-1]} If the value of the @Chg{Version=[3],New=[@SynI{selecting_}],Old=[]}@nt{expression} is covered by the @nt{discrete_@!choice_@!list} of some @nt{case_@!statement_@!alternative}, then the @nt{sequence_of_@!statements} of the @ntf{_alternative} is executed. @IndexCheck{Overflow_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Otherwise (the value is not covered by any @nt{discrete_choice_list}, perhaps due to being outside the base range), Constraint_Error is raised. @begin{Ramification} In this case, the value is outside the base range of its type, or is an invalid representation. @end{Ramification} @end{RunTime} @begin{Notes} The execution of a @nt{case_statement} chooses one and only one alternative. Qualification of the expression of a @nt{case_statement} by a static subtype can often be used to limit the number of choices that need be given explicitly. @end{Notes} @begin{Examples} @Leading@keepnext@i{Examples of case statements:} @begin{Example} @tabclear()@tabset(P22) @key[case] Sensor @key[is] @key[when] Elevation@\=> Record_Elevation(Sensor_Value); @key[when] Azimuth@\=> Record_Azimuth (Sensor_Value); @key[when] Distance@\=> Record_Distance (Sensor_Value); @key[when] @key[others]@\=> @key[null]; @key[end] @key[case]; @tabclear()@tabset(P22) @key[case] Today @key[is] @key[when] Mon@\=> Compute_Initial_Balance; @key[when] Fri@\=> Compute_Closing_Balance; @key[when] Tue .. Thu@\=> Generate_Report(Today); @key[when] Sat .. Sun@\=> @key[null]; @key[end] @key[case]; @tabclear()@tabset(P16) @key[case] Bin_Number(Count) @key[is] @key[when] 1@\=> Update_Bin(1); @key[when] 2@\=> Update_Bin(2); @key[when] 3 | 4@\=> Empty_Bin(1); Empty_Bin(2); @key[when] @key[others]@\=> @key[raise] Error; @key[end] @key[case]; @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00020} @Chg{New=[@Defn{incompatibilities with Ada 83} In Ada 95, @nt{function_call}s and @nt{type_conversion}s are @nt{name}s, whereas in Ada 83, they were @nt{expression}s. Therefore, if the @nt{expression} of a @nt{case_statement} is a @nt{function_call} or @nt{type_conversion}, and the result subtype is static, it is illegal to specify a choice outside the bounds of the subtype. For this case in Ada 83 choices only are required to be in the base range of the type.],Old=[]} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00020} @Chg{New=[In addition, the rule about which choices must be covered is unchanged in Ada 95. Therefore, for a @nt{case_statement} whose @nt{expression} is a @nt{function_call} or @nt{type_conversion}, Ada 83 required covering all choices in the base range, while Ada 95 only requires covering choices in the bounds of the subtype. If the @nt{case_statement} does not include an @key{others} @nt{discrete_choice}, then a legal Ada 83 @nt{case_statement} will be illegal in Ada 95 if the bounds of the subtype are different than the bounds of the base type.],Old=[]} @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, the @nt{expression} in a @nt{case_statement} is not allowed to be of a generic formal type. This restriction is removed in Ada 95; an @key{others} @nt{discrete_choice} is required instead. In Ada 95, a function call is the name of an object; this was not true in Ada 83 (see @RefSec{Names}). This change makes the following @nt{case_statement} legal: @begin{Example} @key[subtype] S @key[is] Integer @key[range] 1..2; @key[function] F @key[return] S; @key[case] F @key[is] @key[when] 1 => ...; @key[when] 2 => ...; --@RI{ No @key{others} needed.} @key[end] @key[case]; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Note that the result subtype given in a function @nt{renaming_declaration} is ignored; for a @nt{case_statement} whose expression calls a such a function, the full coverage rules are checked using the result subtype of the original function. Note that predefined operators such as "+" have an unconstrained result subtype (see @RefSecNum{Logical Operators and Short-circuit Control Forms}). Note that generic formal functions do not have static result subtypes. Note that the result subtype of an inherited subprogram need not correspond to any @Chg{Version=[3],New=[nameable],Old=[namable]} subtype; there is still a perfectly good result subtype, though. @end{Extend83} @begin{DiffWord83} Ada 83 forgot to say what happens for @lquotes@;legally@rquotes@; out-of-bounds values. We take advantage of rules and terms (e.g. @i(cover a value)) defined for @nt{discrete_choice}s and @nt{discrete_choice_list}s in @RefSec{Variant Parts and Discrete Choices}. In the @ResolutionName for the case expression, we no longer need RM83-5.4(3)'s @lquotes@;which must be determinable independently of the context in which the expression occurs, but using the fact that the expression must be of a discrete type,@rquotes@; because the @nt{expression} is now a complete context. See @RefSec{The Context of Overload Resolution}. Since @nt<type_conversion>s are now defined as @nt<name>s, their coverage rule is now covered under the general rule for @nt<name>s, rather than being separated out along with @nt<qualified_expression>s. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0003-1]} @ChgAdded{Version=[3],Text=[Rewording to reflect that a @nt{qualified_expression} is now a @nt{name}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[Revised for changes to @nt{discrete_choice}s made to allow static predicates (see @RefSecNum{Subtype Predicates}) as case choices (see @RefSecNum{Variant Parts and Discrete Choices}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0188-1]} @ChgAdded{Version=[3],Text=[Added the @SynI{selecting_} prefix to make this wording consistent with @nt{case_expression}, and to clarify which @nt{expression} is being talked about in the wording.]} @end{Diffword2005} @LabeledClause{Loop Statements} @begin{Intro} @Redundant[A @nt{loop_statement} includes a @nt{sequence_of_statements} that is to be executed repeatedly, zero or more times.] @end{Intro} @begin{Syntax} @Syn{lhs=<loop_statement>,rhs=" [@SynI{loop_}@Syn2{statement_identifier}:] [@Syn2{iteration_scheme}] @key{loop} @Syn2{sequence_of_statements} @key{end} @key{loop} [@SynI{loop_}@Syn2{identifier}];"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0139-2]} @Syn{lhs=<iteration_scheme>,rhs="@key{while} @Syn2{condition} | @key{for} @Syn2{loop_parameter_specification}@Chg{Version=[3],New=[ | @key{for} @Syn2{iterator_specification}],Old=[]}"} @Syn{lhs=<loop_parameter_specification>,rhs=" @Syn2{defining_identifier} @key{in} [@key{reverse}] @Syn2{discrete_subtype_definition}"} @begin(SyntaxText) If a @nt{loop_statement} has a @SynI{loop_}@nt{statement_identifier}, then the @nt<identifier> shall be repeated after the @key{end loop}; otherwise, there shall not be an @nt<identifier> after the @key{end loop}. @end(SyntaxText) @end{Syntax} @begin{StaticSem} @Defn{loop parameter} A @nt{loop_parameter_specification} declares a @i{loop parameter}, which is an object whose subtype is that defined by the @nt{discrete_subtype_definition}. @IndexSeeAlso{Term=[parameter],See=[loop parameter]} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(loop_statement)} For the execution of a @nt{loop_statement}, the @nt{sequence_of_statements} is executed repeatedly, zero or more times, until the @nt{loop_statement} is complete. The @nt{loop_statement} is complete when a transfer of control occurs that transfers control out of the loop, or, in the case of an @nt{iteration_scheme}, as specified below. @PDefn2{Term=[execution], Sec=(loop_statement with a while iteration_scheme)} For the execution of a @nt{loop_statement} with a @key{while} @nt{iteration_scheme}, the condition is evaluated before each execution of the @nt{sequence_of_@!statements}; if the value of the @nt{condition} is True, the @nt{sequence_of_@!statements} is executed; if False, the execution of the @nt{loop_@!statement} is complete. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0139-2],ARef=[AI05-0262-1]} @PDefn2{Term=[execution], Sec=(loop_statement with a for iteration_scheme)} @PDefn2{Term=[elaboration], Sec=(loop_parameter_specification)} For the execution of a @nt{loop_statement} with @Chg{Version=[3],New=[the],Old=[a @key{for}]} @nt{iteration_scheme}@Chg{Version=[3],New=[ being @key[for] @nt{loop_@!parameter_@!specification}],Old=[]}, the @nt{loop_@!parameter_@!specification} is first elaborated. This elaboration creates the loop parameter and elaborates the @nt{discrete_@!subtype_@!definition}. If the @nt{discrete_@!subtype_@!definition} defines a subtype with a null range, the execution of the @nt{loop_statement} is complete. Otherwise, the @nt{sequence_of_@!statements} is executed once for each value of the discrete subtype defined by the @nt{discrete_@!subtype_@!definition} @Chg{Version=[3],New=[that satisfies the predicate of the subtype ],Old=[]}(or until the loop is left as a consequence of a transfer of control). @Defn2{Term=[assignment operation], Sec=(during execution of a @key{for} loop)} Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter. These values are assigned in increasing order unless the reserved word @key{reverse} is present, in which case the values are assigned in decreasing order. @begin{Ramification} The order of creating the loop parameter and evaluating the @nt{discrete_subtype_definition} doesn't matter, since the creation of the loop parameter has no side effects (other than possibly raising Storage_Error, but anything can do that). @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The predicate (if any) necessarily has to be a static predicate as a dynamic predicate is explicitly disallowed @em see @RefSecNum{Subtype Predicates}.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If there is a predicate, the loop still visits the values in the order of the underlying base type; the order of the values in the predicate is irrelevant. This is the case so that the following loops have the same sequence of calls and parameters on procedure Call for any subtype S:]} @begin{Example} @ChgAdded{Version=[3],Text=[@key[for] I @key[in] S @key[loop] Call (I); @key[end loop];]} @ChgAdded{Version=[3],Text=[@key[for] I @key[in] S'Base @key[loop] @key[if] I @key[in] S @key[then] Call (I); @key[end if]; @key[end loop];]} @end{Example} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@Redundant[For details about the execution of a @nt{loop_statement} with the @nt{iteration_scheme} being @key[for] @nt{iterator_specification}, see @RefSecNum{Generalized Loop Iteration}.]]} @end{RunTime} @begin{Notes} A loop parameter is a constant; it cannot be updated within the @nt{sequence_of_statements} of the loop (see @RefSecNum{Objects and Named Numbers}). An @nt{object_declaration} should not be given for a loop parameter, since the loop parameter is automatically declared by the @nt{loop_parameter_specification}. The scope of a loop parameter extends from the @nt{loop_parameter_specification} to the end of the @nt{loop_statement}, and the visibility rules are such that a loop parameter is only visible within the @nt{sequence_of_statements} of the loop. @begin{ImplNote} An implementation could give a warning if a variable is hidden by a @nt{loop_parameter_specification}. @end{ImplNote} The @nt<discrete_subtype_definition> of a for loop is elaborated just once. Use of the reserved word @key[reverse] does not alter the discrete subtype defined, so that the following @nt{iteration_scheme}s are not equivalent; the first has a null range. @begin{Example} @key[for] J @key[in] @key[reverse] 1 .. 0 @key[for] J @key[in] 0 .. 1 @end{Example} @begin{Ramification} If a @nt{loop_parameter_specification} has a static discrete range, the subtype of the loop parameter is static. @end{Ramification} @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of a loop statement without an iteration scheme:} @begin{Example} @key[loop] Get(Current_Character); @key[exit] @key[when] Current_Character = '*'; @key[end] @key[loop]; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a loop statement with a @key[while] iteration scheme:} @end{WideAbove} @begin{Example} @key[while] Bid(N).Price < Cut_Off.Price @key[loop] Record_Bid(Bid(N).Price); N := N + 1; @key[end] @key[loop]; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a loop statement with a @key[for] iteration scheme:} @end{WideAbove} @begin{Example} @key[for] J @key[in] Buffer'Range @key[loop] --@RI{ works even with a null range} @key[if] Buffer(J) /= Space @key[then] Put(Buffer(J)); @key[end] @key[if]; @key[end] @key[loop]; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a loop statement with a name:} @end{WideAbove} @begin{Example} Summation: @key[while] Next /= Head @key[loop] --@RI{ see @RefSecNum{Incomplete Type Declarations}} Sum := Sum + Next.Value; Next := Next.Succ; @key[end] @key[loop] Summation; @end{Example} @end{Examples} @begin{DiffWord83} The constant-ness of loop parameters is specified in @RefSec{Objects and Named Numbers}. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0262-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Generalized @nt{iterator_specification}s are allowed in @key[for] loops; these are documented as an extension in the appropriate subclause.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[User-Defined Iterator Types]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The following language-defined generic library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada],Child=[Iterator_Interfaces]}@key[generic] @key[type] Cursor; @key[with function] Has_Element (Position : Cursor) @key[return] Boolean; @key[package] Ada.Iterator_Interfaces @key[is] @key[pragma] Pure (Iterator_Interfaces);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Forward_Iterator} @key[is limited interface]; @key[function] @AdaSubDefn{First} (Object : Forward_Iterator) @key[return] Cursor @key[is abstract]; @key[function] @AdaSubDefn{Next} (Object : Forward_Iterator; Position : Cursor) @key[return] Cursor @key[is abstract];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reversible_Iterator} @key[is limited interface and] Forward_Iterator; @key[function] @AdaSubDefn{Last} (Object : Reversible_Iterator) @key[return] Cursor @key[is abstract]; @key[function] @AdaSubDefn{Previous} (Object : Reversible_Iterator; Position : Cursor) @key[return] Cursor @key[is abstract];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Iterator_Interfaces;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[An @i<iterator type> is a type descended from the Forward_Iterator interface from some instance of Ada.Iterator_Interfaces.@Defn{iterator type} A @i<reversible iterator type> is a type descended from the Reversible_Iterator interface from some instance of Ada.Iterator_Interfaces.@Defn{reversible iterator type} An @i<iterator object> is an object of an iterator type.@Defn{iterator object} A @i<reversible iterator object> is an object of a reversible iterator type.@Defn{reversible iterator object} The formal subtype Cursor from the associated instance of Ada.Iterator_Interfaces is the @i<iteration cursor subtype> for the iterator type.@Defn{iteration cursor subtype}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following type-related operational aspects may be specified for an indexable container type @i<T> (see @RefSecNum{User-Defined Indexing}):]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Default_Iterator@\This aspect is specified by a @nt{name} that denotes exactly one function declared immediately within the same declaration list in which @i<T> is declared, whose first parameter is of type @i<T> or @i<T>'Class or an access parameter whose designated type is type @i<T> or @i<T>'Class, whose other parameters, if any, have default expressions, and whose result type is an iterator type. This function is the @i<default iterator function> for @i<T>.@Defn{default iterator function} Its result subtype is the @i<default iterator subtype> for @i<T>.@Defn{default iterator subtype} The iteration cursor subtype for the default iterator subtype is the @i<default cursor subtype> for @i<T>.@Defn{default cursor subtype}@AspectDefn{Default_Iterator}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Default_Iterator], Text=[@ChgAdded{Version=[3],Text=[Default iterator to be used in @key[for] loops.]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Iterator_Element@\This aspect is specified by a @nt{name} that denotes a subtype. This is the @i<default element subtype> for @i<T>.@Defn{default element subtype}@AspectDefn{Iterator_Element}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Iterator_Element], Text=[@ChgAdded{Version=[3],Text=[Element type to be used for user-defined iterators.]}]} @end{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These aspects are inherited by descendants of type @i<T> (including @i<T>'Class).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[An @i<iterable container type> is an indexable container type with specified Default_Iterator and Iterator_Element aspects.@Defn{iterable container type} A @i<reversible iterable container type> is an iterable container type with the default iterator type being a reversible iterator type.@Defn{reversible iterable container type} An @i<iterable container object> is an object of an iterable container type.@Defn{iterable container object} A @i<reversible iterable container object> is an object of a reversible iterable container type.@Defn{reversible iterable container object}]} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Iterable container type>, Text=<@ChgAdded{Version=[3],Text=[An iterable container type is one that has user-defined behavior for iteration, via the Default_Iterator and Iterator_Element aspects.]}>} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The Constant_Indexing aspect (if any) of an iterable container type @i<T> shall denote exactly one function with the following properties:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the result type of the function is covered by the default element type of @i<T> or is a reference type (see @RefSecNum{User-Defined References}) with an access discriminant designating a type covered by the default element type of @i<T>;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the type of the second parameter of the function covers the default cursor type for @i<T>;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if there are more than two parameters, the additional parameters all have default expressions.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This function (if any) is the @i<default constant indexing function> for @i<T>.@Defn{default constant indexing function}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This does not mean that Constant_Indexing has to designate only one subprogram, only that there is only one routine that meets all of these properties. There can be other routines designated by Constant_Indexing, but they cannot have the profile described above. For instance, map containers have a version of Constant_Indexing that takes a key instead of a cursor; this is allowed.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The Variable_Indexing aspect (if any) of an iterable container type @i<T> shall denote exactly one function with the following properties:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the result type of the function is a reference type (see @RefSecNum{User-Defined References}) with an access discriminant designating a type covered by the default element type of @i<T>;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the type of the second parameter of the function covers the default cursor type for @i<T>;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if there are more than two parameters, the additional parameters all have default expressions.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This function (if any) is the @i<default variable indexing function> for @i<T>.@Defn{default variable indexing function}]} @end{Legality} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}User-defined iterator types are new in Ada 2012.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[Generalized Loop Iteration]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[Generalized forms of loop iteration are provided by an @nt{iterator_specification}.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<iterator_specification>,Old=<>}>, rhs="@Chg{Version=[3],New=< @Syn2{defining_identifier} @key[in] [@key{reverse}] @SynI{iterator_}@Syn2{name} | @Syn2{defining_identifier} [: @Syn2{subtype_indication}] @key[of] [@key{reverse}] @SynI{iterable_}@Syn2{name}>,Old=<>}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[For the first form of @nt{iterator_specification}, called a @i<generalized iterator>,@Defn{generalized iterator}@Defn2{Term=[iterator],Sec=[generalized]} the expected type for the @SynI<iterator_>@nt{name} is any iterator type.@PDefn2{Term=[expected type],Sec=[@SynI<iterator_>@nt{name}]} For the second form of @nt{iterator_specification}, the expected type for the @SynI<iterable_>@nt{name} is any array or iterable container type.@PDefn2{Term=[expected type],Sec=[@SynI<iterable_>@nt{name}]} If the @SynI<iterable_>@nt{name} denotes an array object, the @nt{iterator_specification} is called an @i<array component iterator>;@Defn{array component iterator}@Defn2{Term=[iterator],Sec=[array component]} otherwise it is called a @i<container element iterator>.@Defn{container element iterator}@Defn2{Term=[iterator],Sec=[container element]}]} @end{Resolution} @begin{Legality} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Iterator>, Text=<@ChgAdded{Version=[3],Text=[An iterator is a construct that is used to loop over the elements of an array or container. Iterators may be user defined, and may perform arbitrary computations to access elements from a container.]}>} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[If the reserved word @key[reverse] appears, the @nt{iterator_specification} is a @i<reverse iterator>;@Defn{reverse iterator}@Defn2{Term=[iterator],Sec=[reverse]} otherwise it is a @i<forward iterator>.@Defn{forward iterator}@Defn2{Term=[iterator],Sec=[forward]} In a reverse generalized iterator, the @SynI<iterator_>@nt{name} shall be of a reversible iterator type. In a reverse container element iterator, the default iterator type for the type of the @SynI<iterable_>@nt{name} shall be a reversible iterator type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[The type of the @nt{subtype_indication}, if any, of an array component iterator shall cover the component type of the type of the @SynI<iterable_>@nt{name}. The type of the @nt{subtype_indication}, if any, of a container element iterator shall cover the default element type for the type of the @SynI<iterable_>@nt{name}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[In a container element iterator whose @SynI<iterable_>@nt{name} has type @i<T>, if the @SynI<iterable_>@nt{name} denotes a constant or the Variable_Indexing aspect is not specified for @i<T>, then the Constant_Indexing aspect shall be specified for @i<T>.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0269-1],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[An @nt{iterator_specification} declares a @i<loop parameter>.@Defn{loop parameter} In a generalized iterator, the nominal subtype of the loop parameter is the iteration cursor subtype. In an array component iterator or a container element iterator, if a @nt{subtype_indication} is present, it determines the nominal subtype of the loop parameter. In an array component iterator, if a @nt{subtype_indication} is not present, the nominal subtype of the loop parameter is the component subtype of the type of the @SynI{iterable_}@nt{name}. In a container element iterator, if a @nt{subtype_indication} is not present, the nominal subtype of the loop parameter is the default element subtype for the type of the @SynI{iterable_}@nt{name}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[In a generalized iterator, the loop parameter is a constant. In an array component iterator, the loop parameter is a constant if the @SynI<iterable_>@nt{name} denotes a constant; otherwise it denotes a variable. In a container element iterator, the loop parameter is a constant if the @SynI{iterable_}@nt{name} denotes a constant, or if the Variable_Indexing aspect is not specified for the type of the @SynI{iterable_}@nt{name}; otherwise it is a variable.]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[For the execution of a @nt{loop_statement} with an @nt{iterator_specification}, the @nt{iterator_specification} is first elaborated. This elaboration elaborates the @nt{subtype_indication}, if any.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[For a generalized iterator, the loop parameter is created, the @SynI{iterator_}@nt{name} is evaluated, and the denoted iterator object becomes the @i<loop iterator>.@Defn{loop iterator} In a forward generalized iterator, the operation First of the iterator type is called on the loop iterator, to produce the initial value for the loop parameter. If the result of calling Has_Element on the initial value is False, then the execution of the @nt{loop_statement} is complete. Otherwise, the @nt{sequence_of_statements} is executed and then the Next operation of the iterator type is called with the loop iterator and the current value of the loop parameter to produce the next value to be assigned to the loop parameter. This repeats until the result of calling Has_Element on the loop parameter is False, or the loop is left as a consequence of a transfer of control. For a reverse generalized iterator, the operations Last and Previous are called rather than First and Next.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[For an array component iterator, the @SynI<iterable_>@nt{name} is evaluated and the denoted array object becomes the @i<array for the loop>.@Defn{array for a loop} If the array for the loop is a null array, then the execution of the @nt{loop_statement} is complete. Otherwise, the @nt{sequence_of_statements} is executed with the loop parameter denoting each component of the array for the loop, using a @i<canonical> order of components,@Defn{canonical order of array components} which is last dimension varying fastest (unless the array has convention Fortran, in which case it is first dimension varying fastest). For a forward array component iterator, the iteration starts with the component whose index values are each the first in their index range, and continues in the canonical order. For a reverse array component iterator, the iteration starts with the component whose index values are each the last in their index range, and continues in the reverse of the canonical order. The loop iteration proceeds until the @nt{sequence_of_statements} has been executed for each component of the array for the loop, or until the loop is left as a consequence of a transfer of control.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[For a container element iterator, the @SynI<iterable_>@nt{name} is evaluated and the denoted iterable container object becomes the @i<iterable container object for the loop>.@Defn{iterable container object for a loop} The default iterator function for the type of the iterable container object for the loop is called on the iterable container object and the result is the @i<loop iterator>.@Defn2{Term=[loop iterator],Sec=[container element iterator]} An object of the default cursor subtype is created (the @i<loop cursor>).@Defn{loop cursor}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2],ARef=[AI05-0292-1]} @ChgAdded{Version=[3],Text=[For a forward container element iterator, the operation First of the iterator type is called on the loop iterator, to produce the initial value for the loop cursor. If the result of calling Has_Element on the initial value is False, then the execution of the @nt{loop_statement} is complete. Otherwise, the @nt{sequence_of_statements} is executed with the loop parameter denoting an indexing (see @RefSecNum{User-Defined Indexing}) into the iterable container object for the loop, with the only parameter to the indexing being the current value of the loop cursor; then the Next operation of the iterator type is called with the loop iterator and the loop cursor to produce the next value to be assigned to the loop cursor. This repeats until the result of calling Has_Element on the loop cursor is False, or until the loop is left as a consequence of a transfer of control. For a reverse container element iterator, the operations Last and Previous are called rather than First and Next. If the loop parameter is a constant (see above), then the indexing uses the default constant indexing function for the type of the iterable container object for the loop; otherwise it uses the default variable indexing function.]} @end{Runtime} @begin{Examples} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[-- @Examcom{Array component iterator example:} @key[for] Element @key[of] Board @key[loop] -- @Examcom{See @RefSecNum{Index Constraints and Discrete Ranges}.} Element := Element * 2.0; -- @Examcom{Double each element of Board, a two-dimensional array.} @key[end loop];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0268-1]} @ChgAdded{Version=[3],Text=[For examples of use of generalized iterators, see @RefSecNum{Example of Container Use} and the corresponding container packages in @RefSecNum{The Generic Package Containers.Vectors} and @RefSecNum{The Generic Package Containers.Doubly_Linked_Lists}.]} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Generalized forms of loop iteration are new.]} @end{Extend2005} @RMNewPageVer{Version=[0]}@Comment{For printed version of Ada 95} @RMNewPageVer{Version=[1]}@Comment{For printed version of Ada 95 + TC1 RM} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Block Statements} @begin{Intro} @Redundant[A @nt{block_statement} encloses a @nt{handled_sequence_of_statements} optionally preceded by a @nt{declarative_part}.] @end{Intro} @begin{Syntax} @Syn{lhs=<block_statement>,rhs=" [@SynI{block_}@Syn2{statement_identifier}:] [@key{declare} @Syn2{declarative_part}] @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{block_}@Syn2{identifier}];"} @begin(SyntaxText) If a @nt{block_statement} has a @SynI{block_}@nt{statement_identifier}, then the @nt<identifier> shall be repeated after the @key{end}; otherwise, there shall not be an @nt<identifier> after the @key{end}. @end(SyntaxText) @end{Syntax} @begin{StaticSem} A @nt{block_statement} that has no explicit @nt{declarative_part} has an implicit empty @nt{declarative_part}. @begin{Ramification} Thus, other rules can always refer to the @nt{declarative_part} of a @nt<block_statement>. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(block_statement)} The execution of a @nt{block_statement} consists of the elaboration of its @nt{declarative_part} followed by the execution of its @nt{handled_sequence_of_statements}. @end{RunTime} @begin{Examples} @Leading@keepnext@i{Example of a block statement with a local variable:} @begin{Example} Swap: @key[declare] Temp : Integer; @key[begin] Temp := V; V := U; U := Temp; @key[end] Swap; @end{Example} @begin{Ramification} If task objects are declared within a @nt{block_statement} whose execution is completed, the @nt{block_statement} is not left until all its dependent tasks are terminated (see @RefSecNum{Assignment and Finalization}). This rule applies to completion caused by a transfer of control. Within a @nt{block_statement}, the block name can be used in expanded names denoting local entities such as Swap.Temp in the above example (see @RefSecNum{Selected Components}). @end{Ramification} @end{Examples} @begin{DiffWord83} The syntax rule for @nt{block_statement} now uses the syntactic category @nt{handled_sequence_of_statements}. @end{DiffWord83} @LabeledClause{Exit Statements} @begin{Intro} @Redundant[An @nt{exit_statement} is used to complete the execution of an enclosing @nt{loop_statement}; the completion is conditional if the @nt{exit_statement} includes a @nt{condition}.] @end{Intro} @begin{Syntax} @Syn{lhs=<exit_statement>,rhs=" @key{exit} [@SynI{loop_}@Syn2{name}] [@key{when} @Syn2{condition}];"} @end{Syntax} @begin{Resolution} The @i(loop_)@nt{name}, if any, in an @nt{exit_statement} shall resolve to denote a @nt{loop_statement}. @end{Resolution} @begin{Legality} @Defn2{Term=[apply], Sec=(to a @nt{loop_statement} by an @nt{exit_statement})} Each @nt{exit_@!statement} @i{applies to} a @nt{loop_@!statement}; this is the @nt{loop_@!statement} being exited. An @nt{exit_@!statement} with a @nt{name} is only allowed within the @nt{loop_@!statement} denoted by the @nt{name}, and applies to that @nt{loop_@!statement}. An @nt{exit_@!statement} without a @nt{name} is only allowed within a @nt{loop_@!statement}, and applies to the innermost enclosing one. An @nt{exit_@!statement} that applies to a given @nt{loop_@!statement} shall not appear within a body or @nt{accept_@!statement}, if this construct is itself enclosed by the given @nt{loop_statement}. @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(exit_statement)} For the execution of an @nt{exit_statement}, the @nt{condition}, if present, is first evaluated. If the value of the @nt{condition} is True, or if there is no @nt{condition}, a transfer of control is done to complete the @nt{loop_@!statement}. If the value of the @nt{condition} is False, no transfer of control takes place. @end{RunTime} @begin{Notes} Several nested loops can be exited by an @nt{exit_statement} that names the outer loop. @end{Notes} @begin{Examples} @i{Examples of loops with exit statements:} @begin{Example} @key[for] N @key[in] 1 .. Max_Num_Items @key[loop] Get_New_Item(New_Item); Merge_Item(New_Item, Storage_File); @key[exit] @key[when] New_Item = Terminal_Item; @key[end] @key[loop]; Main_Cycle: @key[loop] --@RI{ initial statements} @key[exit] Main_Cycle @key[when] Found; --@RI{ final statements} @key[end] @key[loop] Main_Cycle; @end{Example} @end{Examples} @LabeledClause{Goto Statements} @begin{Intro} @Redundant[A @nt{goto_statement} specifies an explicit transfer of control from this @nt{statement} to a target statement with a given label.] @end{Intro} @begin{Syntax} @Syn{lhs=<goto_statement>,rhs="@key{goto} @SynI{label_}@Syn2{name};"} @end{Syntax} @begin{Resolution} @Defn2{Term=[target statement], Sec=(of a @nt{goto_statement})} The @i(label_)@nt{name} shall resolve to denote a @nt<label>; the @nt{statement} with that @nt{label} is the @i(target statement). @end{Resolution} @begin{Legality} The innermost @nt{sequence_of_statements} that encloses the target statement shall also enclose the @nt{goto_statement}. Furthermore, if a @nt{goto_statement} is enclosed by an @nt{accept_statement} or a body, then the target statement shall not be outside this enclosing construct. @begin{Ramification} The @nt{goto_statement} can be a @nt{statement} of an inner @ntf{sequence_}. It follows from the second rule that if the target @nt{statement} is enclosed by such a construct, then the @nt{goto_statement} cannot be outside. @end{Ramification} @end{Legality} @begin{RunTime} @PDefn2{Term=[execution], Sec=(goto_statement)} The execution of a @nt{goto_statement} transfers control to the target statement, completing the execution of any @nt<compound_statement> that encloses the @nt<goto_statement> but does not enclose the target. @end{RunTime} @begin{Notes} The above rules allow transfer of control to a @nt{statement} of an enclosing @nt{sequence_of_statements} but not the reverse. Similarly, they prohibit transfers of control such as between alternatives of a @nt{case_statement}, @nt{if_statement}, or @nt{select_statement}; between @nt{exception_handler}s; or from an @nt{exception_handler} of a @nt{handled_sequence_of_statements} back to its @nt{sequence_of_statements}. @end{Notes} @begin{Examples} @Leading@keepnext@i{Example of a loop containing a goto statement:} @begin{Example} <<Sort>> @key[for] I @key[in] 1 .. N-1 @key[loop] @key[if] A(I) > A(I+1) @key[then] Exchange(A(I), A(I+1)); @key[goto] Sort; @key[end] @key[if]; @key[end] @key[loop]; @end{Example} @end{Examples} �����������������������������������������������������org.adaic.arm_form/source_2012/06.mss���������������������������������������������������������������0000755�0001752�0001001�00000667045�12066652506�016420� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(06, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @LabeledSection{Subprograms} @Comment{$Source: e:\\cvsroot/ARM/Source/06.mss,v $} @Comment{$Revision: 1.128 $} @begin{Intro} @Defn{subprogram} @Defn{procedure} @Defn{function} A subprogram is a program unit or intrinsic operation whose execution is invoked by a subprogram call. There are two forms of subprogram: procedures and functions. A procedure call is a @nt{statement}; a function call is an expression and returns a value. The definition of a subprogram can be given in two parts: a subprogram declaration defining its interface, and a @nt{subprogram_body} defining its execution. @Redundant[Operators and enumeration literals are functions.] @begin{Honest} A function call is an expression, but more specifically it is a @nt<name>. @end{Honest} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Subprogram>, Text=<@ChgAdded{Version=[2],Text=[A subprogram is a section of a program that can be executed in various contexts. It is invoked by a subprogram call that may qualify the effect of the subprogram through the passing of parameters. There are two forms of subprograms: functions, which return values, and procedures, which do not.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Function>, Text=<@ChgAdded{Version=[2],Text=[A function is a form of subprogram that returns a result and can be called as part of an expression.]}>} @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Procedure>, Text=<@ChgAdded{Version=[2],Text=[A procedure is a form of subprogram that does not return a result and can only be called by a @nt{statement}.]}>} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{callable entity} A @i(callable entity) is a subprogram or entry (see @Chg{Version=[3],New=[Section 9],Old=[@RefSecNum{Entries and Accept Statements}]}). @Defn{call} A callable entity is invoked by a @i{call}; that is, a subprogram call or entry call. @Defn{callable construct} A @i(callable construct) is a construct that defines the action of a call upon a callable entity: a @nt{subprogram_body}, @nt{entry_body}, or @nt{accept_statement}. @begin{Ramification} Note that @lquotes@;callable entity@rquotes@; includes predefined operators, enumeration literals, and abstract subprograms. @lquotes@;Call@rquotes@; includes calls of these things. They do not have callable constructs, since they don't have completions. @end{Ramification} @end{Intro} @LabeledClause{Subprogram Declarations} @begin{Intro} @Redundant[A @nt{subprogram_declaration} declares a procedure or function.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<subprogram_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=<>}@Syn2{subprogram_specification}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00348-01]} @DeletedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<>,Old=<abstract_subprogram_declaration>}>, rhs="@Chg{Version=[2],New=<>,Old=<@Syn2{subprogram_specification} @key{is} @key{abstract};>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Syn{lhs=<subprogram_specification>,rhs="@Chg{Version=[2],New=[ @Syn2{procedure_specification} | @Syn2{function_specification}],Old=[ @key{procedure} @Syn2{defining_program_unit_name} @Syn2{parameter_profile} | @key{function} @Syn2{defining_designator} @Syn2{parameter_and_result_profile}]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<procedure_specification>,Old=<>}>, rhs="@Chg{Version=[2],New=<@key{procedure} @Syn2{defining_program_unit_name} @Syn2{parameter_profile}>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<function_specification>,Old=<>}>, rhs="@Chg{Version=[2],New=<@key{function} @Syn2{defining_designator} @Syn2{parameter_and_result_profile}>,Old=<>}"} @Syn{lhs=<designator>,rhs="[@Syn2{parent_unit_name} . ]@Syn2{identifier} | @Syn2{operator_symbol}"} @Syn{lhs=<defining_designator>, rhs="@Syn2{defining_program_unit_name} | @Syn2{defining_operator_symbol}"} @Syn{lhs=<defining_program_unit_name>,rhs="[@Syn2{parent_unit_name} . ]@Syn2{defining_identifier}"} @begin{SyntaxText} @Redundant[The optional @nt{parent_unit_name} is only allowed for library units (see @RefSecNum{Compilation Units - Library Units}).] @end{SyntaxText} @Syn{lhs=<operator_symbol>,rhs="@Syn2{string_literal}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The sequence of characters in an @nt{operator_symbol} shall @Chg{Version=[2], New=[form a reserved word, a delimiter, or compound delimiter that corresponds],Old=[correspond]} to an operator belonging to one of the six @Chg{Version=[2],New=[categories], Old=[classes]} of operators defined in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Operators and Expression Evaluation}@Chg{Version=[2], New=[],Old=[(spaces are not allowed and the case of letters is not significant)]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0090-1]} @ChgAdded{Version=[2],Text=[The @ldquote@;sequence of characters@rdquote of the string literal of the operator is a technical term (see @RefSecNum{String Literals}), and does not include the surrounding quote characters. As defined in @RefSecNum{Lexical Elements, Separators, and Delimiters}, lexical elements are @lquotes@;formed@rquotes from a sequence of characters. Spaces are not allowed, and upper and lower case is not significant.@Chg{Version=[3],New=[],Old=[ See @RefSecNum{Lexical Elements, Separators, and Delimiters} and @RefSecNum{Reserved Words} for rules related to the use of @ntf{other_format} characters in delimiters and reserved words.]}]} @end{Reason} @end{SyntaxText} @Syn{lhs=<defining_operator_symbol>,rhs="@Syn2{operator_symbol}"} @Syn{lhs=<parameter_profile>,rhs="[@Syn2{formal_part}]"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @Syn{lhs=<parameter_and_result_profile>,rhs="@Chg{Version=[2],New=[ ],Old=[]}[@Syn2{formal_part}] @key{return}@Chg{Version=[2],New=< [@Syn2{null_exclusion}]>,Old=<>} @Syn2{subtype_mark}@Chg{Version=[2],New=< | [@Syn2{formal_part}] @key{return} @Syn2{access_definition}>,Old=<>}"} @Syn{lhs=<formal_part>,rhs=" (@Syn2{parameter_specification} {; @Syn2{parameter_specification}})"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0142-4]} @Syn{lhs=<parameter_specification>,rhs=" @Syn2{defining_identifier_list} : @Chg{Version=[3],New=<[@key[aliased]] >,Old=<>}@Syn2{mode} @Chg{Version=[2],New=<[@Syn2{null_exclusion}]>,Old=<>} @Syn2{subtype_mark} [:= @Syn2{default_expression}] | @Syn2{defining_identifier_list} : @Syn2{access_definition} [:= @Syn2{default_expression}]"} @Syn{lhs=<mode>,rhs="[@key{in}] | @key{in} @key{out} | @key{out}"} @end{Syntax} @begin{Resolution} @Defn2{Term=[formal parameter], Sec=(of a subprogram)} A @i(formal parameter) is an object @Redundant[directly visible within a @nt{subprogram_body}] that represents the actual parameter passed to the subprogram in a call; it is declared by a @nt{parameter_specification}. @PDefn2{Term=[expected type], Sec=(parameter @nt{default_expression})} For a formal parameter, the expected type for its @nt<default_expression>, if any, is that of the formal parameter. @IndexSee{Term=[parameter],See=[formal parameter]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0143-1]} @Defn{parameter mode} The @i(parameter mode) of a formal parameter conveys the direction of information transfer with the actual parameter: @key(in), @key(in out), or @key(out). Mode @key(in) is the default, and is the mode of a parameter defined by an @nt{access_definition}.@Chg{Version=[3],New=[],Old=[ The formal parameters of a function, if any, shall have the mode @key(in).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0143-1]} @ChgDeleted{Version=[3],Text=[Access parameters are permitted. This restriction to @b(in) parameters is primarily a methodological restriction, though it also simplifies implementation for some compiler technologies.]} @end{Ramification} A @nt{default_expression} is only allowed in a @nt{parameter_specification} for a formal parameter of mode @key(in). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1],ARef=[AI05-0229-1]} @PDefn2{Term=[requires a completion], Sec=(@nt{subprogram_declaration})} @PDefn2{Term=[requires a completion], Sec=(@nt{generic_subprogram_declaration})} A @nt{subprogram_declaration} or a @nt{generic_subprogram_declaration} requires a completion@Chg{Version=[3],New=[],Old=[:]} @Redundant[@Chg{Version=[3],New=[unless the Import aspect (see @RefSecNum{Interfacing Aspects}) is True for the declaration; the completion shall be ],Old=[]}a body@Chg{Version=[3],New=[ or],Old=[,]} a @nt<renaming_declaration> (see @RefSecNum(Renaming Declarations))@Chg{Version=[3],New=[],Old=[, or a @Chg{Version=[2],New=[@nt{pragma}], Old=[@key(pragma)]} Import (see @RefSecNum{Interfacing Aspects})]}]. @Redundant[A completion is not allowed for an @nt<abstract_subprogram_declaration>@Chg{Version=[2],New=[ (see @RefSecNum{Abstract Types and Subprograms})@Chg{Version=[3],New=[,],Old=[ or]} a @nt{null_procedure_declaration} (see @RefSecNum{Null Procedures})@Chg{Version=[3],New=[, or an @nt{expression_function_declaration} (see @RefSecNum{Expression Functions})],Old=[]}],Old=[]}.] @begin(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} Abstract subprograms @Chg{Version=[2],New=[@Chg{Version=[3],New=[,],Old=[and]} null procedures@Chg{Version=[3],New=[, and expression functions],Old=[]} ],Old=[]}are not declared by @nt{subprogram_declaration}s, and so do not require completion@Chg{Version=[3],New=[ (although the latter two can @i<be> completions)],Old=[]}. Protected subprograms are declared by @nt{subprogram_declaration}s, and so require completion. Note that an abstract subprogram is a subprogram, @Chg{Version=[3],New=[a null procedure is a subprogram, an expression function is a subprogram, ],Old=[]}and a protected subprogram is a subprogram, but a generic subprogram is not a subprogram.@Comment{Who's the idiot that came up with that??} @end(Ramification) @begin(TheProof) @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[When the Import aspect is True for any entity, no completion is allowed (see @RefSecNum{Interfacing Aspects}).]} @end{TheProof} A @nt{name} that denotes a formal parameter is not allowed within the @nt{formal_part} in which it is declared, nor within the @nt{formal_part} of a corresponding body or @nt{accept_statement}. @begin{Ramification} By contrast, @nt<generic_formal_parameter_declaration>s are visible to subsequent declarations in the same @nt<generic_formal_part>. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{profile} The @i(profile) of (a view of) a callable entity is either a @nt{parameter_profile} or @nt{parameter_and_result_profile}@Redundant[; it embodies information about the interface to that entity @em for example, the profile includes information about parameters passed to the callable entity. All callable entities have a profile @em enumeration literals, other subprograms, and entries. An access-to-subprogram type has a designated profile.] Associated with a profile is a calling convention. A @nt<subprogram_declaration> declares a procedure or a function, as indicated by the initial reserved word, with name and profile as given by its specification. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @PDefn2{Term=[nominal subtype], Sec=(of a formal parameter)} The nominal subtype of a formal parameter is the subtype @Chg{Version=[2],New=[determined],Old=[denoted]} by @Chg{Version=[2],New=[the optional @nt{null_exclusion} and ], Old=[]}the @nt{subtype_mark}, or defined by the @nt{access_definition}, in the @nt{parameter_specification}.@Chg{Version=[2],New=[ The nominal subtype of a function result is the subtype determined by the optional @nt{null_exclusion} and the @nt{subtype_mark}, or defined by the @nt{access_definition}, in the @nt{parameter_and_result_profile}. @PDefn2{Term=[nominal subtype], Sec=(of a function result)}], Old=[]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[@Defn{explicitly aliased parameter}@Defn2{Term=[parameter],Sec=(explicitly aliased)}An @i(explicitly aliased parameter) is a formal parameter whose @nt{parameter_specification} includes the reserved word @key[aliased].]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00318-02]} @Defn{access parameter} An @i(access parameter) is a formal @key[in] parameter specified by an @nt{access_definition}. @Defn{access result type} @Chg{Version=[2],New=[An @i(access result type) is a function result type specified by an @nt{access_definition}.],Old=[]} An access parameter @Chg{Version=[2],New=[or result type ],Old=[]}is of an anonymous @Chg{Version=[2],New=[access],Old=[general access-to-variable]} type (see @RefSecNum{Access Types}). @Redundant[Access parameters @Chg{Version=[2],New=[of an access-to-object type],Old=[]} allow dispatching calls to be controlled by access values.@Chg{Version=[2],New=[ Access parameters of an access-to-subprogram type permit calls to subprograms passed as parameters irrespective of their accessibility level.],Old=[]}] @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Access result types have normal accessibility and thus don't have any special properties worth noting here.]} @end{Discussion} @leading@keepnext@Defn2{Term=[subtypes], Sec=(of a profile)} The @i(subtypes of a profile) are: @begin{Itemize} For any non-access parameters, the nominal subtype of the parameter. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} For any access parameters@Chg{Version=[2],New=[ of an access-to-object type],Old=[]}, the designated subtype of the parameter type. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0164-1]} @ChgAdded{Version=[2],Text=[For any access parameters of an access-to-subprogram type, the subtypes of the @Chg{Version=[3],New=[designated ],Old=[]}profile of the parameter type.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For any non-access result, the nominal subtype of the function result.],Old=[For any result, the result subtype.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[For any access result type of an access-to-object type, the designated subtype of the result type.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0164-1]} @Chg{Version=[2],New=[For any access result type of an access-to-subprogram type, the subtypes of the @Chg{Version=[3],New=[designated ],Old=[]}profile of the result type.],Old=[]} @end{Itemize} @Redundant[@Defn2{Term=[types], Sec=(of a profile)} The @i{types of a profile} are the types of those subtypes.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} @Redundant[A subprogram declared by an @nt<abstract_subprogram_declaration> is abstract; a subprogram declared by a @nt<subprogram_declaration> is not. See @RefSec{Abstract Types and Subprograms}.@Chg{Version=[2],New=[ Similarly, a procedure @Chg{Version=[3],New=[declared],Old=[defined]} by a @nt{null_procedure_declaration} is a null procedure; a procedure declared by a @nt{subprogram_declaration} is not. See @RefSec{Null Procedures}.@Chg{Version=[3],New=[ Finally, a function declared by an @nt{expression_function_declaration} is an expression function; a function declared by a @nt{subprogram_declaration} is not. See @RefSec{Expression Functions}.],Old=[]}],Old=[]}] @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Redundant[An @nt{overriding_indicator} is used to indicate whether overriding is intended. See @RefSec{Overriding Indicators}.]]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @PDefn2{Term=[elaboration], Sec=(subprogram_declaration)}@Chg{Version=[2],New=[],Old=[ @PDefn2{Term=[elaboration], Sec=(abstract_subprogram_declaration)}]} The elaboration of a @nt{subprogram_declaration}@Chg{Version=[2],New=[],Old=[ or an @nt{abstract_subprogram_declaration}]} has no effect. @end{RunTime} @begin{Notes} A @nt{parameter_specification} with several identifiers is equivalent to a sequence of single @nt{parameter_specification}s, as explained in @RefSecNum{Objects and Named Numbers}. Abstract subprograms do not have bodies, and cannot be used in a nondispatching call (see @RefSec{Abstract Types and Subprograms}). The evaluation of @nt<default_expression>s is caused by certain calls, as described in @RefSecNum{Parameter Associations}. They are not evaluated during the elaboration of the subprogram declaration. Subprograms can be called recursively and can be called concurrently from multiple tasks. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of subprogram declarations:} @begin{Example} @key[procedure] Traverse_Tree; @key[procedure] Increment(X : @key[in] @key[out] Integer); @key[procedure] Right_Indent(Margin : @key[out] Line_Size); --@RI{ see @RefSecNum{Integer Types}} @key[procedure] Switch(From, To : @key[in] @key[out] Link); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[function] Random @key[return] Probability; --@RI{ see @RefSecNum{Floating Point Types}} @key[function] Min_Cell(X : Link) @key[return] Cell; --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[function] Next_Frame(K : Positive) @key[return] Frame; --@RI{ see @RefSecNum{Access Types}} @key[function] Dot_Product(Left, Right : Vector) @key[return] Real; --@RI{ see @RefSecNum{Array Types}} @key[function] "*"(Left, Right : Matrix) @key[return] Matrix; --@RI{ see @RefSecNum{Array Types}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of @key[in] parameters with default expressions:} @end{WideAbove} @begin{Example} @key[procedure] Print_Header(Pages : @key[in] Natural; Header : @key[in] Line := (1 .. Line'Last => ' '); --@RI{ see @RefSecNum{Array Types}} Center : @key[in] Boolean := True); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for @nt{abstract_subprogram_declaration} is added. The syntax for @nt{parameter_specification} is revised to allow for access parameters (see @RefSecNum{Access Types}) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Program units that are library units may have a @nt{parent_unit_name} to indicate the parent of a child (see @Chg{Version=[3],New=[@RefSecNum{Compilation Units - Library Units}],Old=[Section 10]}). @end{Extend83} @begin{DiffWord83} We have incorporated the rules from RM83-6.5, @lquotes@;Function Subprograms@rquotes@; here and in @RefSec{Subprogram Bodies} We have incorporated the definitions of RM83-6.6, @lquotes@;Parameter and Result Type Profile - Overloading of Subprograms@rquotes@; here. The syntax rule for @nt{defining_operator_symbol} is new. It is used for the defining occurrence of an @nt{operator_symbol}, analogously to @nt{defining_identifier}. Usage occurrences use the @nt{direct_name} or @nt{selector_name} syntactic categories. The syntax rules for @nt{defining_designator} and @nt{defining_program_unit_name} are new. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Subprograms now allow @nt{overriding_indicator}s for better error checking of overriding.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[An optional @nt{null_exclusion} can be used in a formal parameter declaration. Similarly, an optional @nt{null_exclusion} can be used in a function result.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The return type of a function can be an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[A description of the purpose of anonymous access-to-subprogram parameters and the definition of the profile of subprograms containing them was added.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Split the production for @nt{subprogram_specification} in order to make the declaration of null procedures (see @RefSecNum{Null Procedures}) easier.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[Moved the @SyntaxTitle and @RuntimeTitle for @nt{abstract_subprogram_declaration} to @RefSecNum{Abstract Types and Subprograms}, so that the syntax and semantics are together. This also keeps abstract and null subprograms similar.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Revised to allow @ntf{other_format} characters in @nt{operator_symbol}s in the same way as the underlying constructs.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Parameters can now be explicitly aliased, allowing parts of function results to designate parameters and forcing by-reference parameter passing.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0143-1]} @ChgAdded{Version=[3],Text=[The parameters of a function can now have any mode.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[An optional @nt{aspect_specification} can be used in a @nt{subprogram_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Added expression functions (see @RefSecNum{Expression Functions}) to the wording.]} @end{DiffWord2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubClause{Version=[3],Name=[Preconditions and Postconditions]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a subprogram or entry, the following language-defined aspects may be specified with an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}):]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Pre@\This aspect specifies a specific precondition for a callable entity; it shall be specified by an @nt{expression}, called a @i<specific precondition expression>.@Defn{specific precondition expression}@Defn2{Term=[precondition expression],Sec=[specific]} If not specified for an entity, the specific precondition expression for the entity is the enumeration literal True.@AspectDefn{Pre}]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In this and the following rules, we are talking about the enumeration literal True declared in package Standard (see @RefSecNum{The Package Standard}), and not some other value or identifier True. That matters as some rules depend on full conformance of these expressions, which depends on the specific declarations involved.]} @end{Honest} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Pre], Text=[@ChgAdded{Version=[3],Text=[Precondition; a condition that must hold true before a call.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0254-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Pre'Class@\This aspect specifies a class-wide precondition for an operation of a tagged type and its descendants; it shall be specified by an @nt{expression}, called a @i<class-wide precondition expression>.@Defn{class-wide precondition expression}@Defn2{Term=[precondition expression],Sec=[class-wide]} If not specified for an entity, then if no other class-wide precondition applies to the entity, the class-wide precondition expression for the entity is the enumeration literal True.@AspectDefn{Pre'Class}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Text=[If other class-wide preconditions apply to the entity and no class-wide precondition is specified, no class-wide precondition is defined for the entity; of course, the class-wide preconditions (of ancestors) that apply are still going to be checked. We need subprograms that don't have ancestors and don't specify a class-wide precondition to have a class-wide precondition of True, so that adding such a precondition to a descendant has no effect (necessary as a dispatching call through the root routine would not check any precondition).]} @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Pre'Class], Text=[@ChgAdded{Version=[3],Text=[Precondition inherited on type derivation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Post@\This aspect specifies a specific postcondition for a callable entity; it shall be specified by an @nt{expression}, called a @i<specific postcondition expression>.@Defn{specific postcondition expression}@Defn2{Term=[postcondition expression],Sec=[specific]} If not specified for an entity, the specific postcondition expression for the entity is the enumeration literal True.@AspectDefn{Post}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Post], Text=[@ChgAdded{Version=[3],Text=[Postcondition; a condition that must hold true after a call.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Post'Class@\This aspect specifies a class-wide postcondition for an operation of a tagged type and its descendants; it shall be specified by an @nt{expression}, called a @i<class-wide postcondition expression>.@Defn{class-wide postcondition expression}@Defn2{Term=[postcondition expression],Sec=[class-wide]} If not specified for an entity, the class-wide postcondition expression for the entity is the enumeration literal True.@AspectDefn{Post'Class}]} @end{Description} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Post'Class], Text=[@ChgAdded{Version=[3],Text=[Postcondition inherited on type derivation.]}]} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2]} @ChgAdded{Version=[3],Text=[The expected type for a precondition or postcondition expression is any boolean type.@PDefn2{Term=[expected type], Sec=(precondition expression)}@PDefn2{Term=[expected type], Sec=(postcondition expression)}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Within the expression for a Pre'Class or Post'Class aspect for a primitive subprogram of a tagged type @i<T>, a name that denotes a formal parameter of type @i<T> is interpreted as having type @i<T>'Class. Similarly, a name that denotes a formal access parameter of type access-to-@i<T> is interpreted as having type access-to-@i<T>'Class. @Redundant[This ensures that the expression is well-defined for a primitive subprogram of a type descended from @i<T>.]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[For an attribute_reference with attribute_designator Old, if the attribute reference has an expected type or shall resolve to a given type, the same applies to the @nt{prefix}; otherwise, the @nt{prefix} shall be resolved independently of context.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0230-1]} @ChgAdded{Version=[3],Text=[The Pre or Post aspect shall not be specified for an abstract subprogram or a null procedure. @Redundant[Only the Pre'Class and Post'Class aspects may be specified for such a subprogram.]]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Pre'Class and Post'Class can only be specified on primitive routines of tagged types, by a blanket rule found in @RefSecNum{Aspect Specifications}.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0247-1],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If a type @i<T> has an implicitly declared subprogram @i<P> inherited from a parent type @i<T1> and a homograph (see @RefSecNum{Visibility}) of @i<P> from a progenitor type @i<T2>, and]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the corresponding primitive subprogram @i<P1> of type @i<T1> is neither null nor abstract; and]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the class-wide precondition expression True does not apply to @i<P1> (implicitly or explicitly); and]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[there is a class-wide precondition expression that applies to the corresponding primitive subprogram @i<P2> of @i<T2> that does not fully conform to any class-wide precondition expression that applies to @i<P1>,]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0247-1],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[then:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the type @i<T> is abstract, the implicitly declared subprogram @i<P> is @i<abstract>.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Otherwise, the subprogram @i<P> @i{requires overriding} and shall be overridden with a nonabstract subprogram.@PDefn{requires overriding}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We use the term "requires overriding" here so that this rule is taken into account when calculating visibility in @RefSecNum{Visibility}; otherwise we would have a mess when this routine is overridden.]} @end{Discussion} @end{Itemize} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Such an inherited subprogram would necessarily violate the Liskov Substitutability Principle (LSP) if called via a dispatching call from an ancestor other than the one that provides the called body. In such a case, the class-wide precondition of the actual body is stronger than the class-wide precondition of the ancestor. If we did not enforce that precondition for the body, the body could be called when the precondition it knows about is False @em such "counterfeiting" of preconditions has to be avoided. But enforcing the precondition violates LSP. We do not want the language to be implicitly creating bodies that violate LSP; the programmer can still write an explicit body that calls the appropriate parent subprogram. In that case, the violation of LSP is explicitly in the code and obvious to code reviewers (both human and automated).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We have to say that the subprogram is abstract for an abstract type in this case, so that the next concrete type has to override it for the reasons above. Otherwise, inserting an extra level of abstract types would eliminate the requirement to override (as there is only one declared operation for the concrete type), and that would be bad for the reasons given above.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This requires the set of class-wide preconditions that apply to the interface routine to be strictly stronger than those that apply to the concrete routine. Since full conformance requires each name to denote the same declaration, it is unlikely that independently declared preconditions would conform. This rule does allow "diamond inheritance" of preconditions, and of course no preconditions at all match.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We considered adopting a rule that would allow examples where the expressions would conform after all inheritance has been applied, but this is complex and is not likely to be common in practice. Since the penalty here is just that an explicit overriding is required, the complexity is too much.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0247-1]} @ChgAdded{Version=[3],Text=[If a renaming of a subprogram or entry @i<S1> overrides an inherited subprogram @i<S2>, then the overriding is illegal unless each class-wide precondition expression that applies to @i<S1> fully conforms to some class-wide precondition expression that applies to @i<S2> and each class-wide precondition expression that applies to @i<S2> fully conforms to some class-wide precondition expression that applies to @i<S1>.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Such an overriding subprogram would violate LSP, as the precondition of @i<S1> would usually be different (and thus stronger) than the one known to a dispatching call through an ancestor routine of @i<S2>. This is always OK if the preconditions match, so we always allow that.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This only applies to primitives of tagged types; other routines cannot have class-wide preconditions.]} @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2]} @ChgAdded{Version=[3],Text=[If a Pre'Class or Post'Class aspect is specified for a primitive subprogram of a tagged type @i<T>, then the associated expression also applies to the corresponding primitive subprogram of each descendant of @i<T>.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0262-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If performing checks is required by the Pre, Pre'Class, Post, or Post'Class assertion policies (see @RefSecNum{Pragmas Assert and Assertion_Policy}) in effect at the point of a corresponding aspect specification applicable to a given subprogram or entry, then the respective precondition or postcondition expressions are considered @i<enabled>.@Defn2{Term=[enabled],Sec=[precondition expression]}@Defn2{Term=[enabled],Sec=[postcondition expression]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If a class-wide precondition or postcondition expression is enabled, it remains enabled when inherited by an overriding subprogram, even if the policy in effect is Ignore for the inheriting subprogram.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0273-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An @nt{expression} is @i{potentially unevaluated} if it occurs within:@Defn{potentially unevaluated expression}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[any part of an @nt{if_expression} other than the first @nt{condition};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a @SynI{dependent_}@nt{expression} of a @nt{case_expression};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the right operand of a short-circuit control form; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a @nt{membership_choice} other than the first of a membership operation.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[For @PrefixType{a @nt{prefix} X that denotes an object of a nonlimited type}, the following attribute is defined:]} @begin(description) @ChgAttribute{Version=[3],Kind=[AddedNormal],ChginAnnex=[T], Leading=<F>, Prefix=<X>, AttrName=<Old>, ARef=[AI05-0145-2], ARef=[AI05-0262-1], ARef=[AI05-0273-1], Text=[@Chg{Version=[3],New=[For each X'Old in a postcondition expression that is enabled, a constant is implicitly declared at the beginning of the subprogram or entry. The constant is of the type of X and is initialized to the result of evaluating X (as an expression) at the point of the constant declaration. The value of X'Old in the postcondition expression is the value of this constant; the type of X'Old is the type of X. These implicit constant declarations occur in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]}],Old=[]}]}@Comment{End of Annex text here.} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2], ARef=[AI05-0262-1], ARef=[AI05-0273-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[Reference to this attribute is only allowed within a postcondition expression. The @nt{prefix} of an Old @nt{attribute_reference} shall not contain a Result @nt{attribute_reference}, nor an Old @nt{attribute_reference}, nor a use of an entity declared within the postcondition expression but not within @nt{prefix} itself (for example, the loop parameter of an enclosing @nt{quantified_expression}). The @nt{prefix} of an Old @nt{attribute_reference} that is potentially unevaluated shall statically denote an entity.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=<The @nt{prefix} X can be any nonlimited object that obeys the syntax for prefix other than the few exceptions given above (discussed below). Useful cases are: the @nt{name} of a formal parameter of mode [@key[in]] @key[out], the @nt{name} of a global variable updated by the subprogram, a function call passing those as parameters, a subcomponent of those things, etc.>} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A qualified expression can be used to make an arbitrary expression into a valid prefix, so T'(X + Y)'Old is legal, even though (X + Y)'Old is not. The value being saved here is the sum of X and Y (a function result is an object). Of course, in this case "+"(X, Y)'Old is also legal, but the qualified expression is arguably more readable.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that F(X)'Old and F(X'Old) are not necessarily equal. The former calls F(X) and saves that value for later use during the postcondition. The latter saves the value of X, and during the postcondition, passes that saved value to F. In most cases, the former is what one wants (but it is not always legal, see below).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If X has controlled parts, adjustment and finalization are implied by the implicit constant declaration.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If postconditions are disabled, we want the compiler to avoid any overhead associated with saving 'Old values.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=['Old makes no sense for limited types, because its implementation involves copying. It might make semantic sense to allow build-in-place, but it's not worth the trouble.]} @end{Discussion} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0273-1]} @ChgAdded{Version=[3],Text=[Since the @nt{prefix} is evaluated unconditionally when the subprogram is called, we cannot allow it to include values that do not exist at that time (like 'Result and loop parameters of @nt{quantified_expression}s). We also do not allow it to include 'Old references, as those would be redundant (the entire @nt{prefix} is evaluated when the subprogram is called), and allowing them would require some sort of order to the implicit constant declarations (because in A(I'Old)'Old, we surely would want the value of I'Old evaluated before the A(I'Old) is evaluated).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0273-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[In addition, we only allow simple names as the @nt{prefix} of the Old attribute if the @nt{attribute_reference} might not be evaluated when the postcondition expression is evaluated. This is necessary because the Old @nt{prefix}es have to be unconditionally evaluated when the subprogram is called; the compiler cannot in general know whether they will be needed in the postcondition expression. To see the problem, consider:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Table : @key[array] (1..10) @key[of] Integer := ... @key[procedure] Bar (I : @key[in out] Natural) @key[with] Post => I > 0 @key[and then] Table(I)'Old = 1; -- @Examcom{Illegal}]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[In this example, the compiler cannot know the value of I when the subprogram returns (since the subprogram execution can change it), and thus it does not know whether Table(I)'Old will be needed then. Thus it has to always create an implicit constant and evaluate Table(I) when Bar is called (because not having the value when it is needed is not acceptable). But if I = 0 when the subprogram is called, that evaluation will raise Constraint_Error, and that will happen even if I is unchanged by the subprogram and the value of Table(I)'Old is not ultimately needed. It's easy to see how a similar problem could occur for a dereference of an access type. This would be mystifying (since the point of the short circuit is to eliminate this possibility, but it cannot do so). Therefore, we require the @nt{prefix} of any Old attribute in such a context to statically denote an object, which eliminates anything that could change at during execution.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is easy to work around most errors that occur because of this rule. Just move the 'Old to the outer object, before any indexing, dereferences, or components. (That does not work for function calls, however, nor does it work for array indexing if the index can change during the execution of the subprogram.)]} @end{Reason} @end(description) @EndPrefixType{} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[For @PrefixType{a @nt{prefix} F that denotes a function declaration}, the following attribute is defined:]} @begin(description) @ChgAttribute{Version=[3],Kind=[AddedNormal],ChginAnnex=[T], Leading=<F>, Prefix=<F>, AttrName=<Result>, ARef=[AI05-0145-2], ARef=[AI05-0262-1], Text=[@Chg{Version=[3],New=[Within a postcondition expression for function F, denotes the result object of the function. The type of this attribute is that of the function result except within a Post'Class postcondition expression for a function with a controlling result or with a controlling access result. For a controlling result, the type of the attribute is @i<T>'Class, where @i<T> is the function result type. For a controlling access result, the type of the attribute is an anonymous access type whose designated type is @i<T>'Class, where @i<T> is the designated type of the function result type.],Old=[]}]}@Comment{End of Annex text here.} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[Use of this attribute is allowed only within a postcondition expression for F.]} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Upon a call of the subprogram or entry, after evaluating any actual parameters, precondition checks are performed as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The specific precondition check begins with the evaluation of the specific precondition expression that applies to the subprogram or entry, if it is enabled; if the expression evaluates to False, Assertions.Assertion_Error is raised; if the expression is not enabled, the check succeeds.@Defn2{Term=(Assertion_Error), Sec=(raised by failure of run-time check)}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}@Defn2{Term=[precondition check],Sec=[specific]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The class-wide precondition check begins with the evaluation of any enabled class-wide precondition expressions that apply to the subprogram or entry. If and only if all the class-wide precondition expressions evaluate to False, Assertions.Assertion_Error is raised.@Defn2{Term=(Assertion_Error), Sec=(raised by failure of run-time check)}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}@Defn2{Term=[precondition check],Sec=[class-wide]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The class-wide precondition expressions of the entity itself as well as those of any parent or progenitor operations are evaluated, as these expressions apply to the corresponding operations of all descendants.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Class-wide precondition checks are performed for all appropriate calls, but only enabled precondition expressions are evaluated. Thus, the check would be trivial if no precondition expressions are enabled.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0254-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The precondition checks are performed in an arbitrary order, and if any of the class-wide precondition expressions evaluate to True, it is not specified whether the other class-wide precondition expressions are evaluated. The precondition checks and any check for elaboration of the subprogram body are performed in an arbitrary order. It is not specified whether in a call on a protected operation, the checks are performed before or after starting the protected action. For an entry call, the checks are performed prior to checking whether the entry is open.@PDefn2{Term=(arbitrary order), Sec=(allowed)}@PDefn{unspecified}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We need to explicitly allow short-circuiting of the evaluation of the class-wide precondition check if any expression fails, as it consists of multiple expressions; we don't need a similar permission for the specific precondition check as it consists only of a single expression. Nothing is evaluated for the call after a check fails, as the failed check propagates an exception.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0254-1],ARef=[AI05-0262-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[Upon successful return from a call of the subprogram or entry, prior to copying back any by-copy @key[in out] or @key[out] parameters, the postcondition check is performed. This consists of the evaluation of any enabled specific and class-wide postcondition expressions that apply to the subprogram or entry. If any of the postcondition expressions evaluate to False, then Assertions.Assertion_Error is raised. The postcondition expressions are evaluated in an arbitrary order, and if any postcondition expression evaluates to False, it is not specified whether any other postcondition expressions are evaluated. The postcondition check, and any constraint or predicate checks associated with @key[in out] or @key[out] parameters are performed in an arbitrary order.@Defn{postcondition check}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}@Defn2{Term=(Assertion_Error), Sec=(raised by failure of run-time check)}@PDefn2{Term=(arbitrary order), Sec=(allowed)}@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The class-wide postcondition expressions of the entity itself as well as those of any parent or progenitor operations are evaluated, as these apply to all descendants; in contrast, only the specific postcondition of the entity applies. Postconditions can always be evaluated inside the invoked body.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[If a precondition or postcondition check fails, the exception is raised at the point of the call@Redundant[; the exception cannot be handled inside the called subprogram or entry]. Similarly, any exception raised by the evaluation of a precondition or postcondition expression is raised at the point of call.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0254-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[For any subprogram or entry call (including dispatching calls), the checks that are performed to verify specific precondition expressions and specific and class-wide postcondition expressions are determined by those for the subprogram or entry actually invoked. Note that the class-wide postcondition expressions verified by the postcondition check that is part of a call on a primitive subprogram of type @i<T> includes all class-wide postcondition expressions originating in any progenitor of @i<T>@Redundant[, even if the primitive subprogram called is inherited from a type @i<T1> and some of the postcondition expressions do not apply to the corresponding primitive subprogram of @i<T1>].]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This applies to access-to-subprogram calls, dispatching calls, and to statically bound calls. We need this rule to cover statically bound calls as well, as specific pre- and postconditions are not inherited, but the subprogram might be.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For concrete subprograms, we require the original specific postcondition to be evaluated as well as the inherited class-wide postconditions in order that the semantics of an explicitly defined wrapper that does nothing but call the original subprogram is the same as that of an inherited subprogram.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that this rule does not apply to class-wide preconditions; they have their own rules mentioned below.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Text=[The class-wide precondition check for a call to a subprogram or entry consists solely of checking the class-wide precondition expressions that apply to the denoted callable entity (not necessarily the one that is invoked).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For a dispatching call, we are talking about the Pre'Class(es) that apply to the subprogram that the dispatching call is resolving to, not the Pre'Class(es) for the subprogram that is ultimately dispatched to. The class-wide precondition of the resolved call is necessarily the same or stronger than that of the invoked call. For a statically bound call, these are the same; for an access-to-subprogram, (which has no class-wide preconditions of its own), we check the class-wide preconditions of the invoked routine.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These rules imply that logically, class-wide preconditions of routines must be checked at the point of call (other than for access-to-subprogram calls, which must be checked in the body, probably using a wrapper). Specific preconditions that might be called with a dispatching call or via an access-to-subprogram value must be checked inside of the subprogram body. In contrast, the postcondition checks always need to be checked inside the body of the routine. Of course, an implementation can evaluate all of these at the point of call for statically bound calls if the implementation uses wrappers for dispatching bodies and for 'Access values.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There is no requirement for an implementation to generate special code for routines that are imported from outside of the Ada program. That's because there is a requirement on the programmer that the use of interfacing aspects do not violate Ada semantics (see B.1). That includes making pre- and postcondition checks. For instance, if the implementation expects routines to make their own postcondition checks in the body before returning, C code can be assumed to do this (even though that is highly unlikely). That's even though the formal definition of those checks is that they are evaluated at the call site. Note that pre- and postconditions can be very useful for verification tools (even if they aren't checked), because they tell the tool about the expectations on the foreign code that it most likely cannot analyze.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0247-1],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Text=[For a call via an access-to-subprogram value, all precondition and postcondition checks performed are determined by the subprogram or entry denoted by the prefix of the Access attribute reference that produced the value.]} @end{Runtime} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A precondition is checked just before the call. If another task can change any value that the precondition expression depends on, the precondition need not hold within the subprogram or entry body.]} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0145-2],ARef=[AI05-0230-1],ARef=[AI05-0247-1],ARef=[AI05-0254-1],ARef=[AI05-0262-1],ARef=[AI05-0273-1],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Pre and Post aspects are new.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Formal Parameter Modes} @begin{Intro} @Redundant[A @nt{parameter_specification} declares a formal parameter of mode @key[in], @key[in out], or @key[out].] @end{Intro} @begin{StaticSem} @Defn{pass by copy} @Defn{by copy parameter passing} @Defn{copy parameter passing} @Defn{pass by reference} @Defn{by reference parameter passing} @Defn{reference parameter passing} A parameter is passed either @i{by copy} or @i{by reference}. @Redundant[When a parameter is passed by copy, the formal parameter denotes a separate object from the actual parameter, and any information transfer between the two occurs only before and after executing the subprogram. When a parameter is passed by reference, the formal parameter denotes (a view of) the object denoted by the actual parameter; reads and updates of the formal parameter directly reference the actual parameter object.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0142-4],ARef=[AI05-0262-1]} @Defn{by-copy type} A type is a @i(by-copy type) if it is an elementary type, or if it is a descendant of a private type whose full type is a by-copy type. A parameter of a by-copy type is passed by copy@Chg{Version=[3],New=[, unless the formal parameter is explicitly aliased],Old=[]}. @leading@keepnext@Defn{by-reference type} A type is a @i(by-reference type) if it is a descendant of one of the following: @begin(itemize) a tagged type; a task or protected type; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0096-1]} @Chg{Version=[3],New=[an explicitly limited record type],Old=[a nonprivate type with the reserved word @key[limited] in its declaration]}; @begin{Ramification} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0096-1]} @ChgDeleted{Version=[3],Text=[A limited private type is by-reference only if it falls under one of the other categories.]} @end{Ramification} a composite type with a subcomponent of a by-reference type; a private type whose full type is a by-reference type. @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0142-4],ARef=[AI05-0188-1]} A parameter of a by-reference type is passed by reference@Chg{Version=[3],New=[, as is an explicitly aliased parameter of any type],Old=[]}. @Defn2{Term=[associated object], Sec=(of a value of a by-reference type)} Each value of a by-reference type has an associated object. For a parenthesized expression, @nt{qualified_expression}, or @nt{type_conversion}, this object is the one associated with the operand.@Chg{Version=[3],New=[ For a @nt{conditional_expression}, this object is the one associated with the evaluated @Syni{dependent_}@nt{expression}.],Old=[]} @begin{Ramification} By-reference parameter passing makes sense only if there is an object to reference; hence, we define such an object for each case. Since tagged types are by-reference types, this implies that every value of a tagged type has an associated object. This simplifies things, because we can define the tag to be a property of the object, and not of the value of the object, which makes it clearer that object tags never change. We considered simplifying things even more by making every value (and therefore every expression) have an associated object. After all, there is little semantic difference between a constant object and a value. However, this would cause problems for untagged types. In particular, we would have to do a constraint check on every read of a type conversion (or a renaming thereof) in certain cases. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} We do not want this definition to depend on the view of the type; privateness is essentially ignored for this definition. Otherwise, things would be confusing (does the rule apply at the call site, at the site of the declaration of the subprogram, at the site of the @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]}?), and requiring different calls to use different mechanisms would be an implementation burden. @RefSec{Shared Variable Control} says that a composite type with an atomic or volatile subcomponent is a by-reference type, among other things. @Defn2{Term=[associated object], Sec=(of a value of a limited type)} Every value of a limited by-reference type is the value of one and only one limited object. The @i{associated object} of a value of a limited by-reference type is the object whose value it represents. @Defn2{Term=[same value], Sec=(for a limited type)} Two values of a limited by-reference type are the @i{same} if and only if they represent the value of the same object. We say @lquotes@;by-reference@rquotes@; above because these statements are not always true for limited private types whose underlying type is nonlimited (unfortunately). @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0240-1]} @PDefn{unspecified} For @Chg{Version=[3],New=[other ],Old=[]}parameters@Chg{Version=[3],New=[],Old=[ of other types]}, it is unspecified whether the parameter is passed by copy or by reference. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} There is no need to incorporate the discussion of AI83-00178, which requires pass-by-copy for certain kinds of actual parameters, while allowing pass-by-reference for others. This is because we explicitly indicate that a function creates an anonymous constant object for its result@Chg{Version=[3],New=[],Old=[, unless the type is a return-by-reference type]} (see @RefSecNum{Return Statements}). We also provide a special dispensation for instances of Unchecked_Conversion to return by reference@Chg{Version=[3],New=[],Old=[, even if the result type is not a return-by-reference type]} (see @RefSecNum{Unchecked Type Conversions}). @end{Discussion} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0240-1]} @Defn{distinct access paths} @Defn2{Term=[access paths],Sec=(distinct)} @IndexSee{Term=[aliasing],See=(distinct access paths)} @PDefn2{Term=(bounded error),Sec=(cause)} If one @nt<name> denotes a part of a formal parameter, and a second @nt<name> denotes a part of a distinct formal parameter or an object that is not part of a formal parameter, then the two @nt<name>s are considered @i(distinct access paths). If an object is of a type for which the parameter passing mechanism is not specified@Chg{Version=[3],New=[ and is not an explicitly aliased parameter],Old=[]}, then it is a bounded error to assign to the object via one access path, and then read the value of the object via a distinct access path, unless the first access path denotes a part of a formal parameter that no longer exists at the point of the second access @Redundant[(due to leaving the corresponding callable construct).] @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible consequences are that Program_Error is raised, or the newly assigned value is read, or some old value of the object is read. @begin{Discussion} For example, if we call @lquotes@;P(X => Global_Variable, Y => Global_Variable)@rquotes@;, then within P, the names @lquotes@;X@rquotes@;, @lquotes@;Y@rquotes@;, and @lquotes@;Global_Variable@rquotes@; are all distinct access paths. If Global_Variable's type is neither pass-by-copy nor pass-by-reference, then it is a bounded error to assign to Global_Variable and then read X or Y, since the language does not specify whether the old or the new value would be read. On the other hand, if Global_Variable's type is pass-by-copy, then the old value would always be read, and there is no error. Similarly, if Global_Variable's type is defined by the language to be pass-by-reference, then the new value would always be read, and again there is no error. @end{Discussion} @begin{Reason} We are saying @i(assign) here, not @i(update), because updating any subcomponent is considered to update the enclosing object. The @lquotes@;still exists@rquotes@; part is so that a read after the subprogram returns is OK. If the parameter is of a by-copy type, then there is no issue here @em the formal is not a view of the actual. If the parameter is of a by-reference type, then the programmer may depend on updates through one access path being visible through some other access path, just as if the parameter were of an access type. @end{Reason} @begin{ImplNote} The implementation can keep a copy in a register of a parameter whose parameter-passing mechanism is not specified. If a different access path is used to update the object (creating a bounded error situation), then the implementation can still use the value of the register, even though the in-memory version of the object has been changed. However, to keep the error properly bounded, if the implementation chooses to read the in-memory version, it has to be consistent -- it cannot then assume that something it has proven about the register is true of the memory location. For example, suppose the formal parameter is L, the value of L(6) is now in a register, and L(6) is used in an @nt{indexed_component} as in @lquotes@;A(L(6)) := 99;@rquotes@;, where A has bounds 1..3. If the implementation can prove that the value for L(6) in the register is in the range 1..3, then it need not perform the constraint check if it uses the register value. However, if the memory value of L(6) has been changed to 4, and the implementation uses that memory value, then it had better not alter memory outside of A. Note that the rule allows the implementation to pass a parameter by reference and then keep just part of it in a register, or, equivalently, to pass part of the parameter by reference and another part by copy. @end{ImplNote} @begin{Reason} @leading@;We do not want to go so far as to say that the mere presence of aliasing is wrong. We wish to be able to write the following sorts of things in standard Ada: @begin{Example} @key[procedure] Move ( Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@RI{ Copies elements from Source to Target (safely if they overlap)} @end{Example} This is from the standard string handling package. It would be embarrassing if this couldn't be written in Ada! The @lquotes@;then@rquotes@; before @lquotes@;read@rquotes@; in the rule implies that the implementation can move a read to an earlier place in the code, but not to a later place after a potentially aliased assignment. Thus, if the subprogram reads one of its parameters into a local variable, and then updates another potentially aliased one, the local copy is safe @em it is known to have the old value. For example, the above-mentioned Move subprogram can be implemented by copying Source into a local variable before assigning into Target. @leading@;For an @nt{assignment_statement} assigning one array parameter to another, the implementation has to check which direction to copy at run time, in general, in case the actual parameters are overlapping slices. For example: @begin{Example} @key[procedure] Copy(X : @key[in out] String; Y: String) @key[is] @key[begin] X := Y; @key[end] Copy; @end{Example} It would be wrong for the compiler to assume that X and Y do not overlap (unless, of course, it can prove otherwise). @end{Reason} @end{Bounded} @begin{Notes} A formal parameter of mode @key(in) is a constant view (see @RefSecNum{Objects and Named Numbers}); it cannot be updated within the @nt{subprogram_body}. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The value of an @key(out) parameter may be read. An @key(out) parameter is treated like a declared variable without an explicit initial expression. @end{Extend83} @begin{DiffWord83} Discussion of copy-in for parts of out parameters is now covered in @RefSec{Parameter Associations}. The concept of a by-reference type is new to Ada 95. We now cover in a general way in @RefSecNum{Operations of Discriminated Types} the rule regarding erroneous execution when a discriminant is changed and one of the parameters depends on the discriminant. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0096-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected so that limited derived types are by-reference only if their parent is.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Defined that explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}) are always passed by reference.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Subprogram Bodies} @begin{Intro} @Redundant[A @nt{subprogram_body} specifies the execution of a subprogram.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<subprogram_body>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}]>,Old=<>} @Syn2{subprogram_specification}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@Syn2{designator}];"} @begin{SyntaxText} If a @nt{designator} appears at the end of a @nt{subprogram_body}, it shall repeat the @nt{defining_designator} of the @nt{subprogram_specification}. @end{SyntaxText} @end{Syntax} @begin{Legality} @Redundant[In contrast to other bodies,] a @nt{subprogram_body} need not be the completion of a previous declaration@Redundant[, in which case the body declares the subprogram]. If the body is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of a @nt{subprogram_body} that completes a declaration shall conform fully to that of the declaration. @Defn2{Term=[full conformance],Sec=(required)} @end{Legality} @begin{StaticSem} A @nt{subprogram_body} is considered a declaration. It can either complete a previous declaration, or itself be the initial declaration of the subprogram. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(nongeneric subprogram_body)} The elaboration of a nongeneric @nt{subprogram_body} has no other effect than to establish that the subprogram can from then on be called without failing the Elaboration_Check. @begin{Ramification} See @RefSecNum{Generic Bodies} for elaboration of a generic body. Note that protected @ntf{subprogram_bodies} never get elaborated; the elaboration of the containing @nt{protected_body} allows them to be called without failing the Elaboration_Check. @end{Ramification} @PDefn2{Term=[execution], Sec=(subprogram_body)} @Redundant[The execution of a @nt{subprogram_body} is invoked by a subprogram call.] For this execution the @nt{declarative_part} is elaborated, and the @nt{handled_sequence_of_statements} is then executed. @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of procedure body:} @begin{Example} @key[procedure] Push(E : @key[in] Element_Type; S : @key[in] @key[out] Stack) @key[is] @key[begin] @key[if] S.Index = S.Size @key[then] @key[raise] Stack_Overflow; @key[else] S.Index := S.Index + 1; S.Space(S.Index) := E; @key[end] @key[if]; @key[end] Push; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a function body:} @end{WideAbove} @begin{Example} @key[function] Dot_Product(Left, Right : Vector) @key[return] Real @key[is] Sum : Real := 0.0; @key[begin] Check(Left'First = Right'First @key[and] Left'Last = Right'Last); @key[for] J @key[in] Left'Range @key[loop] Sum := Sum + Left(J)*Right(J); @key[end] @key[loop]; @key[return] Sum; @key[end] Dot_Product; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} A @nt{renaming_declaration} may be used instead of a @nt{subprogram_body}. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{subprogram_body} now uses the syntactic category @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{subprogram_body} is now required; that doesn't make any real difference, because a @nt{declarative_part} can be empty. We have incorporated some rules from RM83-6.5 here. RM83 forgot to restrict the definition of elaboration of a @nt{subprogram_body} to nongenerics. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@nt{Overriding_indicator} is added to @nt{subprogram_body}.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}An optional @nt{aspect_specification} can be used in a @nt{subprogram_body}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Conformance Rules} @begin{Intro} @Defn{conformance} @SeeAlso{Primary=[conformance],Other=(type conformance)} @SeeAlso{Primary=[conformance],Other=(mode conformance)} @SeeAlso{Primary=[conformance],Other=(subtype conformance)} @SeeAlso{Primary=[conformance],Other=(full conformance)} @Redundant[When subprogram profiles are given in more than one place, they are required to conform in one of four ways: type conformance, mode conformance, subtype conformance, or full conformance.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0011],ARef=[AI95-00117-01]} @leading@Defn{convention} @Defn{calling convention} @Redundant[As explained in @RefSec{Interfacing Aspects}, a @i{convention} can be specified for an entity.] @Chg{New=[Unless this International Standard states otherwise, the default convention of an entity is Ada.],Old=[]} @Redundant[For a callable entity or access-to-subprogram type, the convention is called the @i{calling convention}.] The following conventions are defined by the language: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{Ada calling convention} @Defn2{Term=[calling convention], Sec=(Ada)} The default calling convention for any subprogram not listed below is @i{Ada}. @Redundant[@Chg{Version=[3],New=[The],Old=[A @nt{pragma}]} Convention@Chg{Version=[3],New=[ aspect],Old=[, Import, or Export]} may be @Chg{Version=[3],New=[specified],Old=[used]} to override the default calling convention (see @RefSecNum{Interfacing Aspects})]. @begin{Ramification} See also the rule about renamings-as-body in @RefSecNum{Subprogram Renaming Declarations}. @end{Ramification} @leading@Defn{Intrinsic calling convention} @Defn2{Term=[calling convention], Sec=(Intrinsic)} The @i{Intrinsic} calling convention represents subprograms that are @lquotes@;built in@rquotes@; to the compiler. The default calling convention is Intrinsic for the following: @begin{InnerItemize} an enumeration literal; a "/=" operator declared implicitly due to the declaration of "=" (see @RefSecNum{Overloading of Operators}); any other implicitly declared subprogram unless it is a dispatching operation of a tagged type; an inherited subprogram of a generic formal tagged type with unknown discriminants; @begin{Reason} @Comment{8652/0011 suggests that the reason for this rule be documented in the AARM.} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Consider:],Old=[]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] P @key[is] @key[type] Root @key[is tagged null record]; @key[procedure] Proc(X: Root); @key[end] P;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[generic] @key[type] Formal(<>) @key[is new] Root @key[with private]; @key[package] G @key[is] ... @key[end] G;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@key[package body] G @key[is] ... X: Formal := ...; ... Proc(X); -- @RI[This is a dispatching call in Instance, because] -- @RI[the actual type for Formal is class-wide.] ... -- @RI[Proc'Access would be illegal here, because it is of] -- @RI[convention Intrinsic, by the above rule.] @key[end] G;]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@key[type] Actual @key[is new] Root @key[with] ...; @key[procedure] Proc(X: Actual); @key[package] Instance @key[is new] G(Formal => Actual'Class); -- @RI[It is legal to pass in a class-wide actual, because Formal] -- @RI[has unknown discriminants.]]} @end{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Within Instance, all calls to Proc will be dispatching calls, so Proc doesn't really exist in machine code, so we wish to avoid taking 'Access of it. This rule applies to those cases where the actual type might be class-wide, and makes these Intrinsic, thus forbidding 'Access.],Old=[]} @end{Reason} an attribute that is a subprogram; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00252-01]} a subprogram declared immediately within a @nt{protected_body}@Chg{Version=[2],New=[;],Old=[.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00252-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[any prefixed view of a subprogram (see @RefSecNum{Selected Components}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The profile of a prefixed view is different than the @lquotes@;real@rquotes profile of the subprogram (it doesn't have the first parameter), so we don't want to be able to take 'Access of it, as that would require generating a wrapper of some sort.]} @end{Reason} @end{InnerItemize} @NoPrefix@Redundant[The Access attribute is not allowed for Intrinsic subprograms.] @begin{Ramification} The Intrinsic calling convention really represents any number of calling conventions at the machine code level; the compiler might have a different instruction sequence for each intrinsic. That's why the Access attribute is disallowed. We do not wish to require the implementation to generate an out of line body for an intrinsic. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Whenever we wish to disallow the Access attribute in order to ease implementation, we make the subprogram Intrinsic. Several language-defined subprograms have @lquotes@;@Chg{Version=[3],New=[@key[with]],Old=[@key[pragma]]} Convention@Chg{Version=[3],New=[ => ],Old=[(]}Intrinsic@Chg{Version=[3],New=[],Old=[, ...)]};@rquotes@;. An implementation might actually implement this as @lquotes@;@Chg{Version=[3],New=[@key[with]],Old=[@key[pragma]]} Import@Chg{Version=[3],New=[ => True, Convention => ],Old=[(]}Intrinsic@Chg{Version=[3],New=[],Old=[, ...)]};@rquotes@;, if there is really no body, and the implementation of the subprogram is built into the code generator. Subprograms declared in @ntf{protected_bodies} will generally have a special calling convention so as to pass along the identification of the current instance of the protected type. The convention is not @i(protected) since such local subprograms need not contain any @lquotes@;locking@rquotes@; logic since they are not callable via @lquotes@;external@rquotes@; calls; this rule prevents an access value designating such a subprogram from being passed outside the protected unit. The @lquotes@;implicitly declared subprogram@rquotes@; above refers to predefined operators (other than the "=" of a tagged type) and the inherited subprograms of untagged types. @end{Ramification} @Defn{protected calling convention} @Defn2{Term=[calling convention], Sec=(protected)} The default calling convention is @i{protected} for a protected subprogram, and for an access-to-subprogram type with the reserved word @key(protected) in its definition. @Defn{entry calling convention} @Defn2{Term=[calling convention], Sec=(entry)} The default calling convention is @i{entry} for an entry. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The calling convention for an anonymous access-to-subprogram parameter or anonymous access-to-subprogram result is @i<protected> if the reserved word @key{protected} appears in its definition@Chg{Version=[3],New=[;],Old=[ and]} otherwise@Chg{Version=[3],New=[, it],Old=[]} is the convention of the subprogram that contains the parameter.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The calling convention for other anonymous access-to-subprogram types is Ada.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0011],ARef=[AI95-00117-01]} @Chg{Version=[1],New=[@Redundant[If not specified above as Intrinsic, the calling convention for any inherited or overriding dispatching operation of a tagged type is that of the corresponding subprogram of the parent type.] The default calling convention for a new dispatching operation of a tagged type is the convention of the type.], Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The first rule is officially stated in @RefSecNum(Dispatching Operations of Tagged Types). The second is intended to make interfacing to foreign OOP languages easier, by making the default be that the type and operations all have the same convention.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Of these four conventions, only Ada and Intrinsic are allowed as a @SynI{convention_}@nt{identifier} in @Chg{Version=[3],New=[the specification of a],Old=[a @nt{pragma}]} Convention@Chg{Version=[3],New=[ aspect],Old=[, Import, or Export]}. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The names of the @i{protected} and @i{entry} calling conventions cannot be used in the @Chg{Version=[3],New=[specification of Convention], Old=[interfacing pragmas]}. Note that @key[protected] and @key[entry] are reserved words. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00409-01]} @Defn{type conformance} @Defn2{Term=[profile],Sec=(type conformant)} Two profiles are @i{type conformant} if they have the same number of parameters, and both have a result if either does, and corresponding parameter and result types are the same, or, for access parameters@Chg{Version=[2],New=[ or access results],Old=[]}, corresponding designated types are the same@Chg{Version=[2],New=[, or corresponding designated profiles are type conformant],Old=[]}. @IndexSee{Term=[type profile],See=(profile, type conformant)} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00409-01]} For @Chg{Version=[2],New=[anonymous access-to-object],Old=[access]} parameters, the designated types have to be the same for type conformance, not the access types, since in general each access parameter has its own anonymous access type, created when the subprogram is called. Of course, corresponding parameters have to be either both access parameters or both not access parameters. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[Similarly, for anonymous access-to-subprogram parameters, the designated profiles of the types, not the types themselves, have to be conformant.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00409-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{Dummy for conditional leading.} @Defn{mode conformance} @Defn2{Term=[profile],Sec=(mode conformant)} Two profiles are @i{mode conformant} if@Chg{Version=[3],New=[:],Old=[ they are type-conformant, and corresponding parameters have identical modes, and, for access parameters@Chg{Version=[2],New=[ or access result types],Old=[]}, the designated subtypes statically match@Chg{Version=[2],New=[, or the designated profiles are subtype conformant.],Old=[]} @PDefn2{Term=[statically matching],Sec=(required)}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[they are type conformant; and]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[corresponding parameters have identical modes and both or neither are explicitly aliased parameters; and]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0207-1]} @ChgAdded{Version=[3],Text=[for corresponding access parameters and any access result type, the designated subtypes statically match and either both or neither are access-to-constant, or the designated profiles are subtype conformant. @PDefn2{Term=[statically matching],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} @Defn{subtype conformance} @Defn2{Term=[profile],Sec=(subtype conformant)} Two profiles are @i{subtype conformant} if they are @Chg{Version=[3],New=[mode conformant],Old=[mode-conformant]}, corresponding subtypes of the profile statically match, and the associated calling conventions are the same. The profile of a generic formal subprogram is not @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]} with any other profile. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Ramification} @PDefn{generic contract issue} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0134-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{Dummy for conditional leading.} @Defn2{Term=[full conformance], Sec=(for profiles)} @Defn2{Term=[profile],Sec=(fully conformant)} Two profiles are @i{fully conformant} if they are @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]}, @Chg{Version=[3],New=[if they have access-to-subprogram results whose designated profiles are fully conformant, ],Old=[]}and @Chg{Version=[3],New=[for ],Old=[]} corresponding parameters@Chg{Version=[3],New=[:], Old=[ have the same names and have @nt<default_expression>s that are fully conformant with one another.]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[they have the same names; and]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0046-1]} @ChgAdded{Version=[3],Text=[both or neither have @nt{null_exclusion}s; and]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[neither have @nt{default_expression}s, or they both have @nt{default_expression}s that are fully conformant with one another; and]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0134-1]} @ChgAdded{Version=[3],Text=[for access-to-subprogram parameters, the designated profiles are fully conformant.]} @end{Itemize} @begin{Ramification} Full conformance requires subtype conformance, which requires the same calling conventions. However, the calling convention of the declaration and body of a subprogram or entry are always the same by definition. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0046-1]} @ChgAdded{Version=[3],Text=[The part about @nt{null_exclusion}s is necessary to prevent controlling parameters from having different exclusions, as such a parameter is defined to exclude null whether or not an exclusion is given.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0134-1]} @ChgAdded{Version=[3],Text=[The parts about access-to-subprogram parameters and results is necessary to prevent such types from having different @nt{default_expression}s in the specification and body of a subprogram. If that was allowed, it would be undefined which @nt{default_expression} was used in a call of an access-to-subprogram parameter.]} @end{Reason} @leading@Defn2{Term=[full conformance], Sec=(for expressions)} Two expressions are @i(fully conformant) if, @Redundant[after replacing each use of an operator with the equivalent @nt{function_call}:] @begin{Itemize} each constituent construct of one corresponds to an instance of the same syntactic category in the other, except that an expanded name may correspond to a @nt{direct_name} (or @nt{character_literal}) or to a different expanded name in the other; and each @nt{direct_name}, @nt{character_literal}, and @nt{selector_name} that is not part of the @nt{prefix} of an expanded name in one denotes the same declaration as the corresponding @nt{direct_name}, @nt{character_literal}, or @nt{selector_name} in the other; and @begin{Ramification} Note that it doesn't say @lquotes@;respectively@rquotes@; because a @nt{direct_name} can correspond to a @nt{selector_name}, and vice-versa, by the previous bullet. This rule allows the @nt{prefix} of an expanded name to be removed, or replaced with a different @nt{prefix} that denotes a renaming of the same entity. However, it does not allow a @nt{direct_name} or @nt{selector_name} to be replaced with one denoting a distinct renaming (except for @nt{direct_name}s and @nt{selector_name}s in @nt{prefix}es of expanded names). Note that calls using operator notation are equivalent to calls using prefix notation. @leading@keepnext@;Given the following declarations: @begin{Example} @key[package] A @key[is] @key[function] F(X : Integer := 1) @key[return] Boolean; @key[end] A; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0005-1]} @key[with] A; @key[package] B @key[is] @key[package] A_View @key[renames] A; @key[function] F_View(X : Integer := 9999) @key[return] Boolean @key[renames] @Chg{Version=[3],New=[A.F],Old=[F]}; @key[end] B; @key[with] A, B; @key[use] A, B; @key[procedure] Main @key[is] ... @end{Example} Within Main, the expressions @lquotes@;F@rquotes@;, @lquotes@;A.F@rquotes@;, @lquotes@;B.A_View.F@rquotes@;, and @lquotes@;A_View.F@rquotes@; are all fully conformant with one another. However, @lquotes@;F@rquotes@; and @lquotes@;F_View@rquotes@; are not fully conformant. If they were, it would be bad news, since the two denoted views have different @nt{default_expression}s. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0018],ARef=[AI95-00175-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0092-1]} @ChgAdded{Version=[1],Text=[each @nt{attribute_designator} in one @Chg{Version=[3],New=[is],Old=[must be]} the same as the corresponding @nt{attribute_designator} in the other; and]} each @nt{primary} that is a literal in one has the same value as the corresponding literal in the other. @begin{Ramification} The literals may be written differently. @end{Ramification} @end{Itemize} @begin{Ramification} Note that the above definition makes full conformance a transitive relation. @end{Ramification} @Defn2{Term=[full conformance], Sec=(for @nt{known_discriminant_part}s)} Two @nt{known_discriminant_part}s are @i(fully conformant) if they have the same number of discriminants, and discriminants in the same positions have the same names, statically matching subtypes, and @nt{default_expression}s that are fully conformant with one another. @PDefn2{Term=[statically matching],Sec=(required)} @Defn2{Term=[full conformance], Sec=(for @nt{discrete_subtype_definition}s)} Two @nt<discrete_subtype_definition>s are @i(fully conformant) if they are both @nt<subtype_indication>s or are both @nt<range>s, the @nt<subtype_mark>s (if any) denote the same subtype, and the corresponding @nt<simple_expression>s of the @nt<range>s (if any) fully conform. @begin{Ramification} In the @nt{subtype_indication} case, any ranges have to @i{be} corresponding; that is, two @nt{subtype_indication}s cannot conform unless both or neither has a @nt{range}. @end{Ramification} @begin{Discussion} This definition is used in @RefSec(Entries and Accept Statements) for the conformance required between the @nt<discrete_subtype_definition>s of an @nt<entry_declaration> for a family of entries and the corresponding @nt<entry_index_specification> of the @nt<entry_body>. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[@Defn{prefixed view profile} The @i<prefixed view profile> of a subprogram is the profile obtained by omitting the first parameter of that subprogram. There is no prefixed view profile for a parameterless subprogram. For the purposes of defining subtype and mode conformance, the convention of a prefixed view profile is considered to match that of either an entry or a protected operation.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This definition is used to define how primitive subprograms of interfaces match operations in task and protected type definitions (see @RefSecNum{Task Units and Task Objects} and @RefSecNum{Protected Units and Protected Objects}).]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The weird rule about conventions is pretty much required for synchronized interfaces to make any sense. There will be wrappers all over the place for interfaces anyway. Of course, this doesn't imply that entries have the same convention as protected operations.]} @end{Reason} @end{StaticSem} @begin{ImplPerm} An implementation may declare an operator declared in a language-defined library unit to be intrinsic. @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} The rules for full conformance are relaxed @em they are now based on the structure of constructs, rather than the sequence of lexical elements. This implies, for example, that "(X, Y: T)" conforms fully with "(X: T; Y: T)", and "(X: T)" conforms fully with "(X: @key[in] T)". @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the default convention is Ada. Also clarified that the convention of a primitive operation of a tagged type is the same as that of the type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0018],ARef=[AI95-00175-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to ensure that two attributes conform only if they have the same @nt{attribute_designator}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00252-01],ARef=[AI95-00254-01],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[Defined the calling convention for anonymous access-to-subprogram types and for prefixed views of subprograms (see @RefSecNum{Selected Components}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Defined the conformance of access result types (see @RefSecNum{Subprogram Declarations}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[Defined the prefixed view profile of subprograms for later use.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[Defined the conformance of anonymous access-to-subprogram parameters.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0046-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Now require @nt{null_exclusion}s to match for full conformance. While this is technically incompatible with Ada 2005 as defined by Amendment 1, it is a new Ada 2005 feature and it is unlikely that users have been intentionally taking advantage of the ability to write mismatching exclusions. In any case, it is easy to fix: add a @nt{null_exclusion} where needed for conformance.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0134-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Now require full conformance of anonymous access-to-subprogram parameters and results for full conformance. This is necessary so that there is no confusion about the default expression that is used for a call. While this is technically incompatible with Ada 2005 as defined by Amendment 1, it is a new Ada 2005 feature and it is unlikely that users have been intentionally taking advantage and writing different default expressions. In any case, it is easy to fix: change any default expressions that don't conform so that they do conform.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0207-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Now include the presence or absence of @key[constant] in access parameters to be considered when checking mode conformance. This is necessary to prevent modification of constants. While this is technically incompatible with Ada 2005 as defined by Amendment 1, it is a new Ada 2005 feature and it is unlikely that users have been intentionally taking advantage and writing mismatching access types.]} @end{Incompatible2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Explicitly aliased parameters are included as part of mode conformance (since it affects the parameter passing mechanism).]} @end{Diffword2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Inline Expansion of Subprograms} @begin{Intro} @Redundant[Subprograms may be expanded in line at the call site.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 4 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[@PDefn2{Term=[program unit pragma], Sec=(Inline)} @PDefn2{Term=[pragma, program unit], Sec=(Inline)} The form of a @nt{pragma} Inline, which is a program unit pragma (see @RefSecNum{Pragmas and Program Units}), is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn{Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Inline)(@Syn2{name} {, @Syn2{name}});]}} @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The @nt{pragma} shall apply to one or more callable entities or generic subprograms.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@ChgNote{Conditional leading} @Chg{Version=[3],New=[For],Old=[If a @nt{pragma} Inline applies to]} a callable entity@Chg{Version=[3],New=[ or],Old=[, this indicates that inline expansion is desired for all calls to that entity. If a @nt{pragma} Inline applies to]} a generic subprogram, @Chg{Version=[3],New=[the following language-defined representation aspect may be specified:],Old=[this indicates that inline expansion is desired for all calls to all instances of that generic subprogram.]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Inline@\The type of aspect Inline is Boolean. When aspect Inline is True for a callable entity, inline expansion is desired for all calls to that entity. When aspect Inline is True for a generic subprogram, inline expansion is desired for all calls to all instances of that generic subprogram.@AspectDefn{Inline}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If directly specified, the @nt{aspect_definition} shall be a static expression. @Redundant[This aspect is never inherited;] if not directly specified, the aspect is False.]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Inline], Text=[@ChgAdded{Version=[3],Text=[For efficiency, Inline calls are requested for a subprogram.]}]} @end{Description} @begin{Ramification} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[Note that inline expansion is desired no matter what name is used in the call. This allows one to request inlining for only one of several overloaded subprograms as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[Deleted]} @ChgDeleted{Version=[3],Text=[@key[package] IO @key[is] @key[procedure] Put(X : @key[in] Integer); @key[procedure] Put(X : @key[in] String); @key[procedure] Put(X : @key[in] Character); @key[private] @key[procedure] Character_Put(X : @key[in] Character) @key[renames] Put; @key[pragma] Inline(Character_Put); @key[end] IO;]} @ChgRef{Version=[3],Kind=[Deleted]} @ChgDeleted{Version=[3],Text=[@key[with] IO; @key[use] IO; @key[procedure] Main @key[is] I : Integer; C : Character; @key[begin] ... Put(C); --@Examcom{ Inline expansion is desired.} Put(I); --@Examcom{ Inline expansion is NOT desired.} @key[end] Main;]} @end{Example} @end{Ramification} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The meaning of a subprogram can be changed by @Chg{Version=[3],New=[inline expansion as requested by aspect],Old=[a @nt{pragma}]} Inline only in the presence of failing checks (see @RefSecNum{Exceptions and Optimization}). @end{Ramification} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For each call, an implementation is free to follow or to ignore the recommendation @Chg{Version=[3],New=[determined],Old=[expressed]} by the @Chg{Version=[3],New=[Inline aspect],Old=[@nt{pragma}]}. @begin{Ramification} Note, in particular, that the recommendation cannot always be followed for a recursive call, and is often infeasible for entries. Note also that the implementation can inline calls even when no such desire was expressed @Chg{Version=[3],New=[via the Inline aspect],Old=[by a pragma]}, so long as the semantics of the program remains unchanged. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00309-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[An implementation may allow a @nt{pragma} Inline that has an argument which is a @nt{direct_name} denoting a @nt{subprogram_body} of the same @nt{declarative_part}.],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This is allowed for Ada 83 compatibility. This is only a permission as this usage is considered obsolescent.]}]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[We only need to allow this in @nt{declarative_part}s, because a body is only allowed in another body, and these all have @nt{declarative_part}s.]}]} @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The @nt{name} in a @nt{pragma} Inline can denote more than one entity in the case of overloading. Such a @nt{pragma} applies to all of the denoted entities.]} @end{Notes} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00309-01]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[@Defn{incompatibilities with Ada 83} A pragma Inline cannot refer to a @nt{subprogram_body} outside of that body. The pragma can be given inside of the subprogram body. Ada 2005 adds an @ImplPermName to allow this usage for compatibility (and Ada 95 implementations also can use this permission), but implementations do not have to allow such @nt{pragma}s.]}]} @end{Incompatible83} @begin{Extend83} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@Defn{extensions to Ada 83} A @nt{pragma} Inline is allowed inside a @nt{subprogram_body} if there is no corresponding @nt{subprogram_declaration}. This is for uniformity with other program unit pragmas.]} @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00309-01]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Implementations are allowed to let @nt{Pragma} Inline apply to a @nt{subprogram_body}.]}]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect Inline is new; @nt{pragma} Inline is now obsolescent.]} @end{Extend2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Subprogram Calls} @begin{Intro} @Defn{subprogram call} A @i{subprogram call} is either a @nt{procedure_call_statement} or a @nt{function_call}; @Redundant[it invokes the execution of the @nt{subprogram_body}. The call specifies the association of the actual parameters, if any, with formal parameters of the subprogram.] @end{Intro} @begin{Syntax} @Syn{lhs=<procedure_call_statement>,rhs=" @SynI{procedure_}@Syn2{name}; | @SynI{procedure_}@Syn2{prefix} @Syn2{actual_parameter_part};"} @Syn{lhs=<function_call>,rhs=" @SynI{function_}@Syn2{name} | @SynI{function_}@Syn2{prefix} @Syn2{actual_parameter_part}"} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[For the purpose of non-syntax rules, infix operator calls are considered @nt{function_call}s. See @RefSecNum{Overloading of Operators}.]} @end{Honest} @Syn{lhs=<actual_parameter_part>,rhs=" (@Syn2{parameter_association} {, @Syn2{parameter_association}})"} @Syn{lhs=<parameter_association>,rhs=" [@SynI{formal_parameter_}@Syn2{selector_name} =>] @Syn2{explicit_actual_parameter}"} @Syn{lhs=<explicit_actual_parameter>,rhs="@Syn2{expression} | @SynI{variable_}@Syn2{name}"} @begin{SyntaxText} @Defn{named association} @Defn{positional association} A @nt{parameter_association} is @i{named} or @i{positional} according to whether or not the @SynI{formal_@!parameter_}@!@nt{selector_@!name} is specified. Any positional associations shall precede any named associations. Named associations are not allowed if the @nt{prefix} in a subprogram call is an @nt{attribute_@!reference}. @begin{Ramification} This means that the formal parameter names used in describing predefined attributes are to aid presentation of their semantics, but are not intended for use in actual calls. @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00310-01]} The @nt{name} or @nt{prefix} given in a @nt{procedure_call_statement} shall resolve to denote a callable entity that is a procedure, or an entry renamed as (viewed as) a procedure. The @nt{name} or @nt{prefix} given in a @nt{function_call} shall resolve to denote a callable entity that is a function.@Chg{Version=[2],New=[ The @nt{name} or @nt{prefix} shall not resolve to denote an abstract subprogram unless it is also a dispatching subprogram.],Old=[]} @Redundant[When there is an @nt<actual_@!parameter_@!part>, the @nt<prefix> can be an @nt<implicit_@!dereference> of an access-to-subprogram value.] @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[This rule is talking about dispatching operations (which is a static concept) and not about dispatching calls (which is a dynamic concept).]} @end{Discussion} @begin{Ramification} The function can be an operator, enumeration literal, attribute that is a function, etc. @end{Ramification} A subprogram call shall contain at most one association for each formal parameter. Each formal parameter without an association shall have a @nt{default_expression} (in the profile of the view denoted by the @nt<name> or @nt<prefix>). @Redundant[This rule is an overloading rule (see @RefSecNum{The Context of Overload Resolution}).] @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0240-1]} @ChgAdded{Version=[3],Text=[All @ResolutionTitle are overloading rules, see @RefSecNum{The Context of Overload Resolution}.]} @end{TheProof} @end{Resolution} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(subprogram call)} For the execution of a subprogram call, the @nt{name} or @nt{prefix} of the call is evaluated, and each @nt{parameter_@!association} is evaluated (see @RefSecNum{Parameter Associations}). If a @nt{default_@!expression} is used, an implicit @nt{parameter_@!association} is assumed for this rule. These evaluations are done in an arbitrary order. The @nt{subprogram_@!body} is then executed@Chg{Version=[2],New=[, or a call on an entry or protected subprogram is performed (see @RefSecNum{Dispatching Operations of Tagged Types})],Old=[]}. Finally, if the subprogram completes normally, then after it is left, any necessary assigning back of formal to actual parameters occurs (see @RefSecNum{Parameter Associations}).@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Discussion} The implicit association for a default is only for this run-time rule. At compile time, the visibility rules are applied to the default at the place where it occurs, not at the place of a call. @end{Discussion} @begin{Honest} If the subprogram is inherited, see @RefSec{Derived Types and Classes}. If the subprogram is protected, see @RefSec{Protected Subprograms and Protected Actions}. If the subprogram is really a renaming of an entry, see @RefSec{Entry Calls}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If the subprogram is implemented by an entry or protected subprogram, it will be treated as a dispatching call to the corresponding entry (see @RefSec{Entry Calls}) or protected subprogram (see @RefSec{Protected Subprograms and Protected Actions}).]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} Normally, the @nt{subprogram_body} that is executed by the above rule is the one for the subprogram being called. For an enumeration literal, implicitly declared (but noninherited) subprogram, @Chg{Version=[2],New=[null procedure, ],Old=[]}or an attribute that is a subprogram, an implicit body is assumed. For a dispatching call, @RefSec{Dispatching Operations of Tagged Types} defines which @nt{subprogram_body} is executed. @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[If the @nt{name} or @nt{prefix} of a subprogram call denotes a prefixed view (see @RefSecNum{Selected Components}), the subprogram call is equivalent to a call on the underlying subprogram, with the first actual parameter being provided by the @nt{prefix} of the prefixed view (or the Access attribute of this @nt{prefix} if the first formal parameter is an access parameter), and the remaining actual parameters given by the @nt{actual_parameter_part}, if any.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised at the point of a @nt{function_call} if the function completes normally without executing a @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]}. @begin{Discussion} We are committing to raising the exception at the point of call, for uniformity @em see AI83-00152. This happens after the function is left, of course. Note that there is no name for suppressing this check, since the check imposes no time overhead and minimal space overhead (since it can usually be statically eliminated as dead code). @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} A @nt{function_call} denotes a constant, as defined in @RefSecNum{Return Statements}; the nominal subtype of the constant is given by the @Chg{Version=[2],New=[nominal],Old=[result]} subtype of the function@Chg{Version=[2],New=[ result],Old=[]}. @PDefn2{Term=[nominal subtype], Sec=(of the result of a @nt<function_call>)} @PDefn2{Term=[constant], Sec=(result of a @nt<function_call>)} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of procedure calls:} @begin{Example} Traverse_Tree; --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(128, Title, True); --@RI{ see @RefSecNum{Subprogram Declarations}} Switch(From => X, To => Next); --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(128, Header => Title, Center => True); --@RI{ see @RefSecNum{Subprogram Declarations}} Print_Header(Header => Title, Center => True, Pages => 128); --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of function calls:} @end{WideAbove} @begin{Example} Dot_Product(U, V) --@RI{ see @RefSecNum{Subprogram Declarations} and @RefSecNum{Subprogram Bodies}} Clock --@RI{ see @RefSecNum{Delay Statements, Duration, and Time}} F.@key[all] --@RI{ presuming F is of an access-to-subprogram type @em see @RefSecNum{Access Types}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of procedures with default expressions:} @end{WideAbove} @begin{Example} @key[procedure] Activate(Process : @key[in] Process_Name; After : @key[in] Process_Name := No_Process; Wait : @key[in] Duration := 0.0; Prior : @key[in] Boolean := False); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @key[procedure] Pair(Left, Right : @key[in] Person_Name := @key[new] Person@Chg{Version=[3],New=[(M)],Old=[]}); --@RI{ see @RefSecNum{Incomplete Type Declarations}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of their calls:} @end{WideAbove} @begin{Example} Activate(X); Activate(X, After => Y); Activate(X, Wait => 60.0, Prior => True); Activate(X, Y, 10.0, False); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Pair; Pair(Left => @key[new] Person@Chg{Version=[3],New=[(F)],Old=[]}, Right => @key[new] Person@Chg{Version=[3],New=[(M)],Old=[]}); @end{Example} @end{Examples} @begin{Notes} If a @nt{default_expression} is used for two or more parameters in a multiple @nt{parameter_@!specification}, the @nt{default_@!expression} is evaluated once for each omitted parameter. Hence in the above examples, the two calls of Pair are equivalent. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of overloaded subprograms:} @begin{Example} @key[procedure] Put(X : @key[in] Integer); @key[procedure] Put(X : @key[in] String); @key[procedure] Set(Tint : @key[in] Color); @key[procedure] Set(Signal : @key[in] Light); @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of their calls:} @end{WideAbove} @begin{Example} Put(28); Put("no possible ambiguity here"); Set(Tint => Red); Set(Signal => Red); Set(Color'(Red)); --@RI{ Set(Red) would be ambiguous since Red may} --@RI{ denote a value either of type Color or of type Light} @end{Example} @end{Examples} @begin{DiffWord83} We have gotten rid of parameters @lquotes@;of the form of a type conversion@rquotes@; (see RM83-6.4.1(3)). The new view semantics of @nt{type_conversion}s allows us to use normal @nt{type_conversion}s instead. We have moved wording about run-time semantics of parameter associations to @RefSecNum{Parameter Associations}. We have moved wording about raising Program_Error for a function that falls off the end to here from RM83-6.5. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00310-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Nondispatching abstract operations are no longer considered when resolving a subprogram call. That makes it possible to use @key{abstract} to @lquotes@;undefine@rquotes@; a predefined operation for an untagged type. That's especially helpful when defining custom arithmetic packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Changed the definition of the nominal subtype of a @nt{function_call} to use the nominal subtype wording of @RefSecNum{Subprogram Declarations}, to take into account @nt{null_exclusion}s and access result types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that the meaning of a call on a subprogram @lquotes@;implemented by@rquotes an entry or protected operation is defined by @RefSecNum{Dispatching Operations of Tagged Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00407-01]} @ChgAdded{Version=[2],Text=[Defined the meaning of a call on a prefixed view of a subprogram (see @RefSecNum{Selected Components}).]} @end{DiffWord95} @LabeledSubClause{Parameter Associations} @begin{Intro} @Redundant[@Defn{parameter passing} A parameter association defines the association between an actual parameter and a formal parameter.] @end{Intro} @begin{MetaRules} The parameter passing rules for @b(out) parameters are designed to ensure that the parts of a type that have implicit initial values (see @RefSecNum{Object Declarations}) don't become @lquotes@;de-initialized@rquotes@; by being passed as an @b(out) parameter. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[For explicitly aliased parameters of functions, we will ensure at the call site that a part of the parameter can be returned as part of the function result without creating a dangling pointer. We do this with accessibility checks at the call site that all actual objects of explicitly aliased parameters live at least as long as the function result; then we can allow them to be returned as access discriminants or anonymous access results, as those have the master of the function result.]} @end{MetaRules} @begin{Resolution} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0118-1]} The @SynI{formal_parameter_}@nt{selector_name} of a@Chg{Version=[3],New=[ named],Old=[]} @nt{parameter_@!association} shall resolve to denote a @nt{parameter_@!specification} of the view being called@Chg{Version=[3],New=[; @Defn{named association}@Defn{positional association}@Defn{named parameter association}@Defn{positional parameter association}this is the formal parameter of the association. The formal parameter for a positional @nt{parameter_@!association} is the parameter with the corresponding position in the formal part of the view being called],Old=[]}. @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0118-1]} @ChgAdded{Version=[3],Text=[For positional parameters, the @ldquote@;corresponding position@rdquote is calculated after any transformation of prefixed views.]} @end{Honest} @Defn2{Term=[actual parameter], Sec=(for a formal parameter)} The @i(actual parameter) is either the @nt<explicit_actual_parameter> given in a @nt<parameter_association> for a given formal parameter, or the corresponding @nt<default_expression> if no @nt<parameter_association> is given for the formal parameter. @Defn2{Term=[expected type], Sec=(actual parameter)} The expected type for an actual parameter is the type of the corresponding formal parameter. @begin{Honest} The corresponding @nt<default_expression> is the one of the corresponding formal parameter in the profile of the view denoted by the @nt<name> or @nt<prefix> of the call. @end{Honest} If the mode is @key(in), the actual is interpreted as an @nt{expression}; otherwise, the actual is interpreted only as a @nt{name}, if possible. @begin{Ramification} This formally resolves the ambiguity present in the syntax rule for @nt<explicit_actual_parameter>. Note that we don't actually require that the actual be a @nt<name> if the mode is not @key(in); we do that below. @end{Ramification} @end{Resolution} @begin{Legality} If the mode is @key(in out) or @key(out), the actual shall be a @nt<name> that denotes a variable. @begin{Discussion} We no longer need @lquotes@;or a @nt{type_conversion} whose argument is the @nt{name} of a variable,@rquotes@; because a @nt{type_conversion} is now a @nt{name}, and a @nt{type_conversion} of a variable is a variable. @end{Discussion} @begin{Reason} @leading@;The requirement that the actual be a (variable) @nt<name> is not an overload resolution rule, since we don't want the difference between @nt<expression> and @nt{name} to be used to resolve overloading. For example: @begin{Example} procedure Print(X : @key[in] Integer; Y : @key[in] Boolean := True); procedure Print(Z : @key[in out] Integer); . . . Print(3); --@RI{ Ambiguous!} @end{Example} The above call to Print is ambiguous even though the call is not compatible with the second Print which requires an actual that is a (variable) @nt<name> (@lquotes@;3@rquotes@; is an @nt<expression>, not a @nt<name>). This requirement is a legality rule, so overload resolution fails before it is considered, meaning that the call is ambiguous. @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0102-1],ARef=[AI05-0142-4]} @leading@;@Chg{Version=[3],New=[If the formal parameter is an explicitly aliased parameter, the type of the actual parameter shall be tagged or the actual parameter shall be an aliased view of an object. Further, if the formal parameter subtype @i{F} is untagged:], Old=[The type of the actual parameter associated with an access parameter shall be convertible (see @RefSecNum{Type Conversions}) to its anonymous access type. @PDefn2{Term=[convertible],Sec=(required)}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[the subtype @i{F} shall statically match the nominal subtype of the actual object; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[the subtype @i{F} shall be unconstrained, discriminated in its full view, and unconstrained in any partial view.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tagged objects (and tagged @nt{aggregate}s for @key[in] parameters) do not need to be aliased. This matches the behavior of unaliased formal parameters of tagged types, which allow 'Access to be taken of the formal parameter regardless of the form of the actual parameter.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We need the subtype check on untagged actual parameters so that the requirements of 'Access are not lost. 'Access makes its checks against the nominal subtype of its prefix, and parameter passing can change that subtype. But we don't want this parameter passing to change the objects that would be allowed as the prefix of 'Access. This is particularly important for arrays, where we don't want to require any additional implementation burden.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[In a function call, the accessibility level of the actual object for each explicitly aliased parameter shall not be statically deeper than the accessibility level of the master of the call (see @RefSecNum{Operations of Access Types}).]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Since explicitly aliased parameters are either tagged or required to be objects, there is always an object (possibly anonymous) to talk about. This is discussing the static accessibility level of the actual object; it does not depend on any runtime information (for instance when the actual object is a formal parameter of another subprogram, it does not depend on the actual parameter of that other subprogram).]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This accessibility check (and its dynamic cousin as well) can only fail if the function call is used to directly initialize a built-in-place object with a master different than that enclosing the call. The only place all of those conditions exist is in the initializer of an @nt{allocator}; in all other cases this check will always pass.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[Two @nt{name}s are @i{known to denote the same object} if:@Defn{known to denote the same object}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[both @nt{name}s statically denote the same stand-alone object or parameter; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[both @nt{name}s are @nt{selected_component}s, their @nt{prefix}es are known to denote the same object, and their @nt{selector_name}s denote the same component; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[both @nt{name}s are dereferences (implicit or explicit) and the dereferenced @nt{name}s are known to denote the same object; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[both @nt{name}s are @nt{indexed_component}s, their @nt{prefix}es are known to denote the same object, and each of the pairs of corresponding index values are either both static expressions with the same static value or both @nt{name}s that are known to denote the same object; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[both @nt{name}s are @nt{slice}s, their @nt{prefix}es are known to denote the same object, and the two @nt{slice}s have statically matching index constraints; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[one of the two @nt{name}s statically denotes a renaming declaration whose renamed @SynI{object_}@nt{name} is known to denote the same object as the other, the @nt{prefix} of any dereference within the renamed @SynI{object_}@nt{name} is not a variable, and any @nt{expression} within the renamed @SynI{object_}@nt{name} contains no references to variables nor calls on nonstatic functions.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This exposes known renamings of slices, indexing, and so on to this definition. In particular, if we have]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[C : Character @key[renames] S(1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[then C and S(1) are known to denote the same object.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[We need the requirement that no variables occur in the @nt{prefix}es of dereferences and in (index) @nt{expression}s of the renamed object in order to avoid problems from later changes to those parts of renamed names. Consider:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[ @key[type] Ref @key[is access] Some_Type; Ptr : Ref := @key[new] Some_Type'(...); X : Some_Type @key[renames] Ptr.@key[all]; @key[begin] Ptr := @key[new] Some_Type'(...); P (Func_With_Out_Params (Ptr.@key[all]), X);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[X and Ptr.@key[all] should not be known to denote the same object, since they denote different allocated objects (and this is not an unreasonable thing to do).]} @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The exclusion of variables from renamed object_names is not enough to prevent altering the value of the name or expression by another access path. For instance, both @key[in] parameters passed by reference and access-to-constant values can designate variables. For the intended use of "known to be the same object", this is OK; the modification via another access path is very tricky and it is OK to reject code that would be buggy except for the tricky code. Assuming Element is an elementary type, consider the following example:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Global : Tagged_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{procedure} Foo (Param : @key{in} Tagged_Type := Global) @key{is} X : Element @key{renames} Some_Global_Array (Param.C); @key{begin} Global.C := Global.C + 1; Swap (X, Some_Global_Array (Param.C));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The rules will flag the call of procedure Swap as illegal, since X and Some_Global_Array (Parameter.C) are known to denote the same object (even though they will actually represent different objects if Param = Global). But this is only incorrect if the parameter actually is Global and not some other value; the error could exist for some calls. So this flagging seems harmless.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Similar examples can be constructed using stand-alone composite constants with controlled or immutably limited components, and (as previously noted) with dereferences of access-to-constant values. Even when these examples flag a call incorrectly, that call depends on very tricky code (modifying the value of a constant); the code is likely to confuse future maintainers as well and thus we do not mind rejecting it.]} @end{Honest} @end{Itemize} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Whether or not @nt{name}s or @nt{prefix}es are known to denote the same object is determined statically. If the name contains some dynamic portion other than a dereference, @nt{indexed_component}, or @nt{slice}, it is not "known to denote the same object".]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These rules make no attempt to handle slices of objects that are known to be the same when the slices have dynamic bounds (other than the trivial case of bounds being defined by the same subtype), even when the bounds could be proven to be the same, as it is just too complex to get right and these rules are intended to be conservative.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=["Known to denote the same object" is intended to be an equivalence relationship, that is, it is reflexive, symmetric, and transitive. We believe this follows from the rules. For instance, given the following declarations:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[S : String(1..10); ONE : @key[constant] Natural := 1; R : Character @key[renames] S(1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[the names R and S(1) are known to denote the same object by the sixth bullet, and S(1) and S(ONE) are known to denote the same object by the fourth bullet, so using the sixth bullet on R and S(ONE), we simply have to test S(1) vs. S(ONE), which we already know denote the same object.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[Two @nt{name}s are @i{known to refer to the same object} if @Defn{known to refer to the same object}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The two @nt{name}s are known to denote the same object; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[One of the @nt{name}s is a @nt{selected_component}, @nt{indexed_component}, or @nt{slice} and its @nt{prefix} is known to refer to the same object as the other @nt{name}; or]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[One of the two @nt{name}s statically denotes a renaming declaration whose renamed @SynI{object_}@nt{name} is known to refer to the same object as the other @nt{name}.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This ensures that names Prefix.Comp and Prefix are known to refer to the same object for the purposes of the rules below. This intentionally does not include dereferences; we only want to worry about accesses to the same object, and a dereference changes the object in question. (There is nothing shared between an access value and the object it designates.)]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[ If a call @i<C> has two or more parameters of mode @key[in out] or @key[out] that are of an elementary type, then the call is legal only if:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For each @nt{name} @i<N> that is passed as a parameter of mode @key[in out] or @key[out] to the call @i<C>, there is no other @nt{name} among the other parameters of mode @key[in out] or @key[out] to @i<C> that is known to denote the same object.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This means @i{visibly} an elementary type; it does not include partial views of elementary types (partial views are always composite). That's necessary to avoid having @LegalityTitle depend on the contents of the private part.]} @end{Honest} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[If a construct @i<C> has two or more direct constituents that are @nt{name}s or @nt{expression}s whose evaluation may occur in an arbitrary order, at least one of which contains a function call with an @key[in out] or @key[out] parameter, then the construct is legal only if:]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[All of the places where the language allows an arbitrary order can be found by looking in the index under "arbitrary order, allowed". Note that this listing includes places that don't involve @nt{name}s or @nt{expression}s (such as checks or finalization).]} @end{Ramification} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For each name @i<N> that is passed as a parameter of mode @key[in out] or @key[out] to some inner function call @i<C2> (not including the construct @i<C> itself), there is no other @nt{name} anywhere within a direct constituent of the construct @i<C> other than the one containing @i<C2>, that is known to refer to the same object.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This requirement cannot fail for a procedure or entry call alone; there must be at least one function with an @key[in out] or @key[out] parameter called as part of a parameter expression of the call in order for it to fail.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[These rules prevent obvious cases of dependence on the order of evaluation of @nt{name}s or @nt{expression}s. Such dependence is usually a bug, and in any case, is not portable to another implementation (or even another optimization setting).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In the case that the top-level construct C is a call, these rules do not require checks for most @key[in out] parameters, as the rules about evaluation of calls prevent problems. Similarly, we do not need checks for short circuit operations or other operations with a defined order of evaluation. The rules about arbitrary order (see @RefSecNum{Method of Description and Syntax Notation}) allow evaluating parameters and writing parameters back in an arbitrary order, but not interleaving of evaluating parameters of one call with writing parameters back from another @em that would not correspond to any allowed sequential order.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[For the purposes of checking this rule:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For an array @nt{aggregate}, an @nt{expression} associated with a @nt{discrete_choice_list} that has two or more discrete choices, or that has a nonstatic range, is considered as two or more separate occurrences of the @nt{expression};]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a record @nt{aggregate}:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The @nt{expression} of a @nt{record_component_association} is considered to occur once for each associated component; and]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The @nt{default_expression} for each @nt{record_component_association} with <> for which the associated component has a @nt{default_expression} is considered part of the @nt{aggregate};]} @end{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For a call, any @nt{default_expression} evaluated as part of the call is considered part of the call.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not check expressions that are evaluated only because of a component initialized by default in an aggregate (via <>).]} @end{Ramification} @end{Legality} @begin{RunTime} @leading@keepnext@PDefn2{Term=[evaluation], Sec=(parameter_association)} For the evaluation of a @nt{parameter_association}: @begin{Itemize} The actual parameter is first evaluated. For an access parameter, the @nt{access_definition} is elaborated, which creates the anonymous access type. For a parameter @Redundant[(of any mode)] that is passed by reference (see @RefSecNum{Formal Parameter Modes}), a view conversion of the actual parameter to the nominal subtype of the formal parameter is evaluated, and the formal parameter denotes that conversion. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} @begin{Discussion} We are always allowing sliding, even for [@key(in)] @key(out) by-reference parameters. @end{Discussion} @Defn2{Term=[assignment operation], Sec=(during evaluation of a @nt{parameter_association})} For an @key(in) or @key(in out) parameter that is passed by copy (see @RefSecNum{Formal Parameter Modes}), the formal parameter object is created, and the value of the actual parameter is converted to the nominal subtype of the formal parameter and assigned to the formal. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} @begin{Ramification} The conversion mentioned here is a value conversion. @end{Ramification} @leading@keepnext@;For an @key(out) parameter that is passed by copy, the formal parameter object is created, and: @begin(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0153-3],ARef=[AI05-0196-1]} For an access type, the formal parameter is initialized from the value of the actual, without @Chg{Version=[3],New=[checking that the value satisfies any constraint, any predicate, or any exclusion of the null value],Old=[a constraint check]}; @begin{Reason} This preserves the @MetaRulesName that an object of an access type is always initialized with a @lquotes@;reasonable@rquotes@; value. @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0153-3],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[For a scalar type that has the Default_Value aspect specified, the formal parameter is initialized from the value of the actual, without checking that the value satisfies any constraint or any predicate;]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This preserves the @MetaRulesName that all objects of a type with an implicit initial value are initialized. This is important so that a programmer can guarantee that all objects of a scalar type have a valid value with a carefully chosen Default_Value.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule means that @b<out> parameters of a subtype @i<T> with a specified Default_Value need to be large enough to support any possible value of the base type of @i<T>. In contrast, a type that does not have a Default_Value only need support the size of the subtype (since no values are passed in).]} @end{ImplNote} For a composite type with discriminants or that has implicit initial values for any subcomponents (see @RefSecNum{Object Declarations}), the behavior is as for an @key[in out] parameter passed by copy. @begin{Reason} This ensures that no part of an object of such a type can become @lquotes@;de-initialized@rquotes@; by being part of an @b(out) parameter. @end{Reason} @begin{Ramification} This includes an array type whose component type is an access type, and a record type with a component that has a @nt{default_expression}, among other things. @end{Ramification} For any other type, the formal parameter is uninitialized. If composite, a view conversion of the actual parameter to the nominal subtype of the formal is evaluated @Redundant[(which might raise Constraint_Error)], and the actual subtype of the formal is that of the view conversion. If elementary, the actual subtype of the formal is given by its nominal subtype. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0228-1]} This case covers scalar types@Chg{Version=[3],New=[ that do not have Default_Value specified],Old=[]}, and composite types whose subcomponent's subtypes do not have any implicit initial values. The view conversion for composite types ensures that if the lengths don't match between an actual and a formal array parameter, the Constraint_Error is raised before the call, rather than after. @end{Ramification} @end(itemize) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0142-4],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[In a function call, for each explicitly aliased parameter, a check is made that the accessibility level of the master of the actual object is not deeper than that of the master of the call (see @RefSecNum{Operations of Access Types}).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the actual object to a call @i<C> is a formal parameter of some function call @i<F>, no dynamic check against the master of the actual parameter of @i<F> is necessary. Any case which could fail the dynamic check is already statically illegal (either at the call site of @i<F>, or at the call site @i<C>). This is important, as it would require nasty distributed overhead to accurately know the dynamic accessibility of a formal parameter (all tagged and explicitly aliased parameters would have to carry accessibility levels).]} @end{Ramification} @end{Itemize} @PDefn2{Term=[constrained],Sec=(object)} @PDefn2{Term=[unconstrained],Sec=(object)} A formal parameter of mode @key[in out] or @key[out] with discriminants is constrained if either its nominal subtype or the actual parameter is constrained. @Defn{parameter copy back} @Defn{copy back of parameters} @Defn{parameter assigning back} @Defn{assigning back of parameters} @Defn2{Term=[assignment operation], Sec=(during parameter copy back)} After normal completion and leaving of a subprogram, for each @key(in out) or @key(out) parameter that is passed by copy, the value of the formal parameter is converted to the subtype of the variable given as the actual parameter and assigned to it. @PDefn2{Term=[implicit subtype conversion],Sec=(parameter passing)} These conversions and assignments occur in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @begin{Ramification} The conversions mentioned above during parameter passing might raise Constraint_Error @em (see @RefSecNum{Type Conversions}). @end{Ramification} @begin{Ramification} If any conversion or assignment as part of parameter passing propagates an exception, the exception is raised at the place of the subprogram call; that is, it cannot be handled inside the @nt{subprogram_body}. @end{Ramification} @begin{TheProof} Since these checks happen before or after executing the @nt{subprogram_body}, the execution of the @nt{subprogram_body} does not dynamically enclose them, so it can't handle the exceptions. @end{TheProof} @begin{Discussion} The variable we're talking about is the one denoted by the @i{variable_}@nt{name} given as the @nt{explicit_actual_parameter}. If this @i{variable_}@nt{name} is a @nt{type_conversion}, then the rules in @RefSecNum{Type Conversions} for assigning to a view conversion apply. That is, if X is of subtype S1, and the actual is S2(X), the above-mentioned conversion will convert to S2, and the one mentioned in @RefSecNum{Type Conversions} will convert to S1. @end{Discussion} @end{RunTime} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)}If the nominal subtype of a formal parameter with discriminants is constrained or indefinite, and the parameter is passed by reference, then the execution of the call is erroneous if the value of any discriminant of the actual is changed while the formal parameter exists (that is, before leaving the corresponding callable construct).]} @end{Erron} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 95, a program can rely on the fact that passing an object as an @key[out] parameter does not @lquotes@;de-initialize@rquotes@; any parts of the object whose subtypes have implicit initial values. (This generalizes the RM83 rule that required copy-in for parts that were discriminants or of an access type.) @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We have eliminated the subclause on Default Parameters, as it is subsumed by earlier @Chg{Version=[3],New=[],Old=[clauses and ]}subclauses. @end{DiffWord83} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0196-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} @b<Correction:> Clarified that @key[out] parameters of an access type are not checked for null exclusions when they are passed in (which is similar to the behavior for constraints). This was unspecified in Ada 2005, so a program which depends on the behavior of an implementation which does check the exclusion may malfunction. But a program depending on an exception being raised is unlikely.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Additional rules have been added to make illegal passing the same elementary object to more than one @key[in out] or @key[out] parameters of the same call. In this case, the result in the object could depend on the compiler version, optimization settings, and potentially the phase of the moon, so this check will mostly reject programs that are nonportable and could fail with any change. Even when the result is expected to be the same in both parameters, the code is unnecessarily tricky. Programs which fail this new check should be rare and are easily fixed by adding a temporary object.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> A missing rule was added to cover cases that were missed in Ada 95 and Ada 2005; specifically, that an @key[in] parameter passed by reference might have its discriminants changed via another path. Such cases are erroneous as requiring compilers to detect such errors would be expensive, and requiring such cases to work would be a major change of the user model (@key[in] parameters with discriminants could no longer be assumed constant). This is not an inconsistency, as compilers are not required to change any current behavior.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0102-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Moved implicit conversion @LegalityName to @RefSecNum{The Context of Overload Resolution}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0118-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a definition for positional parameters, as this is missing from Ada 95 and later.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Rules have been added defining the legality and dynamic checks needed for explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Text=[Additional rules have been added such that passing an object to an @key[in out] or @key[out] parameter of a function is illegal if it is used elsewhere in a construct which allows evaluation in an arbitrary order. Such calls are not portable (since the results may depend on the evaluation order), and the results could even vary because of optimization settings and the like. Thus they've been banned.]} @end{DiffWord2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Return Statements} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} A @Chg{Version=[2],New=[@nt{simple_@!return_@!statement} or @nt{extended_@!return_@!statement} (collectively called a @i<return statement>) @Defn{return statement}],Old=[@nt{return_statement}]} is used to complete the execution of the innermost enclosing @nt{subprogram_@!body}, @nt{entry_@!body}, or @nt{accept_@!statement}. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Syn{lhs=<@Chg{Version=[2],New=[simple_return_statement],Old=[return_statement]}>,rhs="@key{return} [@Syn2{expression}];"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0277-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=[extended_return_object_declaration],Old=[]}>, rhs="@Chg{Version=[3],New=< @Syn2{defining_identifier} : [@key{aliased}][@key{constant}] @Syn2{return_subtype_indication} [:= @Syn2{expression}]>,Old=[]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0015-1],ARef=[AI05-0053-1],ARef=[AI05-0277-1],ARef=[AI05-0299-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[extended_return_statement],Old=[]}>, rhs="@Chg{Version=[2],New=< @key{return} @Chg{Version=[3],New=<@Syn2{extended_return_object_declaration}>,Old=<@Syn2{defining_identifier} : [@Chg{Version=[3],New=<@Key{constant}>,Old=[@Key{aliased}]}] @Syn2{return_subtype_indication} [:= @Syn2{expression}]>} [@Key{do} @Syn2{handled_sequence_of_statements} @key{end} @key{return}];>,Old=[]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[return_subtype_indication],Old=[]}>, rhs="@Chg{Version=[2],New=<@Syn2{subtype_indication} | @Syn2{access_definition}>,Old=[]}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@Defn2{Term=[result subtype], Sec=(of a function)} The @i<result subtype> of a function is the subtype denoted by the @nt<subtype_mark>, or defined by the @nt<access_definition>, after the reserved word @key<return> in the profile of the function.@PDefn2{Term=[expected type], Sec=(@nt{expression} of @nt<simple_@!return_@!statement>)}],Old=[@Defn{return expression} The @nt{expression}, if any, of a @nt{return_statement} is called the @i{return expression}. @Defn2{Term=[result subtype], Sec=(of a function)} The @i(result subtype) of a function is the subtype denoted by the @nt{subtype_mark} after the reserved word @key(return) in the profile of the function.@PDefn2{Term=[expected type], Sec=(return expression)}]} The expected type for @Chg{Version=[2],New=[the @nt{expression}, if any, of a @nt{simple_@!return_@!statement}],Old=[a return expression]} is the result type of the corresponding function.@Chg{Version=[2],New=[ @PDefn2{Term=[expected type], Sec=(@nt{expression} of @nt{extended_return_statement})} The expected type for the @nt{expression} of an @nt{extended_return_statement} is that of the @nt{return_@!subtype_@!indication}.],Old=[]} @begin{Honest} The same applies to generic functions. @end{Honest} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@Defn2{Term=[apply], Sec=(to a callable construct by a return statement)}], Old=[@Defn2{Term=[apply], Sec=(to a callable construct by a @nt{return_statement})}]} A @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} shall be within a callable construct, and it @i{applies to} the innermost @Chg{Version=[2],New=[callable construct or @nt{extended_return_statement} that contains it],Old=[one]}. A @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} shall not be within a body that is within the construct to which the @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} applies. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0015-1]} A function body shall contain at least one @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} that applies to the function body, unless the function contains @nt{code_statement}s. A @Chg{Version=[2],New=[@nt{simple_@!return_@!statement}],Old=[@nt{return_@!statement}]} shall include @Chg{Version=[2],New=[an @nt{expression}],Old=[a return expression]} if and only if it applies to a function body.@Chg{Version=[2],New=[ An @nt<extended_return_statement> shall apply to a function body.],Old=[]}@Chg{Version=[3],New=[ An @nt{extended_return_statement} with the reserved word @key[constant] shall include an @nt{expression}.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The requirement that a function body has to have at least one @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} is a @lquotes@;helpful@rquotes@; restriction. There @Chg{Version=[2],New=[has],Old=[was]} been some interest in lifting this restriction, or allowing a raise statement to substitute for the @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]}. However, there was enough interest in leaving it as is that we decided not to change it. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[A return statement can apply to an @nt{extended_return_statement}, so a @nt{simple_@!return_@!statement} without an @nt{expression} can be given in one. However, neither @nt{simple_@!return_@!statement} with an @nt{expression} nor an @nt{extended_return_statement} can be given inside an @nt{extended_return_statement}, as they must apply (directly) to a function body.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an @nt{extended_@!return_@!statement} that applies to a function body:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0032-1],ARef=[AI05-0103-1]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is defined by a @nt{subtype_mark}, the @nt{return_@!subtype_@!indication} shall be a @nt{subtype_indication}. The type of the @nt{subtype_indication} shall be@Chg{Version=[3],New=[ covered by],Old=[]} the result type of the function. @Chg{Version=[3],New=[The],Old=[If the result subtype of the function is constrained, then the]} subtype defined by the @nt{subtype_indication} shall @Chg{Version=[3],New=[be statically compatible with the result subtype of the function; if the result type of the function is elementary, the two subtypes],Old=[also be constrained and]} shall statically match@Chg{Version=[3],New=[],Old=[ this result subtype]}.@PDefn2{Term=[statically matching],Sec=(required)} If the result subtype of the function is @Chg{Version=[3],New=[indefinite], Old=[unconstrained]}, then the subtype defined by the @nt{subtype_indication} shall be a definite subtype, or there shall be an @nt{expression}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is defined by an @nt{access_definition}, the @nt{return_@!subtype_@!indication} shall be an @nt{access_definition}. The subtype defined by the @nt{access_definition} shall statically match the result subtype of the function. The accessibility level of this anonymous access subtype is that of the result subtype.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0032-1]} @ChgAdded{Version=[3],Text=[If the result subtype of the function is class-wide, the accessibility level of the type of the subtype defined by the @nt{return_subtype_indication} shall not be statically deeper than that of the master that elaborated the function body.]} @begin{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In this case, the @nt{return_subtype_indication} could be a specific type initialized by default; in that case there is no @nt{expression} to check.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0032-1]}@Comment{Paragraph number only change} @ChgAdded{Version=[2],Type=[Leading],Text=[For any return statement that applies to a function body:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0188-1]}@Comment{Paragraph number only change} @ChgAdded{Version=[2],Text=[@Redundant[If the result subtype of the function is limited, then the @nt{expression} of the return statement (if any) shall @Chg{Version=[3], New=[meet the restrictions described in @RefSecNum{Limited Types}],Old=[be an @nt{aggregate}, a function call (or equivalent use of an operator), or a @nt{qualified_expression} or parenthesized expression whose operand is one of these]}.]]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0188-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[In other words, if limited, the @nt{expression} must produce a @lquotes@;new@rquotes@; object, rather than being the name of a preexisting object (which would imply copying).],Old=[]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0032-1],ARef=[AI05-0051-1]} @ChgAdded{Version=[2],Text=[If the result subtype of the function is class-wide, the accessibility level of the type of the @nt{expression} @Chg{Version=[3],New=[(if any) ],Old=[]}of the return statement shall not be statically deeper than that of the master that elaborated the function body.@Chg{Version=[3],New=[],Old=[ If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{expression} of the @nt{simple_@!return_@!statement} or the @nt{return_@!subtype_@!indication}, shall not be statically deeper than that of the master that elaborated the function body.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0032-1],ARef=[AI05-0051-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[If],Old=[We know that if]} the result type is class wide, then there must be an @nt{expression} of the return statement@Chg{Version=[3],New=[ unless this is an @nt{extended_return_statement} whose @nt{return_subtype_indication} is a specific type. We have a separate rule to cover that case. Note that if an @nt{extended_return_statement} has an @nt{expression}, then both this rule and the next one must be satisfied],Old=[. Similarly, if the result subtype is unconstrained, then either the @nt{return_@!subtype_@!indication} (if any) is constrained, or there must be an @nt{expression}]}.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0051-1]} @ChgAdded{Version=[3],Text=[If the subtype determined by the @nt{expression} of the @nt{simple_return_statement} or by the @nt{return_subtype_indication} has one or more access discriminants, the accessibility level of the anonymous access type of each access discriminant shall not be statically deeper than that of the master that elaborated the function body.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[We use the type used by the return statement rather than from the function return type since we want to check whenever the return object has access discriminants, even if the function return type doesn't have any (mostly for a class-wide type).]} @end{Discussion} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0277-1]} @ChgAdded{Version=[3],Text=[If the keyword @key[aliased] is present in an @nt{extended_return_object_declaration}, the type of the extended return object shall be immutably limited.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0015-1],ARef=[AI05-0144-2]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[return object], Sec=(extended_return_statement)} Within an @nt{extended_return_statement}, the @i{return object} is declared with the given @nt{defining_identifier}, with the nominal subtype defined by the @nt{return_@!subtype_@!indication}.@Chg{Version=[3],New=[ An @nt{extended_return_statement} with the reserved word @key[constant] is a full constant declaration that declares the return object to be a constant object.],Old=[]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0032-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[execution], Sec=(extended_return_statement)} For the execution of an @nt{extended_return_statement}, the @nt{subtype_indication} or @nt{access_definition} is elaborated. This creates the nominal subtype of the return object. If there is an @nt{expression}, it is evaluated and converted to the nominal subtype (which might raise Constraint_Error @em see @RefSecNum{Type Conversions}@PDefn2{Term=[implicit subtype conversion],Sec=(function return)}); the return object is created and the converted value is assigned to the return object. Otherwise, the return object is created and initialized by default as for a stand-alone object of its nominal subtype (see @RefSecNum{Object Declarations}). If the nominal subtype is indefinite, the return object is constrained by its initial value.@PDefn2{Term=[creation],Sec=[of a return object]}@PDefn{constrained by its initial value}@Chg{Version=[3],New=[ A check is made that the value of the return object belongs to the function result subtype. Constraint_Error is raised if this check fails.@Defn2{Term=[Constraint_Error], Sec=(raised by failure of run-time check)} @IndexCheck{Discriminant_Check}],Old=[]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the result type is controlled or has a controlled part, appropriate calls on Initialize or Adjust are performed prior to executing the @nt{handled_sequence_of_statements}, except when the initial expression is an @nt{aggregate} (which requires build-in-place with no call on Adjust).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[If the return statement is left without resulting in a return (for example, due to an exception propagated from the @nt{expression} or the @nt{handled_sequence_of_statements}, or a goto out of the @nt{handled_sequence_of_statements}), @Chg{Version=[3],New=[if ],Old=[]}the return object @Chg{Version=[3],New=[has been created, it ],Old=[]}is finalized prior to leaving the return statement.@Chg{Version=[3],New=[ If it has not been created when the return statement is left, it is not created or finalized.],Old=[]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0032-1]} @ChgAdded{Version=[3],Text=[Other rules ensure that the check required by this rule cannot fail unless the function has a class-wide result subtype where the associated specific subtype is constrained. In other cases, either the subtypes have to match or the function's subtype is unconstrained and needs no checking.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Chg{Version=[2],New=[@PDefn2{Term=[execution], Sec=(simple_@!return_@!statement)}], Old=[@PDefn2{Term=[execution], Sec=(return_statement)}]} For the execution of a @Chg{Version=[2],New=[@nt{simple_@!return_@!statement}], Old=[@nt{return_statement}]}, the @nt{expression} (if any) is first evaluated@Chg{Version=[2],New=[,],Old=[ and]} converted to the result subtype@Chg{Version=[2], New=[, and then is assigned to the anonymous @i{return object}. @PDefn2{Term=[return object], Sec=(simple_@!return_@!statement)}],Old=[.]} @PDefn2{Term=[implicit subtype conversion],Sec=(function return)} @begin{Ramification} The conversion might raise Constraint_Error @em (see @RefSecNum{Type Conversions}). @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[@Redundant[If the return object has any parts that are tasks, the activation of those tasks does not occur until after the function returns (see @RefSecNum{Task Execution - Task Activation}).]], Old=[If the result type is class-wide, then the tag of the result is the tag of the value of the @nt<expression>.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is specified by the rules in @RefSecNum{Task Execution - Task Activation}.]} @end{TheProof} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Only the caller can know when task activations should take place, as it depends on the context of the call. If the function is being used to initialize the component of some larger object, then that entire object must be initialized before any task activations. Even after the outer object is fully initialized, task activations are still postponed until the @key{begin} at the end of the declarative part if the function is being used to initialize part of a declared object.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00344-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0024-1],ARef=[AI05-0032-1]} @ChgDeleted{Version=[2],Type=[Leading],Keepnext=[T],Text=[]}@ChgNote{A dummy ChgDeleted to get conditional "Leading".}If the result type @Chg{Version=[2],New=[of a function ],Old=[]}is a specific tagged type@Chg{Version=[2],New=[, the tag of the return object is that of the result type. If the result type is class-wide, the tag of the return object is that of @Chg{Version=[3],New=[the type of the @nt{subtype_indication} if it is specific, or otherwise that of ],Old=[]}the value of the @Chg{Version=[3],New=[@nt{expression}],Old=[expression]}. A check is made that the @Chg{Version=[3],New=[master],Old=[accessibility level]} of the type identified by the tag of the result @Chg{Version=[3],New=[includes the elaboration],Old=[is not deeper than that]} of the master that elaborated the function body. If this check fails, Program_Error is raised.@Defn2{Term=[Program_Error], Sec=(raised by failure of run-time check)} @IndexCheck{Accessibility_Check}],Old=[:]} @begin{Ramification} @ChgNote{Moved from after paragraph 10} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The first sentence is true even if the tag of the @nt{expression} is different, which could happen if the @nt{expression} were a view conversion or a dereference of an access value. Note that for a limited type, because of the restriction to @nt{aggregate}s and function calls (and no conversions), the tag will already match]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The first rule ensures that a function whose result type is a specific tagged type always returns an object whose tag is that of the result type. This is important for dispatching on controlling result, and allows the caller to allocate the appropriate amount of space to hold the value being returned (assuming there are no discriminants).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[The @Chg{Version=[3],New=[master ],Old=[]}check prevents the returned object from outliving its type. Note that this check cannot fail for a specific tagged type, as the tag represents the function's type, which necessarily must be declared outside of the function.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We can't use the normal accessibility level @lquotes@;deeper than@rquotes@; check here because we may have @lquotes@;incomparable@rquotes@; levels if the masters belong to two different tasks. This can happen when an accept statement calls a function declared in the enclosing task body, and the function returns an object passed to it from the accept statement, and this object was itself a parameter to the accept statement.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0073-1]} @ChgAdded{Version=[3],Text=[@IndexCheck{Tag_Check}If the result subtype of the function is defined by an @nt{access_definition} designating a specific tagged type @i<T>, a check is made that the result value is null or the tag of the object designated by the result value identifies @i<T>. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This check is needed so that dispatching on controlling access results works for tag-indeterminate functions. If it was not made, it would be possible for such functions to return an access to a descendant type, meaning the function could return an object with a tag different than the one assumed by the dispatching rules.]} @end{Reason} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 9 through 20 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[@IndexCheck{Tag_Check} If it is limited, then a check is made that the tag of the value of the return expression identifies the result type. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[If it is nonlimited, then the tag of the result is that of the result type.]} @begin{Ramification} @ChgNote{These two notes were revised and moved up} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[This is true even if the tag of the return expression is different.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[These rules ensure that a function whose result type is a specific tagged type always returns an object whose tag is that of the result type. This is important for dispatching on controlling result, and, if nonlimited, allows the caller to allocate the appropriate amount of space to hold the value being returned (assuming there are no discriminants).]} @end{Reason} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Type=[Leading],Keepnext=[T], Text=[@Defn{return-by-reference type} A type is a @i(return-by-reference) type if it is a descendant of one of the following:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a tagged limited type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a task or protected type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a nonprivate type with the reserved word @b(limited) in its declaration;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a composite type with a subcomponent of a return-by-reference type;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a private type whose full type is a return-by-reference type.]} @end(itemize) @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[ The above rules are such that there are no "Ada 83" types other than those containing tasks that are return-by-reference. This helps to minimize upward incompatibilities relating to return-by-reference.]} @end{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@IndexCheck{Accessibility_Check} If the result type is a return-by-reference type, then a check is made that the return expression is one of the following:]} @begin(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a @nt{name} that denotes an object view whose accessibility level is not deeper than that of the master that elaborated the function body; or]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00316-01]} @ChgNote{This really wasn't in the previous version, but we don't want it in a version without deletions shown...} @ChgDeleted{Version=[2],Text=[This rule was unnecessarily confusing, and the parenthetical remark "(or a value with an associated object, see 6.2)" was added @em and then the entire concept was deleted.]} @end{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[a parenthesized expression or @nt{qualified_expression} whose operand is one of these kinds of expressions.]} @end(itemize) @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00318-02]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if this check fails.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Compare the definition of return-by-reference with that of by-reference.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The return-by-reference types are all limited types except those that are limited only because of a limited private type with a nonlimited untagged full type.]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[@PDefn{generic contract issue} This check can often be performed at compile time. It is defined to be a run-time check to avoid generic contract model problems. In a future version of the standard, we anticipate that function return of a local variable will be illegal for all limited types, eliminating the need for the run-time check except for dereferences of an access parameter.]} @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0051-1]} @Chg{Version=[2], New=[If @Chg{Version=[3],New=[any part of the specific type of the return object], Old=[the result subtype]} of a function @Chg{Version=[3],New=[(or coextension thereof) ],Old=[]}has one or more @Chg{Version=[3],New=[],Old=[unconstrained ]}access discriminants@Chg{Version=[3],New=[ whose value is not constrained by the result subtype of the function],Old=[]}, a check is made that the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{expression} or the @nt{return_@!subtype_@!indication} of the @Chg{Version=[3],New=[return statement],Old=[function]}, is not deeper than @Chg{Version=[3],New=[the level of the master of the call (see @RefSecNum{Operations of Access Types})], Old=[that of the master that elaborated the function body]}. If this check fails, Program_Error is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @IndexCheck{Accessibility_Check}], Old=[For a function with a return-by-reference result type the result is returned by reference; that is, the function call denotes a constant view of the object associated with the value of the return expression. @Defn2{Term=[assignment operation], Sec=(during execution of a @nt{return_statement})} For any other function, the result is returned by copy; that is, the converted value is assigned into an anonymous constant created at the point of the @nt{return_statement}, and the function call denotes that object.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The assignment operation does the necessary value adjustment, as described in @RefSec{Assignment and Finalization}. @RefSecNum{Completion and Finalization} describes when the anonymous constant is finalized.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check prevents the returned object (for a nonlimited type) from outliving the object designated by one of its discriminants. The check is made on the values of the discriminants, which may come from the @nt{return_@!subtype_@!indication} (if constrained), or the @nt{expression}, but it is never necessary to check both.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[The reason for saying @ldquote@;any part of the specific type@rdquote is to simplify implementation. In the case of class-wide result objects, this allows the testing of a simple flag in the tagged type descriptor that indicates whether the specific type has any parts with access discriminants. By basing the test on the type of the object rather than the object itself, we avoid concerns about whether subcomponents in variant parts and of arrays (which might be empty) are present.]} @end{ImplNote} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[For a function with a class-wide result type, the access values that need to be checked are determined by the tag of the return object. In order to implement this accessibility check in the case where the tag of the result is not known statically at the point of the return statement, an implementation may need to somehow associate with the tag of a specific tagged type an indication of whether the type has unconstrained access discriminants (explicit or inherited) or has any subcomponents with such discriminants. If an implementation is already maintaining a statically initialized descriptor of some kind for each specific tagged type, then an additional Boolean could be added to this descriptor.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[Note that the flag should only be queried in the case where the result object might have access discriminants that might have subtypes with "bad" accessibility levels (as determined by the rules of @RefSecNum{Operations of Access Types} for determining the accessibility level of the type of an access discriminant in the @nt{expression} or @nt{return_subtype_indication} of a return statement).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Thus, in a case like]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[type] Global @key[is access] T'Class; @key[function] F (Ptr : Global) @key[return] T'Class @key[is] @key[begin] @key[return] Ptr.@key[all]; @key[end] F;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[there is no need for a run-time accessibility check. While an object of T'Class "might have" access discriminants, the accessibility of those potential discriminants cannot be bad. The setting of the bit doesn't matter and there is no need to query it.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[On the other hand, given]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] F @key[return] T'Class @key[is] Local : T'Class := ... ; @key[begin] @key[return] Local; @key[end] F;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[In this case, a check would typically be required.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The need for including subcomponents in this check is illustrated by the following example:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[X : @key[aliased] Integer;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[type] Component_Type (Discrim : @key[access] Integer := X'Access) @key[is limited null record];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[type] Undiscriminated @key[is record] Fld : Component_Type; @key[end record];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] F @key[return] Undiscriminated @key[is] Local : @key[aliased] Integer; @key[begin] @key[return] X : Undiscriminated := (Fld => (Discrim => Local'Access)) @key[do] Foo; @key[end return]; --@Examcom{ raises Program_Error after calling Foo.} @key[end] F;]} @end{Example} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[In the case where the tag of the result is not known statically at the point of the return statement and the run-time accessibility check is needed, discriminant values and array bounds play no role in performing this check. That is, array components are assumed to have nonzero length and components declared within variant parts are assumed to be present. Thus, the check may be implemented simply by testing the aforementioned descriptor bit and conditionally raising Program_Error.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0058-1]} @Chg{Version=[2],New=[For the execution of an @nt{extended_@!return_@!statement}, the @nt{handled_@!sequence_@!of_@!statements} is executed. Within this @nt{handled_@!sequence_@!of_@!statements}, the execution of a @nt{simple_@!return_@!statement} that applies to the @nt{extended_@!return_@!statement} causes a transfer of control that completes the @nt{extended_@!return_@!statement}. Upon completion of a return statement that applies to a callable construct@Chg{Version=[3], New=[ by the normal completion of a @nt{simple_@!return_@!statement} or by reaching the @key[end return] of an @nt{extended_@!return_@!statement}], Old=[]}],Old=[Finally]}, a transfer of control is performed which completes the execution of the callable construct@Chg{Version=[2],New=[], Old=[ to which the @nt{return_@!statement} applies]}, and returns to the caller. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0058-1]} @ChgAdded{Version=[3],Text=[A transfer of control that completes an @nt{extended_return_statement} (such as an exit or goto) does not cause a return to the caller unless it is caused by @nt{simple_return_statement} (that is, triggers the second sentence of this paragraph). The return to the caller occurs for the @nt{simple_return_statement} that applies to an @nt{extended_return_statement} because the last sentence says @ldquote@;the normal completion of a @nt{simple_return_statement}@rdquote@;, which includes the one nested in the @nt{extended_return_statement}.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[In the case of a function, the @nt{function_call} denotes a constant view of the return object.]} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{This is a fake used to provide a conditional leading.} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[For a function call used to initialize a composite],Old=[If the result subtype of a function is unconstrained, and a call on the function is used to provide the initial value of an]} object with a constrained nominal subtype@Chg{Version=[3],New=[ or used to initialize a return object that is built in place into such an object:],Old=[, Constraint_Error may be raised at the point of the call (after abandoning the execution of the function body) if, while elaborating the @nt{return_@!subtype_@!indication} or evaluating the @nt{expression} of a return statement that applies to the function body, it is determined that the value of the result will violate the constraint of the subtype of this object.]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Text=[If the result subtype of the function is constrained, and conversion of an object of this subtype to the subtype of the object being initialized would raise Constraint_Error, then Constraint_Error may be raised before calling the function.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Text=[If the result subtype of the function is unconstrained, and a return statement is executed such that the return object is known to be constrained, and conversion of the return object to the subtype of the object being initialized would raise Constraint_Error, then Constraint_Error may be raised at the point of the call (after abandoning the execution of the function body).]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0050-1]} @ChgAdded{Version=[2],Text=[Without such a permission, it would be very difficult to implement @lquotes@;@Chg{Version=[3],New=[built-in-place],Old=[build-in-place]}@rquotes semantics. @Chg{Version=[3],New=[The intention is that the exception is raised at the same point that it would have been raised without the permission; it should not change handlers if the implementation switches between return-by-copy and built-in-place. This means that the],Old=[Such an]} exception is not handleable within the function, because in the return-by-copy case, the constraint check to verify that the result satisfies the constraints of the object being initialized happens after the function returns@Chg{Version=[3],New=[],Old=[, and we want the semantics to change as little as possible when switching between return-by-copy and build-in-place]}. This implies further that upon detecting such a situation, the implementation may need to simulate a goto to a point outside any local exception handlers prior to raising the exception.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0050-1]} @Chg{Version=[3],New=[These permissions do not apply in the case of an extended return object with mutable discriminants. That's necessary because in that case a return object can be created with the @ldquote@;wrong@rdquote discriminants and then changed to the @ldquote@;right@rdquote discriminants later (but before returning). We don't want this case raising an exception when the canonical semantics will not do so.],Old=[@Chg{Version=[2],New=[This permission is allowed during the evaluation of the @nt{expression} of an @nt{extended_return_statement}, because the @nt{return_@!subtype_@!indication} may be unconstrained and the @nt{expression} then would provide the constraints.],Old=[]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Text=[It's still possible to write a program that will raise an exception using this permission that would not in the canonical semantics. That could happen if a return statement with the @ldquote@;wrong@rdquote discriminants or bounds is abandoned (via an exception, or for an extended_return_statement, via an exit or goto statement), and then a return statement with the @ldquote@;right@rdquote discriminants or bounds is executed. The only solution for this problem is to not have the permission at all, but this is too unusual of a case to worry about the effects of the permission, especially given the implementation difficulties for built-in-place objects that this permission is intended to ease.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Text=[Note that the mutable-discriminant case only happens when built-in-place initialization is optional. This means that any difficulties associated with implementing built-in-place initialization without these permissions can be sidestepped by not building in place.]} @end{Ramification} @end{ImplPerm} @begin{Examples} @leading@keepnext@i{Examples of return statements:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @key[return]; --@ExamCom{ in a procedure body, }@nt{entry_body}@ExamCom{,}@Chg{Version=[2],New=[ -- @nt{accept_statement}@ExamCom{, or }@nt{extended_return_statement}],Old=[@ExamCom{ or }@nt{accept_statement}]} @key[return] Key_Value(Last_Index); --@ExamCom{ in a function body} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @Chg{Version=[2],New=<@key[return] Node : Cell @key{do} --@ExamCom{ in a function body, see @RefSecNum{Incomplete Type Declarations} for Cell} Node.Value := Result; Node.Succ := Next_Node; @key{end} @key{return};>,Old=<>} @end{Example} @end{Examples} @begin{Incompatible83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{incompatibilities with Ada 83} In Ada 95, if the result type of a function has a part that is a task, then an attempt to return a local variable will raise Program_Error. @Chg{Version=[2],New=[This is illegal in Ada 2005, see below. ], Old=[]}In Ada 83, if a function returns a local variable containing a task, execution is erroneous according to AI83-00867. However, there are other situations where functions that return tasks (or that return a variant record only one of whose variants includes a task) are correct in Ada 83 but will raise Program_Error according to the new rules. The rule change was made because there will be more types (protected types, limited controlled types) in Ada 95 for which it will be meaningless to return a local variable, and making all of these erroneous is unacceptable. The current rule was felt to be the simplest that kept upward incompatibilities to situations involving returning tasks, which are quite rare. @end{Incompatible83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} has been moved here from chapter 5, since it has mainly to do with subprograms. A function now creates an anonymous object. This is necessary so that controlled types will work. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} We have clarified that a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} applies to a callable construct, not to a callable entity. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} There is no need to mention generics in the rules about where a @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} can appear and what it applies to; the phrase @lquotes@;body of a subprogram or generic subprogram@rquotes@; is syntactic, and refers exactly to @lquotes@;@nt{subprogram_body}@rquotes@;. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-0416-1]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0005-1],ARef=[AI05-0050-1]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} Added an @ImplPermName allowing early raising of Constraint_Error if the result cannot fit in the ultimate object. This gives implementations more flexibility to do built-in-place returns, and is essential for limited types (which cannot be built in a temporary). However, it allows raising @Chg{Version=[3],New=[],Old=[an ]} Constraint_Error in some cases where it would not be raised if the permission was not used. @Chg{Version=[3],New=[See @Inconsistent2005Title for additional changes. ],Old=[]}This case is potentially inconsistent with Ada 95, but a compiler does not have to take advantage of these permissions for any Ada 95 code, so there should be little practical impact.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The entire business about return-by-reference types has been dropped. Instead, the @nt{expression} of a return statement of a limited type can only be an @nt{aggregate} or @nt{function_call} (see @RefSecNum{Limited Types}). This means that returning a global object or @nt{type_conversion}, legal in Ada 95, is now illegal. Such functions can be converted to use anonymous access return types by adding @key{access} in the function definition and return statement, adding .@key{all} in uses, and adding @key{aliased} in the object declarations. This has the advantage of making the reference return semantics much clearer to the casual reader.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We changed these rules so that functions, combined with the new rules for limited types (@RefSecnum{Limited Types}), can be used as build-in-place constructors for limited types. This reduces the differences between limited and nonlimited types, which will make limited types useful in more circumstances.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{extended_return_statement} is new. This provides a name for the object being returned, which reduces the copying needed to return complex objects (including no copying at all for limited objects). It also allows component-by-component construction of the return object.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The wording was updated to support anonymous access return subtypes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[The term @lquotes@;return expression@rquotes@; was dropped because reviewers found it confusing when applied to the default @nt{expression} of an @nt{extended_return_statement}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to class-wide return statements. These checks could not fail in Ada 95 (as all of the types had to be declared at the same level, so the tagged type would necessarily have been at the same level as the type of the object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00402-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added accessibility checks to return statements for types with access discriminants. Since such types have to be limited in Ada 95, the @nt{expression} of a return statement would have been illegal in order for this check to fail.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0050-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} @b<Correction:> The @ImplPermName allowing early raising of Constraint_Error was modified to remove the most common of these cases from the permission (returning an object with mutable discriminants, where the return object is created with one set of discriminants and then changed to another). (The permission was also widened to allow the early check for constrained functions when that constraint is wrong.) However, there still is an unlikely case where the permission would allow an exception to be raised when none would be raised by the canonical semantics (when a return statement is abandoned). These changes can only remove the raising of an exception (or change the place where it is raised) compared to Ada 2005, so programs that depend on the previous behavior should be very rare.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0051-1],ARef=[AI05-0234-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Accessibility checks for access discriminants now depend on the master of the call rather than the point of declaration of the function. This will result in cases that used to raise Program_Error now running without raising any exception. This is technically inconsistent with Ada 2005 (as defined by Amendment 1), but it is unlikely that any real code depends on the raising of this exception.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0073-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a tag check for functions returning anonymous access-to-tagged types, so that dispatching of tag-indeterminate function works as expected. This is technically inconsistent with Ada 2005 (as defined by Amendment 1), but as the feature in question was newly added to Ada 2005, there should be little code that depends on the behavior that now raises an exception.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0053-1],ARef=[AI05-0277-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> The @key{aliased} keyword can now only appear on extended return objects with an immutably limited type. Other types would provide a way to get an aliased view of an object that is not necessarily aliased, which would be very bad. This is incompatible, but since the feature was added in Ada 2005, the keyword had no defined meaning in Ada 2005 (a significant oversight), and most sensible uses involve immutably limited types, it is unlikely that it appears meaningfully in existing programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0103-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to require static matching for unconstrained access types in extended return statements. This disallows adding or omitting null exclusions, and adding access constraints, in the declaration of the return object. While this is incompatible, the incompatible cases in question are either useless (access constraints @en the constraint can be given on an @nt{allocator} if necessary, and still must be given there even if given on the return object) or wrong (null exclusions @en null could be returned from a function declared to be null excluding), so we expect them to be extremely rare in practice.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0015-1],ARef=[AI05-0144-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The return object of an @nt{extended_return_statement} can be declared constant; this works similarly to a constant object declaration.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0032-1]} @ChgAdded{Version=[3],Text=[Added wording to allow the @nt{return_subtype_indication} to have a specific type if the return subtype of the function is class-wide. Specifying the (specific) type of the return object is awkward without this change, and this is consistent with the way @nt{allocator}s work.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0024-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the master check for tags since the masters may be for different tasks and thus incomparable.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0058-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the wording defining returns for @nt{extended_return_statement}s, since leaving by an exit or goto is considered @ldquote@;normal@rdquote completion of the statement.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0205-1],ARef=[AI05-0277-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added the @nt{extended_return_object_declaration} to make other rules easier to write and eliminate the problem described in AI05-0205-1.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledRevisedSubClause{Version=[3],InitialVersion=[2],New=[Nonreturning Procedures],Old=[Pragma No_Return]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[Specifying aspect],Old=[A @nt{pragma}]} No_Return @Chg{Version=[3],New=[to have the value True ],Old=[]}indicates that a procedure cannot return normally@Redundant[; it may propagate an exception or loop forever].]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[Aspect],Old=[@nt{Pragma}]} No_Deposit@Defn{No_Deposit aspect} will have to wait for Ada @Chg{Version=[3],New=[2020],Old=[2017]}. :-)]} @end{Discussion} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 and 3 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[],Old=[The form of a @nt{pragma} No_Return, which is a representation pragma (see @RefSecNum{Operational and Representation Aspects}), is as follows:]}]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn{Version=[3],InitialVersion=[2],@ChgAdded{Version=[2], Text=`@Chg{Version=[3],New=[],Old=[@key{pragma} @prag<No_Return>(@SynI{procedure_}@Syn2{local_name}{, @SynI{procedure_}@Syn2{local_name}});]}'}} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a procedure or generic procedure, the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[No_Return@\The type of aspect No_Return is Boolean. When aspect No_Return is True for an entity, the entity is said to be @i<nonreturning>.@Defn{nonreturning}@AspectDefn{No_Return}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If directly specified, the @nt{aspect_definition} shall be a static expression. @Redundant[This aspect is never inherited;] if not directly specified, the aspect is False.]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[No_Return], Text=[@ChgAdded{Version=[3],Text=[A procedure will not return normally.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]}@ChgNote{Moved from below} @ChgAdded{Version=[3],Text=[If a generic procedure is nonreturning, then so are its instances. If a procedure declared within a generic unit is nonreturning, then so are the corresponding copies of that procedure in instances.]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[Aspect No_Return], Old=[@Defn{nonreturning}Each @SynI{procedure_}@nt{local_name} shall denote one or more procedures or generic procedures; the denoted entities are @i<nonreturning>. The @SynI{procedure_}@nt{local_name}]} shall not @Chg{Version=[3],New=[be specified for],Old=[denote]} a null procedure nor an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A null procedure cannot have the appropriate nonreturning semantics, as it does not raise an exception or loop forever.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[The procedure can be abstract.@Chg{Version=[3],New=[], Old=[ The denoted declaration can be a @nt{renaming_declaration} if it obeys the usual rules for representation pragmas: the renaming has to occur immediately within the same declarative region as the renamed subprogram.]} If a nonreturning procedure is renamed (anywhere) calls through the new name still have the nonreturning semantics.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[A return statement shall not apply to a nonreturning procedure or generic procedure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[A procedure shall be nonreturning if it overrides a dispatching nonreturning procedure. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that dispatching calls to nonreturning procedures will, in fact, not return.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[If a renaming-as-body completes a nonreturning procedure declaration, then the renamed procedure shall be nonreturning.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This ensures that no extra code is needed to implement the renames (that is, no wrapper is needed) as the body has the same property.]} @end{Reason} @end{Legality} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraph 8 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.}@ChgNote{This special message is needed to get rid of the old, now unused, subheader} @end{NotIso} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[If a generic procedure is nonreturning, then so are its instances. If a procedure declared within a generic unit is nonreturning, then so are the corresponding copies of that procedure in instances.]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[If the body of a nonreturning procedure completes normally, Program_Error is raised at the point of the call. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{RunTime} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that there is no name for suppressing this check, since the check represents a bug, imposes no time overhead, and minimal space overhead (since it can usually be statically eliminated as dead code).]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a nonreturning procedure tries to return, we raise Program_Error. This is stated as happening at the call site, because we do not wish to allow the procedure to handle the exception (and then, perhaps, try to return again!). However, the expected run-time model is that the compiler will generate @key{raise} Program_Error at the end of the procedure body (but not handleable by the procedure itself), as opposed to doing it at the call site. (This is just like the typical run-time model for functions that fall off the end without returning a value). The reason is indirect calls: in P.@key{all}(...);, the compiler cannot know whether P designates a nonreturning procedure or a normal one. Putting the @key{raise} Program_Error in the procedure's generated code solves this problem neatly.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Similarly, if one passes a nonreturning procedure to a generic formal parameter, the compiler cannot know this at call sites (in shared code implementations); the raise-in-body solution deals with this neatly.]} @end{ImplNote} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@key(procedure) Fail(Msg : String)@Chg{Version=[3],New=[],Old=[;]} --@ExamCom[ raises Fatal_Error exception] @Chg{Version=[3],New=[ @key(with)],Old=[@key(pragma)]} No_Return@Chg{Version=[3],New=[],Old=[(Fail)]}; --@ExamCom[ Inform compiler and reader that procedure never returns normally]]} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00329-01],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} No_Return is new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect No_Return is new; @nt{pragma} No_Return is now obsolescent.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Overloading of Operators} @begin{Intro} @Defn{operator} @Defn{user-defined operator} @Defn2{Term=[operator], Sec=(user-defined)} An @i{operator} is a function whose @nt{designator} is an @nt<operator_symbol>. @Redundant[Operators, like other functions, may be overloaded.] @end{Intro} @begin{Resolution} Each use of a unary or binary operator is equivalent to a @nt{function_call} with @SynI{function_}@nt{prefix} being the corresponding @nt{operator_symbol}, and with (respectively) one or two positional actual parameters being the operand(s) of the operator (in order). @begin{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We also use the term operator (in @Chg{Version=[3],New=[Clause],Old=[Section]} 4 and in @RefSecNum{Subprogram Declarations}) to refer to one of the syntactic categories defined in @RefSec{Operators and Expression Evaluation} whose names end with @lquotes@;_operator:@rquotes@; @nt<logical_@!operator>, @nt<relational_@!operator>, @nt<binary_@!adding_@!operator>, @nt<unary_@!adding_@!operator>, @nt<multiplying_@!operator>, and @nt<highest_@!precedence_@!operator>. @end{Honest} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This equivalence extends to uses of @nt{function_call} in most other language rules. However, as often happens, the equivalence is not perfect, as operator calls are not a @nt{name}, while a @nt{function_call} is a @nt{name}. Thus, operator calls cannot be used in contexts that require a @nt{name} (such as a rename of an object). A direct fix for this problem would be very disruptive, and thus we have not done that. However, qualifying an operator call can be used as a workaround in contexts that require a @nt{name}.]} @end{Discussion} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0143-1]} The @nt{subprogram_specification} of a unary or binary operator shall have one or two parameters, respectively.@Chg{Version=[3],New=[ The parameters shall be of mode @key[in].],Old=[]} A generic function instantiation whose @nt{designator} is an @nt{operator_symbol} is only allowed if the specification of the generic function has the corresponding number of parameters@Chg{Version=[3],New=[, and they are all of mode @key[in]],Old=[]}. @nt{Default_expression}s are not allowed for the parameters of an operator (whether the operator is declared with an explicit @nt{subprogram_specification} or by a @nt{generic_instantiation}). An explicit declaration of "/=" shall not have a result type of the predefined type Boolean. @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0128-1]} @Chg{Version=[3],New=[An explicit],Old=[A]} declaration of "=" whose result type is Boolean implicitly declares @Chg{Version=[3],New=[an operator],Old=[a declaration of]} "/=" that gives the complementary result.@Defn{/= operator} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0128-1]} @ChgAdded{Version=[3],Text=[A "/=" defined by this rule is considered user-defined, which means that it will be inherited by a derived type. @ldquote@;User-defined@rdquote means @ldquote@;not language-defined@rdquote for the purposes of inheritance, that is anything other than predefined operators. @Defn{Number of the Beast}@Comment{This is 6.6(6) :-)}]} @end{Discussion} @end{StaticSem} @begin{Notes} The operators "+" and "@en@;" are both unary and binary operators, and hence may be overloaded with both one- and two-parameter functions. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of user-defined operators:} @begin{Example} @key[function] "+" (Left, Right : Matrix) @key[return] Matrix; @key[function] "+" (Left, Right : Vector) @key[return] Vector; @Comment{Blank line} --@ExamCom{ assuming that A, B, and C are of the type Vector} --@ExamCom{ the following two statements are equivalent:} @Comment{Blank line} A := B + C; A := "+"(B, C); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Explicit declarations of "=" are now permitted for any combination of parameter and result types. Explicit declarations of "/=" are now permitted, so long as the result type is not Boolean. @end{Extend83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0128-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the wording so that only explicit declarations of "=" cause an implicit declaration of "/="; otherwise, we could get multiple implicit definitions of "/=" without an obvious way to chose between them.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0143-1]} @ChgAdded{Version=[3],Text=[Added wording so that operators only allow parameters of mode @key[in]. This was made necessary by the elimination elsewhere of the restriction that function parameters be only of mode @key[in].]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedClause{Version=[2],Name=[Null Procedures]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A @nt<null_procedure_declaration> provides a shorthand to declare a procedure with an empty body.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<null_procedure_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] @Syn2{procedure_specification} @key{is} @key{null}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[If a @nt{null_procedure_declaration} is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of a @nt{null_procedure_declaration} that completes a declaration shall conform fully to that of the declaration.@Defn2{Term=[full conformance],Sec=(required)}]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[A @nt<null_procedure_declaration> declares a @i<null procedure>.@Defn{null procedure}@Defn2{Term=[procedure],Sec=[null]} A completion is not allowed for a @nt<null_procedure_declaration>@Chg{Version=[3],New=[; however, a @nt{null_procedure_declaration} can complete a previous declaration],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no null functions because the return value has to be constructed somehow; a function that always raises Program_Error doesn't seem very useful or worth the complication.]} @end{Reason} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[The execution of a null procedure is invoked by a subprogram call. For the execution of a subprogram call on a null procedure, the execution of the @nt<subprogram_body> has no effect.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, a null procedure is equivalent to the body]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{begin} @key{null}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[with the exception that a null procedure can be used in place of a procedure specification.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[elaboration], Sec=(null_procedure_declaration)} The elaboration of a @nt{null_procedure_declaration} has no @Chg{Version=[3],New=[other ],Old=[]}effect@Chg{Version=[3],New=[ than to establish that the null procedure can be called without failing the Elaboration_Check],Old=[]}.]} @end{RunTime} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(procedure) Simplify(Expr : @key(in out) Expression) @key(is null); --@ExamCom[ see @RefSecNum{Tagged Types and Type Extensions}] --@ExamCom[ By default, Simplify does nothing, but it may be overridden in extensions of Expression]]} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Null procedures are new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} A @nt{null_procedure_declaration} can now be a completion.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[An optional @nt{aspect_specification} can be used in a @nt{null_procedure_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedClause{Version=[3],Name=[Expression Functions]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[An @nt{expression_function_declaration} provides a shorthand to declare a function whose body consists of a single return statement.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0177-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<expression_function_declaration>,Old=<>}>, rhs="@Chg{Version=[3],New=< [@Syn2{overriding_indicator}] @Syn2{function_specification} @key{is} (@Syn2{expression}) [@Syn2{aspect_specification}];>,Old=<>}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} of an @nt{expression_@!function_@!declaration} is the result type (see @RefSecNum{Return Statements}) of the function.@PDefn2{Term=[expected type], Sec=(expression of expression function)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[If an @nt{expression_@!function_@!declaration} is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of an @nt{expression_@!function_@!declaration} that completes a declaration shall conform fully to that of the declaration.@Defn2{Term=[full conformance],Sec=(required)}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the @nt{expression} of the expression function, shall not be statically deeper than that of the master that elaborated the @nt{expression_@!function_@!declaration}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This can only fail if the discriminant is an access to a part of a non-aliased parameter, as there can be no local declarations here.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We don't need to repeat any of the other @LegalityTitle for return statements since none of them can fail here: the implicit return statement has to apply to this function (and isn't nested in something), there clearly is a return statement in this function, and the static classwide accessibility check cannot fail as a tagged type cannot be declared locally in an expression function.]} @end{Discussion} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[An @nt{expression_@!function_@!declaration} declares an @i{expression function}.@Defn{exception function}@Defn2{Term=[function],Sec=[expression]} A completion is not allowed for an @nt{expression_@!function_@!declaration}; however, an @nt{expression_@!function_@!declaration} can complete a previous declaration.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[ The execution of an expression function is invoked by a subprogram call. For the execution of a subprogram call on an expression function, the execution of the @nt{subprogram_body} executes an implicit function body containing only a @nt{simple_return_statement} whose @nt{expression} is that of the expression function.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The last sentence effectively means that all of the dynamic wording in @RefSecNum{Return Statements} applies as needed, and we don't have to repeat it here.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[elaboration], Sec=(expression_function_declaration)}The elaboration of an @nt{expression_@!function_@!declaration} has no other effect than to establish that the expression function can be called without failing the Elaboration_Check.]} @end{RunTime} @begin{Examples} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@key(function) Is_Origin (P : @key[in] Point) @key[return] Boolean @key[is] -- @Examcom[see @RefSecNum{Tagged Types and Type Extensions}] (P.X = 0.0 @key[and] P.Y = 0.0);]} @end{Example} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Expression functions are new in Ada 2012.]} @end{Extend2005} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/07.mss���������������������������������������������������������������0000755�0001752�0001001�00000640334�12066652506�016411� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(07, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @LabeledSection{Packages} @Comment{$Source: e:\\cvsroot/ARM/Source/07.mss,v $} @Comment{$Revision: 1.130 $} @begin{Intro} @redundant[@ToGlossaryAlso{Term=<Package>, Text=<Packages are program units that allow the specification of groups of logically related entities. Typically, a package contains the declaration of a type (often a private type or private extension) along with the declarations of primitive subprograms of the type, which can be called from outside the package, while their inner workings remain hidden from outside users.>} @IndexSee{Term=[information hiding],See=(package)} @IndexSee{Term=[encapsulation],See=(package)} @IndexSee{Term=[module],See=(package)} @IndexSeeAlso{Term=[class],See=(package)}] @end{Intro} @LabeledClause{Package Specifications and Declarations} @begin{Intro} @redundant[A package is generally provided in two parts: a @nt{package_specification} and a @nt{package_body}. Every package has a @nt{package_specification}, but not all packages have a @nt{package_body}.] @end{Intro} @begin{Syntax} @Syn{lhs=<package_declaration>,rhs="@Syn2{package_specification};"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<package_specification>,rhs=" @key{package} @Syn2{defining_program_unit_name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is} {@Syn2{basic_declarative_item}} [@key{private} {@Syn2{basic_declarative_item}}] @key{end} [[@Syn2{parent_unit_name}.]@Syn2{identifier}]"} @begin{SyntaxText} If an @nt{identifier} or @nt{parent_unit_name}.@nt{identifier} appears at the end of a @nt{package_specification}, then this sequence of lexical elements shall repeat the @nt{defining_program_unit_name}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @PDefn2{Term=[requires a completion], Sec=(@nt{package_declaration})} @PDefn2{Term=[requires a completion], Sec=(@nt{generic_package_declaration})} A @nt{package_declaration} or @nt{generic_package_declaration} requires a completion @Redundant[(a body)] if it contains any @Chg{Version=[2],New=[@nt{basic_declarative_item}], Old=[@nt<declarative_item>]} that requires a completion, but whose completion is not in its @nt{package_specification}. @begin(Honest) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If an implementation supports it,@Chg{Version=[3],New=[],Old=[ a @nt{pragma} Import may substitute for]} the body of a package or generic package@Chg{Version=[3],New=[ may be imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no explicit body is allowed],Old=[]}. @end(Honest) @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00420-01],ARef=[AI95-00434-01]} @PDefn2{Term=[visible part], Sec=<of a package (other than a generic formal package)>} The first list of @Chg{Version=[2],New=[@nt{basic_declarative_item}s], Old=[@nt{declarative_item}s]} of a @nt{package_specification} of a package other than a generic formal package is called the @i{visible part} of the package. @Redundant[@PDefn2{Term=[private part], Sec=(of a package)} The optional list of @Chg{Version=[2],New=[@nt{basic_declarative_item}s], Old=[@nt{declarative_item}s]} after the reserved word @key{private} (of any @nt{package_specification}) is called the @i{private part} of the package. If the reserved word @key{private} does not appear, the package has an implicit empty private part.]@Chg{Version=[2],New=[ Each list of @nt{basic_declarative_item}s of a @nt{package_specification} forms a @i{declaration list} of the package.@PDefn2{Term=[declaration list],Sec=(package_specification)}],Old=[]} @begin{Ramification} This definition of visible part does not apply to generic formal packages @em @RefSecNum{Formal Packages} defines the visible part of a generic formal package. The implicit empty private part is important because certain implicit declarations occur there if the package is a child package, and it defines types in its visible part that are derived from, or contain as components, private types declared within the parent package. These implicit declarations are visible in children of the child package. See @RefSecNum(Compilation Units - Library Units). @end{Ramification} @redundant[An entity declared in the private part of a package is visible only within the declarative region of the package itself (including any child units @em see @RefSecNum{Compilation Units - Library Units}). In contrast, expanded names denoting entities declared in the visible part can be used even outside the package; furthermore, direct visibility of such entities can be achieved by means of @nt{use_clause}s (see @RefSecNum{Selected Components} and @RefSecNum{Use Clauses}).] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(package_declaration)} The elaboration of a @nt{package_declaration} consists of the elaboration of its @nt{basic_declarative_item}s in the given order. @end{RunTime} @begin{Notes} The visible part of a package contains all the information that another program unit is able to know about the package. If a declaration occurs immediately within the specification of a package, and the declaration has a corresponding completion that is a body, then that body has to occur immediately within the body of the package. @begin{TheProof} This follows from the fact that the declaration and completion are required to occur immediately within the same declarative region, and the fact that @ntf{bodies} are disallowed (by the @SyntaxName@;s) in @nt{package_specification}s. This does not apply to instances of generic units, whose bodies can occur in @nt{package_specification}s. @end{TheProof} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package declaration:} @begin{Example} @key[package] Rational_Numbers @key[is] @key[type] Rational @key[is] @key[record] Numerator : Integer; Denominator : Positive; @key[end] @key[record]; @key[function] "="(X,Y : Rational) @key[return] Boolean; @key[function] "/" (X,Y : Integer) @key[return] Rational; --@RI{ to construct a rational number} @key[function] "+" (X,Y : Rational) @key[return] Rational; @key[function] "-" (X,Y : Rational) @key[return] Rational; @key[function] "*" (X,Y : Rational) @key[return] Rational; @key[function] "/" (X,Y : Rational) @key[return] Rational; @key[end] Rational_Numbers; @end{Example} There are also many examples of package declarations in the predefined language environment (see @RefSecNum{Predefined Language Environment}). @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} In Ada 83, a library package is allowed to have a body even if it doesn't need one. In Ada 95, a library package body is either required or forbidden @em never optional. The workaround is to add @key[pragma] Elaborate_Body, or something else requiring a body, to each library package that has a body that isn't otherwise required. @end{Incompatible83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We have moved the syntax into this @Chg{Version=[3],New=[subclause],Old=[clause]} and the next @Chg{Version=[3],New=[subclause],Old=[clause]} from RM83-7.1, @lquotes@;Package Structure@rquotes@;, which we have removed. RM83 was unclear on the rules about when a package requires a body. For example, RM83-7.1(4) and RM83-7.1(8) clearly forgot about the case of an incomplete type declared in a @nt{package_declaration} but completed in the body. In addition, RM83 forgot to make this rule apply to a generic package. We have corrected these rules. Finally, since we now allow a @nt{pragma} Import for any explicit declaration, the completion rules need to take this into account as well. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00420-01]} @ChgAdded{Version=[2],Text=[Defined @lquotes@;declaration list@rquotes to avoid ambiguity in other rules as to whether packages are included.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{package_specification}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledClause{Package Bodies} @begin{Intro} @redundant[In contrast to the entities declared in the visible part of a package, the entities declared in the @nt{package_body} are visible only within the @nt{package_body} itself. As a consequence, a package with a @nt{package_body} can be used for the construction of a group of related subprograms in which the logical operations available to clients are clearly isolated from the internal entities.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0267-1]} @Syn{lhs=<package_body>,rhs=" @key{package} @key{body} @Syn2{defining_program_unit_name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is} @Syn2{declarative_part} [@key{begin} @Syn2{handled_sequence_of_statements}] @key{end} [[@Syn2{parent_unit_name}.]@Syn2{identifier}];"} @begin{SyntaxText} If an @nt{identifier} or @nt{parent_unit_name}.@nt{identifier} appears at the end of a @nt{package_body}, then this sequence of lexical elements shall repeat the @nt{defining_program_unit_name}. @end{SyntaxText} @end{Syntax} @begin{Legality} A @nt{package_body} shall be the completion of a previous @nt{package_@!declaration} or @nt{generic_@!package_@!declaration}. A library @nt{package_@!declaration} or library @nt{generic_@!package_@!declaration} shall not have a body unless it requires a body@Redundant[; @key<pragma> Elaborate_Body can be used to require a @nt<library_@!unit_@!declaration> to have a body (see @RefSecNum{Elaboration Control}) if it would not otherwise require one]. @begin{Ramification} The first part of the rule forbids a @nt{package_body} from standing alone @em it has to belong to some previous @nt{package_declaration} or @nt{generic_package_declaration}. A nonlibrary @nt{package_declaration} or nonlibrary @nt<generic_package_declaration> that does not require a completion may have a corresponding body anyway. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} In any @nt{package_body} without @nt{statement}s there is an implicit @nt{null_@!statement}. For any @nt{package_@!declaration} without an explicit completion, there is an implicit @nt{package_@!body} containing a single @nt{null_statement}. For a noninstance, nonlibrary package, this body occurs at the end of the @nt{declarative_@!part} of the innermost enclosing program unit or @nt{block_@!statement}; if there are several such packages, the order of the implicit @ntf{package_@!bodies} is unspecified. @PDefn{unspecified} @Redundant[(For an instance, the implicit @nt{package_@!body} occurs at the place of the instantiation (see @RefSecNum{Generic Instantiation}). For a library package, the place is partially determined by the elaboration dependences (see @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Program Structure and Compilation Issues}).)] @begin{Discussion} Thus, for example, we can refer to something happening just after the @key{begin} of a @nt{package_body}, and we can refer to the @nt{handled_sequence_of_statements} of a @nt{package_body}, without worrying about all the optional pieces. The place of the implicit body makes a difference for tasks activated by the package. See also RM83-9.3(5). The implicit body would be illegal if explicit in the case of a library package that does not require (and therefore does not allow) a body. This is a bit strange, but not harmful. @end{Discussion} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(nongeneric package_body)} For the elaboration of a nongeneric @nt{package_body}, its @nt{declarative_@!part} is first elaborated, and its @nt{handled_@!sequence_of_@!statements} is then executed. @end{RunTime} @begin{Notes} A variable declared in the body of a package is only visible within this body and, consequently, its value can only be changed within the @nt{package_body}. In the absence of local tasks, the value of such a variable remains unchanged between calls issued from outside the package to subprograms declared in the visible part. The properties of such a variable are similar to those of a @lquotes@;static@rquotes@; variable of C. The elaboration of the body of a subprogram explicitly declared in the visible part of a package is caused by the elaboration of the body of the package. Hence a call of such a subprogram by an outside program unit raises the exception Program_Error if the call takes place before the elaboration of the @nt{package_body} (see @RefSecNum{Declarative Parts}). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package body (see @RefSecNum{Package Specifications and Declarations}):} @begin{Example} @key[package] @key[body] Rational_Numbers @key[is] @key[procedure] Same_Denominator (X,Y : @key[in] @key[out] Rational) @key[is] @key[begin] --@RI{ reduces X and Y to the same denominator:} ... @key[end] Same_Denominator; @key[function] "="(X,Y : Rational) @key[return] Boolean @key[is] U : Rational := X; V : Rational := Y; @key[begin] Same_Denominator (U,V); @key[return] U.Numerator = V.Numerator; @key[end] "="; @key[function] "/" (X,Y : Integer) @key[return] Rational @key[is] @key[begin] @key[if] Y > 0 @key[then] @key[return] (Numerator => X, Denominator => Y); @key[else] @key[return] (Numerator => -X, Denominator => -Y); @key[end] @key[if]; @key[end] "/"; @key[function] "+" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "+"; @key[function] "-" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "-"; @key[function] "*" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "*"; @key[function] "/" (X,Y : Rational) @key[return] Rational @key[is] ... @key[end] "/"; @key[end] Rational_Numbers; @end{Example} @end{Examples} @begin{DiffWord83} The syntax rule for @nt{package_body} now uses the syntactic category @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{package_body} is now required; that doesn't make any real difference, since a @nt{declarative_part} can be empty. RM83 seems to have forgotten to say that a @nt{package_body} can't stand alone, without a previous declaration. We state that rule here. RM83 forgot to restrict the definition of elaboration of @ntf{package_bodies} to nongeneric ones. We have corrected that omission. The rule about implicit bodies (from RM83-9.3(5)) is moved here, since it is more generally applicable. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{package_body}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledClause{Private Types and Private Extensions} @begin{Intro} @redundant[The declaration (in the visible part of a package) of a type as a private type or private extension serves to separate the characteristics that can be used directly by outside program units (that is, the logical properties) from other characteristics whose direct use is confined to the package (the details of the definition of the type itself). See @RefSecNum(Type Extensions) for an overview of type extensions. @Defn{private types and private extensions} @IndexSee{Term=[information hiding],See=(private types and private extensions)} @IndexSee{Term=[opaque type],See=(private types and private extensions)} @IndexSee{Term=[abstract data type (ADT)],See=(private types and private extensions)} @IndexSee{Term=[ADT (abstract data type)],See=(private types and private extensions)}] @end{Intro} @begin{MetaRules} A private (untagged) type can be thought of as a record type with the type of its single (hidden) component being the full view. A private tagged type can be thought of as a private extension of an anonymous parent with no components. The only dispatching operation of the parent is equality (although the Size attribute, and, if nonlimited, assignment are allowed, and those will presumably be implemented in terms of dispatching). @end{MetaRules} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<private_type_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}] @key{is} [[@key{abstract}] @key{tagged}] [@key{limited}] @key{private}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<private_extension_declaration>,rhs=" @key{type} @Syn2{defining_identifier} [@Syn2{discriminant_part}] @key{is} [@key{abstract}] @Chg{Version=[2],New=<[@key{limited} | @key{synchronized}]>,Old=[]} @key{new} @SynI(ancestor_)@Syn2{subtype_indication}@Chg{Version=[2],New=< [@key{and} @Syn2[interface_list]]>,Old=<>} @key{with private}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Legality} @ChgNote{We don't mark this as a change, since it only involves the AARM} @Defn2{Term=[partial view], Sec=(of a type)} @PDefn2{Term=[requires a completion], Sec=(declaration of a partial view)} A @nt<private_type_declaration> or @nt<private_extension_declaration> declares a @i{partial view} of the type; such a declaration is allowed only as a @nt{declarative_item} of the visible part of a package, and it requires a completion, which shall be a @nt{full_type_declaration} that occurs as a @nt{declarative_item} of the private part of the package. @Chg{Version=[2],New=[],Old=[@Defn2{Term=[full view], Sec=(of a type)}]} @Redundant[@ChgNote{This really should be a change, but that's too hard.} The view of the type declared by the @nt<full_type_declaration> is called the @i(full view).] A generic formal private type or a generic formal private extension is also a partial view. @begin(Honest) A private type can also be@Chg{Version=[3],New=[ imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no completion is allowed],Old=[completed by a @nt{pragma} Import]}, if supported by an implementation. @end(Honest) @begin{Reason} We originally used the term @lquotes@;private view,@rquotes@; but this was easily confused with the view provided @i(from) the private part, namely the full view. @end{Reason} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[Full view is now defined in @RefSec{Type Declarations}, as all types now have them.]} @end{TheProof} @Redundant[A type shall be completely defined before it is frozen (see @RefSecNum{Completions of Declarations} and @RefSecNum{Freezing Rules}). Thus, neither the declaration of a variable of a partial view of a type, nor the creation by an @nt{allocator} of an object of the partial view are allowed before the full declaration of the type. Similarly, before the full declaration, the name of the partial view cannot be used in a @nt{generic_instantiation} or in a representation item.] @begin{TheProof} This rule is stated officially in @RefSec{Completions of Declarations}. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Redundant[A private type is limited if its declaration includes the reserved word @key[limited]; a private extension is limited if its ancestor type is @Chg{Version=[2], New=[a limited type that is not an interface type, or if the reserved word @key{limited} or @key{synchronized} appears in its definition],Old=[limited]}.] If the partial view is nonlimited, then the full view shall be nonlimited. If a tagged partial view is limited, then the full view shall be limited. @Redundant[On the other hand, if an untagged partial view is limited, the full view may be limited or nonlimited.] If the partial view is tagged, then the full view shall be tagged. @Redundant[On the other hand, if the partial view is untagged, then the full view may be tagged or untagged.] In the case where the partial view is untagged and the full view is tagged, no derivatives of the partial view are allowed within the immediate scope of the partial view; @Redundant[derivatives of the full view are allowed.] @begin{Ramification} Note that deriving from a partial view within its immediate scope can only occur in a package that is a child of the one where the partial view is declared. The rule implies that in the visible part of a public child package, it is impossible to derive from an untagged private type declared in the visible part of the parent package in the case where the full view of the parent type turns out to be tagged. We considered a model in which the derived type was implicitly redeclared at the earliest place within its immediate scope where characteristics needed to be added. However, we rejected that model, because (1) it would imply that (for an untagged type) subprograms explicitly declared after the derived type could be inherited, and (2) to make this model work for composite types as well, several implicit redeclarations would be needed, since new characteristics can become visible one by one; that seemed like too much mechanism. @end{Ramification} @begin{Discussion} The rule for tagged partial views is redundant for partial views that are private extensions, since all extensions of a given ancestor tagged type are tagged, and limited if the ancestor is limited. We phrase this rule partially redundantly to keep its structure parallel with the other rules. @end{Discussion} @begin{Honest} This rule is checked in a generic unit, rather than using the @lquotes@;assume the best@rquotes@; or @lquotes@;assume the worst@rquotes@; method. @end{Honest} @begin{Reason} @leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}Tagged limited private types have certain capabilities that are incompatible with having assignment for the full view of the type. In particular, tagged limited private types can be extended with @Chg{Version=[2],New=[],Old=[access discriminants and ]}components of a limited type, which works only because assignment is not allowed. Consider the following example: @begin{Example} @key[package] P1 @key[is] @key[type] T1 @key[is] @key[tagged] @key[limited] @key[private]; @key[procedure] Foo(X : @key[in] T1'Class); @key[private] @key[type] T1 @key[is] @key[tagged] @key[null] @key[record]; --@RI{ Illegal!} --@RI{ This should say @lquotes@;@key[tagged limited null record]@rquotes@;.} @key[end] P1; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] @key[body] P1 @key[is] @key[type] A @key[is] @key[access] T1'Class; Global : A; @key[procedure] Foo(X : @key[in] T1'Class) @key[is] @key[begin] Global := @key[new] T1'Class'(X); --@RI{ This would be illegal if the full view of} --@RI{ T1 were limited, like it's supposed to be.} @key[end] @Chg{New=[Foo],Old=[A]}; @key[end] P1; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}@key[with] P1; @key[package] P2 @key[is] @key[type] T2(D : @key[access] Integer)@Chg{Version=[2],New=[],Old=[ --@RI{ Trouble!}]} @key[is] @key[new] P1.T1 @key[with] @key[record] My_Task : Some_Task_Type; --@RI{ @Chg{Version=[2],New=[Trouble],Old=[More trouble]}!} @key[end] @key[record]; @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[with] P1; @key[with] P2; @key[procedure] Main @key[is] Local : @key[aliased] Integer; Y : P2.T2(@Chg{New=[D],Old=[A]} => Local'Access); @key[begin] P1.Foo(Y); @key[end] Main; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If the above example were legal, we would have succeeded in @Chg{Version=[2],New=[],Old=[making an access value that points to Main.Local after Main has been left, and we would also have succeeded in ]}doing an assignment of a task object, @Chg{Version=[2],New=[],Old=[both of ]}which @Chg{Version=[2],New=[is], Old=[are]} supposed to be @Chg{Version=[2],New=[a no-no],Old=[no-no's]}. @ChgNote{A runtime check prevents the first from being a problem in Ada 2005.} This rule is not needed for private extensions, because they inherit their limitedness from their ancestor, and there is a separate rule forbidding limited components of the corresponding record extension if the parent is nonlimited. @end{Reason} @begin{Ramification} @leading@;A type derived from an untagged private type is untagged, even if the full view of the parent is tagged, and even at places that can see the parent: @begin{Example} @key[package] P @key[is] @key[type] Parent @key[is] @key[private]; @key[private] @key[type] Parent @key[is] @key[tagged] @key[record] X: Integer; @key[end] @key[record]; @key[end] P; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @Chg{New=[@key[with] P; ],Old=[]}@key[package] Q @key[is] @key[type] T @key[is] @key[new] @Chg{New=[P.],Old=[]}Parent; @key[end] Q; @key[with] Q; @key[use] Q; @key[package] @key[body] P @key[is] ... T'Class ... --@RI{ Illegal!} Object: T; ... Object.X ... --@RI{ Illegal!} ... Parent(Object).X ... --@RI{ OK.} @key[end] P; @end{Example} The declaration of T declares an untagged view. This view is always untagged, so T'Class is illegal, it would be illegal to extend T, and so forth. The component name X is never visible for this view, although the component is still there @em one can get one's hands on it via a @nt{type_conversion}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00396-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If a full type has a partial view that is tagged, then:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the partial view shall be a synchronized tagged type (see @RefSecNum{Interface Types}) if and only if the full type is a synchronized tagged type;]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Since we do not allow record extensions of synchronized tagged types, this property has to be visible in the partial view to avoid privacy breaking. Generic formals do not need a similar rule as any extensions are rechecked for legality in the specification, and extensions of tagged formals are always illegal in a generic body.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the partial view shall be a descendant of an interface type (see 3.9.4) if and only if the full type is a descendant of the interface type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[Consider the following example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} P @key{is} @key{package} Pkg @key{is} @key{type} Ifc @key{is interface}; @key{procedure} Foo (X : Ifc) @key{is abstract}; @key{end} Pkg;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Parent_1 @key{is tagged null record};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} T1 @key{is new} Parent_1 @key{with private}; @key{private} @key{type} Parent_2 @key{is new} Parent_1 @key{and} Pkg.Ifc @key{with null record}; @key{procedure} Foo (X : Parent_2); -- @RI[Foo #1]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} T1 @key{is new} Parent_2 @key{with null record}; -- @RI[Illegal.] @key{end} P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} P; @key{package} P_Client @key{is} @key{type} T2 @key{is new} P.T1 @key{and} P.Pkg.Ifc @key{with null record}; @key{procedure} Foo (X : T2); -- @RI[Foo #2] X : T2; @key{end} P_Client;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} P_Client; @key{package body} P @key{is} ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Bar (X : T1'Class) @key{is} @key{begin} Pkg.Foo (X); -- @RI[should call Foo #1 or an override thereof] @key{end};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{begin} Pkg.Foo (Pkg.Ifc'Class (P_Client.X)); -- @RI[should call Foo #2] Bar (T1'Class (P_Client.X)); @key{end} P;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This example is illegal because the completion of T1 is descended from an interface that the partial view is not descended from. If it were legal, T2 would implement Ifc twice, once in the visible part of P, and once in the visible part of P_Client. We would need to decide how Foo #1 and Foo #2 relate to each other. There are two options: either Foo #2 overrides Foo #1, or it doesn't.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Foo #2 overrides Foo #1, we have a problem because the client redefines a behavior that it doesn't know about, and we try to avoid this at all costs, as it would lead to a breakdown of whatever abstraction was implemented. If the abstraction didn't expose that it implements Ifc, there must be a reason, and it should be able to depend on the fact that no overriding takes place in clients. Also, during maintenance, things may change and the full view might implement a different set of interfaces. Furthermore, the situation is even worse if the full type implements another interface Ifc2 that happens to have a conforming Foo (otherwise unrelated, except for its name and profile).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Foo #2 doesn't override Foo #1, there is some similarity with the case of normal tagged private types, where a client can declare an operation that happens to conform to some private operation, and that's OK, it gets a different slot in the type descriptor. The problem here is that T2 would implement Ifc in two different ways, and through conversions to Ifc'Class we could end up with visibility on both of these two different implementations. This is the @lquotes@;diamond inheritance@rquotes problem of C++ all over again, and we would need some kind of a preference rule to pick one implementation. We don't want to go there (if we did, we might as well provide full-fledged multiple inheritance).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that there wouldn't be any difficulty to implement the first option, so the restriction is essentially methodological. The second option might be harder to implement, depending on the language rules that we would choose.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[This rule also prevents completing a private type with an interface. @Chg{Version=[3],New=[An],Old=[A]} interface, like all types, is a descendant of itself, and thus this rule is triggered. One reason this is necessary is that a client of a private extension should be able to inherit limitedness without having to look in the private part to see if the type is an interface (remember that limitedness of interfaces is never inherited, while it is inherited from other types).]} @end{Ramification} @end{Itemize} @Defn2{Term=[ancestor subtype], Sec=(of a @nt<private_extension_declaration>)} The @i(ancestor subtype) of a @nt<private_extension_declaration> is the subtype defined by the @i(ancestor_)@!@nt<subtype_@!indication>; the ancestor type shall be a specific tagged type. The full view of a private extension shall be derived (directly or indirectly) from the ancestor type. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), the requirement that the ancestor be specific applies also in the private part of an instance of a generic unit.@PDefn{generic contract issue} @begin{Reason} This rule allows the full view to be defined through several intermediate derivations, possibly from a series of types produced by @nt{generic_instantiation}s. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[If the reserved word @key{limited} appears in a @nt{private_extension_declaration}, the ancestor type shall be a limited type. If the reserved word @key{synchronized} appears in a @nt{private_extension_declaration}, the ancestor type shall be a limited interface.]} If the declaration of a partial view includes a @nt{known_discriminant_part}, then the @nt{full_type_declaration} shall have a fully conforming @Redundant[(explicit)] @nt{known_discriminant_part} @Redundant[(see @RefSec(Conformance Rules))]. @Defn2{Term=[full conformance],Sec=(required)} @Redundant[The ancestor subtype may be unconstrained; the parent subtype of the full view is required to be constrained (see @RefSecNum{Discriminants}).] @begin{Discussion} If the ancestor subtype has discriminants, then it is usually best to make it unconstrained. @end{Discussion} @begin{Ramification} If the partial view has a @nt<known_discriminant_part>, then the full view has to be a composite, non-array type, since only such types may have known discriminants. Also, the full view cannot inherit the discriminants in this case; the @nt{known_discriminant_part} has to be explicit. @leading@keepnext@;That is, the following is illegal: @begin{Example} @key[package] P @key[is] @key[type] T(D : Integer) @key[is] @key[private]; @key[private] @key[type] T @key[is] @key[new] Some_Other_Type; --@RI{ Illegal!} @key[end] P; @end{Example} even if Some_Other_Type has an integer discriminant called D. It is a ramification of this and other rules that in order for a tagged type to privately inherit unconstrained discriminants, the private type declaration has to have an @nt{unknown_discriminant_part}. @end{Ramification} If a private extension inherits known discriminants from the ancestor subtype, then the full view shall also inherit its discriminants from the ancestor subtype, and the parent subtype of the full view shall be constrained if and only if the ancestor subtype is constrained. @begin{Reason} The first part ensures that the full view has the same discriminants as the partial view. The second part ensures that if the partial view is unconstrained, then the full view is also unconstrained; otherwise, a client might constrain the partial view in a way that conflicts with the constraint on the full view. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[If the @nt{full_type_declaration} for a private extension @Chg{Version=[3],New=[includes],Old=[is]} a @Chg{Version=[3],New=[@nt{derived_type_definition}],Old=[@ntf{derived_type_declaration}]}, then the reserved word @key{limited} shall appear in the @nt{full_type_declaration} if and only if it also appears in the @nt{private_extension_declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[The word @key{limited} is optional (unless the ancestor is an interface), but it should be used consistently. Otherwise things would be too confusing for the reader. Of course, we only require that if the full type @Chg{Version=[3],New=[includes],Old=[is defined by]} a @nt{derived_type_definition}, as we want to allow task and protected types to complete extensions of synchronized interfaces.]} @end{Reason} @Redundant[If a partial view has unknown discriminants, then the @nt{full_type_declaration} may define a definite or an indefinite subtype, with or without discriminants.] If a partial view has neither known nor unknown discriminants, then the @nt{full_type_declaration} shall define a definite subtype. If the ancestor subtype of a private extension has constrained discriminants, then the parent subtype of the full view shall impose a statically matching constraint on those discriminants. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Ramification} If the parent type of the full view is not the ancestor type, but is rather some descendant thereof, the constraint on the discriminants of the parent type might come from the declaration of some intermediate type in the derivation chain between the ancestor type and the parent type. @end{Ramification} @begin{Reason} @leading@keepnext@;This prevents the following: @begin{Example} @key[package] P @key[is] @key[type] T2 @key[is] @key[new] T1(Discrim => 3) @key[with] @key[private]; @key[private] @key[type] T2 @key[is] @key[new] T1(Discrim => 999) --@RI{ Illegal!} @key[with] @key[record] ...; @key[end] P; @end{Example} The constraints in this example do not statically match. @leading@;If the constraint on the parent subtype of the full view depends on discriminants of the full view, then the ancestor subtype has to be unconstrained: @begin{Example} @key[type] One_Discrim(A: Integer) @key[is] @key[tagged] ...; ... @key[package] P @key[is] @key[type] Two_Discrims(B: Boolean; C: Integer) @key[is] @key[new] One_Discrim @key[with] @key[private]; @key[private] @key[type] Two_Discrims(B: Boolean; C: Integer) @key[is] @key[new] One_Discrim(A => C) @key[with] @key[record] ... @key[end] @key[record]; @key[end] P; @end{Example} The above example would be illegal if the private extension said @lquotes@;is new One_Discrim(A => C);@rquotes@;, because then the constraints would not statically match. (Constraints that depend on discriminants are not static.) @end{Reason} @end{Legality} @begin{StaticSem} @PDefn{private type} A @nt{private_type_declaration} declares a private type and its first subtype. @PDefn{private extension} Similarly, a @nt{private_@!extension_@!declaration} declares a private extension and its first subtype. @begin{Discussion} @Defn{package-private type} A @i(package-private type) is one declared by a @nt<private_type_declaration>; that is, a private type other than a generic formal private type. @Defn{package-private extension} Similarly, a @i(package-private extension) is one declared by a @nt<private_extension_declaration>. These terms are not used in the RM95 version of this document. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0269-1]} A declaration of a partial view and the corresponding @nt{full_type_declaration} define two views of a single type. The declaration of a partial view together with the visible part define the operations that are available to outside program units; the declaration of the full view together with the private part define other operations whose direct use is possible only within the declarative region of the package itself. @Chg{Version=[3],New=[],Old=[@PDefn{characteristics}]}Moreover, within the scope of the declaration of the full view, the @Chg{Version=[3],New=[characteristics (see @RefSecNum{Derived Types and Classes})],Old=[@i{characteristics}]} of the type are determined by the full view; in particular, within its scope, the full view determines the classes that include the type, which components, entries, and protected subprograms are visible, what attributes and other predefined operations are allowed, and whether the first subtype is static. See @RefSecNum{Private Operations}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0110-1]} @Chg{Version=[3],New=[For a],Old=[A]} private extension@Chg{Version=[3],New=[, the characteristics], Old=[inherits components]} (including @Chg{Version=[3],New=[components, but excluding ],Old=[]}discriminants @Chg{Version=[3],New=[if],Old=[unless]} there is a new @nt<discriminant_part> specified)@Chg{Version=[3],New=[, predefined operators,],Old=[]} and @Chg{Version=[3],New=[inherited ],Old=[]}user-defined primitive subprograms @Chg{Version=[3],New=[are determined by],Old=[from]} its ancestor type@Chg{Version=[2],New=[ and its progenitor types (if any)],Old=[]}, in the same way that@Chg{Version=[3],New=[ those of],Old=[]} a record extension @Chg{Version=[3],New=[are determined by those of],Old=[inherits components and user-defined primitive subprograms from]} its parent type@Chg{Version=[2],New=[ and its progenitor types],Old=[]} (see @RefSecNum{Derived Types and Classes}@Chg{Version=[3],New=[ and @RefSecNum{Private Operations}],Old=[]}). @begin{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0110-1]} If an operation of the @Chg{Version=[3],New=[ancestor or],Old=[]} parent type is abstract, then the abstractness of the inherited operation is different for nonabstract record extensions than for nonabstract private extensions (see @RefSecNum{Abstract Types and Subprograms}). @end{Honest} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(private_type_declaration)} The elaboration of a @nt{private_type_declaration} creates a partial view of a type. @PDefn2{Term=[elaboration], Sec=(private_extension_declaration)} The elaboration of a @nt{private_extension_declaration} elaborates the @i(ancestor_)@nt<subtype_indication>, and creates a partial view of a type. @end{RunTime} @begin{Notes} The partial view of a type as declared by a @nt<private_type_declaration> is defined to be a composite view (in @RefSecNum{Types and Subtypes}). The full view of the type might or might not be composite. A private extension is also composite, as is its full view. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} Declaring a private type with an @nt{unknown_discriminant_part} is a way of preventing clients from creating uninitialized objects of the type; they are then forced to initialize each object by calling some operation declared in the visible part of the package. @Chg{Version=[2],New=[],Old=[If such a type is also limited, then no objects of the type can be declared outside the scope of the @nt{full_type_declaration}, restricting all object creation to the package defining the type. This allows complete control over all storage allocation for the type. Objects of such a type can still be passed as parameters, however.]} @begin{Discussion} @Defn{generic contract/private type contract analogy} Packages with private types are analogous to generic packages with formal private types, as follows: The declaration of a package-private type is like the declaration of a formal private type. The visible part of the package is like the generic formal part; these both specify a contract (that is, a set of operations and other things available for the private type). The private part of the package is like an instantiation of the generic; they both give a @nt{full_type_declaration} that specifies implementation details of the private type. The clients of the package are like the body of the generic; usage of the private type in these places is restricted to the operations defined by the contract. In other words, being inside the package is like being outside the generic, and being outside the package is like being inside the generic; a generic is like an @lquotes@;inside-out@rquotes@; package. This analogy also works for private extensions in the same inside-out way. Many of the legality rules are defined with this analogy in mind. See, for example, the rules relating to operations of [formal] derived types. The completion rules for a private type are intentionally quite similar to the matching rules for a generic formal private type. This analogy breaks down in one respect: a generic actual subtype is a subtype, whereas the full view for a private type is always a new type. (We considered allowing the completion of a @nt{private_type_declaration} to be a @nt{subtype_declaration}, but the semantics just won't work.) This difference is behind the fact that a generic actual type can be class-wide, whereas the completion of a private type always declares a specific type. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401]} The ancestor type specified in a @nt<private_extension_declaration> and the parent type specified in the corresponding declaration of a record extension given in the private part need not be the same@Chg{Version=[2],New=[. If the ancestor type is not an interface type,],Old=[ @em]} the parent type of the full view can be any descendant of the ancestor type. In this case, for a primitive subprogram that is inherited from the ancestor type and not overridden, the formal parameter names and default expressions (if any) come from the corresponding primitive subprogram of the specified ancestor type, while the body comes from the corresponding primitive subprogram of the parent type of the full view. See @RefSecNum{Dispatching Operations of Tagged Types}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00401]} @ChgAdded{Version=[2],Text=[If the ancestor type specified in a @nt{private_extension_declaration} is an interface type, the parent type can be any type so long as the full view is a descendant of the ancestor type. The progenitor types specified in a @nt{private_extension_declaration} and the progenitor types specified in the corresponding declaration of a record extension given in the private part need not be the same @em the only requirement is that the private extension and the record extension be descended from the same set of interfaces.]} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of private type declarations:} @begin{Example} @key[type] Key @key[is] @key[private]; @key[type] File_Name @key[is] @key[limited] @key[private]; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a private extension declaration:} @end{WideAbove} @begin{Example} @key[type] List @key[is] @key[new] Ada.Finalization.Controlled @key[with] @key[private]; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax for a @nt{private_type_declaration} is augmented to allow the reserved word @key{tagged}. In Ada 83, a private type without discriminants cannot be completed with a type with discriminants. Ada 95 allows the full view to have discriminants, so long as they have defaults (that is, so long as the first subtype is definite). This change is made for uniformity with generics, and because the rule as stated is simpler and easier to remember than the Ada 83 rule. In the original version of Ada 83, the same restriction applied to generic formal private types. However, the restriction was removed by the ARG for generics. In order to maintain the @lquotes@;generic contract/private type contract analogy@rquotes@; discussed above, we have to apply the same rule to package-private types. Note that a private untagged type without discriminants can be completed with a tagged type with discriminants only if the full view is constrained, because discriminants of tagged types cannot have defaults. @end{Extend83} @begin{DiffWord83} RM83-7.4.1(4), @lquotes@;Within the specification of the package that declares a private type and before the end of the corresponding full type declaration, a restriction applies....@rquotes@;, is subsumed (and corrected) by the rule that a type shall be completely defined before it is frozen, and the rule that the parent type of a derived type declaration shall be completely defined, unless the derived type is a private extension. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00396-01],ARef=[AI95-00401-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Added @nt{interface_list} to private extensions to support interfaces and multiple inheritance (see @RefSecNum{Interface Types}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A private extension may specify that it is a limited type. This is required for interface ancestors (from which limitedness is not inherited), but it is generally useful as documentation of limitedness.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[A private extension may specify that it is a synchronized type. This is required in order so that a regular limited interface can be used as the ancestor of a synchronized type (we do not allow hiding of synchronization).]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{private_type_declaration} and a @nt{private_extension_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0110-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The description of how a private extension inherits characteristics was made consistent with the way formal derived types inherit characteristics (see @RefSecNum{Formal Private and Derived Types}).]} @end{DiffWord2005} @LabeledSubClause{Private Operations} @begin{Intro} @Redundant[For a type declared in the visible part of a package or generic package, certain operations on the type do not become visible until later in the package @em either in the private part or the body. @Defn{private operations} Such @i{private operations} are available only inside the declarative region of the package or generic package.] @end{Intro} @begin{StaticSem} The predefined operators that exist for a given type are determined by the classes to which the type belongs. For example, an integer type has a predefined "+" operator. In most cases, the predefined operators of a type are declared immediately after the definition of the type; the exceptions are explained below. Inherited subprograms are also implicitly declared immediately after the definition of the type, except as stated below. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0029-1]} For a composite type, the characteristics (see @RefSecNum{Private Types and Private Extensions}) of the type are determined in part by the characteristics of its component types. At the place where the composite type is declared, the only characteristics of component types used are those characteristics visible at that place. If later @Chg{New=[immediately within the declarative region in which the composite type is declared], Old=[within the immediate scope of the composite type]} additional characteristics become visible for a component type, then any corresponding characteristics become visible for the composite type. Any additional predefined operators are implicitly declared at that place.@Chg{Version=[3],New=[ If there is no such place, then additional predefined operators are not declared at all, but they still exist.],Old=[]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Text=[We say that the predefined operators exist because they can emerge in some unusual generic instantiations. See @RefSecNum{Formal Types}.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Text=[The predefined operators for the underlying class of a type always exist, even if there is no visibility on that underlying class. This rule is simply about where (if ever) those operators are declared (and thus become usable). The @ldquote@;additional predefined operators@rdquote defined by this rule are any that are not declared at the point of the original type declaration. For instance, a type derived from a private type whose full type is type String always will have a ">" operator, but where that operator is declared (and thus whether it is visible) will depend on the visibility of the full type of the parent type.]} @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} The corresponding rule applies to a type defined by a @nt{derived_type_definition}, if there is a place @Chg{New=[immediately within the declarative region in which the type is declared], Old=[within its immediate scope]} where additional characteristics of its parent type become visible. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} @Defn{become nonlimited} @Defn2{Term=[nonlimited type],Sec=(becoming nonlimited)} @Defn2{Term=[limited type],Sec=(becoming nonlimited)} @Redundant[For example, an array type whose component type is limited private becomes nonlimited if the full view of the component type is nonlimited and visible at some later place @Chg{New=[immediately within the declarative region in which the array type is declared.], Old=[within the immediate scope of the array type.]} In such a case, the predefined "=" operator is implicitly declared at that place, and assignment is allowed after that place.] @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0115-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[A type is a @i<descendant>@Defn2{Term=[descendant], Sec=[of the full view of a type]} of the full view of some ancestor of its parent type only if the current view it has of its parent is a descendant of the full view of that ancestor. More generally, at any given place, a type is descended from the same view of an ancestor as that from which the current view of its parent is descended. This view determines what characteristics are inherited from the ancestor@Redundant[, and, for example, whether the type is considered to be a descendant of a record type, or a descendant only through record extensions of a more distant ancestor].]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[@Redundant[It is possible for there to be places where a derived type is visibly a descendant of an ancestor type, but not a descendant of even a partial view of the ancestor type, because the parent of the derived type is not visibly a descendant of the ancestor. In this case, the derived type inherits no characteristics from that ancestor, but nevertheless is within the derivation class of the ancestor for the purposes of type conversion, the "covers" relationship, and matching against a formal derived type. In this case the derived type is considered to be a @i<descendant> of an incomplete view of the ancestor.@Defn2{Term=[descendant], Sec=[of an incomplete view]}]]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Leading],Text=[Here is an example of this situation:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[package] P @key[is] @key[type] T @key[is] @key[private]; C : @key[constant] T; @key[private] @key[type] T @key[is new] Integer; C : @key[constant] T := 42; @key[end] P;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[with] P; @key[package] Q @key[is] @key[type] T2 @key[is new] P.T; @key[end] Q;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[with] Q; @key[package] P.Child @key[is] @key[type] T3 @key[is new] Q.T2; @key[private] Int : Integer := 52; V : T3 := T3(P.C); -- @Examcom{Legal: conversion allowed} W : T3 := T3(Int); -- @Examcom{Legal: conversion allowed} X : T3 := T3(42); -- @Examcom{Error: T3 is not a numeric type} Y : T3 := X + 1; -- @Examcom{Error: no visible "+" operator} Z : T3 := T3(Integer(W) + 1); -- @Examcom{Legal: convert to Integer first} @key[end] P.Child;]} @end{Example} @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0019],ARef=[AI95-00033-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0029-1]} Inherited primitive subprograms follow a different rule. For a @nt{derived_type_definition}, each inherited primitive subprogram is implicitly declared at the earliest place, if any, @Chg{New=[immediately within the declarative region in which], Old=[within the immediate scope of]} the @nt{type_declaration}@Chg{New=[ occurs],Old=[]}, but after the @nt{type_declaration}, where the corresponding declaration from the parent is visible. If there is no such place, then the inherited subprogram is not declared at all@Chg{Version=[3],New=[, but it still exists],Old=[]}. @Redundant[@Chg{Version=[3],New=[For a tagged type, it is possible to dispatch to an],Old=[An]} inherited subprogram that is not declared at all@Chg{Version=[3],New=[],Old=[cannot be named in a call and cannot be overridden, but for a tagged type, it is possible to dispatch to it]}.] For a @nt{private_extension_declaration}, each inherited subprogram is declared immediately after the @nt{private_extension_declaration} if the corresponding declaration from the ancestor is visible at that place. Otherwise, the inherited subprogram is not declared for the private extension, @Redundant[though it might be for the full type]. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} There is no need for the @lquotes@;earliest place @Chg{New=[immediately within the declarative region], Old=[within the immediate scope]}@rquotes@; business here, because a @nt{private_extension_declaration} will be completed with a @nt{full_type_declaration}, so we can hang the necessary private implicit declarations on the @nt{full_type_declaration}. @end{Reason} @begin{Discussion} The above rules matter only when the component type (or parent type) is declared in the visible part of a package, and the composite type (or derived type) is declared within the declarative region of that package (possibly in a nested package or a child package). @leading@keepnext@;Consider: @begin{Example} @key[package] Parent @key[is] @key[type] Root @key[is] @key[tagged] @key[null] @key[record]; @key[procedure] Op1(X : Root); @key[type] My_Int @key[is] @key[range] 1..10; @key[private] @key[procedure] Op2(X : Root); @key[type] Another_Int @key[is] @key[new] My_Int; @key[procedure] Int_Op(X : My_Int); @key[end] Parent; @key[with] Parent; @key[use] Parent; @key[package] Unrelated @key[is] @key[type] T2 @key[is] @key[new] Root @key[with] @key[null] @key[record]; @key[procedure] Op2(X : T2); @key[end] Unrelated; @key[package] Parent.Child @key[is] @key[type] T3 @key[is] @key[new] Root @key[with] @key[null] @key[record]; --@RI{ Op1(T3) implicitly declared here.} @key[package] Nested @key[is] @key[type] T4 @key[is] @key[new] Root @key[with] @key[null] @key[record]; @key[private] ... @key[end] Nested; @key[private] --@RI{ Op2(T3) implicitly declared here.} ... @key[end] Parent.Child; @key[with] Unrelated; @key[use] Unrelated; @key[package] @key[body] Parent.Child @key[is] @key[package] @key[body] Nested @key[is] --@RI{ Op2(T4) implicitly declared here.} @key[end] Nested; @key[type] T5 @key[is] @key[new] T2 @key[with] @key[null] @key[record]; @key[end] Parent.Child; @end{Example} Another_Int does not inherit Int_Op, because Int_Op does not @lquotes@;exist@rquotes@; at the place where Another_Int is declared. @ChgRef{Version=[1],Kind=[Revised]} Type T2 inherits Op1 and Op2 from Root. However, the inherited Op2 is never declared, because Parent.Op2 is never visible @Chg{New=[immediately within the declarative region], Old=[within the immediate scope]} of T2. T2 explicitly declares its own Op2, but this is unrelated to the inherited one @em it does not override the inherited one, and occupies a different slot in the type descriptor. T3 inherits both Op1 and Op2. Op1 is implicitly declared immediately after the type declaration, whereas Op2 is declared at the beginning of the private part. Note that if Child were a private child of Parent, then Op1 and Op2 would both be implicitly declared immediately after the type declaration. @ChgRef{Version=[1],Kind=[Revised]} T4 is similar to T3, except that the earliest place @Chg{New=[immediately within the declarative region containing T4], Old=[within T4's immediate scope]} where Root's Op2 is visible is in the body of Nested. If T3 or T4 were to declare a type-conformant Op2, this would override the one inherited from Root. This is different from the situation with T2. T5 inherits Op1 and two Op2's from T2. Op1 is implicitly declared immediately after the declaration of T5, as is the Op2 that came from Unrelated.Op2. However, the Op2 that originally came from Parent.Op2 is never implicitly declared for T5, since T2's version of that Op2 is never visible (anywhere @em it never got declared either). For all of these rules, implicit private parts and bodies are assumed as needed. @leading@keepnext@;It is possible for characteristics of a type to be revealed in more than one place: @begin{Example} @key[package] P @key[is] @key[type] Comp1 @key[is] @key[private]; @key[private] @key[type] Comp1 @key[is] @key[new] Boolean; @key[end] P; @key[package] P.Q @key[is] @key[package] R @key[is] @key[type] Comp2 @key[is] @key[limited] @key[private]; @key[type] A @key[is] @key[array](Integer @key[range] <>) @key[of] Comp2; @key[private] @key[type] Comp2 @key[is] @key[new] Comp1; --@RI{ A becomes nonlimited here.} --@RI{ "="(A, A) return Boolean is implicitly declared here.} ... @key[end] R; @key[private] --@RI{ Now we find out what Comp1 really is, which reveals} --@RI{ more information about Comp2, but we're not within} --@RI{ the immediate scope of Comp2, so we don't do anything} --@RI{ about it yet.} @key[end] P.Q; @key[package] @key[body] P.Q @key[is] @key[package] @key[body] R @key[is] --@RI{ Things like "@key[xor]"(A,A) return A are implicitly} --@RI{ declared here.} @key[end] R; @key[end] P.Q; @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0019],ARef=[AI95-00033-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[We say @i<immediately> within the declarative region in order that types do not gain operations within a nested scope. Consider:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@Key[package] Outer @key[is] @key[package] Inner @key[is] @key[type] Inner_Type @key[is] @key[private]; @key[private] @key[type] Inner_Type @key[is] @key[new] Boolean; @key[end] Inner; @key[type] Outer_Type @key[is] @key[array](Natural @key[range] <>) @key[of] Inner.Inner_Type; @key[end] Outer;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] @key[body] Outer @key[is] @key[package] @key[body] Inner @key[is] -- At this point, we can see that Inner_Type is a Boolean type. -- But we don't want Outer_Type to gain an "and" operator here. @key[end] Inner; @key[end] Outer;],Old=[]} @end{Example} @end{Discussion} @leading@Redundant[The Class attribute is defined for tagged subtypes in @RefSecNum{Tagged Types and Type Extensions}. In addition,] for @PrefixType{every subtype S of an untagged private type whose full view is tagged}, the following attribute is defined: @begin(description) @Attribute{Prefix=<S>, AttrName=<Class>, Text=<Denotes the class-wide subtype corresponding to the full view of S. This attribute is allowed only from the beginning of the private part in which the full view is declared, until the declaration of the full view. @Redundant[After the full view, the Class attribute of the full view can be used.]>} @end(description) @EndPrefixType{} @end{StaticSem} @begin{Notes} Because a partial view and a full view are two different views of one and the same type, outside of the defining package the characteristics of the type are those defined by the visible part. Within these outside program units the type is just a private type or private extension, and any language rule that applies only to another class of types does not apply. The fact that the full declaration might implement a private type with a type of a particular class (for example, as an array type) is relevant only within the declarative region of the package itself including any child units. @NoPrefix@;The consequences of this actual implementation are, however, valid everywhere. For example: any default initialization of components takes place; the attribute Size provides the size of the full view; finalization is still done for controlled components of the full view; task dependence rules still apply to components that are task objects. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Partial views provide @Chg{Version=[2],New=[initialization], Old=[assignment (unless the view is limited)]}, membership tests, selected components for the selection of discriminants and inherited components, qualification, and explicit conversion.@Chg{Version=[2],New=[ Nonlimited partial views also allow use of @nt{assignment_statement}s.],Old=[]} For a subtype S of a partial view, S'Size is defined (see @RefSecNum{Operational and Representation Attributes}). For an object A of a partial view, the attributes A'Size and A'Address are defined (see @RefSecNum{Operational and Representation Attributes}). The Position, First_Bit, and Last_Bit attributes are also defined for discriminants and inherited components. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a type with private operations:} @begin{Example} @key[package] Key_Manager @key[is] @key[type] Key @key[is] @key[private]; Null_Key : @key[constant] Key; --@RI{ a deferred constant declaration (see @RefSecNum{Deferred Constants})} @key[procedure] Get_Key(K : @key[out] Key); @key[function] "<" (X, Y : Key) @key[return] Boolean; @key[private] @key[type] Key @key[is] @key[new] Natural; Null_Key : @key[constant] Key := Key'First; @key[end] Key_Manager; @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @key[package] @key[body] Key_Manager @key[is] Last_Key : Key := Null_Key; @key[procedure] Get_Key(K : @key[out] Key) @key[is] @key[begin] Last_Key := Last_Key + 1; K := Last_Key; @key[end] Get_Key; @key[function] "<" (X, Y : Key) @key[return] Boolean @key[is] @key[begin] @key[return] Natural(X) < Natural(Y); @key[end] "<"; @key[end] Key_Manager; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the example:} Outside of the package Key_Manager, the operations available for objects of type Key include assignment, the comparison for equality or inequality, the procedure Get_Key and the operator "<"; they do not include other relational operators such as ">=", or arithmetic operators. @NoPrefix@;The explicitly declared operator "<" hides the predefined operator "<" implicitly declared by the @nt{full_type_declaration}. Within the body of the function, an explicit conversion of X and Y to the subtype Natural is necessary to invoke the "<" operator of the parent type. Alternatively, the result of the function could be written as not (X >= Y), since the operator ">=" is not redefined. @NoPrefix@;The value of the variable Last_Key, declared in the package body, remains unchanged between calls of the procedure Get_Key. (See also the NOTES of @RefSecNum{Package Bodies}.) @end{Notes} @begin{DiffWord83} The phrase in RM83-7.4.2(7), @lquotes@;...after the full type declaration@rquotes@;, doesn't work in the presence of child units, so we define that rule in terms of visibility. The definition of the Constrained attribute for private types has been moved to @lquotes@;Obsolescent Features.@rquotes@; (The Constrained attribute of an object has not been moved there.) @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0018],ARef=[AI95-00033-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified when additional operations are declared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Revised the note on operations of partial views to reflect that limited types do have an assignment operation, but not @nt{assignment_statement}s.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the wording to say that predefined operations still exist even if they are never declared, because it is possible to reference them in a generic unit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0115-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that the characteristics of a descendant of a private type depend on the visibility of the full view of the direct ancestor. This has to be the case (so that privacy is not violated), but it wasn't spelled out in earlier versions of Ada.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Type Invariants]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a private type or private extension, the following language-defined aspects may be specified with an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}):]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0250-1]} @ChgAdded{Version=[3],Text=[Type_Invariant@\This aspect shall be specified by an @nt{expression}, called an @i<invariant expression>.@Defn{invariant expression} Type_Invariant may be specified on a @nt{private_@!type_@!declaration}, on a @nt{private_@!extension_@!declaration}, or on a @nt{full_@!type_@!declaration} that declares the completion of a private type or private extension.@AspectDefn{Type_Invariant}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Type_Invariant], Text=[@ChgAdded{Version=[3],Text=[A condition that must hold true for all objects of a type.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Text=[Type_Invariant'Class@\This aspect shall be specified by an @nt{expression}, called an @i<invariant expression>. Type_Invariant'Class may be specified on a @nt{private_@!type_@!declaration} or a @nt{private_@!extension_@!declaration}.@AspectDefn{Type_Invariant'Class}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0254-1]} @ChgAdded{Version=[3],Text=[A class-wide type invariant cannot be hidden in the private part, as the creator of an extension needs to know about it in order to conform to it in any new or overriding operations. On the other hand, a specific type invariant is not inherited, so that no operation outside of the original package needs to conform to it; thus there is no need for it to be visible.]} @end{Reason} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Type_Invariant'Class], Text=[@ChgAdded{Version=[3],Text=[A condition that must hold true for all objects in a class of types.]}]} @end{Description} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Text=[The expected type for an invariant expression is any boolean type.@PDefn2{Term=[expected type], Sec=(invariant expression)}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Text=[@Redundant[Within an invariant expression, the identifier of the first subtype of the associated type denotes the current instance of the type.] Within an invariant expression associated with type @i<T>, the type of the current instance is @i<T> for the Type_Invariant aspect and @i<T>'Class for the Type_Invariant'Class aspect.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The first sentence is given formally in @RefSecNum{Aspect Specifications}.]} @end{TheProof} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Text=[@Redundant[The Type_Invariant'Class aspect shall not be specified for an untagged type.] The Type_Invariant aspect shall not be specified for an abstract type.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The first sentence is given formally in @RefSecNum{Aspect Specifications}.]} @end{TheProof} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0250-1]} @ChgAdded{Version=[3],Text=[@Redundant[If the Type_Invariant aspect is specified for a type @i<T>, then the invariant expression applies to @i<T>.]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1]} @ChgAdded{Version=[3],Text=[@Redundant[If the Type_Invariant'Class aspect is specified for a tagged type @i<T>, then the invariant expression applies to all descendants of @i<T>.]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=["Applies" is formally defined in @RefSecNum{Aspect Specifications}.]} @end{TheProof} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0247-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If one or more invariant expressions apply to a type @i<T>, then an invariant check is performed at the following places, on the specified object(s):@Defn{invariant check}@Defn2{Term=[check, language-defined], Sec=[controlled by assertion policy]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[After successful default initialization of an object of type @i<T>, the check is performed on the new object;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[After successful conversion to type @i<T>, the check is performed on the result of the conversion;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[For a view conversion, outside the immediate scope of @i<T>, that converts from a descendant of @i<T> (including @i<T> itself) to an ancestor of type @i<T> (other than @i<T> itself), a check is performed on the part of the object that is of type @i<T>:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[after assigning to the view conversion; and]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[after successful return from a call that passes the view conversion as an @key[in out] or @key[out] parameter.]} @end{InnerItemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For a single view conversion that converts between distantly related types, this rule could be triggered for multiple types and thus multiple invariant checks may be needed.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[For calls to inherited subprograms (including dispatching calls), the implied view conversions mean that a wrapper is probably needed. (See the Note at the bottom of this subclause for more on the model of checks for inherited subprograms.)]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For view conversions involving class-wide types, the exact checks needed may not be known at compile-time. One way to deal with this is to have an implicit dispatching operation that is given the object to check and the tag of the target of the conversion, and which first checks if the passed tag is not for itself, and if not, checks the its invariant on the object and then calls the operation of its parent type. If the tag is for itself, the operation is complete.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[After a successful call on the Read or Input stream attribute of the type @i<T>, the check is performed on the object initialized by the stream attribute;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An invariant is checked upon successful return from a call on any subprogram or entry that:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[is declared within the immediate scope of type @i<T> (or by an instance of a generic unit, and the generic is declared within the immediate scope of type @i<T>), and]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[is visible outside the immediate scope of type @i<T> or overrides an operation that is visible outside the immediate scope of @i<T>, and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0289-1]} @ChgAdded{Version=[3],Text=[has a result with a part of type @i<T>, or one or more parameters with a part of type @i<T>, or an access to variable parameter whose designated type has a part of type @i<T>.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[The check is performed on each such part of type @i<T>.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If performing checks is required by the Invariant or Invariant'Class assertion policies (see @RefSecNum{Pragmas Assert and Assertion_Policy}) in effect at the point of corresponding aspect specification applicable to a given type, then the respective invariant expression is considered @i(enabled).@Defn2{Term=[enabled],Sec=[invariant expression]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If a class-wide invariant expression is enabled for a type, it remains enabled when inherited by descendants of that type, even if the policy in effect is Ignore for the inheriting type.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0250-1],ARef=[AI05-0289-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[The invariant check consists of the evaluation of each enabled invariant expression that applies to @i<T>, on each of the objects specified above. If any of these evaluate to False, Assertions.Assertion_Error is raised at the point of the object initialization, conversion, or call.@Defn2{Term=(Assertion_Error), Sec=(raised by failure of run-time check)} If a given call requires more than one evaluation of an invariant expression, either for multiple objects of a single type or for multiple types with invariants, the evaluations are performed in an arbitrary order, and if one of them evaluates to False, it is not specified whether the others are evaluated. Any invariant check is performed prior to copying back any by-copy @key[in out] or @key[out] parameters. Invariant checks, any postcondition check, and any constraint or predicate checks associated with @key[in out] or @key[out] parameters are performed in an arbitrary order.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0247-1],ARef=[AI05-0250-1]} @ChgAdded{Version=[3],Text=[The invariant checks performed on a call are determined by the subprogram or entry actually invoked, whether directly, as part of a dispatching call, or as part of a call through an access-to-subprogram value.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Invariant checks on subprogram return are not performed on objects that are accessible only through access values. It is also possible to call through an access-to-subprogram value and reach a subprogram body that has visibility on the full declaration of a type, from outside the immediate scope of the type. No invariant checks will be performed if the designated subprogram is not itself externally visible. These cases represent "holes" in the protection provided by invariant checks; but note that these holes cannot be caused by clients of the type @i<T> with the invariant without help for the designer of the package containing @i<T>.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The implementation might want to produce a warning if a private extension has an ancestor type that is a visible extension, and an invariant expression depends on the value of one of the components from a visible extension part.]} @end{ImplNote} @end{Runtime} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0250-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[For a call of a primitive subprogram of type @i<NT> that is inherited from type @i<T>, the specified checks of the specific invariants of both the types @i<NT> and @i<T> are performed. For a call of a primitive subprogram of type @i<NT> that is overridden for type @i<NT>, the specified checks of the specific invariants of only type @i<NT> are performed.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This follows from the definition of a call on an inherited subprogram as view conversions of the parameters of the type and a call to the original subprogram (see @RefSecNum{Derived Types and Classes}), along with the normal invariant checking rules. In particular, the call to the original subprogram takes care of any checks needed on type @i<T>, and the checks required on view conversions take care of any checks needed on type @i<NT>, specifically on @key[in out] and @key[out] parameters. We require this in order that the semantics of an explicitly defined wrapper that does nothing but call the original subprogram is the same as that of an inherited subprogram.]} @end{TheProof} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0146-1],ARef=[AI05-0247-1],ARef=[AI05-0250-1],ARef=[AI05-0289-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Type_Invariant aspects are new.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Deferred Constants} @begin{Intro} @redundant[Deferred constant declarations may be used to declare constants in the visible part of a package, but with the value of the constant given in the private part. They may also be used to declare constants imported from other languages (see @RefSecNum{Interface to Other Languages}).] @end{Intro} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @Redundant[@Defn{deferred constant declaration} A @i(deferred constant declaration) is an @nt<object_declaration> with the reserved word @key(constant) but no initialization expression.] @Defn{deferred constant} The constant declared by a deferred constant declaration is called a @i{deferred constant}. @PDefn2{Term=[requires a completion], Sec=(deferred constant declaration)} @Chg{Version=[3],New=[@Redundant[Unless the Import aspect (see @RefSecNum{Interfacing Aspects}) is True for a deferred constant declaration, the ]],Old=[A]} deferred constant declaration requires a completion, which shall be a full constant declaration (called the @i{full declaration} of the deferred constant)@Chg{Version=[3],New=[],Old=[, or a @nt{pragma} Import (see @RefSecNum(Interface to Other Languages))]}. @Defn{full declaration} @begin{TheProof} The first sentence is redundant, as it is stated officially in @RefSecNum(Object Declarations). @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The first part of the last sentence is redundant, as no imported entity may have a completion, as stated in @RefSecNum{Interfacing Aspects}.]} @end{TheProof} @leading@;A deferred constant declaration that is completed by a full constant declaration shall occur immediately within the visible part of a @nt<package_specification>. For this case, the following additional rules apply to the corresponding full declaration: @begin(itemize) The full declaration shall occur immediately within the private part of the same package; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} The deferred and full constants shall have the same type@Chg{Version=[2], New=[, or shall have statically matching anonymous access subtypes],Old=[]}; @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} This implies that both the deferred declaration and the full declaration have to have a @nt<subtype_indication>@Chg{Version=[2],New=[ or @nt{access_definition}],Old=[]} rather than an @nt<array_type_definition>, because each @nt{array_type_definition} would define a new type. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00385-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0062-1],ARef=[AI05-0262-1]} If the @Chg{Version=[2],New=[deferred constant declaration includes a],Old=[subtype defined by the]} @nt<subtype_indication> @Chg{Version=[3],New=[@i<S> ],Old=[]}@Chg{Version=[2], New=[that defines a],Old=[in the deferred declaration is]} constrained@Chg{Version=[2],New=[ subtype],Old=[]}, then the @Chg{Version=[3],New=[constraint],Old=[subtype]} defined by the @nt<subtype_indication> in the full declaration shall match @Chg{Version=[3],New=[the constraint defined by @i<S>],Old=[it]} statically.@Redundant[ On the other hand, if the subtype of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint. The constant itself will be constrained, like all constants;] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} If the deferred constant declaration includes the reserved word @key(aliased), then the full declaration shall also@Chg{Version=[2],New=[;],Old=[.]} @begin{Ramification} On the other hand, the full constant can be aliased even if the deferred constant is not. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If the subtype of the deferred constant declaration excludes null, the subtype of the full declaration shall also exclude null.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[On the other hand, the full constant can exclude null even if the deferred constant does not. But that can only happen for a @nt{subtype_indication}, as anonymous access types are required to statically match (which includes any @nt{null_exclusion}).]} @end{Ramification} @end(itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Redundant[A deferred constant declaration @Chg{Version=[3],New=[for which the],Old=[that is completed by a @nt{pragma}]} Import @Chg{Version=[3],New=[aspect is True ],Old=[]}need not appear in the visible part of a @nt{package_specification}, and has no full constant declaration.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} The completion of a deferred constant declaration shall occur before the constant is frozen (see @Chg{Version=[2],New=[@RefSecNum{Freezing Rules}], Old=[@RefSecNum{Deferred Constants}]}). @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @PDefn2{Term=[elaboration], Sec=(deferred constant declaration)} The elaboration of a deferred constant declaration elaborates the @nt<subtype_indication>@Chg{Version=[3],New=[, @nt<access_definition>,],Old=[]} or (only allowed in the case of an imported constant) the @nt<array_type_definition>. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1]} @ChgAdded{Version=[3],Text=[For nonimported constants, these elaborations cannot require any code or checks for a legal program, because the given @nt<subtype_indication> has to be indefinite or statically match that of the full constant, meaning that either it is a @nt<subtype_mark> or it has static constraints. If the deferred constant instead has an @nt<access_definition>, the designated subtype must be a @nt<subtype_mark>. We still say that these are elaborated, however, because part of elaboration is creating the type, which is clearly needed for @nt<access_definition>s. (A deferred constant and its full constant have different types when they are specified by an @nt<access_definition>, although there is no visible effect of these types being different as neither can be named.)]} @end{Ramification} @end{RunTime} @begin{Notes} The full constant declaration for a deferred constant that is of a given private type or private extension is not allowed before the corresponding @nt{full_type_declaration}. This is a consequence of the freezing rules for types (see @RefSecNum{Freezing Rules}). @begin{Ramification} Multiple or single declarations are allowed for the deferred and the full declarations, provided that the equivalent single declarations would be allowed. Deferred constant declarations are useful for declaring constants of private views, and types with components of private views. They are also useful for declaring access-to-constant objects that designate variables declared in the private part of a package. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of deferred constant declarations:} @begin{Example} Null_Key : @key[constant] Key; --@RI[ see @RefSecNum{Private Operations}] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} CPU_Identifier : @key[constant] String(1..8)@Chg{Version=[3],New=[],Old=[;]} @Chg{Version=[3],New=[ @key[with]],Old=[@key[pragma]]} Import@Chg{Version=[3],New=[ => True, Convention => ],Old=[(]}Assembler, @Chg{Version=[3],New=[],Old=[CPU_Identifier, ]}Link_Name => "CPU_ID"@Chg{Version=[3],New=[],Old=[)]}; --@RI[ see @RefSecNum{Interfacing Aspects}] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, a deferred constant is required to be of a private type declared in the same visible part. This restriction is removed for Ada 95; deferred constants can be of any type. In Ada 83, a deferred constant declaration was not permitted to include a constraint, nor the reserved word @key(aliased). In Ada 83, the rules required conformance of type marks; here we require static matching of subtypes if the deferred constant is constrained. A deferred constant declaration can be completed with a @nt{pragma} Import. Such a deferred constant declaration need not be within a @nt{package_specification}. The rules for too-early uses of deferred constants are modified in Ada 95 to allow more cases, and catch all errors at compile time. This change is necessary in order to allow deferred constants of a tagged type without violating the principle that for a dispatching call, there is always an implementation to dispatch to. It has the beneficial side effect of catching some Ada-83-erroneous programs at compile time. The new rule fits in well with the new freezing-point rules. Furthermore, we are trying to convert undefined-value problems into bounded errors, and we were having trouble for the case of deferred constants. Furthermore, uninitialized deferred constants cause trouble for the shared variable / tasking rules, since they are really variable, even though they purport to be constant. In Ada 95, they cannot be touched until they become constant. Note that we do not consider this change to be an upward incompatibility, because it merely changes an erroneous execution in Ada 83 into a compile-time error. The Ada 83 semantics are unclear in the case where the full view turns out to be an access type. It is a goal of the language design to prevent uninitialized access objects. One wonders if the implementation is required to initialize the deferred constant to null, and then initialize it (again!) to its real value. In Ada 95, the problem goes away. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Since deferred constants can now be of a nonprivate type, we have made this a stand-alone @Chg{Version=[3],New=[subclause],Old=[clause]}, rather than a subclause of @RefSec{Private Types and Private Extensions}. Deferred constant declarations used to have their own syntax, but now they are simply a special case of @nt<object_declaration>s. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00385-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Deferred constants were enhanced to allow the use of anonymous access types in them.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added matching rules for subtypes that exclude null.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0062-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected rules so that the intent that a full constant may have a null exclusion even if the deferred constant does not is actually met.]} @end{DiffWord2005} @LabeledClause{Limited Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @redundant[A limited type is (a view of) a type for which @Chg{Version=[2],New=[copying (such as for an @nt{assignment_statement})], Old=[the assignment operation]} is not allowed. A nonlimited type is a (view of a) type for which @Chg{Version=[2],New=[copying], Old=[the assignment operation]} is allowed.] @begin{Discussion} The concept of the @i(value) of a limited type is difficult to define, since the abstract value of a limited type often extends beyond its physical representation. In some sense, values of a limited type cannot be divorced from their object. The value @i(is) the object. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} In Ada 83, in the two places where limited types were defined by the language, namely tasks and files, an implicit level of indirection was implied by the semantics to avoid the separation of the value from an associated object. In Ada 95, most limited types are passed by reference, and even return-ed by reference.@Chg{Version=[2],New=[ In Ada 2005, most limited types are built-in-place upon return, rather than returned by reference. Thus the object @lquotes@;identity@rquotes is part of the logical value of most limited types.],Old=[]} @end{Discussion} @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00419-01]} For a limited partial view whose full view is nonlimited, @Chg{Version=[2],New=[copying],Old=[assignment]} is possible on parameter passing and function return. To prevent any copying whatsoever, one should make both the partial @i{and} full views limited. @end{Honest} @Comment{The below was moved from a ChgToGlossaryAlso.} @ChgToGlossary{Version=[2],Kind=[Revised],Term=<Limited type>, Text=<A limited type is @Chg{Version=[2],New=[],Old=[(a view of) ]}a type for which @Chg{Version=[2],New=[copying (such as in an @nt{assignment_statement})], Old=[the assignment operation]} is not allowed. A nonlimited type is a @Chg{Version=[2],New=[],Old=[(view of a) ]}type for which @Chg{Version=[2],New=[copying], Old=[the assignment operation]} is allowed.>} @end{Intro} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} If a tagged record type has any limited components, then the reserved word @key[limited] shall appear in its @nt<record_type_definition>.@Chg{Version=[2],New=[ @Redundant[If the reserved word @key[limited] appears in the definition of a @nt{derived_type_definition}, its parent type and any progenitor interfaces shall be limited.]],Old=[]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[The rule about the parent type being required to be limited can be found in @RefSecNum{Derived Types and Classes}. Rules about progenitor interfaces can be found in @RefSecNum{Interface Types}, specifically, a nonlimited interface can appear only on a nonlimited type. We repeat these rules here to gather these scattered rules in one obvious place.]} @end{TheProof} @begin{Reason} @leading@;This prevents tagged limited types from becoming nonlimited. Otherwise, the following could happen: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[limited] @key[private]; @key[type] R @key[is] @key[tagged] @key[record] --@RI{ Illegal!} --@RI{ This should say @lquotes@;@key[limited record]@rquotes@;.} X : T; @key[end] @key[record]; @key[private] @key[type] T @key[is] @key[new] Integer; --@RI{ R becomes nonlimited here.} @key[end] P; @ChgRef{Version=[2],Kind=[Revised]} @key[package] Q @key[is] @key[type] R2@Chg{Version=[2],New=[],Old=[(Access_Discrim : @key[access] ...)]} @key[is] @key[new] R @key[with] @key[record] Y : Some_Task_Type; @key[end] @key[record]; @key[end] Q; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} If the above were legal, then assignment would be defined for R'Class in the body of P, which is bad news, given @Chg{Version=[2],New=[],Old=[the access discriminant and ]}the task. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0147-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the following contexts, an @nt{expression} of a limited type is not permitted unless it is an @nt{aggregate}, a @nt{function_call}, @Chg{Version=[3],New=[],Old=[or ]}a parenthesized @nt{expression} or @nt{qualified_expression} whose operand is permitted by this rule@Chg{Version=[3],New=[, or a @nt{conditional_expression} all of whose @Syni{dependent_}@nt{expression}s are permitted by this rule],Old=[]}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the initialization @nt{expression} of an @nt{object_declaration} (see @RefSecNum{Object Declarations})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{default_expression} of a @nt{component_declaration} (see @RefSecNum{Record Types})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} of a @nt{record_component_association} (see @RefSecNum{Record Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} for an @nt{ancestor_part} of an @nt{extension_aggregate} (see @RefSecNum{Extension Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[an @nt{expression} of a @nt{positional_array_aggregate} or the @nt{expression} of an @nt{array_component_association} (see @RefSecNum{Array Aggregates})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{qualified_expression} of an initialized allocator (see @RefSecNum{Allocators})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[the @nt{expression} of a return statement (see @RefSecNum{Return Statements})],Old=[]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0177-1]} @Chg{Version=[3],New=[the @nt{expression} of an @nt{expression_function_declaration} (see @RefSecNum{Expression Functions})],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{Only because the paragraph number has changed} @Chg{Version=[2],New=[the @nt{default_expression} or actual parameter for a formal object of mode @b{in} (see @RefSecNum{Formal Objects})],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[All of these contexts normally require copying; by restricting the uses as above, we can require the new object to be built-in-place.]} @end{Discussion} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0178-1]} @leading@keepnext@Defn{limited type} A @Chg{Version=[3],New=[view of a ],Old=[]}type is @i{limited} if it is @Chg{Version=[2],New=[],Old=[a descendant of ]}one of the following: @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00411-01],ARef=[AI95-00419-01]} a type with the reserved word @key(limited)@Chg{Version=[2],New=[, @key(synchronized), @key(task), or @key(protected) ],Old=[]} in its definition; @begin{Ramification} Note that there is always a @lquotes@;definition,@rquotes@; conceptually, even if there is no syntactic category called @lquotes@;..._definition@rquotes@;. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[This includes interfaces of the above kinds, derived types with the reserved word @key{limited}, as well as task and protected types.]} @end{Ramification} @ChgNote{This should really be deleted in Version 2, but we want to reuse the paragraph number, and that is hard, so we add the message manually.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0087-1]} @Chg{Version=[3],New=[a class-wide type whose specific type is limited;], Old=[@Chg{Version=[2],New=[@Shrink{@i<This paragraph was deleted.>}], Old=[a task or protected type;]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} a composite type with a limited component@Chg{Version=[2],New=[;],Old=[.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0178-1]} @ChgAdded{Version=[3],Text=[an incomplete view;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[a derived type whose parent is limited and is not an interface.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Limitedness is not inherited from interfaces; it must be explicitly specified when the parent is an interface.]} @end{Ramification} @end(itemize) @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[A derived type can become nonlimited if @key{limited} does not appear and the derivation takes place in the visible part of a child package, and the parent type is nonlimited as viewed from the private part or body of the child package.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[We considered a rule where limitedness was always inherited from the parent for derived types, but in the case of a type whose parent is an interface, this meant that the first interface is treated differently than other interfaces. It also would have forced users to declare dummy nonlimited interfaces just to get the limitedness right. We also considered a syntax like @key{not limited} to specify nonlimitedness when the parent was limited, but that was unsavory. The rule given is more uniform and simpler to understand.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[The rules for interfaces are asymmetrical, but the language is not: if the parent interface is limited, the presence of the word @key{limited} determines the limitedness, and nonlimited progenitors are illegal by the rules in @RefSecNum{Interface Types} if @key{limited} is present. If the parent interface is nonlimited, the word @key{limited} is illegal by the rules in @RefSecNum{Derived Types and Classes}. The net effect is that the order of the interfaces doesn't matter.]} @end{Reason} @Defn{nonlimited type} Otherwise, the type is nonlimited. @Redundant[There are no predefined equality operators for a limited type.] @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0052-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[A type is @i{immutably limited} if it is one of the following:@Defn{immutably limited}@Defn2{Term=[limited type],Sec=[immutably]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[An explicitly limited record type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0217-1]} @ChgAdded{Version=[3],Text=[A record extension with the reserved word @key[limited];]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[A nonformal limited private type that is tagged or has at least one access discriminant with a @nt{default_expression};]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The full type in both of these cases must necessarily be immutably limited. We need to include private types as much as possible so that we aren't unintentionally discouraging the use of private types.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[A task type, a protected type, or a synchronized interface;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[A type derived from an immutably limited type.]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An immutably limited type is a type that cannot become nonlimited subsequently in a private part or in a child unit. If a view of the type makes it immutably limited, then no copying (assignment) operations are ever available for objects of the type. This allows other properties; for instance, it is safe for such objects to have access discriminants that have defaults or designate other limited objects.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A nonsynchronized limited interface type is not immutably limited; a type derived from it can be nonlimited.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0052-1]} @ChgAdded{Version=[3],Text=[A descendant of a generic formal limited private type is presumed to be immutably limited except within the body of a generic unit or a body declared within the declarative region of a generic unit, if the formal type is declared within the formal part of the generic unit.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In an instance, a type is descended from the actual type corresponding to the formal, and all rules are rechecked in the specification. Bodies are excepted so that we assume the worst there; the complex wording is required to handle children of generics and unrelated bodies properly.]} @end{Ramification} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0067-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[ For an @nt{aggregate} of a limited type used to initialize an object as allowed above, the implementation shall not create a separate anonymous object for the @nt{aggregate}. For a @nt{function_call} of a type with a part that is of a task, protected, or explicitly limited record type that is used to initialize an object as allowed above, the implementation shall not create a separate return object (see 6.5) for the @nt{function_call}. The @nt{aggregate} or @nt{function_call} shall be constructed directly in the new object.],Old=[]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0067-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[For a @nt{function_call}, we only require @i{build-in-place}@PDefn{build-in-place} for a limited type that would have been a return-by-reference type in Ada 95. We do this because we want to minimize disruption to Ada 95 implementations and users.],Old=[]}]} @end{Discussion} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} @Chg{Version=[2],New=[While it is allowed to write initializations of limited objects, such initializations never copy a limited object. The source of such an assignment operation must be an @nt<aggregate> or @nt<function_call>, and such @nt<aggregate>s and @nt<function_call>s must be built directly in the target object@Chg{Version=[3],New=[ (see @RefSecNum{Assignment and Finalization})],Old=[]}.], Old=[@leading@keepnext@;The following are consequences of the rules for limited types:]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This isn't quite true if the type can become nonlimited (see below); @nt{function_call}s only are required to be build-in-place for @lquotes@;really@rquotes@; limited types.]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 10 through 15 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[An initialization expression is not allowed in an @nt{object_declaration} if the type of the object is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A default expression is not allowed in a @nt{component_declaration} if the type of the record component is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[An initialized allocator is not allowed if the designated type is limited.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[A generic formal parameter of mode @key[in] must not be of a limited type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[@nt{Aggregate}s are not available for a limited composite type. Concatenation is not available for a limited array type.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[The rules do not exclude a @nt{default_expression} for a formal parameter of a limited type; they do not exclude a deferred constant of a limited type if the full declaration of the constant is of a nonlimited type.]} @Defn{become nonlimited} @Defn2{Term=[nonlimited type],Sec=(becoming nonlimited)} @Defn2{Term=[limited type],Sec=(becoming nonlimited)} As illustrated in @RefSecNum{Private Operations}, an untagged limited type can become nonlimited under certain circumstances. @begin{Ramification} Limited private types do not become nonlimited; instead, their full view can be nonlimited, which has a similar effect. It is important to remember that a single nonprivate type can be both limited and nonlimited in different parts of its scope. In other words, @lquotes@;limited@rquotes@; is a property that depends on where you are in the scope of the type. We don't call this a @lquotes@;view property@rquotes@; because there is no particular declaration to declare the nonlimited view. Tagged types never become nonlimited. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a package with a limited type:} @begin{Example} @key[package] IO_Package @key[is] @key[type] File_Name @key[is] @key[limited] @key[private]; @key[procedure] Open (F : @key[in] @key[out] File_Name); @key[procedure] Close(F : @key[in] @key[out] File_Name); @key[procedure] Read (F : @key[in] File_Name; Item : @key[out] Integer); @key[procedure] Write(F : @key[in] File_Name; Item : @key[in] Integer); @key[private] @key[type] File_Name @key[is] @key[limited] @key[record] Internal_Name : Integer := 0; @key[end] @key[record]; @key[end] IO_Package; @key[package] @key[body] IO_Package @key[is] Limit : @key[constant] := 200; @key[type] File_Descriptor @key[is] @key[record] ... @key[end] @key[record]; Directory : @key[array] (1 .. Limit) @key[of] File_Descriptor; ... @key[procedure] Open (F : @key[in] @key[out] File_Name) @key[is] ... @key[end]; @key[procedure] Close(F : @key[in] @key[out] File_Name) @key[is] ... @key[end]; @key[procedure] Read (F : @key[in] File_Name; Item : @key[out] Integer) @key[is] ... @key[end]; @key[procedure] Write(F : @key[in] File_Name; Item : @key[in] Integer) @key[is] ... @key[end]; @key[begin] ... @key[end] IO_Package; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the example:} In the example above, an outside subprogram making use of IO_Package may obtain a file name by calling Open and later use it in calls to Read and Write. Thus, outside the package, a file name obtained from Open acts as a kind of password; its internal properties (such as containing a numeric value) are not known and no other operations (such as addition or comparison of internal names) can be performed on a file name. Most importantly, clients of the package cannot make copies of objects of type File_Name. @NoPrefix@;This example is characteristic of any case where complete control over the operations of a type is desired. Such packages serve a dual purpose. They prevent a user from making use of the internal structure of the type. They also implement the notion of an encapsulated data type where the only operations on the type are those given in the package specification. @NoPrefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} The fact that the full view of File_Name is explicitly declared @key[limited] means that parameter passing @Chg{Version=[2],New=[], Old=[and function return ]}will always be by reference@Chg{Version=[2],New=[ and function results will always be built directly in the result object],Old=[]} (see @RefSecNum{Formal Parameter Modes} and @RefSecNum{Return Statements}). @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The restrictions in RM83-7.4.4(4), which disallowed @key[out] parameters of limited types in certain cases, are removed. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Since limitedness and privateness are orthogonal in Ada 95 (and to some extent in Ada 83), this is now its own @Chg{Version=[3],New=[subclause],Old=[clause]} rather than being a subclause of @RefSec{Private Types and Private Extensions}. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Limited types now have an assignment operation, but its use is restricted such that all uses are build-in-place. This is accomplished by restricting uses to @nt{aggregate}s and @nt{function_call}s. @nt{Aggregate}s were not allowed to have a limited type in Ada 95, which causes a compatibility issue discussed in @RefSec{Aggregates}. Compatibility issues with return statements for limited @nt{function_call}s are discussed in @RefSec{Return Statements}.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00411-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[Rewrote the definition of limited to ensure that interfaces are covered, but that limitedness is not inherited from interfaces. Derived types that explicitly include @key{limited} are now also covered.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0052-1],ARef=[AI05-0217-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a definition for immutably limited types, so that the fairly complex definition does not need to be repeated in rules elsewhere in the Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The built-in-place rules are consolidated in @RefSecNum{Assignment and Finalization}, and thus they are removed from this subclause.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0087-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Fixed an oversight: class-wide types were never defined to be limited, even if their associated specific type is. It is thought that this oversight was never implemented incorrectly by any compiler, thus we have not classified it as an incompatibility.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0147-1]} @ChgAdded{Version=[3],Text=[Allowed @nt{conditional_expression}s in limited constructor contexts @em we want to treat these as closely to parentheses as possible.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0178-1]} @ChgAdded{Version=[3],Text=[Added wording so that expression functions can return limited entities.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0178-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added incomplete views to the list of reasons for a view of a type to be limited. This is not a change as the definition already was in @RefSecNum{Incomplete Type Declarations}. But it is much better to have all of the reasons for limitedness together.]} @end{DiffWord2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledRevisedClause{Version=[3],New=[Assignment and Finalization],Old=[User-Defined Assignment and Finalization]} @begin{Intro} @redundant[@Defn{user-defined assignment} @Defn2{Term=[assignment], Sec=(user-defined)} Three kinds of actions are fundamental to the manipulation of objects: initialization, finalization, and assignment. Every object is initialized, either explicitly or by default, after being created (for example, by an @nt{object_declaration} or @nt{allocator}). Every object is finalized before being destroyed (for example, by leaving a @nt{subprogram_body} containing an @nt{object_declaration}, or by a call to an instance of Unchecked_Deallocation). An assignment operation is used as part of @nt{assignment_statement}s, explicit initialization, parameter passing, and other operations. @IndexSee{Term=[constructor],See=[initialization]} @IndexSee{Term=[constructor],See=[Initialize]} @IndexSee{Term=[destructor],See=[finalization]} Default definitions for these three fundamental operations are provided by the language, but @Defn{controlled type} a @i{controlled} type gives the user additional control over parts of these operations. @Defn{Initialize}@Defn{Finalize}@Defn{Adjust} In particular, the user can define, for a controlled type, an Initialize procedure which is invoked immediately after the normal default initialization of a controlled object, a Finalize procedure which is invoked immediately before finalization of any of the components of a controlled object, and an Adjust procedure which is invoked as the last step of an assignment to a (nonlimited) controlled object.] @ToGlossary{Term=<Controlled type>, Text=<A controlled type supports user-defined assignment and finalization. Objects are always finalized before being destroyed.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01],ARef=[AI95-00287-01]} Here's the basic idea of initialization, value adjustment, and finalization, whether or not user defined: When an object is created, if it is explicitly assigned an initial value, @Chg{Version=[2],New=[the object is either built-in-place from an @nt{aggregate} or function call (in which case neither Adjust nor Initialize is applied), or ],Old=[]} the assignment copies and adjusts the initial value. Otherwise, Initialize is applied to it (except in the case of an @nt{aggregate} as a whole). An @nt{assignment_statement} finalizes the target before copying in and adjusting the new value. Whenever an object goes away, it is finalized. Calls on Initialize and Adjust happen bottom-up; that is, components first, followed by the containing object. Calls on Finalize @Chg{Version=[2],New=[happen],Old=[happens]} top-down; that is, first the containing object, and then its components. These ordering rules ensure that any components will be in a well-defined state when Initialize, Adjust, or Finalize is applied to the containing object. @end{Ramification} @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{Example}@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @key[package] Ada.Finalization @key[is]@ChildUnit{Parent=[Ada],Child=[Finalization]} @key[pragma] @Chg{Version=[3],New=[Pure],Old=[Preelaborate]}(Finalization);@Chg{Version=[3],New=[],Old=[@Chg{New=[ @key[pragma] Remote_Types(Finalization);],Old=[]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Controlled} @key[is abstract tagged private];@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Controlled);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @key(procedure) @AdaSubDefn{Initialize} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Adjust} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Finalize} (Object : @key(in out) Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Limited_Controlled} @key[is abstract tagged limited private];@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Limited_Controlled);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @key(procedure) @AdaSubDefn{Initialize} (Object : @key(in out) Limited_Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(procedure) @AdaSubDefn{Finalize} (Object : @key(in out) Limited_Controlled)@Chg{Version=[2],New=[ @key{is null}],Old=[]}; @key(private) ... -- @RI{not specified by the language} @key[end] Ada.Finalization; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Defn{controlled type} A controlled type is a descendant of Controlled or Limited_Controlled. @Chg{Version=[2],New=[],Old=[The (default) implementations of Initialize, Adjust, and Finalize have no effect. ]}The predefined "=" operator of type Controlled always returns True, @Redundant[since this operator is incorporated into the implementation of the predefined equality operator of types derived from Controlled, as explained in @RefSecNum(Relational Operators and Membership Tests).] The type Limited_Controlled is like Controlled, except that it is limited and it lacks the primitive subprogram Adjust. @begin{Discussion} We say @lquotes@;nonlimited controlled type@rquotes@ (rather than just @lquotes@;controlled type@rquotes@;;) when we want to talk about descendants of Controlled only. @end{Discussion} @begin{Reason} We considered making Adjust and Finalize abstract. However, a reasonable coding convention is e.g. for Finalize to always call the parent's Finalize after doing whatever work is needed for the extension part. (Unlike CLOS, we have no way to do that automatically in Ada 95.) For this to work, Finalize cannot be abstract. In a generic unit, for a generic formal abstract derived type whose ancestor is Controlled or Limited_Controlled, calling the ancestor's Finalize would be illegal if it were abstract, even though the actual type might have a concrete version. Types Controlled and Limited_Controlled are abstract, even though they have no abstract primitive subprograms. It is not clear that they need to be abstract, but there seems to be no harm in it, and it might make an implementation's life easier to know that there are no objects of these types @em in case the implementation wishes to make them @lquotes@;magic@rquotes@; in some way. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[For Ada 2005, we considered making these types interfaces. That would have the advantage of allowing them to be added to existing trees. But that was rejected both because it would cause massive disruptions to existing implementations, and because it would be very incompatible due to the "no hidden interfaces" rule. The latter rule would prevent a tagged private type from being completed with a derivation from Controlled or Limited_Controlled @em a very common idiom.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A type is said to @i{need finalization} if:@Defn{needs finalization}@Defn2{Term=[type],Sec=[needs finalization]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is a controlled type, a task type or a protected type; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[it has a component @Chg{Version=[3],New=[whose type ],Old=[that ]} needs finalization; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0013-1]} @Chg{Version=[3],New=[it is a class-wide type; or], Old=[@Chg{Version=[2],New=[it is a limited type that has an access discriminant whose designated type needs finalization; or],Old=[]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0026-1]} @ChgAdded{Version=[3],Text=[it is a partial view whose full view needs finalization; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[it is one of a number of language-defined types that are explicitly defined to need finalization.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The fact that a type needs finalization does not require it to be implemented with a controlled type. It just has to be recognized by the No_Nested_Finalization restriction.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This property is defined for the type, not for a particular view. That's necessary as restrictions look in private parts to enforce their restrictions; the point is to eliminate all controlled parts, not just ones that are visible.]} @end{Ramification} @end{Itemize} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} @Chg{Version=[2],New=[],Old=[@PDefn2{Term=[elaboration], Sec=(object_declaration)}]}During the elaboration @Chg{Version=[2],New=[or evaluation of a construct that causes an object to be initialized by default],Old=[of an @nt{object_declaration}]}, for every controlled subcomponent of the object that is not assigned an initial value (as defined in @RefSecNum{Object Declarations}), Initialize is called on that subcomponent. Similarly, if the object @Chg{Version=[2],New=[that is initialized by default ],Old=[]}as a whole is controlled@Chg{Version=[2],New=[],Old=[ and is not assigned an initial value]}, Initialize is called on the object.@Chg{Version=[2], New=[],Old=[ The same applies to the evaluation of an @nt{allocator}, as explained in @RefSecNum{Allocators}.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00373-01]} For an @nt{extension_aggregate} whose @nt{ancestor_part} is a @nt{subtype_mark}@Chg{Version=[2],New=[ denoting a], Old=[, @Chg{New=[for each controlled subcomponent of the ancestor part, either Initialize is called, or its initial value is assigned, as appropriate], Old=[Initialize is called on all controlled subcomponents of the ancestor part]}; if the type of the ancestor part is itself]} controlled@Chg{Version=[2],New=[ subtype],Old=[]}, the Initialize procedure of the ancestor type is called, unless that Initialize procedure is abstract. @begin{Discussion} @leading@keepnext@;Example: @begin{Example} @key[type] T1 @key[is] @key[new] Controlled @key[with] @key[record] ... --@RI{ some components might have defaults} @key[end] @key[record]; @key[type] T2 @key[is] @key[new] Controlled @key[with] @key[record] X : T1; --@RI{ no default} Y : T1 := ...; --@RI{ default} @key[end] @key[record]; A : T2; B : T2 := ...; @end{Example} As part of the elaboration of A's declaration, A.Y is assigned a value; therefore Initialize is not applied to A.Y. Instead, Adjust is applied to A.Y as part of the assignment operation. Initialize is applied to A.X and to A, since those objects are not assigned an initial value. The assignment to A.Y is not considered an assignment to A. For the elaboration of B's declaration, Initialize is not called at all. Instead the assignment adjusts B's value; that is, it applies Adjust to B.X, B.Y, and B. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00373-01]} @ChgAdded{Version=[1],Text=[The @nt{ancestor_part} of an @nt{extension_aggregate}@Chg{Version=[2],New=[, <> in aggregates, and the return object of an @nt{extended_return_statement} are],Old=[ is]} handled similarly.]} @end{Discussion} Initialize and other initialization operations are done in an arbitrary order, except as follows.@PDefn2{Term=[arbitrary order],Sec=[allowed]} Initialize is applied to an object after initialization of its subcomponents, if any @Redundant[(including both implicit initialization and Initialize calls)]. If an object has a component with an access discriminant constrained by a per-object expression, Initialize is applied to this component after any components that do not have such discriminants. For an object with several components with such a discriminant, Initialize is applied to them in order of their @nt{component_declaration}s. For an @nt<allocator>, any task activations follow all calls on Initialize. @begin{Reason} The fact that Initialize is done for subcomponents first allows Initialize for a composite object to refer to its subcomponents knowing they have been properly initialized. The fact that Initialize is done for components with access discriminants after other components allows the Initialize operation for a component with a self-referential access discriminant to assume that other components of the enclosing object have already been properly initialized. For multiple such components, it allows some predictability. @end{Reason} @leading@keepnext@Defn{assignment operation} When a target object with any controlled parts is assigned a value, @Redundant[either when created or in a subsequent @nt{assignment_statement},] the @i{assignment operation} proceeds as follows: @begin(itemize) The value of the target becomes the assigned value. @Defn{adjusting the value of an object} @Defn{adjustment} The value of the target is @i{adjusted.} @end(itemize) @begin{Ramification} If any parts of the object are controlled, abort is deferred during the assignment operation. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]}@Comment{May need future changes.} @Defn{adjusting the value of an object} @Defn{adjustment} To adjust the value of a @Chg{Version=[3],New=[],Old=[@Redundant[(nonlimited)] ]}composite object, the values of the components of the object are first adjusted in an arbitrary order, and then, if the object is @Chg{Version=[3],New=[nonlimited ],Old=[]}controlled, Adjust is called.@PDefn2{Term=[arbitrary order],Sec=[allowed]} Adjusting the value of an elementary object has no effect@Redundant[, nor does adjusting the value of a composite object with no controlled parts.] @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} Adjustment is never @Chg{Version=[3],New=[actually ],Old=[]}performed for values of @Chg{Version=[3],New=[an immutably],Old=[a by-reference]} limited type, since @Chg{Version=[3],New=[all assignment operations for such types are required to be built-in-place. Even so, we still define adjustment for all types in order that the canonical semantics is well-defined],Old=[these types do not support copying]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The verbiage in the Initialize rule about access discriminants constrained by per-object expressions is not necessary here, since such types are @Chg{Version=[3],New=[either ],Old=[]}limited@Chg{Version=[3],New=[ or do not have defaults, so the discriminant can only be changed by an assignment to an outer object. Such an assignment could happen only before any adjustments or (if part of an outer Adjust) only after any inner (component) adjustments have completed.], Old=[, and therefore are never adjusted.]} @end{Reason} @PDefn2{Term=[execution], Sec=(assignment_statement)} For an @nt{assignment_statement}, @Redundant[ after the @nt{name} and @nt{expression} have been evaluated, and any conversion (including constraint checking) has been done,] an anonymous object is created, and the value is assigned into it; @Redundant[that is, the assignment operation is applied]. @Redundant[(Assignment includes value adjustment.)] The target of the @nt{assignment_statement} is then finalized. The value of the anonymous object is then assigned into the target of the @nt{assignment_statement}. Finally, the anonymous object is finalized. @Redundant[As explained below, the implementation may eliminate the intermediate anonymous object, so this description subsumes the one given in @RefSec{Assignment Statements}.] @begin{Reason} @leading@;An alternative design for user-defined assignment might involve an Assign operation instead of Adjust: @begin{Example} @key[procedure] Assign(Target : @key[in] @key[out] Controlled; Source : @key[in] @key[out] Controlled); @end{Example} @leading@keepnext@;Or perhaps even a syntax like this: @begin{Example} @key[procedure] ":="(Target : @key[in] @key[out] Controlled; Source : @key[in] @key[out] Controlled); @end{Example} @leading@;Assign (or ":=") would have the responsibility of doing the copy, as well as whatever else is necessary. This would have the advantage that the Assign operation knows about both the target and the source at the same time @em it would be possible to do things like reuse storage belonging to the target, for example, which Adjust cannot do. However, this sort of design would not work in the case of unconstrained discriminated variables, because there is no way to change the discriminants individually. For example: @begin{Example} @key[type] Mutable(D : Integer := 0) @key[is] @key[record] X : Array_Of_Controlled_Things(1..D); @key[case] D @key[is] @key[when] 17 => Y : Controlled_Thing; @key[when] @key[others] => @key[null]; @key[end] D; @key[end] @key[record]; @end{Example} An assignment to an unconstrained variable of type Mutable can cause some of the components of X, and the component Y, to appear and/or disappear. There is no way to write the Assign operation to handle this sort of case. Forbidding such cases is not an option @em it would cause generic contract model violations. @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[When a function call or @nt{aggregate} is used to initialize an object, the result of the function call or @nt{aggregate} is an anonymous object, which is assigned into the newly-created object. For such an assignment, the anonymous object might be @i<built in place>,@Defn{built in place}@Seeother{Primary=[build-in-place],Other=[built in place]} in which case the assignment does not involve any copying. Under certain circumstances, the anonymous object is required to be built in place. In particular:]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[We say assignment to built-in-place objects does not involve copying, which matches the intended implementation (see below). Of course, the implementation can do any copying it likes, if it can make such copying semantically invisible (by patching up access values to point to the copy, and so forth).]} @end{Discussion} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If the full type of any part of the object is immutably limited, the anonymous object is built in place.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[We talk about the full types being immutably limited, as this is independent of the view of a type (in the same way that it is for determining the technique of parameter passing). That is, privacy is ignored for this purpose.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[For function calls, we only require building in place for immutably limited types. These are the types that would have been return-by-reference types in Ada 95. We limited the requirement because we want to minimize disruption to Ada 95 implementations and users.]} @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0232-1]} @ChgAdded{Version=[3],Text=[This is a dynamic property and is determined by the specific type of the parts of the actual object. In particular, if a part has a class-wide type, the tag of the object might need to be examined in order to determine if build-in-place is required. However, we expect that most Ada implementations will determine this property at compile-time using some assume-the-worst algorithm in order to chose the appropriate method to implement a given call or aggregate. In addition, there is no attribute or other method for a program to determine if a particular object has this property (or not), so there is no value to a more careful description of this rule.]} @end{Honest} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In the case of an @nt{aggregate}, if the full type of any part of the newly-created object is controlled, the anonymous object is built in place.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[This is necessary to prevent elaboration problems with deferred constants of controlled types. Consider:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[package] P @key[is] @key[type] Dyn_String @key[is private]; Null_String : @key[constant] Dyn_String; ... @key[private] @key[type] Dyn_String @key[is new] Ada.Finalization.Controlled @key[with] ... @key[procedure] Finalize(X : @key[in out] Dyn_String); @key[procedure] Adjust(X : @key[in out] Dyn_String); @comment{Blank Line} Null_String : @key[constant] Dyn_String := (Ada.Finalization.Controlled @key[with] ...); ... @key[end] P;]} @end{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[When Null_String is elaborated, the bodies of Finalize and Adjust clearly have not been elaborated. Without this rule, this declaration would necessarily raise Program_Error (unless the permissions given below are used by the implementation).]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An @nt{aggregate} with a controlled part used in the return expression of a @nt{simple_@!return_@!statement} has to be built in place in the anonymous return object, as this is similar to an object declaration. (This is a change from Ada 95, but it is not an inconsistency as it only serves to restrict implementation choices.) But this only covers the @nt{aggregate}; a separate anonymous return object can still be used unless it too is required to be built in place.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Similarly, an @nt{aggregate} that has a controlled part but is not itself controlled and that is used to initialize an object also has to be built in place. This is also a change from Ada 95, but it is not an inconsistency as it only serves to restrict implementation choices. This avoids problems if a type like Dyn_String (in the example above) is used as a component in a type used as a deferred constant in package P.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In other cases, it is unspecified whether the anonymous object is built in place.@PDefn{unspecified}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is left unspecified so the implementation can use any appropriate criteria for determining when to build in place. That includes making the decision on a call-by-call basis. Reasonable programs will not care what decision is made here anyway.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Notwithstanding@Defn{notwithstanding} what this International Standard says elsewhere, if an object is built in place:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Upon successful completion of the return statement or @nt{aggregate}, the anonymous object @i<mutates into> the newly-created object; that is, the anonymous object ceases to exist, and the newly-created object appears in its place.@Defn{mutates}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Finalization is not performed on the anonymous object.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Adjustment is not performed on the newly-created object.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[All access values that designate parts of the anonymous object now designate the corresponding parts of the newly-created object.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[All renamings of parts of the anonymous object now denote views of the corresponding parts of the newly-created object.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Coextensions of the anonymous object become coextensions of the newly-created object.]} @end{Itemize} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This @ldquote@;mutating@rdquote does not necessarily happen atomically with respect to abort and other tasks. For example, if a function call is used as the parent part of an @nt{extension_aggregate}, then the tag of the anonymous object (the function result) will be different from the tag of the newly-created object (the parent part of the @nt{extension_aggregate}). In implementation terms, this involves modifying the tag field. If the current task is aborted during this modification, the object might become abnormal. Likewise, if some other task accesses the tag field during this modification, it constitutes improper use of shared variables, and is erroneous.]} @end{Honest} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The intended implementation is that the anonymous object is allocated at the same address as the newly-created object. Thus, no run-time action is required to cause all the access values and renamings to point to the right place. They just point to the newly-created object, which is what the return object has magically @ldquote@;mutated into@rdquote.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There is no requirement that 'Address of the return object is equal to 'Address of the newly-created object, but that will be true in the intended implementation.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For a function call, if the size of the newly-created object is known at the call site, the object is allocated there, and the address is implicitly passed to the function; the return object is created at that address. Otherwise, a storage pool is implicitly passed to the function; the size is determined at the point of the return statement, and passed to the Allocate procedure. The address returned by the storage pool is returned from the function, and the newly-created object uses that same address. If the return statement is left without returning (via an exception or a goto, for example), then Deallocate is called. The storage pool might be a dummy pool that represents @ldquote@;allocate on the stack@rdquote.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The Tag of the newly-created object may be different from that of the result object. Likewise, the master and accessibility level may be different.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An alternative implementation model might allow objects to move around to different addresses. In this case, access values and renamings would need to be modified at run time. It seems that this model requires the full power of tracing garbage collection.]} @end{ImplNote} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0022],ARef=[AI95-00083-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0067-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[1],New=[For an @nt{aggregate} of a controlled type whose value is assigned, other than by an @nt{assignment_statement}@Chg{Version=[2],New=[],Old=[ or a @nt{return_statement}]}, the implementation shall not create a separate anonymous object for the @nt{aggregate}. The @nt{aggregate} value shall be constructed directly in the target of the assignment operation and Adjust is not called on the target object.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0067-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[@Chg{Version=[1],New=[@Chg{Version=[2], New=[@PDefn{build-in-place}],Old=[]}This@Chg{Version=[2], New=[ @i<build-in-place> requirement],Old=[]} is necessary to prevent elaboration problems with deferred constants of controlled types. Consider:],Old=[]}]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@Chg{New=[@key[package] P @key[is] @key[type] Dyn_String @key[is private]; Null_String : @key[constant] Dyn_String; ... @key[private] @key[type] Dyn_String @key[is new] Ada.Finalization.Controlled @key[with] ... @key[procedure] Finalize(X : @key[in out] Dyn_String); @key[procedure] Adjust(X : @key[in out] Dyn_String); @comment{Blank Line} Null_String : @key[constant] Dyn_String := (Ada.Finalization.Controlled @key[with] ...); ... @key[end] P;],Old=[]}]} @end{Example} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@Chg{New=[When Null_String is elaborated, the bodies of Finalize and Adjust clearly have not been elaborated. Without this rule, this declaration would necessarily raise Program_Error (unless the permissions given below are used by the implementation).],Old=[]}]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[An @nt{aggregate} of a controlled type used in the return expression of a @nt{simple_@!return_@!statement} has to be built-in-place in the anonymous return object, as this is similar to an object declaration. (This is a change from Ada 95, but it is not an inconsistency as it only serves to restrict implementation choices.) But this only covers the @nt{aggregate}; a separate anonymous return object can still be used unless it too is required to be built-in-place (see @RefSecNum{Limited Types}).],Old=[]}]} @end{Ramification} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} An implementation is allowed to relax the above rules @Chg{Version=[3],New=[for @nt{assignment_statement}s], Old=[@Redundant[(for nonlimited controlled types)]]} in the following ways: @begin{TheProof} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0067-1]} @ChgDeleted{Version=[3],Text=[The phrase @lquotes@;for nonlimited controlled types@rquotes@; follows from the fact that all of the following permissions apply to cases involving assignment. It is important because the programmer can count on a stricter semantics for limited controlled types.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[The relaxations apply only to nonlimited types, as @nt{assignment_statement}s are not allowed for limited types. This is important so that the programmer can count on a stricter semantics for limited controlled types.]} @end{Ramification} @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} @Chg{Version=[3],New=[If],Old=[For an @nt{assignment_statement} that assigns to]} an object @Chg{Version=[3],New=[is assigned ],Old=[]}the value of that same object, the implementation need not do anything. @begin{Ramification} In other words, even if an object is controlled and a combination of Finalize and Adjust on the object might have a net side effect, they need not be performed. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} For @Chg{Version=[3],New=[assignment of],Old=[an @nt{assignment_statement} for]} a noncontrolled type, the implementation may finalize and assign each component of the variable separately (rather than finalizing the entire variable and assigning the entire new value) unless a discriminant of the variable is changed by the assignment. @begin{Reason} For example, in a slice assignment, an anonymous object is not necessary if the slice is copied component-by-component in the right direction, since array types are not controlled (although their components may be). Note that the direction, and even the fact that it's a slice assignment, can in general be determined only at run time. @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This potentially breaks a single assignment operation into many, and thus abort deferral (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}) needs to last only across an individual component assignment when the component has a controlled part. It is only important that the copy step is not separated (by an abort) from the adjust step, so aborts between component assignments is not harmful.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00147-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0067-1]} @Chg{Version=[3],New=[The],Old=[For an @nt{aggregate} or function call whose value is assigned into a target object, the implementation need not create a separate anonymous object if it can safely create the value of the @nt{aggregate} or function call directly in the target object. Similarly, for an @nt{assignment_@!statement}, the]} implementation need not create an anonymous object if the value being assigned is the result of evaluating a @nt{name} denoting an object (the source object) whose storage cannot overlap with the target. If the source object might overlap with the target object, then the implementation can avoid the need for an intermediary anonymous object by exercising one of the above permissions and perform the assignment one component at a time (for an overlapping array assignment), or not at all (for an assignment where the target and the source of the assignment are the same object).@Chg{Version=[2],New=[],Old=[ Even if an anonymous object is created, the implementation may move its value to the target object as part of the assignment without re-adjusting so long as the anonymous object has no aliased subcomponents.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @Chg{Version=[3],New=[If the anonymous object is eliminated by this permission, ], Old=[In the @nt{aggregate} case, only one value adjustment is necessary, and]} there is no anonymous object to be finalized@Chg{Version=[3],New=[ and thus the Finalize call on it is eliminated],Old=[]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00147-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @Chg{Version=[2],New=[@Chg{Version=[3],New=[Note that if the anonymous object is eliminated but the new value is not built in place in the target object],Old=[Similarly, in the function call case, the anonymous object can be eliminated. Note, however]}, that Adjust must be called],Old=[In the @nt{assignment_statement} case as well, no finalization of the anonymous object is needed. On the other hand, if the target has aliased subcomponents, then an adjustment takes place]} directly on the target object as the last step of the assignment, since some of the subcomponents may be self-referential or otherwise position-dependent.@Chg{Version=[2],New=[ This Adjust can be eliminated only by using one of the following permissions.],Old=[]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00147-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Furthermore, an implementation is permitted to omit implicit Initialize, Adjust, and Finalize calls and associated assignment operations on an object of a nonlimited controlled type provided that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[any omitted Initialize call is not a call on a user-defined Initialize procedure, and]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This does not apply to any calls to a user-defined Initialize routine that happen to occur in an Adjust or Finalize routine. It is intended that it is never necessary to look inside of an Adjust or Finalize routine to determine if the call can be omitted.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't want to eliminate objects for which the Initialize might have side effects (such as locking a resource).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[any usage of the value of the object after the implicit Initialize or Adjust call and before any subsequent Finalize call on the object does not change the external effect of the program, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[after the omission of such calls and operations, any execution of the program that executes an Initialize or Adjust call on an object or initializes an object by an @nt{aggregate} will also later execute a Finalize call on the object and will always do so prior to assigning a new value to the object, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the assignment operations associated with omitted Adjust calls are also omitted.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This permission applies to Adjust and Finalize calls even if the implicit calls have additional external effects.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The goal of the above permissions is to allow typical dead assignment and dead variable removal algorithms to work for nonlimited controlled types. We require that @lquotes@;pairs@rquotes@; of Initialize/Adjust/Finalize operations are removed. (These aren't always pairs, which is why we talk about @lquotes@;any execution of the program@rquotes@;.)]} @end{Reason} @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} Controlled types and user-defined finalization are new to Ada 95. (Ada 83 had finalization semantics only for masters of tasks.) @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Types Controlled and Limited_Controlled now have Preelaborable_Initialization, so that objects of types derived from these types can be used in preelaborated packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Ada.Finalization is a remote types package.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to clarify that the default initialization (whatever it is) of an ancestor part is used.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0022],ARef=[AI95-00083-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Adjust is never called on an @nt{aggregate} used for the initialization of an object or subaggregate, or passed as a parameter.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00147-01]} @ChgAdded{Version=[2],Text=[Additional optimizations are allowed for nonlimited controlled types. These allow traditional dead variable elimination to be applied to such types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Corrected the build-in-place requirement for controlled @nt{aggregate}s to be consistent with the requirements for limited types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[The operations of types Controlled and Limited_Controlled are now declared as null procedures (see @RefSecNum{Null Procedures}) to make the semantics clear (and to provide a good example of what null procedures can be used for).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[Types that need finalization are defined; this is used by the No_Nested_Finalization restriction (see @RefSec{Tasking Restrictions}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00373-01]} @ChgAdded{Version=[2],Text=[Generalized the description of objects that have Initialize called for them to say that it is done for all objects that are initialized by default. This is needed so that all of the new cases are covered.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Package Ada.Finalization now has Pure categorization, so it can be mentioned for any package. Note that this does not change the preelaborability of objects descended from Controlled and Limited_Controlled.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Eliminated coextensions from the @ldquote@;needs finalization@rdquote rules, as this cannot be determined in general in the compilation unit that declares the type. (The designated type of the coextension may have been imported as a limited view.) Uses of @ldquote@;needs finalization@rdquote need to ensure that coextensions are handled by other means (such as in No_Nested_Finalization @en see @RefSecNum{Tasking Restrictions}) or that coextensions cannot happen.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the @ldquote@;needs finalization@rdquote rules to include class-wide types, as a future extension can include a part that needs finalization.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0026-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the @ldquote@;needs finalization@rdquote rules to clearly say that they ignore privacy.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0067-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Changed @ldquote@;built in place@rdquote to @RuntimeTitle and centralized the rules here. This eliminates the fiction that built in place is just a combination of a permission and a requirement; it clearly has noticeable semantic effects. This wording change is not intended to change the semantics of any correct Ada program.]} @end{DiffWord2005} @LabeledSubClause{Completion and Finalization} @begin{Intro} @redundant[This subclause defines @i{completion} and @i{leaving} of the execution of constructs and entities. A @i{master} is the execution of a construct that includes finalization of local objects after it is complete (and after waiting for any local tasks @em see @RefSecNum(Task Dependence - Termination of Tasks)), but before leaving. Other constructs and entities are left immediately upon completion. @IndexSee{Term=[cleanup],See=(finalization)} @IndexSee{Term=[destructor],See=(finalization)}] @end{Intro} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn{completion and leaving (completed and left)} @Defn2{Term=[completion], Sec=(run-time concept)} The execution of a construct or entity is @i{complete} when the end of that execution has been reached, or when a transfer of control (see @RefSecNum{Simple and Compound Statements - Sequences of Statements}) causes it to be abandoned. @Defn{normal completion} @Defn2{Term=[completion], Sec=(normal)} @Defn{abnormal completion} @Defn2{Term=[completion], Sec=(abnormal)} Completion due to reaching the end of execution, or due to the transfer of control of an @Chg{Version=[2], New=[@nt{exit_statement}, return statement, @nt{goto_statement}], Old=[@ntf{exit_}, @ntf{return_}, @ntf{goto_}]}, or @nt{requeue_statement} or of the selection of a @nt{terminate_alternative} is @i{normal completion}. Completion is @i{abnormal} otherwise @Redundant[@em when control is transferred out of a construct due to abort or the raising of an exception]. @begin{Discussion} Don't confuse the run-time concept of completion with the compile-time concept of completion defined in @RefSecNum{Completions of Declarations}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @Defn{leaving} @Defn{left} After execution of a construct or entity is complete, it is @i{left}, meaning that execution continues with the next action, as defined for the execution that is taking place. @Defn{master} Leaving an execution happens immediately after its completion, except in the case of a @i{master}: the execution of a @Chg{Version=[2],New=[body other than a @nt{package_body}; the execution of a @nt{statement}; or the evaluation of an @nt{expression}, @nt{function_call}, or @nt{range} that is not part of an enclosing @nt{expression}, @nt{function_call}, @nt{range}, or @nt{simple_@!statement} other than a @nt{simple_@!return_@!statement}], Old=[@nt{task_body}, a @nt{block_@!statement}, a @nt{subprogram_body}, an @nt{entry_body}, or an @nt{accept_@!statement}]}. A master is finalized after it is complete, and before it is left. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @Chg{Version=[2],New=[@nt{Expression}s and @nt{statement}s are masters so that objects created by subprogram calls (in @nt{aggregate}s, @nt{allocator}s for anonymous access-to-object types, and so on) are finalized and have their tasks awaited before the @nt{expression}s or @nt{statement}s are left. Note that @nt{expression}s like the @nt{condition} of an @nt{if_statement} are masters, because they are not enclosed by a @nt{simple_statement}. Similarly, a @nt{function_call} which is renamed is a master, as it is not in a @nt{simple_@!statement}.], Old=[Note that although an @nt{accept_statement} has no @nt{declarative_part}, it can call functions and evaluate @nt{aggregate}s, possibly causing anonymous controlled objects to be created, and we don't want those objects to escape outside the rendezvous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[We have to include @nt{function_call}s in the contexts that do not cause masters to occur so that @nt{expression}s contained in a @nt{function_call} (that is not part of an @nt{expression} or @nt{simple_statement}) do not individually become masters. We certainly do not want the parameter @nt{expression}s of a @nt{function_call} to be separate masters, as they would then be finalized before the function is called.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The fact that a @nt{function_call} is a master does not change the accessibility of the return object denoted by the @nt{function_call}; that depends on the use of the @nt{function_call}. The @nt{function_call} is the master of any short-lived entities (such as @nt{aggregate}s used as parameters of types with task or controlled parts).]} @end{Ramification} @Defn2{Term=[finalization], Sec=(of a master)} For the @i{finalization} of a master, dependent tasks are first awaited, as explained in @RefSecNum{Task Dependence - Termination of Tasks}. Then each object whose accessibility level is the same as that of the master is finalized if the object was successfully initialized and still exists. @Redundant[These actions are performed whether the master is left by reaching the last statement or via a transfer of control.] When a transfer of control causes completion of an execution, each included master is finalized in order, from innermost outward. @begin{Ramification} As explained in @RefSecNum{Operations of Access Types}, the set of objects with the same accessibility level as that of the master includes objects declared immediately within the master, objects declared in nested packages, objects created by @nt{allocator}s (if the ultimate ancestor access type is declared in one of those places) and subcomponents of all of these things. If an object was already finalized by Unchecked_Deallocation, then it is not finalized again when the master is left. Note that any object whose accessibility level is deeper than that of the master would no longer exist; those objects would have been finalized by some inner master. Thus, after leaving a master, the only objects yet to be finalized are those whose accessibility level is less deep than that of the master. @end{Ramification} @begin{Honest} Subcomponents of objects due to be finalized are not finalized by the finalization of the master; they are finalized by the finalization of the containing object. @end{Honest} @begin{Reason} We need to finalize subcomponents of objects even if the containing object is not going to get finalized because it was not fully initialized. But if the containing object is finalized, we don't want to require repeated finalization of the subcomponents, as might normally be implied by the recursion in finalization of a master and the recursion in finalization of an object. @end{Reason} @begin{Honest} Formally, completion and leaving refer to executions of constructs or entities. However, the standard sometimes (informally) refers to the constructs or entities whose executions are being completed. Thus, for example, @lquotes@;the subprogram call or task is complete@rquotes@; really means @lquotes@;@i{the execution of} the subprogram call or task is complete.@rquotes@; @end{Honest} @leading@keepnext@RootDefn2{Term=[finalization], Sec=(of an object)} For the @i{finalization} of an object: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0099-1]} If @Chg{Version=[3],New=[the full type of ],Old=[]}the object is @Chg{Version=[3],New=[],Old=[of ]}an elementary type, finalization has no effect; @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0099-1]} @ChgAdded{Version=[3],Text=[We say @ldquote@;full type@rdquote in this and the following bullets as privacy is ignored for the purpose of determining the finalization actions of an object; that is as expected for @RunTimeTitle rules.]} @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0099-1]} If @Chg{Version=[3],New=[the full type of ],Old=[]}the object is @Chg{Version=[3],New=[a tagged type, and the tag of the object identifies],Old=[of]} a controlled type, the Finalize procedure @Chg{Version=[3],New=[of that controlled type ],Old=[]}is called; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0099-1]} If @Chg{Version=[3],New=[the full type of ],Old=[]}the object is @Chg{Version=[3],New=[],Old=[of ]}a protected type, @Chg{Version=[3],New=[or if the full type of the object is a tagged type and the tag of the object identifies a protected type, ],Old=[]}the actions defined in @RefSecNum{Protected Units and Protected Objects} are performed; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0099-1]} If @Chg{Version=[3],New=[the full type of ],Old=[]}the object is @Chg{Version=[3],New=[],Old=[of ]}a composite type, then after performing the above actions, if any, every component of the object is finalized in an arbitrary order, except as follows:@PDefn2{Term=[arbitrary order],Sec=[allowed]} if the object has a component with an access discriminant constrained by a per-object expression, this component is finalized before any components that do not have such discriminants; for an object with several components with such a discriminant, they are finalized in the reverse of the order of their @nt<component_declaration>s@Chg{Version=[2],New=[;],Old=[.]} @begin{Reason} This allows the finalization of a component with an access discriminant to refer to other components of the enclosing object prior to their being finalized. @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0099-1]} @ChgAdded{Version=[3],Text=[The components discussed here are all of the components that the object actually has, not just those components that are statically identified by the type of the object. These can be different if the object has a classwide type.]} @end{Honest} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the object has coextensions (see @RefSecNum{Operations of Access Types}), each coextension is finalized after the object whose access discriminant designates it.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0066-1]} @ChgAdded{Version=[3],Text=[In the case of an @nt{aggregate} or function call that is used (in its entirety) to directly initialize a part of an object, the coextensions of the result of evaluating the @nt{aggregate} or function call are transfered to become coextensions of the object being initialized and are not finalized until the object being initialized is ultimately finalized, even if an anonymous object is created as part of the operation.]} @end{Ramification} @end{Itemize} @PDefn2{Term=[execution], Sec=(instance of Unchecked_Deallocation)} Immediately before an instance of Unchecked_Deallocation reclaims the storage of an object, the object is finalized. @Redundant[If an instance of Unchecked_Deallocation is never applied to an object created by an @nt{allocator}, the object will still exist when the corresponding master completes, and it will be finalized then.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00280-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0051-1],ARef=[AI05-0190-1]} The @Chg{Version=[3],New=[],Old=[order in which the ]}finalization of a master performs finalization of objects @Chg{Version=[3],New=[],Old=[is as follows: Objects ]}created by declarations in the master @Chg{Version=[3],New=[],Old=[are finalized ]}in the reverse order of their creation.@Chg{Version=[3],New=[],Old=[ For objects that were created by @nt{allocator}s for an access type whose ultimate ancestor is declared in the master, this rule is applied as though each such object that still exists had been created in an arbitrary order at the first freezing point (see @RefSecNum{Freezing Rules})@PDefn2{Term=[arbitrary order],Sec=[allowed]} of the ultimate ancestor type@Chg{Version=[2],New=[; the finalization of these objects is called the @i<finalization of the collection>@Defn{finalization of the collection}@Defn2{Term=[collection], Sec=[finalization of]}],Old=[]}.@Chg{Version=[3],New=[ Objects created by allocators for an anonymous access type that are not coextensions of some other object, are finalized in an arbitrary order during the finalization of their associated master.@PDefn2{Term=[arbitrary order],Sec=[allowed]}],Old=[]}]}@Chg{Version=[2], New=[ After the finalization of a master is complete, the objects finalized as part of its finalization cease to @i<exist>, as do any types and subtypes defined and created within the master.@PDefn2{Term=[exist],Sec=[cease to]} @PDefn2{Term=[cease to exist],Sec=[object]} @Defn2{Term=[cease to exist],Sec=[type]}],Old=[]} @begin{Reason} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgDeleted{Version=[3],Text=[Note that we talk about the type of the @nt{allocator} here. There may be access values of a (general) access type pointing at objects created by @nt{allocator}s for some other type; these are not finalized at this point.]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgDeleted{Version=[3],Text=[The freezing point of the ultimate ancestor access type is chosen because before that point, pool elements cannot be created, and after that point, access values designating (parts of) the pool elements can be created. This is also the point after which the pool object cannot have been declared. We don't want to finalize the pool elements until after anything finalizing objects that contain access values designating them. Nor do we want to finalize pool elements after finalizing the pool object itself.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgDeleted{Version=[3],Text=[Finalization of allocated objects is done according to the (ultimate ancestor) @nt{allocator} type, not according to the storage pool in which they are allocated. Pool finalization might reclaim storage (see @RefSec{Storage Management}), but has nothing (directly) to do with finalization of the pool elements.]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgDeleted{Version=[3],Text=[Note that finalization is done only for objects that still exist; if an instance of Unchecked_Deallocation has already gotten rid of a given pool element, that pool element will not be finalized when the master is left.]} Note that a deferred constant declaration does not create the constant; the full constant declaration creates it. Therefore, the order of finalization depends on where the full constant declaration occurs, not the deferred constant declaration. An imported object is not created by its declaration. It is neither initialized nor finalized. @end{Ramification} @begin{ImplNote} An implementation has to ensure that the storage for an object is not reclaimed when references to the object are still possible (unless, of course, the user explicitly requests reclamation via an instance of Unchecked_Deallocation). This implies, in general, that objects cannot be deallocated one by one as they are finalized; a subsequent finalization might reference an object that has been finalized, and that object had better be in its (well-defined) finalized state. @end{ImplNote} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Each nonderived access type @i<T> has an associated @i<collection>,@Defn2{Term=[collection],Sec=[of an access type]} which is the set of objects created by @nt{allocator}s of @i<T>, or of types derived from @i<T>. Unchecked_Deallocation removes an object from its collection. Finalization of a collection consists of finalization of each object in the collection, in an arbitrary order. The collection of an access type is an object implicitly declared at the following place:@PDefn2{Term=[arbitrary order],Sec=[allowed]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[The place of the implicit declaration determines when allocated objects are finalized. For multiple collections declared at the same place, we do not define the order of their implicit declarations.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgAdded{Version=[3],Text=[Finalization of allocated objects is done according to the (ultimate ancestor) @nt{allocator} type, not according to the storage pool in which they are allocated. Pool finalization might reclaim storage (see @RefSec{Storage Management}), but has nothing (directly) to do with finalization of the pool elements.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgAdded{Version=[3],Text=[Note that finalization is done only for objects that still exist; if an instance of Unchecked_Deallocation has already gotten rid of a given pool element, that pool element will not be finalized when the master is left.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgAdded{Version=[3],Text=[Note that we talk about the type of the @nt{allocator} here. There may be access values of a (general) access type pointing at objects created by @nt{allocator}s for some other type; these are not (necessarily) finalized at this point.]} @end{Reason} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For a named access type, the first freezing point (see @RefSecNum{Freezing Rules}) of the type.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]}@ChgNote{Moved down} @ChgAdded{Version=[3],Text=[The freezing point of the ultimate ancestor access type is chosen because before that point, pool elements cannot be created, and after that point, access values designating (parts of) the pool elements can be created. This is also the point after which the pool object cannot have been declared. We don't want to finalize the pool elements until after anything finalizing objects that contain access values designating them. Nor do we want to finalize pool elements after finalizing the pool object itself.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For the type of an access parameter, the call that contains the @nt{allocator}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For the type of an access result, within the master of the call (see @RefSecNum{Operations of Access Types}).]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[We mean at a place within the master consistent with the execution of the call within the master. We don't say that normatively, as it is difficult to explain that when the master of the call need not be the master that immediately includes the call (such as when an anonymous result is converted to a named access type).]} @end{Honest} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For any other anonymous access type, the first freezing point of the innermost enclosing declaration.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @PDefn2{Term=[execution], Sec=(assignment_statement)} The target of an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment statement]} is finalized before copying in the new value, as explained in @RefSecNum{Assignment and Finalization}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0066-1],ARef=[AI05-0142-4],ARef=[AI05-0269-1]} @Chg{Version=[2],New=[The master of an object is the master enclosing its creation whose accessibility level (see @RefSecNum{Operations of Access Types}) is equal to that of the object@Chg{Version=[3],New=[, except in the case of an anonymous object representing the result of an @nt{aggregate} or function call. If such an anonymous object is part of the result of evaluating the actual parameter expression for an explicitly aliased parameter of a function call, the master of the object is the innermost master enclosing the evaluation of the @nt{aggregate} or function call, excluding the @nt{aggregate} or function call itself. Otherwise, the master of such an anonymous object is the innermost master enclosing the evaluation of the @nt{aggregate} or function call, which may be the @nt{aggregate} or function call itself],Old=[]}.], Old=[@Chg{New=[If the @i{object_}@nt{name} in an @nt{object_renaming_declaration}, or the actual parameter for a generic formal @key[in out] parameter in a @nt{generic_instantiation}, denotes any part of an anonymous object created by a function call, the anonymous object is not finalized until after it is no longer accessible via any name. Otherwise, an], Old=[The]} anonymous object@Chg{New=[],Old=[s]} created by @Chg{New=[a ],Old=[]}function @Chg{New=[call or],Old=[calls and]} by @Chg{New=[an ],Old=[]}@nt{aggregate}@Chg{New=[ is],Old=[s are]} finalized no later than the end of the innermost enclosing @nt{declarative_item} or @nt{statement}; if that is a @nt{compound_statement}, @Chg{New=[the object is],Old=[they are]} finalized before starting the execution of any @nt{statement} within the @nt{compound_statement}.]} @begin{Honest} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00162-01]}@ChgNote{Should be ChgDeleted} @ChgDeleted{Version=[2],Text=[@leading@;This is not to be construed as permission to call Finalize asynchronously with respect to normal user code. For example,]} @begin{Example} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[@key[declare] X : Some_Controlled_Type := F(G(...)); --@RI{ The anonymous objects created for F and G are finalized} --@RI{ no later than this point.} Y : ... @key[begin] ... @key[end];]} @end{Example} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[ The anonymous object for G should not be finalized at some random point in the middle of the body of F, because F might manipulate the same data structures as the Finalize operation, resulting in erroneous access to shared variables.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00162-01]} @Chg{Version=[2],New=[This effectively imports all of the special rules for the accessibility level of renames, @nt{allocator}s, and so on, and applies them to determine where objects created in them are finalized. For instance, the master of a rename of a subprogram is that of the renamed subprogram.], Old=[It might be quite inconvenient for the implementation to defer finalization of the anonymous object for G until after copying the value of F into X, especially if the size of the result is not known at the call site.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0066-1]} @ChgAdded{Version=[3],Text=[In @RefSecNum{Operations of Access Types} we assign an accessibility level to the result of an @nt{aggregate} or function call that is used to directly initialize a part of an object based on the object being initialized. This is important to ensure that any access discriminants denote objects that live at least as long as the object being initialized. However, if the result of the @nt{aggregate} or function call is not built directly in the target object, but instead is built in an anonymous object that is then assigned to the target, the anonymous object needs to be finalized after the assignment rather than persisting until the target object is finalized (but not its coextensions). (Note than an implementation is never required to create such an anonymous object, and in some cases is required to @i{not} have such a separate object, but rather to build the result directly in the target.)]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[The special case for explicitly aliased parameters of functions is needed for the same reason, as access discriminants of the returned object may designate one of these parameters. In that case, we want to lengthen the lifetime of the anonymous objects as long as the possible lifetime of the result.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[We don't do a similar change for other kinds of calls, because the extended lifetime of the parameters adds no value, but could constitute a storage leak. For instance, such an anonymous object created by a procedure call in the elaboration part of a package body would have to live until the end of the program, even though it could not be used after the procedure returns (other than via Unchecked_Access).]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Note that the lifetime of the master given to anonymous objects in explicitly aliased parameters of functions is not necessarily as long as the lifetime of the master of the object being initialized (if the function call is used to initialize an @nt{allocator}, for instance). In that case, the accessibility check on explicitly aliased parameters will necessarily fail if any such anonymous objects exist. This is necessary to avoid requiring the objects to live as long as the access type or having the implementation complexity of an implicit coextension.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00162-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0066-1],ARef=[AI05-0262-1]} @Chg{Version=[2],New=[In the case of an @nt{expression} that is a master, finalization of any (anonymous) objects occurs @Chg{Version=[3],New=[after completing],Old=[as the final part of]} evaluation of the @nt{expression}@Chg{Version=[3],New=[ and all use of the objects, prior to starting the execution of any subsequent construct],Old=[]}.], Old=[@Chg{New=[If a transfer of control or raising of an exception occurs prior to performing a finalization of an anonymous object, the anonymous object is finalized as part of the finalizations due to be performed for the object's innermost enclosing master.],Old=[]}]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0023],ARef=[AI95-00169-01]} @leading@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for a call on Finalize or Adjust @Chg{New=[that occurs as part of object finalization or assignment ], Old=[]}to propagate an exception. The possible consequences depend on what action invoked the Finalize or Adjust operation: @begin{Ramification} It is not a bounded error for Initialize to propagate an exception. If Initialize propagates an exception, then no further calls on Initialize are performed, and those components that have already been initialized (either explicitly or by default) are finalized in the usual way. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @Chg{New=[It also is not a bounded error for an explicit call to Finalize or Adjust to propagate an exception. We do not want implementations to have to treat explicit calls to these routines specially.],Old=[]} @end{Ramification} @begin{Itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of an @nt<assignment_statement>, Program_Error is raised at that point. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @Chg{New=[For an Adjust invoked as part of @Chg{Version=[2],New=[assignment operations other than those invoked as part of an @nt{assignment_statement}], Old=[the initialization of a controlled object]}, other adjustments due to be performed might or might not be performed, and then Program_Error is raised. During its propagation, finalization might or might not be applied to objects whose Adjust failed.],Old=[]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For an Adjust invoked as part of an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment @Chg{New=[statement],Old=[operation]}]}, any other adjustments due to be performed are performed, and then Program_Error is raised. @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[In the case of assignments that are part of initialization, there is no need to complete all adjustments if one propagates an exception, as the object will immediately be finalized. So long as a subcomponent is not going to be finalized, it need not be adjusted, even if it is initialized as part of an enclosing composite assignment operation for which some adjustments are performed. However, there is no harm in an implementation making additional Adjust calls (as long as any additional components that are adjusted are also finalized), so we allow the implementation flexibility here. On the other hand, for an @Chg{Version=[2],New=[@nt{assignment_statement}], Old=[assignment statement]}, it is important that all adjustments be performed, even if one fails, because all controlled subcomponents are going to be finalized.@Chg{Version=[2],New=[ Other kinds of assignment are more like initialization than @nt{assignment_statement}s, so we include them as well in the permission.],Old=[]}]} @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgAdded{Version=[1],Text=[Even if an Adjust invoked as part of the initialization of a controlled object propagates an exception, objects whose initialization (including any Adjust or Initialize calls) successfully completed will be finalized. The permission above only applies to objects whose Adjust failed. Objects for which Adjust was never even invoked must not be finalized.]} @end{Ramification} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of a call on an instance of Unchecked_Deallocation, any other finalizations due to be performed are performed, and then Program_Error is raised. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0104],ARef=[AI95-00179-01]} @ChgAdded{Version=[1],Text=[The standard does not specify if storage is recovered in this case. If storage is not recovered (and the object continues to exist), Finalize may be called on the object again (when the @nt<allocator>'s master is finalized).]} @end{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0064-1]} @ChgDeleted{Version=[3],Text=[@Chg{New=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked as part of the finalization of the anonymous object created by a function call or @nt{aggregate}, any other finalizations due to be performed are performed, and then Program_Error is raised.],Old=[]}]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0023],ARef=[AI95-00169-01]} @Chg{New=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked due to reaching the end of the execution of a master, any other finalizations associated with the master are performed, and Program_Error is raised immediately after leaving the master.],Old=[]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0064-1]} @begin{Discussion} @ChgAdded{Version=[3],Text=[This rule covers both ordinary objects created by a declaration, and anonymous objects created as part of evaluating an @nt{expression}. All contexts that create objects that need finalization are defined to be masters.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} For a Finalize invoked by the transfer of control of an @Chg{Version=[2], New=[@nt{exit_statement}, return statement, @nt{goto_statement}], Old=[@ntf{exit_}, @ntf{return_}, @ntf{goto_}]}, or @nt{requeue_@!statement}, Program_Error is raised no earlier than after the finalization of the master being finalized when the exception occurred, and no later than the point where normal execution would have continued. Any other finalizations due to be performed up to that point are performed before raising Program_Error. @begin{Ramification} For example, upon leaving a @nt{block_statement} due to a @nt{goto_statement}, the Program_Error would be raised at the point of the target statement denoted by the label, or else in some more dynamically nested place, but not so nested as to allow an @nt{exception_handler} that has visibility upon the finalized object to handle it. For example, @begin{Example} @key[procedure] Main @key[is] @key[begin] <<The_Label>> Outer_Block_Statement : @key[declare] X : Some_Controlled_Type; @key[begin] Inner_Block_Statement : @key[declare] Y : Some_Controlled_Type; Z : Some_Controlled_Type; @key[begin] @key[goto] The_Label; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 1.} @key[end]; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 2.} @key[end]; @key[exception] @key[when] Program_Error => ... --@RI{ Handler number 3.} @key[end] Main; @end{Example} The @nt{goto_statement} will first cause Finalize(Y) to be called. Suppose that Finalize(Y) propagates an exception. Program_Error will be raised after leaving Inner_Block_Statement, but before leaving Main. Thus, handler number 1 cannot handle this Program_Error; it will be handled either by handler number 2 or handler number 3. If it is handled by handler number 2, then Finalize(Z) will be done before executing the handler. If it is handled by handler number 3, then Finalize(Z) and Finalize(X) will both be done before executing the handler. @end{Ramification} For a Finalize invoked by a transfer of control that is due to raising an exception, any other finalizations due to be performed for the same master are performed; Program_Error is raised immediately after leaving the master. @begin{Ramification} If, in the above example, the @nt{goto_statement} were replaced by a @nt{raise_statement}, then the Program_Error would be handled by handler number 2, and Finalize(Z) would be done before executing the handler. @end{Ramification} @begin{Reason} We considered treating this case in the same way as the others, but that would render certain @nt{exception_handler}s useless. For example, suppose the only @nt{exception_handler} is one for @key{others} in the main subprogram. If some deeply nested call raises an exception, causing some Finalize operation to be called, which then raises an exception, then normal execution @lquotes@;would have continued@rquotes@; at the beginning of the @nt{exception_handler}. Raising Program_Error at that point would cause that handler's code to be skipped. One would need two nested @nt{exception_handler}s to be sure of catching such cases! On the other hand, the @nt{exception_handler} for a given master should not be allowed to handle exceptions raised during finalization of that master. @end{Reason} For a Finalize invoked by a transfer of control due to an abort or selection of a terminate alternative, the exception is ignored; any other finalizations due to be performed are performed. @begin{Ramification} This case includes an asynchronous transfer of control. @end{Ramification} @begin{Honest} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This violates the general principle that it is always possible for a bounded error to raise Program_Error (see @RefSec{Classification of Errors}). @end{Honest} @end{Itemize} @end{Bounded} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[If the execution of an @nt{allocator} propagates an exception, any parts of the allocated object that were successfully initialized may be finalized as part of the finalization of the innermost master enclosing the @nt{allocator}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This allows deallocating the memory for the allocated object at the innermost master, preventing a storage leak. Otherwise, the object would have to stay around until the finalization of the collection that it belongs to, which could be the entire life of the program if the associated access type is library level.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0111-3],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The implementation may finalize objects created by @nt{allocator}s for an access type whose storage pool supports subpools (see @RefSecNum{Storage Subpools}) as if the objects were created (in an arbitrary order) at the point where the storage pool was elaborated instead of at the first freezing point of the access type.@PDefn2{Term=[arbitrary order],Sec=[allowed]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This allows the finalization of such objects to occur later than they otherwise would, but still as part of the finalization of the same master. Accessibility rules in @RefSecNum{Storage Subpools} ensure that it is the same master (usually that of the environment task).]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This permission is intended to allow the allocated objects to "belong" to the subpool objects and to allow those objects to be finalized at the time that the storage pool is finalized (if they are not finalized earlier). This is expected to ease implementation, as the objects will only need to belong to the subpool and not also to the collection.]} @end{ImplNote} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The rules of @Chg{Version=[3],New=[Clause],Old=[Section]} 10 imply that immediately prior to partition termination, Finalize operations are applied to library-level controlled objects (including those created by @nt{allocator}s of library-level access types, except those already finalized). This occurs after waiting for library-level tasks to terminate. @begin{Discussion} We considered defining a pragma that would apply to a controlled type that would suppress Finalize operations for library-level objects of the type upon partition termination. This would be useful for types whose finalization actions consist of simply reclaiming global heap storage, when this is already provided automatically by the environment upon program termination. @end{Discussion} A constant is only constant between its initialization and finalization. Both initialization and finalization are allowed to change the value of a constant. Abort is deferred during certain operations related to controlled types, as explained in @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}. Those rules prevent an abort from causing a controlled object to be left in an ill-defined state. The Finalize procedure is called upon finalization of a controlled object, even if Finalize was called earlier, either explicitly or as part of an assignment; hence, if a controlled type is visibly controlled (implying that its Finalize primitive is directly callable), or is nonlimited (implying that assignment is allowed), its Finalize procedure should be designed to have no ill effect if it is applied a second time to the same object. @begin{Discussion} Or equivalently, a Finalize procedure should be @lquotes@;idempotent@rquotes@;; applying it twice to the same object should be equivalent to applying it once. @end{Discussion} @begin{Reason} A user-written Finalize procedure should be idempotent since it can be called explicitly by a client (at least if the type is "visibly" controlled). Also, Finalize is used implicitly as part of the @nt<assignment_statement> if the type is nonlimited, and an abort is permitted to disrupt an @nt<assignment_statement> between finalizing the left-hand side and assigning the new value to it (an abort is not permitted to disrupt an assignment operation between copying in the new value and adjusting it). @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} Either Initialize or Adjust, but not both, is applied to (almost) every controlled object when it is created: Initialize is done when no initial value is assigned to the object, whereas Adjust is done as part of assigning the initial value. The one exception is the @Chg{Version=[2],New=[],Old=[anonymous ]}object @Chg{Version=[2],New=[initialized],Old=[created]} by an @nt{aggregate}@Chg{Version=[2],New=[ (both the anonymous object created for an aggregate, or an object initialized by an @nt{aggregate} that is built-in-place)],Old=[]}; Initialize is not applied to the @nt{aggregate} as a whole, nor is the value of the @nt<aggregate> @Chg{Version=[2], New=[or object ],Old=[]}adjusted. @leading@Defn2{Term=[assignment operation], Sec=(list of uses)} All of the following use the assignment operation, and thus perform value adjustment: @begin{Itemize} the @nt{assignment_statement} (see @RefSecNum{Assignment Statements}); explicit initialization of a stand-alone object (see @RefSecNum{Object Declarations}) or of a pool element (see @RefSecNum{Allocators}); default initialization of a component of a stand-alone object or pool element (in this case, the value of each component is assigned, and therefore adjusted, but the value of the object as a whole is not adjusted); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} function return, when the result @Chg{Version=[2],New=[is not built-in-place], Old=[type is not a return-by-reference type (see @RefSecNum{Return Statements});]} (adjustment of the result happens before finalization of the function@Chg{Version=[2],New=[],Old=[; values of return-by-reference types are not adjusted]}); predefined operators (although the only one that matters is concatenation; see @RefSecNum{Binary Adding Operators}); generic formal objects of mode @key{in} (see @RefSecNum{Formal Objects}); these are defined in terms of constant declarations; and @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @nt{aggregate}s (see @RefSecNum{Aggregates})@Chg{Version=[2],New=[, when the result is not built-in-place],Old=[]} (in this case, the value of each component, and the parent part, for an @nt{extension_aggregate}, is assigned, and therefore adjusted, but the value of the @nt{aggregate} as a whole is not adjusted; neither is Initialize called); @end{Itemize} @leading@;The following also use the assignment operation, but adjustment never does anything interesting in these cases: @begin{Itemize} By-copy parameter passing uses the assignment operation (see @RefSecNum{Parameter Associations}), but controlled objects are always passed by reference, so the assignment operation never does anything interesting in this case. If we were to allow by-copy parameter passing for controlled objects, we would need to make sure that the actual is finalized before doing the copy back for [@key{in}] @key{out} parameters. The finalization of the parameter itself needs to happen after the copy back (if any), similar to the finalization of an anonymous function return object or @nt{aggregate} object. @key{For} loops use the assignment operation (see @RefSecNum{Loop Statements}), but since the type of the loop parameter is never controlled, nothing interesting happens there, either. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[Objects initialized by function results and @nt{aggregate}s that are built-in-place. In this case, the assignment operation is never executed, and no adjustment takes place. While built-in-place is always allowed, it is required for some types @em see @RefSecNum{Limited Types} and @RefSecNum{Assignment and Finalization} @em and that's important since limited types have no Adjust to call.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00287-01]} @ChgDeleted{Version=[2],Text=[Because Controlled and Limited_Controlled are library-level tagged types, all controlled types will be library-level types, because of the accessibility rules (see @RefSecNum{Operations of Access Types} and @RefSecNum{Type Extensions}). This ensures that the Finalize operations may be applied without providing any @lquotes@;display@rquotes@; or @lquotes@;static-link.@rquotes@; This simplifies finalization as a result of garbage collection, abort, and asynchronous transfer of control.]} Finalization of the parts of a protected object are not done as protected actions. It is possible (in pathological cases) to create tasks during finalization that access these parts in parallel with the finalization itself. This is an erroneous use of shared variables. @end{Discussion} @begin{ImplNote} One implementation technique for finalization is to chain the controlled objects together on a per-task list. When leaving a master, the list can be walked up to a marked place. The links needed to implement the list can be declared (privately) in types Controlled and Limited_Controlled, so they will be inherited by all controlled types. Another implementation technique, which we refer to as the @lquotes@;PC-map@rquotes@; approach essentially implies inserting exception handlers at various places, and finalizing objects based on where the exception was raised. @Defn{PC-map approach to finalization} @Defn{program-counter-map approach to finalization} The PC-map approach is for the compiler/linker to create a map of code addresses; when an exception is raised, or abort occurs, the map can be consulted to see where the task was executing, and what finalization needs to be performed. This approach was given in the Ada 83 Rationale as a possible implementation strategy for exception handling @em the map is consulted to determine which exception handler applies. If the PC-map approach is used, the implementation must take care in the case of arrays. The generated code will generally contain a loop to initialize an array. If an exception is raised part way through the array, the components that have been initialized must be finalized, and the others must not be finalized. It is our intention that both of these implementation methods should be possible. @end{ImplNote} @end{Notes} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Finalization depends on the concepts of completion and leaving, and on the concept of a master. Therefore, we have moved the definitions of these concepts here, from where they used to be in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Tasks and Synchronization}. These concepts also needed to be generalized somewhat. Task waiting is closely related to user-defined finalization; the rules here refer to the task-waiting rules of @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Tasks and Synchronization}. @end{DiffWord83} @begin{Inconsistent95} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0066-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 95}@b<Ada 2012 Correction:> Changed the definition of the master of an anonymous object used to directly initialize an object, so it can be finalized immediately rather than having to hang around as long as the object. In this case, the Ada 2005 definition was inconsistent with Ada 95, and Ada 2012 changes it back. It is unlikely that many compilers implemented the rule as written in Amendment 1, so an inconsistency is unlikely to arise in practice.]} @end{Inconsistent95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0021],ARef=[AI95-00182-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the wording to say that anonymous objects aren't finalized until the object can't be used anymore.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0023],ARef=[AI95-00169-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to clarify what happens when Adjust or Finalize raises an exception; some cases had been omitted.]} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0024],ARef=[AI95-00193-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Stated that if Adjust raises an exception during initialization, nothing further is required. This is corrected in Ada 2005 to include all kinds of assignment other than @nt{assignment_statement}s.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00162-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Revised the definition of master to include @nt{expression}s and @nt{statement}s, in order to cleanly define what happens for tasks and controlled objects created as part of a subprogram call. Having done that, all of the special wording to cover those cases is eliminated (at least until the Ada comments start rolling in).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[We define @i{finalization of the collection} here, so as to be able to conveniently refer to it in other rules (especially in @RefSec{Allocators}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Clarified that a coextension is finalized at the same time as the outer object. (This was intended for Ada 95, but since the concept did not have a name, it was overlooked.)]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0051-1],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Better defined when objects allocated from anonymous access types are finalized. This could be inconsistent if objects are finalized in a different order than in an Ada 2005 implementation and that order caused different program behavior; however programs that depend on the order of finalization within a single master are already fragile and hopefully are rare.]} @end{Inconsistent2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0064-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Removed a redundant rule, which is now covered by the additional places where masters are defined.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0099-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified the finalization rules so that there is no doubt that privacy is ignored, and to ensure that objects of classwide interface types are finalized based on their specific concrete type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Allowed premature finalization of parts of failed @nt{allocator}s. This could be an inconsistency, but the previous behavior is still allowed and there is no requirement that implementations take advantage of the permission.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[Added a permission to finalize object allocated from a subpool later than usual.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Added text to specially define the master of anonymous objects which are passed as explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}) of functions. The model for these parameters is explained in detail in @RefSecNum{Parameter Associations}.]} @end{DiffWord2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/08.mss���������������������������������������������������������������0000755�0001752�0001001�00000471224�12066652506�016412� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(08, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:03 $} @LabeledSection{Visibility Rules} @Comment{$Source: e:\\cvsroot/ARM/Source/08.mss,v $} @Comment{$Revision: 1.100 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[The rules defining the scope of declarations and the rules defining which @nt{identifier}s, @nt{character_literal}s, and @nt{operator_symbol}s are visible at (or from) various places in the text of the program are described in this @Chg{Version=[3],New=[clause],Old=[section]}. The formulation of these rules uses the notion of a declarative region. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} As explained in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Declarations and Types}, a declaration declares a view of an entity and associates a defining name with that view. The view comprises an identification of the viewed entity, and possibly additional properties. A usage name denotes a declaration. It also denotes the view declared by that declaration, and denotes the entity of that view. Thus, two different usage names might denote two different views of the same entity; in this case they denote the same entity.] @begin{Honest} In some cases, a usage name that denotes a declaration does not denote the view declared by that declaration, nor the entity of that view, but instead denotes a view of the current instance of the entity, and denotes the current instance of the entity. This sometimes happens when the usage name occurs inside the declarative region of the declaration. @end{Honest} @end{Intro} @begin{DiffWord83} We no longer define the term @lquotes@;basic operation;@rquotes@; thus we no longer have to worry about the visibility of them. Since they were essentially always visible in Ada 83, this change has no effect. The reason for this change is that the definition in Ada 83 was confusing, and not quite correct, and we found it difficult to fix. For example, one wonders why an @nt{if_statement} was not a basic operation of type Boolean. For another example, one wonders what it meant for a basic operation to be @lquotes@;inherent in@rquotes@; something. Finally, this fixes the problem addressed by AI83-00027/07. @end{DiffWord83} @LabeledClause{Declarative Region} @begin{StaticSem} @leading@Defn2{Term=[declarative region], Sec=(of a construct)} For each of the following constructs, there is a portion of the program text called its @i{declarative region}, @Redundant[within which nested declarations can occur]: @begin(itemize) any declaration, other than that of an enumeration type, that is not a completion @Redundant[of a previous declaration]; a @nt{block_statement}; a @nt{loop_statement}; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0255-1]} @ChgAdded{Version=[3],Text=[a @nt{quantified_expression};]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00318-02]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@Comment{Paragraph number changed} @ChgAdded{Version=[2],Text=[an @nt{extended_return_statement};]} an @nt{accept_statement}; an @nt{exception_handler}. @end(itemize) @begin{WideAbove} @leading@;The declarative region includes the text of the construct together with additional text determined @Redundant[(recursively)], as follows: @end{WideAbove} @begin{Itemize} If a declaration is included, so is its completion, if any. If the declaration of a library unit @Redundant[(including Standard @em see @RefSecNum{Compilation Units - Library Units})] is included, so are the declarations of any child units @Redundant[(and their completions, by the previous rule)]. The child declarations occur after the declaration. If a @nt{body_stub} is included, so is the corresponding @nt{subunit}. If a @nt{type_declaration} is included, then so is a corresponding @nt{record_representation_clause}, if any. @begin{Reason} This is so that the @nt{component_declaration}s can be directly visible in the @nt{record_representation_clause}. @end{Reason} @end{Itemize} The declarative region of a declaration is also called the @i{declarative region} of any view or entity declared by the declaration. @begin{Reason} The constructs that have declarative regions are the constructs that can have declarations nested inside them. Nested declarations are declared in that declarative region. The one exception is for enumeration literals; although they are nested inside an enumeration type declaration, they behave as if they were declared at the same level as the type. @end{Reason} @begin{Honest} A declarative region does not include @nt{parent_unit_name}s. @end{Honest} @begin{Ramification} A declarative region does not include @nt{context_clause}s. @end{Ramification} @Defn{occur immediately within} @Defn{immediately within} @Defn2{Term=[within],Sec=(immediately)} @Defn{immediately enclosing} @Defn2{Term=[enclosing],Sec=(immediately)} A declaration occurs @i{immediately within} a declarative region if this region is the innermost declarative region that encloses the declaration (the @i{immediately enclosing} declarative region), not counting the declarative region (if any) associated with the declaration itself. @begin{Discussion} Don't confuse the declarative region of a declaration with the declarative region in which it immediately occurs. @end{Discussion} @redundant[@Defn{local to} A declaration is @i{local} to a declarative region if the declaration occurs immediately within the declarative region.] @redundant[An entity is @i{local} to a declarative region if the entity is declared by a declaration that is local to the declarative region.] @begin{Ramification} "Occurs immediately within" and "local to" are synonyms (when referring to declarations). Thus, @lquotes@;local to@rquotes@; applies to both declarations and entities, whereas @lquotes@;occurs immediately within@rquotes@; only applies to declarations. We use this term only informally; for cases where precision is required, we use the term "occurs immediately within", since it is less likely to cause confusion. @end{Ramification} @Defn{global to} A declaration is @i{global} to a declarative region if the declaration occurs immediately within another declarative region that encloses the declarative region. An entity is @i{global} to a declarative region if the entity is declared by a declaration that is global to the declarative region. @end{StaticSem} @begin{Notes} The children of a parent library unit are inside the parent's declarative region, even though they do not occur inside the parent's declaration or body. This implies that one can use (for example) "P.Q" to refer to a child of P whose defining name is Q, and that after "@key[use] P;" Q can refer (directly) to that child. As explained above and in @RefSec{Compilation Units - Library Units}, all library units are descendants of Standard, and so are contained in the declarative region of Standard. They are @i{not} inside the declaration or body of Standard, but they @i{are} inside its declarative region. For a declarative region that comes in multiple parts, the text of the declarative region does not contain any text that might appear between the parts. Thus, when a portion of a declarative region is said to extend from one place to another in the declarative region, the portion does not contain any text that might appear between the parts of the declarative region. @begin{Discussion} It is necessary for the things that have a declarative region to include anything that contains declarations (except for enumeration type declarations). This includes any declaration that has a profile (that is, @nt{subprogram_declaration}, @nt{subprogram_body}, @nt{entry_declaration}, @nt{subprogram_renaming_declaration}, @nt{formal_subprogram_declaration}, access-to-subprogram @nt{type_declaration}), anything that has a @nt{discriminant_part} (that is, various kinds of @nt{type_declaration}), anything that has a @nt{component_list} (that is, record @nt{type_declaration} and record extension @nt{type_declaration}), and finally the declarations of task and protected units and packages. @end{Discussion} @end{Notes} @begin{DiffWord83} @leading@;It was necessary to extend Ada 83's definition of declarative region to take the following Ada 95 features into account: @begin{Itemize} Child library units. Derived types/type extensions @em we need a declarative region for inherited components and also for new components. All the kinds of types that allow discriminants. Protected units. Entries that have bodies instead of accept statements. The @nt{choice_parameter_specification} of an @nt{exception_handler}. The formal parameters of access-to-subprogram types. Renamings-as-body. @end{Itemize} Discriminated and access-to-subprogram type declarations need a declarative region. Enumeration type declarations cannot have one, because you don't have to say "Color.Red" to refer to the literal Red of Color. For other type declarations, it doesn't really matter whether or not there is an associated declarative region, so for simplicity, we give one to all types except enumeration types. We now say that an @nt{accept_statement} has its own declarative region, rather than being part of the declarative region of the @nt{entry_declaration}, so that declarative regions are properly nested regions of text, so that it makes sense to talk about "inner declarative regions," and "...extends to the end of a declarative region." Inside an @nt{accept_statement}, the @nt{name} of one of the parameters denotes the @nt{parameter_specification} of the @nt{accept_statement}, not that of the @nt{entry_declaration}. If the @nt{accept_statement} is nested within a @nt{block_statement}, these @nt{parameter_specification}s can hide declarations of the @nt{block_statement}. The semantics of such cases was unclear in RM83. @begin{Honest} Unfortunately, we have the same problem for the entry name itself @em it should denote the @nt{accept_statement}, but @nt{accept_statement}s are not declarations. They should be, and they should hide the entry from all visibility within themselves. @end{Honest} Note that we can't generalize this to @ntf{entry_bodies}, or other bodies, because the @nt{declarative_part} of a body is not supposed to contain (explicit) homographs of things in the declaration. It works for @nt{accept_statement}s only because an @nt{accept_statement} does not have a @nt{declarative_part}. To avoid confusion, we use the term @lquotes@;local to@rquotes@; only informally in Ada 95. Even RM83 used the term incorrectly (see, for example, RM83-12.3(13)). In Ada 83, (root) library units were inside Standard; it was not clear whether the declaration or body of Standard was meant. In Ada 95, they are children of Standard, and so occur immediately within Standard's declarative region, but not within either the declaration or the body. (See RM83-8.6(2) and RM83-10.1.1(5).) @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00318-02]} @ChgAdded{Version=[2],Text=[@nt{Extended_return_statement} (see @RefSecNum{Return Statements}) is added to the list of constructs that have a declarative region.]} @end{DiffWord95} @LabeledClause{Scope of Declarations} @begin{Intro} @redundant[For each declaration, the language rules define a certain portion of the program text called the @i{scope} of the declaration. The scope of a declaration is also called the scope of any view or entity declared by the declaration. Within the scope of an entity, and only there, there are places where it is legal to refer to the declared entity. These places are defined by the rules of visibility and overloading.] @end{Intro} @begin{StaticSem} @Leading@Defn2{Term=[immediate scope], Sec=(of a declaration)} The @i{immediate scope} of a declaration is a portion of the declarative region immediately enclosing the declaration. The immediate scope starts at the beginning of the declaration, except in the case of an overloadable declaration, in which case the immediate scope starts just after the place where the profile of the callable entity is determined (which is at the end of the @ntf<_specification> for the callable entity, or at the end of the @nt<generic_instantiation> if an instance). The immediate scope extends to the end of the declarative region, with the following exceptions: @begin{Reason} The reason for making overloadable declarations with profiles special is to simplify compilation: until the compiler has determined the profile, it doesn't know which other declarations are homographs of this one, so it doesn't know which ones this one should hide. Without this rule, two passes over the @ntf<_specification> or @nt<generic_instantiation> would be required to resolve names that denote things with the same name as this one. @end{Reason} @begin{Itemize} The immediate scope of a @nt{library_item} includes only its semantic dependents. @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Chg{Version=[3],New=[Clause],Old=[Section]} 10 defines only a partial ordering of @nt{library_item}s. Therefore, it is a good idea to restrict the immediate scope (and the scope, defined below) to semantic dependents. @leading@;Consider also examples like this: @begin{Example} @key[package] P @key[is] @key[end] P; @key[package] P.Q @key[is] I : Integer := 0; @key[end] P.Q; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00080 - syntax error} @key[with] P; @key[package] R @key[is] @key[package] X @key[renames] P; @Chg{New=[J : Integer := ],Old=[]}X.Q.I@Chg{New=[],Old=[ := 17]}; --@RI{ Illegal!} @key[end] R; @end{Example} The scope of P.Q does not contain R. Hence, neither P.Q nor X.Q are visible within R. However, the name R.X.Q would be visible in some other library unit where both R and P.Q are visible (assuming R were made legal by removing the offending declaration). @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[This rule applies to limited views as well as @lquotes@;normal@rquotes library items. In that case, the semantic dependents are the units that have a @nt{limited_with_clause} for the limited view.]} @end{Ramification} The immediate scope of a declaration in the private part of a library unit does not include the visible part of any public descendant of that library unit. @Pdefn2{Term=[descendant],Sec=(relationship with scope)} @begin{Ramification} In other words, a declaration in the private part can be visible within the visible part, private part and body of a private child unit. On the other hand, such a declaration can be visible within only the private part and body of a public child unit. @end{Ramification} @begin{Reason} The purpose of this rule is to prevent children from giving private information to clients. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} For a public child subprogram, this means that the parent's private part is not visible in the @Chg{Version=[2],New=[profile],Old=[@nt{formal_part}s]} of the declaration and of the body. This is true even for @ntf{subprogram_bodies} that are not completions. For a public child generic unit, it means that the parent's private part is not visible in the @nt{generic_formal_part}, as well as in the first list of @nt{basic_declarative_item}s (for a generic package), or the @Chg{Version=[2],New=[(syntactic) profile],Old=[@nt{formal_part}(s)]} (for a generic subprogram). @end{Ramification} @end{Itemize} @Defn{visible part} @Redundant[The @i(visible part) of (a view of) an entity is a portion of the text of its declaration containing declarations that are visible from outside.] @RootDefn{private part} The @i{private part} of (a view of) an entity that has a visible part contains all declarations within the declaration of (the view of) the entity, except those in the visible part; @Redundant[these are not visible from outside. Visible and private parts are defined only for these kinds of entities: callable entities, other program units, and composite types.] @begin{Itemize} @PDefn2{Term=[visible part], Sec=(of a view of a callable entity)} The visible part of a view of a callable entity is its profile. @PDefn2{Term=[visible part], Sec=(of a view of a composite type)} The visible part of a composite type other than a task or protected type consists of the declarations of all components declared @Redundant[(explicitly or implicitly)] within the @nt{type_declaration}. @PDefn2{Term=[visible part], Sec=(of a generic unit)} The visible part of a generic unit includes the @nt{generic_formal_part}. For a generic package, it also includes the first list of @nt{basic_declarative_item}s of the @nt{package_specification}. For a generic subprogram, it also includes the profile. @begin{Reason} Although there is no way to reference anything but the formals from outside a generic unit, they are still in the visible part in the sense that the corresponding declarations in an instance can be referenced (at least in some cases). In other words, these declarations have an effect on the outside world. The visible part of a generic unit needs to be defined this way in order to properly support the rule that makes a parent's private part invisible within a public child's visible part. @end{Reason} @begin{Ramification} The visible part of an instance of a generic unit is as defined for packages and subprograms; it is not defined in terms of the visible part of a generic unit. @end{Ramification} @Redundant[The visible part of a package, task unit, or protected unit consists of declarations in the program unit's declaration other than those following the reserved word @key{private}, if any; see @RefSecNum{Package Specifications and Declarations} and @RefSecNum{Formal Packages} for packages, @RefSecNum{Task Units and Task Objects} for task units, and @RefSecNum{Protected Units and Protected Objects} for protected units.] @end{Itemize} @Defn2{Term=[scope], Sec=(of a declaration)} The scope of a declaration always contains the immediate scope of the declaration. In addition, for a given declaration that occurs immediately within the visible part of an outer declaration, or is a public child of an outer declaration, the scope of the given declaration extends to the end of the scope of the outer declaration, except that the scope of a @nt{library_item} includes only its semantic dependents. @begin{Ramification} Note the recursion. If a declaration appears in the visible part of a library unit, its scope extends to the end of the scope of the library unit, but since that only includes dependents of the declaration of the library unit, the scope of the inner declaration also only includes those dependents. If X renames library package P, which has a child Q, a @nt{with_clause} mentioning P.Q is necessary to be able to refer to X.Q, even if P.Q is visible at the place where X is declared. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00408-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[scope], Sec=(of an attribute_@!definition_@!clause)} The scope of an @nt{attribute_definition_clause} is identical to the scope of a declaration that would occur at the point of the @nt{attribute_definition_clause}.@Chg{Version=[3],New=[ The scope of an @nt{aspect_specification} is identical to the scope of the associated declaration.@Defn2{Term=[scope], Sec=(of an aspect_@!specification)}],Old=[]}]} @Defn2{Term=[immediate scope], Sec=[of (a view of) an entity]} The immediate scope of a declaration is also the immediate scope of the entity or view declared by the declaration. @Defn2{Term=[scope], Sec=[of (a view of) an entity]} Similarly, the scope of a declaration is also the scope of the entity or view declared by the declaration. @begin{Ramification} @leading@;The rule for immediate scope implies the following: @begin{Itemize} If the declaration is that of a library unit, then the immediate scope includes the declarative region of the declaration itself, but not other places, unless they are within the scope of a @nt{with_clause} that mentions the library unit. @NoPrefix@;It is necessary to attach the semantics of @nt{with_clause}s to [immediate] scopes (as opposed to visibility), in order for various rules to work properly. A library unit should hide a homographic implicit declaration that appears in its parent, but only within the scope of a @nt{with_clause} that mentions the library unit. Otherwise, we would violate the "legality determinable via semantic dependences" rule of @RefSec{Program Structure and Compilation Issues}. The declaration of a library unit should be allowed to be a homograph of an explicit declaration in its parent's body, so long as that body does not mention the library unit in a @nt{with_clause}. @NoPrefix@;This means that one cannot denote the declaration of the library unit, but one might still be able to denote the library unit via another view. @NoPrefix@;A @nt{with_clause} does not make the declaration of a library unit visible; the lack of a @nt{with_clause} prevents it from being visible. Even if a library unit is mentioned in a @nt{with_clause}, its declaration can still be hidden. The completion of the declaration of a library unit (assuming that's also a declaration) is not visible, neither directly nor by selection, outside that completion. The immediate scope of a declaration immediately within the body of a library unit does not include any child of that library unit. @NoPrefix@;This is needed to prevent children from looking inside their parent's body. The children are in the declarative region of the parent, and they might be after the parent's body. Therefore, the scope of a declaration that occurs immediately within the body might include some children. @end{Itemize} @end{Ramification} @end{StaticSem} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} There are notations for denoting visible declarations that are not directly visible. For example, @nt{parameter_@!specification}s are in the visible part of a @nt{subprogram_@!declaration} so that they can be used in named-notation calls appearing outside the called subprogram. For another example, declarations of the visible part of a package can be denoted by expanded names appearing outside the package, and can be made directly visible by a @nt{use_clause}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} There are some obscure @Chg{Version=[2],New=[cases ],Old=[]}involving generics @Chg{Version=[2],New=[],Old=[cases ]}in which there is no such notation. See @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Generic Units}. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The fact that the immediate scope of an overloadable declaration does not include its profile is new to Ada 95. It replaces RM83-8.3(16), which said that within a subprogram specification and within the formal part of an entry declaration or accept statement, all declarations with the same designator as the subprogram or entry were hidden from all visibility. The RM83-8.3(16) rule seemed to be overkill, and created both implementation difficulties and unnecessary semantic complexity. @end{Extend83} @begin{DiffWord83} We no longer need to talk about the scope of notations, @nt{identifier}s, @nt{character_literal}s, and @nt{operator_symbol}s. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The notion of "visible part" has been extended in Ada 95. The syntax of task and protected units now allows private parts, thus requiring us to be able to talk about the visible part as well. It was necessary to extend the concept to subprograms and to generic units, in order for the visibility rules related to child library units to work properly. It was necessary to define the concept separately for generic formal packages, since their visible part is slightly different from that of a normal package. Extending the concept to composite types made the definition of scope slightly simpler. We define visible part for some things elsewhere, since it makes a big difference to the user for those things. For composite types and subprograms, however, the concept is used only in arcane visibility rules, so we localize it to this @Chg{Version=[3],New=[subclause],Old=[clause]}. In Ada 83, the semantics of @nt{with_clause}s was described in terms of visibility. It is now described in terms of [immediate] scope. @leading@;We have clarified that the following is illegal (where Q and R are library units): @begin{Example} @key[package] Q @key[is] I : Integer := 0; @key[end] Q; @key[package] R @key[is] @key[package] X @key[renames] Standard; X.Q.I := 17; --@RI{ Illegal!} @key[end] R; @end{Example} even though Q is declared in the declarative region of Standard, because R does not mention Q in a @nt{with_clause}. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[The scope of an @nt{attribute_definition_clause} is defined so that it can be used to define the visibility of such a clause, so @i<that> can be used by the stream attribute availability rules (see @RefSecNum{Stream-Oriented Attributes}).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[The scope of an @nt{aspect_specification} is defined for similar reasons that it was defined for @nt{attribute_definition_clause}s.]} @end{DiffWord2005} @LabeledClause{Visibility} @begin{Intro} @redundant[@Defn{visibility rules} The @i{visibility rules}, given below, determine which declarations are visible and directly visible at each place within a program. The visibility rules apply to both explicit and implicit declarations.] @end{Intro} @begin{StaticSem} @Defn2{Term=[visibility], Sec=(direct)} @Defn{directly visible} @Defn{directly visible} A declaration is defined to be @i{directly visible} at places where a @nt<name> consisting of only an @nt{identifier} or @nt{operator_symbol} is sufficient to denote the declaration; that is, no @nt<selected_component> notation or special context (such as preceding => in a named association) is necessary to denote the declaration. @Defn{visible} A declaration is defined to be @i{visible} wherever it is directly visible, as well as at other places where some @nt<name> (such as a @nt<selected_component>) can denote the declaration. The syntactic category @nt<direct_name> is used to indicate contexts where direct visibility is required. The syntactic category @nt<selector_name> is used to indicate contexts where visibility, but not direct visibility, is required. @Defn2{Term=[visibility], Sec=(immediate)} @Defn2{Term=[visibility], Sec=(use clause)} There are two kinds of direct visibility: @i{immediate visibility} and @i{use-visibility}. @Defn{immediately visible} A declaration is immediately visible at a place if it is directly visible because the place is within its immediate scope. @Defn{use-visible} A declaration is use-visible if it is directly visible because of a @nt{use_clause} (see @RefSecNum{Use Clauses}). Both conditions can apply. @Defn{hiding} A declaration can be @i{hidden}, either from direct visibility, or from all visibility, within certain parts of its scope. @Defn{hidden from all visibility} Where @i{hidden from all visibility}, it is not visible at all (neither using a @nt<direct_name> nor a @nt<selector_name>). @Defn{hidden from direct visibility} Where @i{hidden from direct visibility}, only direct visibility is lost; visibility using a @nt<selector_name> is still possible. @redundant[@Defn{overloaded} Two or more declarations are @i{overloaded} if they all have the same defining name and there is a place where they are all directly visible.] @begin{Ramification} Note that a @nt{name} can have more than one possible interpretation even if it denotes a nonoverloadable entity. For example, if there are two functions F that return records, both containing a component called C, then the name F.C has two possible interpretations, even though component declarations are not overloadable. @end{Ramification} @Defn{overloadable} The declarations of callable entities @Redundant[(including enumeration literals)] are @i{overloadable}@Redundant[, meaning that overloading is allowed for them]. @begin{Ramification} A @nt{generic_declaration} is not overloadable within its own @nt{generic_formal_part}. This follows from the rules about when a @nt{name} denotes a current instance. See AI83-00286. This implies that within a @nt{generic_formal_part}, outer declarations with the same defining name are hidden from direct visibility. It also implies that if a generic formal parameter has the same defining name as the generic itself, the formal parameter hides the generic from direct visibility. @end{Ramification} @Defn{homograph} Two declarations are @i{homographs} if they have the same defining name, and, if both are overloadable, their profiles are type conformant. @PDefn{type conformance} @redundant[An inner declaration hides any outer homograph from direct visibility.] @ChgToGlossary{Version=[2],Kind=[AddedNormal],Term=<Overriding operation>, Text=[@ChgAdded{Version=[2],Text=[An overriding operation is one that replaces an inherited primitive operation. Operations may be marked explicitly as overriding or not overriding.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} @leading@Redundant[Two homographs are not generally allowed immediately within the same declarative region unless one @i{overrides} the other (see Legality Rules below).] @Defn{override} @Chg{New=[The only declarations that are @Defn{overridable}@i{overridable} are the implicit declarations for predefined operators and inherited primitive subprograms.],Old=[]} A declaration overrides another homograph that occurs immediately within the same declarative region in the following cases: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} @Chg{New=[A declaration that is not overridable overrides one that is overridable], Old=[An explicit declaration overrides an implicit declaration of a primitive subprogram]}, @Redundant[regardless of which declaration occurs first]; @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],ARef=[AI95-00044-01]} And regardless of whether the @Chg{New=[nonoverridable],Old=[explicit]} declaration is overloadable or not. @Chg{New=[For example, @nt{statement_identifier}s are covered by this rule.],Old=[]} The @lquotes@;regardless of which declaration occurs first@rquotes@; is there because the explicit declaration could be a primitive subprogram of a partial view, and then the full view might inherit a homograph. We are saying that the explicit one wins (within its scope), even though the implicit one comes later. If the overriding declaration is also a subprogram, then it is a primitive subprogram. As explained in @RefSec{Private Operations}, some inherited primitive subprograms are never declared. Such subprograms cannot be overridden, although they can be reached by dispatching calls in the case of a tagged type. @end{Ramification} The implicit declaration of an inherited operator overrides that of a predefined operator; @begin{Ramification} In a previous version of Ada 9X, we tried to avoid the notion of predefined operators, and say that they were inherited from some magical root type. However, this seemed like too much mechanism. Therefore, a type can have a predefined "+" as well as an inherited "+". The above rule says the inherited one wins. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The @lquotes@;regardless of which declaration occurs first@rquotes@; applies here as well, in the case where @Chg{Version=[2],New=[@nt{derived_type_definition}], Old=[@ntf{derived_type_declaration}]} in the visible part of a public library unit derives from a private type declared in the parent unit, and the full view of the parent type has additional predefined operators, as explained in @RefSec{Private Operations}. Those predefined operators can be overridden by inherited subprograms implicitly declared earlier. @end{Ramification} An implicit declaration of an inherited subprogram overrides a previous implicit declaration of an inherited subprogram. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If two or more homographs are implicitly declared at the same place:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If at least one is a subprogram that is neither a null procedure nor an abstract subprogram, and does not require overriding (see @RefSecNum{Abstract Types and Subprograms}), then they override those that are null procedures, abstract subprograms, or require overriding. If more than one such homograph remains that is not thus overridden, then they are all hidden from all visibility.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Otherwise (all are null procedures, abstract subprograms, or require overriding), then any null procedure overrides all abstract subprograms and all subprograms that require overriding; if more than one such homograph remains that is not thus overridden, then if they are all fully conformant with one another, one is chosen arbitrarily; if not, they are all hidden from all visibility. @Defn2{Term=[full conformance],Sec=(required)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case where the implementation arbitrarily chooses one overrider from among a group of inherited subprograms, users should not be able to determine which member was chosen, as the set of inherited subprograms which are chosen from must be fully conformant. This rule is needed in order to allow]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[@Key{package} Outer @Key{is} @Key{package} P1 @Key{is} @Key{type} Ifc1 @Key{is interface}; @Key{procedure} Null_Procedure (X : Ifc1) @Key{is null}; @Key{procedure} Abstract_Subp (X : Ifc1) @Key{is abstract}; @Key{end} P1;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[ @Key{package} P2 @Key{is} @Key{type} Ifc2 @Key{is interface}; @Key{procedure} Null_Procedure (X : Ifc2) @Key{is null}; @Key{procedure} Abstract_Subp (X : Ifc2) @Key{is abstract}; @Key{end} P2;],Old=[]} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2],New=[ @Key{type} T @Key{is abstract new} P1.Ifc1 @Key{and} P2.Ifc2 @Key{with null record}; @Key{end} Outer;],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[without requiring that T explicitly override any of its inherited operations.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Full conformance is required here, as we cannot allow the parameter names to differ. If they did differ, the routine which was selected for overriding could be determined by using named parameter notation in a call.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the subprograms do not conform, we chose not to adopt the @lquotes@;use clause@rquotes rule which would make them all visible resulting in likely ambiguity. If we had used such a rule, any successful calls would be confusing; and the fact that there are no Beaujolais-like effect to worry about means we can consider other rules. The hidden-from-all-visibility homographs are still inherited by further derivations, which avoids order-of-declaration dependencies and other anomalies.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to be careful to not include arbitrary selection if the routines have real bodies. (This can happen in generics, see the example in the incompatibilities section below.) We don't want the ability to successfully call routines where the body executed depends on the compiler or a phase of the moon.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that if the type is concrete, abstract subprograms are inherited as subprograms that require overriding. We include functions that require overriding as well; these don't have real bodies, so they can use the more liberal rules.]} @end{Discussion} @end{InnerItemize} @Redundant[For an implicit declaration of a primitive subprogram in a generic unit, there is a copy of this declaration in an instance.] However, a whole new set of primitive subprograms is implicitly declared for each type declared within the visible part of the instance. These new declarations occur immediately after the type declaration, and override the copied ones. @Redundant[The copied ones can be called only from within the instance; the new ones can be called only from outside the instance, although for tagged types, the body of a new one can be executed by a call to an old one.] @begin{Discussion} In addition, this is also stated redundantly (again), and is repeated, in @RefSec{Generic Instantiation}. The rationale for the rule is explained there. @end{Discussion} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0042-1]} @ChgAdded{Version=[3],Text=[The implicit subprograms declared when an operation of a progenitor is implemented by an entry or subprogram also override the appropriate implicitly declared inherited operations of the progenitor.@PDefn2{Term=[override],Sec=[when implemented by]}]} @end{Honest} @end{Itemize} @leading@Defn{visible} @RootDefn{hidden from all visibility} A declaration is visible within its scope, except where hidden from all visibility, as follows: @begin{Itemize} @PDefn2{Term=[hidden from all visibility], Sec=(for overridden declaration)} An overridden declaration is hidden from all visibility within the scope of the overriding declaration. @begin{Ramification} We have to talk about the scope of the overriding declaration, not its visibility, because it hides even when it is itself hidden. Note that the scope of an explicit @nt{subprogram_declaration} does not start until after its profile. @end{Ramification} @leading@PDefn2{Term=[hidden from all visibility], Sec=(within the declaration itself)} A declaration is hidden from all visibility until the end of the declaration, except: @begin(InnerItemize) For a record type or record extension, the declaration is hidden from all visibility only until the reserved word @b(record); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} For a @nt{package_declaration}, @Chg{Version=[2],New=[],Old=[task declaration, protected declaration, ]}@nt{generic_@!package_@!declaration}, @Chg{Version=[3],New=[],Old=[or ]}@nt{subprogram_@!body}, @Chg{Version=[3],New=[or @nt{expression_@!function_@!declaration}, ],Old=[]}the declaration is hidden from all visibility only until the reserved word @key(is) of the declaration@Chg{Version=[2],New=[;],Old=[.]} @begin{Ramification} We're talking about the @key{is} of the construct itself, here, not some random @key{is} that might appear in a @nt{generic_formal_part}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[For a task declaration or protected declaration, the declaration is hidden from all visibility only until the reserved word @key(with) of the declaration if there is one, or the reserved word @key(is) of the declaration if there is no @key(with).]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If there is neither a @key(with) nor @key(is), then the exception does not apply and the name is hidden from all visibility until the end of the declaration. This oddity was inherited from Ada 95.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We need the @lquotes@key(with) or @key(is)@rquotes rule so that the visibility within an @nt{interface_list} does not vary by construct. That would make it harder to complete private extensions and would complicate implementations.]} @end{Reason} @end(InnerItemize) @PDefn2{Term=[hidden from all visibility], Sec=(for a declaration completed by a subsequent declaration)} If the completion of a declaration is a declaration, then within the scope of the completion, the first declaration is hidden from all visibility. Similarly, a @nt{discriminant_@!specification} or @nt{parameter_@!specification} is hidden within the scope of a corresponding @nt{discriminant_@!specification} or @nt{parameter_@!specification} of a corresponding completion, or of a corresponding @nt{accept_@!statement}. @begin{Ramification} This rule means, for example, that within the scope of a @nt{full_type_declaration} that completes a @nt{private_type_declaration}, the name of the type will denote the @nt{full_type_declaration}, and therefore the full view of the type. On the other hand, if the completion is not a declaration, then it doesn't hide anything, and you can't denote it. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @PDefn2{Term=[hidden from all visibility], Sec=(by lack of a @nt{with_clause})} The declaration of a library unit (including a @nt{library_unit_renaming_declaration}) is hidden from all visibility @Chg{Version=[2],New=[],Old=[except ]}at places @Chg{Version=[2],New=[outside],Old=[that are within]} its declarative region @Chg{Version=[2],New=[that are not],Old=[or]} within the scope of a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} that mentions it.@Chg{Version=[2],New=[ The limited view of a library package is hidden from all visibility at places that are not within the scope of a @nt{limited_with_clause} that mentions it; in addition, the limited view is hidden from all visibility within the declarative region of the package, as well as within the scope of any @nt{nonlimited_with_clause} that mentions the package. Where the declaration of the limited view of a package is visible, any name that denotes the package denotes the limited view, including those provided by a package renaming.],Old=[@Redundant[For each declaration or renaming of a generic unit as a child of some parent generic package, there is a corresponding declaration nested immediately within each instance of the parent.] Such a nested declaration is hidden from all visibility except at places that are within the scope of a @nt{with_clause} that mentions the child.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} This is the rule that prevents @nt{with_clause}s from being transitive; the [immediate] scope includes indirect semantic dependents. @Chg{Version=[2],New=[This rule also prevents the limited view of a package from being visible in the same place as the full view of the package, which prevents various ripple effects.],Old=[]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00412-01]}@ChgNote{Just moved from above} @ChgAdded{Version=[2],Text=[@Redundant[For each declaration or renaming of a generic unit as a child of some parent generic package, there is a corresponding declaration nested immediately within each instance of the parent.] Such a nested declaration is hidden from all visibility except at places that are within the scope of a @nt{with_clause} that mentions the child.]} @end{Itemize} @leading@Defn{directly visible} @Defn{immediately visible} @Defn2{Term=[visibility], Sec=(direct)} @Defn2{Term=[visibility], Sec=(immediate)} A declaration with a @nt{defining_identifier} or @nt{defining_operator_symbol} is immediately visible @Redundant[(and hence directly visible)] within its immediate scope @RootDefn{hidden from direct visibility} except where hidden from direct visibility, as follows: @begin{Itemize} @PDefn2{Term=[hidden from direct visibility], Sec=(by an inner homograph)} A declaration is hidden from direct visibility within the immediate scope of a homograph of the declaration, if the homograph occurs within an inner declarative region; @PDefn2{Term=[hidden from direct visibility], Sec=(where hidden from all visibility)} A declaration is also hidden from direct visibility where hidden from all visibility. @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00195-01],ARef=[AI95-00408-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[visible], Sec=(attribute_@!definition_@!clause)} An @nt{attribute_definition_clause} @Chg{Version=[3],New=[or an @nt{aspect_specification}@PDefn2{Term=[visible], Sec=(aspect_@!specification)} ],Old=[]}is @i{visible} everywhere within its scope.]} @end{StaticSem} @begin{Resolution} @PDefn2{Term=[possible interpretation], Sec=(for @nt{direct_name}s)} A @nt{direct_name} shall resolve to denote a directly visible declaration whose defining name is the same as the @nt{direct_name}. @PDefn2{Term=[possible interpretation], Sec=(for @nt{selector_name}s)} A @nt{selector_name} shall resolve to denote a visible declaration whose defining name is the same as the @nt{selector_name}. @begin{Discussion} "The same as" has the obvious meaning here, so for +, the possible interpretations are declarations whose defining name is "+" (an @nt{operator_symbol}). @end{Discussion} These rules on visibility and direct visibility do not apply in a @nt{context_clause}, a @nt{parent_unit_name}, or a @nt{pragma} that appears at the place of a @nt{compilation_unit}. For those contexts, see the rules in @RefSec{Environment-Level Visibility Rules}. @begin{Ramification} Direct visibility is irrelevant for @nt{character_literal}s. In terms of overload resolution @nt{character_literal}s are similar to other literals, like @key{null} @em see @RefSecNum{Literals}. For @nt{character_literal}s, there is no need to worry about hiding, since there is no way to declare homographs. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0025],Ref=[8652/0026],ARef=[AI95-00044-01],ARef=[AI95-00150-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00377-01]} @Chg{New=[A nonoverridable],Old=[An explicit]} declaration is illegal if there is a homograph occurring immediately within the same declarative region that is visible at the place of the declaration, and is not hidden from all visibility by the @Chg{New=[nonoverridable],Old=[explicit]} declaration. @Chg{New=[In addition, a type extension is illegal if somewhere within its immediate scope it has two visible components with the same name.],Old=[]} Similarly, the @nt<context_clause> for a @Chg{Version=[2], New=[compilation unit],Old=[@nt<subunit>]} is illegal if it mentions (in a @nt<with_clause>) some library unit, and there is a homograph of the library unit that is visible at the place of the @Chg{Version=[2], New=[compilation unit],Old=[corresponding stub]}, and the homograph and the mentioned library unit are both declared immediately within the same declarative region.@PDefn{generic contract issue} These rules also apply to dispatching operations declared in the visible part of an instance of a generic unit. However, they do not apply to other overloadable declarations in an instance@Redundant[; such declarations may have type conformant profiles in the instance, so long as the corresponding declarations in the generic were not type conformant]. @PDefn{type conformance} @begin{Discussion} @leading@;Normally, these rules just mean you can't explicitly declare two homographs immediately within the same declarative region. The wording is designed to handle the following special cases: @begin{Itemize} If the second declaration completes the first one, the second declaration is legal. @leading@;If the body of a library unit contains an explicit homograph of a child of that same library unit, this is illegal only if the body mentions the child in its @nt<context_clause>, or if some subunit mentions the child. Here's an example: @begin{Example} @key[package] P @key[is] @key[end] P; @key[package] P.Q @key[is] @key[end] P.Q; @key[package] @key[body] P @key[is] Q : Integer; --@RI{ OK; we cannot see package P.Q here.} @key[procedure] Sub @key[is] @key[separate]; @key[end] P; @key[with] P.Q; @key[separate](P) @key[procedure] Sub @key[is] --@RI{ Illegal.} @key[begin] @key[null]; @key[end] Sub; @end{Example} @NoPrefix@;If package body P said "@key[with] P.Q;", then it would be illegal to declare the homograph Q: Integer. But it does not, so the body of P is OK. However, the subunit would be able to see both P.Q's, and is therefore illegal. @NoPrefix@;A previous version of Ada 9X allowed the subunit, and said that references to P.Q would tend to be ambiguous. However, that was a bad idea, because it requires overload resolution to resolve references to directly visible nonoverloadable homographs, which is something compilers have never before been required to do. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0026],Ref=[8652/0102],ARef=[AI95-00150-01],ARef=[AI95-00157-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[If a type extension contains a component with the same name as a component in an ancestor type, there must be no place where both components are visible. For instance:]} @begin{Example}@ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] A @key[is] @key[type] T @key[is tagged private]; @key[package] B @key[is] @key[type] NT @key[is new] T @key[with record] I: Integer; -- @RI{Illegal because T.I is visible in the body.} @key[end record]; -- @RI{T.I is not visible here.} @key[end] B; @key[private] @key[type] T @key[is tagged record] I: Integer; -- @RI{Illegal because T.I is visible in the body.} @key[end record]; @key[end] A;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @Chg{New=[@Chg{Version=[2],New=[],Old=[@key[package] A @key[is] ]}@key[package] @key[body] A @key[is] @key[package] @key[body] B @key[is] -- @RI{T.I becomes visible here.} @key[end] B; @key[end] A;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[package] A.C @key[is] @key[type] NT2 @key[is new] A.T @key[with record] I: Integer; -- @RI{Illegal because T.I is visible in the private part.} @key[end record]; -- @RI{T.I is not visible here.} @key[private] -- @RI{T.I is visible here.} @key[end] A.C;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[with] A; @key[package] D @key[is] @key[type] NT3 @key[is new] A.T @key[with record] I: Integer; -- @RI{Legal because T.I is never visible in this package.} @key[end record]; @key[end] D;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[with] D; @key[package] A.E @key[is] @key[type] NT4 @key[is new] D.NT3 @key[with null record]; X : NT4; I1 : Integer := X.I; -- @RI{D.NT3.I} I2 : Integer := D.NT3(X).I; -- @RI{D.NT3.I} I3 : Integer := A.T(X).I; -- @RI{A.T.I} @key[end] A.E;],Old=[]} @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0102],ARef=[AI95-00157-01]} @ChgAdded{Version=[1],NoPrefix=[T],Text=[D.NT3 can have a component I because the component I of the parent type is never visible. The parent component exists, of course, but is never declared for the type D.NT3. In the child package A.E, the component I of A.T is visible, but that does not change the fact that the A.T.I component was never declared for type D.NT3. Thus, A.E.NT4 does not (visibly) inherit the component I from A.T, while it does inherit the component I from D.NT3. Of course, both components exist, and can be accessed by a type conversion as shown above. This behavior stems from the fact that every characteristic of a type (including components) must be declared somewhere in the innermost declarative region containing the type @em if the characteristic is never visible in that declarative region, it is never declared. Therefore, such characteristics do not suddenly become available even if they are in fact visible in some other scope. See @RefSecNum{Private Operations} for more on the rules.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00377-01]} @ChgAdded{Version=[2],Text=[It is illegal to mention both an explicit child of an instance, and a child of the generic from which the instance was instantiated. This is easier to understand with an example:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{generic} @key{package} G1 @key{is} @key{end} G1;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{generic} @key{package} G1.G2 @key{is} @key{end} G1.G2;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{with} G1; @key{package} I1 @key{is new} G1;],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key{package} I1.G2 @key{renames} ...]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[@key{with} G1.G2; @key{with} I1.G2; -- @RI{Illegal} @key{package} Bad @key{is} ...],Old=[]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The context clause for Bad is illegal as I1 has an implicit declaration of I1.G2 based on the generic child G1.G2, as well as the mention of the explicit child I1.G2. As in the previous cases, this is illegal only if the context clause makes both children visible; the explicit child can be mentioned as long as the generic child is not (and vice-versa).]} @end{Itemize} Note that we need to be careful which things we make "hidden from all visibility" versus which things we make simply illegal for names to denote. The distinction is subtle. The rules that disallow names denoting components within a type declaration (see @RefSecNum{Discriminants}) do not make the components invisible at those places, so that the above rule makes components with the same name illegal. The same is true for the rule that disallows names denoting formal parameters within a @nt{formal_part} (see @RefSecNum{Subprogram Declarations}). @end{Discussion} @begin{Discussion} The part about instances is from AI83-00012. The reason it says @lquotes@;overloadable declarations@rquotes@; is because we don't want it to apply to type extensions that appear in an instance; components are not overloadable. @end{Discussion} @end{Legality} @begin{Notes} Visibility for compilation units follows from the definition of the environment in @RefSecNum{The Compilation Process}, except that it is necessary to apply a @nt{with_clause} to obtain visibility to a @nt{library_unit_declaration} or @nt{library_unit_renaming_declaration}. In addition to the visibility rules given above, the meaning of the occurrence of a @nt{direct_name} or @nt{selector_name} at a given place in the text can depend on the overloading rules (see @RefSecNum{The Context of Overload Resolution}). Not all contexts where an @nt<identifier>, @nt<character_literal>, or @nt<operator_symbol> are allowed require visibility of a corresponding declaration. Contexts where visibility is not required are identified by using one of these three syntactic categories directly in a syntax rule, rather than using @nt<direct_name> or @nt<selector_name>. @begin{Ramification} @leading@;An @nt{identifier}, @nt{character_literal} or @nt{operator_symbol} that occurs in one of the following contexts is not required to denote a visible or directly visible declaration: @begin{enumerate} A defining name. The @nt{identifier}s or @nt{operator_symbol} that appear after the reserved word @key{end} in a @nt{proper_body}. Similarly for @lquotes@;@key{end loop}@rquotes@;, etc. An @nt{attribute_designator}. A @nt{pragma} @nt{identifier}. A @SynI{pragma_argument_}@nt{identifier}. An @nt{identifier} specific to a pragma used in a pragma argument. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[An @nt{aspect_mark};]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[An @nt{identifier} specific to an aspect used in an @nt{aspect_definition}.]} @end{enumerate} The visibility rules have nothing to do with the above cases; the meanings of such things are defined elsewhere. Reserved words are not @nt{identifier}s; the visibility rules don't apply to them either. Because of the way we have defined "declaration", it is possible for a usage name to denote a @nt{subprogram_body}, either within that body, or (for a nonlibrary unit) after it (since the body hides the corresponding declaration, if any). Other bodies do not work that way. Completions of @nt{type_declaration}s and deferred constant declarations do work that way. @nt{Accept_statement}s are never denoted, although the @nt{parameter_specification}s in their profiles can be. @leading@;The scope of a subprogram does not start until after its profile. Thus, the following is legal: @begin{Example} X : @key[constant] Integer := 17; ... @key[package] P @key[is] @key[procedure] X(Y : @key[in] Integer := X); @key[end] P; @end{Example} The body of the subprogram will probably be illegal, however, since the constant X will be hidden by then. @leading@;The rule is different for generic subprograms, since they are not overloadable; the following is illegal: @begin{Example} X : @key[constant] Integer := 17; @key[package] P @key[is] @key[generic] Z : Integer := X; --@RI{ Illegal!} @key[procedure] X(Y : @key[in] Integer := X); --@RI{ Illegal!} @key[end] P; @end{Example} The constant X is hidden from direct visibility by the generic declaration. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Declarations with the same defining name as that of a subprogram or entry being defined are nevertheless visible within the subprogram specification or entry declaration. @end{Extend83} @begin{DiffWord83} The term @lquotes@;visible by selection@rquotes@; is no longer defined. We use the terms @lquotes@;directly visible@rquotes@; and @lquotes@;visible@rquotes@; (among other things). There are only two regions of text that are of interest, here: the region in which a declaration is visible, and the region in which it is directly visible. Visibility is defined only for declarations. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} Added rules to handle the inheritance and overriding of multiple homographs for a single type declaration, in order to support multiple inheritance from interfaces. The new rules are intended to be compatible with the existing rules so that programs that do not use interfaces do not change their legality. However, there is a very rare case where this is not true:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T1 @key{is private}; @key{type} T2 @key{is private}; @key{package} G @key{is} @key{type} T @key{is null record}; @key{procedure} P (X : T; Y : T1); @key{procedure} P (X : T; Z : T2); @key{end} G;]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} I @key{is new} G (Integer, Integer); -- @RI[Exports homographs of P.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} D @key{is new} I.T; -- @RI[Both Ps are inherited.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Obj : D;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[P (Obj, Z => 10); -- @RI[Legal in Ada 95, illegal in Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The call to P would resolve in Ada 95 by using the parameter name, while the procedures P would be hidden from all visibility in Ada 2005 and thus would not resolve. This case doesn't seem worth making the rules any more complex than they already are.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00377-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] A @nt{with_clause} is illegal if it would create a homograph of an implicitly declared generic child (see @RefSecNum{Compilation Units - Library Units}). An Ada 95 compiler could have allowed this, but which unit of the two units involved would be denoted wasn't specified, so any successful use isn't portable. Removing one of the two @nt{with_clause}s involved will fix the problem.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0025],ARef=[AI95-00044-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the overriding rules so that "/=" and @nt{statement_identifier}s are covered.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0026],ARef=[AI95-00150-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that is it never possible for two components with the same name to be visible; any such program is illegal.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01],ARef=[AI95-00408-01]} @ChgAdded{Version=[2],Text=[The visibility of an @nt{attribute_definition_clause} is defined so that it can be used by the stream attribute availability rules (see @RefSecNum{Stream-Oriented Attributes}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The visibility of a limited view of a library package is defined (see @RefSecNum{Compilation Units - Library Units}).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Added wording so that the parameters of an @nt{expression_@!function_@!declaration} are visible in the @nt{expression} of the function. (It would be pretty useless without such a rule.)]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[The visibility of an @nt{aspect_specification} is defined so that it can be used in various other rules.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledAddedSubClause{Version=[2],Name=[Overriding Indicators]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is used to declare that an operation is intended to override (or not override) an inherited operation.]} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<overriding_indicator>,Old=<>}>, rhs="@Chg{Version=[2],New=<[@key{not}] @key{overriding}>,Old=<>}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03],ARef=[AI95-00348-01],ARef=[AI95-00397-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[If an @nt{abstract_@!subprogram_@!declaration}, @nt{null_@!procedure_@!declaration},@Chg{Version=[3],New=[ @nt{expression_@!function_@!declaration},],Old=[]} @nt{subprogram_body}, @nt{subprogram_@!body_stub}, @nt{subprogram_@!renaming_@!declaration}, @nt{generic_@!instantiation} of a subprogram, or @nt{subprogram_@!declaration} other than a protected subprogram has an @nt{overriding_@!indicator}, then:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the operation shall be a primitive operation for some type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the operation shall override a homograph at the place of the declaration or body;]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This doesn't require that the overriding happen at precisely the place of the declaration or body; it only requires that the region in which the overriding is known to have happened includes this place. That is, the overriding can happen at or before the place of the declaration or body.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the operation shall not override any homograph (at any place).]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply, these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @Key{overriding} and @Key{not overriding} rules differ slightly. For @Key{overriding}, we want the indicator to reflect the overriding state at the place of the declaration; otherwise the indicator would be @LQuotes@;lying@RQuotes@;. Whether a homograph is implicitly declared after the declaration (see 7.3.1 to see how this can happen) has no impact on this check. However, @Key{not overriding} is different; @LQuotes@;lying@RQuotes@; would happen if a homograph declared later actually is overriding. So, we require this check to take into account later overridings. That can be implemented either by looking ahead, or by rechecking when additional operations are declared.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @LQuotes@;no lying@RQuotes@; rules are needed to prevent a @nt{subprogram_declaration} and @nt{subprogram_body} from having contradictory @nt{overriding_indicator}s.]} @end{Discussion} @end{Legality} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[Rules for @nt{overriding_indicator}s of task and protected entries and of protected subprograms are found in @RefSecNum{Entries and Accept Statements} and @RefSecNum{Protected Units and Protected Objects}, respectively.]} @end{Notes} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The use of @nt{overriding_indicator}s allows the detection of errors at compile-time that otherwise might not be detected at all. For instance, we might declare a security queue derived from the Queue interface of 3.9.4 as:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Security_Queue @key{is new} Queue @key{with record} ...;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{procedure} Append(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{procedure} Remove_First(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{function} Cur_Count(Q : @key{in} Security_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{overriding} @key{function} Max_Count(Q : @key{in} Security_Queue) @key{return} Natural;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{not overriding} @key{procedure} Arrest(Q : @key{in out} Security_Queue; Person : @key{in} Person_Name);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The first four subprogram declarations guarantee that these subprograms will override the four subprograms inherited from the Queue interface. A misspelling in one of these subprograms will be detected by the implementation. Conversely, the declaration of Arrest guarantees that this is a new operation.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, the subprograms are abstract, so misspellings will get detected anyway. But for other subprograms (especially when deriving from concrete types), the error might never be detected, and a body other than the one the programmer intended might be executed without warning. Thus our new motto: @lquotes@;Overriding indicators @em don't derive a type without them!@rquotes]} @end{Discussion} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Overriding_indicator}s are new. These let the programmer state her overriding intentions to the compiler; if the compiler disagrees, an error will be produced rather than a hard to find bug.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0177-1]} @ChgAdded{Version=[3],Text=[Expression functions can have overriding indicators.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Use Clauses} @begin{Intro} @redundant[A @nt{use_package_clause} achieves direct visibility of declarations that appear in the visible part of a package; a @nt{use_type_clause} achieves direct visibility of the primitive operators of a type.] @end{Intro} @begin{MetaRules} @Defn{equivalence of @nt{use_clause}s and @nt{selected_component}s} If and only if the visibility rules allow P.A, "@key[use] P;" should make A directly visible (barring name conflicts). This means, for example, that child library units, and generic formals of a formal package whose @nt{formal_package_actual_part} is (<>), should be made visible by a @nt{use_clause} for the appropriate package. @Defn{Beaujolais effect} The rules for @nt{use_clause}s were carefully constructed to avoid so-called @i(Beaujolais) effects, where the addition or removal of a single @nt{use_clause}, or a single declaration in a "use"d package, would change the meaning of a program from one legal interpretation to another. @end{MetaRules} @begin{Syntax} @Syn{lhs=<use_clause>,rhs="@Syn2{use_package_clause} | @Syn2{use_type_clause}"} @Syn{lhs=<use_package_clause>,rhs="@key{use} @SynI{package_}@Syn2{name} {, @SynI{package_}@Syn2{name}};"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0150-1]} @Syn{lhs=<use_type_clause>,rhs="@key[use] @Chg{Version=[3],New={[@key[all]] },Old=[]}@key[type] @Syn2{subtype_mark} {, @Syn2{subtype_mark}};"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @SynI{package_}@nt{name} of a @nt{use_package_clause} shall denote @Chg{Version=[2],New=[a nonlimited view of ],Old=[]}a package. @begin{Ramification} This includes formal packages. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn2{Term=[scope], Sec=(of a @nt{use_clause})} For each @nt{use_clause}, there is a certain region of text called the @i{scope} of the @nt{use_clause}. For a @nt{use_clause} within a @nt{context_clause} of a @nt{library_unit_declaration} or @nt{library_unit_renaming_declaration}, the scope is the entire declarative region of the declaration. For a @nt{use_clause} within a @nt{context_clause} of a body, the scope is the entire body @Redundant[and any subunits (including multiply nested subunits). The scope does not include @nt<context_clause>s themselves.] For a @nt{use_clause} immediately within a declarative region, the scope is the portion of the declarative region starting just after the @nt{use_clause} and extending to the end of the declarative region. However, the scope of a @nt{use_clause} in the private part of a library unit does not include the visible part of any public descendant of that library unit. @begin{Reason} @leading@;The exception echoes the similar exception for @lquotes@;immediate scope (of a declaration)@rquotes@; (see @RefSecNum{Scope of Declarations}). It makes @nt{use_clause}s work like this: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[range] 1..10; @key[end] P; @key[with] P; @key[package] Parent @key[is] @key[private] @key[use] P; X : T; @key[end] Parent; @key[package] Parent.Child @key[is] Y : T; --@RI{ Illegal!} Z : P.T; @key[private] W : T; @key[end] Parent.Child; @end{Example} The declaration of Y is illegal because the scope of the @lquotes@;@key[use] P@rquotes@; does not include that place, so T is not directly visible there. The declarations of X, Z, and W are legal. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @Chg{Version=[2],New=[A package is @i{named} in a @nt{use_package_clause} if it is denoted by a @SynI{package_}@nt{name} of that clause. A type is @i{named} in a @nt{use_type_clause} if it is determined by a @nt{subtype_mark} of that clause.@Defn2{Term=[named],Sec=[in a use clause]}],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0150-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{Dummy to add conditional leading} @Defn{potentially use-visible} For each package @Chg{Version=[2],New=[named in ],Old=[denoted by a @SynI{package_}@nt{name} of ]}a @nt{use_package_clause} whose scope encloses a place, each declaration that occurs immediately within the declarative region of the package is @i(potentially use-visible) at this place if the declaration is visible at this place. For each type @i(T) or @i(T)'Class @Chg{Version=[2],New=[named in ],Old=[ determined by a @nt<subtype_mark> of ]}a @nt{use_type_clause} whose scope encloses a place, the declaration of each primitive operator of type @i(T) is potentially use-visible at this place if its declaration is visible at this place.@Chg{Version=[3], New=[ If a @nt{use_type_clause} whose scope encloses a place includes the reserved word @key[all], then the following entities are also potentially use-visible at this place if the declaration of the entity is visible at this place:],Old=[]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0150-1]} @ChgAdded{Version=[3],Text=[Each primitive subprogram of @i<T> including each enumeration literal (if any);]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0150-1]} @ChgAdded{Version=[3],Text=[Each subprogram that is declared immediately within the declarative region in which an ancestor type of @i<T> is declared and that operates on a class-wide type that covers @i<T>.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0150-1]} Primitive subprograms whose defining name is an @nt{identifier} are @i{not} made potentially visible by a @nt{use_type_clause}@Chg{Version=[3],New=[ unless reserved word @key[all] is included],Old=[]}. A @nt{use_type_clause} @Chg{Version=[3],New=[without @key[all] ],Old=[]}is only for operators. The semantics described here should be similar to the semantics for expanded names given in @RefSec{Selected Components} so as to achieve the effect requested by the @lquotes@;principle of equivalence of @nt{use_clause}s and @nt{selected_component}s.@rquotes@; Thus, child library units and generic formal parameters of a formal package are potentially use-visible when their enclosing package is use'd. The "visible at that place" part implies that applying a @nt{use_clause} to a parent unit does not make all of its children use-visible @em only those that have been made visible by a @nt{with_clause}. It also implies that we don't have to worry about hiding in the definition of "directly visible" @em a declaration cannot be use-visible unless it is visible. Note that "@key[use type] T'Class;" is equivalent to "@key[use type] T;", which helps avoid breaking the generic contract model. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[Certain implicit declarations may become potentially use-visible in certain contexts as described in @RefSecNum{Formal Subprograms}.]} @leading@Defn{use-visible} @Defn2{Term=[visibility],Sec=(use clause)} A declaration is @i{use-visible} if it is potentially use-visible, except in these naming-conflict cases: @begin{itemize} A potentially use-visible declaration is not use-visible if the place considered is within the immediate scope of a homograph of the declaration. Potentially use-visible declarations that have the same @nt{identifier} are not use-visible unless each of them is an overloadable declaration. @begin{Ramification} Overloadable declarations don't cancel each other out, even if they are homographs, though if they are not distinguishable by formal parameter names or the presence or absence of @nt{default_expression}s, any use will be ambiguous. We only mention @nt{identifier}s here, because declarations named by @nt<operator_symbol>s are always overloadable, and hence never cancel each other. Direct visibility is irrelevant for @nt{character_literal}s. @end{Ramification} @end{itemize} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(use_clause)} The elaboration of a @nt{use_clause} has no effect. @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of a use clause in a context clause:} @begin{Example} @key[with] Ada.Calendar; @key[use] Ada; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a use type clause:} @end{WideAbove} @begin{Example} @key[use type] Rational_Numbers.Rational; --@RI{ see @RefSecNum{Package Specifications and Declarations}} Two_Thirds: Rational_Numbers.Rational := 2/3; @end{Example} @begin{Ramification} In @lquotes@;@key[use] X, Y;@rquotes@;, Y cannot refer to something made visible by the @lquotes@;@key[use]@rquotes@; of X. Thus, it's not (quite) equivalent to @lquotes@;@key[use] X; @key[use] Y;@rquotes@;. If a given declaration is already immediately visible, then a @nt{use_clause} that makes it potentially use-visible has no effect. Therefore, a @nt{use_type_clause} for a type whose declaration appears in a place other than the visible part of a package has no effect; it cannot make a declaration use-visible unless that declaration is already immediately visible. "@key[Use] @key[type] S1;" and "@key[use] @key[type] S2;" are equivalent if S1 and S2 are both subtypes of the same type. In particular, "@key[use] @key[type] S;" and "@key[use] @key[type] S'Base;" are equivalent. @end{Ramification} @begin{Reason} We considered adding a rule that prevented several declarations of views of the same entity that all have the same semantics from cancelling each other out. For example, if a (possibly implicit) @nt{subprogram_declaration} for "+" is potentially use-visible, and a fully conformant renaming of it is also potentially use-visible, then they (annoyingly) cancel each other out; neither one is use-visible. The considered rule would have made just one of them use-visible. We gave up on this idea due to the complexity of the rule. It would have had to account for both overloadable and nonoverloadable @nt{renaming_declaration}s, the case where the rule should apply only to some subset of the declarations with the same defining name, and the case of @nt{subtype_declaration}s (since they are claimed to be sufficient for renaming of subtypes). @end{Reason} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt{use_type_clause} is new to Ada 95. @end{Extend83} @begin{DiffWord83} The phrase @lquotes@;omitting from this set any packages that enclose this place@rquotes@; is no longer necessary to avoid making something visible outside its scope, because we explicitly state that the declaration has to be visible in order to be potentially use-visible. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Limited views of packages are not allowed in use clauses. Defined @i<named in a use clause> for use in other limited view rules (see @RefSecNum{Context Clauses - With Clauses}).]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0150-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}The @key[use all type] version of the @nt{use_type_clause} is new to Ada 2012. It works similarly to prefixed views.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to allow other declarations to be potentially use-visible, to support corrections to formal subprograms.]} @end{DiffWord2005} @LabeledClause{Renaming Declarations} @begin{Intro} @redundant[A @nt{renaming_declaration} declares another name for an entity, such as an object, exception, package, subprogram, entry, or generic unit. Alternatively, a @nt{subprogram_renaming_declaration} can be the completion of a previous @nt{subprogram_declaration}.] @ChgToGlossary{Version=[2],Kind=[Added],Term=<Renaming>, Text=<@ChgAdded{Version=[2],Text=[A @nt{renaming_declaration} is a declaration that does not define a new entity, but instead defines a view of an existing entity.]}>} @end{Intro} @begin{Syntax} @Syn{lhs=<renaming_declaration>,rhs=" @Syn2{object_renaming_declaration} | @Syn2{exception_renaming_declaration} | @Syn2{package_renaming_declaration} | @Syn2{subprogram_renaming_declaration} | @Syn2{generic_renaming_declaration}"} @end{Syntax} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(renaming_declaration)} The elaboration of a @nt{renaming_declaration} evaluates the @nt{name} that follows the reserved word @key{renames} and thereby determines the view and entity denoted by this name @Defn{renamed view} @Defn{renamed entity} (the @i{renamed view} and @i{renamed entity}). @Redundant[A @nt{name} that denotes the @nt{renaming_declaration} denotes (a new view of) the renamed entity.] @end{RunTime} @begin{Notes} Renaming may be used to resolve name conflicts and to act as a shorthand. Renaming with a different @nt{identifier} or @nt{operator_symbol} does not hide the old @nt{name}; the new @nt{name} and the old @nt{name} need not be visible at the same places. A task or protected object that is declared by an explicit @nt{object_declaration} can be renamed as an object. However, a single task or protected object cannot be renamed since the corresponding type is anonymous (meaning it has no nameable subtypes). For similar reasons, an object of an anonymous array or access type cannot be renamed. @leading@keepnext@;A subtype defined without any additional constraint can be used to achieve the effect of renaming another subtype (including a task or protected subtype) as in @begin{Example} @key[subtype] Mode @key[is] Ada.Text_IO.File_Mode; @end{Example} @end{Notes} @begin{DiffWord83} The second sentence of RM83-8.5(3), @lquotes@;At any point where a renaming declaration is visible, the identifier, or operator symbol of this declaration denotes the renamed entity.@rquotes@; is incorrect. It doesn't say directly visible. Also, such an @nt{identifier} might resolve to something else. The verbiage about renamings being legal @lquotes@;only if exactly one...@rquotes@;, which appears in RM83-8.5(4) (for objects) and RM83-8.5(7) (for subprograms) is removed, because it follows from the normal rules about overload resolution. For language lawyers, these facts are obvious; for programmers, they are irrelevant, since failing these tests is highly unlikely. @end{DiffWord83} @LabeledSubClause{Object Renaming Declarations} @begin{Intro} @redundant[An @nt{object_renaming_declaration} is used to rename an object.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00423-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<object_renaming_declaration>,rhs="@Chg{Version=[2],New=[ ],Old=[]}@Syn2{defining_identifier} : @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} @key{renames} @SynI{object_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};@Chg{Version=[2],New=[ | @Syn2{defining_identifier} : @Syn2{access_definition} @key{renames} @SynI{object_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};],Old=[]}"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} The type of the @SynI{object_}@nt{name} shall resolve to the type determined by the @nt{subtype_mark}@Chg{Version=[2],New=[, or in the case where the type is defined by an @nt{access_definition}, to an anonymous access type. If the anonymous access type is an access-to-object type, the type of the @SynI{object_}@nt{name} shall have the same designated type as that of the @nt{access_definition}. If the anonymous access type is an access-to-subprogram type, the type of the @SynI{object_}@nt{name} shall have a designated profile that is type conformant with that of the @nt{access_definition}],Old=[]}. @begin{Reason} @leading@;A previous version of Ada 9X used the usual @lquotes@;expected type@rquotes@; wording:@* @lquotes@;The expected type for the @SynI{object_}@nt{name} is that determined by the @nt{subtype_mark}.@rquotes@;@* We changed it so that this would be illegal: @begin{Example} X: T; Y: T'Class @key[renames] X; --@RI{ Illegal!} @end{Example} @leading@;When the above was legal, it was unclear whether Y was of type T or T'Class. Note that we still allow this: @begin{Example} Z: T'Class := ...; W: T @key[renames] F(Z); @end{Example} where F is a function with a controlling parameter and result. This is admittedly a bit odd. Note that the matching rule for generic formal parameters of mode @key[in out] was changed to keep it consistent with the rule for renaming. That makes the rule different for @key[in] vs. @key[in out]. @end{Reason} @end{Resolution} @begin{Legality} The renamed entity shall be an object. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In the case where the type is defined by an @nt{access_definition}, the type of the renamed object and the type defined by the @nt{access_definition}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-object types with statically matching designated subtypes and with both or neither being access-to-constant types; or @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-subprogram types with subtype conformant designated profiles. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an @nt{object_renaming_declaration} with a @nt{null_exclusion} or an @nt{access_definition} that has a @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @Syni{object_}@nt{name} denotes a generic formal object of a generic unit @i{G}, and the @nt{object_renaming_declaration} occurs within the body of @i{G} or within the body of a generic unit declared within the declarative region of @i{G}, then the declaration of the formal object of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the @Syni{object_}@nt{name} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of an object with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in one obscure case:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Acc_I @key{is access} Integer; @key{subtype} Acc_NN_I @key{is not null} Acc_I; Obj : Acc_I := @key{null};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} B : @key{in out} Acc_NN_I; @key{package} Gen @key{is} ... @key{end} Gen;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Gen @key{is} D : @key{not null} Acc_I @key{renames} B; @key{end} Gen;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Inst @key{is new} Gen (B => Obj);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Without the first bullet rule, D would be legal, and contain the value @key{null}, because the rule about lying is satisfied for generic matching (Obj matches B; B does not explicitly state @key{not null}), @LegalityTitle are not rechecked in the body of any instance, and the template passes the lying rule as well. The rule is so complex because it has to apply to formals used in bodies of child generics as well as in the bodies of generics.]} @end{Reason} @end{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00363-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0008-1]} The renamed entity shall not be a subcomponent that depends on discriminants of @Chg{Version=[3],New=[an object],Old=[a variable]} whose nominal subtype is unconstrained@Chg{Version=[3],New=[],Old=[,]} unless @Chg{Version=[3],New=[the object is known to be constrained], Old=[this subtype is indefinite, or the variable is @Chg{Version=[2], New=[constrained by its initial value],Old=[aliased]}]}. A @nt{slice} of an array shall not be renamed if this restriction disallows renaming of the array. @Chg{New=[@PDefn{generic contract issue}In addition to the places where Legality Rules normally apply, these rules apply also in the private part of an instance of a generic unit.@Chg{Version=[3],New=[],Old=[ These rules also apply for a renaming that appears in the body of a generic unit, with the additional requirement that even if the nominal subtype of the variable is indefinite, its type shall not be a descendant of an untagged generic formal derived type.]}],Old=[]} @begin{Reason} This prevents renaming of subcomponents that might disappear, which might leave dangling references. Similar restrictions exist for the Access attribute. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0008-1]} @ChgAdded{Version=[1],Type=[Leading],Text=[The @lquotes@;recheck on instantiation@rquotes@; @Chg{Version=[3],New=[requirement], Old=[and @lquotes@;assume-the-worst in the body@rquotes@; restrictions]} on generics @Chg{Version=[3],New=[is],Old=[are]} necessary to avoid renaming of components which could disappear even when the nominal subtype would prevent the problem:]} @begin{Example} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{type} T1 (D1 : Boolean) @key{is} @key{record} @key{case} D1 @key{is} @key{when} False => C1 : Integer; @key{when} True => @key{null}; @key{end} @key{case}; @key{end} @key{record};],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{generic} @key{type} F @key{is} @key{new} T1; X : @key{in out} F; @key{package} G @key{is} C1_Ren : Integer @key{renames} X.C1; @key{end} G;],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key{type} T2 (D2 : Boolean := False) @key{is} @key{new} T1 (D1 => D2); @Comment{Blank line} Y : T2; @Comment{Blank line} @key{package} I @key{is new} G (T2, Y); @Comment{Blank line} Y := (D1 => True); -- @RI[Oops! What happened to I.C1_Ren?]],Old=[]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[In addition, the @ldquote@;known to be constrained@rdquote rules include assume-the-worst rules for generic bodies partially to prevent such problems.]} @end{Reason} @begin{ImplNote} Note that if an implementation chooses to deallocate-then-reallocate on @nt{assignment_@!statement}s assigning to unconstrained definite objects, then it cannot represent renamings and access values as simple addresses, because the above rule does not apply to all components of such an object. @end{ImplNote} @begin{Ramification} If it is a generic formal object, then the assume-the-best or assume-the-worst rules are applied as appropriate. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00409-01]} An @nt{object_renaming_declaration} declares a new view @Redundant{of the renamed object} whose properties are identical to those of the renamed view. @Redundant[Thus, the properties of the renamed object are not affected by the @nt{renaming_declaration}. In particular, its value and whether or not it is a constant are unaffected; similarly, the@Chg{Version=[2],New=[ null exclusion or],Old=[]} constraints that apply to an object are not affected by renaming (any constraint implied by the @nt{subtype_mark} @Chg{Version=[2],New=[or @nt{access_definition} ],Old=[]}of the @nt{object_renaming_declaration} is ignored).] @begin{Discussion} Because the constraints are ignored, it is a good idea to use the nominal subtype of the renamed object when writing an @nt{object_renaming_declaration}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[If no @nt{null_exclusion} is given in the renaming, the object may or may not exclude null. This is similar to the way that constraints need not match, and @key{constant} is not specified. The renaming defines a view of the renamed entity, inheriting the original properties.]} @end{Discussion} @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming an object:} @begin{Example} @key[declare] L : Person @key[renames] Leftmost_Person; --@RI{ see @RefSecNum{Incomplete Type Declarations}} @key[begin] L.Age := L.Age + 1; @key[end]; @end{Example} @end{Examples} @begin{DiffWord83} The phrase @lquotes@;subtype ... as defined in a corresponding object declaration, component declaration, or component subtype indication,@rquotes@; from RM83-8.5(5), is incorrect in Ada 95; therefore we removed it. It is incorrect in the case of an object with an indefinite unconstrained nominal subtype. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00363-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Leading@;@Defn{incompatibilities with Ada 95} Aliased variables are not necessarily constrained in Ada 2005 (see @RefSecNum{Array Types}). Therefore, a subcomponent of an aliased variable may disappear or change shape, and renaming such a subcomponent thus is illegal, while the same operation would have been legal in Ada 95. Note that most allocated objects are still constrained by their initial value (see @RefSecNum{Allocators}), and thus have no change in the legality of renaming for them. For example, using the type T2 of the previous example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ AT2 : @key{aliased} T2; C1_Ren : Integer @key{renames} AT2.C1; -- @RI[Illegal in Ada 2005, legal in Ada 95] AT2 := (D1 => True); -- @RI[Raised Constraint_Error in Ada 95,] -- @RI[but does not in Ada 2005, so C1_Ren becomes] -- @RI[invalid when this is assigned.]]} @end{Example} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A renaming can have an anonymous access type. In that case, the accessibility of the renaming is that of the original object (accessibility is not lost as it is for assignment to a component or stand-alone object).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[A renaming can have a @nt{null_exclusion}; if so, the renamed object must also exclude null, so that the @nt{null_exclusion} does not lie. On the other hand, if the renaming does not have a @nt{null_exclusion}. it excludes null if the renamed object does.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0017],ARef=[AI95-00184-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed to forbid renamings of depends-on-discriminant components if the type @i{might} be definite.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0008-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Simplified the description of when a discriminant-dependent component is allowed to be renamed @em it's now simply when the object is known to be constrained. This fixes a confusion as to whether a subcomponent of an object that is not certain to be constrained can be renamed. The fix introduces an incompatibility, as the rule did not apply in Ada 95 if the prefix was a constant; but it now applies no matter what kind of object is involved. The incompatibility is not too bad, since most kinds of constants are known to be constrained.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in an @nt{object_renaming_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Exception Renaming Declarations} @begin{Intro} @redundant[An @nt{exception_renaming_declaration} is used to rename an exception.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<exception_renaming_declaration>,rhs="@Syn2{defining_identifier} : @key{exception} @key{renames} @SynI{exception_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Legality} The renamed entity shall be an exception. @end{Legality} @begin{StaticSem} An @nt{exception_renaming_declaration} declares a new view @Redundant{of the renamed exception}. @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming an exception:} @begin{Example} EOF : @key[exception] @key[renames] Ada.IO_Exceptions.End_Error; @RI{-- see @RefSecNum{Exceptions in Input-Output}} @end{Example} @end{Examples} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in an @nt{exception_renaming_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Package Renaming Declarations} @begin{Intro} @redundant[A @nt{package_renaming_declaration} is used to rename a package.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<package_renaming_declaration>,rhs="@key{package} @Syn2{defining_program_unit_name} @key{renames} @SynI{package_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Legality} The renamed entity shall be a package. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[If the @SynI{package_}@nt{name} of a @nt{package_renaming_declaration} denotes a limited view of a package @i{P}, then a name that denotes the @nt{package_renaming_declaration} shall occur only within the immediate scope of the renaming or the scope of a @nt{with_clause} that mentions the package @i{P} or, if @i{P} is a nested package, the innermost library package enclosing @i{P}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The use of a renaming that designates a limited view is restricted to locations where we know whether the view is limited or nonlimited (based on a @nt{with_clause}). We don't want to make an implicit limited view, as those are not transitive like a regular view. Implementations should be able to see all limited views needed based on the @nt{context_clause}.]} @end{Discussion} @end{Legality} @begin{StaticSem} A @nt{package_renaming_declaration} declares a new view @Redundant{of the renamed package}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[@Redundant[At places where the declaration of the limited view of the renamed package is visible, a @nt{name} that denotes the @nt{package_renaming_declaration} denotes a limited view of the package (see @RefSecNum{Compilation Units - Library Units}).]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This rule is found in @RefSec{Visibility}.]} @end{TheProof} @end{StaticSem} @begin{Examples} @leading@keepnext@i{Example of renaming a package:} @begin{Example} @key[package] TM @key[renames] Table_Manager; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[Uses of renamed limited views of packages can only be used within the scope of a with_clause for the renamed package.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{package_renaming_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Subprogram Renaming Declarations} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} A @nt{subprogram_renaming_declaration} can serve as the completion of a @nt{subprogram_declaration}; @Defn{renaming-as-body} such a @nt{renaming_declaration} is called a @i{renaming-as-body}. @Defn{renaming-as-declaration} A @nt{subprogram_renaming_declaration} that is not a completion is called a @i{renaming-as-declaration}@Redundant[, and is used to rename a subprogram (possibly an enumeration literal) or an entry]. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} A renaming-as-body is a declaration, as defined in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Declarations and Types}. @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<subprogram_renaming_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=<>}@Syn2{subprogram_specification} @key{renames} @SynI{callable_entity_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(subprogram_renaming_declaration)} The expected profile for the @i(callable_entity_)@nt<name> is the profile given in the @nt<subprogram_specification>. @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The profile of a renaming-as-declaration shall be @Chg{Version=[3],New=[mode conformant],Old=[mode-conformant]}, with that of the renamed callable entity. @Defn2{Term=[mode conformance],Sec=(required)} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a parameter or result subtype of the @nt{subprogram_specification} that has an explicit @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @Syni{callable_entity_}@nt{name} denotes a generic formal subprogram of a generic unit @i{G}, and the @nt{subprogram_renaming_declaration} occurs within the body of a generic unit @i{G} or within the body of a generic unit declared within the declarative region of the generic unit @i{G}, then the corresponding parameter or result subtype of the formal subprogram of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the corresponding parameter or result type of the renamed callable entity shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of a parameter or result with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child units) when the formal subtype excludes null implicitly.]} @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0027],Ref=[8652/0028],ARef=[AI95-00135-01],ARef=[AI95-00145-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The profile of a renaming-as-body @Chg{New=[],Old=[shall be subtype-conformant with that of the renamed callable entity, and ]}shall conform fully to that of the declaration it completes. @Defn2{Term=[full conformance],Sec=(required)} If the renaming-as-body completes that declaration before the subprogram it declares is frozen, @Chg{New=[the profile shall be @Chg{Version=[3],New=[mode conformant],Old=[mode-conformant]} @Defn2{Term=[mode conformance],Sec=(required)}with that of the renamed callable entity and ],Old=[]}the subprogram it declares takes its convention from the renamed subprogram; otherwise@Chg{New=[, the profile shall be @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]} with that of the renamed callable entity and],Old=[]} the convention of the renamed subprogram shall not be Intrinsic. @Defn2{Term=[subtype conformance],Sec=(required)} @Chg{New=[A renaming-as-body is illegal if the declaration occurs before the subprogram whose declaration it completes is frozen, and the renaming renames the subprogram itself, through one or more subprogram renaming declarations, none of whose subprograms has been frozen.],Old=[]} @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} The @Chg{New=[otherwise part of the second sentence],Old=[first part of the first sentence]} is to allow an implementation of a renaming-as-body as a single jump instruction to the target subprogram. Among other things, this prevents a subprogram from being completed with a renaming of an entry. (In most cases, the target of the jump can be filled in at link time. In some cases, such as a renaming of a name like "A(I).@key[all]", an indirect jump is needed. Note that the name is evaluated at renaming time, not at call time.) @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0028],ARef=[AI95-00145-01]} @Chg{New=[The first part of the second sentence is intended to allow renaming-as-body of predefined operators before the @nt{subprogram_declaration} is frozen. For some types (such as integer types), the parameter type for operators is the base type, and it would be very strange for@* @f{@ @ @ @key{function} Equal (A, B : @key{in} T) @key{return} Boolean;}@* @f{@ @ @ @key{function} Equal (A, B : @key{in} T) @key{return} Boolean @key{renames} "=";}@* to be illegal. (Note that predefined operators cannot be renamed this way after the @nt{subprogram_declaration} is frozen, as they have convention Intrinsic.)],Old=[]} @ChgRef{Version=[1],Kind=[Revised]} The @Chg{New=[],Old=[second part of the ]}first sentence is the normal rule for completions of @nt{subprogram_declaration}s. @end{Reason} @begin{Ramification} An @nt{entry_declaration}, unlike a @nt{subprogram_declaration}, cannot be completed with a @nt{renaming_@!declaration}. Nor can a @nt{generic_@!subprogram_@!declaration}. The syntax rules prevent a protected subprogram declaration from being completed by a renaming. This is fortunate, because it allows us to avoid worrying about whether the implicit protected object parameter of a protected operation is involved in the conformance rules. @end{Ramification} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[Circular renames before freezing is illegal, as the compiler would not be able to determine the convention of the subprogram. Other circular renames are handled below; see @BoundedTitle.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[The @Syni{callable_entity_}@nt{name} of a renaming shall not denote a subprogram that requires overriding (see @RefSecNum{Abstract Types and Subprograms}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[Such a rename cannot be of the inherited subprogram (which requires overriding because it cannot be called), and thus cannot squirrel away a subprogram (see below). That would be confusing, so we make it illegal. The renaming is allowed after the overriding, as then the @nt{name} will denote the overriding subprogram, not the inherited one.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[The @Syni{callable_entity_}@nt{name} of a renaming-as-body shall not denote an abstract subprogram.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[Such a subprogram has no body, so it hardly can replace one in the program.]} @end{Reason} A @nt{name} that denotes a formal parameter of the @nt{subprogram_specification} is not allowed within the @Syni{callable_entity_}@nt{name}. @begin{Reason} @leading@keepnext@;This is to prevent things like this: @begin{Example} @key[function] F(X : Integer) @key[return] Integer @key[renames] Table(X).@key[all]; @end{Example} @begin{WideAbove} @leading@;A similar rule in @RefSecNum{Subprogram Declarations} forbids things like this: @end{WideAbove} @begin{Example} @key[function] F(X : Integer; Y : Integer := X) @key[return] Integer; @end{Example} @end{Reason} @end{Legality} @begin{StaticSem} A renaming-as-declaration declares a new view of the renamed entity. The profile of this new view takes its subtypes, parameter modes, and calling convention from the original profile of the callable entity, while taking the formal parameter @nt{name}s and @nt{default_expression}s from the profile given in the @nt{subprogram_renaming_declaration}. The new view is a function or procedure, never an entry. @begin{Honest} When renaming an entry as a procedure, the compile-time rules apply as if the new view is a procedure, but the run-time semantics of a call are that of an entry call. @end{Honest} @begin{Ramification} For example, it is illegal for the @nt{entry_call_statement} of a @nt{timed_entry_call} to call the new view. But what looks like a procedure call will do things like barrier waiting. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0105],ARef=[AI95-00211-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00228-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0095-1]} @Chg{New=[All properties of the renamed entity are inherited by the new view unless otherwise stated by this International Standard. In particular, if the renamed entity is abstract@Chg{Version=[2],New=[],Old=[ or requires overriding (see @RefSecNum{Abstract Types and Subprograms})]}, the new view also is abstract@Chg{Version=[2],New=[.],Old=[ or requires overriding. (The renaming will often be illegal in these cases, as a renaming cannot be overridden.)]}],Old=[]} @ChgAdded{Version=[3],Text=[Similarly, if the renamed entity is not a program unit, then neither is the renaming. (Implicitly declared subprograms are not program units, see @RefSecNum{Separate Compilation}).]} @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0014],ARef=[AI95-00064-01]} @Chg{New=[For a call to a subprogram whose body is given as a renaming-as-body, the execution of the renaming-as-body is equivalent to the execution of a @nt{subprogram_body} that simply calls the renamed subprogram with its formal parameters as the actual parameters and, if it is a function, returns the value of the call.],Old=[]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[This implies that the subprogram completed by the renaming-as-body has its own elaboration check.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} For a call on a renaming of a dispatching subprogram that is overridden, if the overriding occurred before the renaming, then the body executed is that of the overriding declaration, even if the overriding declaration is not visible at the place of the renaming; otherwise, the inherited or predefined subprogram is called.@Chg{Version=[3],New=[ A corresponding rule applies to a call on a renaming of a predefined equality operator for an untagged record type.],Old=[]} @begin{Discussion} Note that whether or not the renaming is itself primitive has nothing to do with the renamed subprogram. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0123-1]} Note that the above rule is only for tagged types@Chg{Version=[3],New=[ and equality of untagged record types],Old=[]}. @leading@keepnext@;Consider the following example: @begin{Example} @key[package] P @key[is] @key[type] T @key[is] @key[tagged] @key[null] @key[record]; @key[function] Predefined_Equal(X, Y : T) @key[return] Boolean @key[renames] "="; @key[private] @key[function] "="(X, Y : T) @key[return] Boolean; --@RI{ Override predefined "=".} @key[end] P; @key[with] P; @key[use] P; @key[package] Q @key[is] @key[function] User_Defined_Equal(X, Y : T) @key[return] Boolean @key[renames] P."="; @key[end] Q; @end{Example} A call on Predefined_Equal will execute the predefined equality operator of T, whereas a call on User_Defined_Equal will execute the body of the overriding declaration in the private part of P. Thus a renaming allows one to squirrel away a copy of an inherited or predefined subprogram before later overriding it.@Defn{squirrel away} @end{Discussion} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If a subprogram directly or indirectly renames itself, then it is a bounded error to call that subprogram. Possible consequences are that Program_Error or Storage_Error is raised, or that the call results in infinite recursion.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[1],Text=[This has to be a bounded error, as it is possible for a renaming-as-body appearing in a package body to cause this problem. Thus it is not possible in general to detect this problem at compile time.]} @end{Reason} @end{Bounded} @begin{Notes} A procedure can only be renamed as a procedure. A function whose @nt{defining_designator} is either an @nt{identifier} or an @nt{operator_symbol} can be renamed with either an @nt{identifier} or an @nt{operator_symbol}; for renaming as an operator, the subprogram specification given in the @nt{renaming_declaration} is subject to the rules given in @RefSecNum{Overloading of Operators} for operator declarations. Enumeration literals can be renamed as functions; similarly, @nt{attribute_reference}s that denote functions (such as references to Succ and Pred) can be renamed as functions. An entry can only be renamed as a procedure; the new @nt{name} is only allowed to appear in contexts that allow a procedure @nt{name}. An entry of a family can be renamed, but an entry family cannot be renamed as a whole. The operators of the root numeric types cannot be renamed because the types in the profile are anonymous, so the corresponding specifications cannot be written; the same holds for certain attributes, such as Pos. Calls with the new @nt{name} of a renamed entry are @nt{procedure_call_statement}s and are not allowed at places where the syntax requires an @nt{entry_call_statement} in @ntf{conditional_} and @nt{timed_entry_call}s, nor in an @nt{asynchronous_select}; similarly, the Count attribute is not available for the new @nt{name}. The primitiveness of a renaming-as-declaration is determined by its profile, and by where it occurs, as for any declaration of (a view of) a subprogram; primitiveness is not determined by the renamed view. In order to perform a dispatching call, the subprogram name has to denote a primitive subprogram, not a nonprimitive renaming of a primitive subprogram. @begin{Reason} A @nt{subprogram_renaming_declaration} could more properly be called @ntf{renaming_@!as_@!subprogram_@!declaration}, since you're renaming something as a subprogram, but you're not necessarily renaming a subprogram. But that's too much of a mouthful. Or, alternatively, we could call it a @ntf{callable_@!entity_@!renaming_@!declaration}, but that's even worse. Not only is it a mouthful, it emphasizes the entity being renamed, rather than the new view, which we think is a bad idea. We'll live with the oddity. @end{Reason} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of subprogram renaming declarations:} @begin{Example} @key[procedure] My_Write(C : @key[in] Character) @key[renames] Pool(K).Write; --@RI{ see @RefSecNum{Selected Components}} @key[function] Real_Plus(Left, Right : Real ) @key[return] Real @key[renames] "+"; @key[function] Int_Plus (Left, Right : Integer) @key[return] Integer @key[renames] "+"; @key[function] Rouge @key[return] Color @key[renames] Red; --@RI{ see @RefSecNum{Enumeration Types}} @key[function] Rot @key[return] Color @key[renames] Red; @key[function] Rosso @key[return] Color @key[renames] Rouge; @key[function] Next(X : Color) @key[return] Color @key[renames] Color'Succ; --@RI{ see @RefSecNum{Enumeration Types}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a subprogram renaming declaration with new parameter names:} @end{WideAbove} @begin{Example} @key[function] "*" (X,Y : Vector) @key[return] Real @key[renames] Dot_Product; --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a subprogram renaming declaration with a new default expression:} @end{WideAbove} @begin{Example} @key[function] Minimum(L : Link := Head) @key[return] Cell @key[renames] Min_Cell; --@RI{ see @RefSecNum{Subprogram Declarations}} @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0028],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b<Corrigendum:> Allowed a renaming-as-body to be just mode conformant with the specification if the subprogram is not yet frozen.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@nt{Overriding_indicator} (see @RefSecNum{Overriding Indicators}) is optionally added to subprogram renamings.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0014],ARef=[AI95-00064-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Described the semantics of renaming-as-body, so that the location of elaboration checks is clear.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0027],ARef=[AI95-00135-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that circular renaming-as-body is illegal (if it can be detected in time) or a bounded error.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00228-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Clarified that renaming a shall-be-overridden subprogram is illegal, as well as renaming-as-body an abstract subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[Added matching rules for @nt{null_exclusion}s.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0123-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} Renaming of user-defined untagged record equality is now defined to call the overridden body so long as the overriding occurred before the renames. This could change the body called in unusual cases; the change is necessary to preserve the principle that the body called for an explicit call to "=" (via a renames in this case) is the same as the one inherited for a derived type and used in generics. Note that any renamings before the overriding will be unchanged. Any differences caused by the change will be rare and most likely will fix a bug.]} @end{Inconsistent2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{subprogram_renaming_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledSubClause{Generic Renaming Declarations} @begin{Intro} @redundant[A @nt{generic_renaming_declaration} is used to rename a generic unit.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{tabs=[P22], lhs=<generic_renaming_declaration>,rhs=" @key{generic package}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_package_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @key{generic procedure}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_procedure_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @key{generic function}@\@Syn2{defining_program_unit_name} @key{renames} @SynI{generic_function_}@Syn2{name}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{Legality} The renamed entity shall be a generic unit of the corresponding kind. @end{Legality} @begin{StaticSem} A @nt{generic_renaming_declaration} declares a new view @Redundant{of the renamed generic unit}. @end{StaticSem} @begin{Notes} Although the properties of the new view are the same as those of the renamed view, the place where the @nt<generic_renaming_declaration> occurs may affect the legality of subsequent renamings and instantiations that denote the @nt<generic_renaming_declaration>, in particular if the renamed generic unit is a library unit (see @RefSecNum{Compilation Units - Library Units}). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of renaming a generic unit:} @begin{Example} @key[generic package] Enum_IO @key[renames] Ada.Text_IO.Enumeration_IO; @RI{-- see @RefSecNum{Input-Output for Enumeration Types}} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Renaming of generic units is new to Ada 95. It is particularly important for renaming child library units that are generic units. For example, it might be used to rename Numerics.Generic_Elementary_Functions as simply Generic_Elementary_Functions, to match the name for the corresponding Ada-83-based package. @end{Extend83} @begin{DiffWord83} The information in RM83-8.6, @lquotes@;The Package Standard,@rquotes@; has been updated for the child unit feature, and moved to @RefSecNum{Predefined Language Environment}, except for the definition of @lquotes@;predefined type,@rquotes@; which has been moved to @RefSecNum{Type Declarations}. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{generic_renaming_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledClause{The Context of Overload Resolution} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[@Defn{overload resolution} Because declarations can be overloaded, it is possible for an occurrence of a usage name to have more than one possible interpretation; in most cases, ambiguity is disallowed. This @Chg{Version=[3],New=[subclause],Old=[clause]} describes how the possible interpretations resolve to the actual interpretation. @Defn{overloading rules} Certain rules of the language (the @ResolutionTitle) are considered @lquotes@;overloading rules@rquotes@;. If a possible interpretation violates an overloading rule, it is assumed not to be the intended interpretation; some other possible interpretation is assumed to be the actual interpretation. On the other hand, violations of nonoverloading rules do not affect which interpretation is chosen; instead, they cause the construct to be illegal. To be legal, there usually has to be exactly one acceptable interpretation of a construct that is a @lquotes@;complete context@rquotes@;, not counting any nested complete contexts. @Defn2{Term=[grammar],Sec=(resolution of ambiguity)} The syntax rules of the language and the visibility rules given in @RefSecNum{Visibility} determine the possible interpretations. Most type checking rules (rules that require a particular type, or a particular class of types, for example) are overloading rules. Various rules for the matching of formal and actual parameters are overloading rules.] @end{Intro} @begin{MetaRules} The type resolution rules are intended to minimize the need for implicit declarations and preference rules associated with implicit conversion and dispatching operations. @end{MetaRules} @begin{Resolution} @leading@Defn{complete context} @Redundant{Overload resolution is applied separately to each @i{complete context}, not counting inner complete contexts.} Each of the following constructs is a @i{complete context}: @begin{itemize} A @nt{context_item}. A @nt{declarative_item} or declaration. @begin{Ramification} A @nt{loop_parameter_specification} is a declaration, and hence a complete context. @end{Ramification} A @nt{statement}. A @nt{pragma_argument_association}. @begin{Reason} We would make it the whole @nt{pragma}, except that certain pragma arguments are allowed to be ambiguous, and ambiguity applies to a complete context. @end{Reason} The @nt{expression} of a @nt{case_statement}. @begin{Ramification} This means that the @nt{expression} is resolved without looking at the choices. @end{Ramification} @end{itemize} @leading@Defn2{Term=[interpretation], Sec=(of a complete context)} @Defn2{Term=[overall interpretation], Sec=(of a complete context)} An (overall) @i{interpretation} of a complete context embodies its meaning, and includes the following information about the constituents of the complete context, not including constituents of inner complete contexts: @begin{Itemize} for each constituent of the complete context, to which syntactic categories it belongs, and by which syntax rules; and @begin{Ramification} Syntactic categor@i{ies} is plural here, because there are lots of trivial productions @em an @nt{expression} might also be all of the following, in this order: @nt{identifier}, @nt{name}, @nt{primary}, @nt{factor}, @nt{term}, @nt{simple_expression}, and @nt{relation}. Basically, we're trying to capture all the information in the parse tree here, without using compiler-writer's jargon like @lquotes@;parse tree@rquotes@;. @end{Ramification} for each usage name, which declaration it denotes (and, therefore, which view and which entity it denotes); and @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} In most cases, a usage name denotes the view declared by the denoted declaration. However, in certain cases, a usage name that denotes a declaration and appears inside the declarative region of that same declaration, denotes the current instance of the declaration. For example, within a @nt{task_body}@Chg{Version=[2],New=[ other than in an @nt{access_definition}],Old=[]}, a usage name that denotes the @nt{task_type_declaration} denotes the object containing the currently executing task, and not the task type declared by the declaration. @end{Ramification} for a complete context that is a @nt{declarative_item}, whether or not it is a completion of a declaration, and (if so) which declaration it completes. @end{Itemize} @begin{Ramification} Unfortunately, we are not confident that the above list is complete. We'll have to live with that. @end{Ramification} @begin{Honest} For @lquotes@;possible@rquotes@; interpretations, the above information is tentative. @end{Honest} @begin{Discussion} A possible interpretation (an @i{input} to overload resolution) contains information about what a usage name @i{might} denote, but what it actually @i{does} denote requires overload resolution to determine. Hence the term @lquotes@;tentative@rquotes@; is needed for possible interpretations; otherwise, the definition would be circular. @end{Discussion} @Defn{possible interpretation} A @i{possible interpretation} is one that obeys the syntax rules and the visibility rules. @Defn{acceptable interpretation} @Defn2{Term=[resolve],Sec=(overload resolution)} @Defn2{Term=[interpretation],Sec=(overload resolution)} An @i{acceptable interpretation} is a possible interpretation that obeys the @i{overloading rules}@Redundant{, that is, those rules that specify an expected type or expected profile, or specify how a construct shall @i(resolve) or be @i(interpreted).} @begin{Honest} One rule that falls into this category, but does not use the above-mentioned magic words, is the rule about numbers of parameter associations in a call (see @RefSecNum{Subprogram Calls}). @end{Honest} @begin{Ramification} The @ResolutionName@;s are the ones that appear under the @ResolutionTitle heading. Some @SyntaxName@;s are written in English, instead of BNF. No rule is a @SyntaxName or @ResolutionName unless it appears under the appropriate heading. @end{Ramification} @Defn2{Term=[interpretation], Sec=(of a constituent of a complete context)} The @i{interpretation} of a constituent of a complete context is determined from the overall interpretation of the complete context as a whole. @Redundant{Thus, for example, @lquotes@;interpreted as a @nt{function_call},@rquotes@; means that the construct's interpretation says that it belongs to the syntactic category @nt{function_call}.} @leading@Defn{denote} @Redundant[Each occurrence of] a usage name @i{denotes} the declaration determined by its interpretation. It also denotes the view declared by its denoted declaration, except in the following cases: @begin{Ramification} As explained below, a pragma argument is allowed to be ambiguous, so it can denote several declarations, and all of the views declared by those declarations. @end{Ramification} @begin(itemize) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0287-1]} @Defn2{Term=[current instance], Sec=(of a type)} If a usage name appears within the declarative region of a @nt{type_declaration} and denotes that same @nt{type_declaration}, then it denotes the @i{current instance} of the type (rather than the type itself)@Chg{Version=[2],New=[; the],Old=[. The]} current instance of a type is the object or value of the type that is associated with the execution that evaluates the usage name.@Chg{Version=[2],New=[ @Chg{Version=[3], New=[ Similarly, if a usage name appears within the declarative region of a @nt{subtype_declaration} and denotes that same @nt{subtype_declaration}, then it denotes the current instance of the subtype. These rules do], Old=[This rule does]} not apply if the usage name appears within the @nt{subtype_mark} of an @nt{access_definition} for an access-to-object type, or within the subtype of a parameter or result of an access-to-subprogram type.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} This is needed, for example, for references to the Access attribute from within the @nt{type_declaration}. Also, within a @nt{task_body} or @nt{protected_body}, we need to be able to denote the current task or protected object. (For a @nt{single_task_declaration} or @nt{single_protected_declaration}, the rule about current instances is not needed.)@Chg{Version=[2],New=[ We exclude anonymous access types so that they can be used to create self-referencing types in the natural manner (otherwise such types would be illegal).],Old=[]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[The phrase @lquotes@;within the @nt{subtype_mark}@rquotes@; in the @lquotes@;this rule does not apply@rquotes@; part is intended to cover a case like @key{access} T'Class appearing within the declarative region of T: here T denotes the type, not the current instance.]} @end{Discussion} @Defn2{Term=[current instance], Sec=(of a generic unit)} If a usage name appears within the declarative region of a @nt{generic_declaration} (but not within its @nt{generic_formal_part}) and it denotes that same @nt{generic_declaration}, then it denotes the @i{current instance} of the generic unit (rather than the generic unit itself). See also @RefSecNum{Generic Instantiation}. @begin{Honest} The current instance of a generic unit is the instance created by whichever @nt{generic_instantiation} is of interest at any given time. @end{Honest} @begin{Ramification} Within a @nt{generic_formal_part}, a @nt{name} that denotes the @nt{generic_declaration} denotes the generic unit, which implies that it is not overloadable. @end{Ramification} @end(itemize) A usage name that denotes a view also denotes the entity of that view. @begin{Ramification} Usually, a usage name denotes only one declaration, and therefore one view and one entity. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @leading@RootDefn[expected type] The @i(expected type) for a given @nt<expression>, @nt<name>, or other construct determines, according to the @i{type resolution rules} given below, the types considered for the construct during overload resolution. @Defn{type resolution rules} @Redundant[ The type resolution rules provide support for class-wide programming, universal @Chg{Version=[2],New=[],Old=[numeric ]}literals, dispatching operations, and anonymous access types:] @begin{Ramification} Expected types are defined throughout the RM95. The most important definition is that, for a subprogram, the expected type for the actual parameter is the type of the formal parameter. The type resolution rules are trivial unless either the actual or expected type is universal, class-wide, or of an anonymous access type. @end{Ramification} @begin{Itemize} @PDefn2{Term=[type resolution rules], Sec=(if any type in a specified class of types is expected)} @PDefn2{Term=[type resolution rules], Sec=(if expected type is universal or class-wide)} If a construct is expected to be of any type in a class of types, or of the universal or class-wide type for a class, then the type of the construct shall resolve to a type in that class or to a universal type that covers the class. @begin{Ramification} This matching rule handles (among other things) cases like the Val attribute, which denotes a function that takes a parameter of type @i(universal_integer). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00021 - Quoted text doesn't match} The last part of the rule, @lquotes@;or to a universal type that @Chg{New=[covers],Old=[includes]} the class@rquotes implies that if the expected type for an expression is @i{universal_fixed}, then an expression whose type is @i{universal_real} (such as a real literal) is OK. @end{Ramification} @leading@PDefn2{Term=[type resolution rules], Sec=(if expected type is specific)} If the expected type for a construct is a specific type @i(T), then the type of the construct shall resolve either to @i(T), or: @begin{Ramification} @PDefn{Beaujolais effect} This rule is @i{not} intended to create a preference for the specific type @em such a preference would cause Beaujolais effects. @end{Ramification} @begin(Inneritemize) to @i(T)'Class; or @begin{Ramification} This will only be legal as part of a call on a dispatching operation; see @RefSec(Dispatching Operations of Tagged Types). Note that that rule is not a @ResolutionName. @end{Ramification} to a universal type that covers @i(T); or @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} when @i(T) is @Chg{Version=[2],New=[a specific],Old=[an]} anonymous access@Chg{Version=[2],New=[-to-object],Old=[]} type (see @RefSecNum{Access Types}) with designated type @i(D), to an access-to-@Chg{Version=[2],New=[object],Old=[variable]} type whose designated type is @i(D)'Class or is covered by @i(D)@Chg{Version=[2],New=[; or],Old=[.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00409-01]} @ChgNote{We use Chg here, rather than ChgDeleted so that the prefix is left behind.}@Chg{Version=[2],New=[],Old=[Because it says @lquotes@;access-to-variable@rquotes@; instead of @lquotes@;access-to-object,@rquotes@; two subprograms that differ only in that one has a parameter of an access-to-constant type, and the other has an access parameter, are distinguishable during overload resolution.]} The case where the actual is access-to-@i(D)'Class will only be legal as part of a call on a dispatching operation; see @RefSec(Dispatching Operations of Tagged Types). Note that that rule is not a @ResolutionName. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[when @i(T) is a named general access-to-object type (see @RefSecNum{Access Types}) with designated type @i(D), to an anonymous access-to-object type whose designated type covers or is covered by @i(D); or]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00254-01],ARef=[AI95-00409-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0239-1]} @ChgAdded{Version=[2],Text=[when @i(T) is an anonymous access-to-subprogram type (see @RefSecNum{Access Types}), to an access-to-subprogram type whose designated profile is @Chg{Version=[3],New=[type conformant],Old=[type-conformant]} with that of @i{T}.]} @end(Inneritemize) @end{Itemize} @RootDefn[expected profile] In certain contexts, @Redundant[such as in a @nt{subprogram_renaming_declaration},] the @ResolutionTitle define an @i(expected profile) for a given @nt<name>; @Defn2{Term=[profile resolution rule], Sec=(@nt<name> with a given expected profile)} in such cases, the @nt{name} shall resolve to the name of a callable entity whose profile is type conformant with the expected profile. @Defn2{Term=[type conformance],Sec=(required)} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The parameter and result @i{sub}types are not used in overload resolution. Only type conformance of profiles is considered during overload resolution. Legality rules generally require at least @Chg{Version=[3],New=[mode conformance],Old=[mode-conformance]} in addition, but those rules are not used in overload resolution. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00332-01]} @Defn2{Term=[single], Sec=[class expected type]} When @Chg{Version=[2],New=[],Old=[the expected type for ]}a construct is @Chg{Version=[2],New=[one that requires that its expected type], Old=[required to]} be a @i<single> type in a given class, the type @Chg{Version=[2],New=[of],Old=[expected for]} the construct shall be determinable solely from the context in which the construct appears, excluding the construct itself, but using the requirement that it be in the given class@Chg{Version=[2], New=[],Old=[; the type of the construct is then this single expected type]}. Furthermore, the context shall not be one that expects any type in some class that contains types of the given class; in particular, the construct shall not be the operand of a @nt{type_conversion}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]}@ChgNote{Null no longer requires a single type} For example, the expected type for @Chg{Version=[2],New=[a string literal], Old=[the literal @key{null}]} is required to be a single @Chg{Version=[2],New=[string],Old=[access]} type. But the expected type for the operand of a @nt{type_conversion} is any type. Therefore, @Chg{Version=[2],New=[a string literal], Old=[the literal @key{null}]} is not allowed as the operand of a @nt{type_conversion}. This is true even if there is only one @Chg{Version=[2],New=[string], Old=[access]} type in scope@Chg{Version=[2],New=[ (which is never the case)],Old=[]}. The reason for these rules is so that the compiler will not have to search @lquotes@;everywhere@rquotes@; to see if there is exactly one type in a class in scope. @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00332-01]} @ChgAdded{Version=[2],Text=[The first sentence is carefully worded so that it only mentions @lquotes@;expected type@rquotes as part of identifying the interesting case, but doesn't require that the context actually provide such an expected type. This allows such constructs to be used inside of constructs that don't provide an expected type (like qualified expressions and renames). Otherwise, such constructs wouldn't allow @nt{aggregate}s, 'Access, and so on.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0102-1],ARef=[AI05-0149-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Other than for the @nt{simple_expression} of a membership test, if the expected type for a @nt{name} or @nt{expression} is not the same as the actual type of the @nt{name} or @nt{expression}, the actual type shall be convertible to the expected type (see @RefSecNum{Type Conversions});@Defn2{Term=[implicit conversion], Sec=[legality]}@PDefn2{Term=[convertible],Sec=(required)} further, if the expected type is a named access-to-object type with designated type @i<D1> and the actual type is an anonymous access-to-object type with designated type @i<D2>, then @i<D1> shall cover @i<D2>, and the @nt{name} or @nt{expression} shall denote a view with an accessibility level for which the statically deeper relationship applies@Redundant[; in particular it shall not denote an access parameter nor a stand-alone access object].]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule prevents an implicit conversion that would be illegal if it was an explicit conversion. For instance, this prevents assigning an access-to-constant value into a stand-alone anonymous access-to-variable object. It also covers convertibility of the designated type and accessibility checks.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The rule also minimizes cases of implicit conversions when the tag check or the accessibility check might fail. We word it this way because access discriminants should also be disallowed if their enclosing object is designated by an access parameter.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule does not apply to expressions that don't have expected types (such as the operand of a qualified expression or the expression of a renames). We don't need a rule like this in those cases, as the type needs to be the same; there is no implicit conversion.]} @end{Ramification} A complete context shall have at least one acceptable interpretation; if there is exactly one, then that one is chosen. @begin{Ramification} This, and the rule below about ambiguity, are the ones that suck in all the @SyntaxName@;s and @ResolutionName@;s as compile-time rules. Note that this and the ambiguity rule have to be @LegalityName@;s. @end{Ramification} @Defn2{Term=[preference], Sec=(for root numeric operators and @nt<range>s)} There is a @i{preference} for the primitive operators (and @nt<range>s) of the root numeric types @i{root_integer} and @i{root_real}. In particular, if two acceptable interpretations of a constituent of a complete context differ only in that one is for a primitive operator (or @nt<range>) of the type @i{root_integer} or @i{root_real}, and the other is not, the interpretation using the primitive operator (or @nt<range>) of the root numeric type is @i{preferred}. @begin{Reason} @leading@;The reason for this preference is so that expressions involving literals and named numbers can be unambiguous. For example, without the preference rule, the following would be ambiguous: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00022} N : @key[constant] := 123; @key[if] N > 100 @key[then] --@RI{ Preference for root_integer "@Chg{New=[>],Old=[<]}" operator.} ... @key[end] @key[if]; @end{Example} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[Similarly, there is a preference for the equality operators of the @i{universal_access} type (see @RefSecNum{Relational Operators and Membership Tests}). If two acceptable interpretations of a constituent of a complete context differ only in that one is for an equality operator of the @i{universal_access} type, and the other is not, the interpretation using the equality operator of the @i{universal_access} type is preferred.@Defn2{Term=[preference], Sec=(for universal access equality operators)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This preference is necessary because of implicit conversion from an anonymous access type to a named access type, which would allow the equality operator of any named access type to be used to compare anonymous access values (and that way lies madness).]} @end{Reason} For a complete context, if there is exactly one overall acceptable interpretation where each constituent's interpretation is the same as or preferred (in the above sense) over those in all other overall acceptable interpretations, then that one overall acceptable interpretation is chosen. @Defn{ambiguous} Otherwise, the complete context is @i{ambiguous}. A complete context other than a @nt{pragma_argument_association} shall not be ambiguous. A complete context that is a @nt{pragma_argument_association} is allowed to be ambiguous (unless otherwise specified for the particular pragma), but only if every acceptable interpretation of the pragma argument is as a @nt{name} that statically denotes a callable entity. @PDefn2{Term=[denote],Sec=(name used as a pragma argument)} Such a @nt{name} denotes all of the declarations determined by its interpretations, and all of the views declared by these declarations. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]}@ChgNote{Pragma is obsolete} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} This applies to Inline, Suppress, Import, Export, and Convention @nt{pragma}s. For example, it is OK to say @lquotes@;@key[pragma] @Chg{Version=[2], New=[Export(C, Entity_Name],Old=[Suppress(Elaboration_Check, On]} => P.Q);@rquotes@;, even if there are two directly visible P's, and there are two Q's declared in the visible part of each P. In this case, P.Q denotes four different declarations. This rule also applies to certain pragmas defined in the Specialized Needs Annexes. It almost applies to Pure, Elaborate_Body, and Elaborate_All @nt{pragma}s, but those can't have overloading for other reasons. @Chg{Version=[3],New=[ Note that almost all of these pragmas are obsolescent (see @RefSecNum{Specific Suppression of Checks} and @RefSecNum{Aspect-related Pragmas}), and a major reason is that this rule has proven to be too broad in practice (it is common to want to specify something on a single subprogram of an overloaded set, that can't be done easily with this rule). @nt{Aspect_specification}s, which are given on individual declarations, are preferred in Ada 2012.],Old=[]} Note that if a pragma argument denotes a @i{call} to a callable entity, rather than the entity itself, this exception does not apply, and ambiguity is disallowed. Note that we need to carefully define which pragma-related rules are @ResolutionName@;s, so that, for example, a @nt{pragma} Inline does not pick up subprograms declared in enclosing declarative regions, and therefore make itself illegal. We say @lquotes@;statically denotes@rquotes@; in the above rule in order to avoid having to worry about how many times the @nt{name} is evaluated, in case it denotes more than one callable entity. @end{Ramification} @end{Legality} @begin{Notes} If a usage name has only one acceptable interpretation, then it denotes the corresponding entity. However, this does not mean that the usage name is necessarily legal since other requirements exist which are not considered for overload resolution; for example, the fact that an expression is static, whether an object is constant, mode and subtype conformance rules, freezing rules, order of elaboration, and so on. @NoPrefix@;Similarly, subtypes are not considered for overload resolution (the violation of a constraint does not make a program illegal but raises an exception during program execution). @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} @PDefn{Beaujolais effect} The new preference rule for operators of root numeric types is upward incompatible, but only in cases that involved @i(Beaujolais) effects in Ada 83. Such cases are ambiguous in Ada 95. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The rule that allows an expected type to match an actual expression of a universal type, in combination with the new preference rule for operators of root numeric types, subsumes the Ada 83 "implicit conversion" rules for universal types. @end{Extend83} @begin{DiffWord83} In Ada 83, it is not clear what the @lquotes@;syntax rules@rquotes@; are. AI83-00157 states that a certain textual rule is a syntax rule, but it's still not clear how one tells in general which textual rules are syntax rules. We have solved the problem by stating exactly which rules are syntax rules @em the ones that appear under the @lquotes@;@SyntaxTitle@rquotes@; heading. RM83 has a long list of the @lquotes@;forms@rquotes@; of rules that are to be used in overload resolution (in addition to the syntax rules). It is not clear exactly which rules fall under each form. We have solved the problem by explicitly marking all rules that are used in overload resolution. Thus, the list of kinds of rules is unnecessary. It is replaced with some introductory (intentionally vague) text explaining the basic idea of what sorts of rules are overloading rules. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} It is not clear from RM83 what information is embodied in a @lquotes@;meaning@rquotes@; or an @lquotes@;interpretation.@rquotes@; @lquotes@;Meaning@rquotes@; and @lquotes@;interpretation@rquotes@; were intended to be synonymous; we now use the latter only in defining the rules about overload resolution. @lquotes@;Meaning@rquotes@; is used only informally. This @Chg{Version=[3],New=[subclause],Old=[clause]} attempts to clarify what is meant by @lquotes@;interpretation.@rquotes@; @NoPrefix@;For example, RM83 does not make it clear that overload resolution is required in order to match @ntf{subprogram_bodies} with their corresponding declarations (and even to tell whether a given @nt{subprogram_body} is the completion of a previous declaration). Clearly, the information needed to do this is part of the @lquotes@;interpretation@rquotes@; of a @nt{subprogram_body}. The resolution of such things is defined in terms of the @lquotes@;expected profile@rquotes@; concept. Ada 95 has some new cases where expected profiles are needed @em the resolution of P'Access, where P might denote a subprogram, is an example. @Leading@NoPrefix@;RM83-8.7(2) might seem to imply that an interpretation embodies information about what is denoted by each usage name, but not information about which syntactic category each construct belongs to. However, it seems necessary to include such information, since the Ada grammar is highly ambiguous. For example, X(Y) might be a @nt{function_call} or an @nt{indexed_component}, and no context-free/syntactic information can tell the difference. It seems like we should view X(Y) as being, for example, @lquotes@;interpreted as a @nt{function_call}@rquotes@; (if that's what overload resolution decides it is). Note that there are examples where the denotation of each usage name does not imply the syntactic category. However, even if that were not true, it seems that intuitively, the interpretation includes that information. Here's an example: @begin{Example} @key[type] T; @key[type] A @key[is] @key[access] T; @key[type] T @key[is] @key[array](Integer @key[range] 1..10) @key[of] A; I : Integer := 3; @key[function] F(X : Integer := 7) @key[return] A; Y : A := F(I); --@RI{ Ambiguous? (We hope so.)} @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @NoPrefix@;Consider the declaration of Y (a complete context). In the above example, overload resolution can easily determine the declaration, and therefore the entity, denoted by Y, A, F, and I. However, given all of that information, we still don't know whether F(I) is a @nt{function_call} or an @nt{indexed_component} whose @Chg{New=[@nt{prefix}],Old=[prefix]} is a @nt{function_call}. (In the latter case, it is equivalent to F(7).@key[all](I).) @NoPrefix@;It seems clear that the declaration of Y ought to be considered ambiguous. We describe that by saying that there are two interpretations, one as a @nt{function_call}, and one as an @nt{indexed_component}. These interpretations are both acceptable to the overloading rules. Therefore, the complete context is ambiguous, and therefore illegal. @PDefn{Beaujolais effect} It is the intent that the Ada 95 preference rule for root numeric operators is more locally enforceable than that of RM83-4.6(15). It should also eliminate interpretation shifts due to the addition or removal of a @nt{use_clause} (the so called @i{Beaujolais} effect). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} RM83-8.7 seems to be missing some complete contexts, such as @nt{pragma_argument_association}s, @nt{declarative_item}s that are not declarations or @Chg{Version=[2],New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]}, and @nt{context_item}s. We have added these, and also replaced the @lquotes@;must be determinable@rquotes@; wording of RM83-5.4(3) with the notion that the expression of a @nt{case_statement} is a complete context. Cases like the Val attribute are now handled using the normal type resolution rules, instead of having special cases that explicitly allow things like @lquotes@;any integer type.@rquotes@; @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00409-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{incompatibilities with Ada 95} Ada 95 allowed name resolution to distinguish between anonymous access-to-variable and access-to-constant types. This is similar to distinguishing between subprograms with @key{in} and @key{in out} parameters, which is known to be bad. Thus, that part of the rule was dropped as we now have anonymous access-to-constant types, making this much more likely.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Cacc @key{is access constant} Integer; @key{procedure} Proc (Acc : @key{access} Integer) ... @key{procedure} Proc (Acc : Cacc) ... List : Cacc := ...; Proc (List); -- @RI[OK in Ada 95, ambiguous in Ada 2005.]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If there is any code like this (such code should be rare), it will be ambiguous in Ada 2005.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00231-01],ARef=[AI95-00254-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Generalized the anonymous access resolution rules to support the new capabilities of anonymous access types (that is, access-to-subprogram and access-to-constant).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[We now allow the creation of self-referencing types via anonymous access types. This is an extension in unusual cases involving task and protected types. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{task type} T;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{task body} T @key{is} @key{procedure} P (X : @key{access} T) @key{is} -- @RI[Illegal in Ada 95, legal in Ada 2005] ... @key{end} P; @key{begin} ... @key{end} T;]} @end{Example} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00332-01]} @ChgAdded{Version=[2],Text=[Corrected the @lquotes@;single expected type@rquotes@; so that it works in contexts that don't have expected types (like object renames and qualified expressions). This fixes a hole in Ada 95 that appears to prohibit using @nt{aggregate}s, 'Access, character literals, string literals, and @nt{allocator}s in qualified expressions.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Implicit conversion is now allowed from anonymous access-to-object types to general access-to-object types. Such conversions can make calls ambiguous. That can only happen when there are two visible subprograms with the same name and have profiles that differ only by a parameter that is of a named or anonymous access type, and the actual argument is of an anonymous access type. This should be rare, as many possible calls would be ambiguous even in Ada 2005 (including @nt{allocator}s and any actual of a named access type if the designated types are the same).]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0149-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Implicit conversion is allowed from anonymous access-to-object types to general access-to-object types if the designated type is convertible and runtime checks are minimized. See also the incompatibilities section.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0102-1]} @ChgAdded{Version=[3],Text=[Added a requirement here that implicit conversions are convertible to the appropriate type. This rule was scattered about the Standard, we moved a single generalized version here.]} @end{DiffWord2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/09.mss���������������������������������������������������������������0000755�0001752�0001001�00000756613�12066652506�016423� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(09, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @LabeledSection{Tasks and Synchronization} @Comment{$Source: e:\\cvsroot/ARM/Source/09.mss,v $} @Comment{$Revision: 1.118 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @PDefn2{Term=[execution], Sec=(Ada program)} The execution of an Ada program consists of the execution of one or more @i(tasks). @Defn{task} @Defn2{Term=[interaction], Sec=(between tasks)} Each task represents a separate thread of control that proceeds independently and concurrently between the points where it @i(interacts) with other tasks. The various forms of task interaction are described in this @Chg{Version=[3],New=[clause],Old=[section]}, and include: @IndexSee{Term=[parallel processing],See=(task)} @Defn{synchronization} @IndexSee{Term=[concurrent processing],See=(task)} @IndexSeeAlso{Term=[intertask communication],See=(task)} @begin(Honest) The execution of an Ada program consists of the execution of one or more partitions (see @RefSecNum(Program Execution)), each of which in turn consists of the execution of an environment task and zero or more subtasks. @end(Honest) @begin(itemize) the activation and termination of a task; @Defn{protected object} a call on a protected subprogram of a @i(protected object), providing exclusive read-write access, or concurrent read-only access to shared data; a call on an entry, either of another task, allowing for synchronous communication with that task, or of a protected object, allowing for asynchronous communication with one or more other tasks using that same protected object; a timed operation, including a simple delay statement, a timed entry call or accept, or a timed asynchronous select statement (see next item); an asynchronous transfer of control as part of an asynchronous select statement, where a task stops what it is doing and begins execution at a different point in response to the completion of an entry call or the expiration of a delay; an abort statement, allowing one task to cause the termination of another task. @end(itemize) In addition, tasks can communicate indirectly by reading and updating (unprotected) shared variables, presuming the access is properly synchronized through some other kind of task interaction. @end{Intro} @begin{StaticSem} @Defn{task unit} The properties of a task are defined by a corresponding task declaration and @nt<task_body>, which together define a program unit called a @i(task unit). @end{StaticSem} @begin{RunTime} Over time, tasks proceed through various @i(states). @PDefn2{Term=[task state], Sec=(inactive)} @Defn2{Term=[inactive], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(blocked)} @Defn2{Term=[blocked], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(ready)} @Defn2{Term=[ready], Sec=(a task state)} @PDefn2{Term=[task state], Sec=(terminated)} @Defn2{Term=[terminated], Sec=(a task state)} A task is initially @i(inactive); upon activation, and prior to its @i{termination} it is either @i(blocked) (as part of some task interaction) or @i(ready) to run. @Defn2{Term=[execution resource], Sec=(required for a task to run)} While ready, a task competes for the available @i(execution resources) that it requires to run. @begin(Discussion) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{task dispatching policy} @Defn{dispatching policy for tasks} The means for selecting which of the ready tasks to run, given the currently available execution resources, is determined by the @i(task dispatching policy) in effect, which is generally implementation defined, but may be controlled by @Chg{Version=[3],New=[aspects, ],Old=[]}pragmas@Chg{Version=[3],New=[, ],Old=[]} and operations defined in the Real-Time Annex (see @RefSecNum(Priority Scheduling) and @RefSecNum(Dynamic Priorities)). @end(Discussion) @end{RunTime} @begin{Notes} Concurrent task execution may be implemented on multicomputers, multiprocessors, or with interleaved execution on a single physical processor. On the other hand, whenever an implementation can determine that the required semantic effects can be achieved when parts of the execution of a given task are performed by different physical processors acting in parallel, it may choose to perform them in this way. @end{Notes} @begin{DiffWord83} The introduction has been rewritten. We use the term "concurrent" rather than "parallel" when talking about logically independent execution of threads of control. The term "parallel" is reserved for referring to the situation where multiple physical processors run simultaneously. @end{DiffWord83} @LabeledClause{Task Units and Task Objects} @begin{Intro} @Defn{task declaration} A task unit is declared by a @i(task declaration), which has a corresponding @nt<task_body>. A task declaration may be a @nt<task_type_declaration>, in which case it declares a named task type; alternatively, it may be a @nt<single_task_declaration>, in which case it defines an anonymous task type, as well as declaring a named task object of that type. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<task_type_declaration>,rhs=" @key{task} @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} [@key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{task_definition}];"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00399-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<single_task_declaration>,rhs=" @key{task} @Syn2{defining_identifier} @Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}[@key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{task_definition}];"} @Syn{lhs=<task_definition>,rhs=" {@Syn2{task_item}} [ @key{private} {@Syn2{task_item}}] @key{end} [@SynI{task_}@Syn2{identifier}]"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<task_item>,rhs="@Syn2{entry_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0267-1]} @Syn{lhs=<task_body>,rhs=" @key{task} @key{body} @Syn2{defining_identifier}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{task_}@Syn2{identifier}];"} @begin{SyntaxText} If a @SynI{task_}@nt{identifier} appears at the end of a @nt{task_definition} or @nt{task_body}, it shall repeat the @nt{defining_identifier}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00345-01]}@ChgNote{This was just moved below} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{task_declaration})} A task declaration requires a completion@redundant[, which shall be a @nt{task_body},] and every @nt{task_body} shall be the completion of some task declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @end{Legality} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 8 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{StaticSem} A @nt<task_definition> defines a task type and its first subtype. @PDefn2{Term=[visible part], Sec=(of a task unit)} The first list of @nt{task_item}s of a @nt{task_@!definition}, together with the @nt{known_@!discriminant_@!part}, if any, is called the visible part of the task unit. @Redundant[@PDefn2{Term=[private part], Sec=(of a task unit)} The optional list of @nt{task_item}s after the reserved word @key{private} is called the private part of the task unit.] @begin{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Private part is defined in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules}. @end{theproof} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0029],ARef=[AI95-00116-01]} @ChgAdded{Version=[1],Text=[For a task declaration without a @nt{task_definition}, a @nt{task_definition} without @nt{task_item}s is assumed.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0042-1]} @ChgAdded{Version=[2],Text=[For a task declaration with an @nt{interface_list}, the task type inherits user-defined primitive subprograms from each progenitor type (see @RefSecNum{Interface Types}), in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}). If the first parameter of a primitive inherited subprogram is of the task type or an access parameter designating the task type, and there is an @nt{entry_declaration} for a single entry with the same identifier within the task declaration, whose profile is type conformant with the prefixed view profile of the inherited subprogram, the inherited subprogram is said to be @i{implemented} by the conforming task entry@Chg{Version=[3], New=[ using an implicitly declared nonabstract subprogram which has the same profile as the inherited subprogram and which overrides it@PDefn2{Term=[override],Sec=[when implemented by]}], Old=[]}.@PDefn2{Term=[implemented], Sec=[by a task entry]}@Defn2{Term=[type conformance],Sec=(required)}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inherited subprograms can only come from an interface given as part of the task declaration.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0042-1]} @ChgAdded{Version=[3],Text=[The part about the implicitly declared subprogram is needed so that a subprogram implemented by an entry is considered to be overridden for the purpose of the other rules of the language. Without it, it would for instance be illegal for an abstract subprogram to be implemented by an entry, because the abstract subprogram would not be overridden. The @LegalityTitle below ensure that there is no conflict between the implicit overriding subprogram and a user-defined overriding subprogram.]} @end{Reason} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]}@ChgNote{This was just moved, not changed} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{task_declaration})} A task declaration requires a completion@redundant[, which shall be a @nt{task_body},] and every @nt{task_body} shall be the completion of some task declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[If],Old=[The completion can be a @nt{pragma} Import, if]} the implementation supports it@Chg{Version=[3],New=[, the task body can be imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no explicit @nt{task_body} is allowed],Old=[]}.]} @end(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Text=[@Redundant[Each @i{interface_}@nt{subtype_mark} of an @nt{interface_list} appearing within a task declaration shall denote a limited interface type that is not a protected interface.]]} @begin(TheProof) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@RefSecNum{Interface Types} requires that an @nt{interface_list} only name interface types, and limits the descendants of the various kinds of interface types. Only a limited, task, or synchronized interface can have a task type descendant. Nonlimited or protected interfaces are not allowed, as they offer operations that a task does not have.]} @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0090-1]} @ChgAdded{Version=[2],Text=[The prefixed view profile of an explicitly declared primitive subprogram of a tagged task type shall not be type conformant with any entry of the task type, if the @Chg{Version=[3],New=[ subprogram has the same defining name as the entry and the ],Old=[]}first parameter of the subprogram is of the task type or is an access parameter designating the task type.@Defn2{Term=[type conformance],Sec=(required)}]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the existence of two operations with the same name and profile which could be called with a prefixed view. If the operation was inherited, this would be illegal by the following rules; this rule puts inherited and noninherited routines on the same footing. Note that this only applies to tagged task types (that is, those with an interface in their declaration); we do that as there is no problem with prefixed view calls of primitive operations for @lquotes@;normal@rquotes task types, and having this rule apply to all tasks would be incompatible with Ada 95.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each primitive subprogram inherited by the type declared by a task declaration, at most one of the following shall apply:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is overridden with a primitive subprogram of the task type, in which case the overriding subprogram shall be subtype conformant with the inherited subprogram and not abstract; or@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is implemented by a single entry of the task type; in which case its prefixed view profile shall be subtype conformant with that of the task entry. @Defn2{Term=[subtype conformance],Sec=(required)}]} @begin(Ramification) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An entry may implement two subprograms from the ancestors, one whose first parameter is of type @i<T> and one whose first parameter is of type @key{access} @i{T}. That doesn't cause implementation problems because @lquotes@;implemented by@rquotes (unlike @lquotes@;overridden@rquote) probably entails the creation of wrappers.]} @end(Ramification) @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If neither applies, the inherited subprogram shall be a null procedure. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each inherited subprogram can only have a single implementation (either from overriding a subprogram or implementing an entry), and must have an implementation unless the subprogram is a null procedure.]} @end{Reason} @end{Legality} @begin{RunTime} @redundant[@PDefn2{Term=[elaboration], Sec=(task declaration)} The elaboration of a task declaration elaborates the @nt<task_definition>. @PDefn2{Term=[elaboration], Sec=(single_task_declaration)} The elaboration of a @nt<single_@!task_@!declaration> also creates an object of an (anonymous) task type.] @begin(TheProof) This is redundant with the general rules for the elaboration of a @nt<full_type_declaration> and an @nt<object_declaration>. @end(TheProof) @PDefn2{Term=[elaboration], Sec=(task_definition)} @Redundant[The elaboration of a @nt<task_definition> creates the task type and its first subtype;] it also includes the elaboration of the @nt<entry_declaration>s in the given order. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @PDefn2{Term=[initialization], Sec=(of a task object)} As part of the initialization of a task object, any @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} and any per-object constraints associated with @nt<entry_@!declaration>s of the corresponding @nt<task_@!definition> are elaborated in the given order. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]} The only @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} defined for task entries are ones that specify the Address of an entry, as part of defining an interrupt entry. These clearly need to be elaborated per-object, not per-type. Normally the address will be a function of a discriminant, if such an Address clause is in a task type rather than a single task declaration, though it could rely on a parameterless function that allocates sequential interrupt vectors. We do not mention representation pragmas, since each pragma may have its own elaboration rules. @end{Reason} @PDefn2{Term=[elaboration], Sec=(task_body)} The elaboration of a @nt{task_body} has no effect other than to establish that tasks of the type can from then on be activated without failing the Elaboration_Check. @redundant[The execution of a @nt<task_body> is invoked by the activation of a task of the corresponding type (see @RefSecNum(Task Execution - Task Activation)).] @leading@;The content of a task object of a given task type includes: @begin(itemize) The values of the discriminants of the task object, if any; An entry queue for each entry of the task object; @begin(Ramification) "For each entry" implies one queue for each single entry, plus one for each entry of each entry family. @end(Ramification) A representation of the state of the associated task. @end(itemize) @end{RunTime} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[Other than in an @nt{access_definition}, the name of a task unit within],Old=[Within]} the declaration or body of @Chg{Version=[2],New=[the],Old=[a]} task unit@Chg{Version=[2],New=[],Old=[, the name of the task unit]} denotes the current instance of the unit (see @RefSecNum(The Context of Overload Resolution)), rather than the first subtype of the corresponding task type (and thus the name cannot be used as a @nt<subtype_mark>). @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[It can be used as a @nt{subtype_mark} in an anonymous access type. In addition],Old=[However]}, it is possible to refer to some other subtype of the task type within its body, presuming such a subtype has been declared between the @nt<task_type_declaration> and the @nt<task_body>. @end(Discussion) The notation of a @nt<selected_component> can be used to denote a discriminant of a task (see @RefSecNum(Selected Components)). Within a task unit, the name of a discriminant of the task type denotes the corresponding discriminant of the current instance of the unit. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A task type is a limited type (see @RefSecNum(Limited Types)), and hence @Chg{Version=[2],New=[precludes use of @nt{assignment_statement}s and], Old=[has neither an assignment operation nor]} predefined equality operators. If an application needs to store and exchange task identities, it can do so by defining an access type designating the corresponding task objects and by using access values for identification purposes. Assignment is available for such an access type as for any access type. Alternatively, if the implementation supports the Systems Programming Annex, the Identity attribute can be used for task identification (see @Chg{Version=[2],New=[@RefSecNum(The Package Task_Identification)], Old=[@RefSecNum(Task Information)]}). @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of declarations of task types:} @begin{Example} @key(task) @key(type) Server @key(is) @key(entry) Next_Work_Item(WI : @key(in) Work_Item); @key(entry) Shut_Down; @key(end) Server; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(task) @key(type) Keyboard_Driver(ID : Keyboard_ID := New_ID) @key(is)@Chg{Version=[2],New=[ @key(new) Serial_Device @key(with) --@RI[ see @RefSecNum{Interface Types}]],Old=[]} @key(entry) Read (C : @key(out) Character); @key(entry) Write(C : @key(in) Character); @key(end) Keyboard_Driver; @end{Example} @leading@keepnext@i{Examples of declarations of single tasks:} @begin{Example} @key(task) Controller @key(is) @key(entry) Request(Level)(D : Item); --@RI[ a family of entries] @key(end) Controller; @key(task) Parser @key(is) @key(entry) Next_Lexeme(L : @key(in) Lexical_Element); @key(entry) Next_Action(A : @key(out) Parser_Action); @key(end); @key(task) User; --@RI[ has no entries] @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of task objects:} @end{WideAbove} @begin{Example} Agent : Server; Teletype : Keyboard_Driver(TTY_ID); Pool : @key(array)(1 .. 10) @key(of) Keyboard_Driver; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of access type designating task objects:} @end{WideAbove} @begin{Example} @key(type) Keyboard @key(is) @key(access) Keyboard_Driver; Terminal : Keyboard := @key(new) Keyboard_Driver(Term_ID); @end{Example} @end{Examples} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised]} @Defn{extensions to Ada 83} The syntax rules for task declarations are modified to allow a @nt{known_discriminant_part}, and to allow a private part. They are also modified to allow @nt{entry_declaration}s and @Chg{New=[@nt<aspect_clause>s],Old=[@nt<representation_clause>s]} to be mixed. @end{Extend83} @begin{DiffWord83} The syntax rules for tasks have been split up according to task types and single tasks. In particular: The syntax rules for @ntf{task_declaration} and @ntf{task_specification} are removed. The syntax rules for @nt{task_type_declaration}, @nt{single_task_declaration}, @nt{task_definition} and @nt{task_item} are new. The syntax rule for @nt{task_body} now uses the nonterminal @nt{handled_sequence_of_statements}. The @nt{declarative_part} of a @nt{task_body} is now required; that doesn't make any real difference, because a @nt{declarative_part} can be empty. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Task types and single tasks can be derived from one or more interfaces. Entries of the task type can implement the primitive operations of an interface. @nt{Overriding_indicator}s can be used to specify whether or not an entry implements a primitive operation.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0029],ARef=[AI95-00116-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a task type has an implicit empty @nt{task_definition} if none is given.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Revised the note on operations of task types to reflect that limited types do have an assignment operation, but not copying (@nt{assignment_statement}s).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[Revised the note on use of the name of a task type within itself to reflect the exception for anonymous access types.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{task_type_declaration}, a @nt{single_task_declaration}, and a @nt{task_body}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0042-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that an inherited procedure of a progenitor is overridden when it is implemented by an entry.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0090-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added the missing defining name in the no conflicting primitive operation rule.]} @end{DiffWord2005} @LabeledClause{Task Execution - Task Activation} @begin{RunTime} @PDefn2{Term=[execution], Sec=(task)} The execution of a task of a given task type consists of the execution of the corresponding @nt{task_body}. @PDefn2{Term=[execution], Sec=(task_body)} @Defn2{Term=[task], Sec=(execution)} @Defn2{Term=[activation], Sec=(of a task)} @Defn2{Term=[task], Sec=(activation)} The initial part of this execution is called the @i(activation) of the task; it consists of the elaboration of the @nt<declarative_part> of the @nt<task_body>. @Defn{activation failure} Should an exception be propagated by the elaboration of its @nt<declarative_part>, the activation of the task is defined to have @i(failed), and it becomes a completed task. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} A task object (which represents one task) can be @Chg{Version=[2],New=[a part of a stand-alone object, of an object created by],Old=[created either as part of the elaboration of an @nt<object_@!declaration> occurring immediately within some declarative region, or as part of the evaluation of]} an @nt{allocator}@Chg{Version=[2],New=[, or of an anonymous object of a limited type, or a coextension of one of these],Old=[]}. All tasks@Chg{Version=[2],New=[ that are part or coextensions of any of the stand-alone objects],Old=[]} created by the elaboration of @nt<object_@!declaration>s@Chg{Version=[2], New=[ (or @nt{generic_association}s of formal objects of mode @key{in})],Old=[]} of a single declarative region@Chg{Version=[2], New=[],Old=[ (including subcomponents of the declared objects)]} are activated together. @Chg{Version=[2],New=[All tasks that are part or coextensions of a single object that is not a stand-alone object are activated together.],Old=[Similarly, all tasks created by the evaluation of a single @nt<allocator> are activated together. The activation of a task is associated with the innermost @nt<allocator> or @nt<object_@!declaration> that is responsible for its creation.]} @begin{Discussion} The initialization of an @nt{object_declaration} or @nt{allocator} can indirectly include the creation of other objects that contain tasks. For example, the default expression for a subcomponent of an object created by an @nt{allocator} might call a function that evaluates a completely different @nt{allocator}. Tasks created by the two allocators are @i{not} activated together. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} For @Chg{Version=[2],New=[the ],Old=[]}tasks@Chg{Version=[2],New=[],Old=[ created by the elaboration of @nt<object_declaration>s]} of a given declarative region, the activations are initiated within the context of the @nt<handled_@!sequence_of_@!statements> (and its associated @nt<exception_@!handler>s if any @em see @RefSecNum{Exception Handlers}), just prior to executing the statements of the @Chg{Version=[2],New=[@nt{handled_sequence_of_statements}], Old=[@ntf<_sequence>]}. @Redundant[For a package without an explicit body or an explicit @nt<handled_@!sequence_of_@!statements>, an implicit body or an implicit @nt<null_@!statement> is assumed, as defined in @RefSecNum(Package Bodies).] @begin(Ramification) If Tasking_Error is raised, it can be handled by handlers of the @nt<handled_@!sequence_of_@!statements>. @end(Ramification) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} For tasks @Chg{Version=[2],New=[that are part or coextensions of a single object that is not a stand-alone object, activations are initiated after completing any initialization of the outermost object enclosing these tasks, prior to performing any other operation on the outermost object. In particular, for tasks that are part or coextensions of the object ], Old=[]}created by the evaluation of an @nt<allocator>, the activations are initiated as the last step of evaluating the @nt<allocator>, @Chg{Version=[2],New=[],Old=[after completing any initialization for the object created by the @nt<allocator>, and ]}prior to returning the new access value.@Chg{Version=[2],New=[ For tasks that are part or coextensions of an object that is the result of a function call, the activations are not initiated until after the function returns.],Old=[]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The intent is that @lquotes@;temporary@rquotes@; objects with task parts (or coextensions) are treated similarly to an object created by an allocator. The @lquotes@;whole@rquotes@; object is initialized, and then all of the task parts (including the coextensions) are activated together. Each such @lquotes@;whole@rquotes@; object has its own task activation sequence, involving the activating task being suspended until all the new tasks complete their activation.]} @end{Discussion} @Defn2{Term=[activator], Sec=(of a task)} @PDefn2{term=[blocked], Sec=(waiting for activations to complete)} The task that created the new tasks and initiated their activations (the @i(activator)) is blocked until all of these activations complete (successfully or not). @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Once all of these activations are complete, if the activation of any of the tasks has failed @Redundant[(due to the propagation of an exception)], Tasking_Error is raised in the activator, at the place at which it initiated the activations. Otherwise, the activator proceeds with its execution normally. Any tasks that are aborted prior to completing their activation are ignored when determining whether to raise Tasking_Error. @begin(Ramification) Note that a task created by an @nt<allocator> does not necessarily depend on its activator; in such a case the activator's termination can precede the termination of the newly created task. @end(Ramification) @begin(Discussion) Tasking_Error is raised only once, even if two or more of the tasks being activated fail their activation. @end(Discussion) @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[The pragma Partition_Elaboration_Policy (see @RefSecNum{Pragma Partition_Elaboration_Policy}) can be used to defer task activation to a later point, thus changing many of these rules.]} @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0045-1]} @Chg{Version=[3],New=[If the master that directly encloses the point where the activation of a task @i<T> would be initiated, completes before the activation of @i<T> is initiated, @i<T> becomes terminated and is never activated. Furthermore, if a return statement is left such that the return object is not returned to the caller, any task that was created as a part of the return object or one of its coextensions immediately becomes], Old=[Should the task that created the new tasks never reach the point where it would initiate the activations (due to an abort or the raising of an exception), the newly created tasks become]} terminated @Chg{Version=[3],New=[and is],Old=[are]} never activated. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0045-1]} @ChgAdded{Version=[3],Text=[The first case can only happen if the activation point of T is not reached due to an exception being raised or a task or statement being aborted. Note that this is exclusive; if the master completes normally and starts finalization, we're already past the activation point.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0045-1]} @ChgAdded{Version=[3],Text=[The second case can happen with an exception being raised in a return statement, by an exit or goto from an @nt{extended_return_statement}, or by a return statement being aborted. Any tasks created for the return object of such a return statement are never activated.]} @end{Ramification} @end{RunTime} @begin{Notes} An entry of a task can be called before the task has been activated. If several tasks are activated together, the execution of any of these tasks need not await the end of the activation of the other tasks. A task can become completed during its activation either because of an exception or because it is aborted (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of task activation:} @begin{Example} @key(procedure) P @key(is) A, B : Server; --@RI[ elaborate the task objects A, B] C : Server; --@RI[ elaborate the task object C] @key(begin) --@RI[ the tasks A, B, C are activated together before the first statement] ... @key(end); @end{Example} @end{Examples} @begin{DiffWord83} We have replaced the term @i{suspended} with @i{blocked}, since we didn't want to consider a task blocked when it was simply competing for execution resources. "Suspended" is sometimes used more generally to refer to tasks that are not actually running on some processor, due to the lack of resources. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} has been rewritten in an attempt to improve presentation. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Adjusted the wording for activating tasks to handle the case of anonymous function return objects. This is critical; we don't want to be waiting for the tasks in a return object when we exit the function normally.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0045-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the wording that handles tasks that are never activated to ensure that no lookahead is implied and to make it clear that tasks created by return statements that never return are never activated.]} @end{DiffWord2005} @LabeledClause{Task Dependence - Termination of Tasks} @begin{RunTime} @leading@Defn2{Term=[dependence], Sec=(of a task on a master)} @Defn2{Term=[task], Sec=(dependence)} @Defn2{Term=[task], Sec=(completion)} @Defn2{Term=[task], Sec=(termination)} Each task (other than an environment task @em see @RefSecNum(Program Execution)) @i(depends) on one or more masters (see @RefSecNum(Completion and Finalization)), as follows: @begin(itemize) If the task is created by the evaluation of an @nt<allocator> for a given access type, it depends on each master that includes the elaboration of the declaration of the ultimate ancestor of the given access type. If the task is created by the elaboration of an @nt<object_declaration>, it depends on each master that includes this elaboration. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Otherwise, the task depends on the master of the outermost object of which it is a part (as determined by the accessibility level of that object @em see @RefSecNum{Operations of Access Types} and @RefSecNum{Completion and Finalization}), as well as on any master whose execution includes that of the master of the outermost object.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The master of a task created by a return statement changes when the accessibility of the return object changes. Note that its activation happens, if at all, only after the function returns and all accessibility level changes have occurred.]} @end{Ramification} @end(itemize) @Defn2{term=[dependence], Sec=(of a task on another task)} Furthermore, if a task depends on a given master, it is defined to depend on the task that executes the master, and (recursively) on any master of that task. @begin{Discussion} Don't confuse these kinds of dependences with the dependences among compilation units defined in @RefSec{Compilation Units - Library Units}. @end{Discussion} A task is said to be @i(completed) when the execution of its corresponding @nt<task_body> is completed. A task is said to be @i(terminated) when any finalization of the @nt<task_body> has been performed (see @RefSecNum(Completion and Finalization)). @Redundant[The first step of finalizing a master (including a @nt<task_body>) is to wait for the termination of any tasks dependent on the master.] @PDefn2{Term=[blocked], Sec=(waiting for dependents to terminate)} The task executing the master is blocked until all the dependents have terminated. @Redundant[Any remaining finalization is then performed and the master is left.] @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Doubled word} @leading@;Completion of a task (and the corresponding @nt<task_body>) can occur when the task is blocked at a @nt<select_@!statement> with an @Chg{New=[],Old=[an ]}open @nt<terminate_alternative> (see @RefSecNum(Selective Accept)); the open @nt<terminate_alternative> is selected if and only if the following conditions are satisfied: @begin{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} The task depends on some completed master;@Chg{Version=[2],New=[ and],Old=[]} Each task that depends on the master considered is either already terminated or similarly blocked at a @nt<select_statement> with an open @nt{terminate_alternative}. @end{itemize} When both conditions are satisfied, the task considered becomes completed, together with all tasks that depend on the master considered that are not yet completed. @begin(Ramification) Any required finalization is performed after the selection of @nt<terminate_alternative>s. The tasks are not callable during the finalization. In some ways it is as though they were aborted. @end(Ramification) @end{RunTime} @begin{Notes} The full view of a limited private type can be a task type, or can have subcomponents of a task type. Creation of an object of such a type creates dependences according to the full type. An @nt<object_renaming_declaration> defines a new view of an existing entity and hence creates no further dependence. The rules given for the collective completion of a group of tasks all blocked on @nt<select_statement>s with open @nt<terminate_alternative>s ensure that the collective completion can occur only when there are no remaining active tasks that could call one of the tasks being collectively completed. If two or more tasks are blocked on @nt<select_statement>s with open @nt{terminate_alternative}s, and become completed collectively, their finalization actions proceed concurrently. @leading@keepnext@;The completion of a task can occur due to any of the following: @begin{itemize} the raising of an exception during the elaboration of the @nt{declarative_part} of the corresponding @nt{task_body}; the completion of the @nt{handled_sequence_of_statements} of the corresponding @nt{task_body}; the selection of an open @nt<terminate_alternative> of a @nt<select_statement> in the corresponding @nt<task_body>; the abort of the task. @end{itemize} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of task dependence:} @begin{Example} @key(declare) @key(type) Global @key(is) @key(access) Server; --@RI[ see @RefSecNum(Task Units and Task Objects)] A, B : Server; G : Global;@Softpage @key(begin) --@RI[ activation of A and B] @key(declare) @key(type) Local @key(is) @key(access) Server; X : Global := @key(new) Server; --@RI[ activation of X.@key{all}] L : Local := @key(new) Server; --@RI[ activation of L.@key{all}] C : Server;@Softpage @key(begin) --@RI[ activation of C] G := X; --@RI[ both G and X designate the same task object] ... @key(end;) --@RI[ await termination of C and L.@key{all} (but not X.@key{all})] ... @key(end;) --@RI[ await termination of A, B, and G.@key{all}] @end{Example} @end{Examples} @begin{DiffWord83} We have revised the wording to be consistent with the definition of master now given in @RefSec(Completion and Finalization). Tasks that used to depend on library packages in Ada 83, now depend on the (implicit) @nt<task_body> of the environment task (see @RefSecNum(Program Execution)). Therefore, the environment task has to wait for them before performing library level finalization and terminating the partition. In Ada 83 the requirement to wait for tasks that depended on library packages was not as clear. What was "collective termination" is now "collective completion" resulting from selecting @nt<terminate_alternative>s. This is because finalization still occurs for such tasks, and this happens after selecting the @nt<terminate_alternative>, but before termination. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added missing wording that explained the master of tasks that are neither object declarations nor allocators, such as function returns.]} @end{DiffWord95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Protected Units and Protected Objects} @begin{Intro} @Defn{protected object} @Defn{protected operation} @Defn{protected subprogram} @Defn{protected entry} A @i(protected object) provides coordinated access to shared data, through calls on its visible @i(protected operations), which can be @i{protected subprograms} or @i{protected entries}. @Defn{protected declaration} @Defn{protected unit} @Defn{protected declaration} A @i{protected unit} is declared by a @i(protected declaration), which has a corresponding @nt<protected_body>. A protected declaration may be a @nt<protected_type_declaration>, in which case it declares a named protected type; alternatively, it may be a @nt<single_protected_declaration>, in which case it defines an anonymous protected type, as well as declaring a named protected object of that type. @IndexSee{Term=[broadcast signal],See=(protected object)} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<protected_type_declaration>,rhs=" @key{protected} @key{type} @Syn2{defining_identifier} [@Syn2{known_discriminant_part}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{protected_definition};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00399-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<single_protected_declaration>,rhs=" @key{protected} @Syn2{defining_identifier}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is}@Chg{Version=[2],New=< [@key{new} @Syn2{interface_list} @key{with}] >,Old=<>} @Syn2{protected_definition};"} @Syn{lhs=<protected_definition>,rhs=" { @Syn2{protected_operation_declaration} } [ @key{private} { @Syn2{protected_element_declaration} } ] @key{end} [@SynI{protected_}@Syn2{identifier}]"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<protected_operation_declaration>, rhs="@Syn2{subprogram_declaration} | @Syn2{entry_declaration} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @Syn{lhs=<protected_element_declaration>, rhs="@Syn2<protected_operation_declaration> | @Syn2<component_declaration>"} @begin{Reason} We allow the operations and components to be mixed because that's how other things work (for example, package declarations). We have relaxed the ordering rules for the items inside @nt{declarative_part}s and @nt{task_definition}s as well. @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0267-1]} @Syn{lhs=<protected_body>,rhs=" @key{protected} @key{body} @Syn2{defining_identifier}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]} @key{is} { @Syn2{protected_operation_item} } @key{end} [@SynI{protected_}@Syn2{identifier}];"} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<protected_operation_item>, rhs="@Syn2{subprogram_declaration} | @Syn2{subprogram_body} | @Syn2{entry_body} | @Chg{New=[@Syn2{aspect_clause}],Old=[@Syn2{representation_clause}]}"} @begin{SyntaxText} If a @SynI{protected_}@nt{identifier} appears at the end of a @nt{protected_definition} or @nt{protected_body}, it shall repeat the @nt{defining_identifier}. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00345-01]}@ChgNote{This was just moved below} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{protected_declaration})} A protected declaration requires a completion@redundant[, which shall be a @nt{protected_@!body},] and every @nt{protected_@!body} shall be the completion of some protected declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[The completion can be a @nt{pragma} Import, if the implementation supports it.]} @end(Honest) @end{Legality} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 10 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01],ARef=[AI95-00401-01]}@Comment{This is no change here, but both of these AIs reference this paragraph, adding and removing text.} A @nt<protected_definition> defines a protected type and its first subtype. @PDefn2{Term=[visible part], Sec=(of a protected unit)} The list of @nt{protected_@!operation_@!declaration}s of a @nt{protected_@!definition}, together with the @nt{known_@!discriminant_@!part}, if any, is called the visible part of the protected unit. @Redundant[@PDefn2{Term=[private part], Sec=(of a protected unit)} The optional list of @nt{protected_@!element_@!declaration}s after the reserved word @key{private} is called the private part of the protected unit.] @begin{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Private part is defined in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules}. @end{theproof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0042-1]} @ChgAdded{Version=[2],Text=[For a protected declaration with an @nt{interface_list}, the protected type inherits user-defined primitive subprograms from each progenitor type (see @RefSecNum{Interface Types}), in the same way that a derived type inherits user-defined primitive subprograms from its progenitor types (see @RefSecNum{Derived Types and Classes}). If the first parameter of a primitive inherited subprogram is of the protected type or an access parameter designating the protected type, and there is a @nt{protected_operation_declaration} for a protected subprogram or single entry with the same identifier within the protected declaration, whose profile is type conformant with the prefixed view profile of the inherited subprogram, the inherited subprogram is said to be @i{implemented} by the conforming protected subprogram or entry@Chg{Version=[3],New=[ using an implicitly declared nonabstract subprogram which has the same profile as the inherited subprogram and which overrides it@PDefn2{Term=[override],Sec=[when implemented by]}], Old=[]}.@PDefn2{Term=[implemented], Sec=[by a protected subprogram]}@PDefn2{Term=[implemented], Sec=[by a protected entry]} @Defn2{Term=[type conformance],Sec=(required)}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inherited subprograms can only come from an interface given as part of the protected declaration.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0042-1]} @ChgAdded{Version=[3],Text=[The part about the implicitly declared subprogram is needed so that a subprogram implemented by an entry or subprogram is considered to be overridden for the purpose of the other rules of the language. Without it, it would for instance be illegal for an abstract subprogram to be implemented by an entry, because the abstract subprogram would not be overridden. The @LegalityTitle below ensure that there is no conflict between the implicit overriding subprogram and a user-defined overriding subprogram.]} @end{Reason} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]}@ChgNote{This was just moved, not changed} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[requires a completion], Sec=(@nt{protected_declaration})} A protected declaration requires a completion@redundant[, which shall be a @nt{protected_@!body},] and every @nt{protected_@!body} shall be the completion of some protected declaration.]} @begin(Honest) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[If],Old=[The completion can be a @nt{pragma} Import, if]} the implementation supports it@Chg{Version=[3],New=[, the protected body can be imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no explicit @nt{protected_body} is allowed],Old=[]}.]} @end(Honest) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Text=[@Redundant[Each @i{interface_}@nt{subtype_mark} of an @nt{interface_list} appearing within a protected declaration shall denote a limited interface type that is not a task interface.]]} @begin(TheProof) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@RefSecNum{Interface Types} requires that an @nt{interface_list} only name interface types, and limits the descendants of the various kinds of interface types. Only a limited, protected, or synchronized interface can have a protected type descendant. Nonlimited or task interfaces are not allowed, as they offer operations that a protected type does not have.]} @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0042-1]} @ChgAdded{Version=[2],Text=[The prefixed view profile of an explicitly declared primitive subprogram of a tagged protected type shall not be type conformant with any protected operation of the protected type, if the@Chg{Version=[3],New=[ subprogram has the same defining name as the protected operation and the],Old=[]} first parameter of the subprogram is of the protected type or is an access parameter designating the protected type.@Defn2{Term=[type conformance],Sec=(required)}]} @begin(Reason) @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents the existence of two operations with the same name and profile which could be called with a prefixed view. If the operation was inherited, this would be illegal by the following rules; this rule puts inherited and noninherited routines on the same footing. Note that this only applies to tagged protected types (that is, those with an interface in their declaration); we do that as there is no problem with prefixed view calls of primitive operations for @lquotes@;normal@rquotes protected types, and having this rule apply to all protected types would be incompatible with Ada 95.]} @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00399-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each primitive subprogram inherited by the type declared by a protected declaration, at most one of the following shall apply:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is overridden with a primitive subprogram of the protected type, in which case the overriding subprogram shall be subtype conformant with the inherited subprogram and not abstract; or@Defn2{Term=[subtype conformance],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[the inherited subprogram is implemented by a protected subprogram or single entry of the protected type, in which case its prefixed view profile shall be subtype conformant with that of the protected subprogram or entry. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[If neither applies, the inherited subprogram shall be a null procedure. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each inherited subprogram can only have a single implementation (either from overriding a subprogram, implementing a subprogram, or implementing an entry), and must have an implementation unless the subprogram is a null procedure.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0291-1]} @ChgAdded{Version=[2],Text=[If an inherited subprogram is implemented by a protected procedure or an entry, then the first parameter of the inherited subprogram shall be of mode @key{out} or @key{in out}, or an access-to-variable parameter.@Chg{Version=[3],New=[ If an inherited subprogram is implemented by a protected function, then the first parameter of the inherited subprogram shall be of mode @key{in}, but not an access-to-variable parameter.],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[For a protected procedure or entry, the protected object can be read or written (see @RefSecNum{Protected Subprograms and Protected Actions}). A subprogram that is implemented by a protected procedure or entry must have a profile which reflects that in order to avoid confusion.@Chg{Version=[3],New=[ Similarly, a protected function has a parameter that is a constant, and the inherited routine should reflect that.],Old=[]}]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If a protected subprogram declaration has an @nt{overriding_indicator}, then at the point of the declaration:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the subprogram shall implement an inherited subprogram;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the subprogram shall not implement any inherited subprogram.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are subtly different than those for subprograms (see @RefSecNum{Overriding Indicators}) because there cannot be @lquotes@;late@rquotes inheritance of primitives from interfaces. Hidden (that is, private) interfaces are prohibited explicitly (see @RefSecNum{Private Types and Private Extensions}), as are hidden primitive operations (as private operations of public abstract types are prohibited @em see @RefSecNum{Abstract Types and Subprograms}).]} @end{Discussion} @end{Legality} @begin{RunTime} @redundant[@PDefn2{Term=[elaboration], Sec=(protected declaration)}The elaboration of a protected declaration elaborates the @nt<protected_definition>. @PDefn2{Term=[elaboration], Sec=(single_protected_declaration)} The elaboration of a @nt<single_@!protected_@!declaration> also creates an object of an (anonymous) protected type.] @begin(TheProof) This is redundant with the general rules for the elaboration of a @nt<full_type_declaration> and an @nt<object_declaration>. @end(TheProof) @PDefn2{Term=[elaboration], Sec=(protected_definition)} @Redundant[The elaboration of a @nt<protected_definition> creates the protected type and its first subtype;] it also includes the elaboration of the @nt<component_declaration>s and @nt<protected_operation_declaration>s in the given order. @redundant[@PDefn2{Term=[initialization], Sec=(of a protected object)}As part of the initialization of a protected object, any per-object constraints (see @RefSecNum{Record Types}) are elaborated.] @begin{Discussion} We do not mention pragmas since each pragma has its own elaboration rules. @end{Discussion} @PDefn2{Term=[elaboration], Sec=(protected_body)} The elaboration of a @nt{protected_body} has no other effect than to establish that protected operations of the type can from then on be called without failing the Elaboration_Check. @leading@keepnext@;The content of an object of a given protected type includes: @begin(itemize) The values of the components of the protected object, including (implicitly) an entry queue for each entry declared for the protected object; @begin(Ramification) "For each entry" implies one queue for each single entry, plus one for each entry of each entry family. @end(Ramification) @PDefn2{Term=[execution resource], Sec=(associated with a protected object)} A representation of the state of the execution resource @i(associated) with the protected object (one such resource is associated with each protected object). @end(itemize) @Redundant[The execution resource associated with a protected object has to be acquired to read or update any components of the protected object; it can be acquired (as part of a protected action @em see @RefSecNum(Protected Subprograms and Protected Actions)) either for concurrent read-only access, or for exclusive read-write access.] @PDefn2{Term=[finalization], Sec=(of a protected object)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} As the first step of the @i{finalization} of a protected object, each call remaining on any entry queue of the object is removed from its queue and Program_Error is raised at the place of the corresponding @nt<entry_@!call_@!statement>. @begin(Reason) @leading@;This is analogous to the raising of Tasking_Error in callers of a task that completes before accepting the calls. This situation can only occur due to a requeue (ignoring premature unchecked_deallocation), since any task that has accessibility to a protected object is awaited before finalizing the protected object. For example: @begin{Example} @key[procedure] Main @key[is] @key[task] T @key[is] @key[entry] E; @key[end] T; @key[task] @key[body] T @key[is] @key[protected] PO @key[is] @key[entry] Ee; @key[end] PO; @key[protected] @key[body] PO @key[is] @key[entry] Ee @key[when] False @key[is] @key[begin] @key[null]; @key[end] Ee; @key[end] PO; @key[begin] @key[accept] E @key[do] @key[requeue] PO.Ee; @key[end] E; @key[end] T; @key[begin] T.E; @key[end] Main; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The environment task is queued on PO.@Chg{Version=[3],New=[Ee],Old=[EE]} when PO is finalized. In a real example, a server task might park callers on a local protected object for some useful purpose, so we didn't want to disallow this case. @end(Reason) @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call an entry or subprogram of a protected object after that object is finalized. If the error is detected, Program_Error is raised. Otherwise, the call proceeds normally, which may leave a task queued forever.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is very similar to the finalization rule. It is a bounded error so that an implementation can avoid the overhead of the check if it can ensure that the call still will operate properly. Such an implementation cannot need to return resources (such as locks) to an executive that it needs to execute calls.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This case can happen (and has happened in production code) when a protected object is accessed from the Finalize routine of a type. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Finalization.Controlled; @key{package} Window_Manager @key{is} ... @key{type} Root_Window @key{is new} Ada.Finalization.Controlled @key{with private}; @key{type} Any_Window @key{is access all} Root_Window; ... @key{private} ... @key{procedure} Finalize (Object : @key{in out} Root_Window); ... @key{end} Window_Manager;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Window_Manager @key{is} @key{protected type} Lock @key{is} @key{entry} Get_Lock; @key{procedure} Free_Lock; ... @key{end} Lock;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Window_Lock : Lock;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Finalize (Object : @key{in out} Root_Window) @key{is} @key{begin} Window_Lock.Get_Lock; ... Window_Lock.Free_Lock; @key{end} Finalize; ... A_Window : Any_Window := @key{new} Root_Window; @key{end} Window_Manager;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task will call Window_Lock for the object allocated for A_Window when the collection for Any_Window is finalized, which will happen after the finalization of Window_Lock (because finalization of the package body will occur before that of the package specification).]} @end{Reason} @end{Bounded} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} Within the declaration or body of a protected unit@Chg{Version=[2],New=[ other than in an @nt{access_definition}],Old=[]}, the name of the protected unit denotes the current instance of the unit (see @RefSecNum(The Context of Overload Resolution)), rather than the first subtype of the corresponding protected type (and thus the name cannot be used as a @nt<subtype_mark>). @begin(Discussion) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00382-01]} @Chg{Version=[2],New=[It can be used as a @nt{subtype_mark} in an anonymous access type. In addition],Old=[However]}, it is possible to refer to some other subtype of the protected type within its body, presuming such a subtype has been declared between the @nt<protected_type_declaration> and the @nt<protected_body>. @end(Discussion) A @nt<selected_component> can be used to denote a discriminant of a protected object (see @RefSecNum(Selected Components)). Within a protected unit, the name of a discriminant of the protected type denotes the corresponding discriminant of the current instance of the unit. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} A protected type is a limited type (see @RefSecNum(Limited Types)), and hence @Chg{Version=[2],New=[precludes use of @nt{assignment_statement}s and], Old=[has neither an assignment operation nor]} predefined equality operators. The bodies of the protected operations given in the @nt<protected_body> define the actions that take place upon calls to the protected operations. The declarations in the private part are only visible within the private part and the body of the protected unit. @begin{Reason} @nt{Component_declaration}s are disallowed in a @nt{protected_body} because, for efficiency, we wish to allow the compiler to determine the size of protected objects (when not dynamic); the compiler cannot necessarily see the body. Furthermore, the semantics of initialization of such objects would be problematic @em we do not wish to give protected objects complex initialization semantics similar to task activation. The same applies to @nt{entry_declaration}s, since an entry involves an implicit component @em the entry queue. @end{Reason} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of declaration of protected type and corresponding body:} @begin{Example} @key(protected) @key(type) Resource @key(is) @key(entry) Seize; @key(procedure) Release; @key(private) Busy : Boolean := False; @key(end) Resource; @key(protected) @key(body) Resource @key(is) @key(entry) Seize @key(when not) Busy @key(is) @key(begin) Busy := True; @key(end) Seize; @key(procedure) Release @key(is) @key(begin) Busy := False; @key(end) Release; @key(end) Resource; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a single protected declaration and corresponding body:} @end{WideAbove} @begin{Example} @key(protected) Shared_Array @key(is) --@RI[ Index, Item, and Item_Array are global types] @key(function) Component (N : @key(in) Index) return Item; @key(procedure) Set_Component(N : @key(in) Index; E : @key(in) Item); @key(private) Table : Item_Array(Index) := (others => Null_Item); @key(end) Shared_Array; @key(protected) @key(body) Shared_Array @key(is) @key(function) Component(N : @key(in) Index) @key(return) Item @key(is) @key(begin) @key(return) Table(N); @key(end) Component; @key(procedure) Set_Component(N : @key(in) Index; E : @key(in) Item) @key(is) @key(begin) Table(N) := E; @key(end) Set_Component; @key(end) Shared_Array; @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of protected objects:} @end{WideAbove} @begin{Example} Control : Resource; Flags : @key(array)(1 .. 100) @key(of) Resource; @end{Example} @end{Examples} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{extensions to Ada 83} This entire @Chg{Version=[3],New=[subclause],Old=[clause]} is new; protected units do not exist in Ada 83. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01],ARef=[AI95-00397-01],ARef=[AI95-00399-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Protected types and single protected objects can be derived from one or more interfaces. Operations declared in the protected type can implement the primitive operations of an interface. @nt{Overriding_indicator}s can be used to specify whether or not a protected operation implements a primitive operation.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed representation clauses to aspect clauses to reflect that they are used for more than just representation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Described what happens when an operation of a finalized protected object is called.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Revised the note on operations of protected types to reflect that limited types do have an assignment operation, but not copying (@nt{assignment_statement}s).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00382-01]} @ChgAdded{Version=[2],Text=[Revised the note on use of the name of a protected type within itself to reflect the exception for anonymous access types.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0291-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} When an inherited subprogram is implemented by a protected function, the first parameter has to be an @key[in] parameter, but not an access-to-variable type. Ada 2005 allowed access-to-variable parameters in this case; the parameter will need to be changed to access-to-constant with the addition of the @key[constant] keyword.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{protected_type_declaration}, a @nt{single_protected_declaration}, and a @nt{protected_body}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0042-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that an inherited subprogram of a progenitor is overridden when it is implemented by an entry or subprogram.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0090-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added the missing defining name in the no conflicting primitive operation rule.]} @end{DiffWord2005} @LabeledClause{Intertask Communication} @begin{Intro} @Defn{intertask communication} @IndexSee{Term=[critical section],See=(intertask communication)} The primary means for intertask communication is provided by calls on entries and protected subprograms. Calls on protected subprograms allow coordinated access to shared data objects. Entry calls allow for blocking the caller until a given condition is satisfied (namely, that the corresponding entry is open @em see @RefSecNum(Entry Calls)), and then communicating data or control information directly with another task or indirectly via a shared protected object. @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0225-1],ARef=[AI05-0291-1]} @Leading@;@Chg{Version=[3],New=[@Defn2{Term=[target object], Sec=(of the name of an entry or a protected subprogram)}], Old=[@Defn2{Term=[target object], Sec=(of a call on an entry or a protected subprogram)}]} @Chg{Version=[3],New=[When a @nt{name} or @nt{prefix} denotes],Old=[Any call on]} an entry@Chg{Version=[3],New=[,],Old=[ or on a]} protected subprogram@Chg{Version=[3],New=[, or a prefixed view of a primitive subprogram of a limited interface whose first parameter is a controlling parameter, the @nt{name} or @nt{prefix} determines],Old=[ identifies]} a @i(target object)@Chg{Version=[3],New=[],Old=[ for the operation, which is either a task (for an entry call) or a protected object (for an entry call or a protected subprogram call). The target object is considered an implicit parameter to the operation, and is determined by the operation @nt<name> (or @nt<prefix>) used in the call on the operation]}, as follows: @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0291-1]} @ChgAdded{Version=[3],Text=[This wording uses "denotes" to mean "denotes a view of an entity" (when the term is used in Legality Rules), and "denotes an entity" (when the term is used in Dynamic Semantics rules). It does not mean "view of a declaration", as that would not include renames (a renames is not an entry or protected subprogram).]} @end{Honest} @begin(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0291-1]} If it is a @nt<direct_name> or expanded name that denotes the declaration (or body) of the operation, then the target object is implicitly specified to be the current instance of the task or protected unit immediately enclosing the operation; @Defn{internal call} @Chg{Version=[3],New=[],Old=[such ]}a call@Chg{Version=[3],New=[ using such a name],Old=[]} is defined to be an @i(internal call); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0291-1]} If it is a @nt<selected_component> that is not an expanded name, then the target object is explicitly specified to be the @Chg{Version=[3],New=[],Old=[task or protected]} object denoted by the @nt<prefix> of the @nt<name>; @Defn{external call} @Chg{Version=[3],New=[],Old=[such ]}a call@Chg{Version=[3],New=[ using such a name],Old=[]} is defined to be an @i(external call); @begin{Discussion} For example: @begin{Example} @key[protected] @key[type] Pt @key[is] @key[procedure] Op1; @key[procedure] Op2; @key[end] Pt; PO : Pt; Other_Object : Some_Other_Protected_Type; @key[protected] @key[body] Pt @key[is] @key[procedure] Op1 @key[is] @key[begin] ... @key[end] Op1; @key[procedure] Op2 @key[is] @key[begin] Op1; --@RI{ An internal call.} Pt.Op1; --@RI{ Another internal call.} PO.Op1; --@RI{ An external call. It the current instance is PO, then} --@RI{ this is a bounded error (see @RefSecNum{Protected Subprograms and Protected Actions}).} Other_Object.Some_Op; --@RI{ An external call.} @key[end] Op2; @key[end] Pt; @end{Example} @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0291-1]} If the @nt<name> or @nt<prefix> is a dereference (implicit or explicit) of an access-to-protected-subprogram value, then the target object is determined by the @nt<prefix> of the Access @nt<attribute_reference> that produced the access value originally@Chg{Version=[3],New=[; a], Old=[, and the]} call@Chg{Version=[3],New=[ using such a name],Old=[]} is defined to be an @i(external call); If the @nt<name> or @nt<prefix> denotes a @nt<subprogram_renaming_declaration>, then the target object is as determined by the @nt<name> of the renamed entity. @end(Itemize) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0291-1]} @ChgAdded{Version=[3],Text=[A call on an entry or a protected subprogram either uses a @nt{name} or @nt{prefix} that determines a target object implicitly, as above, or is a call on (a non-prefixed view of) a primitive subprogram of a limited interface whose first parameter is a controlling parameter, in which case the target object is identified explicitly by the first parameter. This latter case is an @i<external call>.]} @Defn2{Term=[target object], Sec=(of a @nt<requeue_statement>)} @Defn{internal requeue} @Defn{external requeue} A corresponding definition of target object applies to a @nt<requeue_statement> (see @RefSecNum(Requeue Statements)), with a corresponding distinction between an @i(internal requeue) and an @i(external requeue). @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0225-1],ARef=[AI05-0291-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[If a @nt{name} or @nt{prefix} determines a target object, and the name denotes],Old=[The view of the target protected object associated with a call of]} a protected @Chg{Version=[3],New=[entry],Old=[procedure]} or @Chg{Version=[3],New=[procedure, then the target object],Old=[entry]} shall be a variable@Chg{Version=[3],New=[, unless the @nt{prefix} is for an @nt{attribute_reference} to the Count attribute (see @RefSecNum{Task and Entry Attributes})],Old=[]}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0225-1]} @ChgAdded{Version=[3],Text=[The point is to prevent any calls to such a @nt{name} whose target object is a constant view of a protected object, directly, or via an access value, renames, or generic formal subprogram. It is, however, legal to say P'Count in a protected function body, even though the protected object is a constant view there.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0291-1]} @ChgAdded{Version=[3],Text=[This rule does not apply to calls that are not to a prefixed view. Specifically a "normal" call to a primitive operation of a limited interface is not covered by this rule. In that case, the normal parameter passing mode checks will prevent passing a constant protected object to an operation implemented by a protected entry or procedure as the mode is required to be @key[in out] or @key[out].]} @end{Ramification} @end{Legality} @begin{RunTime} Within the body of a protected operation, the current instance (see @RefSecNum(The Context of Overload Resolution)) of the immediately enclosing protected unit is determined by the target object specified (implicitly or explicitly) in the call (or requeue) on the protected operation. @begin{Honest} The current instance is defined in the same way within the body of a subprogram declared immediately within a @nt{protected_body}. @end{Honest} Any call on a protected procedure or entry of a target protected object is defined to be an update to the object, as is a requeue on such an entry. @begin(Reason) Read/write access to the components of a protected object is granted while inside the body of a protected procedure or entry. Also, any protected entry call can change the value of the Count attribute, which represents an update. Any protected procedure call can result in servicing the entries, which again might change the value of a Count attribute. @end(Reason) @end{RunTime} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<synchronization_kind>,Old=<>}>, rhs="@Chg{Version=[3],New=<By_Entry | By_Protected_Procedure | Optional>,Old=<>}"} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For the declaration of a primitive procedure of a synchronized tagged type the following language-defined representation aspect may be specified with an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}):]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Synchronization@\If specified, the aspect definition shall be a @nt{synchronization_kind}.@AspectDefn{Synchronization}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Synchronization], Text=[@ChgAdded{Version=[3],Text=[Defines whether a given primitive operation of a synchronized interface must be implemented by an entry or protected procedure.]}]} @end{Description} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[Inherited subprograms inherit the Synchronization aspect, if any, from the corresponding subprogram of the parent or progenitor type. If an overriding operation does not have a directly specified Synchronization aspect then the Synchronization aspect of the inherited operation is inherited by the overriding operation.]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[The @nt{synchronization_kind} By_Protected_Procedure shall not be applied to a primitive procedure of a task interface.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[A procedure for which the specified @nt{synchronization_kind} is By_Entry shall be implemented by an entry. A procedure for which the specified @nt{synchronization_kind} is By_Protected_Procedure shall be implemented by a protected procedure. A procedure for which the specified @nt{synchronization_kind} is Optional may be implemented by an entry or by a procedure (including a protected procedure).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[If a primitive procedure overrides an inherited operation for which the Synchronization aspect has been specified to be By_Entry or By_Protected_Procedure, then any specification of the aspect Synchronization applied to the overriding operation shall have the same @nt{synchronization_kind}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2]} @ChgAdded{Version=[3],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @end{Legality} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[The @nt{synchronization_kind} By_Protected_Procedure implies that the operation will not block.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[Added a @LegalityName to make it crystal-clear that the protected object of an entry or procedure call must be a variable. This rule was implied by the @RuntimeTitle here, along with the @StaticSemTitle of @RefSecNum{Objects and Named Numbers}, but it is much better to explicitly say it. While many implementations have gotten this wrong, this is not an incompatibility @em allowing updates of protected constants has always been wrong.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added the Synchronization aspect to allow specifying that an interface procedure is really an entry or a protected procedure.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0225-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that the target object of any name denoted a protected procedure or entry can never be a constant (other than for the 'Count attribute). This closes holes involving calls to access-to-protected, renaming as a procedure, and generic formal subprograms.]} @end{DiffWord2005} @LabeledSubClause{Protected Subprograms and Protected Actions} @begin{Intro} @Defn{protected subprogram} @Defn{protected procedure} @Defn{protected function} A @i{protected subprogram} is a subprogram declared immediately within a @nt{protected_definition}. Protected procedures provide exclusive read-write access to the data of a protected object; protected functions provide concurrent read-only access to the data. @begin{Ramification} A subprogram declared immediately within a @nt{protected_body} is not a protected subprogram; it is an intrinsic subprogram. See @RefSec{Conformance Rules}. @end{Ramification} @end{Intro} @begin{StaticSem} @Redundant[Within the body of a protected function (or a function declared immediately within a @nt<protected_body>), the current instance of the enclosing protected unit is defined to be a constant (that is, its subcomponents may be read but not updated). Within the body of a protected procedure (or a procedure declared immediately within a @nt<protected_body>), and within an @nt<entry_body>, the current instance is defined to be a variable (updating is permitted).] @begin(TheProof) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0120-1]} @ChgAdded{Version=[3],Text=[All constant views are defined in @RefSec{Objects and Named Numbers}, anything not named there is a variable view.]} @end(TheProof) @begin(Ramification) The current instance is like an implicit parameter, of mode @key(in) for a protected function, and of mode @key(in out) for a protected procedure (or protected entry). @end(Ramification) @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(protected subprogram call)} For the execution of a call on a protected subprogram, the evaluation of the @nt<name> or @nt<prefix> and of the parameter associations, and any assigning back of @key[in out] or @key[out] parameters, proceeds as for a normal subprogram call (see @RefSecNum{Subprogram Calls}). If the call is an internal call (see @RefSecNum(Intertask Communication)), the body of the subprogram is executed as for a normal subprogram call. If the call is an external call, then the body of the subprogram is executed as part of a new @i(protected action) on the target protected object; the protected action completes after the body of the subprogram is executed. @Redundant[A protected action can also be started by an entry call (see @RefSecNum{Entry Calls}).] @leading@Defn{protected action} A new protected action is not started on a protected object while another protected action on the same protected object is underway, unless both actions are the result of a call on a protected function. This rule is expressible in terms of the execution resource associated with the protected object: @begin(Itemize) @Defn2{Term=[protected action], Sec=(start)} @Defn2{Term=[acquire], Sec=(execution resource associated with protected object)} @i(Starting) a protected action on a protected object corresponds to @i(acquiring) the execution resource associated with the protected object, either for concurrent read-only access if the protected action is for a call on a protected function, or for exclusive read-write access otherwise; @Defn2{Term=[protected action], Sec=(complete)} @Defn2{Term=[release], Sec=(execution resource associated with protected object)} @i(Completing) the protected action corresponds to @i(releasing) the associated execution resource. @end(Itemize) @Redundant[After performing an operation on a protected object other than a call on a protected function, but prior to completing the associated protected action, the entry queues (if any) of the protected object are serviced (see @RefSecNum(Entry Calls)).] @end{RunTime} @begin{Bounded} @leading@PDefn2{Term=(bounded error),Sec=(cause)} During a protected action, it is a bounded error to invoke an operation that is @i(potentially blocking). @Defn{potentially blocking operation} @Defn{blocking, potentially} The following are defined to be potentially blocking operations: @begin{Reason} Some of these operations are not directly blocking. However, they are still treated as bounded errors during a protected action, because allowing them might impose an undesirable implementation burden. @end{Reason} @begin{itemize} a @nt{select_statement}; an @nt{accept_statement}; an @nt{entry_call_statement}; a @nt{delay_statement}; an @nt{abort_statement}; task creation or activation; an external call on a protected subprogram (or an external requeue) with the same target object as that of the protected action; @begin(Reason) This is really a deadlocking call, rather than a blocking call, but we include it in this list for simplicity. @end(Reason) a call on a subprogram whose body contains a potentially blocking operation. @begin(Reason) This allows an implementation to check and raise Program_Error as soon as a subprogram is called, rather than waiting to find out whether it actually reaches the potentially blocking operation. This in turn allows the potentially blocking operation check to be performed prior to run time in some environments. @end(Reason) @end{itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the bounded error is detected, Program_Error is raised. If not detected, the bounded error might result in deadlock or a (nested) protected action on the same target object. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[By @lquotes@;nested protected action@rquotes, we mean that an additional protected action can be started by another task on the same protected object. This means that mutual exclusion may be broken in this bounded error case. A way to ensure that this does not happen is to use pragma Detect_Blocking (see @RefSecNum{Pragma Detect_Blocking}).]} @end{Discussion} Certain language-defined subprograms are potentially blocking. In particular, the subprograms of the language-defined input-output packages that manipulate files (implicitly or explicitly) are potentially blocking. Other potentially blocking subprograms are identified where they are defined. When not specified as potentially blocking, a language-defined subprogram is nonblocking. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00178-01]} @ChgAdded{Version=[2],Text=[Any subprogram in a language-defined input-output package that has a file parameter or result or operates on a default file is considered to manipulate a file. An instance of a language-defined input-output generic package provides subprograms that are covered by this rule. The only subprograms in language-defined input-output packages not covered by this rule (and thus not potentially blocking) are the Get and Put routines that take string parameters defined in the packages nested in Text_IO.]}@ChgNote{This was the resolution of a ramification.} @end{Discussion} @end{Bounded} @begin{Notes} If two tasks both try to start a protected action on a protected object, and at most one is calling a protected function, then only one of the tasks can proceed. Although the other task cannot proceed, it is not considered blocked, and it might be consuming processing resources while it awaits its turn. There is no language-defined ordering or queuing presumed for tasks competing to start a protected action @em on a multiprocessor such tasks might use busy-waiting; for monoprocessor considerations, see @RefSec{Priority Ceiling Locking}. @begin{Discussion} The intended implementation on a multi-processor is in terms of @lquotes@;spin locks@rquotes@; @em the waiting task will spin. @end{Discussion} The body of a protected unit may contain declarations and bodies for local subprograms. These are not visible outside the protected unit. The body of a protected function can contain internal calls on other protected functions, but not protected procedures, because the current instance is a constant. On the other hand, the body of a protected procedure can contain internal calls on both protected functions and procedures. From within a protected action, an internal call on a protected subprogram, or an external call on a protected subprogram with a different target object is not considered a potentially blocking operation. @begin(Reason) This is because a task is not considered blocked while attempting to acquire the execution resource associated with a protected object. The acquisition of such a resource is rather considered part of the normal competition for execution resources between the various tasks that are ready. External calls that turn out to be on the same target object are considered potentially blocking, since they can deadlock the task indefinitely. @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[The @nt{pragma} Detect_Blocking may be used to ensure that all executions of potentially blocking operations during a protected action raise Program_Error. See @RefSecNum{Pragma Detect_Blocking}.]} @end{Notes} @begin{Examples} @leading@i{Examples of protected subprogram calls (see @RefSecNum(Protected Units and Protected Objects)):} @begin{Example} Shared_Array.Set_Component(N, E); E := Shared_Array.Component(M); Control.Release; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[Added a note pointing out the existence of @nt{pragma} Detect_Blocking. This pragma can be used to ensure portable (somewhat pessimistic) behavior of protected actions by converting the Bounded Error into a required check.]} @end{DiffWord95} @LabeledSubClause{Entries and Accept Statements} @begin{Intro} @nt<Entry_declaration>s, with the corresponding @ntf<entry_bodies> or @nt<accept_statement>s, are used to define potentially queued operations on tasks and protected objects. @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00397-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<entry_declaration>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}]>,Old=[]} @key{entry} @Syn2{defining_identifier} [(@Syn2{discrete_subtype_definition})] @Syn2{parameter_profile}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<accept_statement>,rhs=" @key{accept} @SynI{entry_}@Syn2{direct_name} [(@Syn2{entry_index})] @Syn2{parameter_profile} [@key{do} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{entry_}@Syn2{identifier}]];"} @begin{Reason} We cannot use @nt{defining_identifier} for @nt<accept_statement>s. Although an @nt{accept_statement} is sort of like a body, it can appear nested within a @nt{block_statement}, and therefore be hidden from its own entry by an outer homograph. @end{Reason} @Syn{lhs=<entry_index>,rhs="@Syn2{expression}"} @Syn{lhs=<entry_body>,rhs=" @key{entry} @Syn2{defining_identifier} @Syn2{entry_body_formal_part} @Syn2{entry_barrier} @key{is} @Syn2{declarative_part} @key{begin} @Syn2{handled_sequence_of_statements} @key{end} [@SynI{entry_}@Syn2{identifier}];"} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[We don't allow an @nt{overriding_indicator} on an @nt{entry_body} because entries always implement procedures at the point of the type declaration; there is no late implementation. And we don't want to have to think about @nt{overriding_indicator}s on @nt{accept_statement}s.]} @end{Discussion} @Syn{lhs=<entry_body_formal_part>, rhs="[(@Syn2{entry_index_specification})] @Syn2{parameter_profile}"} @Syn{lhs=<entry_barrier>, rhs="@key{when} @Syn2{condition}"} @Syn{lhs=<entry_index_specification>, rhs="@key{for} @Syn2{defining_identifier} @key{in} @Syn2{discrete_subtype_definition}"} @begin{SyntaxText} If an @SynI{entry_}@nt{identifier} appears at the end of an @nt{accept_statement}, it shall repeat the @SynI{entry_}@!@nt<direct_@!name>. If an @SynI{entry_}@!@nt{identifier} appears at the end of an @nt{entry_@!body}, it shall repeat the @nt{defining_@!identifier}. @Redundant[An @nt{entry_declaration} is allowed only in a protected or task declaration.] @begin(TheProof) This follows from the BNF. @end(TheProof) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is not allowed in an @nt{entry_declaration} that includes a @nt{discrete_subtype_definition}.]} @begin(Reason) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[An entry family can never implement something, so allowing an indicator is felt by the majority of the ARG to be redundant.]} @end(Reason) @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(accept_statement @i{entry_}@nt<direct_name>)} In an @nt<accept_statement>, the expected profile for the @SynI{entry_}@nt<direct_name> is that of the @nt<entry_@!declaration>; @PDefn2{Term=[expected type], Sec=(entry_index)} the expected type for an @nt<entry_index> is that of the subtype defined by the @nt<discrete_@!subtype_@!definition> of the corresponding @nt<entry_@!declaration>. Within the @nt<handled_sequence_of_statements> of an @nt<accept_statement>, if a @nt<selected_@!component> has a @nt<prefix> that denotes the corresponding @nt<entry_@!declaration>, then the entity denoted by the @nt<prefix> is the @nt<accept_@!statement>, and the @nt<selected_@!component> is interpreted as an expanded name (see @RefSecNum(Selected Components))@Redundant[; the @nt<selector_name> of the @nt<selected_@!component> has to be the @nt<identifier> for some formal parameter of the @nt<accept_@!statement>]. @begin{TheProof} The only declarations that occur immediately within the declarative region of an @nt<accept_statement> are those for its formal parameters. @end{TheProof} @end{Resolution} @begin{Legality} An @nt<entry_declaration> in a task declaration shall not contain a specification for an access parameter (see @RefSecNum(Access Types)). @begin(Reason) @leading@;Access parameters for task entries would require a complex implementation. For example: @begin(Example) @key(task) T @key(is) @key(entry) E(Z : @key(access) Integer); --@RI{ Illegal!} @key(end) T; @key(task body) T @key(is) @key(begin) @key(declare) @key(type) A @key(is access all) Integer; X : A; Int : @key(aliased) Integer; @key(task) Inner; @key(task body) Inner @key(is) @key(begin) T.E(Int'Access); @key(end) Inner; @key(begin) @key(accept) E(Z : @key(access) Integer) @key(do) X := A(Z); --@RI{ Accessibility_Check} @key(end) E; @key(end); @key(end) T; @end(Example) Implementing the Accessibility_Check inside the @nt<accept_statement> for E is difficult, since one does not know whether the entry caller is calling from inside the immediately enclosing declare block or from outside it. This means that the lexical nesting level associated with the designated object is not sufficient to determine whether the Accessibility_Check should pass or fail. Note that such problems do not arise with protected entries, because @ntf<entry_bodies> are always nested immediately within the @nt<protected_body>; they cannot be further nested as can @nt<accept_statement>s, nor can they be called from within the @nt<protected_body> (since no entry calls are permitted inside a @nt<protected_body>). @end(Reason) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If an @nt{entry_declaration} has an @nt{overriding_indicator}, then at the point of the declaration:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{overriding}, then the entry shall implement an inherited subprogram;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the @nt{overriding_indicator} is @key{not overriding}, then the entry shall not implement any inherited subprogram.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules are subtly different than those for subprograms (see @RefSecNum{Overriding Indicators}) because there cannot be @lquotes@;late@rquotes inheritance of primitives from interfaces. Hidden (that is, private) interfaces are prohibited explicitly (see @RefSecNum{Private Types and Private Extensions}), as are hidden primitive operations (as private operations of public abstract types are prohibited @em see @RefSecNum{Abstract Types and Subprograms}).]} @end{Discussion} For an @nt<accept_statement>, the innermost enclosing body shall be a @nt<task_body>, and the @i(entry_)@!@nt<direct_@!name> shall denote an @nt<entry_@!declaration> in the corresponding task declaration; the profile of the @nt{accept_@!statement} shall conform fully to that of the corresponding @nt<entry_@!declaration>. @Defn2{Term=[full conformance],Sec=(required)} An @nt<accept_@!statement> shall have a parenthesized @nt<entry_@!index> if and only if the corresponding @nt<entry_@!declaration> has a @nt<discrete_@!subtype_@!definition>. An @nt<accept_statement> shall not be within another @nt{accept_statement} that corresponds to the same @nt<entry_@!declaration>, nor within an @nt<asynchronous_@!select> inner to the enclosing @nt<task_body>. @begin(Reason) @nt<Accept_statement>s are required to be immediately within the enclosing @nt<task_body> (as opposed to being in a nested subprogram) to ensure that a nested task does not attempt to accept the entry of its enclosing task. We considered relaxing this restriction, either by making the check a run-time check, or by allowing a nested task to accept an entry of its enclosing task. However, neither change seemed to provide sufficient benefit to justify the additional implementation burden. Nested @nt<accept_statement>s for the same entry (or entry family) are prohibited to ensure that there is no ambiguity in the resolution of an expanded name for a formal parameter of the entry. This could be relaxed by allowing the inner one to hide the outer one from all visibility, but again the small added benefit didn't seem to justify making the change for Ada 95. @nt<Accept_statement>s are not permitted within @nt<asynchronous_select> statements to simplify the semantics and implementation: an @nt<accept_statement> in an @nt<abortable_part> could result in Tasking_Error being propagated from an entry call even though the target task was still callable; implementations that use multiple tasks implicitly to implement an @nt<asynchronous_select> might have trouble supporting "up-level" accepts. Furthermore, if @nt<accept_statement>s were permitted in the @nt<abortable_part>, a task could call its own entry and then accept it in the @nt<abortable_part>, leading to rather unusual and possibly difficult-to-specify semantics. @end(Reason) @PDefn2{Term=[requires a completion], Sec=(protected @nt{entry_declaration})} An @nt{entry_declaration} of a protected unit requires a completion@redundant[, which shall be an @nt{entry_body},] @PDefn2{Term=[only as a completion], Sec=(@nt<entry_body>)} and every @nt<entry_@!body> shall be the completion of an @nt<entry_@!declaration> of a protected unit. @PDefn2{Term=[completion legality], Sec=(@nt<entry_body>)} The profile of the @nt<entry_@!body> shall conform fully to that of the corresponding declaration. @Defn2{Term=[full conformance],Sec=(required)} @begin{Ramification} An @nt<entry_declaration>, unlike a @nt<subprogram_declaration>, cannot be completed with a @nt<renaming_@!declaration>. @end{Ramification} @begin(Honest) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[If],Old=[The completion can be a @nt{pragma} Import, if]} the implementation supports it@Chg{Version=[3],New=[, the entry body can be imported (using aspect Import, see @RefSecNum{Interfacing Aspects}), in which case no explicit @nt{entry_body} is allowed],Old=[]}. @end(Honest) @begin{Discussion} The above applies only to protected entries, which are the only ones completed with @ntf{entry_bodies}. Task entries have corresponding @nt{accept_statement}s instead of having @ntf{entry_bodies}, and we do not consider an @nt{accept_statement} to be a @lquotes@;completion,@rquotes@; because a task @nt{entry_declaration} is allowed to have zero, one, or more than one corresponding @nt{accept_statement}s. @end{Discussion} An @nt{entry_body_formal_part} shall have an @nt{entry_@!index_@!specification} if and only if the corresponding @nt{entry_@!declaration} has a @nt<discrete_@!subtype_@!definition>. In this case, the @nt<discrete_@!subtype_@!definition>s of the @nt<entry_@!declaration> and the @nt<entry_@!index_@!specification> shall fully conform to one another (see @RefSecNum(Conformance Rules)). @Defn2{Term=[full conformance],Sec=(required)} A name that denotes a formal parameter of an @nt<entry_body> is not allowed within the @nt<entry_barrier> of the @nt<entry_body>. @end{Legality} @begin{StaticSem} The parameter modes defined for parameters in the @nt<parameter_profile> of an @nt{entry_declaration} are the same as for a @nt<subprogram_declaration> and have the same meaning (see @RefSecNum(Formal Parameter Modes)). @begin{Discussion} Note that access parameters are not allowed for task entries (see above). @end{Discussion} @Defn2{Term=[family], Sec=(entry)} @Defn{entry family} @Defn{entry index subtype} An @nt<entry_declaration> with a @nt<discrete_subtype_definition> (see @RefSecNum(Array Types)) declares a @i(family) of distinct entries having the same profile, with one such entry for each value of the @i(entry index subtype) defined by the @nt<discrete_@!subtype_@!definition>. @Redundant[A name for an entry of a family takes the form of an @nt<indexed_component>, where the @nt<prefix> denotes the @nt<entry_declaration> for the family, and the index value identifies the entry within the family.] @Defn{single entry} @Defn2{Term=[entry], Sec=(single)} The term @i(single entry) is used to refer to any entry other than an entry of an entry family. In the @nt<entry_body> for an entry family, the @nt<entry_index_specification> declares a named constant whose subtype is the entry index subtype defined by the corresponding @nt<entry_declaration>; @Defn{named entry index} the value of the @i(named entry index) identifies which entry of the family was called. @begin{Ramification} The @nt<discrete_subtype_definition> of the @nt<entry_index_specification> is not elaborated; the subtype of the named constant declared is defined by the @nt<discrete_subtype_definition> of the corresponding @nt<entry_declaration>, which is elaborated, either when the type is declared, or when the object is created, if its constraint is per-object. @end{Ramification} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0002],ARef=[AI95-00171-01]} @PDefn2{Term=[elaboration], Sec=(entry_declaration)} @Chg{New=[The elaboration of an @nt<entry_declaration> for an entry family consists of the elaboration of the @nt<discrete_@!subtype_@!definition>, as described in @RefSecNum(Record Types).], Old=[For the elaboration of an @nt<entry_@!declaration> for an entry family, if the @nt{discrete_@!subtype_@!definition} contains no per-object expressions (see @RefSecNum(Record Types)), then the @nt<discrete_@!subtype_@!definition> is elaborated. Otherwise, the elaboration of the @nt<entry_@!declaration> consists of the evaluation of any expression of the @nt<discrete_@!subtype_@!definition> that is not a per-object expression (or part of one).]} The elaboration of an @nt<entry_@!declaration> for a single entry has no effect. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The elaboration of the declaration of a protected subprogram has no effect, as specified in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum(Subprogram Declarations). The default initialization of an object of a task or protected type is covered in @RefSecNum(Object Declarations). @end{Discussion} @Redundant[The actions to be performed when an entry is called are specified by the corresponding @nt{accept_@!statement}s (if any) for an entry of a task unit, and by the corresponding @nt<entry_@!body> for an entry of a protected unit.] @PDefn2{Term=[execution], Sec=(accept_statement)} For the execution of an @nt{accept_statement}, the @nt<entry_index>, if any, is first evaluated and converted to the entry index subtype; this index value identifies which entry of the family is to be accepted. @PDefn2{Term=[implicit subtype conversion],Sec=(entry index)} @PDefn2{Term=[blocked], Sec=(on an @nt<accept_statement>)} @Defn2{Term=[selection], Sec=(of an entry caller)} Further execution of the @nt<accept_statement> is then blocked until a caller of the corresponding entry is selected (see @RefSecNum(Entry Calls)), whereupon the @nt<handled_sequence_of_statements>, if any, of the @nt<accept_statement> is executed, with the formal parameters associated with the corresponding actual parameters of the selected entry call. Upon completion of the @nt<handled_sequence_of_statements>, the @nt<accept_statement> completes and is left. When an exception is propagated from the @nt{handled_sequence_of_statements} of an @nt{accept_statement}, the same exception is also raised by the execution of the corresponding @nt{entry_call_statement}. @begin{Ramification} This is in addition to propagating it to the construct containing the @nt{accept_statement}. In other words, for a rendezvous, the raising splits in two, and continues concurrently in both tasks. The caller gets a new occurrence; this isn't considered propagation. Note that we say @lquotes@;propagated from the @nt{handled_sequence_of_statements} of an @nt{accept_statement}@rquotes@;, not @lquotes@;propagated from an @nt{accept_statement}.@rquotes@; The latter would be wrong @em we don't want exceptions propagated by the @nt<entry_index> to be sent to the caller (there is none yet!). @end{Ramification} @Defn{rendezvous} The above interaction between a calling task and an accepting task is called a @i(rendezvous). @Redundant[After a rendezvous, the two tasks continue their execution independently.] @Redundant[An @nt<entry_body> is executed when the @nt<condition> of the @nt<entry_barrier> evaluates to True and a caller of the corresponding single entry, or entry of the corresponding entry family, has been selected (see @RefSecNum(Entry Calls)).] @PDefn2{Term=[execution], Sec=(entry_body)} For the execution of the @nt<entry_@!body>, the @nt<declarative_@!part> of the @nt<entry_@!body> is elaborated, and the @nt<handled_@!sequence_of_@!statements> of the body is executed, as for the execution of a @nt<subprogram_body>. The value of the named entry index, if any, is determined by the value of the entry index specified in the @i(entry_)@nt<name> of the selected entry call (or intermediate @nt<requeue_@!statement> @em see @RefSecNum(Requeue Statements)). @begin(Honest) If the entry had been renamed as a subprogram, and the call was a @nt<procedure_call_statement> using the name declared by the renaming, the entry index (if any) comes from the entry @nt<name> specified in the @nt<subprogram_renaming_declaration>. @end(Honest) @end{RunTime} @begin{Notes} A task entry has corresponding accept_statements (zero or more), whereas a protected entry has a corresponding entry_body (exactly one). A consequence of the rule regarding the allowed placements of @nt{accept_statement}s is that a task can execute @nt{accept_statement}s only for its own entries. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} A @Chg{Version=[2],New=[return statement],Old=[@nt{return_statement}]} (see @RefSecNum(Return Statements)) or a @nt<requeue_statement> (see @RefSecNum(Requeue Statements)) may be used to complete the execution of an @nt<accept_statement> or an @nt<entry_body>. @begin{Ramification} An @nt<accept_statement> need not have a @nt<handled_sequence_of_statements> even if the corresponding entry has parameters. Equally, it can have a @nt<handled_sequence_of_statements> even if the corresponding entry has no parameters. @end{Ramification} @begin{Ramification} A single entry overloads a subprogram, an enumeration literal, or another single entry if they have the same @nt{defining_identifier}. Overloading is not allowed for entry family names. A single entry or an entry of an entry family can be renamed as a procedure as explained in @RefSecNum{Subprogram Renaming Declarations}. @end{Ramification} The @nt<condition> in the @nt{entry_barrier} may reference anything visible except the formal parameters of the entry. This includes the entry index (if any), the components (including discriminants) of the protected object, the Count attribute of an entry of that protected object, and data global to the protected unit. @NoPrefix@;The restriction against referencing the formal parameters within an @nt{entry_barrier} ensures that all calls of the same entry see the same barrier value. If it is necessary to look at the parameters of an entry call before deciding whether to handle it, the @nt<entry_barrier> can be @lquotes@;@key(when) True@rquotes@; and the caller can be requeued (on some private entry) when its parameters indicate that it cannot be handled immediately. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of entry declarations:} @begin{Example} @key(entry) Read(V : @key(out) Item); @key(entry) Seize; @key(entry) Request(Level)(D : Item); --@RI[ a family of entries] @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of accept statements:} @end{WideAbove} @begin{Example} @key(accept) Shut_Down; @key(accept) Read(V : @key(out) Item) @key(do) V := Local_Item; @key(end) Read; @key(accept) Request(Low)(D : Item) @key(do) ... @key(end) Request; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{entry_body} is new. @nt{Accept_statement}s can now have @nt{exception_handler}s. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the elaboration of per-object constraints.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[@nt{Overriding_indicator}s can be used on entries; this is only useful when a task or protected type inherits from an interface.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in an @nt{entry_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{Entry Calls} @begin{Intro} @Defn{entry call} @Redundant[An @nt<entry_call_statement> (an @i(entry call)) can appear in various contexts.] @Defn{simple entry call} @Defn2{Term={entry call}, Sec=(simple)} A @i(simple) entry call is a stand-alone statement that represents an unconditional call on an entry of a target task or a protected object. @Redundant[Entry calls can also appear as part of @nt<select_statement>s (see @RefSecNum(Select Statements)).] @end{Intro} @begin{Syntax} @Syn{lhs=<entry_call_statement>,rhs="@SynI{entry_}@Syn2{name} [@Syn2{actual_parameter_part}];"} @end{Syntax} @begin{Resolution} The @i(entry_)@nt<name> given in an @nt<entry_call_statement> shall resolve to denote an entry. The rules for parameter associations are the same as for subprogram calls (see @RefSecNum(Subprogram Calls) and @RefSecNum(Parameter Associations)). @end{Resolution} @begin{StaticSem} @Redundant[The @i(entry_)@nt<name> of an @nt<entry_call_statement> specifies (explicitly or implicitly) the target object of the call, the entry or entry family, and the entry index, if any (see @RefSecNum(Intertask Communication)).] @end{StaticSem} @begin{RunTime} @leading@Defn{open entry} @Defn2{Term=[entry], Sec=(open)} @Defn{closed entry} @Defn2{Term=[entry], Sec=(closed)} Under certain circumstances (detailed below), an entry of a task or protected object is checked to see whether it is @i(open) or @i(closed): @begin(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn2{Term=[open entry], Sec=(of a task)} @Defn2{Term=[closed entry], Sec=(of a task)} An entry of a task is open if the task is blocked on an @nt<accept_statement> that corresponds to the entry (see @RefSecNum(Entries and Accept Statements)), or on a @nt<selective_accept> (see @RefSecNum(Selective Accept)) with an open @nt<accept_alternative> that corresponds to the entry; otherwise@Chg{Version=[3],New=[,],Old=[]} it is closed. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn2{Term=[open entry], Sec=(of a protected object)} @Defn2{Term=[closed entry], Sec=(of a protected object)} An entry of a protected object is open if the @nt<condition> of the @nt<entry_barrier> of the corresponding @nt<entry_body> evaluates to True; otherwise@Chg{Version=[3],New=[,],Old=[]} it is closed. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the evaluation of the @nt<condition> propagates an exception, the exception Program_Error is propagated to all current callers of all entries of the protected object. @begin(Reason) An exception during barrier evaluation is considered essentially a fatal error. All current entry callers are notified with a Program_Error. In a fault-tolerant system, a protected object might provide a Reset protected procedure, or equivalent, to support attempts to restore such a "broken" protected object to a reasonable state. @end(Reason) @end(Itemize) @begin(Discussion) Note that the definition of when a task entry is open is based on the state of the (accepting) task, whereas the "openness" of a protected entry is defined only when it is explicitly checked, since the barrier expression needs to be evaluated. Implementation permissions are given (below) to allow implementations to evaluate the barrier expression more or less often than it is checked, but the basic semantic model presumes it is evaluated at the times when it is checked. @end(Discussion) @leading@PDefn2{Term=[execution], Sec=(entry_call_statement)} For the execution of an @nt{entry_call_statement}, evaluation of the @nt<name> and of the parameter associations is as for a subprogram call (see @RefSecNum{Subprogram Calls}). @Defn2{Term=[issue], Sec=(an entry call)} The entry call is then @i(issued): For a call on an entry of a protected object, a new protected action is started on the object (see @RefSecNum(Protected Subprograms and Protected Actions)). The named entry is checked to see if it is open; @Defn2{Term=[select an entry call], Sec=(immediately)} if open, the entry call is said to be @i(selected immediately), and the execution of the call proceeds as follows: @begin(Itemize) For a call on an open entry of a task, the accepting task becomes ready and continues the execution of the corresponding @nt<accept_statement> (see @RefSecNum(Entries and Accept Statements)). For a call on an open entry of a protected object, the corresponding @nt<entry_body> is executed (see @RefSecNum(Entries and Accept Statements)) as part of the protected action. @end(Itemize) If the @nt<accept_statement> or @nt<entry_body> completes other than by a requeue (see @RefSecNum(Requeue Statements)), return is made to the caller (after servicing the entry queues @em see below); any necessary assigning back of formal to actual parameters occurs, as for a subprogram call (see @RefSecNum(Parameter Associations)); such assignments take place outside of any protected action. @begin(Ramification) The return to the caller will generally not occur until the protected action completes, unless some other thread of control is given the job of completing the protected action and releasing the associated execution resource. @end(Ramification) If the named entry is closed, the entry call is added to an @i(entry queue) (as part of the protected action, for a call on a protected entry), and the call remains queued until it is selected or cancelled; @Defn{entry queue} there is a separate (logical) entry queue for each entry of a given task or protected object @Redundant[(including each entry of an entry family)]. @Leading@Defn2{Term=[service], Sec=(an entry queue)} @Defn2{Term=[select an entry call], Sec=(from an entry queue)} When a queued call is @i{selected}, it is removed from its entry queue. Selecting a queued call from a particular entry queue is called @i{servicing} the entry queue. An entry with queued calls can be serviced under the following circumstances: @begin(Itemize) When the associated task reaches a corresponding @nt<accept_statement>, or a @nt<selective_accept> with a corresponding open @nt<accept_alternative>; If after performing, as part of a protected action on the associated protected object, an operation on the object other than a call on a protected function, the entry is checked and found to be open. @end(Itemize) @Defn2{Term=[select an entry call], Sec=(from an entry queue)} If there is at least one call on a queue corresponding to an open entry, then one such call is selected according to the @i(entry queuing policy) in effect (see below), and the corresponding @nt<accept_statement> or @nt<entry_body> is executed as above for an entry call that is selected immediately. @Defn{entry queuing policy} The entry queuing policy controls selection among queued calls both for task and protected entry queues. @Defn{default entry queuing policy} @Defn2{Term=[entry queuing policy], Sec=(default policy)} The default entry queuing policy is to select calls on a given entry queue in order of arrival. If calls from two or more queues are simultaneously eligible for selection, the default entry queuing policy does not specify which queue is serviced first. Other entry queuing policies can be specified by @nt{pragma}s (see @RefSecNum(Entry Queuing Policies)). For a protected object, the above servicing of entry queues continues until there are no open entries with queued calls, at which point the protected action completes. @begin(Discussion) While servicing the entry queues of a protected object, no new calls can be added to any entry queue of the object, except due to an internal requeue (see @RefSecNum(Requeue Statements)). This is because the first step of a call on a protected entry is to start a new protected action, which implies acquiring (for exclusive read-write access) the execution resource associated with the protected object, which cannot be done while another protected action is already in progress. @end(Discussion) @PDefn2{Term=[blocked], Sec=(during an entry call)} For an entry call that is added to a queue, and that is not the @nt<triggering_statement> of an @nt<asynchronous_@!select> (see @RefSecNum{Asynchronous Transfer of Control}), the calling task is blocked until the call is cancelled, or the call is selected and a corresponding @nt<accept_statement> or @nt<entry_body> completes without requeuing. In addition, the calling task is blocked during a rendezvous. @begin{Ramification} For a call on a protected entry, the caller is not blocked if the call is selected immediately, unless a requeue causes the call to be queued. @end{Ramification} @Defn2{Term=[cancellation], Sec=(of an entry call)} An attempt can be made to cancel an entry call upon an abort (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)) and as part of certain forms of @nt<select_statement> (see @RefSecNum(Timed Entry Calls), @RefSecNum(Conditional Entry Calls), and @RefSecNum(Asynchronous Transfer of Control)). The cancellation does not take place until a point (if any) when the call is on some entry queue, and not protected from cancellation as part of a requeue (see @RefSecNum(Requeue Statements)); at such a point, the call is removed from the entry queue and the call completes due to the cancellation. The cancellation of a call on an entry of a protected object is a protected action@Redundant[, and as such cannot take place while any other protected action is occurring on the protected object. Like any protected action, it includes servicing of the entry queues (in case some entry barrier depends on a Count attribute).] @begin(ImplNote) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} In the case of an attempted cancellation due to abort, this removal might have to be performed by the calling task itself if the ceiling priority of the protected object is lower than the @Chg{Version=[2],New=[priority of the ],Old=[]}task initiating the abort. @end(ImplNote) @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} A call on an entry of a task that has already completed its execution raises the exception Tasking_Error at the point of the call; similarly, this exception is raised at the point of the call if the called task completes its execution or becomes abnormal before accepting the call or completing the rendezvous (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). This applies equally to a simple entry call and to an entry call as part of a @nt<select_statement>. @end{RunTime} @begin{ImplPerm} An implementation may perform the sequence of steps of a protected action using any thread of control; it need not be that of the task that started the protected action. If an @nt<entry_body> completes without requeuing, then the corresponding calling task may be made ready without waiting for the entire protected action to complete. @begin(Reason) These permissions are intended to allow flexibility for implementations on multiprocessors. On a monoprocessor, which thread of control executes the protected action is essentially invisible, since the thread is not abortable in any case, and the "current_task" function is not guaranteed to work during a protected action (see @Chg{Version=[2],New=[@RefSecNum(The Package Task_Identification)], Old=[@RefSecNum(Task Information)]}). @end(Reason) When the entry of a protected object is checked to see whether it is open, the implementation need not reevaluate the @nt<condition> of the corresponding @nt<entry_barrier> if no variable or attribute referenced by the @nt<condition> (directly or indirectly) has been altered by the execution (or cancellation) of a protected procedure or entry call on the object since the @nt<condition> was last evaluated. @begin(Ramification) Changes to variables referenced by an entry barrier that result from actions outside of a protected procedure or entry call on the protected object need not be "noticed." For example, if a global variable is referenced by an entry barrier, it should not be altered (except as part of a protected action on the object) any time after the barrier is first evaluated. In other words, globals can be used to "parameterize" a protected object, but they cannot reliably be used to control it after the first use of the protected object. @end(Ramification) @begin{ImplNote} Note that even if a global variable is volatile, the implementation need only reevaluate a barrier if the global is updated during a protected action on the protected object. This ensures that an entry-open bit-vector implementation approach is possible, where the bit-vector is computed at the end of a protected action, rather than upon each entry call. @end{ImplNote} An implementation may evaluate the @nt<condition>s of all @nt<entry_barrier>s of a given protected object any time any entry of the object is checked to see if it is open. @begin(Ramification) In other words, any side effects of evaluating an entry barrier should be innocuous, since an entry barrier might be evaluated more or less often than is implied by the "official" dynamic semantics. @end(Ramification) @begin(ImplNote) It is anticipated that when the number of entries is known to be small, all barriers will be evaluated any time one of them needs to be, to produce an "entry-open bit-vector." The appropriate bit will be tested when the entry is called, and only if the bit is false will a check be made to see whether the bit-vector might need to be recomputed. This should allow an implementation to maximize the performance of a call on an open entry, which seems like the most important case. In addition to the entry-open bit-vector, an "is-valid" bit is needed per object, which indicates whether the current bit-vector setting is valid. A "depends-on-Count-attribute" bit is needed per type. The "is-valid" bit is set to false (as are all the bits of the bit-vector) when the protected object is first created, as well as any time an exception is propagated from computing the bit-vector. Is-valid would also be set false any time the Count is changed and "depends-on-Count-attribute" is true for the type, or a protected procedure or entry returns indicating it might have updated a variable referenced in some barrier. A single procedure can be compiled to evaluate all of the barriers, set the entry-open bit-vector accordingly, and set the is-valid bit to true. It could have a "when others" handler to set them all false, and call a routine to propagate Program_Error to all queued callers. For protected types where the number of entries is not known to be small, it makes more sense to evaluate a barrier only when the corresponding entry is checked to see if it is open. It isn't worth saving the state of the entry between checks, because of the space that would be required. Furthermore, the entry queues probably want to take up space only when there is actually a caller on them, so rather than an array of all entry queues, a linked list of nonempty entry queues make the most sense in this case, with the first caller on each entry queue acting as the queue header. @end(ImplNote) When an attempt is made to cancel an entry call, the implementation need not make the attempt using the thread of control of the task (or interrupt) that initiated the cancellation; in particular, it may use the thread of control of the caller itself to attempt the cancellation, even if this might allow the entry call to be selected in the interim. @begin{Reason} Because cancellation of a protected entry call is a protected action (which helps make the Count attribute of a protected entry meaningful), it might not be practical to attempt the cancellation from the thread of control that initiated the cancellation. For example, if the cancellation is due to the expiration of a delay, it is unlikely that the handler of the timer interrupt could perform the necessary protected action itself (due to being on the interrupt level). Similarly, if the cancellation is due to an abort, it is possible that the task initiating the abort has a priority higher than the ceiling priority of the protected object (for implementations that support ceiling priorities). Similar considerations could apply in a multiprocessor situation. @end{Reason} @end{ImplPerm} @begin{Notes} If an exception is raised during the execution of an @nt{entry_body}, it is propagated to the corresponding caller (see @RefSecNum(Exception Handling)). For a call on a protected entry, the entry is checked to see if it is open prior to queuing the call, and again thereafter if its Count attribute (see @RefSecNum{Task and Entry Attributes}) is referenced in some entry barrier. @begin(Ramification) Given this, extra care is required if a reference to the Count attribute of an entry appears in the entry's own barrier. @end(Ramification) @begin(Reason) An entry is checked to see if it is open prior to queuing to maximize the performance of a call on an open entry. @end(Reason) In addition to simple entry calls, the language permits timed, conditional, and asynchronous entry calls (see @RefSecNum(Timed Entry Calls), @RefSecNum(Conditional Entry Calls), and see @RefSecNum(Asynchronous Transfer of Control)). @begin{Ramification} A task can call its own entries, but the task will deadlock if the call is a simple entry call. @end{Ramification} The @nt<condition> of an @nt<entry_barrier> is allowed to be evaluated by an implementation more often than strictly necessary, even if the evaluation might have side effects. On the other hand, an implementation need not reevaluate the @nt<condition> if nothing it references was updated by an intervening protected action on the protected object, even if the @nt<condition> references some global variable that might have been updated by an action performed from outside of a protected action. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of entry calls:} @begin{Example} Agent.Shut_Down; --@RI[ see @RefSecNum(Task Units and Task Objects)] Parser.Next_Lexeme(E); --@RI[ see @RefSecNum(Task Units and Task Objects)] Pool(5).Read(Next_Char); --@RI[ see @RefSecNum(Task Units and Task Objects)] Controller.Request(Low)(Some_Item); --@RI[ see @RefSecNum(Task Units and Task Objects)] Flags(3).Seize; --@RI[ see @RefSecNum(Protected Units and Protected Objects)] @end{Example} @end{Examples} @LabeledSubClause{Requeue Statements} @begin{Intro} @redundant[A @nt<requeue_statement> can be used to complete an @nt<accept_statement> or @nt<entry_body>, while redirecting the corresponding entry call to a new (or the same) entry queue. @Defn{requeue} Such a @i(requeue) can be performed with or without allowing an intermediate cancellation of the call, due to an abort or the expiration of a delay. @IndexSee{Term=[preference control],See=(requeue)} @IndexSee{Term=[broadcast signal],See=(requeue)}] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2]} @Syn{lhs=<requeue_statement>, rhs="@key{requeue} @SynI{@Chg{Version=[3],New=[procedure_or_entry_],Old=[entry_]}}@Syn2{name} [@key{with} @key{abort}];"} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @Chg{Version=[3],New=[@Defn{requeue target}],Old=[@Defn2{Term=[target entry], Sec=(of a @nt<requeue_statement>)}]} The @Chg{Version=[3],New=[@SynI{procedure_or_entry_}],Old=[@SynI(entry_)]}@nt{name} of a @nt{requeue_statement} shall resolve to denote @Chg{Version=[3],New=[a procedure or ],Old=[]}an entry (the @Chg{Version=[3],New=[@i{requeue }],Old=[]}@i{target}@Chg{Version=[3],New=[], Old=[@i{ entry}]})@Chg{Version=[3],New=[. The profile of the entry, or the profile or prefixed profile of the procedure, shall],Old=[that]} either @Chg{Version=[3],New=[have],Old=[has]} no parameters, or @Chg{Version=[3], New=[be],Old=[that has a profile that is]} type conformant (see @RefSecNum(Conformance Rules)) with the profile of the innermost enclosing @nt<entry_@!body> or @nt<accept_@!statement>. @Defn2{Term=[type conformance],Sec=(required)} @end{Resolution} @begin{Legality} A @nt{requeue_statement} shall be within a callable construct that is either an @nt{entry_body} or an @nt{accept_statement}, and this construct shall be the innermost enclosing body or callable construct. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} If the @Chg{Version=[3],New=[requeue ],Old=[]}target@Chg{Version=[3],New=[],Old=[ entry]} has parameters, then its @Chg{Version=[3],New=[(prefixed) ],Old=[]}profile shall be subtype conformant with the profile of the innermost enclosing callable construct. @Defn2{Term=[subtype conformance],Sec=(required)} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[If the target is a procedure, the name shall denote a renaming of an entry, or shall denote a view or a prefixed view of a primitive subprogram of a synchronized interface, where the first parameter of the unprefixed view of the primitive subprogram shall be a controlling parameter, and the Synchronization aspect shall be specified with @nt{synchronization_kind} By_Entry for the primitive subprogram.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2]} @PDefn2{Term=[accessibility rule],Sec=(requeue statement)} In a @nt<requeue_statement> of an @nt<accept_statement> of some task unit, either the target object shall be a part of a formal parameter of the @nt<accept_statement>, or the accessibility level of the target object shall not be equal to or statically deeper than any enclosing @nt<accept_statement> of the task unit. In a @nt<requeue_@!statement> of an @nt<entry_@!body> of some protected unit, either the target object shall be a part of a formal parameter of the @nt<entry_@!body>, or the accessibility level of the target object shall not be statically deeper than that of the @nt<entry_declaration>@Chg{Version=[3],New=[ for the @nt{entry_body}],Old=[]}. @begin{Ramification} In the @nt{entry_body} case, the intent is that the target object can be global, or can be a component of the protected unit, but cannot be a local variable of the @nt{entry_body}. @end{Ramification} @begin(Reason) These restrictions ensure that the target object of the requeue outlives the completion and finalization of the enclosing callable construct. They also prevent requeuing from a nested @nt<accept_statement> on a parameter of an outer @nt<accept_statement>, which could create some strange "long-distance" connections between an entry caller and its server. Note that in the strange case where a @nt<task_body> is nested inside an @nt<accept_statement>, it is permissible to requeue from an @nt<accept_statement> of the inner @nt<task_body> on parameters of the outer @nt<accept_statement>. This is not a problem because all calls on the inner task have to complete before returning from the outer @nt<accept_statement>, meaning no "dangling calls" will be created. @end(Reason) @begin(ImplNote) By disallowing certain requeues, we ensure that the normal @nt<terminate_alternative> rules remain sensible, and that explicit clearing of the entry queues of a protected object during finalization is rarely necessary. In particular, such clearing of the entry queues is necessary only (ignoring premature Unchecked_Deallocation) for protected objects declared in a @nt<task_body> (or created by an allocator for an access type declared in such a body) containing one or more @nt<requeue_statement>s. Protected objects declared in subprograms, or at the library level, will never need to have their entry queues explicitly cleared during finalization. @end(ImplNote) @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2]} @PDefn2{Term=[execution], Sec=(requeue_statement)} The execution of a @nt{requeue_statement} proceeds by first evaluating the @Chg{Version=[3],New=[@SynI{procedure_or_entry_}],Old=[@SynI(entry_)]}@nt<name>@Redundant[, including the @nt<prefix> identifying the target task or protected object and the @nt<expression> identifying the entry within an entry family, if any]. The @nt{entry_body} or @nt{accept_statement} enclosing the @nt{requeue_statement} is then completed@Redundant[, finalized, and left (see @RefSecNum(Completion and Finalization))]. @PDefn2{Term=[execution], Sec=(requeue task entry)} For the execution of a requeue on an entry of a target task, after leaving the enclosing callable construct, the named entry is checked to see if it is open and the requeued call is either selected immediately or queued, as for a normal entry call (see @RefSecNum(Entry Calls)). @leading@PDefn2{Term=[execution], Sec=(requeue protected entry)} For the execution of a requeue on an entry of a target protected object, after leaving the enclosing callable construct: @begin(Itemize) if the requeue is an internal requeue (that is, the requeue is back on an entry of the same protected object @em see @RefSecNum(Intertask Communication)), the call is added to the queue of the named entry and the ongoing protected action continues (see @RefSecNum(Protected Subprograms and Protected Actions)); @begin(Ramification) Note that for an internal requeue, the call is queued without checking whether the target entry is open. This is because the entry queues will be serviced before the current protected action completes anyway, and considering the requeued call immediately might allow it to "jump" ahead of existing callers on the same queue. @end(Ramification) if the requeue is an external requeue (that is, the target protected object is not implicitly the same as the current object @em see @RefSecNum(Intertask Communication)), a protected action is started on the target object and proceeds as for a normal entry call (see @RefSecNum(Entry Calls)). @end(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0030-2]} If the @Chg{Version=[3],New=[requeue target],Old=[new entry]} named in the @nt<requeue_statement> has formal parameters, then during the execution of the @nt<accept_statement> or @nt<entry_body> corresponding to the new entry, the formal parameters denote the same objects as did the corresponding formal parameters of the callable construct completed by the requeue. @Redundant[In any case, no parameters are specified in a @nt<requeue_statement>; any parameter passing is implicit.] @leading@Defn{requeue-with-abort} If the @nt<requeue_statement> includes the reserved words @key(with abort) (it is a @i(requeue-with-abort)), then: @begin(Itemize) if the original entry call has been aborted (see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)), then the requeue acts as an abort completion point for the call, and the call is cancelled and no requeue is performed; if the original entry call was timed (or conditional), then the original expiration time is the expiration time for the requeued call. @end(Itemize) If the reserved words @key(with abort) do not appear, then the call remains protected against cancellation while queued as the result of the @nt<requeue_statement>. @begin(Ramification) This protection against cancellation lasts only until the call completes or a subsequent requeue-with-abort is performed on the call. @end(Ramification) @begin(Reason) We chose to protect a requeue, by default, against abort or cancellation. This seemed safer, since it is likely that extra steps need to be taken to allow for possible cancellation once the servicing of an entry call has begun. This also means that in the absence of @key(with abort) the usual Ada 83 behavior is preserved, namely that once an entry call is accepted, it cannot be cancelled until it completes. @end(Reason) @end{RunTime} @begin{Notes} A requeue is permitted from a single entry to an entry of an entry family, or vice-versa. The entry index, if any, plays no part in the subtype conformance check between the profiles of the two entries; an entry index is part of the @i(entry_)@nt<name> for an entry of a family. @PDefn{subtype conformance} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of requeue statements:} @begin{Example} @key[requeue] Request(Medium) @key[with abort]; --@RI[ requeue on a member of an entry family of the current task, see @RefSecNum{Task Units and Task Objects}] @key[requeue] Flags(I).Seize; --@RI[ requeue on an entry of an array component, see @RefSecNum{Protected Units and Protected Objects}] @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The @nt<requeue_statement> is new. @end{Extend83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0030-2],ARef=[AI05-0215-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added the ability to requeue on operations of synchronized interfaces that are declared to be an entry.]} @end{Extend2005} @LabeledClause{Delay Statements, Duration, and Time} @begin{Intro} @redundant[@PDefn{expiration time} A @nt<delay_statement> is used to block further execution until a specified @i(expiration time) is reached. The expiration time can be specified either as a particular point in time (in a @nt<delay_@!until_@!statement>), or in seconds from the current time (in a @nt<delay_@!relative_@!statement>). The language-defined package Calendar provides definitions for a type Time and associated operations, including a function Clock that returns the current time. @IndexSee{Term=[timing],See=(delay_statement)}] @end{Intro} @begin{Syntax} @Syn{lhs=<delay_statement>, rhs="@Syn2{delay_until_statement} | @Syn2{delay_relative_statement}"} @Syn{lhs=<delay_until_statement>, rhs="@key{delay until} @SynI(delay_)@Syn2{expression};"} @Syn{lhs=<delay_relative_statement>, rhs="@key{delay} @SynI(delay_)@Syn2{expression};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(delay_relative_statement expression)} The expected type for the @i(delay_)@nt{expression} in a @nt{delay_relative_statement} is the predefined type Duration. @PDefn2{Term=[expected type], Sec=(delay_until_statement expression)} The @i(delay_)@nt<expression> in a @nt<delay_until_statement> is expected to be of any nonlimited type. @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @Defn{time type} @Defn{time base} @Defn{clock} There can be multiple time bases, each with a corresponding clock, and a corresponding @i{time type}. The type of the @i(delay_)@nt<expression> in a @nt{delay_until_statement} shall be a time type @em either the type Time defined in the language-defined package Calendar (see below),@Chg{Version=[3],New=[ the type Time in the package Real_Time (see @RefSecNum(Monotonic Time)),],Old=[]} or some other implementation-defined time type@Chg{Version=[3],New=[],Old=[ (see @RefSecNum(Monotonic Time))]}. @ImplDef{Any implementation-defined time types.} @end{Legality} @begin{StaticSem} @Redundant[There is a predefined fixed point type named Duration, declared in the visible part of package Standard;] a value of type Duration is used to represent the length of an interval of time, expressed in seconds. @Redundant[The type Duration is not specific to a particular time base, but can be used with any time base.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} A value of the type Time in package Calendar, or of some other @Chg{Version=[3],New=[],Old=[implementation-defined ]}time type, represents a time as reported by a corresponding clock. @leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChildUnit{Parent=[Ada],Child=[Calendar]} @key(package) Ada.Calendar @key(is) @key(type) @AdaTypeDefn{Time} @key(is) @key(private); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} @key(subtype) @AdaSubtypeDefn{Name=[Year_Number],Of=[Integer]} @key(is) Integer @key(range) 1901 .. @Chg{Version=[2],New=[2399],Old=[2099]}; @key(subtype) @AdaSubtypeDefn{Name=[Month_Number],Of=[Integer]} @key(is) Integer @key(range) 1 .. 12; @key(subtype) @AdaSubtypeDefn{Name=[Day_Number],Of=[Integer]} @key(is) Integer @key(range) 1 .. 31; @key(subtype) @AdaSubtypeDefn{Name=[Day_Duration],Of=[Duration]} @key(is) Duration @key(range) 0.0 .. 86_400.0; @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[A range of 500 years was chosen, as that only requires one extra bit for the year as compared to Ada 95. This was done to minimize disruptions with existing implementations. (One implementor reports that their time values represent nanoseconds, and this year range requires 63.77 bits to represent.)]} @end{Reason} @key(function) @AdaSubDefn{Clock} @key(return) Time; @key(function) @AdaSubDefn{Year} (Date : Time) @key(return) Year_Number; @key(function) @AdaSubDefn{Month} (Date : Time) @key(return) Month_Number; @key(function) @AdaSubDefn{Day} (Date : Time) @key(return) Day_Number; @key(function) @AdaSubDefn{Seconds}(Date : Time) @key(return) Day_Duration; @key(procedure) @AdaSubDefn{Split} (Date : @key(in) Time; Year : @key(out) Year_Number; Month : @key(out) Month_Number; Day : @key(out) Day_Number; Seconds : @key(out) Day_Duration); @key(function) @AdaSubDefn{Time_Of}(Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0) @key(return) Time; @key(function) "+" (Left : Time; Right : Duration) @key(return) Time; @key(function) "+" (Left : Duration; Right : Time) @key(return) Time; @key(function) "-" (Left : Time; Right : Duration) @key(return) Time; @key(function) "-" (Left : Time; Right : Time) @key(return) Duration; @key(function) "<" (Left, Right : Time) @key(return) Boolean; @key(function) "<="(Left, Right : Time) @key(return) Boolean; @key(function) ">" (Left, Right : Time) @key(return) Boolean; @key(function) ">="(Left, Right : Time) @key(return) Boolean; @AdaExcDefn{Time_Error} : @key(exception;) @key(private) ... -- @RI{not specified by the language} @key(end) Ada.Calendar; @end{Example} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(delay_statement)} For the execution of a @nt<delay_statement>, the @i(delay_)@nt<expression> is first evaluated. @Defn2{Term=[expiration time], Sec=(for a @nt<delay_until_statement>)} For a @nt<delay_until_statement>, the expiration time for the delay is the value of the @i(delay_)@nt<expression>, in the time base associated with the type of the @nt<expression>. @Defn2{Term=[expiration time], Sec=(for a @nt<delay_relative_statement>)} For a @nt<delay_relative_statement>, the expiration time is defined as the current time, in the time base associated with relative delays, plus the value of the @i(delay_)@nt<expression> converted to the type Duration, and then rounded up to the next clock tick. @PDefn2{Term=[implicit subtype conversion],Sec=(delay expression)} The time base associated with relative delays is as defined in @RefSec{Delay Accuracy} or is implementation defined. @ImplDef{The time base associated with relative delays.} @begin{Ramification} Rounding up to the next clock tick means that the reading of the delay-relative clock when the delay expires should be no less than the current reading of the delay-relative clock plus the specified duration. @end{Ramification} @PDefn2{Term=[blocked], Sec=(on a @nt<delay_statement>)} The task executing a @nt<delay_statement> is blocked until the expiration time is reached, at which point it becomes ready again. If the expiration time has already passed, the task is not blocked. @begin(Discussion) For a @nt<delay_relative_statement>, this case corresponds to when the value of the @i(delay_)@nt<expression> is zero or negative. Even though the task is not blocked, it might be put back on the end of its ready queue. See @RefSec(Priority Scheduling). @end(Discussion) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @Defn2{Term=[cancellation], Sec=(of a @nt<delay_statement>)} If an attempt is made to @i(cancel) the @nt<delay_statement> @Redundant[(as part of an @nt<asynchronous_@!select> or abort @em see @RefSecNum{Asynchronous Transfer of Control} and @RefSecNum{Abort of a Task - Abort of a Sequence of Statements})], the @Chg{Version=[3],New=[statement],Old=[@ntf<_statement>]} is cancelled if the expiration time has not yet passed, thereby completing the @nt<delay_statement>. @begin(Reason) This is worded this way so that in an @nt<asynchronous_select> where the @nt<triggering_statement> is a @nt<delay_statement>, an attempt to cancel the delay when the @nt<abortable_part> completes is ignored if the expiration time has already passed, in which case the optional statements of the @nt<triggering_alternative> are executed. @end(Reason) The time base associated with the type Time of package Calendar is implementation defined. The function Clock of package Calendar returns a value representing the current time for this time base. @Redundant[The implementation-defined value of the named number System.Tick (see @RefSecNum(The Package System)) is an approximation of the length of the real-time interval during which the value of Calendar.Clock remains constant.] @ImplDef{The time base of the type Calendar.Time.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} The functions Year, Month, Day, and Seconds return the corresponding values for a given value of the type Time, as appropriate to an implementation-defined @Chg{Version=[2],New=[time zone],Old=[timezone]}; the procedure Split returns all four corresponding values. Conversely, the function Time_Of combines a year number, a month number, a day number, and a duration, into a value of type Time. The operators "+" and "@en@;" for addition and subtraction of times and durations, and the relational operators for times, have the conventional meaning. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The @Chg{Version=[2],New=[time zone],Old=[timezone]} used for package Calendar operations.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0119-1]} @ChgAdded{Version=[3],Text=[The behavior of these values and subprograms if the time zone changes is also implementation-defined. In particular, the changes associated with summer time adjustments (like Daylight Savings Time in the United States) should be treated as a change in the implementation-defined time zone. The language does not specify whether the time zone information is stored in values of type Time; therefore the results of binary operators are unspecified when the operands are the two values with different effective time zones. In particular, the results of "-" may differ from the "real" result by the difference in the time zone adjustment. Similarly, the result of UTC_Time_Offset (see 9.6.1) may or may not reflect a time zone adjustment.]} @end{Ramification} If Time_Of is called with a seconds value of 86_400.0, the value returned is equal to the value of Time_Of for the next day with a seconds value of 0.0. The value returned by the function Seconds or through the Seconds parameter of the procedure Split is always less than 86_400.0. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0030],ARef=[AI95-00113-01]} The exception Time_Error is raised by the function Time_Of if the actual parameters do not form a proper date. This exception is also raised by the operators "+" and "@en@;" if the result is not representable in the type Time or Duration, as appropriate. This exception is also raised by the function@Chg{New=[s],Old=[]} Year@Chg{New=[, Month, Day, and Seconds and], Old=[or]} the procedure Split if the year number of the given date is outside of the range of the subtype Year_Number. @begin(Honest) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0106],ARef=[AI95-00160-01]} By "proper date" above we mean that the given year has a month with the given day. For example, February 29th is a proper date only for a leap year. @Chg{New=[We do not mean to include the Seconds in this notion; in particular, we do not mean to require implementations to check for the @lquotes@;missing hour@rquotes that occurs when Daylight Savings Time starts in the spring.],Old=[]} @end(Honest) @begin(Reason) @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0030],ARef=[AI95-00113-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} We allow Year and Split to raise Time_Error because the arithmetic operators are allowed (but not required) to produce times that are outside the range of years from 1901 to @Chg{Version=[2],New=[2399],Old=[2099]}. This is similar to the way integer operators may return values outside the base range of their type so long as the value is mathematically correct. @Chg{New=[We allow the functions Month, Day and Seconds to raise Time_Error so that they can be implemented in terms of Split.],Old=[]} @end(Reason) @end{RunTime} @begin{ImplReq} The implementation of the type Duration shall allow representation of time intervals (both positive and negative) up to at least 86400 seconds (one day); Duration'Small shall not be greater than twenty milliseconds. The implementation of the type Time shall allow representation of all dates with year numbers in the range of Year_Number@Redundant[; it may allow representation of other dates as well (both earlier and later).] @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} An implementation may define additional time types@Chg{Version=[3],New=[],Old=[ (see @RefSecNum{Monotonic Time})]}. An implementation may raise Time_Error if the value of a @i{delay_}@nt<expression> in a @nt<delay_until_statement> of a @nt<select_statement> represents a time more than 90 days past the current time. The actual limit, if any, is implementation-defined. @ImplDef{Any limit on @nt<delay_until_statement>s of @nt<select_statement>s.} @begin{ImplNote} This allows an implementation to implement @nt<select_statement> timeouts using a representation that does not support the full range of a time type. In particular 90 days of seconds can be represented in 23 bits, allowing a signed 24-bit representation for the seconds part of a timeout. There is no similar restriction allowed for stand-alone @nt<delay_until_statement>s, as these can be implemented internally using a loop if necessary to accommodate a long delay. @end{ImplNote} @end{ImplPerm} @begin{ImplAdvice} Whenever possible in an implementation, the value of Duration'Small should be no greater than 100 microseconds. @begin(ImplNote) This can be satisfied using a 32-bit 2's complement representation with a @i(small) of 2.0**(@en@;14) @em that is, 61 microseconds @em and a range of @PorM 2.0**17 @em that is, 131_072.0. @end(ImplNote) @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The value of Duration'Small should be no greater than 100 microseconds.]}]} The time base for @nt{delay_relative_statement}s should be monotonic; it need not be the same time base as used for Calendar.Clock. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The time base for @nt{delay_relative_statement}s should be monotonic.]}]} @end{ImplAdvice} @begin{Notes} A @nt{delay_relative_statement} with a negative value of the @i(delay_)@nt<expression> is equivalent to one with a zero value. A @nt{delay_statement} may be executed by the environment task; consequently @nt{delay_statement}s may be executed as part of the elaboration of a @nt{library_item} or the execution of the main subprogram. Such statements delay the environment task (see @RefSecNum(Program Execution)). @PDefn2{Term=[potentially blocking operation],Sec=(delay_statement)} @PDefn2{Term=[blocking, potentially],Sec=(delay_statement)} A @nt{delay_statement} is an abort completion point and a potentially blocking operation, even if the task is not actually blocked. There is no necessary relationship between System.Tick (the resolution of the clock of package Calendar) and Duration'Small (the @i(small) of type Duration). @begin{Ramification} The inaccuracy of the @nt{delay_statement} has no relation to System.Tick. In particular, it is possible that the clock used for the @nt{delay_statement} is less accurate than Calendar.Clock. We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in @RefSec{Real-Time Systems}. @end{Ramification} Additional requirements associated with @nt<delay_statement>s are given in @RefSec(Delay Accuracy). @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a relative delay statement:} @begin{example} @key(delay) 3.0; --@RI[ delay 3.0 seconds] @end{example} @begin{WideAbove} @leading@keepnext@Defn2{Term=[periodic task],Sec=(example)} @IndexSee{Term=[periodic task],See=(delay_until_statement)} @i{Example of a periodic task:} @end{WideAbove} @begin{example} @key(declare) @key(use) Ada.Calendar; Next_Time : Time := Clock + Period; --@RI[ Period is a global constant of type Duration] @key(begin) @key(loop) --@RI[ repeated every Period seconds] @key(delay) @key(until) Next_Time; ... --@RI[ perform some actions] Next_Time := Next_Time + Period; @key(end) @key(loop;) @key(end;) @end{example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} For programs that raise Time_Error on "+" or "@en@;" in Ada 83,the exception might be deferred until a call on Split or Year_Number, or might not be raised at all (if the offending time is never Split after being calculated). This should not affect typical programs, since they deal only with times corresponding to the relatively recent past or near future. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{delay_statement} is modified to allow @nt{delay_until_statement}s. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00351-01]} The type Time may represent dates with year numbers outside of Year_Number. Therefore, the operations "+" and "@en@;" need only raise Time_Error if the result is not representable in Time (or Duration); also, Split or Year will now raise Time_Error if the year number is outside of Year_Number. This change is intended to simplify the implementation of "+" and "@en@;" (allowing them to depend on overflow for detecting when to raise Time_Error) and to allow local @Chg{Version=[2],New=[time zone],Old=[timezone]} information to be considered at the time of Split rather than Clock (depending on the implementation approach). For example, in a POSIX environment, it is natural for the type Time to be based on GMT, and the results of procedure Split (and the functions Year, Month, Day, and Seconds) to depend on local time zone information. In other environments, it is more natural for the type Time to be based on the local time zone, with the results of Year, Month, Day, and Seconds being pure functions of their input. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00351-01]} @ChgDeleted{Version=[2],Text=[We anticipate that implementations will provide child packages of Calendar to provide more explicit control over time zones and other environment-dependent time-related issues. These would be appropriate for standardization in a given environment (such as POSIX).]} @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95}The upper bound of Year_Number has been changed to avoid a year 2100 problem. A program which expects years past 2099 to raise Constraint_Error will fail in Ada 2005. We don't expect there to be many programs which are depending on an exception to be raised. A program that uses Year_Number'Last as a magic number may also fail if values of Time are stored outside of the program. Note that the lower bound of Year_Number wasn't changed, because it is not unusual to use that value in a constant to represent an unknown time.]} @end{Inconsistent95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0002],ARef=[AI95-00171-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Month, Day, and Seconds can raise Time_Error.]} @end{DiffWord95} @LabeledAddedSubclause{Version=[2],Name=[Formatting, Time Zones, and other operations for Time]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Text=[The following language-defined library packages exist:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Time_Zones]}@key(package) Ada.Calendar.Time_Zones @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Time zone manipulation:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Time_Offset} @key<is range> -28*60 .. 28*60;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We want to be able to specify the difference between any two arbitrary time zones. You might think that 1440 (24 hours) would be enough, but there are places (like Tonga, which is UTC+13hr) which are more than 12 hours than UTC. Combined with summer time (known as daylight saving time in some parts of the world) @en which switches opposite in the northern and souther hemispheres @en and even greater differences are possible. We know of cases of a 26 hours difference, so we err on the safe side by selecting 28 hours as the limit.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Unknown_Zone_Error} : @key<exception>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{UTC_Time_Offset} (Date : Time := Clock) @key<return> Time_Offset;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Time_Zones;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Arithmetic]} @key(package) Ada.Calendar.Arithmetic @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Arithmetic on days:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Day_Count} @key<is range> -366*(1+Year_Number'Last - Year_Number'First) .. 366*(1+Year_Number'Last - Year_Number'First);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<subtype> @AdaSubtypeDefn{Name=[Leap_Seconds_Count],Of=[Integer]} @key<is> Integer @key<range> -2047 .. 2047;]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The maximum number of leap seconds is likely to be much less than this, but we don't want to reach the limit too soon if the earth's behavior suddenly changes. We believe that the maximum number is 1612, based on the current rules, but that number is too weird to use here.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Difference} (Left, Right : @key<in> Time; Days : @key<out> Day_Count; Seconds : @key<out> Duration; Leap_Seconds : @key<out> Leap_Seconds_Count);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "+" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "+" (Left : Day_Count; Right : Time) @key<return> Time; @key<function> "-" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "-" (Left, Right : Time) @key<return> Day_Count;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Arithmetic;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Calendar],Child=[Formatting]} @key<with> Ada.Calendar.Time_Zones; @key(package) Ada.Calendar.Formatting @key(is)]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Day of the week:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Day_Name} @key<is> (@AdaObjDefn{Monday}, @AdaObjDefn{Tuesday}, @AdaObjDefn{Wednesday}, @AdaObjDefn{Thursday}, @AdaObjDefn{Friday}, @AdaObjDefn{Saturday}, @AdaObjDefn{Sunday});]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Day_of_Week} (Date : Time) @key<return> Day_Name;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Hours:Minutes:Seconds access:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<subtype> @AdaSubtypeDefn{Name=[Hour_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 23; @key<subtype> @AdaSubtypeDefn{Name=[Minute_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 59; @key<subtype> @AdaSubtypeDefn{Name=[Second_Number],Of=[Natural]} @key<is> Natural @key<range> 0 .. 59; @key<subtype> @AdaSubtypeDefn{Name=[Second_Duration],Of=[Day_Duration]} @key<is> Day_Duration @key<range> 0.0 .. 1.0;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Year} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Year_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Month} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Month_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Day} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Day_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Hour} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Hour_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Minute} (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Minute_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Second} (Date : Time) @key<return> Second_Number;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Sub_Second} (Date : Time) @key<return> Second_Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Seconds_Of} (Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number := 0; Sub_Second : Second_Duration := 0.0) @key<return> Day_Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Seconds : @key<in> Day_Duration; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Time_Of} (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Time_Of} (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Split} (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Seconds : @key<out> Day_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Simple image and value:] @key<function> @AdaSubDefn{Image} (Date : Time; Include_Time_Fraction : Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Date : String; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Image} (Elapsed_Time : Duration; Include_Time_Fraction : Boolean := False) @key<return> String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Elapsed_Time : String) @key<return> Duration;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Calendar.Formatting;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[Type Time_Offset represents the number of minutes difference between the implementation-defined time zone used by Calendar and another time zone.]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> UTC_Time_Offset (Date : Time := Clock) @key<return> Time_Offset;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0119-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns, as a number of minutes, the @Chg{Version=[3],New=[result of subtracting],Old=[difference between]} the implementation-defined time zone of Calendar@Chg{Version=[3],New=[ from],Old=[, and]} UTC time, at the time Date. If the time zone of the Calendar implementation is unknown, then Unknown_Zone_Error is raised.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0119-1]} @ChgAdded{Version=[3],Text=[In North America, the result will be negative; in Europe, the result will be zero or positive.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Date parameter is needed to take into account time differences caused by daylight-savings time and other time changes. This parameter is measured in the time zone of Calendar, if any, not necessarily the UTC time zone.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Other time zones can be supported with a child package. We don't define one because of the lack of agreement on the definition of a time zone.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The accuracy of this routine is not specified; the intent is that the facilities of the underlying target operating system are used to implement it.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Difference (Left, Right : @key<in> Time; Days : @key<out> Day_Count; Seconds : @key<out> Duration; Leap_Seconds : @key<out> Leap_Seconds_Count);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the difference between Left and Right. Days is the number of days of difference, Seconds is the remainder seconds of difference excluding leap seconds, and Leap_Seconds is the number of leap seconds. If Left < Right, then Seconds <= 0.0, Days <= 0, and Leap_Seconds <= 0. Otherwise, all values are nonnegative. The absolute value of Seconds is always less than 86_400.0. For the returned values, if Days = 0, then Seconds + Duration(Leap_Seconds) = Calendar."@en" (Left, Right).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Leap_Seconds, if any, are not included in Seconds. However, Leap_Seconds should be included in calculations using the operators defined in Calendar, as is specified for "@en" above.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "+" (Left : Time; Right : Day_Count) @key<return> Time; @key<function> "+" (Left : Day_Count; Right : Time) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Adds a number of days to a time value. Time_Error is raised if the result is not representable as a value of type Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "-" (Left : Time; Right : Day_Count) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Subtracts a number of days from a time value. Time_Error is raised if the result is not representable as a value of type Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> "-" (Left, Right : Time) @key<return> Day_Count;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Subtracts two time values, and returns the number of days between them. This is the same value that Difference would return in Days.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Day_of_Week (Date : Time) @key<return> Day_Name;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the day of the week for Time. This is based on the Year, Month, and Day values of Time.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Year (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Year_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the year for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Month (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Month_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the month for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Day (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Day_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the day number for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Hour (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Hour_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the hour for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Minute (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Minute_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the minute within the hour for Date, as appropriate for the specified time zone offset.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Second (Date : Time) @key<return> Second_Number;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the second within the hour and minute for Date.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Sub_Second (Date : Time) @key<return> Second_Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the fraction of second for Date (this has the same accuracy as Day_Duration). The value returned is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Seconds_Of (Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number := 0; Sub_Second : Second_Duration := 0.0) @key<return> Day_Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Day_Duration value for the combination of the given Hour, Minute, Second, and Sub_Second. This value can be used in Calendar.Time_Of as well as the argument to Calendar."+" and Calendar."@en". If Seconds_Of is called with a Sub_Second value of 1.0, the value returned is equal to the value of Seconds_Of for the next second with a Sub_Second value of 0.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Seconds : @key<in> Day_Duration; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0238-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Splits Seconds into Hour, Minute, Second and Sub_Second in such a way that the resulting values all belong to their respective subtypes. The value returned in the Sub_Second parameter is always less than 1.0.@Chg{Version=[3],New=[ If Seconds = 86400.0, Split propagates Time_Error.],Old=[]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is only one way to do the split which meets all of the requirements.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0238-1]} @ChgAdded{Version=[3],Text=[If Seconds = 86400.0, one of the returned values would have to be out of its defined range (either Sub_Second = 1.0 or Hour = 24 with the other value being 0). This doesn't seem worth breaking the invariants.]} @end{Reason} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Hour : Hour_Number; Minute : Minute_Number; Second : Second_Number; Sub_Second : Second_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Leap_Second is False, returns a Time built from the date and time values, relative to the specified time zone offset. If Leap_Second is True, returns the Time that represents the time within the leap second that is one second later than the time specified by the other parameters. Time_Error is raised if the parameters do not form a proper date or time. If Time_Of is called with a Sub_Second value of 1.0, the value returned is equal to the value of Time_Of for the next second with a Sub_Second value of 0.0.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Time_Error should be raised if Leap_Second is True, and the date and time values do not represent the second before a leap second. A leap second always occurs at midnight UTC, and is 23:59:60 UTC in ISO notation. So, if the time zone is UTC and Leap_Second is True, if any of Hour /= 23, Minute /= 59, or Second /= 59, then Time_Error should be raised. However, we do not say that, because other time zones will have different values where a leap second is allowed.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Time_Of (Year : Year_Number; Month : Month_Number; Day : Day_Number; Seconds : Day_Duration := 0.0; Leap_Second: Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Leap_Second is False, returns a Time built from the date and time values, relative to the specified time zone offset. If Leap_Second is True, returns the Time that represents the time within the leap second that is one second later than the time specified by the other parameters. Time_Error is raised if the parameters do not form a proper date or time. If Time_Of is called with a Seconds value of 86_400.0, the value returned is equal to the value of Time_Of for the next day with a Seconds value of 0.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Date does not represent a time within a leap second, splits Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified time zone offset, and sets Leap_Second to False. If Date represents a time within a leap second, set the constituent parts to values corresponding to a time one second earlier than that given by Date, relative to the specified time zone offset, and sets Leap_Seconds to True. The value returned in the Sub_Second parameter is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Hour : @key<out> Hour_Number; Minute : @key<out> Minute_Number; Second : @key<out> Second_Number; Sub_Second : @key<out> Second_Duration; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Splits Date into its constituent parts (Year, Month, Day, Hour, Minute, Second, Sub_Second), relative to the specified time zone offset. The value returned in the Sub_Second parameter is always less than 1.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<procedure> Split (Date : @key<in> Time; Year : @key<out> Year_Number; Month : @key<out> Month_Number; Day : @key<out> Day_Number; Seconds : @key<out> Day_Duration; Leap_Second: @key<out> Boolean; Time_Zone : @key<in> Time_Zones.Time_Offset := 0);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00427-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Date does not represent a time within a leap second, splits Date into its constituent parts (Year, Month, Day, Seconds), relative to the specified time zone offset, and sets Leap_Second to False. If Date represents a time within a leap second, set the constituent parts to values corresponding to a time one second earlier than that given by Date, relative to the specified time zone offset, and sets Leap_Seconds to True. The value returned in the Seconds parameter is always less than 86_400.0.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Image (Date : Time; Include_Time_Fraction : Boolean := False; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a string form of the Date relative to the given Time_Zone. The format is "Year-Month-Day Hour:Minute:Second", where the Year is a 4-digit value, and all others are 2-digit values, of the functions defined in Calendar and Calendar.Formatting, including a leading zero, if needed. The separators between the values are a minus, another minus, a colon, and a single space between the Day and Hour. If Include_Time_Fraction is True, the integer part of Sub_Seconds*100 is suffixed to the string as a point followed by a 2-digit value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Image provides a string in ISO 8601 format, the international standard time format. Alternative representations allowed in ISO 8601 are not supported here.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ISO 8601 allows 24:00:00 for midnight; and a seconds value of 60 for leap seconds. These are not allowed here (the routines mentioned above cannot produce those results).]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The fractional part is truncated, not rounded. It would be quite hard to define the result with proper rounding, as it can change all of the values of the image. Values can be rounded up by adding an appropriate constant (0.5 if Include_Time_Fraction is False, 0.005 otherwise) to the time before taking the image.]} @end{Ramification} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Value (Date : String; Time_Zone : Time_Zones.Time_Offset := 0) @key<return> Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Time value for the image given as Date, relative to the given time zone. Constraint_Error is raised if the string is not formatted as described for Image, or the function cannot interpret the given string as a Time value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[The intent is that the implementation enforce the same range rules on the string as the appropriate function Time_Of, except for the hour, so @lquotes@;cannot interpret the given string as a Time value@rquotes happens when one of the values is out of the required range. For example, "2005-08-31 @Chg{Version=[3],New=[24:00:00],Old=[24:0:0]}" should raise Constraint_Error (the hour is out of range).]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Image (Elapsed_Time : Duration; Include_Time_Fraction : Boolean := False) @key<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a string form of the Elapsed_Time. The format is "Hour:Minute:Second", where all values are 2-digit values, including a leading zero, if needed. The separators between the values are colons. If Include_Time_Fraction is True, the integer part of Sub_Seconds*100 is suffixed to the string as a point followed by a 2-digit value. If Elapsed_Time < 0.0, the result is Image (@key<abs> Elapsed_Time, Include_Time_Fraction) prefixed with a minus sign. If @key<abs> Elapsed_Time represents 100 hours or more, the result is implementation-defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The result of Calendar.Formating.Image if its argument represents more than 100 hours.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This cannot be implemented (directly) by calling Calendar.Formatting.Split, since it may be out of the range of Day_Duration, and thus the number of hours may be out of the range of Hour_Number.]} @ChgAdded{Version=[2],Text=[If a Duration value can represent more then 100 hours, the implementation will need to define a format for the return of Image.]} @end{ImplNote} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key<function> Value (Elapsed_Time : String) @key<return> Duration;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a Duration value for the image given as Elapsed_Time. Constraint_Error is raised if the string is not formatted as described for Image, or the function cannot interpret the given string as a Duration value.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intent is that the implementation enforce the same range rules on the string as the appropriate function Time_Of, except for the hour, so @lquotes@;cannot interpret the given string as a Time value@rquotes happens when one of the values is out of the required range. For example, "10:23:60" should raise Constraint_Error (the seconds value is out of range).]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[An implementation should support leap seconds if the target system supports them. If leap seconds are not supported, Difference should return zero for Leap_Seconds, Split should return False for Leap_Second, and Time_Of should raise Time_Error if Leap_Second is True.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Leap seconds should be supported if the target system supports them. Otherwise, operations in Calendar.Formatting should return results consistent with no leap seconds.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An implementation can always support leap seconds when the target system does not; indeed, this isn't particularly hard (all that is required is a table of when leap seconds were inserted). As such, leap second support isn't @lquotes@;impossible or impractical@rquotes in the sense of @RefSecNum{Conformity of an Implementation with the Standard}. However, for some purposes, it may be important to follow the target system's lack of leap second support (if the target is a GPS satellite, which does not use leap seconds, leap second support would be a handicap to work around). Thus, this @ImplAdviceTitle should be read as giving permission to not support leap seconds on target systems that don't support leap seconds. Implementers should use the needs of their customers to determine whether or not support leap seconds on such targets.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[The implementation-defined time zone of package Calendar may, but need not, be the local time zone. UTC_Time_Offset always returns the difference relative to the implementation-defined time zone of package Calendar. If UTC_Time_Offset does not raise Unknown_Zone_Error, UTC time can be safely calculated (within the accuracy of the underlying time-base).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[The time in the time zone known as Greenwich Mean Time (GMT) is generally very close to UTC time; for most purposes they can be treated the same. GMT is the time based on the rotation of the Earth; UTC is the time based on atomic clocks, with leap seconds periodically inserted to realign with GMT (because most human activities depend on the rotation of the Earth). At any point in time, there will be a sub-second difference between GMT and UTC.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01]} @ChgAdded{Version=[2],Text=[Calling Split on the results of subtracting Duration(UTC_Time_Offset*60) from Clock provides the components (hours, minutes, and so on) of the UTC time. In the United States, for example, UTC_Time_Offset will generally be negative.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is an illustration to help specify the value of UTC_Time_Offset. A user should pass UTC_Time_Offset as the Time_Zone parameter of Split, rather than trying to make the above calculation.]} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00351-01],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Packages Calendar.Time_Zones, Calendar.Arithmetic, and Calendar.Formatting are new.]} @end{Extend95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0238-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Defined that Split for Seconds raises Time_Error for a value of exactly 86400.0, rather than breaking some invariant or raising some other exception. Ada 2005 left this unspecified; a program that depended on what some implementation does might break, but such a program is not portable anyway.]} @end{Inconsistent2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0119-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified the sign of UTC_Time_Offset.]} @end{Diffword2005} @LabeledClause{Select Statements} @begin{Intro} @redundant[There are four forms of the @nt{select_statement}. One form provides a selective wait for one or more @nt{select_alternative}s. Two provide timed and conditional entry calls. The fourth provides asynchronous transfer of control.] @end{Intro} @begin{Syntax} @Syn{lhs=<select_statement>,rhs=" @Syn2{selective_accept} | @Syn2{timed_entry_call} | @Syn2{conditional_entry_call} | @Syn2{asynchronous_select}"} @end{Syntax} @begin{Examples} @leading@keepnext@i{Example of a select statement:} @begin{Example} @key(select) @key(accept) Driver_Awake_Signal; @key(or) @key(delay) 30.0*Seconds; Stop_The_Train; @key(end) @key(select); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} @nt{Asynchronous_select} is new. @end{Extend83} @LabeledSubClause{Selective Accept} @begin{Intro} @redundant[This form of the @nt{select_statement} allows a combination of waiting for, and selecting from, one or more alternatives. The selection may depend on conditions associated with each alternative of the @nt{selective_accept}. @IndexSee{Term=[time-out],See=(selective_accept)}] @end{Intro} @begin{Syntax} @Syn{lhs=<selective_accept>,rhs=" @key{select} [@Syn2{guard}] @Syn2{select_alternative} { @key{or} [@Syn2{guard}] @Syn2{select_alternative} } [ @key{else} @Syn2{sequence_of_statements} ] @key{end select};"} @Syn{lhs=<guard>,rhs="@key{when} @Syn2{condition} =>"} @Syn{lhs=<select_alternative>,rhs=" @Syn2{accept_alternative} | @Syn2{delay_alternative} | @Syn2{terminate_alternative}"} @Syn{lhs=<accept_alternative>,rhs=" @Syn2{accept_statement} [@Syn2{sequence_of_statements}]"} @Syn{lhs=<delay_alternative>,rhs=" @Syn2{delay_statement} [@Syn2{sequence_of_statements}]"} @Syn{lhs=<terminate_alternative>,rhs="@key{terminate};"} @begin(SyntaxText) @leading@;A @nt{selective_accept} shall contain at least one @nt{accept_alternative}. In addition, it can contain: @begin{itemize} a @nt{terminate_alternative} (only one); or one or more @nt{delay_alternative}s; or @Defn2{Term=[else part], Sec=(of a @nt<selective_accept>)} an @i(else part) (the reserved word @key(else) followed by a @nt<sequence_of_statements>). @end{itemize} These three possibilities are mutually exclusive. @end(SyntaxText) @end{Syntax} @begin{Legality} If a @nt{selective_accept} contains more than one @nt{delay_alternative}, then all shall be @nt<delay_@!relative_@!statement>s, or all shall be @nt<delay_@!until_@!statement>s for the same time type. @begin{Reason} This simplifies the implementation and the description of the semantics. @end{Reason} @end{Legality} @begin{RunTime} @Defn{open alternative} A @nt<select_alternative> is said to be @i(open) if it is not immediately preceded by a @nt<guard>, or if the @nt<condition> of its @nt<guard> evaluates to True. It is said to be @i(closed) otherwise. @PDefn2{Term=[execution], Sec=(selective_accept)} For the execution of a @nt{selective_accept}, any @nt{guard} @nt{condition}s are evaluated; open alternatives are thus determined. For an open @nt{delay_alternative}, the @i(delay_)@nt<expression> is also evaluated. Similarly, for an open @nt{accept_alternative} for an entry of a family, the @nt{entry_index} is also evaluated. These evaluations are performed in an arbitrary order, except that a @i(delay_)@nt<expression> or @nt<entry_index> is not evaluated until after evaluating the corresponding @nt<condition>, if any. Selection and execution of one open alternative, or of the else part, then completes the execution of the @nt{selective_accept}; the rules for this selection are described below.@PDefn2{Term=[arbitrary order],Sec=[allowed]} Open @nt{accept_alternative}s are first considered. Selection of one such alternative takes place immediately if the corresponding entry already has queued calls. If several alternatives can thus be selected, one of them is selected according to the entry queuing policy in effect (see @RefSecNum(Entry Calls) and @RefSecNum(Entry Queuing Policies)). When such an alternative is selected, the selected call is removed from its entry queue and the @nt<handled_sequence_of_@!statements> (if any) of the corresponding @nt{accept_statement} is executed; after the rendezvous completes any subsequent @nt<sequence_of_@!statements> of the alternative is executed. @PDefn2{Term=[blocked], Sec=(execution of a @nt<selective_accept>)} If no selection is immediately possible (in the above sense) and there is no else part, the task blocks until an open alternative can be selected. @leading@;Selection of the other forms of alternative or of an else part is performed as follows: @begin{itemize} An open @nt{delay_alternative} is selected when its expiration time is reached if no @nt{accept_@!alternative} or other @nt<delay_@!alternative> can be selected prior to the expiration time. If several @nt{delay_@!alternative}s have this same expiration time, one of them is selected according to the queuing policy in effect (see @RefSecNum{Entry Queuing Policies}); the default queuing policy chooses arbitrarily among the @nt<delay_@!alternative>s whose expiration time has passed. The else part is selected and its @nt<sequence_of_@!statements> is executed if no @nt{accept_alternative} can immediately be selected; in particular, if all alternatives are closed. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} An open @nt{terminate_alternative} is selected if the conditions stated at the end of @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Task Dependence - Termination of Tasks} are satisfied. @begin(Ramification) In the absence of a @nt<requeue_statement>, the conditions stated are such that a @nt<terminate_alternative> cannot be selected while there is a queued entry call for any entry of the task. In the presence of requeues from a task to one of its subtasks, it is possible that when a @nt<terminate_alternative> of the subtask is selected, requeued calls (for closed entries only) might still be queued on some entry of the subtask. Tasking_Error will be propagated to such callers, as is usual when a task completes while queued callers remain. @end(Ramification) @end{itemize} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exception Program_Error is raised if all alternatives are closed and there is no else part. @end{RunTime} @begin{Notes} A @nt{selective_accept} is allowed to have several open @nt{delay_alternative}s. A @nt{selective_accept} is allowed to have several open @nt{accept_alternative}s for the same entry. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a task body with a selective accept:} @begin{Example} @key(task) @key(body) Server @key(is) Current_Work_Item : Work_Item; @key(begin) @key(loop) @key(select) @key(accept) Next_Work_Item(WI : @key(in) Work_Item) @key(do) Current_Work_Item := WI; @key(end); Process_Work_Item(Current_Work_Item); @key(or) @key(accept) Shut_Down; @key(exit); --@RI[ Premature shut down requested] @key(or) @key(terminate); --@RI[ Normal shutdown at end of scope] @key(end) @key(select); @key(end) @key(loop); @key(end) Server; @end{Example} @end{Examples} @begin{DiffWord83} The name of @ntf{selective_wait} was changed to @nt{selective_accept} to better describe what is being waited for. We kept @nt{select_alternative} as is, because @ntf<selective_accept_alternative> was too easily confused with @nt<accept_alternative>. @end{DiffWord83} @LabeledSubClause{Timed Entry Calls} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @redundant[A @nt{timed_entry_call} issues an entry call that is cancelled if the call (or a requeue-with-abort of the call) is not selected before the expiration time is reached.@Chg{Version=[2],New=[ A procedure call may appear rather than an entry call for cases where the procedure might be implemented by an entry.],Old=[]} @IndexSee{Term=[time-out],See=(timed_entry_call)}] @end{Intro} @begin{Syntax} @Syn{lhs=<timed_entry_call>,rhs=" @key{select} @Syn2{entry_call_alternative} @key{or} @Syn2{delay_alternative} @key{end select};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<entry_call_alternative>,rhs=" @Chg{Version=[2],New=[@Syn2{procedure_or_entry_call}],Old=[@Syn2{entry_call_statement}]} [@Syn2{sequence_of_statements}]"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=[procedure_or_entry_call],Old=[]}>,rhs=" @Chg{Version=[2],New=[@Syn2{procedure_call_statement} | @Syn2{entry_call_statement}],Old=[]}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[If a @nt{procedure_call_statement} is used for a @nt{procedure_or_entry_call}, the @SynI{procedure_}@nt{name} or @SynI{procedure_}@nt{prefix} of the @nt{procedure_call_statement} shall statically denote an entry renamed as a procedure or (a view of) a primitive subprogram of a limited interface whose first parameter is a controlling parameter (see @RefSecNum{Dispatching Operations of Tagged Types}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This would be a confusing way to call a procedure, so we only allow it when it is possible that the procedure is actually an entry. We could have allowed formal subprograms here, but we didn't because we'd have to allow all formal subprograms, and it would increase the difficulty of generic code sharing.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We say @lquotes@;statically denotes@rquotes because an access-to-subprogram cannot be primitive, and we don't have anything like access-to-entry. So only names of entries or procedures are possible.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0291-1]}@Comment{ We don't need a message here, as this is the last inserted paragraph} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[If a @nt{procedure_call_statement} is used for a @nt{procedure_or_entry_call}, and the procedure is implemented by an entry, then the @SynI{procedure_}@nt{name}, or @SynI{procedure_}@nt{prefix} and possibly the first parameter of the @nt{procedure_call_statement}, determine the target object of the call and the entry to be called.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The above says @lquotes@;possibly the first parameter@rquotes@;, because Ada allows entries to be renamed and passed as formal subprograms. In those cases, the task or protected object is implicit in the name of the routine; otherwise the object is an explicit parameter to the call.]}]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(timed_entry_call)} For the execution of a @nt{timed_entry_call}, the @SynI(entry_)@nt<name>@Chg{Version=[2], New=[, @Syni{procedure_}@nt{name}, or @Syni{procedure_}@nt{prefix},],Old=[]} and any actual parameters are evaluated, as for a simple entry call (see @RefSecNum(Entry Calls))@Chg{Version=[2],New=[ or procedure call (see @RefSecNum{Subprogram Calls})],Old=[]}. The expiration time (see @RefSecNum(Delay Statements, Duration, and Time)) for the call is determined by evaluating the @i(delay_)@nt<expression> of the @nt<delay_alternative>@Chg{Version=[2],New=[. If the call is an entry call or a call on a procedure implemented by an entry,],Old=[;]} the entry call is then issued.@Chg{Version=[2],New=[ Otherwise, the call proceeds as described in @RefSecNum{Subprogram Calls} for a procedure call, followed by the @nt{sequence_of_@!statements} of the @nt{entry_call_@!alternative}; the @nt{sequence_of_@!statements} of the @nt{delay_@!alternative} is ignored.],Old=[]} If the call is queued (including due to a requeue-with-abort), and not selected before the expiration time is reached, an attempt to cancel the call is made. If the call completes due to the cancellation, the optional @nt<sequence_of_@!statements> of the @nt<delay_@!alternative> is executed; if the entry call completes normally, the optional @nt<sequence_of_@!statements> of the @nt<entry_call_@!alternative> is executed. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00345-01]} @ChgDeleted{Version=[2],Text=[The fact that the syntax calls for an @nt{entry_call_statement} means that this fact is used in overload resolution. For example, if there is a procedure X and an entry X (both with no parameters), then "select X; ..." is legal, because overload resolution knows that the entry is the one that was meant.]} @end{Ramification} @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of a timed entry call:} @begin{Example} @key(select) Controller.Request(Medium)(Some_Item); @key(or) @key(delay) 45.0; --@RI[ controller too busy, try something else] @key(end) @key(select); @end{Example} @end{Examples} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} comes before the one for Conditional Entry Calls, so we can define conditional entry calls in terms of timed entry calls. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} A procedure @Chg{Version=[3],New=[call ],Old=[]}can be used as the @Chg{Version=[3],New=[@nt{entry_call_alternative} ],Old=[]}in a timed or conditional entry call, if the procedure might actually be an entry. Since the fact that something is an entry could be used in resolving these calls in Ada 95, it is possible for timed or conditional entry calls that resolved in Ada 95 to be ambiguous in Ada 2005. That could happen if both an entry and procedure with the same name and profile exist, which should be rare.]} @end{Incompatible95} @LabeledSubClause{Conditional Entry Calls} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Redundant[A @nt{conditional_entry_call} issues an entry call that is then cancelled if it is not selected immediately (or if a requeue-with-abort of the call is not selected immediately).@Chg{Version=[2],New=[ A procedure call may appear rather than an entry call for cases where the procedure might be implemented by an entry.],Old=[]}] @begin(Honest) In the case of an entry call on a protected object, it is OK if the entry is closed at the start of the corresponding protected action, so long as it opens and the call is selected before the end of that protected action (due to changes in the Count attribute). @end(Honest) @end{Intro} @begin{Syntax} @Syn{lhs=<conditional_entry_call>,rhs=" @key{select} @Syn2{entry_call_alternative} @key{else} @Syn2{sequence_of_statements} @key{end select};"} @end{Syntax} @begin{RunTime} @PDefn2{Term=[execution], Sec=(conditional_entry_call)} The execution of a @nt<conditional_entry_call> is defined to be equivalent to the execution of a @nt<timed_@!entry_@!call> with a @nt<delay_@!alternative> specifying an immediate expiration time and the same @nt<sequence_of_@!statements> as given after the reserved word @key(else). @end{RunTime} @begin{Notes} A @nt{conditional_entry_call} may briefly increase the Count attribute of the entry, even if the conditional call is not selected. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a conditional entry call:} @begin{Example} @key(procedure) Spin(R : @key[in] Resource) @key(is) @key(begin) @key(loop) @key(select) R.Seize; @key(return); @key(else) @key(null); --@RI[ busy waiting] @key(end) @key(select); @key(end) @key(loop); @key(end); @end{Example} @end{Examples} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} comes after the one for Timed Entry Calls, so we can define conditional entry calls in terms of timed entry calls. We do that so that an "expiration time" is defined for both, thereby simplifying the definition of what happens on a requeue-with-abort. @end{DiffWord83} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{Asynchronous Transfer of Control} @begin{Intro} @redundant[An asynchronous @nt{select_statement} provides asynchronous transfer of control upon completion of an entry call or the expiration of a delay.] @end{Intro} @begin{Syntax} @Syn{lhs=<asynchronous_select>,rhs=" @key{select} @Syn2{triggering_alternative} @key{then abort} @Syn2{abortable_part} @key{end select};"} @Syn{lhs=<triggering_alternative>,rhs="@Syn2{triggering_statement} [@Syn2{sequence_of_statements}]"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @Syn{lhs=<triggering_statement>,rhs="@Chg{Version=[2],New=[@Syn2{procedure_or_entry_call}],Old=[@Syn2{entry_call_statement}]} | @Syn2{delay_statement}"} @Syn{lhs=<abortable_part>,rhs="@Syn2{sequence_of_statements}"} @end{Syntax} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @PDefn2{Term=[execution], Sec=(asynchronous_select with an entry call trigger)} @Chg{Version=[2],New=[@PDefn2{Term=[execution], Sec=(asynchronous_select with a procedure call trigger)}],Old=[]} For the execution of an @nt{asynchronous_select} whose @nt<triggering_@!statement> is @Chg{Version=[2], New=[a @nt<procedure_or_entry_call>],Old=[an @nt<entry_call_statement>]}, the @Syni(entry_)@nt<name>@Chg{Version=[2],New=[, @Syni{procedure_}@nt{name}, or @Syni{procedure_}@nt{prefix},],Old=[]} and actual parameters are evaluated as for a simple entry call (see @RefSecNum(Entry Calls))@Chg{Version=[2],New=[ or procedure call (see @RefSecNum{Subprogram Calls}). If the call is an entry call or a call on a procedure implemented by an entry,],Old=[, and]} the entry call is issued. If the entry call is queued (or requeued-with-abort), then the @nt<abortable_part> is executed. @Redundant[If the entry call is selected immediately, and never requeued-with-abort, then the @nt<abortable_part> is never started.]@Chg{Version=[2],New=[ If the call is on a procedure that is not implemented by an entry, the call proceeds as described in @RefSecNum{Subprogram Calls}, followed by the @nt{sequence_of_@!statements} of the @nt{triggering_@!alternative}@Redundant[; the @nt{abortable_part} is never started].],Old=[]} @PDefn2{Term=[execution], Sec=(asynchronous_select with a delay_statement trigger)} For the execution of an @nt<asynchronous_select> whose @nt<triggering_@!statement> is a @nt<delay_statement>, the @i(delay_)@nt<expression> is evaluated and the expiration time is determined, as for a normal @nt<delay_statement>. If the expiration time has not already passed, the @nt<abortable_part> is executed. If the @nt<abortable_part> completes and is left prior to completion of the @nt<triggering_@!statement>, an attempt to cancel the @nt<triggering_@!statement> is made. If the attempt to cancel succeeds (see @RefSecNum(Entry Calls) and @RefSecNum(Delay Statements, Duration, and Time)), the @nt<asynchronous_select> is complete. If the @nt<triggering_@!statement> completes other than due to cancellation, the @nt<abortable_part> is aborted (if started but not yet completed @em see @RefSecNum(Abort of a Task - Abort of a Sequence of Statements)). If the @nt<triggering_@!statement> completes normally, the optional @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> is executed after the @nt<abortable_part> is left. @begin(Discussion) We currently don't specify when the by-copy [@key(in)] @key(out) parameters are assigned back into the actuals. We considered requiring that to happen after the @nt<abortable_part> is left. However, that doesn't seem useful enough to justify possibly overspecifying the implementation approach, since some of the parameters are passed by reference anyway. In an earlier description, we required that the @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> execute after aborting the @nt<abortable_part>, but before waiting for it to complete and finalize, to provide more rapid response to the triggering event in case the finalization was unbounded. However, various reviewers felt that this created unnecessary complexity in the description, and a potential for undesirable concurrency (and nondeterminism) within a single task. We have now reverted to simpler, more deterministic semantics, but anticipate that further discussion of this issue might be appropriate during subsequent reviews. One possibility is to leave this area implementation defined, so as to encourage experimentation. The user would then have to assume the worst about what kinds of actions are appropriate for the @nt<sequence_of_@!statements> of the @nt<triggering_@!alternative> to achieve portability. @end(Discussion) @end{RunTime} @begin{Examples} @leading@keepnext@Defn2{Term=[signal handling], Sec=(example)} @Defn2{Term=[interrupt],Sec=(example using @nt<asynchronous_select>)} @Defn2{Term=[terminal interrupt], Sec=(example)} @i(Example of a main command loop for a command interpreter:) @begin(Example) @key(loop) @key(select) Terminal.Wait_For_Interrupt; Put_Line("Interrupted"); @key(then abort) -- @RI(This will be abandoned upon terminal interrupt) Put_Line("-> "); Get_Line(Command, Last); Process_Command(Command(1..Last)); @key(end) @key(select); @key(end) @key(loop); @end(Example) @begin{WideAbove} @leading@keepnext@i(Example of a time-limited calculation:) @IndexSee{Term=[time-out],See=(asynchronous_select)} @Defn2{Term=[time-out],Sec=(example)} @Defn2{Term=[time limit],Sec=(example)} @Defn2{Term=[interrupt],Sec=(example using @nt<asynchronous_select>)} @Defn2{Term=[timer interrupt],Sec=(example)} @end{WideAbove} @begin(Example) @key(select) @key(delay) 5.0; Put_Line("Calculation does not converge"); @key(then abort) -- @RI(This calculation should finish in 5.0 seconds;) -- @RI( if not, it is assumed to diverge.) Horribly_Complicated_Recursive_Function(X, Y); @key(end) @key(select); @end(Example) @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} @nt<Asynchronous_select> is new. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A procedure can be used as the @nt{triggering_@!statement} of an @nt<asynchronous_select>, if the procedure might actually be an entry.]} @end{Extend95} @LabeledClause{Abort of a Task - Abort of a Sequence of Statements} @begin{Intro} @redundant[An @nt{abort_statement} causes one or more tasks to become abnormal, thus preventing any further interaction with such tasks. The completion of the @nt<triggering_@!statement> of an @nt<asynchronous_select> causes a @nt{sequence_of_@!statements} to be aborted.] @end{Intro} @begin{Syntax} @Syn{lhs=<abort_statement>, rhs="@key{abort} @SynI{task_}@Syn2{name} {, @SynI{task_}@Syn2{name}};"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(abort_statement task_name)} Each @SynI{task_}@nt{name} is expected to be of any task type@Redundant[; they need not all be of the same task type.] @end{Resolution} @begin{RunTime} @PDefn2{Term=[execution], Sec=(abort_statement)} For the execution of an @nt<abort_statement>, the given @i(task_)@nt<name>s are evaluated in an arbitrary order.@PDefn2{Term=[arbitrary order],Sec=[allowed]} @Defn2{Term=[abort], Sec=(of a task)} @Defn{abnormal task} @PDefn2{Term=[task state], Sec=(abnormal)} Each named task is then @i(aborted), which consists of making the task @i(abnormal) and aborting the execution of the corresponding @nt<task_body>, unless it is already completed. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Note that aborting those tasks is not defined to be an abort-deferred operation. Therefore, if one of the named tasks is the task executing the @nt{abort_statement}, or if the task executing the @nt{abort_statement} depends on one of the named tasks, then it is possible for the execution of the @nt{abort_statement} to be aborted, thus leaving some of the tasks unaborted. This allows the implementation to use either a sequence of calls to an @lquotes@;abort task@rquotes@; @Chg{Version=[2],New=[run-time system],Old=[RTS]} primitive, or a single call to an @lquotes@;abort list of tasks@rquotes@; @Chg{Version=[2],New=[run-time system],Old=[RTS]} primitive. @end{Ramification} @leading@PDefn2{Term=[execution], Sec=(aborting the execution of a construct)} @Defn2{Term=[abort], Sec=(of the execution of a construct)} When the execution of a construct is @i(aborted) (including that of a @nt<task_@!body> or of a @nt<sequence_of_@!statements>), the execution of every construct included within the aborted execution is also aborted, except for executions included within the execution of an @i(abort-deferred) operation; the execution of an abort-deferred operation continues to completion without being affected by the abort; @Defn{abort-deferred operation} the following are the abort-deferred operations: @begin(Itemize) a protected action; waiting for an entry call to complete (after having initiated the attempt to cancel it @em see below); waiting for the termination of dependent tasks; the execution of an Initialize procedure as the last step of the default initialization of a controlled object; the execution of a Finalize procedure as part of the finalization of a controlled object; an assignment operation to an object with a controlled part. @end(Itemize) @Redundant[The last three of these are discussed further in @RefSecNum(Assignment and Finalization).] @begin{Reason} Deferring abort during Initialize and finalization allows, for example, the result of an allocator performed in an Initialize operation to be assigned into an access object without being interrupted in the middle, which would cause storage leaks. For an object with several controlled parts, each individual Initialize is abort-deferred. Note that there is generally no semantic difference between making each Finalize abort-deferred, versus making a group of them abort-deferred, because if the task gets aborted, the first thing it will do is complete any remaining finalizations. Individual objects are finalized prior to an assignment operation (if nonlimited controlled) and as part of Unchecked_Deallocation. @end{Reason} @begin(Ramification) Abort is deferred during the entire assignment operation to an object with a controlled part, even if only some subcomponents are controlled. Note that this says "assignment operation," not "@nt{assignment_statement}." Explicit calls to Initialize, Finalize, or Adjust are not abort-deferred. @end(Ramification) When a master is aborted, all tasks that depend on that master are aborted. @PDefn{unspecified} The order in which tasks become abnormal as the result of an @nt<abort_statement> or the abort of a @nt<sequence_of_@!statements> is not specified by the language. @leading@;If the execution of an entry call is aborted, an immediate attempt is made to cancel the entry call (see @RefSecNum(Entry Calls)). If the execution of a construct is aborted at a time when the execution is blocked, other than for an entry call, at a point that is outside the execution of an abort-deferred operation, then the execution of the construct completes immediately. For an abort due to an @nt<abort_statement>, these immediate effects occur before the execution of the @nt<abort_statement> completes. Other than for these immediate cases, the execution of a construct that is aborted does not necessarily complete before the @nt<abort_statement> completes. However, the execution of the aborted construct completes no later than its next @i(abort completion point) (if any) that occurs outside of an abort-deferred operation; @Defn{abort completion point} the following are abort completion points for an execution: @begin(Itemize) the point where the execution initiates the activation of another task; the end of the activation of a task; the start or end of the execution of an entry call, @nt<accept_statement>, @nt<delay_statement>, or @nt<abort_statement>; @begin(Ramification) Although the abort completion point doesn't occur until the end of the entry call or @nt<delay_statement>, these operations might be cut short because an abort attempts to cancel them. @end(Ramification) the start of the execution of a @nt<select_statement>, or of the @nt<sequence_of_@!statements> of an @nt<exception_handler>. @begin(Reason) The start of an @nt<exception_handler> is considered an abort completion point simply because it is easy for an implementation to check at such points. @end(Reason) @begin(ImplNote) Implementations may of course check for abort more often than at each abort completion point; ideally, a fully preemptive implementation of abort will be provided. If preemptive abort is not supported in a given environment, then supporting the checking for abort as part of subprogram calls and loop iterations might be a useful option. @end(ImplNote) @end(Itemize) @end{RunTime} @begin{Bounded} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @PDefn2{Term=(bounded error),Sec=(cause)} An attempt to execute an @nt<asynchronous_select> as part of the execution of an abort-deferred operation is a bounded error. Similarly, an attempt to create a task that depends on a master that is included entirely within the execution of an abort-deferred operation is a bounded error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} In both cases, Program_Error is raised if the error is detected by the implementation; otherwise@Chg{Version=[3],New=[,],Old=[]} the operations proceed as they would outside an abort-deferred operation, except that an abort of the @nt<abortable_part> or the created task might or might not have an effect. @begin(Reason) An @nt<asynchronous_select> relies on an abort of the @nt<abortable_part> to effect the asynchronous transfer of control. For an @nt<asynchronous_select> within an abort-deferred operation, the abort might have no effect. Creating a task dependent on a master included within an abort-deferred operation is considered an error, because such tasks could be aborted while the abort-deferred operation was still progressing, undermining the purpose of abort-deferral. Alternatively, we could say that such tasks are abort-deferred for their entire execution, but that seems too easy to abuse. Note that task creation is already a bounded error in protected actions, so this additional rule only applies to local task creation as part of Initialize, Finalize, or Adjust. @end(Reason) @end{Bounded} @begin{Erron} @PDefn{normal state of an object} @PDefn{abnormal state of an object} @Defn{disruption of an assignment} @PDefn2{Term=(erroneous execution),Sec=(cause)} If an assignment operation completes prematurely due to an abort, the assignment is said to be @i{disrupted}; the target of the assignment or its parts can become abnormal, and certain subsequent uses of the object can be erroneous, as explained in @RefSecNum{Data Validity}. @end{Erron} @begin{Notes} An @nt{abort_statement} should be used only in situations requiring unconditional termination. A task is allowed to abort any task it can name, including itself. Additional requirements associated with abort are given in @RefSec(Preemptive Abort). @end{Notes} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} has been rewritten to accommodate the concept of aborting the execution of a construct, rather than just of a task. @end{DiffWord83} @LabeledClause{Task and Entry Attributes} @begin{RunTime} @leading@; For @PrefixType{a @nt<prefix> T that is of a task type @Redundant[(after any implicit dereference)]}, the following attributes are defined: @begin{Description} @Comment{@ChgAttribute{Version=[2], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<T>, AttrName=<Callable>, ARef=[AI95-00345], Text=<Yields the value True when the task denoted by T is @i(callable), and False otherwise;>} @PDefn2{Term=[task state], Sec=(callable)} @Defn{callable} a task is callable unless it is completed or abnormal. The value of this attribute is of the predefined type Boolean.} @Attribute{Prefix=<T>, AttrName=<Callable>, Text=<Yields the value True when the task denoted by T is @i(callable), and False otherwise;>} @PDefn2{Term=[task state], Sec=(callable)} @Defn{callable} a task is callable unless it is completed or abnormal. The value of this attribute is of the predefined type Boolean. @Attribute{Prefix=<T>, AttrName=<Terminated>, Text=<Yields the value True if the task denoted by T is terminated, and False otherwise. The value of this attribute is of the predefined type Boolean.>} @end{Description} @EndPrefixType{} For @PrefixType{a @nt<prefix> E that denotes an entry of a task or protected unit}, the following attribute is defined. This attribute is only allowed within the body of the task or protected unit, but excluding, in the case of an entry of a task unit, within any program unit that is, itself, inner to the body of the task unit. @begin{Description} @Attribute{Prefix=<E>, AttrName=<Count>, Text=<Yields the number of calls presently queued on the entry E of the current instance of the unit. The value of this attribute is of the type @i{universal_integer}.>} @end{Description} @EndPrefixType{} @end{RunTime} @begin{Notes} For the Count attribute, the entry can be either a single entry or an entry of a family. The name of the entry or entry family can be either a @nt<direct_name> or an expanded name. Within task units, algorithms interrogating the attribute E'Count should take precautions to allow for the increase of the value of this attribute for incoming entry calls, and its decrease, for example with @nt{timed_entry_call}s. Also, a @nt{conditional_entry_call} may briefly increase this value, even if the conditional call is not accepted. Within protected units, algorithms interrogating the attribute E'Count in the @nt<entry_barrier> for the entry E should take precautions to allow for the evaluation of the @nt<condition> of the barrier both before and after queuing a given caller. @end{Notes} @LabeledClause{Shared Variables} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1],ARef=[AI05-0201-1],ARef=[AI05-0229-1],ARef=[AI05-0295-1]} @Defn2{Term=[shared variable], Sec=(protection of)} @Defn{independently addressable} If two different objects, including nonoverlapping parts of the same object, are @i{independently addressable}, they can be manipulated concurrently by two different tasks without synchronization. @Chg{Version=[3],New=[Any two nonoverlapping objects are independently addressable if either object is specified as independently addressable (see @RefSecNum{Shared Variable Control}). Otherwise, two nonoverlapping objects are independently addressable except when they are both parts of a composite object for which a nonconfirming value is specified for any of the following representation aspects: (record) Layout, Component_Size, Pack, Atomic, or Convention; in this case it is unspecified whether the parts are independently addressable.@PDefn{unspecified}], Old=[Normally, any two nonoverlapping objects are independently addressable. However, if packing, record layout, or Component_Size is specified for a given composite object, then it is implementation defined whether or not two nonoverlapping parts of that composite object are independently addressable.]} @ChgImplDef{Version=[3],Kind=[Deleted],InitialVersion=[0], Text=[@Chg{Version=[3],New=[],Old=[Whether or not two nonoverlapping parts of a composite object are independently addressable, in the case where packing, record layout, or Component_Size is specified for the object.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Independent addressability is the only high level semantic effect of @Chg{Version=[3],New=[aspect],Old=[a @nt{pragma}]} Pack. If two objects are independently addressable, the implementation should allocate them in such a way that each can be written by the hardware without writing the other. For example, unless the user asks for it, it is generally not feasible to choose a bit-packed representation on a machine without an atomic bit field insertion instruction, because there might be tasks that update neighboring subcomponents concurrently, and locking operations on all subcomponents is generally not a good idea. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Even if @Chg{Version=[3],New=[Pack],Old=[packing]} or one of the other above-mentioned aspects is specified, subcomponents should still be updated independently if the hardware efficiently supports it. @end{ImplNote} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1],ARef=[AI05-0201-1]} @ChgAdded{Version=[3],Text=[An atomic object (including atomic components) is always independently addressable from any other nonoverlapping object. Any @nt{aspect_specification} or representation item which would prevent this from being true should be rejected, notwithstanding what this Standard says elsewhere. Note, however, that the components of an atomic object are not necessarily atomic.]} @end{Ramification} @end{StaticSem} @begin{RunTime} @leading@redundant[Separate tasks normally proceed independently and concurrently with one another. However, task interactions can be used to synchronize the actions of two or more tasks to allow, for example, meaningful communication by the direct updating and reading of variables shared between the tasks.] The actions of two different tasks are synchronized in this sense when an action of one task @i(signals) an action of the other task; @Defn2{Term=[signal], Sec=(as defined between actions)} an action A1 is defined to signal an action A2 under the following circumstances: @begin(Itemize) If A1 and A2 are part of the execution of the same task, and the language rules require A1 to be performed before A2; If A1 is the action of an activator that initiates the activation of a task, and A2 is part of the execution of the task that is activated; If A1 is part of the activation of a task, and A2 is the action of waiting for completion of the activation; If A1 is part of the execution of a task, and A2 is the action of waiting for the termination of the task; @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0031],ARef=[AI95-00118-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0072-1]} @ChgAdded{Version=[1],Text=[If A1 is the termination of a task T, and A2 is either @Chg{Version=[3],New=[an],Old=[the]} evaluation of the expression T'Terminated@Chg{Version=[3],New=[ that results in True,],Old=[]} or a call to Ada.Task_Identification.Is_Terminated with an actual parameter that identifies T @Chg{Version=[3],New=[and a result of True ],Old=[]}(see @RefSecNum(The Package Task_Identification));]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} If A1 is the action of issuing an entry call, and A2 is part of the corresponding execution of the appropriate @nt<entry_body> or @nt<accept_statement>@Chg{Version=[3],New=[;],Old=[.]} @begin(Ramification) Evaluating the @nt<entry_index> of an @nt<accept_statement> is not synchronized with a corresponding entry call, nor is evaluating the entry barrier of an @nt<entry_body>. @end(Ramification) If A1 is part of the execution of an @nt<accept_statement> or @nt<entry_body>, and A2 is the action of returning from the corresponding entry call; If A1 is part of the execution of a protected procedure body or @nt<entry_body> for a given protected object, and A2 is part of a later execution of an @nt<entry_body> for the same protected object; @begin(Reason) The underlying principle here is that for one action to @lquotes@;signal@rquotes@; a second, the second action has to follow a potentially blocking operation, whose blocking is dependent on the first action in some way. Protected procedures are not potentially blocking, so they can only be "signalers," they cannot be signaled. @end(Reason) @begin(Ramification) Protected subprogram calls are not defined to signal one another, which means that such calls alone cannot be used to synchronize access to shared data outside of a protected object. @end(Ramification) @begin(Reason) The point of this distinction is so that on multiprocessors with inconsistent caches, the caches only need to be refreshed at the beginning of an entry body, and forced out at the end of an entry body or protected procedure that leaves an entry open. Protected function calls, and protected subprogram calls for entryless protected objects do not require full cache consistency. Entryless protected objects are intended to be treated roughly like atomic objects @em each operation is indivisible with respect to other operations (unless both are reads), but such operations cannot be used to synchronize access to other nonvolatile shared variables. @end(Reason) @Leading@Comment{This "Leading" is to help fit the next example on one page.} If A1 signals some action that in turn signals A2. @end(Itemize) @end{RunTime} @begin{Erron} @Leading@;@PDefn2{Term=(erroneous execution),Sec=(cause)} Given an action of assigning to an object, and an action of reading or updating a part of the same object (or of a neighboring object if the two are not independently addressable), then the execution of the actions is erroneous unless the actions are @i(sequential). @Defn2{Term=[sequential], Sec=(actions)} Two actions are sequential if one of the following is true: @begin(Itemize) One action signals the other; Both actions occur as part of the execution of the same task; @begin{Reason} Any two actions of the same task are sequential, even if one does not signal the other because they can be executed in an @lquotes@;arbitrary@rquotes@; (but necessarily equivalent to some @lquotes@;sequential@rquotes@;) order. @end{Reason} Both actions occur as part of protected actions on the same protected object, and at most one of the actions is part of a call on a protected function of the protected object. @begin(Reason) Because actions within protected actions do not always imply signaling, we have to mention them here explicitly to make sure that actions occurring within different protected actions of the same protected object are sequential with respect to one another (unless both are part of calls on protected functions). @end(Reason) @begin(Ramification) It doesn't matter whether or not the variable being assigned is actually a subcomponent of the protected object; globals can be safely updated from within the bodies of protected procedures or entries. @end(Ramification) @end(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[Aspect],Old=[A @nt{pragma}]} Atomic or @Chg{Version=[3],New=[aspect ],Old=[]}Atomic_Components may also be @Chg{Version=[3],New=[specified],Old=[used]} to ensure that certain reads and updates are sequential @em see @RefSecNum(Shared Variable Control). @begin(Ramification) If two actions are @lquotes@;sequential@rquotes@; it is known that their executions don't overlap in time, but it is not necessarily specified which occurs first. For example, all actions of a single task are sequential, even though the exact order of execution is not fully specified for all constructs. @end(Ramification) @begin(Discussion) Note that if two assignments to the same variable are sequential, but neither signals the other, then the program is not erroneous, but it is not specified which assignment ultimately prevails. Such a situation usually corresponds to a programming mistake, but in some (rare) cases, the order makes no difference, and for this reason this situation is not considered erroneous nor even a bounded error. In Ada 83, this was considered an @lquotes@;incorrect order dependence@rquotes@; if the @lquotes@;effect@rquotes@; of the program was affected, but @lquotes@;effect@rquotes@; was never fully defined. In Ada 95, this situation represents a potential nonportability, and a friendly compiler might want to warn the programmer about the situation, but it is not considered an error. An example where this would come up would be in gathering statistics as part of referencing some information, where the assignments associated with statistics gathering don't need to be ordered since they are just accumulating aggregate counts, sums, products, etc. @end(Discussion) @end{Erron} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0031],ARef=[AI95-00118-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a task T2 can rely on values of variables that are updated by another task T1, if task T2 first verifies that T1'Terminated is True.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1],ARef=[AI05-0201-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the definition of independent addressability to exclude conforming representation clauses and to require that atomic and independent objects always have independent addressability. This should not change behavior that the user sees for any Ada program, so it is not an inconsistency.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0072-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the wording of AI95-00118-01 to actually say what was intended (as described above).]} @end{DiffWord2005} @LabeledClause{Example of Tasking and Synchronization} @begin{Examples} @Leading@;The following example defines a buffer protected object to smooth variations between the speed of output of a producing task and the speed of input of some consuming task. For instance, the producing task might have the following structure: @begin(Example) @key(task) Producer; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(task body) Producer @key(is) @Chg{Version=[2],New=[Person : Person_Name; --@RI[ see @RefSecNum{Incomplete Type Declarations}]],Old=[Char : Character;]} @key(begin) @key(loop) ... --@RI[ @Chg{Version=[2],New=[simulate arrival of the next customer],Old=[produce the next character Char]}] Buffer.@Chg{Version=[2],New=[Append_Wait(Person)],Old=[Write(Char)]}; @key(exit) @key(when) @Chg{Version=[2],New=[Person = @key(null)],Old=[Char = ASCII.EOT]}; @key(end) @key(loop); @key(end) Producer; @end(Example) @leading@keepnext@;and the consuming task might have the following structure: @begin(Example) @key(task) Consumer; @Trailing@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]}@key(task body) Consumer @key(is) @Chg{Version=[2],New=[Person : Person_Name;],Old=[Char : Character;]} @key(begin) @key(loop) Buffer.@Chg{Version=[2],New=[Remove_First_Wait(Person)],Old=[Read(Char)]}; @key(exit) @key(when) @Chg{Version=[2],New=[Person = @key(null)],Old=[Char = ASCII.EOT]}; ... --@RI[ @Chg{Version=[2],New=[simulate serving a customer],Old=[consume the character Char]}] @key(end) @key(loop); @key(end) Consumer; @end(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} The buffer object contains an internal @Chg{Version=[2],New=[array],Old=[pool]} of @Chg{Version=[2],New=[person names],Old=[characters]} managed in a round-robin fashion. The @Chg{Version=[2],New=[array],Old=[pool]} has two indices, an In_Index denoting the @Chg{Version=[2],New=[index],Old=[space]} for the next input @Chg{Version=[2],New=[person name],Old=[character]} and an Out_Index denoting the @Chg{Version=[2],New=[index],Old=[space]} for the next output @Chg{Version=[2],New=[person name],Old=[character]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The Buffer is defined as an extension of the Synchronized_Queue interface (see @RefSecNum{Interface Types}), and as such promises to implement the abstraction defined by that interface. By doing so, the Buffer can be passed to the Transfer class-wide operation defined for objects of a type covered by Queue'Class.]} @begin(Example) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(protected) Buffer @key(is)@Chg{Version=[2],New=[ @key(new) Synchronized_Queue @key(with) --@RI[ see @RefSecNum{Interface Types}]],Old=[]} @key(entry) @Chg{Version=[2],New=[Append_Wait(Person : @key(in) Person_Name);],Old=[Read (C : @key(out) Character);]} @key(entry) @Chg{Version=[2],New=[Remove_First_Wait(Person : @key(out) Person_Name); @key(function) Cur_Count @key(return) Natural; @key(function) Max_Count @key(return) Natural; @key(procedure) Append(Person : @key(in) Person_Name); @key(procedure) Remove_First(Person : @key(out) Person_Name);],Old=[Write(C : @key(in) Character);]} @key(private) Pool : @Chg{Version=[2],New=[Person_Name_Array],Old=[String]}(1 .. 100); Count : Natural := 0; In_Index, Out_Index : Positive := 1; @key(end) Buffer; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(protected body) Buffer @key(is) @key(entry) @Chg{Version=[2],New=[Append_Wait(Person : @key(in) Person_Name)],Old=[Write(C : @key(in) Character)]} @key(when) Count < Pool'Length @key(is) @key(begin) @Chg{Version=[2],New=[Append(Person);],Old=[Pool(In_Index) := C; In_Index := (In_Index @key(mod) Pool'Length) + 1; Count := Count + 1;]} @key(end) @Chg{Version=[2],New=[Append_Wait],Old=[Write]}; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(procedure) Append(Person : @key(in) Person_Name) @key(is) @key(begin) @key(if) Count = Pool'Length @key(then) @key(raise) Queue_Error @key(with) "Buffer Full"; --@RI[ see @RefSecNum{Raise Statements}] @key(end if); Pool(In_Index) := Person; In_Index := (In_Index @key(mod) Pool'Length) + 1; Count := Count + 1; @key(end) Append;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key(entry) @Chg{Version=[2],New=[Remove_First_Wait(Person : @key(out) Person_Name)],Old=[Read(C : @key(out) Character)]} @key(when) Count > 0 @key(is) @key(begin) @Chg{Version=[2],New=[Remove_First(Person);],Old=[C := Pool(Out_Index); Out_Index := (Out_Index @key(mod) Pool'Length) + 1; Count := Count - 1;]} @key(end) @Chg{Version=[2],New=[Remove_First_Wait],Old=[Read; @key(end) Buffer]}; @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(procedure) Remove_First(Person : @key(out) Person_Name) @key(is) @key(begin) @key(if) Count = 0 @key(then) @key(raise) Queue_Error @key(with) "Buffer Empty"; --@RI[ see @RefSecNum{Raise Statements}] @key(end if); Person := Pool(Out_Index); Out_Index := (Out_Index @key(mod) Pool'Length) + 1; Count := Count - 1; @key(end) Remove_First;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(function) Cur_Count @key(return) Natural @key(is) @key(begin) @key(return) Buffer.Count; @key(end) Cur_Count;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[ @key(function) Max_Count @key(return) Natural @key(is) @key(begin) @key(return) Pool'Length; @key(end) Max_Count; @key(end) Buffer;]} @end(Example) @end{Examples} ���������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/10.mss���������������������������������������������������������������0000755�0001752�0001001�00000530221�12066652506�016374� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(10, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @LabeledSection{Program Structure and Compilation Issues} @Comment{$Source: e:\\cvsroot/ARM/Source/10.mss,v $} @Comment{$Revision: 1.102 $} @Comment{Corrigendum changes added, 2000/04/24, RLB} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[The overall structure of programs and the facilities for separate compilation are described in this @Chg{Version=[3],New=[clause],Old=[section]}. A @i(program) is a set of @i(partitions), each of which may execute in a separate address space, possibly on a separate computer. @ToGlossary{Term=<Program>, Text=<A @i(program) is a set of @i(partitions), each of which may execute in a separate address space, possibly on a separate computer. A partition consists of a set of library units.>} @ToGlossary{Term=<Partition>, Text=<A @i(partition) is a part of a program. Each partition consists of a set of library units. Each partition may run in a separate address space, possibly on a separate computer. A program may contain just one partition. A distributed program typically contains multiple partitions, which can execute concurrently.>} @Defn2{Term=[library unit],Sec=(informal introduction)} @Defn2{Term=[library_item],Sec=(informal introduction)} @Defn2{Term=[library],Sec=(informal introduction)} As explained below, a partition is constructed from @i{library units}. Syntactically, the declaration of a library unit is a @nt{library_item}, as is the body of a library unit. An implementation may support a concept of a @i{program library} (or simply, a @lquotes@;library@rquotes@;), which contains @nt{library_item}s and their subunits. @IndexSee{Term=[program library],See=(library)} Library units may be organized into a hierarchy of children, grandchildren, and so on.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[clause],Old=[section]} has two @Chg{Version=[3],New=[subclauses],Old=[clauses]}: @RefSec{Separate Compilation} discusses compile-time issues related to separate compilation. @RefSec{Program Execution} discusses issues related to what is traditionally known as @lquotes@;link time@rquotes@; and @lquotes@;run time@rquotes@; @em building and executing partitions. @end{Intro} @begin{MetaRules} @Defn{avoid overspecifying environmental issues} We should avoid specifying details that are outside the domain of the language itself. The standard is intended (at least in part) to promote portability of Ada programs at the source level. It is not intended to standardize extra-language issues such as how one invokes the compiler (or other tools), how one's source is represented and organized, version management, the format of error messages, etc. @Defn{safe separate compilation} @Defn2{Term=[separate compilation], Sec=(safe)} The rules of the language should be enforced even in the presence of separate compilation. Using separate compilation should not make a program less safe. @Defn{legality determinable via semantic dependences} It should be possible to determine the legality of a compilation unit by looking only at the compilation unit itself and the compilation units upon which it depends semantically. As an example, it should be possible to analyze the legality of two compilation units in parallel if they do not depend semantically upon each other. On the other hand, it may be necessary to look outside that set in order to generate code @em this is generally true for generic instantiation and inlining, for example. Also on the other hand, it is generally necessary to look outside that set in order to check @LinkTimeName@;s. See also the @lquotes@;generic contract model@rquotes@; @MetaRulesName of @RefSec{Generic Instantiation}. @end{MetaRules} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The @Chg{Version=[3],New=[clause],Old=[section]} organization mentioned above is different from that of RM83. @end{DiffWord83} @LabeledClause{Separate Compilation} @begin{Intro} @redundant[@Defn{separate compilation} @Defn2{Term=[compilation], Sec=(separate)} @ToGlossaryAlso{Term=<Program unit>, Text=<A @i(program unit) is either a package, a task unit, a protected unit, a protected entry, a generic unit, or an explicitly declared subprogram other than an enumeration literal. Certain kinds of program units can be separately compiled. Alternatively, they can appear physically nested within other program units.>} @ToGlossaryAlso{Term=<Compilation unit>, Text=<The text of a program can be submitted to the compiler in one or more @nt(compilation)s. Each @nt(compilation) is a succession of @nt(compilation_unit)s. A @nt(compilation_unit) contains either the declaration, the body, or a renaming of a program unit.>}] The representation for a @nt<compilation> is implementation-defined. @ImplDef{The representation for a @nt{compilation}.} @begin{Ramification} Some implementations might choose to make a @nt{compilation} be a source (text) file. Others might allow multiple source files to be automatically concatenated to form a single @nt{compilation}. Others still may represent the source in a nontextual form such as a parse tree. Note that the RM95 does not even define the concept of a source file. Note that a protected subprogram is a subprogram, and therefore a program unit. An instance of a generic unit is a program unit. A protected entry is a program unit, but protected entries cannot be separately compiled. @end{Ramification} @ToGlossaryAlso{Term=<Library unit>, Text=<A library unit is a separately compiled program unit, and is always a package, subprogram, or generic unit. Library units may have other (logically nested) library units as children, and may have other program units physically nested within them. @Defn(subsystem) A root library unit, together with its children and grandchildren and so on, form a @i(subsystem).>} @end{Intro} @begin{ImplPerm} An implementation may impose implementation-defined restrictions on @nt{compilation}s that contain multiple @nt<compilation_unit>s. @ImplDef{Any restrictions on @nt<compilation>s that contain multiple @nt<compilation_unit>s.} @begin{Discussion} For example, an implementation might disallow a @nt{compilation} that contains two versions of the same compilation unit, or that contains the declarations for library packages P1 and P2, where P1 precedes P2 in the @nt<compilation> but P1 has a @nt<with_clause> that mentions P2. @end{Discussion} @end{ImplPerm} @begin{DiffWord83} The interactions between language issues and environmental issues are left open in Ada 95. The environment concept is new. In Ada 83, the concept of the program library, for example, appeared to be quite concrete, although the rules had no force, since implementations could get around them simply by defining various mappings from the concept of an Ada program library to whatever data structures were actually stored in support of separate compilation. Indeed, implementations were encouraged to do so. In RM83, it was unclear which was the official definition of @lquotes@;program unit.@rquotes@; Definitions appeared in RM83-5, 6, 7, and 9, but not 12. Placing it here seems logical, since a program unit is sort of a potential compilation unit. @end{DiffWord83} @LabeledSubClause{Compilation Units - Library Units} @begin{Intro} @redundant[A @nt{library_item} is a compilation unit that is the declaration, body, or renaming of a library unit. Each library unit (except Standard) has a @i{parent unit}, which is a library package or generic library package.] @Defn2{Term=[child], Sec=(of a library unit)} A library unit is a @i{child} of its parent unit. The @i{root} library units are the children of the predefined library package Standard. @begin{Ramification} Standard is a library unit. @end{Ramification} @end{Intro} @begin{Syntax} @Syn{lhs=<compilation>,rhs="{@Syn2{compilation_unit}}"} @Syn{lhs=<compilation_unit>,rhs=" @Syn2{context_clause} @Syn2{library_item} | @Syn2{context_clause} @Syn2{subunit}"} @Syn{lhs=<library_item>,rhs="[@key{private}] @Syn2{library_unit_declaration} | @Syn2{library_unit_body} | [@key{private}] @Syn2{library_unit_renaming_declaration}"} @Syn{tabs=[P25], lhs=<library_unit_declaration>,rhs=" @Syn2{subprogram_declaration}@\| @Syn2{package_declaration} | @Syn2{generic_declaration}@\| @Syn2{generic_instantiation}"} @Syn{lhs=<library_unit_renaming_declaration>,rhs=" @Syn2{package_renaming_declaration} | @Syn2{generic_renaming_declaration} | @Syn2{subprogram_renaming_declaration}"} @Syn{lhs=<library_unit_body>,rhs="@Syn2{subprogram_body} | @Syn2{package_body}"} @Syn{lhs=<parent_unit_name>,rhs="@Syn2{name}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00397-01]} @ChgAdded{Version=[2],Text=[An @nt{overriding_indicator} is not allowed in a @nt{subprogram_declaration}, @nt{generic_instantiation}, or @nt{subprogram_renaming_declaration} that declares a library unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[All of the listed items syntactically include @nt{overriding_indicator}, but a library unit can never override anything. A majority of the ARG thought that allowing @key{not overriding} in that case would be confusing instead of helpful.]} @end{Reason} @end{Syntax} @begin{Intro} @Defn{library unit} @PDefn{library}@Comment{There is a different definition of library in 10.1.4.} @Seealso{Primary=[library],Other=[library level]} @Seealso{Primary=[library],Other=[library unit]} @Seealso{Primary=[library],Other=[library_item]} A @i{library unit} is a program unit that is declared by a @nt{library_item}. When a program unit is a library unit, the prefix @lquotes@;library@rquotes@; is used to refer to it (or @lquotes@;generic library@rquotes@; if generic), as well as to its declaration and body, as in @lquotes@;library procedure@rquotes@;, @lquotes@;library @nt{package_body}@rquotes@;, or @lquotes@;generic library package@rquotes@;. @Defn{compilation unit} The term @i{compilation unit} is used to refer to a @nt{compilation_unit}. When the meaning is clear from context, the term is also used to refer to the @nt{library_item} of a @nt{compilation_unit} or to the @nt{proper_body} of a @nt{subunit} @Redundant[(that is, the @nt{compilation_unit} without the @nt{context_clause} and the @key[separate] (@nt{parent_unit_name}))]. @begin{Discussion} @leading@keepnext@;In this example: @begin{Example} @key[with] Ada.Text_IO; @key[package] P @key[is] ... @key[end] P; @end{Example} the term @lquotes@;compilation unit@rquotes@; can refer to this text: @lquotes@;@key[with] Ada.Text_IO; @key[package] P @key[is] ... @key[end] P;@rquotes@; or to this text: @lquotes@;@key[package] P @key[is] ... @key[end] P;@rquotes@;. We use this shorthand because it corresponds to common usage. We like to use the word @lquotes@;unit@rquotes@; for declaration-plus-body things, and @lquotes@;item@rquotes@; for declaration or body separately (as in @nt{declarative_item}). The terms @lquotes@;@nt{compilation_unit},@rquotes@; @lquotes@;compilation unit,@rquotes@; and @lquotes@;@nt{subunit}@rquotes@; are exceptions to this rule. We considered changing @lquotes@;@nt{compilation_unit},@rquotes@; @lquotes@;compilation unit@rquotes@; to @lquotes@;@ntf{compilation_item},@rquotes@; @lquotes@;compilation item,@rquotes@; respectively, but we decided not to. @end{Discussion} @Defn2{Term=[parent declaration], Sec=(of a @nt{library_item})} @Defn2{Term=[parent declaration], Sec=(of a library unit)} The @i{parent declaration} of a @nt{library_item} (and of the library unit) is the declaration denoted by the @nt{parent_@!unit_name}, if any, of the @nt{defining_@!program_@!unit_name} of the @nt<library_item>. @Defn{root library unit} If there is no @nt{parent_@!unit_name}, the parent declaration is the declaration of Standard, the @nt{library_item} is a @i{root} @nt{library_item}, and the library unit (renaming) is a @i{root} library unit (renaming). The declaration and body of Standard itself have no parent declaration. @Defn2{Term=[parent unit], Sec=(of a library unit)} The @i{parent unit} of a @nt{library_item} or library unit is the library unit declared by its parent declaration. @begin{Discussion} The declaration and body of Standard are presumed to exist from the beginning of time, as it were. There is no way to actually write them, since there is no syntactic way to indicate lack of a parent. An attempt to compile a package Standard would result in Standard.Standard. @end{Discussion} @begin{Reason} Library units (other than Standard) have @lquotes@;parent declarations@rquotes@; and @lquotes@;parent units@rquotes@;. Subunits have @lquotes@;parent bodies@rquotes@;. We didn't bother to define the other possibilities: parent body of a library unit, parent declaration of a subunit, parent unit of a subunit. These are not needed, and might get in the way of a correct definition of @lquotes@;child.@rquotes@; @end{Reason} @Redundant[The children of a library unit occur immediately within the declarative region of the declaration of the library unit.] @Defn2{Term=[ancestor], Sec=(of a library unit)} The @i{ancestors} of a library unit are itself, its parent, its parent's parent, and so on. @Redundant[(Standard is an ancestor of every library unit.)] @Defn{descendant} The @i{descendant} relation is the inverse of the ancestor relation. @begin{Reason} These definitions are worded carefully to avoid defining subunits as children. Only library units can be children. We use the unadorned term @lquotes@;ancestors@rquotes@; here to concisely define both @lquotes@;ancestor unit@rquotes@; and @lquotes@;ancestor declaration.@rquotes@; @end{Reason} @Defn{public library unit} @Defn{public declaration of a library unit} @Defn{private library unit} @Defn{private declaration of a library unit} A @nt<library_unit_declaration> or a @nt<library_@!unit_@!renaming_@!declaration> is @i{private} if the declaration is immediately preceded by the reserved word @key{private}; it is otherwise @i{public}. A library unit is private or public according to its declaration. @Defn2{Term=[public descendant], Sec=(of a library unit)} The @i{public descendants} of a library unit are the library unit itself, and the public descendants of its public children. @Defn2{Term=[private descendant], Sec=(of a library unit)} Its other descendants are @i{private descendants}. @begin{Discussion} The first concept defined here is that a @nt<library_item> is either public or private (not in relation to anything else @em it's just a property of the library unit). The second concept is that a @nt<library_item> is a public descendant or private descendant @i{of a given ancestor}. A given @nt<library_item> can be a public descendant of one of its ancestors, but a private descendant of some other ancestor. A subprogram declared by a @nt{subprogram_body} (as opposed to a @nt{subprogram_declaration}) is always public, since the syntax rules disallow the reserved word @key[private] on a body. Note that a private library unit is a @i{public} descendant of itself, but a @i{private} descendant of its parent. This is because it is visible outside itself @em its privateness means that it is not visible outside its parent. Private children of Standard are legal, and follow the normal rules. It is intended that implementations might have some method for taking an existing environment, and treating it as a package to be @lquotes@;imported@rquotes@; into another environment, treating children of Standard in the imported environment as children of the imported package. @end{Discussion} @begin{Ramification} @leading@;Suppose we have a public library unit A, a private library unit A.B, and a public library unit A.B.C. A.B.C is a public descendant of itself and of A.B, but a private descendant of A; since A.B is private to A, we don't allow A.B.C to escape outside A either. This is similar to the situation that would occur with physical nesting, like this: @begin{Example} @key[package] A @key[is] @key[private] @key[package] B @key[is] @key[package] C @key[is] @key[end] C; @key[private] @key[end] B; @key[end] A; @end{Example} Here, A.B.C is visible outside itself and outside A.B, but not outside A. (Note that this example is intended to illustrate the visibility of program units from the outside; the visibility within child units is not quite identical to that of physically nested units, since child units are nested after their parent's declaration.) @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[For each library @nt{package_declaration} in the environment, there is an implicit declaration of a @i{limited view} of that library package.@Defn{limited view} The limited view of a package contains:]} @begin(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0129-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[For each@Chg{Version=[3],New=[],Old=[ nested]} @nt{package_declaration}@Chg{Version=[3],New=[ occurring immediately within the visible part],Old=[]}, a declaration of the limited view of that package, with the same @nt{defining_program_unit_name}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0108-1],ARef=[AI05-0129-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[For each @nt{type_declaration} @Chg{Version=[3],New=[occurring immediately within],Old=[in]} the visible part@Chg{Version=[3],New=[ that is not an @nt{incomplete_type_declaration}],Old=[]}, an incomplete view of the type@Chg{Version=[3],New=[ with no @nt{discriminant_part}],Old=[]}; if the @nt{type_declaration} is tagged, then the view is a tagged incomplete view.]} @begin{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0108-1]} @ChgAdded{Version=[3],Text=[The incomplete view of a type does not have a discriminant_part even if the @nt{type_declaration} does have one. This is necessary because semantic analysis (and the associated dependence on @nt{with_clause}s) would be necessary to determine the types of the discriminants.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0129-1]} @ChgAdded{Version=[3],Text=[No incomplete views of incomplete types are included in the limited view. The rules of @RefSecNum{Incomplete Type Declarations} ensure that the completion of any visible incomplete type is declared in the same visible part, so such an incomplete view would simply be redundant.]} @end{Reason} @end(Itemize) @begin(Discussion) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The implementation model of a limited view is that it can be determined solely from the syntax of the source of the unit, without any semantic analysis. That allows it to be created without the semantic dependences of a full unit, which is necessary for it to break mutual dependences of units.]} @end(Discussion) @begin(Ramification) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The limited view does not include package instances and their contents. Semantic analysis of a unit (and dependence on its @nt{with_clause}s) would be needed to determine the contents of an instance.]} @end(Ramification) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The limited view of a library @nt{package_declaration} is private if that library @nt{package_declaration} is immediately preceded by the reserved word @key{private}.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Redundant[There is no syntax for declaring limited views of packages, because they are always implicit.] The implicit declaration of a limited view of a library package @Redundant[is not the declaration of a library unit (the library @nt{package_declaration} is); nonetheless, it] is a @nt{library_item}. The implicit declaration of the limited view of a library package forms an (implicit) compilation unit whose @nt{context_clause} is empty.]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A library @nt{package_declaration} is the completion of the declaration of its limited view.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is notwithstanding the rule in @RefSecNum{Completions of Declarations} that says that implicit declarations don't have completions.]} @end{Honest} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule explains where to find the completions of the incomplete views defined by the limited view.]} @end{Reason} @end{Intro} @begin{Legality} The parent unit of a @nt<library_item> shall be a @Redundant[library] package or generic @Redundant[library] package. If a @nt{defining_program_unit_name} of a given declaration or body has a @nt{parent_unit_name}, then the given declaration or body shall be a @nt<library_item>. The body of a program unit shall be a @nt{library_item} if and only if the declaration of the program unit is a @nt<library_item>. In a @nt{library_@!unit_@!renaming_@!declaration}, the @Redundant[(old)] @nt{name} shall denote a @nt<library_item>. @begin{Discussion} We could have allowed nested program units to be children of other program units; their semantics would make sense. We disallow them to keep things simpler and because they wouldn't be particularly useful. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @nt{parent_unit_name} @Redundant[(which can be used within a @nt<defining_program_unit_name> of a @nt<library_item> and in the @key[separate] clause of a @nt<subunit>)], and each of its @nt{prefix}es, shall not denote a @nt{renaming_declaration}. @Redundant[On the other hand, a name that denotes a @nt{library_@!unit_@!renaming_@!declaration} is allowed in a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} and other places where the name of a library unit is allowed.] If a library package is an instance of a generic package, then every child of the library package shall either be itself an instance or be a renaming of a library unit. @begin{Discussion} A child of an instance of a given generic unit will often be an instance of a (generic) child of the given generic unit. This is not required, however. @end{Discussion} @begin{Reason} @leading@;Instances are forbidden from having noninstance children for two reasons: @begin(Enumerate) We want all source code that can depend on information from the private part of a library unit to be inside the "subsystem" rooted at the library unit. If an instance of a generic unit were allowed to have a noninstance as a child, the source code of that child might depend on information from the private part of the generic unit, even though it is outside the subsystem rooted at the generic unit. Disallowing noninstance children simplifies the description of the semantics of children of generic packages. @end(Enumerate) @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit.@Chg{Version=[3], New=[],Old=[ The renaming of a child of a generic package shall occur only within the declarative region of the generic package.]} A child of a parent generic package shall be instantiated or renamed only within the declarative region of the parent generic. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00331-01]} For each @Chg{Version=[2],New=[child @i<C>], Old=[declaration or renaming of a generic unit as a child]} of some parent generic package@Chg{Version=[2],New=[ @i<P>],Old=[]}, there is a corresponding declaration @Chg{Version=[2],New=[@i<C>],Old=[]} nested immediately within each instance @Chg{Version=[2],New=[of @i<P>. For the purposes of this rule, if a child @i<C> itself has a child @i<D>, each corresponding declaration for @i<C> has a corresponding child @i<D>], Old=[of the parent]}. @Redundant[@Chg{Version=[2],New=[The corresponding],Old=[This]} declaration @Chg{Version=[2],New=[for a child within an instance ],Old=[]}is visible only within the scope of a @nt{with_clause} that mentions the @Chg{Version=[2],New=[(original) ],Old=[]}child generic unit.] @begin{ImplNote} Within the child, like anything nested in a generic unit, one can make up-level references to the current instance of its parent, and thereby gain access to the formal parameters of the parent, to the types declared in the parent, etc. This @lquotes@;nesting@rquotes@; model applies even within the @nt{generic_formal_part} of the child, as it does for a generic child of a nongeneric unit. @end{ImplNote} @begin{Ramification} Suppose P is a generic library package, and P.C is a generic child of P. P.C can be instantiated inside the declarative region of P. Outside P, P.C can be mentioned only in a @nt{with_clause}. Conceptually, an instance I of P is a package that has a nested generic unit called I.C. Mentioning P.C in a @nt{with_clause} allows I.C to be instantiated. I need not be a library unit, and the instantiation of I.C need not be a library unit. If I is a library unit, and an instance of I.C is a child of I, then this instance has to be called something other than C. @end{Ramification} A library subprogram shall not override a primitive subprogram. @begin{Reason} This prevents certain obscure anomalies. For example, if a library subprogram were to override a subprogram declared in its parent package, then in a compilation unit that depends @i{in}directly on the library subprogram, the library subprogram could hide the overridden operation from all visibility, but the library subprogram itself would not be visible. Note that even without this rule, such subprograms would be illegal for tagged types, because of the freezing rules. @end{Reason} The defining name of a function that is a compilation unit shall not be an @nt{operator_symbol}. @begin{Reason} Since overloading is not permitted among compilation units, it seems unlikely that it would be useful to define one as an operator. Note that a subunit could be renamed within its parent to be an operator. @end{Reason} @end{Legality} @begin{StaticSem} A @nt<subprogram_renaming_declaration> that is a @nt{library_@!unit_@!renaming_@!declaration} is a renaming-as-declaration, not a renaming-as-body. @leading@keepnext@redundant[There are two kinds of dependences among compilation units:] @begin{Itemize} @redundant[The @i{semantic dependences} (see below) are the ones needed to check the compile-time rules across compilation unit boundaries; a compilation unit depends semantically on the other compilation units needed to determine its legality. The visibility rules are based on the semantic dependences. The @i{elaboration dependences} (see @RefSecNum{Program Execution}) determine the order of elaboration of @nt{library_item}s.] @end{Itemize} @begin{Discussion} Don't confuse these kinds of dependences with the run-time dependences among tasks and masters defined in @RefSec{Task Dependence - Termination of Tasks}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @Defn2{Term=[semantic dependence], Sec=(of one compilation unit upon another)} @Defn2{Term=[dependence], Sec=(semantic)} A @nt{library_item} depends semantically upon its parent declaration. A subunit depends semantically upon its parent body. A @nt{library_unit_body} depends semantically upon the corresponding @nt{library_unit_declaration}, if any. @Chg{Version=[2],New=[The declaration of the limited view of a library package depends semantically upon the declaration of the limited view of its parent. The declaration of a library package depends semantically upon the declaration of its limited view.],Old=[]} A compilation unit depends semantically upon each @nt<library_item> mentioned in a @nt{with_clause} of the compilation unit. In addition, if a given compilation unit contains an @nt{attribute_reference} of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. The semantic dependence relationship is transitive. @begin{Discussion} The @lquotes@;if any@rquotes@; in the third sentence is necessary because library subprograms are not required to have a @nt{subprogram_declaration}. @end{Discussion} @begin{Honest} If a given compilation unit contains a @nt{choice_parameter_specification}, then the given compilation unit depends semantically upon the declaration of Ada.Exceptions. If a given compilation unit contains a @nt{pragma} with an argument of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. @end{Honest} @begin{Discussion} For example, a compilation unit containing X'Address depends semantically upon the declaration of package System. For the Address attribute, this fixes a hole in Ada 83. Note that in almost all cases, the dependence will need to exist due to @nt{with_clause}s, even without this rule. Hence, the rule has very little effect on programmers. Note that the semantic dependence does not have the same effect as a @nt{with_clause}; in order to denote a declaration in one of those packages, a @nt{with_clause} will generally be needed. Note that no special rule is needed for an @nt{attribute_definition_clause}, since an expression after @key[use] will require semantic dependence upon the compilation unit containing the @nt{type_declaration} of interest. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Unlike a full view of a package, a limited view does not depend semantically on units mentioned in @nt{with_clause}s of the @nt{compilation_unit} that defines the package. Formally, this is achieved by saying that the limited view has an empty @nt{context_clause}. This is necessary so that they can be useful for their intended purpose: allowing mutual dependences between packages. The lack of semantic dependence limits the contents of a limited view to the items that can be determined solely from the syntax of the source of the package, without any semantic analysis. That allows it to be created without the semantic dependences of a full package.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The elaboration of the declaration of the limited view of a package has no effect.]} @end{RunTime} @begin{Notes} A simple program may consist of a single compilation unit. A @nt{compilation} need not have any compilation units; for example, its text can consist of @nt{pragma}s. @begin{Ramification} Such @nt{pragma}s cannot have any arguments that are @nt{name}s, by a previous rule of this subclause. A @nt{compilation} can even be entirely empty, which is probably not useful. Some interesting properties of the three kinds of dependence: The elaboration dependences also include the semantic dependences, except that subunits are taken together with their parents. The semantic dependences partly determine the order in which the compilation units appear in the environment at compile time. At run time, the order is partly determined by the elaboration dependences. @leading@;The model whereby a child is inside its parent's declarative region, after the parent's declaration, as explained in @RefSecNum{Declarative Region}, has the following ramifications: @begin(itemize) The restrictions on @lquotes@;early@rquotes@; use of a private type (RM83-7.4.1(4)) or a deferred constant (RM83-7.4.3(2)) do not apply to uses in child units, because they follow the full declaration. A library subprogram is never primitive, even if its profile includes a type declared immediately within the parent's @nt{package_specification}, because the child is not declared immediately within the same @nt{package_specification} as the type (so it doesn't declare a new primitive subprogram), and because the child is forbidden from overriding an old primitive subprogram. It is immediately within the same declarative region, but not the same @nt{package_specification}. Thus, for a tagged type, it is not possible to call a child subprogram in a dispatching manner. (This is also forbidden by the freezing rules.) Similarly, it is not possible for the user to declare primitive subprograms of the types declared in the declaration of Standard, such as Integer (even if the rules were changed to allow a library unit whose name is an operator symbol). When the parent unit is @lquotes@;used@rquotes@; the simple names of the with'd child units are directly visible (see @RefSec{Use Clauses}). When a parent body with's its own child, the defining name of the child is directly visible, and the parent body is not allowed to include a declaration of a homograph of the child unit immediately within the @nt{declarative_part} of the body (RM83-8.3(17)). @end(itemize) Note that @lquotes@;declaration of a library unit@rquotes@; is different from @lquotes@;@nt{library_unit_declaration}@rquotes@; @em the former includes @nt{subprogram_body}. Also, we sometimes really mean @lquotes@;declaration of a view of a library unit@rquotes@;, which includes @nt{library_@!unit_@!renaming_@!declaration}s. The visibility rules generally imply that the renamed view of a @nt{library_@!unit_@!renaming_@!declaration} has to be mentioned in a @nt{with_@!clause} of the @nt{library_@!unit_@!renaming_@!declaration}. @end{Ramification} @begin{Honest} The real rule is that the renamed library unit has to be visible in the @nt{library_@!unit_@!renaming_@!declaration}. @end{Honest} @begin{Reason} In most cases, @lquotes@;has to be visible@rquotes@; means there has to be a @nt{with_clause}. However, it is possible in obscure cases to avoid the need for a @nt{with_clause}; in particular, a compilation unit such as @lquotes@;@key[package] P.Q @key[renames] P;@rquotes@; is legal with no @nt{with_clause}s (though not particularly interesting). ASCII is physically nested in Standard, and so is not a library unit, and cannot be renamed as a library unit. @end{Reason} The @nt{designator} of a library function cannot be an @nt{operator_symbol}, but a nonlibrary @nt{renaming_declaration} is allowed to rename a library function as an operator. Within a partition, two library subprograms are required to have distinct names and hence cannot overload each other. However, @nt{renaming_declaration}s are allowed to define overloaded names for such subprograms, and a locally declared subprogram is allowed to overload a library subprogram. The expanded name Standard.L can be used to denote a root library unit L (unless the declaration of Standard is hidden) since root library unit declarations occur immediately within the declarative region of package Standard. @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of library units:} @begin{Example} @key[package] Rational_Numbers.IO @key[is] --@RI[ public child of Rational_Numbers, see @RefSecNum{Package Specifications and Declarations}] @key[procedure] Put(R : @key[in] Rational); @key[procedure] Get(R : @key[out] Rational); @key[end] Rational_Numbers.IO; @key[private procedure] Rational_Numbers.Reduce(R : @key[in out] Rational); --@RI[ private child of Rational_Numbers] @key[with] Rational_Numbers.Reduce; --@RI[ refer to a private child] @key[package body] Rational_Numbers @key[is] ... @key[end] Rational_Numbers; @key[with] Rational_Numbers.IO; @key[use] Rational_Numbers; @key[with] Ada.Text_io; --@RI[ see @RefSecNum{Text Input-Output}] @key[procedure] Main @key[is] --@RI[ a root library procedure] R : Rational; @key[begin] R := 5/3; --@RI[ construct a rational number, see @RefSecNum{Package Specifications and Declarations}] Ada.Text_IO.Put("The answer is: "); IO.Put(R); Ada.Text_IO.New_Line; @key[end] Main; @key[with] Rational_Numbers.IO; @key[package] Rational_IO @key[renames] Rational_Numbers.IO; --@RI[ a library unit renaming declaration] @end{Example} Each of the above @nt{library_item}s can be submitted to the compiler separately. @begin{Discussion} @leading@keepnext@i{Example of a generic package with children:} @begin{Example} @key[generic] @key[type] Element @key[is] @key[private]; @key[with] @key[function] Image(E : Element) @key[return] String; @key[package] Generic_Bags @key[is] @key[type] Bag @key[is] @key[limited] @key[private]; --@RI{ A bag of Elements.} @key[procedure] Add(B : @key[in] @key[out] Bag; E : Element); @key[function] Bag_Image(B : Bag) @key[return] String; @key[private] @key[type] Bag @key[is] ...; @key[end] Generic_Bags; @key[generic] @key[package] Generic_Bags.Generic_Iterators @key[is] ... --@RI{ various additional operations on Bags.} @key[generic] @key[with] @key[procedure] Use_Element(E : @key[in] Element); --@RI{ Called once per bag element.} @key[procedure] Iterate(B : @key[in] Bag); @key[end] Generic_Bags.Generic_Iterators; @end{Example} @begin{WideAbove} @leading@keepnext@;A package that instantiates the above generic units: @end{WideAbove} @begin{Example} @key[with] Generic_Bags; @key[with] Generic_Bags.Generic_Iterators; @key[package] My_Abstraction @key[is] @key[type] My_Type @key[is] ...; @key[function] Image(X : My_Type) @key[return] String; @key[package] Bags_Of_My_Type @key[is] @key[new] Generic_Bags(My_Type, Image); @key[package] Iterators_Of_Bags_Of_My_Type @key[is] @key[new] Bags_Of_My_Type.Generic_Iterators; @key[end] My_Abstraction; @end{Example} In the above example, Bags_Of_My_Type has a nested generic unit called Generic_Iterators. The second @nt{with_clause} makes that nested unit visible. @leading@;Here we show how the generic body could depend on one of its own children: @begin{Example} @key[with] Generic_Bags.Generic_Iterators; @key[package] @key[body] Generic_Bags @key[is] @key[procedure] Add(B : @key[in] @key[out] Bag; E : Element) @key[is] ... @key[end] Add; @key[package] Iters @key[is] @key[new] Generic_Iterators; @key[function] Bag_Image(B : Bag) @key[return] String @key[is] Buffer : String(1..10_000); Last : Integer := 0; @key[procedure] Append_Image(E : @key[in] Element) @key[is] Im : @key[constant] String := Image(E); @key[begin] @key[if] Last /= 0 @key[then] --@RI{ Insert a comma.} Last := Last + 1; Buffer(Last) := ','; @key[end] @key[if]; Buffer(Last+1 .. Last+Im'Length) := Im; Last := Last + Im'Length; @key[end] Append_Image; @key[procedure] Append_All @key[is] @key[new] Iters.Iterate(Append_Image); @key[begin] Append_All(B); @key[return] Buffer(1..Last); @key[end] Bag_Image; @key[end] Generic_Bags; @end{Example} @end{Discussion} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{library_item} is modified to allow the reserved word @key{private} before a @nt{library_unit_declaration}. Children (other than children of Standard) are new in Ada 95. Library unit renaming is new in Ada 95. @end{Extend83} @begin{DiffWord83} Standard is considered a library unit in Ada 95. This simplifies the descriptions, since it implies that the parent of each library unit is a library unit. (Standard itself has no parent, of course.) As in Ada 83, the language does not define any way to recompile Standard, since the name given in the declaration of a library unit is always interpreted in relation to Standard. That is, an attempt to compile a package Standard would result in Standard.Standard. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The concept of a limited view is new. Combined with @nt{limited_with_clause}s (see @RefSecNum{Context Clauses - With Clauses}), they facilitate construction of mutually recursive types in multiple packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00331-01]} @ChgAdded{Version=[2],Text=[Clarified the wording so that a grandchild generic unit will work as expected.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0108-1],ARef=[AI05-0129-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified the wording so that it is clear that limited views of types never have discriminants and never are of incomplete types.]} @end{DiffWord2005} @LabeledSubClause{Context Clauses - With Clauses} @begin{Intro} @redundant[A @nt{context_clause} is used to specify the @nt<library_item>s whose names are needed within a compilation unit.] @end{Intro} @begin{MetaRules} @Defn{one-pass @nt{context_clause}s} The reader should be able to understand a @nt{context_clause} without looking ahead. Similarly, when compiling a @nt{context_clause}, the compiler should not have to look ahead at subsequent @nt{context_item}s, nor at the compilation unit to which the @nt{context_clause} is attached. (We have not completely achieved this.) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{ripple effect}A @i<ripple effect> occurs when the legality of a compilation unit could be affected by adding or removing an otherwise unneeded @nt{with_clause} on some compilation unit on which the unit depends, directly or indirectly. We try to avoid ripple effects because they make understanding and maintenance more difficult. However, ripple effects can occur because of direct visibility (as in child units); this seems impossible to eliminate. The ripple effect for @nt{with_clause}s is somewhat similar to the Beaujolais effect (see @RefSecNum{Use Clauses}) for @nt{use_clause}s, which we also try to avoid.]} @end{MetaRules} @begin{Syntax} @Syn{lhs=<context_clause>,rhs="{@Syn2{context_item}}"} @Syn{lhs=<context_item>,rhs="@Syn2{with_clause} | @Syn2{use_clause}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00262-01]} @Syn{lhs=<with_clause>,rhs="@Chg{Version=[2],New=<@Syn2{limited_with_clause} | @Syn2{nonlimited_with_clause}>,Old=<@key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>}"} @ChgRef{Version=[2],Kind=[Added]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<limited_with_clause>,Old=<>}>,rhs="@Chg{Version=[2],New=<@key{limited} [@key{private}] @key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<nonlimited_with_clause>,Old=<>}>,rhs="@Chg{Version=[2],New=<[@key{private}] @key{with} @SynI{library_unit_}@Syn2{name} {, @SynI{library_unit_}@Syn2{name}};>,Old=<>}"} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[A @nt{limited_with_clause} makes a limited view of a unit visible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[@Defn{private with_clause}A @nt{with_clause} containing the reserved word @key{private} is called a @i{private with_clause}. It can be thought of as making items visible only in the private part, although it really makes items visible everywhere except the visible part. It can be used both for documentation purposes (to say that a unit is not used in the visible part), and to allow access to private units that otherwise would be prohibited.]} @end{Discussion} @end{Syntax} @begin{Resolution} @Defn2{Term=[scope], Sec=(of a @nt{with_clause})} The @i{scope} of a @nt{with_clause} that appears on a @nt{library_@!unit_@!declaration} or @nt{library_@!unit_@!renaming_@!declaration} consists of the entire declarative region of the declaration@Redundant[, which includes all children and subunits]. The scope of a @nt{with_clause} that appears on a body consists of the body@Redundant[, which includes all subunits]. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} Suppose a @Chg{Version=[2],New=[nonprivate ],Old=[]} @nt{with_clause} of a public library unit mentions one of its private siblings. (This is only allowed on the body of the public library unit.) We considered making the scope of that @nt{with_clause} not include the visible part of the public library unit. (This would only matter for a @nt{subprogram_body}, since those are the only kinds of body that have a visible part, and only if the @nt{subprogram_body} completes a @nt{subprogram_declaration}, since otherwise the @nt{with_clause} would be illegal.) We did not put in such a rule for two reasons: (1) It would complicate the wording of the rules, because we would have to split each @nt{with_clause} into pieces, in order to correctly handle @lquotes@;@key[with] P, Q;@rquotes@; where P is public and Q is private. (2) The conformance rules prevent any problems. It doesn't matter if a type name in the spec of the body denotes the completion of a @nt{private_type_declaration}. A @nt{with_clause} also affects visibility within subsequent @nt{use_clause}s and @nt{pragma}s of the same @nt{context_clause}, even though those are not in the scope of the @nt{with_clause}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} @Defn2{Term=[mentioned],Sec=[in a @nt<with_clause>]} @Defn2{Term=[with_clause], Sec=(mentioned in)} A @nt<library_item> @Chg{Version=[2],New=[(and the corresponding library unit) ],Old=[]}is @Chg{Version=[2],New=[@i{named} @Defn2{Term=[named],Sec=[in a @nt<with_clause>]} @Defn2{Term=[with_clause], Sec=(named in)}],Old=[@i{mentioned} ]}in a @nt<with_clause> if it is denoted by a @i(library_unit_)@nt<name> @Chg{Version=[2],New=[],Old=[or a @nt<prefix> ]} in the @nt<with_clause>. @Chg{Version=[2],New=[A @nt{library_item} (and the corresponding library unit) is @i<mentioned> in a @nt{with_clause} if it is named in the @nt{with_clause} or if it is denoted by a @nt{prefix} in the @nt{with_clause}.],Old=[]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @nt{With_clause}s control the visibility of declarations or renamings of library units. Mentioning a root library unit in a @nt{with_clause} makes its declaration directly visible. Mentioning a nonroot library unit makes its declaration visible. See @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Visibility Rules} for details. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Note that this rule implies that @lquotes@;@key{with} A.B.C;@rquotes@; is @chg{Version=[2],New=[almost ],Old=[]}equivalent to @lquotes@;@key{with} A, A.B, A.B.C;@rquotes@;@Chg{Version=[2],New=[.],Old=[]} The reason for making a @nt{with_clause} apply to all the ancestor units is to avoid @lquotes@;visibility holes@rquotes@; @em situations in which an inner program unit is visible while an outer one is not. Visibility holes would cause semantic complexity and implementation difficulty.@Chg{Version=[2],New=[ (This is not exactly equivalent because the latter @nt{with_clause} names A and A.B, while the previous one does not. Whether a unit is @ldquote@;named@rdquote does not have any effect on visibility, however, so it is equivalent for visibility purposes.)],Old=[]} @end{Discussion} @redundant[Outside its own declarative region, the declaration or renaming of a library unit can be visible only within the scope of a @nt{with_clause} that mentions it. The visibility of the declaration or renaming of a library unit otherwise follows from its placement in the environment.] @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} If a @nt{with_clause} of a given @nt<compilation_unit> mentions a private child of some library unit, then the given @nt{compilation_unit} shall be @Chg{Version=[2],New=[one of:], Old=[either the declaration of a private descendant of that library unit or the body or subunit of a @Redundant[(public or private)] descendant of that library unit.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the declaration, body, or subunit of a private descendant of that library unit;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00220-01],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the body or subunit of a public descendant of that library unit, but not a subprogram body acting as a subprogram declaration (see @RefSecNum{The Compilation Process}); or]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgAdded{Version=[2],Text=[the declaration of a public descendant of that library unit, in which case the @nt<with_clause> shall include the reserved word @key<private>.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} The purpose of this rule is to prevent a private child from being visible @Chg{Version=[2],New=[],Old=[(or even semantically depended-on) ]}from outside the subsystem rooted at its parent. @Chg{Version=[2],New=[A private child can be semantically depended-on without violating this principle if it is used in a private @nt{with_clause}.],Old=[]} @end{Reason} @begin{Discussion} This rule violates the one-pass @nt{context_clause}s @MetaRulesName. We rationalize this by saying that at least that @MetaRulesName works for legal compilation units. @leading@keepnext@;Example: @begin{Example} @key[package] A @key[is] @key[end] A; @key[package] A.B @key[is] @key[end] A.B; @key[private] @key[package] A.B.C @key[is] @key[end] A.B.C; @key[package] A.B.C.D @key[is] @key[end] A.B.C.D; @key[with] A.B.C; -- @RI[(1)] @key[private] @key[package] A.B.X @key[is] @key[end] A.B.X; @key[package] A.B.Y @key[is] @key[end] A.B.Y; @key[with] A.B.C; -- @RI[(2)] @key[package] @key[body] A.B.Y @key[is] @key[end] A.B.Y; @ChgRef{Version=[2],Kind=[Added]}@ChgAdded{Version=[2],Text=[@key[private] @key[with] A.B.C; -- @RI[(3)] @key[package] A.B.Z @key[is] @key[end] A.B.Z;]} @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} (1) is OK because it's a private child of A.B @em it would be illegal if we made A.B.X a public child of A.B. (2) is OK because it's the body of a child of A.B. @Chg{Version=[2],New=[(3) is OK because it's a child of A.B, and it is a private @nt{with_clause}.],Old=[]} It would be illegal to say @lquotes@;@key[with] A.B.C;@rquotes@; on any @nt{library_item} whose name does not start with @lquotes@;A.B@rquotes@;. Note that mentioning A.B.C.D in a @nt{with_clause} automatically mentions A.B.C as well, so @lquotes@;@key[with] A.B.C.D;@rquotes@; is illegal in the same places as @lquotes@;@key[with] A.B.C;@rquotes@;. @end{Discussion} @begin{Honest} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0005-1]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00262-01]} @ChgDeleted{Version=[3],Text=[For the purposes of this rule, if a @nt{subprogram_body} has no preceding @nt{subprogram_declaration}, the @nt{subprogram_body} should be considered a declaration and not a body. Thus, it is illegal for such a @nt{subprogram_body} to mention one of its siblings in a @Chg{Version=[2],New=[nonprivate ],Old=[]}@nt{with_clause} if the sibling is a private library unit.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1],ARef=[AI05-0122-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[A @nt<name> denoting a @Chg{Version=[3],New=[@nt{library_item} (or the corresponding declaration for a child of a generic within an instance @em see @RefSecNum{Compilation Units - Library Units}), if it],Old=[library item that]} is visible only due to being mentioned in one or more @nt<with_clause>s that include the reserved word @key<private>@Chg{Version=[3],New=[,],Old=[]} shall appear only within:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a private part;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a body, but not within the @nt<subprogram_specification> of a library subprogram body;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a private descendant of the unit on which one of these @nt<with_clause>s appear; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a pragma within a context clause.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules apply only if all of the @nt{with_clause}s that mention the name include the reserved word @key{private}. They do not apply if the name is mentioned in any @nt{with_clause} that does not include @key{private}.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1]} @ChgAdded{Version=[2],Text=[These rules make the @Chg{Version=[3],New=[@nt{library_item}],Old=[library item]} visible anywhere that is not visible outside the subsystem rooted at the @nt{compilation_unit} having the private @nt{with_clause}, including private parts of packages nested in the visible part, private parts of child packages, the visible part of private children, and context clause pragmas like Elaborate_All.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We considered having the scope of a private @nt{with_clause} not include the visible part. However, that rule would mean that moving a declaration between the visible part and the private part could change its meaning from one legal interpretation to a different legal interpretation. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} A @key{is} @key{function} B @key{return} Integer; @key{end} A;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{function} B @key{return} Integer;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} A; @key{private} @key{with} B; @key{package} C @key{is} @key{use} A; V1 : Integer := B; -- (1) @key{private} V2 : Integer := B; -- (2) @key{end} C;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If we say that library subprogram B is not in scope in the visible part of C, then the B at (1) resolves to A.B, while (2) resolves to library unit B. Simply moving a declaration could silently change its meaning. With the legality rule defined above, the B at (1) is illegal. If the user really meant A.B, they still can say that.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Redundant[A @nt{library_item} mentioned in a @nt{limited_with_clause} shall be the implicit declaration of the limited view of a library package, not the declaration of a subprogram, generic unit, generic instance, or a renaming.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is redundant because only such implicit declarations are visible in a @nt{limited_with_clause}. See @RefSecNum{Environment-Level Visibility Rules}.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[A @nt{limited_with_clause} shall not appear on a @nt{library_unit_body}, @nt{subunit}, or @nt{library_@!unit_@!renaming_@!declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00412-01]} @ChgAdded{Version=[2],Text=[We don't allow a @nt{limited_with_clause} on a @nt{library_@!unit_@!renaming_@!declaration} because it would be useless and therefore probably is a mistake. A renaming cannot appear in a @nt{limited_with_clause} (by the rule prior to this one), and a renaming of a limited view cannot appear in a @nt{nonlimited_with_clause} (because the name would not be within the scope of a @nt{with_clause} denoting the package, see @RefSecNum{Package Renaming Declarations}). Nor could it be the parent of another unit. That doesn't leave anywhere that the name of such a renaming @b<could> appear, so we simply make writing it illegal.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[A @nt{limited_with_clause} that names a library package shall not appear:]} @begin(Itemize) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0040-1]} @ChgAdded{Version=[2],Text=[in the @nt{context_clause} for the explicit declaration of the named library package@Chg{Version=[3],New=[ or any of its descendants],Old=[]};]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to explicitly disallow]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{limited} @key{with} P; @key{package} P @key{is} ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[as we can't depend on the semantic dependence rules to do it for us as with regular withs. This says @lquotes@;named@rquotes and not @lquotes@;mentioned@rquotes in order that]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{limited} @key{private} @key{with} P.Child; @key{package} P @key{is} ...]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[can be used to allow a mutual dependence between the private part of P and the private child P.Child, which occurs in interfacing and other problems. Since the child always semantically depends on the parent, this is the only way such a dependence can be broken.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0040-1]} @ChgAdded{Version=[3],Text=[The part about descendants catches examples like]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{limited} @key{with} P; @key{package} P.Child @key{is} ...]} @end{Example} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[within a], Old=[in the same]} @nt{context_clause} @Chg{Version=[3],New=[for a @nt{library_item} that is],Old=[as, or]} within the scope of@Chg{Version=[3],New=[],Old=[,]} a @nt{nonlimited_with_clause} that mentions the same library package; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0077-1]} @ChgAdded{Version=[3],Text=[This applies to @nt{nonlimited_with_clause}s found in the same @nt{context_clause}, as well as @nt{nonlimited_with_clause}s found on parent units.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1]} @ChgAdded{Version=[2],Text=[Such a @nt{limited_with_clause} could have no effect, and would be confusing. If@Chg{Version=[3],New=[],Old=[ it is within the scope of]} a @nt{nonlimited_with_clause}@Chg{Version=[3],New=[ for the same package is inherited from a parent unit or given],Old=[, or if such a clause is]} in the @nt{context_clause}, the full view is available, which strictly provides more information than the limited view.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[within a], Old=[in the same]} @nt{context_clause} @Chg{Version=[3],New=[for a @nt{library_item} that is],Old=[as, or]} within the scope of@Chg{Version=[3],New=[],Old=[,]} a @nt{use_clause} that names an entity declared within the declarative region of the library package.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0077-1]} @ChgAdded{Version=[3],Text=[This applies to @nt{use_clause}s found in the same @nt{context_clause}, as well as @nt{use_clause}s found in (or on) parent units.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents visibility issues, where whether an entity is an incomplete or full view depends on how the name of the entity is written. The @nt{limited_with_clause} cannot be useful, as we must have the full view available in the parent in order for the @nt{use_clause} to be legal.]} @end{Reason} @end(Itemize) @end{Legality} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} A @nt<library_item> mentioned in a @Chg{Version=[2], New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]} of a compilation unit is visible within the compilation unit and hence acts just like an ordinary declaration. Thus, within a compilation unit that mentions its declaration, the name of a library package can be given in @nt{use_clause}s and can be used to form expanded names, a library subprogram can be called, and instances of a generic library unit can be declared. If a child of a parent generic package is mentioned in a @Chg{Version=[2], New=[@nt{nonlimited_with_clause}],Old=[@nt{with_clause}]}, then the corresponding declaration nested within each visible instance is visible within the compilation unit.@Chg{Version=[2], New=[ Similarly, a @nt{library_item} mentioned in a @nt{limited_with_clause} of a compilation unit is visible within the compilation unit and thus can be used to form expanded names.],Old=[]} @begin{Ramification} The rules given for @nt{with_clause}s are such that the same effect is obtained whether the name of a library unit is mentioned once or more than once by the applicable @nt{with_clause}s, or even within a given @nt{with_clause}. If a @nt{with_clause} mentions a @nt{library_@!unit_@!renaming_@!declaration}, it only @lquotes@;mentions@rquotes@; the @nt<prefix>es appearing explicitly in the @nt<with_clause> (and the renamed view itself); the @nt{with_clause} is not defined to mention the ancestors of the renamed entity. Thus, if X renames Y.Z, then @lquotes@;with X;@rquotes@; does not make the declarations of Y or Z visible. Note that this does not cause the dreaded visibility holes mentioned above. @end{Ramification} @end{Notes} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(package) Office @key(is) @key{end} Office;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(with) Ada.Strings.Unbounded; @key(package) Office.Locations @key(is) @key(type) Location @key(is new) Ada.Strings.Unbounded.Unbounded_String; @key(end) Office.Locations;]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key(limited with) Office.Departments; --@RI[ types are incomplete] @key(private with) Office.Locations; --@RI[ only visible in private part] @key(package) Office.Employees @key(is) @key(type) Employee @key(is private);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key(function) Dept_Of(Emp : Employee) @key(return access) Departments.Department; @key(procedure) Assign_Dept(Emp : @key(in out) Employee; Dept : @key(access) Departments.Department);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key(private type) Employee @key(is record) Dept : @key(access) Departments.Department; Loc : Locations.Location; ... @key(end record); @key(end) Office.Employees;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key(limited with) Office.Employees; @key(package) Office.Departments @key(is) @key(type) Department @key(is private);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key(function) Manager_Of(Dept : Department) @key(return access) Employees.Employee; @key(procedure) Assign_Manager(Dept : @key(in out) Department; Mgr : @key(access) Employees.Employee); ... @key(end) Office.Departments;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[The @nt{limited_with_clause} may be used to support mutually dependent abstractions that are split across multiple packages. In this case, an employee is assigned to a department, and a department has a manager who is an employee. If a @nt{with_clause} with the reserved word @key(private) appears on one library unit and mentions a second library unit, it provides visibility to the second library unit, but restricts that visibility to the private part and body of the first unit. The compiler checks that no use is made of the second unit in the visible part of the first unit.]} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{with_clause} is modified to allow expanded name notation. A @nt<use_clause> in a @nt<context_clause> may be for a package (or type) nested in a library package. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{context_clause} is modified to more closely reflect the semantics. The Ada 83 syntax rule implies that the @nt{use_clause}s that appear immediately after a particular @nt{with_clause} are somehow attached to that @nt{with_clause}, which is not true. The new syntax allows a @nt{use_clause} to appear first, but that is prevented by a textual rule that already exists in Ada 83. The concept of @lquotes@;scope of a @nt{with_clause}@rquotes@; (which is a region of text) replaces RM83's notion of @lquotes@;apply to@rquotes@; (a @nt{with_clause} applies to a @nt{library_item}) The visibility rules are interested in a region of text, not in a set of compilation units. No need to define @lquotes@;apply to@rquotes@; for @nt{use_clause}s. Their semantics are fully covered by the @lquotes@;scope (of a @nt{use_clause})@rquotes@; definition in @RefSecNum{Use Clauses}. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00220-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] A subprogram body acting as a declaration cannot @key[with] a private child unit. This would allow public export of types declared in private child packages, and thus cannot be allowed. This was allowed by mistake in Ada 95; a subprogram that does this will now be illegal.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{limited_with_clause}s are new. They make a limited view of a package visible, where all of the types in the package are incomplete. They facilitate construction of mutually recursive types in multiple packages.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00262-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0077-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The syntax rules for @nt{with_clause} are modified to allow the reserved word @key{private}. Private @nt{with_clause}s do not allow the use of their @Chg{Version=[3],New=[@nt{library_item}],Old=[library item]} in the visible part of their @nt{compilation_unit}. They also allow using private units in more locations than in Ada 95.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0040-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added missing rule that a limited with clause cannot name an ancestor unit. This is incompatible if an Ada 2005 program does this, but as this is a new Ada 2005 feature and the unintentionally allowed capability is not useful, the incompatibility is very unlikely to occur in practice.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0077-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Fixed wording so that we are not checking whether something in a @nt{context_clause} is @ldquote@;within the scope of@rdquote something, as @nt{context_clause}s are never included in anything's scope. The intended meaning is unchanged, however.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0122-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Fixed wording so the rules for private with clauses also apply to "sprouted" generic child units.]} @end{DiffWord2005} @LabeledSubClause{Subunits of Compilation Units} @begin{Intro} @redundant[Subunits are like child units, with these (important) differences: subunits support the separate compilation of bodies only (not declarations); the parent contains a @nt{body_stub} to indicate the existence and place of each of its subunits; declarations appearing in the parent's body can be visible within the subunits.] @end{Intro} @begin{Syntax} @Syn{lhs=<body_stub>,rhs="@Syn2{subprogram_body_stub} | @Syn2{package_body_stub} | @Syn2{task_body_stub} | @Syn2{protected_body_stub}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0267-1]} @Syn{lhs=<subprogram_body_stub>,rhs="@Chg{Version=[2],New=< [@Syn2{overriding_indicator}] >,Old=[]}@Syn2{subprogram_specification} @key{is} @key{separate}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @begin{Discussion} Although this syntax allows a @nt{parent_unit_name}, that is disallowed by @RefSec{Compilation Units - Library Units}. @end{Discussion} @Syn{lhs=<package_body_stub>,rhs="@Chg{Version=[3],New=< >,Old=[]}@key{package} @key{body} @Syn2{defining_identifier} @key{is} @key{separate}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<task_body_stub>,rhs="@Chg{Version=[3],New=< >,Old=[]}@key{task} @key{body} @Syn2{defining_identifier} @key{is} @key{separate}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<protected_body_stub>,rhs="@Chg{Version=[3],New=< >,Old=[]}@key{protected} @key{body} @Syn2{defining_identifier} @key{is} @key{separate}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<subunit>,rhs="@key{separate} (@Syn2{parent_unit_name}) @Syn2{proper_body}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00243-01]} @Defn2{Term=[parent body], Sec=(of a subunit)} The @i{parent body} of a subunit is the body of the program unit denoted by its @nt{parent_unit_name}. @Defn{subunit} The term @i{subunit} is used to refer to a @nt{subunit} and also to the @nt{proper_body} of a @nt{subunit}. @Chg{Version=[2],New=<The @i<subunits of a program unit> include any subunit that names that program unit as its parent, as well as any subunit that names such a subunit as its parent (recursively).@Defn2{Term=[subunit], Sec=(of a program unit)}>,Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00243-01]} @ChgAdded{Version=[2],Text=[We want any rule that applies to a subunit to apply to a subunit of a subunit as well.]} @end{Reason} The parent body of a subunit shall be present in the current environment, and shall contain a corresponding @nt{body_stub} with the same @nt{defining_identifier} as the subunit. @begin{Discussion} This can't be a @ResolutionName, because a @nt{subunit} is not a complete context. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} A @nt{package_body_stub} shall be the completion of a @nt{package_@!declaration} or @nt{generic_@!package_@!declaration}; a @nt{task_@!body_@!stub} shall be the completion of a @Chg{Version=[3],New=[task declaration],Old=[@ntf{task_@!declaration}]}; a @nt{protected_@!body_stub} shall be the completion of a @Chg{Version=[3],New=[protected declaration],Old=[@ntf{protected_@!declaration}]}. In contrast, a @nt{subprogram_body_stub} need not be the completion of a previous declaration, @Redundant[in which case the @ntf{_stub} declares the subprogram]. If the @ntf{_stub} is a completion, it shall be the completion of a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}. The profile of a @nt{subprogram_body_stub} that completes a declaration shall conform fully to that of the declaration. @Defn2{Term=[full conformance],Sec=(required)} @begin{Discussion} The part about @nt{subprogram_body_stub}s echoes the corresponding rule for @ntf{subprogram_bodies} in @RefSec{Subprogram Bodies}. @end{Discussion} A subunit that corresponds to a @nt{body_stub} shall be of the same kind (@ntf{package_}, @ntf{subprogram_}, @ntf{task_}, or @ntf{protected_}) as the @nt{body_stub}. The profile of a @nt{subprogram_body} subunit shall be fully conformant to that of the corresponding @nt{body_stub}. @Defn2{Term=[full conformance],Sec=(required)} A @nt{body_stub} shall appear immediately within the @nt{declarative_part} of a compilation unit body. This rule does not apply within an instance of a generic unit. @begin{Discussion} @Defn{methodological restriction} This is a methodological restriction; that is, it is not necessary for the semantics of the language to make sense. @end{Discussion} The @nt{defining_identifier}s of all @nt{body_stub}s that appear immediately within a particular @nt{declarative_part} shall be distinct. @end{Legality} @begin{LinkTime} For each @nt{body_stub}, there shall be a subunit containing the corresponding @nt{proper_body}. @end{LinkTime} @begin{Notes} @leading@;The rules in @RefSec{The Compilation Process} say that a @nt{body_stub} is equivalent to the corresponding @nt{proper_body}. This implies: @begin{Itemize} Visibility within a subunit is the visibility that would be obtained at the place of the corresponding @nt{body_stub} (within the parent body) if the @nt{context_clause} of the subunit were appended to that of the parent body. @begin{Ramification} Recursively. Note that this transformation might make the parent illegal; hence it is not a true equivalence, but applies only to visibility within the subunit. @end{Ramification} The effect of the elaboration of a @nt{body_stub} is to elaborate the subunit. @begin{Ramification} The elaboration of a subunit is part of its parent body's elaboration, whereas the elaboration of a child unit is not part of its parent declaration's elaboration. @end{Ramification} @end{Itemize} @begin{Ramification} A @nt<library_item> that is mentioned in a @nt{with_clause} of a subunit can be hidden (from direct @Chg{Version=[2],New=[visibility], Old=[visiblity]}) by a declaration (with the same @nt{identifier}) given in the subunit. Moreover, such a @nt<library_item> can even be hidden by a declaration given within the parent body since a library unit is declared in its parent's declarative region; this however does not affect the interpretation of the @nt{with_clause}s themselves, since only @nt<library_item>s are visible or directly visible in @nt{with_clause}s. The body of a protected operation cannot be a subunit. This follows from the syntax rules. The body of a protected unit can be a subunit. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@;The package Parent is first written without subunits: @begin{Example} @key[package] Parent @key[is] @key[procedure] Inner; @key[end] Parent; @key[with] Ada.Text_IO; @key[package] @key[body] Parent @key[is] Variable : String := "Hello, there."; @key[procedure] Inner @key[is] @key[begin] Ada.Text_IO.Put_Line(Variable); @key[end] Inner; @key[end] Parent; @end{Example} @begin{WideAbove} @leading@;The body of procedure Inner may be turned into a subunit by rewriting the package body as follows (with the declaration of Parent remaining the same): @end{WideAbove} @begin{Example} @key[package] @key[body] Parent @key[is] Variable : String := "Hello, there."; @key[procedure] Inner @key[is] @key[separate]; @key[end] Parent; @key[with] Ada.Text_IO; @key[separate](Parent) @key[procedure] Inner @key[is] @key[begin] Ada.Text_IO.Put_Line(Variable); @key[end] Inner; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Subunits of the same ancestor library unit are no longer restricted to have distinct identifiers. Instead, we require only that the full expanded names be distinct. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{overriding_indicator} (see @RefSecNum{Overriding Indicators}) is allowed on a subprogram stub.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00243-01]} @ChgAdded{Version=[2],Text=[Clarified that a subunit of a subunit is still a subunit.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{body_stub}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledSubClause{The Compilation Process} @begin{Intro} @Defn{environment} @Defn{environment @nt<declarative_part>} Each compilation unit submitted to the compiler is compiled in the context of an @i{environment} @nt<declarative_part> (or simply, an @i{environment}), which is a conceptual @nt<declarative_part> that forms the outermost declarative region of the context of any @nt{compilation}. At run time, an environment forms the @nt<declarative_part> of the body of the environment task of a partition (see @RefSec{Program Execution}). @begin{Ramification} At compile time, there is no particular construct that the declarative region is considered to be nested within @em the environment is the universe. @end{Ramification} @begin{Honest} The environment is really just a portion of a @nt{declarative_part}, since there might, for example, be bodies that do not yet exist. @end{Honest} The @nt{declarative_item}s of the environment are @nt{library_item}s appearing in an order such that there are no forward semantic dependences. Each included subunit occurs in place of the corresponding stub. The visibility rules apply as if the environment were the outermost declarative region, except that @nt{with_@!clause}s are needed to make declarations of library units visible (see @RefSecNum{Context Clauses - With Clauses}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} The mechanisms for creating an environment and for adding and replacing compilation units within an environment are implementation defined.@Chg{Version=[2],New=[ The mechanisms for adding a compilation unit mentioned in a @nt{limited_with_clause} to an environment are implementation defined.],Old=[]} @ImplDef{The mechanisms for creating an environment and for adding and replacing compilation units.} @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[The mechanisms for adding a compilation unit mentioned in a @nt{limited_with_clause} to an environment.],Old=[]}]} @begin{Ramification} The traditional model, used by most Ada 83 implementations, is that one places a compilation unit in the environment by compiling it. Other models are possible. For example, an implementation might define the environment to be a directory; that is, the compilation units in the environment are all the compilation units in the source files contained in the directory. In this model, the mechanism for replacing a compilation unit with a new one is simply to edit the source file containing that compilation unit. @end{Ramification} @end{Intro} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0032],ARef=[AI95-00192-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If a @nt<library_unit_body> that is a @nt<subprogram_body> is submitted to the compiler, it is interpreted only as a completion if a @nt<library_unit_declaration> @Chg{New=[], Old=[for a subprogram or a generic subprogram ]}with the same @nt<defining_program_unit_name> already exists in the environment @Chg{New=[for a subprogram other than an instance of a generic subprogram or for a generic subprogram ], Old=[]} (even if the profile of the body is not type conformant with that of the declaration); otherwise@Chg{Version=[3],New=[,],Old=[]} the @nt<subprogram_body> is interpreted as both the declaration and body of a library subprogram. @PDefn{type conformance} @begin{Ramification} The principle here is that a @nt{subprogram_body} should be interpreted as only a completion if and only if it @lquotes@;might@rquotes@; be legal as the completion of some preexisting declaration, where @lquotes@;might@rquotes@; is defined in a way that does not require overload resolution to determine. Hence, if the preexisting declaration is a @nt{subprogram_declaration} or @nt{generic_subprogram_declaration}, we treat the new @nt{subprogram_body} as its completion, because it @lquotes@;might@rquotes@; be legal. If it turns out that the profiles don't fully conform, it's an error. In all other cases (the preexisting declaration is a package or a generic package, or an instance of a generic subprogram, or a renaming, or a @lquotes@;spec-less@rquotes@; subprogram, or in the case where there is no preexisting thing), the @nt{subprogram_body} declares a new subprogram. See also AI83-00266/09. @end{Ramification} @end{Resolution} @begin{Legality} When a compilation unit is compiled, all compilation units upon which it depends semantically shall already exist in the environment; @Defn2{Term=[consistency], Sec=(among compilation units)} the set of these compilation units shall be @i{consistent} in the sense that the new compilation unit shall not semantically depend (directly or indirectly) on two different versions of the same compilation unit, nor on an earlier version of itself. @begin{Discussion} For example, if package declarations A and B both say @lquotes@;@key[with] X;@rquotes@;, and the user compiles a compilation unit that says @lquotes@;@key[with] A, B;@rquotes@;, then the A and B have to be talking about the same version of X. @end{Discussion} @begin{Ramification} What it means to be a @lquotes@;different version@rquotes@; is not specified by the language. In some implementations, it means that the compilation unit has been recompiled. In others, it means that the source of the compilation unit has been edited in some significant way. Note that an implementation cannot require the existence of compilation units upon which the given one does not semantically depend. For example, an implementation is required to be able to compile a compilation unit that says "@key{with} A;" when A's body does not exist. It has to be able to detect errors without looking at A's body. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Similarly, the implementation has to be able to compile a call to a subprogram for which @Chg{Version=[3],New=[aspect],Old=[a @nt{pragma}]} Inline has been specified without seeing the body of that subprogram @em inlining would not be achieved in this case, but the call is still legal. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[The @Chg{Version=[2],New=[consistency], Old=[second]} rule applies to limited views as well as the full view of a compilation unit. That means that an implementation needs a way to enforce consistency of limited views, not just of full views.]} @end{Ramification} @end{Legality} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} The implementation may require that a compilation unit be legal before @Chg{Version=[2],New=[it can be mentioned in a @nt{limited_with_clause} or it can be inserted],Old=[inserting it]} into the environment. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00214-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} When a compilation unit that declares or renames a library unit is added to the environment, the implementation may remove from the environment any preexisting @nt<library_item> @Chg{Version=[2],New=[or @nt<subunit> with the same full expanded name], Old=[with the same @nt<defining_@!program_@!unit_name>]}. When a compilation unit that is a subunit or the body of a library unit is added to the environment, the implementation may remove from the environment any preexisting version of the same compilation unit. @Chg{Version=[2],New=[When a compilation unit that contains a @nt<body_stub> is added to the environment, the implementation may remove any preexisting @nt<library_item> or @nt<subunit> with the same full expanded name as the @nt<body_stub>.],Old=[]} When a given compilation unit is removed from the environment, the implementation may also remove any compilation unit that depends semantically upon the given one. If the given compilation unit contains the body of a subprogram @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[aspect],Old=[a @nt{pragma}]} Inline @Chg{Version=[3],New=[is True],Old=[applies]}, the implementation may also remove any compilation unit containing a call to that subprogram. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The permissions given in this paragraph correspond to the traditional model, where compilation units enter the environment by being compiled into it, and the compiler checks their legality at that time. @Chg{Version=[3],New=[An],Old=[A]} implementation model in which the environment consists of all source files in a given directory might not want to take advantage of these permissions. Compilation units would not be checked for legality as soon as they enter the environment; legality checking would happen later, when compilation units are compiled. In this model, compilation units might never be automatically removed from the environment; they would be removed when the user explicitly deletes a source file. Note that the rule is recursive: if the above permission is used to remove a compilation unit containing an inlined subprogram call, then compilation units that depend semantically upon the removed one may also be removed, and so on. Note that here we are talking about dependences among existing compilation units in the environment; it doesn't matter what @nt{with_clause}s are attached to the new compilation unit that triggered all this. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation may have other modes in which compilation units in addition to the ones mentioned above are removed. For example, an implementation might inline subprogram calls without an explicit @Chg{Version=[3],New=[aspect],Old=[@nt{pragma}]} Inline. If so, it either has to have a mode in which that optimization is turned off, or it has to automatically regenerate code for the inlined calls without requiring the user to resubmit them to the compiler. @end{Ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0108],ARef=[AI95-00077-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @ChgAdded{Version=[1],Text=[In the standard mode, implementations may only remove units from the environment for one of the reasons listed here, or in response to an explicit user command to modify the environment. It is not intended that the act of compiling a unit is one of the @lquotes@;@Chg{Version=[2],New=[mechanisms],Old=[mechansisms]}@rquotes for removing units other than those specified by this International Standard.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00214-01]} @ChgAdded{Version=[2],Text=[These rules are intended to ensure that an implementation never need keep more than one compilation unit with any full expanded name. In particular, it is not necessary to be able to have a subunit and a child unit with the same name in the environment at one time.]} @end{Discussion} @end{ImplPerm} @begin{Notes} The rules of the language are enforced across @nt{compilation} and compilation unit boundaries, just as they are enforced within a single compilation unit. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Note that @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{General} requires an implementation to detect illegal compilation units at compile time. @end{Ramification} @Defn{library} An implementation may support a concept of a @i{library}, which contains @nt{library_item}s. If multiple libraries are supported, the implementation has to define how a single environment is constructed when a compilation unit is submitted to the compiler. Naming conflicts between different libraries might be resolved by treating each library as the root of a hierarchy of child library units. @IndexSee{Term=[program library],See=(library)} @begin{ImplNote} Alternatively, naming conflicts could be resolved via some sort of hiding rule. @end{ImplNote} @begin{Discussion} For example, the implementation might support a command to import library Y into library X. If a root library unit called LU (that is, Standard.LU) exists in Y, then from the point of view of library X, it could be called Y.LU. X might contain library units that say, @lquotes@;@key[with] Y.LU;@rquotes@;. @end{Discussion} A compilation unit containing an instantiation of a separately compiled generic unit does not semantically depend on the body of the generic unit. Therefore, replacing the generic body in the environment does not result in the removal of the compilation unit containing the instantiation. @begin{ImplNote} Therefore, implementations have to be prepared to automatically instantiate generic bodies at link-time, as needed. This might imply a complete automatic recompilation, but it is the intent of the language that generic bodies can be (re)instantiated without forcing all of the compilation units that semantically depend on the compilation unit containing the instantiation to be recompiled. @end{ImplNote} @end{Notes} @begin{Extend83} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00077-01],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 83} Ada 83 allowed implementations to require that the body of a generic unit be available when the instantiation is compiled; that permission is dropped in Ada 95. This isn't really an extension (it doesn't allow Ada users to write anything that they couldn't in Ada 83), but there isn't a more appropriate category, and it does allow users more flexibility when developing programs.]} @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0032],ARef=[AI95-00192-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The wording was clarified to ensure that a @nt{subprogram_body} is not considered a completion of an instance of a generic subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00214-01]} @ChgAdded{Version=[2],Text=[The permissions to remove a unit from the environment were clarified to ensure that it is never necessary to keep multiple (sub)units with the same full expanded name in the environment.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Units mentioned in a @nt{limited_with_clause} were added to several rules; limited views have the same presence in the environment as the corresponding full views.]} @end{DiffWord95} @LabeledSubClause{Pragmas and Program Units} @begin{Intro} @Redundant[This subclause discusses pragmas related to program units, library units, and @nt{compilation}s.] @end{Intro} @begin{Resolution} @RootDefn{program unit pragma} @RootDefn{pragma, program unit} Certain @nt{pragma}s are defined to be @i{program unit pragmas}. @PDefn2{Term=[apply], Sec=(to a program unit by a program unit pragma)} A @nt{name} given as the argument of a program unit pragma shall resolve to denote the declarations or renamings of one or more program units that occur immediately within the declarative region or @nt<compilation> in which the @nt<pragma> immediately occurs, or it shall resolve to denote the declaration of the immediately enclosing program unit (if any); the @nt{pragma} applies to the denoted program unit(s). If there are no @nt{name}s given as arguments, the @nt{pragma} applies to the immediately enclosing program unit. @begin{Ramification} The fact that this is a @ResolutionName means that the @nt{pragma} will not apply to declarations from outer declarative regions. @end{Ramification} @end{Resolution} @begin{Legality} @leading@keepnext@;A program unit pragma shall appear in one of these places: @begin{Itemize} At the place of a @nt{compilation_unit}, in which case the @nt<pragma> shall immediately follow in the same @nt<compilation> (except for other @nt{pragma}s) a @nt{library_@!unit_@!declaration} that is a @nt<subprogram_@!declaration>, @nt<generic_@!subprogram_@!declaration>, or @nt<generic_@!instantiation>, and the @nt<pragma> shall have an argument that is a @nt<name> denoting that declaration. @begin{Ramification} The @nt{name} has to denote the immediately preceding @nt{library_unit_declaration}. @end{Ramification} @ChgRef{Version=[1], Kind=[Revised], Ref=[8652/0033], ARef=[AI95-00136-01]} Immediately within the @Chg{New=[visible part],Old=[declaration]} of a program unit and before any nested declaration@Chg{New=[ (but not within a generic formal part)], Old=[]}, in which case the argument, if any, shall be a @nt{direct_name} that denotes the immediately enclosing program unit declaration. @begin{Ramification} The argument is optional in this case. @end{Ramification} At the place of a declaration other than the first, of a @nt{declarative_part} or program unit declaration, in which case the @nt{pragma} shall have an argument, which shall be a @nt{direct_name} that denotes one or more of the following (and nothing else): a @nt{subprogram_@!declaration}, a @nt{generic_@!subprogram_@!declaration}, or a @nt{generic_@!instantiation}, of the same @nt<declarative_@!part> or program unit declaration. @begin{Ramification} If you want to denote a @nt<subprogram_body> that is not a completion, or a @nt{package_declaration}, for example, you have to put the @nt{pragma} inside. @end{Ramification} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0132-1]} @RootDefn{library unit pragma} @RootDefn{pragma, library unit} @PDefn2{Term=[program unit pragma], Sec=(library unit pragmas)} @PDefn2{Term=[pragma, program unit], Sec=(library unit pragmas)} Certain program unit pragmas are defined to be @i{library unit pragmas}. @Chg{Version=[3],New=[If a library unit pragma applies to a program unit, the program unit shall be],Old=[The @nt{name}, if any, in a library unit pragma shall denote the declaration of]} a library unit. @begin{Ramification} This, together with the rules for program unit pragmas above, implies that if a library unit pragma applies to a @nt{subprogram_declaration} (and similar things), it has to appear immediately after the @nt{compilation_unit}, whereas if the @nt{pragma} applies to a @nt{package_declaration}, a @nt{subprogram_body} that is not a completion (and similar things), it has to appear inside, as the first @nt{declarative_item}. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1], Kind=[Added], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[1],Text=[A library unit pragma that applies to a generic unit does not apply to its instances, unless a specific rule for the pragma specifies the contrary.]} @end{StaticSem} @begin{LinkTime} @RootDefn{configuration pragma} @RootDefn{pragma, configuration} Certain @nt{pragma}s are defined to be @i{configuration pragmas}; they shall appear before the first @nt{compilation_unit} of a @nt{compilation}. @Redundant[They are generally used to select a partition-wide or system-wide option.] The @nt<pragma> applies to all @nt{compilation_unit}s appearing in the @nt{compilation}, unless there are none, in which case it applies to all future @nt{compilation_unit}s compiled into the same environment. @end{LinkTime} @begin{ImplPerm} @ChgRef{Version=[2], Kind=[Revised], ARef=[AI95-00212-01]} An implementation may @Chg{Version=[2], New=[require that configuration pragmas that select partition-wide or system-wide options be compiled], Old=[place restrictions on configuration pragmas, so long as it allows them]} when the environment contains no @nt{library_item}s other than those of the predefined environment. @Chg{Version=[2], New=[In this case, the implementation shall still accept configuration pragmas in individual compilations that confirm the initially selected partition-wide or system-wide options.],Old=[]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[1], Kind=[AddedNormal], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[1],Text=[When applied to a generic unit, a program unit pragma that is not a library unit pragma should apply to each instance of the generic unit for which there is not an overriding pragma applied directly to the instance.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When applied to a generic unit, a program unit pragma that is not a library unit pragma should apply to each instance of the generic unit for which there is not an overriding pragma applied directly to the instance.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2], Kind=[AddedNormal], Ref=[8652/0033], ARef=[AI95-00136-01]} @ChgAdded{Version=[2], Text=[@B<Corrigendum:> The wording was corrected to ensure that a program unit pragma cannot appear in private parts or generic formal parts.]} @ChgRef{Version=[2], Kind=[AddedNormal], Ref=[8652/0034], ARef=[AI95-00041-01]} @ChgAdded{Version=[2], Text=[@B<Corrigendum:> The wording was clarified to explain the meaning of program unit and library unit pragmas in generic units.]} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[The Implementation Advice added by the Corrigendum was moved, as it was not in the normal order. (This changes the paragraph number.) It originally was directly after the new Static Semantics rule.]} @ChgRef{Version=[2], Kind=[AddedNormal], ARef=[AI95-00212-01]} @ChgAdded{Version=[2], Type=[Leading],Keepnext=[T],Text=[The permission to place restrictions was clarified to:]} @begin{itemize} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[Ensure that it applies only to partition-wide configuration pragmas, not ones like Assertion_Policy (see @RefSecNum{Pragmas Assert and Assertion_Policy}), which can be different in different units; and]} @ChgRef{Version=[2], Kind=[AddedNormal]} @ChgAdded{Version=[2], Text=[Ensure that confirming pragmas are always allowed.]} @end{itemize} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0132-1]} @ChgAdded{Version=[3], Text=[@b<Correction:> A library unit pragma must apply directly to a library unit, even if no name is given in the pragma.]} @end{DiffWord2005} @LabeledSubClause{Environment-Level Visibility Rules} @begin{Intro} @Redundant[The normal visibility rules do not apply within a @nt{parent_unit_name} or a @nt{context_clause}, nor within a @nt{pragma} that appears at the place of a compilation unit. The special visibility rules for those contexts are given here.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06],ARef=[AI95-00312-01]} @PDefn2{Term=[directly visible], Sec=(within the @nt{parent_unit_name} of a library unit)} @PDefn2{Term=[visible], Sec=(within the @nt{parent_unit_name} of a library unit)} @PDefn2{Term=[directly visible], Sec=(within a @nt{with_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{with_clause})} Within the @nt{parent_unit_name} at the beginning of @Chg{Version=[2],New=[an explicit],Old=[a]} @nt{library_item}, and within a @Chg{Version=[2],New=[@nt{nonlimited_with_clause}], Old=[@nt{with_clause}]}, the only declarations that are visible are those that are@Chg{Version=[2],New=[ explicit],Old=[]} @nt<library_item>s of the environment, and the only declarations that are directly visible are those that are@Chg{Version=[2],New=[ explicit],Old=[]} root @nt<library_item>s of the environment. @Chg{Version=[2],New=[Within a @nt{limited_with_clause}, the only declarations that are visible are those that are the implicit declaration of the limited view of a library package of the environment, and the only declarations that are directly visible are those that are the implicit declaration of the limited view of a root library package.], Old=[@Defn{notwithstanding} Notwithstanding the rules of @RefSecNum(Selected Components), an expanded name in a @nt{with_clause} may consist of a @nt<prefix> that denotes a generic package and a @nt<selector_name> that denotes a child of that generic package. @Redundant[(The child is necessarily a generic unit; see @RefSecNum{Compilation Units - Library Units}.)]]} @begin{Ramification} In @lquotes@;@key{package} P.Q.R @key{is} ... @key{end} P.Q.R;@rquotes@;, this rule requires P to be a root library unit, and Q to be a library unit (because those are the things that are directly visible and visible). Note that visibility does not apply between the @lquotes@;@key{end}@rquotes@; and the @lquotes@;;@rquotes@;. Physically nested declarations are not visible at these places. @ChgNote{Changed the classification of this note from Reason to Ramification, as it certainly isn't a "reason". Besides, there were two reasons, which was goofy.} Although Standard is visible at these places, it is impossible to name it, since it is not directly visible, and it has no parent. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Only compilation units defining limited views can be mentioned in a @nt{limited_with_clause}, while only compilation units defining full views (that is, the explicit declarations) can be mentioned in a @nt{nonlimited_with_clause}. This resolves the conflict inherent in having two compilation units with the same defining name.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00312-01]} @ChgDeleted{Version=[2],Text=[The @lquotes@;notwithstanding@rquotes@; part allows @lquotes@;@key[with] A.B;@rquotes@; where A is a generic library package and B is one of its (generic) children. This is necessary because it is not normally legal to use an expanded name to reach inside a generic package.]} @end{Reason} @PDefn2{Term=[directly visible], Sec=(within a @nt{use_clause} in a @nt{context_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{use_clause} in a @nt{context_clause})} @PDefn2{Term=[directly visible], Sec=(within a @nt{pragma} in a @nt{context_clause})} @PDefn2{Term=[visible], Sec=(within a @nt{pragma} in a @nt{context_clause})} Within a @nt{use_clause} or @nt{pragma} that is within a @nt{context_clause}, each @nt<library_item> mentioned in a previous @nt{with_clause} of the same @nt{context_clause} is visible, and each root @nt<library_item> so mentioned is directly visible. In addition, within such a @nt{use_clause}, if a given declaration is visible or directly visible, each declaration that occurs immediately within the given declaration's visible part is also visible. No other declarations are visible or directly visible. @begin{Discussion} Note the word @lquotes@;same@rquotes@;. For example, if a @nt{with_clause} on a declaration mentions X, this does not make X visible in @nt{use_clause}s and @nt{pragma}s that are on the body. The reason for this rule is the one-pass @nt{context_clause}s @MetaRulesName. Note that the second part of the rule does not mention @nt{pragma}s. @end{Discussion} @PDefn2{Term=[directly visible], Sec=(within the @nt{parent_unit_name} of a subunit)} @PDefn2{Term=[visible], Sec=(within the @nt{parent_unit_name} of a subunit)} Within the @nt{parent_unit_name} of a subunit, @nt<library_item>s are visible as they are in the @nt{parent_unit_name} of a @nt{library_item}; in addition, the declaration corresponding to each @nt{body_stub} in the environment is also visible. @begin{Ramification} For a subprogram without a separate @nt<subprogram_declaration>, the @nt<body_stub> itself is the declaration. @end{Ramification} @PDefn2{Term=[directly visible], Sec=(within a @nt{pragma} that appears at the place of a compilation unit)} @PDefn2{Term=[visible], Sec=(within a @nt{pragma} that appears at the place of a compilation unit)} Within a @nt{pragma} that appears at the place of a compilation unit, the immediately preceding @nt<library_item> and each of its ancestors is visible. The ancestor root @nt<library_item> is directly visible. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00312-01]} @ChgAdded{Version=[2],Text=[@Defn{notwithstanding} Notwithstanding the rules of @RefSecNum(Selected Components), an expanded name in a @nt{with_clause}, a @nt{pragma} in a @nt{context_clause}, or a @nt{pragma} that appears at the place of a compilation unit may consist of a @nt{prefix} that denotes a generic package and a @nt<selector_name> that denotes a child of that generic package. @Redundant[(The child is necessarily a generic unit; see @RefSecNum{Compilation Units - Library Units}.)]]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule allows @key[with] A.B; and @key[pragma] Elaborate(A.B); where A is a generic library package and B is one of its (generic) children. This is necessary because it is not normally legal to use an expanded name to reach inside a generic package.]} @end{Reason} @end{StaticSem} @begin{DiffWord83} The special visibility rules that apply within a @nt{parent_unit_name} or a @nt{context_clause}, and within a @nt{pragma} that appears at the place of a @nt{compilation_unit} are clarified. Note that a @nt{context_clause} is not part of any declarative region. We considered making the visibility rules within @nt{parent_unit_name}s and @nt{context_clause}s follow from the context of compilation. However, this attempt failed for various reasons. For example, it would require @nt{use_clause}s in @nt{context_clause}s to be within the declarative region of Standard, which sounds suspiciously like a kludge. And we would still need a special rule to prevent seeing things (in our own @nt{context_clause}) that were with-ed by our parent, etc. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Added separate visibility rules for @nt{limited_with_clause}s; the existing rules apply only to @nt{nonlimited_with_clause}s.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00312-01]} @ChgAdded{Version=[2],Text=[Clarified that the name of a generic child unit may appear in a @nt{pragma} in a @nt{context_clause}.]} @end{DiffWord95} @LabeledClause{Program Execution} @begin{Intro} @Defn{program} @Defn{program execution} @IndexSee{Term=[running a program],See=(program execution)} An Ada @i{program} consists of a set of @i{partitions}@Redundant[, which can execute in parallel with one another, possibly in a separate address space, and possibly on a separate computer.] @end{Intro} @begin{LinkTime} @RootDefn{partition} @Defn{partition building} A partition is a program or part of a program that can be invoked from outside the Ada implementation. @Redundant[For example, on many systems, a partition might be an executable file generated by the system linker.] @Defn{explicitly assign} The user can @i{explicitly assign} library units to a partition. The assignment is done in an implementation-defined manner. The compilation units included in a partition are those of the explicitly assigned library units, as well as other compilation units @i{needed by} those library units. The compilation units needed by a given compilation unit are determined as follows (unless specified otherwise via an implementation-defined @nt{pragma}, or by some other implementation-defined means): @IndexSee{Term=[linking],See=(partition building)} @RootDefn2{Term=[compilation units needed], Sec=(by a compilation unit)} @RootDefn2{Term=[needed], Sec=(of a compilation unit by another)} @begin{Discussion} From a run-time point of view, an Ada 95 partition is identical to an Ada 83 program @em implementations were always allowed to provide inter-program communication mechanisms. The additional semantics of partitions is that interfaces between them can be defined to obey normal language rules (as is done in @RefSec{Distributed Systems}), whereas interfaces between separate programs had no particular semantics. @end{Discussion} @ImplDef{The manner of explicitly assigning library units to a partition.} @ImplDef{The implementation-defined means, if any, of specifying which compilation units are needed by a given compilation unit.} @begin{Discussion} There are no pragmas that @lquotes@;specify otherwise@rquotes@; defined by the core language. However, an implementation is allowed to provide such pragmas, and in fact @RefSec{Distributed Systems} defines some pragmas whose semantics includes reducing the set of compilation units described here. @end{Discussion} @begin{Itemize} A compilation unit needs itself; If a compilation unit is needed, then so are any compilation units upon which it depends semantically; If a @nt{library_unit_declaration} is needed, then so is any corresponding @nt{library_unit_body}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00217-06]} If a compilation unit with stubs is needed, then so are any corresponding subunits@Chg{Version=[2],New=[;],Old=[.]} @begin{Discussion} Note that in the environment, the stubs are replaced with the corresponding @ntf{proper_bodies}. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[If the (implicit) declaration of the limited view of a library package is needed, then so is the explicit declaration of the library package.]} @end{Itemize} @begin{Discussion} Note that a child unit is not included just because its parent is included @em to include a child, mention it in a @nt{with_clause}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[A package is included in a partition even if the only reference to it is in a @nt{limited_with_clause}. While this isn't strictly necessary (no objects of types imported from such a unit can be created), it ensures that all incomplete types are eventually completed, and is the least surprising option.]} @end{Discussion} @Defn2{Term=[main subprogram], Sec=(for a partition)} The user can optionally designate (in an implementation-defined manner) one subprogram as the @i{main subprogram} for the partition. A main subprogram, if specified, shall be a subprogram. @begin{Discussion} This may seem superfluous, since it follows from the definition. But we would like to have every error message that might be generated (before run time) by an implementation correspond to some explicitly stated @lquotes@;shall@rquotes@; rule. Of course, this does not mean that the @lquotes@;shall@rquotes@; rules correspond one-to-one with an implementation's error messages. For example, the rule that says overload resolution @lquotes@;shall@rquotes@; succeed in producing a single interpretation would correspond to many error messages in a good implementation @em the implementation would want to explain to the user exactly why overload resolution failed. This is especially true for the syntax rules @em they are considered part of overload resolution, but in most cases, one would expect an error message based on the particular syntax rule that was violated. @end{Discussion} @ImplDef{The manner of designating the main subprogram of a partition.} @begin{Ramification} An implementation cannot require the user to specify, say, all of the library units to be included. It has to support, for example, perhaps the most typical case, where the user specifies just one library unit, the main program. The implementation has to do the work of tracking down all the other ones. @end{Ramification} @Defn{environment task} Each partition has an anonymous @i{environment task}@Redundant[, which is an implicit outermost task whose execution elaborates the @nt{library_item}s of the environment @nt{declarative_part}, and then calls the main subprogram, if there is one. A partition's execution is that of its tasks.] @begin{Ramification} An environment task has no master; all nonenvironment tasks have masters. An implementation is allowed to support multiple concurrent executions of the same partition. @end{Ramification} @Redundant[The order of elaboration of library units is determined primarily by the @i{elaboration dependences}.] @Defn2{Term=[elaboration dependence], Sec=(library_item on another)} @Defn2{Term=[dependence], Sec=(elaboration)} There is an elaboration dependence of a given @nt{library_item} upon another if the given @nt{library_item} or any of its subunits depends semantically on the other @nt{library_item}. In addition, if a given @nt{library_item} or any of its subunits has a @nt{pragma} Elaborate or Elaborate_All that @Chg{Version=[2],New=[names],Old=[mentions]} another library unit, then there is an elaboration dependence of the given @nt{library_item} upon the body of the other library unit, and, for Elaborate_All only, upon each @nt{library_item} needed by the declaration of the other library unit. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0107],ARef=[AI95-00180-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[@Lquotes@;Mentions@rquotes @Chg{Version=[2],New=[was],Old=[is]} used informally in the above rule; it @Chg{Version=[2],New=[was],Old=[is]} not intended to refer to the definition of @i{mentions} in @RefSecNum{Context Clauses - With Clauses}. @Chg{Version=[2],New=[It was changed to @Lquotes@;names@rquotes to make this clear.], Old=[It would have been better to use @Lquotes@;names@rquotes instead of @Lquotes@;mentions@rquotes above.]}]} See above for a definition of which @nt{library_item}s are @lquotes@;needed by@rquotes@; a given declaration. Note that elaboration dependences are among @nt{library_item}s, whereas the other two forms of dependence are among compilation units. Note that elaboration dependence includes semantic dependence. It's a little bit sad that pragma Elaborate_Body can't be folded into this mechanism. It follows from the definition that the elaboration dependence relationship is transitive. Note that the wording of the rule does not need to take into account a semantic dependence of a @nt{library_item} or one of its subunits upon a subunit of a different library unit, because that can never happen. @end{Discussion} @leading@keepnext@;The environment task for a partition has the following structure: @begin{Example} @key[task] @RI{Environment_Task}; @key[task] @key[body] @RI{Environment_Task} @key[is] ... (1) --@RI{ The environment }@nt{declarative_part} --@RI{ (that is, the sequence of }@nt{library_item}@RI{s) goes here.} @key[begin] ... (2) --@RI{ Call the main subprogram, if there is one.} @key[end] @RI{Environment_Task}; @end{Example} @begin{Ramification} The name of the environment task is written in italics here to indicate that this task is anonymous. @end{Ramification} @begin{Discussion} The model is different for a @lquotes@;passive partition@rquotes@; (see @RefSecNum{Partitions}). Either there is no environment task, or its @nt<sequence_of_statements> is an infinite loop rather than a call on a main subprogram. @end{Discussion} @leading@PDefn2{Term=[environment @nt<declarative_part>], Sec=(for the environment task of a partition)} The environment @nt{declarative_part} at (1) is a sequence of @nt{declarative_item}s consisting of copies of the @nt{library_item}s included in the partition@Redundant[. The order of elaboration of @nt{library_item}s is the order in which they appear in the environment @nt{declarative_part}]: @begin{Itemize} The order of all included @nt<library_item>s is such that there are no forward elaboration dependences. @begin{Ramification} This rule is written so that if a @nt{library_item} depends on itself, we don't require it to be elaborated before itself. See AI83-00113/12. This can happen only in pathological circumstances. For example, if a library @nt{subprogram_body} has no corresponding @nt{subprogram_declaration}, and one of the subunits of the @nt{subprogram_body} mentions the @nt{subprogram_body} in a @nt{with_clause}, the @nt{subprogram_body} will depend on itself. For another example, if a @nt{library_unit_body} applies a @nt{pragma} Elaborate_All to its own declaration, then the @nt{library_unit_body} will depend on itself. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Any included @nt{library_unit_declaration} @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[aspect],Old=[a @nt{pragma}]} Elaborate_Body @Chg{Version=[3],New=[is True @Redundant[(including when a @nt{pragma} Elaborate_Body applies)]],Old=[applies]} is immediately followed by its @nt{library_unit_body}, if included. @begin{Discussion} This implies that the body of such a library unit shall not @lquotes@;with@rquotes@; any of its own children, or anything else that depends semantically upon the declaration of the library unit. @end{Discussion} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} Elaborate_Body sets aspect Elaborate_Body, see @RefSecNum{Elaboration Control}.]} @end{TheProof} All @nt{library_item}s declared pure occur before any that are not declared pure. All preelaborated @nt<library_item>s occur before any that are not preelaborated. @end{Itemize} @begin{Discussion} Normally, if two partitions contain the same compilation unit, they each contain a separate @i{copy} of that compilation unit. See @RefSec{Distributed Systems} for cases where two partitions share the same copy of something. There is no requirement that the main subprogram be elaborated last. In fact, it is possible to write a partition in which the main subprogram cannot be elaborated last. @end{Discussion} @begin{Ramification} This @nt{declarative_part} has the properties required of all environments (see @RefSecNum{The Compilation Process}). However, the environment @nt{declarative_part} of a partition will typically contain fewer compilation units than the environment @nt{declarative_part} used at compile time @em only the @lquotes@;needed@rquotes@; ones are included in the partition. @end{Ramification} There shall be a total order of the @nt{library_item}s that obeys the above rules. The order is otherwise implementation defined. @begin{Discussion} The only way to violate this rule is to have Elaborate, Elaborate_All, or Elaborate_Body @nt{pragma}s that cause circular ordering requirements, thus preventing an order that has no forward elaboration dependences. @end{Discussion} @ImplDef{The order of elaboration of @nt{library_item}s.} @begin{Honest} @PDefn2{Term=[requires a completion], Sec=(library_unit_declaration)} @Defn{notwithstanding} Notwithstanding what the RM95 says elsewhere, each rule that requires a declaration to have a corresponding completion is considered to be a @LinkTimeName when the declaration is that of a library unit. @end{Honest} @begin{Discussion} Such rules may be checked at @lquotes@;link time,@rquotes@; for example. Rules requiring the completion to have certain properties, on the other hand, are checked at compile time of the completion. @end{Discussion} The full expanded names of the library units and subunits included in a given partition shall be distinct. @begin{Reason} This is a @LinkTimeName because making it a @LegalityName would violate the @MetaRulesName labeled @lquotes@;legality determinable via semantic dependences.@rquotes@; @end{Reason} @leading@;The @nt{sequence_of_statements} of the environment task (see (2) above) consists of either: @begin{Itemize} A call to the main subprogram, if the partition has one. If the main subprogram has parameters, they are passed; where the actuals come from is implementation defined. What happens to the result of a main function is also implementation defined. @ImplDef{Parameter passing and function return for the main subprogram.} @end{Itemize} @leading@keepnext@;or: @begin{Itemize} A @nt{null_statement}, if there is no main subprogram. @begin{Discussion} For a passive partition, either there is no environment task, or its @nt<sequence_of_statements> is an infinite loop. See @RefSecNum{Partitions}. @end{Discussion} @end{Itemize} The mechanisms for building and running partitions are implementation defined. @Redundant[These might be combined into one operation, as, for example, in dynamic linking, or @lquotes@;load-and-go@rquotes@; systems.] @ImplDef{The mechanisms for building and running partitions.} @end{LinkTime} @begin{RunTime} @PDefn2{Term=[execution], Sec=(program)} The execution of a program consists of the execution of a set of partitions. Further details are implementation defined. @PDefn2{Term=[execution], Sec=(partition)} The execution of a partition starts with the execution of its environment task, ends when the environment task terminates, and includes the executions of all tasks of the partition. @Redundant[The execution of the (implicit) @nt<task_body> of the environment task acts as a master for all other tasks created as part of the execution of the partition. When the environment task completes (normally or abnormally), it waits for the termination of all such tasks, and then finalizes any remaining objects of the partition.] @begin{Ramification} The @lquotes@;further details@rquotes@; mentioned above include, for example, program termination @em it is implementation defined. There is no need to define it here; it's entirely up to the implementation whether it wants to consider the program as a whole to exist beyond the existence of individual partitions. @end{Ramification} @ImplDef{The details of program execution, including program termination.} @begin{Honest} @PDefn2{Term=[termination], Sec=(of a partition)} @PDefn2{Term=[normal termination], Sec=(of a partition)} @PDefn2{Term=[termination], Sec=(normal)} @PDefn2{Term=[abnormal termination], Sec=(of a partition)} @PDefn2{Term=[termination], Sec=(abnormal)} The execution of the partition terminates (normally or abnormally) when the environment task terminates (normally or abnormally, respectively). @end{Honest} @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Once the environment task has awaited the termination of all other tasks of the partition, any further attempt to create a task (during finalization) is a bounded error, and may result in the raising of Program_Error either upon creation or activation of the task. @PDefn{unspecified} If such a task is activated, it is not specified whether the task is awaited prior to termination of the environment task. @end{Bounded} @begin{ImplReq} @Leading@;The implementation shall ensure that all compilation units included in a partition are consistent with one another, and are legal according to the rules of the language. @begin{Discussion} The consistency requirement implies that a partition cannot contain two versions of the same compilation unit. That is, a partition cannot contain two different library units with the same full expanded name, nor two different bodies for the same program unit. For example, suppose we compile the following: @begin{Example} @key[package] A @key[is] --@RI{ Version 1.} ... @key[end] A; @key[with] A; @key[package] B @key[is] @key[end] B; @key[package] A @key[is] --@RI{ Version 2.} ... @key[end] A; @key[with] A; @key[package] C @key[is] @key[end] C; @end{Example} It would be wrong for a partition containing B and C to contain both versions of A. Typically, the implementation would require the use of Version 2 of A, which might require the recompilation of B. Alternatively, the implementation might automatically recompile B when the partition is built. A third alternative would be an incremental compiler that, when Version 2 of A is compiled, automatically patches the object code for B to reflect the changes to A (if there are any relevant changes @em there might not be any). An implementation that supported fancy version management might allow the use of Version 1 in some circumstances. In no case can the implementation allow the use of both versions in the same partition (unless, of course, it can prove that the two versions are semantically identical). The core language says nothing about inter-partition consistency; see also @RefSec{Distributed Systems}. @end{Discussion} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{active partition} The kind of partition described in this @Chg{Version=[3],New=[subclause],Old=[clause]} is known as an @i{active} partition. An implementation is allowed to support other kinds of partitions, with implementation-defined semantics. @ImplDef{The semantics of any nonactive partitions supported by the implementation.} @begin{Discussion} @RefSec{Distributed Systems} defines the concept of passive partitions; they may be thought of as a partition without an environment task, or as one with a particularly simple form of environment task, having an infinite loop rather than a call on a main subprogram as its @nt<sequence_of_statements>. @end{Discussion} An implementation may restrict the kinds of subprograms it supports as main subprograms. However, an implementation is required to support all main subprograms that are public parameterless library procedures. @begin{Ramification} The implementation is required to support main subprograms that are procedures declared by @nt{generic_instantiation}s, as well as those that are children of library units other than Standard. Generic units are, of course, not allowed to be main subprograms, since they are not subprograms. Note that renamings are irrelevant to this rule. This rules says which subprograms (not views) have to be supported. The implementation can choose any way it wants for the user to indicate which subprogram should be the main subprogram. An implementation might allow any name of any view, including those declared by renamings. Another implementation might require it to be the original name. Another implementation still might use the name of the source file or some such thing. @end{Ramification} If the environment task completes abnormally, the implementation may abort any dependent tasks. @begin{Reason} If the implementation does not take advantage of this permission, the normal action takes place @em the environment task awaits those tasks. The possibility of aborting them is not shown in the @i{Environment_Task} code above, because there is nowhere to put an @nt{exception_handler} that can handle exceptions raised in both the environment @nt{declarative_part} and the main subprogram, such that the dependent tasks can be aborted. If we put an @nt{exception_handler} in the body of the environment task, then it won't handle exceptions that occur during elaboration of the environment @nt{declarative_part}. If we were to move those things into a nested @nt{block_statement}, with the @nt{exception_handler} outside that, then the @nt{block_statement} would await the library tasks we are trying to abort. Furthermore, this is merely a permission, and is not fundamental to the model, so it is probably better to state it separately anyway. Note that implementations (and tools like debuggers) can have modes that provide other behaviors in addition. @end{Reason} @end{ImplPerm} @begin{Notes} An implementation may provide inter-partition communication mechanism(s) via special packages and pragmas. Standard pragmas for distribution and methods for specifying inter-partition communication are defined in @RefSec{Distributed Systems}. If no such mechanisms are provided, then each partition is isolated from all others, and behaves as a program in and of itself. @begin{Ramification} Not providing such mechanisms is equivalent to disallowing multi-partition programs. An implementation may provide mechanisms to facilitate checking the consistency of library units elaborated in different partitions; @RefSec{Distributed Systems} does so. @end{Ramification} Partitions are not required to run in separate address spaces. For example, an implementation might support dynamic linking via the partition concept. An order of elaboration of @nt{library_item}s that is consistent with the partial ordering defined above does not always ensure that each @nt{library_unit_body} is elaborated before any other compilation unit whose elaboration necessitates that the @nt{library_unit_body} be already elaborated. (In particular, there is no requirement that the body of a library unit be elaborated as soon as possible after the @nt{library_unit_declaration} is elaborated, unless the pragmas in subclause @RefSecNum{Elaboration Control} are used.) A partition (active or otherwise) need not have a main subprogram. In such a case, all the work done by the partition would be done by elaboration of various @nt{library_item}s, and by tasks created by that elaboration. Passive partitions, which cannot have main subprograms, are defined in @RefSec{Distributed Systems}. @begin{Ramification} The environment task is the outermost semantic level defined by the language. Standard has no private part. This prevents strange implementation-dependences involving private children of Standard having visibility upon Standard's private part. It doesn't matter where the body of Standard appears in the environment, since it doesn't do anything. See @RefSec{Predefined Language Environment}. Note that elaboration dependence is carefully defined in such a way that if (say) the body of something doesn't exist yet, then there is no elaboration dependence upon the nonexistent body. (This follows from the fact that @lquotes@;needed by@rquotes@; is defined that way, and the elaboration dependences caused by a @nt{pragma} Elaborate or Elaborate_All are defined in terms of @lquotes@;needed by@rquotes@;.) This property allows us to use the environment concept both at compile time and at partition-construction time/run time. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concept of partitions is new to Ada 95. A main subprogram is now optional. The language-defined restrictions on main subprograms are relaxed. @end{Extend83} @begin{DiffWord83} Ada 95 uses the term @lquotes@;main subprogram@rquotes@; instead of Ada 83's @lquotes@;main program@rquotes@; (which was inherited from Pascal). This is done to avoid confusion @em a main subprogram is a subprogram, not a program. The program as a whole is an entirely different thing. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[The mistaken use of @lquotes@;mentions@rquotes@; in the elaboration dependence rule was fixed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The @i<needs> relationship was extended to include limited views.]} @end{DiffWord95} @LabeledSubClause{Elaboration Control} @begin{Intro} @Redundant[@Defn{elaboration control} This subclause defines pragmas that help control the elaboration order of @nt{library_item}s.] @end{Intro} @begin{MetaRules} The rules governing preelaboration are designed to allow it to be done largely by bulk initialization of statically allocated storage from information in a @lquotes@;load module@rquotes@; created by a linker. Some implementations may require run-time code to be executed in some cases, but we consider these cases rare enough that we need not further complicate the rules. It is important that programs be able to declare data structures that are link-time initialized with @nt{aggregate}s, @nt{string_literal}s, and concatenations thereof. It is important to be able to write link-time evaluated expressions involving the First, Last, and Length attributes of such data structures (including variables), because they might be initialized with positional @nt{aggregate}s or @nt{string_literal}s, and we don't want the user to have to count the elements. There is no corresponding need for accessing discriminants, since they can be initialized with a static constant, and then the constant can be referred to elsewhere. It is important to allow link-time initialized data structures involving discriminant-dependent components. It is important to be able to write link-time evaluated expressions involving pointers (both access values and addresses) to the above-mentioned data structures. The rules also ensure that no Elaboration_Check need be performed for calls on library-level subprograms declared within a preelaborated package. This is true also of the Elaboration_Check on task activation for library level task types declared in a preelaborated package. However, it is not true of the Elaboration_Check on instantiations. A static expression should never prevent a library unit from being preelaborable. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Preelaborate is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Preelaborate)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(Preelaborate)} @PDefn2{Term=[pragma, library unit], Sec=(Preelaborate)} A @nt{pragma} Preelaborate is a library unit pragma. @end{SyntaxText} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Preelaborable_Initialization is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[Added]} @AddedPragmaSyn{Version=[2],@ChgAdded{Version=[2], Text=<@key{pragma} @prag<Preelaborable_Initialization>(@Syn2{direct_name});>}} @end{Syntax} @begin{Legality} @Leading@RootDefn2{Term=[preelaborable], Sec=(of an elaborable construct)} An elaborable construct is preelaborable unless its elaboration performs any of the following actions: @begin{Ramification} A @i{preelaborable} construct can be elaborated without using any information that is available only at run time. Note that we don't try to prevent exceptions in preelaborable constructs; if the implementation wishes to generate code to raise an exception, that's OK. Because there is no flow of control and there are no calls (other than to predefined subprograms), these run-time properties can actually be detected at compile time. This is necessary in order to require compile-time enforcement of the rules. @end{Ramification} @begin{Itemize} The execution of a @nt{statement} other than a @nt{null_statement}. @begin{Ramification} A preelaborable construct can contain @nt{label}s and @nt{null_statement}s. @end{Ramification} A call to a subprogram other than a static function. The evaluation of a @nt{primary} that is a @nt{name} of an object, unless the @nt{name} is a static expression, or statically denotes a discriminant of an enclosing type. @begin{Ramification} One can evaluate such a @nt{name}, but not as a @nt{primary}. For example, one can evaluate an attribute of the object. One can evaluate an @nt{attribute_reference}, so long as it does not denote an object, and its @nt{prefix} does not disobey any of these rules. For example, Obj'Access, Obj'Unchecked_Access, and Obj'Address are generally legal in preelaborated library units. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0028-1]} The creation of @Chg{Version=[2],New=[an object @Redundant[(including a component)] @Chg{Version=[3],New=[that is initialized by default, if its],Old=[of a]} type @Chg{Version=[3],New=[],Old=[that ]}does not have preelaborable initialization. Similarly,], Old=[a default-initialized object @Redundant[(including a component)] of a descendant of a private type, private extension, controlled type, task type, or protected type with @nt{entry_@!declaration}s; similarly]} the evaluation of an @nt<extension_@!aggregate> with an ancestor @nt<subtype_@!mark> denoting a subtype of such a type. @begin{Ramification} One can declare these kinds of types, but one cannot create objects of those types. It is also nonpreelaborable to create an object if that will cause the evaluation of a default expression that will call a user-defined function. This follows from the rule above forbidding nonnull statements. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00161-01]} @ChgDeleted{Version=[2],Text=[Controlled objects are disallowed because most implementations will have to take some run-time action during initialization, even if the Initialize procedure is null.]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Phony addition to get conditional leading} A generic body is preelaborable only if elaboration of a corresponding instance body would not perform any such actions, presuming that@Chg{Version=[2],New=[:],Old=[ the actual for each formal private type (or extension) is a private type (or extension), and the actual for each formal subprogram is a user-defined subprogram.]} @Defn{generic contract issue} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI95-0028-1]} @ChgAdded{Version=[2],Text=[the actual for each@Chg{Version=[3], New=[ discriminated formal derived type,],Old=[]} formal private type@Chg{Version=[3],New=[, ],Old=[ (]}or @Chg{Version=[3],New=[formal private ],Old=[]}extension@Chg{Version=[3],New=[],Old=[)]} declared within the formal part of the generic unit is a @Chg{Version=[3],New=[],Old=[private ]}type@Chg{Version=[3],New=[],Old=[ (or extension)]} that does not have preelaborable initialization@Chg{Version=[3], New=[, unless @nt<pragma> Preelaborable_Initialization has been applied to the formal type],Old=[]};]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal type is nonstatic;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal object is nonstatic; and]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[the actual for each formal subprogram is a user-defined subprogram.]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[This is an @lquotes@;assume-the-worst@rquotes rule. The elaboration of a generic unit doesn't perform any of the actions listed above, because its sole effect is to establish that the generic can from now on be instantiated. So the elaboration of the generic itself is not the interesting part when it comes to preelaboration rules. The interesting part is what happens when you elaborate @lquotes@;any instantiation@rquotes of the generic. For instance, declaring an object of a limited formal private type might well start tasks, call functions, and do all sorts of nonpreelaborable things. We prevent these situations by assuming that the actual parameters are as badly behaved as possible.]} @end{Discussion} @begin{Reason} Without this rule about generics, we would have to forbid instantiations in preelaborated library units, which would significantly reduce their usefulness. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0034-1],ARef=[AI05-0243-1]} @PDefn{preelaborated} @Chg{Version=[3],New=[A],Old=[If a]} @nt{pragma} Preelaborate (or @nt<pragma> Pure @em see below) @Chg{Version=[3],New=[is used to specify that], Old=[applies to]} a library unit@Chg{Version=[3],New=[],Old=[, then it]} is @i{preelaborated}@Chg{Version=[3],New=[, namely that the Preelaborate aspect@AspectDefn{Preelaborate} of the library unit is True; all compilation units of the library unit are preelaborated],Old=[]}. @Chg{Version=[3],New=[],Old=[@Redundant[ @RootDefn{preelaborated} If a library unit is preelaborated, then its declaration, if any, and body, if any, are elaborated prior to all nonpreelaborated @nt{library_item}s of the partition.] ]}@Chg{New=[The declaration and body of a preelaborated library unit, and all subunits that are elaborated as part of elaborating the library unit,], Old=[All compilation units of a preelaborated library unit]} shall be preelaborable.@Chg{Version=[3],New=[ All compilation units of a preelaborated library unit shall depend semantically only on declared pure or preelaborated @nt{library_item}s.],Old=[]} @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), @Chg{Version=[3],New=[these rules also apply],Old=[this rule applies also]} in the private part of an instance of a generic unit. @Chg{Version=[3],New=[@Redundant[ @RootDefn{preelaborated} If a library unit is preelaborated, then its declaration, if any, and body, if any, are elaborated prior to all nonpreelaborated @nt{library_item}s of the partition.]], Old=[In addition, all compilation units of a preelaborated library unit shall depend semantically only on compilation units of other preelaborated library units.]} @begin{Ramification} In a generic body, we assume the worst about formal private types and extensions. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0035],ARef=[AI95-00002-01]} @ChgAdded{Version=[1],Text=[Subunits of a preelaborated subprogram unit do not need to be preelaborable. This is needed in order to be consistent with units nested in a subprogram body, which do not need to be preelaborable even if the subprogram is preelaborated. However, such subunits cannot depend semantically on nonpreelaborated units, which is also consistent with nested units.]} @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Preelaborate], Text=[@ChgAdded{Version=[3],Text=[Code execution during elaboration is avoided for a given package.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@defn{preelaborable initialization}The following rules specify which entities have @i{preelaborable initialization}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0028-1]} @ChgAdded{Version=[2],Text=[The partial view of a private type or private extension, a protected type without @nt<entry_declaration>s, a generic formal private type, or a generic formal derived type, @Chg{Version=[3],New=[has],Old=[have]} preelaborable initialization if and only if the @nt<pragma> Preelaborable_Initialization has been applied to them. @Redundant[A protected type with @nt{entry_declaration}s or a task type never has preelaborable initialization.]]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A component (including a discriminant) of a record or protected type has preelaborable initialization if its declaration includes a @nt<default_expression> whose execution does not perform any actions prohibited in preelaborable constructs as described above, or if its declaration does not include a default expression and its type has preelaborable initialization.]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0028-1],ARef=[AI05-0221-1]} @ChgAdded{Version=[2],Text=[A derived type has preelaborable initialization if its parent type has preelaborable initialization and @Chg{Version=[3],New=[],Old=[(in the case of a derived record extension) ]}if the noninherited components all have preelaborable initialization. However, a @Chg{Version=[3],New=[], Old=[user-defined ]}controlled type with an @Chg{Version=[3],New=[],Old=[overriding ]}Initialize procedure @Chg{Version=[3],New=[that is not a null procedure ],Old=[]}does not have preelaborable initialization.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[A view of a type has preelaborable initialization if it is an elementary type, an array type whose component type has preelaborable initialization, a record type whose components all have preelaborable initialization, or an interface type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[A @nt<pragma> Preelaborable_Initialization specifies that a type has preelaborable initialization. This pragma shall appear in the visible part of a package or generic package.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0028-1]} @ChgAdded{Version=[2],Text=[If the pragma appears in the first list of @nt{basic_declarative_item}s of a @nt<package_specification>, then the @nt<direct_name> shall denote the first subtype of a @Chg{Version=[3],New=[composite],Old=[private]} type@Chg{Version=[3],New=[],Old=[, private extension, or protected type that is not an interface type and is without @nt<entry_declaration>s]}, and the type shall be declared immediately within the same package as the @nt<pragma>. If the @nt<pragma> is applied to a private type or a private extension, the full view of the type shall have preelaborable initialization. If the @nt<pragma> is applied to a protected type, @Chg{Version=[3],New=[the protected type shall not have entries, and ],Old=[]}each component of the protected type shall have preelaborable initialization. @Chg{Version=[3],New=[For any other composite type, the type shall have preelaborable initialization. ],Old=[]}@PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules apply also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0028-1]} @ChgAdded{Version=[3],Text=[The reason why we need the pragma for private types, private extensions, and protected types is fairly clear: the properties of the full view determine whether the type has preelaborable initialization or not; in order to preserve privacy we need a way to express on the partial view that the full view is well-behaved. The reason why we need the pragma for other composite types is more subtle: a nonnull override for Initialize might occur in the private part, even for a nonprivate type; in order to preserve privacy, we need a way to express on a type declared in a visible part that the private part does not contain any nasty override of Initialize.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[If the @nt<pragma> appears in a @nt<generic_formal_part>, then the @nt<direct_name> shall denote a generic formal private type or a generic formal derived type declared in the same @nt<generic_formal_part> as the @nt<pragma>. In a @nt<generic_instantiation> the corresponding actual type shall have preelaborable initialization.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Not only do protected types with @nt{entry_declaration}s and task types not have preelaborable initialization, but they cannot have pragma Preelaborable_Initialization applied to them.]} @end{Ramification} @end{Legality} @begin{ImplAdvice} In an implementation, a type declared in a preelaborated package should have the same representation in every elaboration of a given version of the package, whether the elaborations occur in distinct executions of the same program, or in executions of distinct programs or partitions that include the given version. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A type declared in a preelaborated package should have the same representation in every elaboration of a given version of the package.]}]} @end{ImplAdvice} @begin{Syntax} @begin{SyntaxText} @leading@keepnext@;The form of a @nt{pragma} Pure is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Pure)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(Pure)} @PDefn2{Term=[pragma, library unit], Sec=(Pure)} A @nt{pragma} Pure is a library unit pragma. @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0035-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{pure} A @i{pure} @Chg{Version=[3],New=[compilation unit],Old=[@nt{library_item}]} is a preelaborable @Chg{Version=[3],New=[compilation unit],Old=[@nt{library_item}]} whose elaboration does not perform any of the following actions:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the elaboration of a variable declaration;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the evaluation of an @nt{allocator} of an access-to-variable type; for the purposes of this rule, the partial view of a type is presumed to have nonvisible components whose default initialization evaluates such an @nt{allocator};]} @begin{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0004-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Such an @nt{allocator} would provide a backdoor way to get a global variable into a pure unit, so it is prohibited. Most such @nt{allocator}s are illegal anyway, as their type is required to have Storage_Size = 0 (see the next two rules). But access parameters and access discriminants don't necessarily disallow @nt{allocator}s. However, a call is also illegal here (by the preelaboration rules), so access parameters cannot cause trouble. So this rule is really about prohibiting allocators in discriminant constraints:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[type] Rec (Acc : @key[access] Integer) @key[is record] C : Character; @key[end record];]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Not_Const : @key[constant] Rec (Acc => @key[new] Integer'(2)); -- @RI{Illegal in a pure unit}.]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[The second half of the],Old=[This]} rule is needed because aggregates can specify the default initialization of a private type or extension using <> or the ancestor subtype of an extension aggregate. The subtype of a component could use an @nt{allocator} to initialize an access discriminant; the type still could have a pragma Preelaborable_Initialization given. Ada 95 did not allow such private types to have preelaborable initialization, so such a default initialization could not have occurred. Thus this rule is not incompatible with Ada 95.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0035-1]} @ChgAdded{Version=[2],Text=[the elaboration of the declaration of a @Chg{Version=[3],New=[nonderived ],Old=[]}named access-to-variable type unless the Storage_Size of the type has been specified by a static expression with value zero or is defined by the language to be zero;]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A remote access-to-class-wide type (see @RefSecNum{Remote Types Library Units}) has its Storage_Size defined to be zero.]} @end{Discussion} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[We disallow most named access-to-object types because an @nt{allocator} has a side effect; the pool constitutes variable data. We allow access-to-subprogram types because they don't have @nt{allocator}s. We even allow named access-to-object types if they have an empty predefined pool (they can't have a user-defined pool as System.Storage_Pools is not pure). In this case, most attempts to use an @nt{allocator} are illegal, and any others (in a generic body) will raise Storage_Error.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0035-1]} @ChgAdded{Version=[2],Text=[the elaboration of the declaration of a @Chg{Version=[3],New=[nonderived ],Old=[]}named access-to-constant type for which the Storage_Size has been specified by an expression other than a static expression with value zero.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow access-to-constant types so long as there is no user-specified nonzero Storage_Size; if there were a user-specified nonzero Storage_Size restricting the size of the storage pool, allocators would be problematic since the package is supposedly @lquote@;stateless@rquote, and the allocated size count for the storage pool would represent state.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0035-1]} @ChgAdded{Version=[3],Text=[A generic body is pure only if elaboration of a corresponding instance body would not perform any such actions presuming any composite formal types have nonvisible components whose default initialization evaluates an @nt{allocator} of an access-to-variable type.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[The Storage_Size for an anonymous access-to-variable type declared at library level in a library unit that is declared pure is defined to be zero.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This makes @nt{allocator}s illegal for such types (see @RefSecNum{Allocators}), making a storage pool unnecessary for these types. A storage pool would represent state.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that access discriminants and access parameters are never library-level, even when they are declared in a type or subprogram declared at library-level. That's because they have their own special accessibility rules (see @RefSecNum{Operations of Access Types}).]} @end{Ramification} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00366-01]} @ChgDeleted{Version=[2],Text=[@Defn{pure} A @i{pure} @nt{library_item} is a preelaborable @nt{library_item} that does not contain the declaration of any variable or named access within a subprogram, generic subprogram, task unit, or protected unit.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0034-1],ARef=[AI05-0035-1],ARef=[AI05-0243-1]} @Defn{declared pure} A @nt{pragma} Pure is used to @Chg{Version=[3],New=[specify],Old=[declare]} that a library unit is @Chg{Version=[3],New=[@i{declared pure}, namely that the Pure aspect@AspectDefn{Pure} of the library unit is True; all compilation units of the library unit are declared ],Old=[]}pure. @Chg{Version=[3],New=[In addition, the limited view of any library package is declared pure. The declaration and body of a declared pure library unit, and all subunits that are elaborated as part of elaborating the library unit, shall be pure. All],Old=[If a @nt{pragma} Pure applies to a library unit, then its]} compilation units @Chg{Version=[3],New=[of a declared pure library unit],Old=[shall be pure, and they]} shall depend semantically only on @Chg{Version=[3],New=[],Old=[compilation units of other library units that are ]}declared pure@Chg{Version=[3],New=[ @nt{library_item}s], Old=[]}.@Chg{Version=[3],New=[ @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.], Old=[]}@Chg{Version=[2],New=[ Furthermore, the full view of any partial view declared in the visible part of @Chg{Version=[3],New=[a declared pure],Old=[the]} library unit that has any available stream attributes shall support external streaming (see @RefSecNum{Stream-Oriented Attributes}).],Old=[]} @begin{Honest} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0243-1]}@ChgNote{This is now described normatively} @ChgDeleted{Version=[3],Text=[A @i{declared-pure} library unit is one to which a @nt{pragma} Pure applies. Its declaration and body are also said to be declared pure.]} @end{Honest} @begin{Discussion} A declared-pure package is useful for defining types to be shared between partitions with no common address space. @end{Discussion} @begin{Reason} Note that generic packages are not mentioned in the list of things that can contain variable declarations. Note that the Ada 95 rules for deferred constants make them allowable in library units that are declared pure; that isn't true of Ada 83's deferred constants. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} Anonymous access types @Chg{Version=[2],New=[],Old=[(that is, access discriminants and access parameters) ]}are allowed. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[A limited view is not a library unit, so any rule that starts @ldquote@;declared pure library unit@rdquote does not apply to a limited view. In particular, the 3rd and last sentences never apply to limited views. However, a limited view is a @nt{library_item}, so rules that discuss @ldquote@;declared pure @nt{library_item}s@rdquote do include limited views.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @Chg{Version=[2],New=[Ada 95 didn't allow any access types as], Old=[The primary reason for disallowing named access types is that an @nt{allocator} has a side effect; the pool constitutes variable data. We considered somehow allowing @nt{allocator}-less access types. However,]} these (including access-to-subprogram types) @Chg{Version=[2],New=[],Old=[would ]}cause trouble for @RefSec{Distributed Systems}, because such types @Chg{Version=[2],New=[], Old=[would ]} allow access values in a shared passive partition to designate objects in an active partition, thus allowing inter-address space references.@Chg{Version=[2],New=[ We decided to disallow such uses in the relatively rare cases where they cause problems, rather than making life harder for the majority of users. Types declared in a pure package can be used in remote operations only if they are externally streamable. That simply means that there is a means to transport values of the type; that's automatically true for nonlimited types that don't have an access part. The only tricky part about this is to avoid privacy leakage; that was handled by ensuring that any private types (and private extensions) declared in a pure package that have available stream attributes (which include all nonlimited types by definition) have to be externally streamable.], Old=[Furthermore, a named access-to-object type without a pool would be a new concept, adding complexity from the user's point of view. Finally, the prevention of @nt{allocator}s would have to be a run-time check, in order to avoid violations of the generic contract model.]} @end{Reason} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Pure], Text=[@ChgAdded{Version=[3],Text=[Side effects are avoided in the subprograms of a given package.]}]} @end{Legality} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0219-1]} If a library unit is declared pure, then the implementation is permitted to omit a call on a library-level subprogram of the library unit if the results are not needed after the call. @Chg{Version=[2],New=[In addition, the implementation],Old=[Similarly, it]} may omit @Chg{Version=[2],New=[], Old=[such ]}a call@Chg{Version=[2],New=[ on such a subprogram],Old=[]} and simply reuse the results produced by an earlier call on the same subprogram, provided that none of the parameters @Chg{Version=[2],New=[nor any object accessible via access values from the parameters ],Old=[]}@Chg{Version=[3],New=[have any part that is of a type whose full type is an immutably],Old=[are of a]} limited type, and the addresses and values of all by-reference actual parameters, @Chg{Version=[2],New=[],Old=[and ]}the values of all by-copy-in actual parameters, @Chg{Version=[2],New=[and the values of all objects accessible via access values from the parameters, ],Old=[]}are the same as they were at the earlier call. @Redundant[This permission applies even if the subprogram produces other side effects when called.] @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1],ARef=[AI05-0299-1]} A declared-pure @nt{library_item} has no variable state. Hence, a call on one of its (nonnested) subprograms cannot @Chg{Version=[2],New=[normally],Old=[@lquotes@;normally@rquotes]} have side effects. @Chg{Version=[3],New=[Side effects are still possible via dispatching calls and via indirect calls through access-to-subprogram values. Other mechanisms that might be used to modify variable state include],Old=[The only possible side effects from such a call would be through]} machine code insertions,@Chg{Version=[2],New=[ imported subprograms, @Chg{Version=[3],New=[ and ],Old=[]}],Old=[]}unchecked conversion to an access type declared within the subprogram@Chg{Version=[3],New=[; this list is not exhaustive],Old=[, and similar features]}.@Chg{Version=[3],New=[ Thus, the permissions described in this subclause may apply to a subprogram whose execution has side effects.],Old=[]} The compiler may omit a call to such a subprogram even if @Chg{Version=[3],New=[],Old=[such]} side effects exist, so the writer of such a subprogram has to keep this in mind. @end{Discussion} @end{ImplPerm} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Elaborate, Elaborate_All, or Elaborate_Body is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Elaborate)(@SynI{library_unit_}@Syn2{name}{, @SynI{library_unit_}@Syn2{name}});' @PragmaSyn`@key{pragma} @prag(Elaborate_All)(@SynI{library_unit_}@Syn2{name}{, @SynI{library_unit_}@Syn2{name}});' @PragmaSyn`@key{pragma} @prag(Elaborate_Body)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} A @nt{pragma} Elaborate or Elaborate_All is only allowed within a @nt{context_clause}. @begin{Ramification} @lquotes@;Within a @nt{context_clause}@rquotes@; allows it to be the last item in the @nt{context_clause}. It can't be first, because the @nt{name} has to denote something mentioned earlier. @end{Ramification} @PDefn2{Term=[library unit pragma], Sec=(Elaborate_Body)} @PDefn2{Term=[pragma, library unit], Sec=(Elaborate_Body)} A @nt{pragma} Elaborate_Body is a library unit pragma. @end{SyntaxText} @begin{Discussion} Hence, a @nt{pragma} Elaborate or Elaborate_All is not elaborated, not that it makes any practical difference. Note that a @nt{pragma} Elaborate or Elaborate_All is neither a program unit pragma, nor a library unit pragma. @end{Discussion} @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @PDefn2{Term=[requires a completion], Sec=(declaration to which a @nt{pragma} Elaborate_Body applies)} If @Chg{Version=[3],New=[the aspect],Old=[a @nt{pragma}]} Elaborate_Body @Chg{Version=[3],New=[is True for],Old=[applies to]} a declaration@Chg{Version=[3],New=[ @Redundant[(including when @nt{pragma} Elaborate_Body applies)]],Old=[]}, then the declaration requires a completion @Redundant[(a body)].@Chg{Version=[3],New=[@PDefn2{Term=[requires a completion], Sec=(declaration for which aspect Elaborate_Body is True)}],Old=[]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} Elaborate_Body sets the aspect (see below).]} @end{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[The @SynI{library_unit_}@nt{name} of a @nt{pragma} Elaborate or Elaborate_All shall denote a nonlimited view of a library unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These @nt{pragma}s are intended to prevent elaboration check failures. But a limited view does not make anything visible that has an elaboration check, so the @nt{pragma}s cannot do anything useful. Moreover, the @nt{pragma}s would probably reintroduce the circularity that the @nt{limited_with_clause} was intended to break. So we make such uses illegal.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @redundant[A @nt{pragma} Elaborate specifies that the body of the named library unit is elaborated before the current @nt{library_item}. A @nt{pragma} Elaborate_All specifies that each @nt{library_item} that is needed by the named library unit declaration is elaborated before the current @nt{library_item}.@Chg{Version=[3],New=[],Old=[ A @nt{pragma} Elaborate_Body specifies that the body of the library unit is elaborated immediately after its declaration.]}] @begin{TheProof} The official statement of the semantics of these @nt{pragma}s is given in @RefSecNum{Program Execution}. @end{TheProof} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Elaborate_Body sets the Elaborate_Body representation aspect of the library unit to which it applies to the value True. @Redundant[If the Elaborate_Body aspect of a library unit is True, the body of the library unit is elaborated immediately after its declaration.@AspectDefn{Elaborate_Body}]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The official statement of the semantics of this aspect is given in @RefSecNum{Program Execution}.]} @end{TheProof} @begin{ImplNote} The presence of a @nt{pragma} Elaborate_Body simplifies the removal of unnecessary Elaboration_Checks. For a subprogram declared immediately within a library unit to which a @nt{pragma} Elaborate_Body applies, the only calls that can fail the Elaboration_Check are those that occur in the library unit itself, between the declaration and body of the called subprogram; if there are no such calls (which can easily be detected at compile time if there are no @ntf{stub}s), then no Elaboration_Checks are needed for that subprogram. The same is true for Elaboration_Checks on task activations and instantiations, and for library subprograms and generic units. @end{ImplNote} @begin{Ramification} The fact that the unit of elaboration is the @nt{library_item} means that if a @nt{subprogram_body} is not a completion, it is impossible for any @nt{library_item} to be elaborated between the declaration and the body of such a subprogram. Therefore, it is impossible for a call to such a subprogram to fail its Elaboration_Check. @end{Ramification} @begin{Discussion} The visibility rules imply that each @i{library_unit_}@nt{name} of a @nt{pragma} Elaborate or Elaborate_All has to denote a library unit mentioned by a previous @nt{with_clause} of the same @nt{context_clause}. @end{Discussion} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Elaborate_Body], Text=[@ChgAdded{Version=[3],Text=[A given package must have a body, and that body is elaborated immediately after the declaration.]}]} @end{StaticSem} @begin{Notes} A preelaborated library unit is allowed to have nonpreelaborable children. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} But @Chg{New=[generally ], Old=[]}not nonpreelaborated subunits. @Chg{New=[(Nonpreelaborated subunits of subprograms are allowed as discussed above.)], Old=[]} @end{Ramification} A library unit that is declared pure is allowed to have impure children. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0035],ARef=[AI95-00002-01]} But @Chg{New=[generally ], Old=[]}not impure subunits. @Chg{New=[(Impure subunits of subprograms are allowed as discussed above.)], Old=[]} @end{Ramification} @begin{Ramification} Pragma Elaborate is mainly for closely related library units, such as when two package bodies 'with' each other's declarations. In such cases, Elaborate_All sometimes won't work. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The concepts of preelaborability and purity are new to Ada 95. The Elaborate_All, Elaborate_Body, Preelaborate, and Pure @nt{pragma}s are new to Ada 95. Pragmas Elaborate are allowed to be mixed in with the other things in the @nt{context_clause} @em in Ada 83, they were required to appear last. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The requirement that a partial view with available stream attributes be externally streamable can cause an incompatibility in rare cases. If there is a limited tagged type declared in a pure package with available attributes, and that type is used to declare a private extension in another pure package, and the full type for the private extension has a component of an explicitly limited record type, a protected type, or a type with access discriminants, then the stream attributes will have to be user-specified in the visible part of the package. That is not a requirement for Ada 95, but this combination seems very unlikely in pure packages. Note that this cannot be an incompatibility for a nonlimited type, as all of the types that are allowed in Ada 95 that would require explicitly defined stream attributes are limited (and thus cannot be used as components in a nonlimited type).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00403-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Added wording to cover missing cases for preelaborated generic units. This is incompatible as a preelaborated unit could have used a formal object to initialize a library-level object; that isn't allowed in Ada 2005. But such a unit wouldn't really be preelaborable, and Ada 95 compilers can reject such units (as this is a Binding Interpretation), so such units should be very rare.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] The concept of preelaborable initialization and @nt{pragma} Preelaborable_Initialization are new. These allow more types of objects to be created in preelaborable units, and fix holes in the old rules.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Access-to-subprogram types and access-to-object types with a Storage_Size of 0 are allowed in pure units. The permission to omit calls was adjusted accordingly (which also fixes a hole in Ada 95, as access parameters are allowed, and changes in the values accessed by them must be taken into account).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00002-01]} @ChgAdded{Version=[2],Text=[@B<Corrigendum:> The wording was changed so that subunits of a preelaborated subprogram are also preelaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00217-06]} @ChgAdded{Version=[2],Text=[Disallowed pragma Elaborate and Elaborate_All for packages that are mentioned in a @nt{limited_with_clause}.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0028-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@B<Correction:> Corrected a serious unintended incompatibility with Ada 95 in the new preelaboration wording @em explicit initialization of objects of types that don't have preelaborable initialization was not allowed. Ada 2012 switches back to the Ada 95 rule in these cases. This is unlikely to occur in practice, as it is unlikely that a compiler would have implemented the more restrictive rule (it would fail many ACATS tests if it did).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0035-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> Added an assume-the-worst rule for generic bodies (else they would never be checked for purity) and added the boilerplate so that the entire generic specification is rechecked. Also fixed wording to have consistent handling for subunits for Pure and Preelaborate. An Ada 95 program could have depended on marking a generic pure that was not really pure, although this would defeat the purpose of the categorization and likely cause problems with distributed programs.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0035-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@B<Correction:> Adjusted wording so that a subunit can be pure (it is not a @nt<library_item>, but it is a compilation unit).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0035-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> Adjusted wording so that the rules for access types only apply to nonderived types (derived types share their storage pool with their parent, so if the parent access type is legal, so is any derived type.)]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Elaborate_Body is now an aspect, so it can be specified by an @nt{aspect_specification} @em although the pragma is still preferred by the Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[Pure and Preelaborate are now aspects, so they can be specified by an @nt{aspect_specification} @em although the pragmas are still preferred by the Standard.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0034-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> Added wording so that a limited view is always treated as pure, no matter what categorization is used for the originating unit. This was undefined in Ada 2005.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0028-1],ARef=[AI05-0221-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> Fixed minor issues with preelaborable initialization (PI): null Initialize procedures do not make a type non-PI; formal types with pragma PI can be assumed to have PI; formal extensions are assumed to not have PI; all composite types can have pragma PI (so that the possibility of hidden Initialize routines can be handled); added discriminants of a derived type are not considered in calculating PI.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0219-1]} @ChgAdded{Version=[3],Text=[@B<Correction:> Clarified that the implementation permission to omit pure subprogram calls does not apply if any part of the parameters or any designated object has a part that is immutably limited. The old wording just said "limited type", which can change via visibility and thus isn't appropriate for dynamic semantics permissions.]} @end{DiffWord2005} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/11.mss���������������������������������������������������������������0000755�0001752�0001001�00000325172�12066652506�016404� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(11, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @LabeledSection{Exceptions} @Comment{$Source: e:\\cvsroot/ARM/Source/11.mss,v $} @Comment{$Revision: 1.87 $} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[This @Chg{Version=[3],New=[clause],Old=[section]} defines the facilities for dealing with errors or other exceptional situations that arise during program execution.] @Defn{exception occurrence} @IndexSeeAlso{Term=[condition],See=(exception)} @IndexSee{Term=[signal (an exception)],See=(raise)} @IndexSee{Term=[throw (an exception)],See=(raise)} @IndexSee{Term=[catch (an exception)],See=(handle)} @ToGlossaryAlso{Term=<Exception>, Text=<An @i(exception) represents a kind of exceptional situation; an occurrence of such a situation (at run time) is called an @i(exception occurrence). @redundant[@PDefn2{Term=[raise], Sec=(an exception)} To @i{raise} an exception is to abandon normal program execution so as to draw attention to the fact that the corresponding situation has arisen. @PDefn2{Term=[handle], Sec=(an exception)} Performing some actions in response to the arising of an exception is called @i{handling} the exception. ]>} @begin{Honest} @PDefn2{Term=[handle], Sec=(an exception occurrence)} ...or handling the exception occurrence. @end{Honest} @begin{Ramification} For example, an exception End_Error might represent error situations in which an attempt is made to read beyond end-of-file. During the execution of a partition, there might be numerous occurrences of this exception. @end{Ramification} @begin{Honest} @Defn{occurrence (of an exception)} When the meaning is clear from the context, we sometimes use @lquotes@;@i{occurrence}@rquotes@; as a short-hand for @lquotes@;exception occurrence.@rquotes@; @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0043-1],ARef=[AI05-0258-1]} @redundant[An @nt{exception_declaration} declares a name for an exception. An exception @Chg{Version=[3],New=[can be],Old=[is]} raised @Chg{Version=[3],New=[explicitly (for example,],Old=[initially either]} by a @nt{raise_statement}@Chg{Version=[3],New=[)],Old=[]} or@Chg{Version=[3],New=[ implicitly (for example,],Old=[]} by the failure of a language-defined check@Chg{Version=[3],New=[)],Old=[]}. When an exception arises, control can be transferred to a user-provided @nt{exception_handler} at the end of a @nt{handled_@!sequence_of_@!statements}, or it can be propagated to a dynamically enclosing execution.] @end{Intro} @begin{DiffWord83} We are more explicit about the difference between an exception and an occurrence of an exception. This is necessary because we now have a type (Exception_Occurrence) that represents exception occurrences, so the program can manipulate them. Furthermore, we say that when an exception is propagated, it is the same occurrence that is being propagated (as opposed to a new occurrence of the same exception). The same issue applies to a re-raise statement. In order to understand these semantics, we have to make this distinction. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0043-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Generalized the introductory description of how an exception can be raised so that it does not appear to cover all of the cases.]} @end{DiffWord2005} @LabeledClause{Exception Declarations} @begin{Intro} @Defn{exception} An @nt{exception_declaration} declares a name for an exception. @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<exception_declaration>,rhs="@Syn2{defining_identifier_list} : @key{exception}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @end{Syntax} @begin{StaticSem} Each single @nt{exception_declaration} declares a name for a different exception. If a generic unit includes an @nt{exception_declaration}, the @nt{exception_declaration}s implicitly generated by different instantiations of the generic unit refer to distinct exceptions (but all have the same @nt{defining_identifier}). The particular exception denoted by an exception name is determined at compilation time and is the same regardless of how many times the @nt{exception_declaration} is elaborated. @begin{Reason} We considered removing this requirement inside generic bodies, because it is an implementation burden for implementations that wish to share code among several instances. In the end, it was decided that it would introduce too much implementation dependence. @end{Reason} @begin{Ramification} Hence, if an @nt{exception_declaration} occurs in a recursive subprogram, the exception name denotes the same exception for all invocations of the recursive subprogram. The reason for this rule is that we allow an exception occurrence to propagate out of its declaration's innermost containing master; if exceptions were created by their declarations like other entities, they would presumably be destroyed upon leaving the master; we would have to do something special to prevent them from propagating to places where they no longer exist. @end{Ramification} @begin{Ramification} Exception identities are unique across all partitions of a program. @end{Ramification} @Defn{predefined exception} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} The @i{predefined} exceptions are the ones declared in the declaration of package Standard: Constraint_Error, Program_Error, Storage_Error, and Tasking_Error@Redundant[; one of them is raised when a language-defined check fails.] @begin{Ramification} The exceptions declared in the language-defined package IO_Exceptions, for example, are not predefined. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(exception_declaration)} The elaboration of an @nt{exception_declaration} has no effect. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} The execution of any construct raises Storage_Error if there is insufficient storage for that execution. @PDefn{unspecified} The amount of storage needed for the execution of constructs is unspecified. @begin{Ramification} Note that any execution whatsoever can raise Storage_Error. This allows much implementation freedom in storage management. @end{Ramification} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of user-defined exception declarations:} @begin{Example} Singular : @key[exception]; Error : @key[exception]; Overflow, Underflow : @key[exception]; @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The exception Numeric_Error is now defined in the Obsolescent features Annex, as a rename of Constraint_Error. All checks that raise Numeric_Error in Ada 83 instead raise Constraint_Error in Ada 95. To increase upward compatibility, we also changed the rules to allow the same exception to be named more than once by a given handler. Thus, @lquotes@;@key[when] Constraint_Error | Numeric_Error =>@rquotes@; will remain legal in Ada 95, even though Constraint_Error and Numeric_Error now denote the same exception. However, it will not be legal to have separate handlers for Constraint_Error and Numeric_Error. This change is inconsistent in the rare case that an existing program explicitly raises Numeric_Error at a point where there is a handler for Constraint_Error; the exception will now be caught by that handler. @end{Inconsistent83} @begin{DiffWord83} We explicitly define elaboration for @nt{exception_declaration}s. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{exception_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Exception Handlers} @begin{Intro} @redundant[The response to one or more exceptions is specified by an @nt{exception_handler}.] @end{Intro} @begin{Syntax} @Syn{lhs=<handled_sequence_of_statements>,rhs=" @Syn2{sequence_of_statements} [@key{exception} @Syn2{exception_handler} {@Syn2{exception_handler}}]"} @Syn{lhs=<exception_handler>,rhs=" @key{when} [@Syn2{choice_parameter_specification}:] @Syn2{exception_choice} {| @Syn2{exception_choice}} => @Syn2{sequence_of_statements}"} @Syn{lhs=<choice_parameter_specification>,rhs="@Syn2{defining_identifier}"} @Syn{lhs=<exception_choice>,rhs="@SynI{exception_}@Syn2{name} | @key{others}"} @begin{Honest} @Defn{handler} @lquotes@;@i{Handler}@rquotes@; is an abbreviation for @lquotes@;@nt{exception_handler}.@rquotes@; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn2{term=<choice>, Sec=<of an @nt{exception_handler}>} Within this @Chg{Version=[3],New=[clause],Old=[section]}, we sometimes abbreviate @lquotes@;@nt{exception_choice}@rquotes@; to @lquotes@;@i{choice}.@rquotes@; @end{Honest} @end{Syntax} @begin{Legality} @Defn2{term=<cover>, Sec=<of a choice and an exception>} A choice with an @SynI{exception_}@nt{name} @i{covers} the named exception. A choice with @key{others} covers all exceptions not named by previous choices of the same @nt{handled_@!sequence_of_@!statements}. Two choices in different @nt<exception_handler>s of the same @nt{handled_@!sequence_of_@!statements} shall not cover the same exception. @begin{Ramification} Two @nt<exception_choice>s of the same @nt<exception_handler> may cover the same exception. For example, given two renaming declarations in separate packages for the same exception, one may nevertheless write, for example, @lquotes@;@key[when] Ada.Text_IO.Data_Error | My_Seq_IO.Data_Error =>@rquotes@;. An @key{others} choice even covers exceptions that are not visible at the place of the handler. Since exception raising is a dynamic activity, it is entirely possible for an @key{others} handler to handle an exception that it could not have named. @end{Ramification} A choice with @key{others} is allowed only for the last handler of a @nt{handled_sequence_of_statements} and as the only choice of that handler. An @SynI{exception_}@nt{name} of a choice shall not denote an exception declared in a generic formal package. @begin{Reason} This is because the compiler doesn't know the identity of such an exception, and thus can't enforce the coverage rules. @end{Reason} @end{Legality} @begin{StaticSem} @Defn{choice parameter} A @nt{choice_parameter_specification} declares a @i{choice parameter}, which is a constant object of type Exception_Occurrence (see @RefSecNum{The Package Exceptions}). During the handling of an exception occurrence, the choice parameter, if any, of the handler represents the exception occurrence that is being handled. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[execution], Sec=(handled_sequence_of_statements)} The execution of a @nt<handled_sequence_of_statements> consists of the execution of the @nt<sequence_of_@!statements>. @Redundant[The optional handlers are used to handle any exceptions that are propagated by the @nt{sequence_of_@!statements}.] @end{RunTime} @begin{Examples} @leading@keepnext@i{Example of an exception handler:} @begin{Example} @key[begin] Open(File, In_File, "input.txt"); --@RI[ see @RefSecNum{File Management}] @key[exception] @key[when] E : Name_Error => Put("Cannot open input file : "); Put_Line(Exception_Message(E)); --@RI[ see @RefSecNum{The Package Exceptions}] @key[raise]; @key[end]; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{exception_handler} is modified to allow a @nt{choice_parameter_specification}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Different @Chg{Version=[2],New=[@nt{exception_choice}s],Old=[@ntf<choice>s]} of the same @nt<exception_handler> may cover the same exception. This allows for @lquotes@;when Numeric_Error | Constraint_Error =>@rquotes@; even though Numeric_Error is a rename of Constraint_Error. This also allows one to @lquotes@;with@rquotes@; two different I/O packages, and then write, for example, @lquotes@;when Ada.Text_IO.Data_Error | My_Seq_IO.Data_Error =>@rquotes@; even though these might both be renames of the same exception. @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{handled_sequence_of_statements} is new. These are now used in all the places where handlers are allowed. This obviates the need to explain (in @Chg{Version=[3],New=[Clauses],Old=[Sections]} 5, 6, 7, and 9) what portions of the program are handled by the handlers. Note that there are more such cases in Ada 95. The syntax rule for @nt{choice_parameter_specification} is new. @end{DiffWord83} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Raise Statements} @begin{Intro} @redundant[A @nt{raise_statement} raises an exception.] @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} @Syn{lhs=<raise_statement>,rhs="@Chg{Version=[2],New=<@key{raise}; | @key{raise} @SynI{exception_}@Syn2{name} [@key{with} @SynI{string_}@Syn2{expression}];>, Old=<@key{raise} [@SynI{exception_}@Syn2{name}];>}"} @end{Syntax} @begin{Legality} The @nt{name}, if any, in a @nt{raise_statement} shall denote an exception. @Defn{re-raise statement} A @nt{raise_statement} with no @SynI{exception_}@nt{name} (that is, a @i{re-raise statement}) shall be within a handler, but not within a body enclosed by that handler. @end{Legality} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The @nt<expression>, if any, in a @nt<raise_statement>, is expected to be of type String.]} @end{Resolution} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} @Defn2{Term=[raise], Sec=(an exception)} To @i(raise an exception) is to raise a new occurrence of that exception@Redundant[, as explained in @RefSecNum{Exception Handling}]. @PDefn2{Term=[execution], Sec=(raise_statement with an exception_name)} For the execution of a @nt{raise_statement} with an @SynI{exception_}@nt{name}, the named exception is raised. @Chg{Version=[2],New=[@redundant{If a @SynI<string_>@nt<expression> is present, the @nt{expression} is evaluated and its value is associated with the exception occurrence.}],Old=[]} @PDefn2{Term=[execution], Sec=(re-raise statement)} For the execution of a re-raise statement, the exception occurrence that caused transfer of control to the innermost enclosing handler is raised @Redundant[again]. @begin{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The definition of Exceptions.Exception_Message includes a statement that the string is returned (see @RefSecNum{The Package Exceptions}). We describe the use of the string here so that we don't have an unexplained parameter in this subclause.]} @end{TheProof} @begin{ImplNote} For a re-raise statement, the implementation does not create a new Exception_Occurrence, but instead propagates the same Exception_Occurrence value. This allows the original cause of the exception to be determined. @end{ImplNote} @end{RunTime} @begin{Examples} @leading@keepnext@i{Examples of raise statements:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[raise] Ada.IO_Exceptions.Name_Error; --@RI[ see @RefSecNum{Exceptions In Input-Output}]@Chg{Version=[2],New=[ @key[raise] Queue_Error @key[with] "Buffer Full"; --@RI[ see @RefSecNum{Example of Tasking and Synchronization}]],Old=[]} @key[raise]; --@RI[ re-raise the current exception] @end{Example} @end{Examples} @begin{DiffWord83} The fact that the @nt{name} in a @nt{raise_statement} has to denote an exception is not clear from RM83. Clearly that was the intent, since the italicized part of the syntax rules so indicate, but there was no explicit rule. RM83-1.5(11) doesn't seem to give the italicized parts of the syntax any force. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}The syntax of a @nt{raise_statement} is extended to include a string message. This is more convenient than calling Exceptions.Exception_Message (@SynI{exception_}@nt{name}'Identity, @SynI{string_}@nt{expression}), and should encourage the use of message strings when raising exceptions.]} @end{Extend95} @LabeledClause{Exception Handling} @begin{Intro} @redundant[When an exception occurrence is raised, normal program execution is abandoned and control is transferred to an applicable @nt{exception_handler}, if any. @Defn2{Term=[handle], Sec=(an exception occurrence)} To @i(handle) an exception occurrence is to respond to the exceptional event. @Defn{propagate} To @i(propagate) an exception occurrence is to raise it again in another context; that is, to fail to respond to the exceptional event in the present context.] @begin{Ramification} In other words, if the execution of a given construct raises an exception, but does not handle it, the exception is propagated to an enclosing execution (except in the case of a @nt{task_body}). @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00023} Propagation involves re-raising the same exception occurrence@Chg{New=[], Old=[(assuming the implementation has not taken advantage of the @ImplPermName of @RefSecNum{Raise Statements})]}. For example, calling an entry of an uncallable task raises Tasking_Error; this is not propagation. @end{Ramification} @end{Intro} @begin{RunTime} @Defn2{Term=[dynamically enclosing], Sec=(of one execution by another)} @Defn2{Term=[execution], Sec=(dynamically enclosing)} Within a given task, if the execution of construct @i{a} is defined by this International Standard to consist (in part) of the execution of construct @i{b}, then while @i{b} is executing, the execution of @i{a} is said to @i(dynamically enclose) the execution of @i{b}. @Defn{innermost dynamically enclosing} The @i(innermost dynamically enclosing) execution of a given execution is the dynamically enclosing execution that started most recently. @begin{Honest} @Defn2{Term=[included], Sec=(one execution by another)} @Defn2{Term=[execution], Sec=(included by another execution)} If the execution of @i{a} dynamically encloses that of @i{b}, then we also say that the execution of @i{b} is @i{included in} the execution of @i{a}. @end{Honest} @begin{Ramification} Examples: The execution of an @nt{if_statement} dynamically encloses the evaluation of the @nt{condition} after the @key{if} (during that evaluation). (Recall that @lquotes@;execution@rquotes@; includes both @lquotes@;elaboration@rquotes@; and @lquotes@;evaluation@rquotes@;, as well as other executions.) The evaluation of a function call dynamically encloses the execution of the @nt{sequence_of_statements} of the function @nt{body} (during that execution). Note that, due to recursion, several simultaneous executions of the same construct can be occurring at once during the execution of a particular task. Dynamically enclosing is not defined across task boundaries; a task's execution does not include the execution of any other tasks. Dynamically enclosing is only defined for executions that are occurring at a given moment in time; if an @nt{if_statement} is currently executing the @nt{sequence_of_statements} after @key{then}, then the evaluation of the @nt{condition} is no longer dynamically enclosed by the execution of the @nt{if_statement} (or anything else). @end{Ramification} @Leading@Defn2{Term=[raise], Sec=(an exception occurrence)} When an exception occurrence is raised by the execution of a given construct, the rest of the execution of that construct is @i{abandoned}; that is, any portions of the execution that have not yet taken place are not performed. The construct is first completed, and then left, as explained in @RefSecNum{Completion and Finalization}. Then: @begin{Itemize} If the construct is a @nt<task_body>, the exception does not propagate further; @begin{Ramification} When an exception is raised by the execution of a @nt{task_body}, there is no dynamically enclosing execution, so the exception does not propagate any further. If the exception occurred during the activation of the task, then the activator raises Tasking_Error, as explained in @RefSec{Task Execution - Task Activation}, but we don't define that as propagation; it's a special rule. Otherwise (the exception occurred during the execution of the @nt{handled_sequence_of_statements} of the task), the task silently disappears. Thus, abnormal termination of tasks is not always considered to be an error. @end{Ramification} If the construct is the @nt{sequence_of_statements} of a @nt{handled_sequence_of_statements} that has a handler with a choice covering the exception, the occurrence is handled by that handler; @Defn2{Term=[propagate], Sec=(an exception occurrence by an execution, to a dynamically enclosing execution)} Otherwise, the occurrence is @i{propagated} to the innermost dynamically enclosing execution, which means that the occurrence is raised again in that context. @begin{Honest} @Defn2{Term=[propagate], Sec=(an exception by an execution)} @Defn2{Term=[propagate], Sec=(an exception by a construct)} As shorthands, we refer to the @i{propagation of an exception}, and the @i{propagation by a construct}, if the execution of the construct propagates an exception occurrence. @end{Honest} @end{Itemize} @Defn2{Term=[handle], Sec=(an exception occurrence)} @PDefn2{Term=[execution], Sec=(handler)} @PDefn2{Term=[elaboration], Sec=(choice_parameter_specification)} When an occurrence is @i(handled) by a given handler, the @nt{choice_parameter_specification}, if any, is first elaborated, which creates the choice parameter and initializes it to the occurrence. Then, the @nt{sequence_of_statements} of the handler is executed; this execution replaces the abandoned portion of the execution of the @nt{sequence_of_statements}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} This @lquotes@;replacement@rquotes@; semantics implies that the handler can do pretty much anything the abandoned sequence could do; for example, in a function, the handler can execute a @Chg{Version=[2],New=[return statement], Old=[@nt{return_statement}]} that applies to the function. @end{Ramification} @begin{Ramification} The rules for exceptions raised in library units, main subprograms and partitions follow from the normal rules, plus the semantics of the environment task described in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Program Structure and Compilation Issues} (for example, the environment task of a partition elaborates library units and calls the main subprogram). If an exception is propagated by the main subprogram, it is propagated to the environment task, which then terminates abnormally, causing the partition to terminate abnormally. Although abnormal termination of tasks is not necessarily an error, abnormal termination of a partition due to an exception @i{is} an error. @end{Ramification} @end{RunTime} @begin{Notes} Note that exceptions raised in a @nt{declarative_part} of a body are not handled by the handlers of the @nt{handled_@!sequence_of_@!statements} of that body. @end{Notes} @LabeledSubClause{The Package Exceptions} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01],ARef=[AI95-00400-01],ARef=[AI95-00438-01]} @ChildUnit{Parent=[Ada],Child=[Exceptions]}@Chg{Version=[2],New=[@key[with] Ada.Streams; ],Old=[]}@key[package] Ada.Exceptions @key[is]@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Exceptions);],Old=[]} @key[type] @AdaTypeDefn{Exception_Id} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Exception_Id);],Old=[]} @AdaObjDefn{Null_Id} : @key[constant] Exception_Id; @key[function] @AdaSubDefn{Exception_Name}(Id : Exception_Id) @key[return] String;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Exception_Name}(Id : Exception_Id) @key[return] Wide_String; @key[function] @AdaSubDefn{Wide_Wide_Exception_Name}(Id : Exception_Id) @key[return] Wide_Wide_String;],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[type] @AdaTypeDefn{Exception_Occurrence} @key[is] @key[limited] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Exception_Occurrence);],Old=[]} @key[type] @AdaTypeDefn{Exception_Occurrence_Access} @key[is] @key[access] @key[all] Exception_Occurrence; @AdaObjDefn{Null_Occurrence} : @key[constant] Exception_Occurrence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00329-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[procedure] @AdaSubDefn{Raise_Exception}(E : @key[in] Exception_Id; Message : @key[in] String := "")@Chg{Version=[3],New=[],Old=[;]}@Chg{Version=[2],New=[ @Chg{Version=[3],New=[@key[with]],Old=[@key[pragma]]} No_Return@Chg{Version=[3],New=[],Old=[(Raise_Exception)]};],Old=[]} @key[function] @AdaSubDefn{Exception_Message}(X : Exception_Occurrence) @key[return] String; @key[procedure] @AdaSubDefn{Reraise_Occurrence}(X : @key[in] Exception_Occurrence); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} @key[function] @AdaSubDefn{Exception_Identity}(X : Exception_Occurrence) @key[return] Exception_Id; @key[function] @AdaSubDefn{Exception_Name}(X : Exception_Occurrence) @key[return] String; --@RI{ Same as Exception_Name(Exception_Identity(X)).}@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Wide_Exception_Name}(X : Exception_Occurrence) @key[return] Wide_String; --@RI{ Same as Wide_Exception_Name(Exception_Identity(X)).} @key[function] @AdaSubDefn{Wide_Wide_Exception_Name}(X : Exception_Occurrence) @key[return] Wide_Wide_String; --@RI{ Same as Wide_Wide_Exception_Name(Exception_Identity(X)).}],Old=[]} @key[function] @AdaSubDefn{Exception_Information}(X : Exception_Occurrence) @key[return] String; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00438-01]} @key[procedure] @AdaSubDefn{Save_Occurrence}(Target : @key[out] Exception_Occurrence; Source : @key[in] Exception_Occurrence); @key[function] @AdaSubDefn{Save_Occurrence}(Source : Exception_Occurrence) @key[return] Exception_Occurrence_Access;@Chg{Version=[2],New=[],Old=[ @key[private] ... --@RI{ not specified by the language} @key[end] Ada.Exceptions;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] Read_Exception_Occurrence (Stream : @key[not null access] Ada.Streams.Root_Stream_Type'Class; Item : @key[out] Exception_Occurrence); @key[procedure] Write_Exception_Occurrence (Stream : @key[not null access] Ada.Streams.Root_Stream_Type'Class; Item : @key[in] Exception_Occurrence);]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[ @key[for] Exception_Occurrence'Read @key[use] Read_Exception_Occurrence; @key[for] Exception_Occurrence'Write @key[use] Write_Exception_Occurrence;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[@key[private] ... --@RI{ not specified by the language} @key[end] Ada.Exceptions;]} @end{Example} Each distinct exception is represented by a distinct value of type Exception_Id. Null_Id does not represent any exception, and is the default initial value of type Exception_Id. Each occurrence of an exception is represented by a value of type Exception_Occurrence. Null_Occurrence does not represent any exception occurrence, and is the default initial value of type Exception_Occurrence. @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} E that denotes an exception]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<E>, AttrName=<Identity>, Text=[E'Identity returns the unique identity of the exception. The type of this attribute is Exception_Id.]} @begin{Ramification} In a distributed program, the identity is unique across an entire program, not just across a single partition. Exception propagation works properly across RPC's. An exception can be propagated from one partition to another, and then back to the first, where its identity is known. @end{Ramification} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00361-01]} Raise_Exception raises a new occurrence of the identified exception.@Chg{Version=[2],New=[],Old=[ In this case Exception_Message returns the Message parameter of Raise_Exception. For a @nt{raise_statement} with an @i{exception_}@nt{name}, Exception_Message returns implementation-defined information about the exception occurrence. Reraise_Occurrence reraises the specified exception occurrence.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01],ARef=[AI95-00378-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0043-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[Exception_Message returns the message associated with the given Exception_Occurrence. For an occurrence raised by a call to Raise_Exception, the message is the Message parameter passed to Raise_Exception. For the occurrence raised by a @nt{raise_statement} with an @SynI{exception_}@nt{name} and a @SynI{string_}@nt{expression}, the message is the @Syni{string_}@nt{expression}. For the occurrence raised by a @nt{raise_statement} with an @Syni{exception_}@nt{name} but without a @Syni{string_}@nt{expression}, the message is a string giving implementation-defined information about the exception occurrence. @Chg{Version=[3],New=[For an occurrence originally raised in some other manner (including by the failure of a language-defined check), the message is an unspecified string.@PDefn{unspecified} ],Old=[]}In all cases, Exception_Message returns a string with lower bound 1.]} @ImplDef{The information returned by Exception_Message.} @begin{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0043-1]} @ChgAdded{Version=[3],Text=[There is @ImplAdviceName about the contents of this string for language-defined checks.]} @end{Discussion} @begin{Ramification} @Leading@Keepnext@;Given an exception E, the @nt{raise_statement}: @begin{Example} @key[raise] E; @end{Example} @Leading@keepnext@;is equivalent to this call to Raise_Exception: @begin{Example} Raise_Exception(E'Identity, Message => @RI{implementation-defined-string}); @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Similarly, the @nt{raise_statement}:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[raise] E @key[with] "some information";]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[is equivalent to this call to Raise_Exception:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Raise_Exception(E'Identity, Message => "some information");]} @end{Example} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[Reraise_Occurrence reraises the specified exception occurrence.]} @begin{Ramification} @Leading@keepnext@;The following handler: @begin{Example} @key[when] @key[others] => Cleanup; @key[raise]; @end{Example} @begin{WideAbove} @Leading@keepnext@;is equivalent to this one: @end{WideAbove} @begin{Example} @key[when] X : @key[others] => Cleanup; Reraise_Occurrence(X); @end{Example} @end{Ramification} Exception_Identity returns the identity of the exception of the occurrence. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00400-01]} The @Chg{Version=[2],New=[Wide_@!Wide_@!Exception_Name],Old=[Exception_Name]} functions return the full expanded name of the exception, in upper case, starting with a root library unit. For an exception declared immediately within package Standard, the @nt{defining_@!identifier} is returned. The result is implementation defined if the exception is declared within an unnamed @nt{block_statement}. @begin{Ramification} See the @ImplPermName below. @end{Ramification} @begin{Honest} This name, as well as each @nt{prefix} of it, does not denote a @nt{renaming_declaration}. @end{Honest} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The result of @Chg{Version=[2], New=[Exceptions.@!Wide_@!Wide_@!Exception_@!Name],Old=[Exceptions.@!Exception_@!Name]} for @Chg{Version=[2],New=[exceptions],Old=[types]} declared within an unnamed @nt{block_statement}.]} @begin{Ramification} Note that we're talking about the name of the exception, not the name of the occurrence. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[The Exception_Name functions (respectively, Wide_Exception_Name) return the same sequence of graphic characters as that defined for Wide_Wide_Exception_Name, if all the graphic characters are defined in Character (respectively, Wide_Character); otherwise, the sequence of characters is implementation defined, but no shorter than that returned by Wide_Wide_Exception_Name for the same value of the argument.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[ The sequence of characters of the value returned by Exceptions.Exception_Name (respectively, Exceptions.Wide_Exception_Name) when some of the graphic characters of Exceptions.Wide_Wide_Exception_Name are not defined in Character (respectively, Wide_Character).],Old=[]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00378-01],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=[The string returned by the Exception_Name, Wide_Exception_Name, and Wide_Wide_Exception_Name functions has lower bound 1.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00378-01]} Exception_Information returns implementation-defined information about the exception occurrence. @Chg{Version=[2],New=[The returned string has lower bound 1.],Old=[]} @ImplDef{The information returned by Exception_Information.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00241-01],ARef=[AI95-00446-01]} @Chg{Version=[2],New=[],Old=[Raise_Exception and ]}Reraise_Occurrence @Chg{Version=[2],New=[has],Old=[have]} no effect in the case of @Chg{Version=[2],New=[],Old=[Null_Id or ]}Null_Occurrence. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Chg{Version=[2],New=[Raise_Exception and Exception_Name raise Constraint_Error for a Null_Id. Exception_Message, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Occurrence. Exception_Identity applied to Null_Occurrence returns Null_Id.], Old=[Exception_Message, Exception_Identity, Exception_Name, and Exception_Information raise Constraint_Error for a Null_Id or Null_Occurrence.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00241-01]} @ChgAdded{Version=[2],Text=[Null_Occurrence can be tested for by comparing Exception_Identity(Occurrence) to Null_Id.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00446-01]} @ChgAdded{Version=[2],Text=[Raise_Exception was changed so that it always raises an exception and thus can be a No_Return procedure. A similar change was not made for Reraise_Occurrence, as doing so was determined to be a significant incompatibility. It is not unusual to pass an Exception_Occurrence to other code to delay raising it. If there was no exception, passing Null_Occurrence works fine (nothing is raised). Moreover, as there is no test for Null_Occurrence in Ada 95, this is the only way to write such code without using additional flags. Breaking this sort of code is unacceptable.]} @end{Discussion} The Save_Occurrence procedure copies the Source to the Target. The Save_Occurrence function uses an @nt{allocator} of type Exception_Occurrence_Access to create a new object, copies the Source to this new object, and returns an access value designating this new object; @Redundant[the result may be deallocated using an instance of Unchecked_Deallocation.] @begin{Ramification} It's OK to pass Null_Occurrence to the Save_Occurrence subprograms; they don't raise an exception, but simply save the Null_Occurrence. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00438-01]} @ChgAdded{Version=[2],Text=[Write_Exception_Occurrence writes a representation of an exception occurrence to a stream; Read_Exception_Occurrence reconstructs an exception occurrence from a stream (including one written in a different partition).]} @ChgNote{All of these notes (except the first) are moved from below.} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routines are used to define the stream attributes (see @RefSecNum{Stream-Oriented Attributes}) for Exception_Occurrence.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The identity of the exception, as well as the Exception_Name and Exception_Message, have to be preserved across partitions.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The string returned by Exception_Name or Exception_Message on the result of calling the Read attribute on a given stream has to be the same as the value returned by calling the corresponding function on the exception occurrence that was written into the stream with the Write attribute. The string returned by Exception_Information need not be the same, since it is implementation defined anyway.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important for supporting writing exception occurrences to external files for post-mortem analysis, as well as propagating exceptions across remote subprogram calls in a distributed system (see @RefSecNum{Remote Subprogram Calls}).]} @end{Reason} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00438-01]} @ChgDeleted{Version=[2],Text=[The implementation of the Write attribute (see @RefSecNum{Stream-Oriented Attributes}) of Exception_Occurrence shall support writing a representation of an exception occurrence to a stream; the implementation of the Read attribute of Exception_Occurrence shall support reconstructing an exception occurrence from a stream (including one written in a different partition).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The identity of the exception, as well as the Exception_Name and Exception_Message, have to be preserved across partitions.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[The string returned by Exception_Name or Exception_Message on the result of calling the Read attribute on a given stream has to be the same as the value returned by calling the corresponding function on the exception occurrence that was written into the stream with the Write attribute. The string returned by Exception_Information need not be the same, since it is implementation defined anyway.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This is important for supporting writing exception occurrences to external files for post-mortem analysis, as well as propagating exceptions across remote subprogram calls in a distributed system (see @RefSecNum{Remote Subprogram Calls}).]} @end{Reason} @end{ImplReq} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraph 16 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{ImplPerm} An implementation of Exception_Name in a space-constrained environment may return the @nt{defining_@!identifier} instead of the full expanded name. The string returned by Exception_Message may be truncated (to no less than 200 characters) by the Save_Occurrence procedure @Redundant[(not the function)], the Reraise_Occurrence procedure, and the re-raise statement. @begin{Reason} The reason for allowing truncation is to ease implementations. The reason for choosing the number 200 is that this is the minimum source line length that implementations have to support, and this feature seems vaguely related since it's usually a @lquotes@;one-liner@rquotes@;. Note that an implementation is allowed to do this truncation even if it supports arbitrarily long lines. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} Exception_Message (by default) and Exception_Information should produce information useful for debugging. Exception_Message should be short (about one line), whereas Exception_Information can be long. Exception_Message should not include the Exception_Name. Exception_Information should include both the Exception_Name and the Exception_Message. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Exception_Information should provide information useful for debugging, and should include the Exception_Name and Exception_Message.]}]} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Exception_Message by default should be short, provide information useful for debugging, and should not include the Exception_Name.]}]} @begin{Reason} It may seem strange to define two subprograms whose semantics is implementation defined. The idea is that a program can print out debugging/error-logging information in a portable way. The program is portable in the sense that it will work in any implementation; it might print out different information, but the presumption is that the information printed out is appropriate for debugging/error analysis on that system. @end{Reason} @begin{ImplNote} As an example, Exception_Information might include information identifying the location where the exception occurred, and, for predefined exceptions, the specific kind of language-defined check that failed. There is an implementation trade-off here, between how much information is represented in an Exception_Occurrence, and how much can be passed through a re-raise. The string returned should be in a form suitable for printing to an error log file. This means that it might need to contain line-termination control characters with implementation-defined I/O semantics. The string should neither start nor end with a newline. If an implementation chooses to provide additional functionality related to exceptions and their occurrences, it should do so by providing one or more children of Ada.Exceptions. Note that exceptions behave as if declared at library level; there is no @lquotes@;natural scope@rquotes@; for an exception; an exception always exists. Hence, there is no harm in saving an exception occurrence in a data structure, and reraising it later. The reraise has to occur as part of the same program execution, so saving an exception occurrence in a file, reading it back in from a different program execution, and then reraising it is not required to work. This is similar to I/O of access types. Note that it is possible to use RPC to propagate exceptions across partitions. @Leading@;Here's one way to implement Exception_Occurrence in the private part of the package. Using this method, an implementation need store only the actual number of characters in exception messages. If the user always uses small messages, then exception occurrences can be small. If the user never uses messages, then exception occurrences can be smaller still: @begin{Example} @key[type] Exception_Occurrence(Message_Length : Natural := 200) @key[is] @key[limited] @key[record] Id : Exception_Id; Message : String(1..Message_Length); @key[end] @key[record]; @end{Example} @Leading@;At the point where an exception is raised, an Exception_Occurrence can be allocated on the stack with exactly the right amount of space for the message @em none for an empty message. This is just like declaring a constrained object of the type: @begin{Example} Temp : Exception_Occurrence(10); --@RI{ for a 10-character message} @end{Example} After finding the appropriate handler, the stack can be cut back, and the Temp copied to the right place. This is similar to returning an unknown-sized object from a function. It is not necessary to allocate the maximum possible size for every Exception_Occurrence. If, however, the user declares an Exception_Occurrence object, the discriminant will be permanently set to 200. The Save_Occurrence procedure would then truncate the Exception_Message. Thus, nothing is lost until the user tries to save the occurrence. If the user is willing to pay the cost of heap allocation, the Save_Occurrence function can be used instead. Note that any arbitrary-sized implementation-defined Exception_Information can be handled in a similar way. For example, if the Exception_Occurrence includes a stack traceback, a discriminant can control the number of stack frames stored. The traceback would be truncated or entirely deleted by the Save_Occurrence procedure @em as the implementation sees fit. If the internal representation involves pointers to data structures that might disappear, it would behoove the implementation to implement it as a controlled type, so that assignment can either copy the data structures or else null out the pointers. Alternatively, if the data structures being pointed at are in a task control block, the implementation could keep a unique sequence number for each task, so it could tell when a task's data structures no longer exist. Using the above method, heap space is never allocated unless the user calls the Save_Occurrence function. @Leading@;An alternative implementation would be to store the message strings on the heap when the exception is raised. (It could be the global heap, or it could be a special heap just for this purpose @em it doesn't matter.) This representation would be used only for choice parameters. For normal user-defined exception occurrences, the Save_Occurrence procedure would copy the message string into the occurrence itself, truncating as necessary. Thus, in this implementation, Exception_Occurrence would be implemented as a variant record: @begin{Example} @key[type] Exception_Occurrence_Kind @key[is] (Normal, As_Choice_Param); @key[type] Exception_Occurrence(Kind : Exception_Occurrence_Kind := Normal) @key[is] @key[limited] @key[record] @key[case] Kind @key[is] @key[when] Normal => ... --@RI{ space for 200 characters} @key[when] As_Choice_Param => ... --@RI{ pointer to heap string} @key[end] @key[case]; @key[end] @key[record]; @end{Example} Exception_Occurrences created by the run-time system during exception raising would be As_Choice_Param. User-declared ones would be Normal @em the user cannot see the discriminant, and so cannot set it to As_Choice_Param. The strings in the heap would be freed upon completion of the handler. This alternative implementation corresponds to a heap-based implementation of functions returning unknown-sized results. @Leading@;One possible implementation of Reraise_Occurrence is as follows: @begin{Example} @key[procedure] Reraise_Occurrence(X : @key[in] Exception_Occurrence) @key[is] @key[begin] Raise_Exception(Identity(X), Exception_Message(X)); @key[end] Reraise_Occurrence; @end{Example} However, some implementations may wish to retain more information across a re-raise @em a stack traceback, for example. @end{ImplNote} @begin{Ramification} Note that Exception_Occurrence is a definite subtype. Hence, values of type Exception_Occurrence may be written to an error log for later analysis, or may be passed to subprograms for immediate error analysis. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00400-01]} @ChgDeleted{Version=[2],Text=[If an implementation chooses to have a mode in which it supports non-Latin-1 characters in identifiers, then it needs to define what the above functions return in the case where the name of an exception contains such a character.]} @end{ImplNote} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} The Identity attribute of exceptions is new, as is the package Exceptions. @end{Extend83} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00241-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @B[Amendment Correction:] Exception_Identity of an Exception_Occurrence now is defined to return Null_Id for Null_Occurrence, rather than raising Constraint_Error. This provides a simple way to test for Null_Occurrence. We expect that programs that need Constraint_Error raised will be very rare; they can be easily fixed by explicitly testing for Null_Id or by using Exception_Name instead.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00378-01],ARef=[AI95-00417-01]} @ChgAdded{Version=[2],Text=<@B[Amendment Correction:] We now define the lower bound of the string returned from [[Wide_]Wide_]Exception_Name, Exception_Message, and Exception_Information. This makes working with the returned string easier, and is consistent with many other string-returning functions in Ada. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from one of these functions, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.>} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00446-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Raise_Exception now raises Constraint_Error if passed Null_Id. This means that it always raises an exception, and thus we can apply pragma No_Return to it. We expect that programs that call Raise_Exception with Null_Id will be rare, and programs that do that and expect no exception to be raised will be rarer; such programs can be easily fixed by explicitly testing for Null_Id before calling Raise_Exception.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00400-01],ARef=[AI95-00438-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Functions Wide_Exception_Name and Wide_Wide_Exception_Name, and procedures Read_Exception_Occurrence and Write_Exception_Occurrence are @Chg{Version=[3],New=[],Old=[newly ]}added to Exceptions. If Exceptions is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Exceptions is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Exceptions is preelaborated, and types Exception_Id and Exception_Occurrence have preelaborable initialization, allowing this package to be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00361-01]} @ChgAdded{Version=[2],Text=[The meaning of Exception_Message is reworded to reflect that the string can come from a @nt{raise_statement} as well as a call of Raise_Exception.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[Added Wide_Exception_Name and Wide_Wide_Exception_Name because identifiers can now contain characters outside of Latin-1.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0043-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added explicit wording that the exception message for language-defined checks is unspecified. The old wording appeared inclusive, but it was not.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[2],Name=[Pragmas Assert and Assertion_Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0274-1]} @ChgAdded{Version=[2],Text=[Pragma Assert is used to assert the truth of a @Chg{Version=[3],New=[boolean],Old=[Boolean]} expression at @Chg{Version=[3],New=[a],Old=[any]} point within a sequence of declarations or statements.@Chg{Version=[3],New=[],Old=[ Pragma Assertion_Policy is used to control whether such assertions@Defn{Assertions} are to be ignored by the implementation, checked at run-time, or handled in some implementation-defined manner.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[Assert pragmas, subtype predicates (see @RefSecNum{Subtype Predicates}), preconditions and postconditions (see @RefSecNum{Preconditions and Postconditions}), and type invariants (see @RefSecNum{Type Invariants}) are collectively referred to as @i{assertions}; their boolean expressions are referred to as @i{assertion expressions}.@Defn{assertions}@Defn{assertion expressions}]} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Predicate>, Text=<@ChgAdded{Version=[3],Text=[A predicate is an assertion that is expected to be True for all objects of a given subtype.]}>} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Precondition>, Text=<@ChgAdded{Version=[3],Text=[A precondition is an assertion that is expected to be True when a given subprogram is called.]}>} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Postcondition>, Text=<@ChgAdded{Version=[3],Text=[A postcondition is an assertion that is expected to be True when a given subprogram returns normally.]}>} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Invariant>, Text=<@ChgAdded{Version=[3],Text=[A invariant is an assertion that is expected to be True for all objects of a given private type when viewed from outside the defining package.]}>} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Assertion>, Text=<@ChgAdded{Version=[3],Text=[An assertion is a boolean expression that appears in any of the following: a @nt{pragma} Assert, a predicate, a precondition, a postcondition, an invariant, a constraint, or a null exclusion. An assertion is expected to be True at run time at certain specified places.]}>} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[Pragma Assertion_Policy is used to control whether assertions are to be ignored by the implementation, checked at run time, or handled in some implementation-defined manner.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Assert is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[2],@ChgAdded{Version=[2], Text=`@key{pragma} @prag<Assert>([Check =>] @SynI{boolean_}@Syn2{expression}[, [Message =>] @SynI{string_}@Syn2{expression}]);'}> @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A @nt{pragma} Assert is allowed at the place where a @nt{declarative_item} or a @nt{statement} is allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Assertion_Policy is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[2],@ChgAdded[Version=[2], Text=<@key{pragma} @prag<Assertion_Policy>(@SynI{policy_}@Syn2{identifier});>]> @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @AddedPragmaSyn<Version=[3],@ChgAdded[Version=[3], Text=[@key{pragma} @prag<Assertion_Policy>(@* @ @ @ @ @ @ @ @ @ @SynI(assertion_)@Syn2{aspect_mark} => @SynI{policy_}@Syn2{identifier}@* @ @ @ @ @ {, @SynI(assertion_)@Syn2{aspect_mark} => @SynI{policy_}@Syn2{identifier}});]]> @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Assertion_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Assertion_Policy)} A @nt{pragma} Assertion_Policy is@Chg{Version=[3],New=[ allowed only immediately within a @nt{declarative_part}, immediately within a @nt{package_specification}, or as],Old=[]} a configuration pragma.]} @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The expected type for the @Syni{boolean_}@nt{expression} of a @nt{pragma} Assert is any boolean type. The expected type for the @Syni{string_}@nt{expression} of a @nt{pragma} Assert is type String.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We allow any boolean type to be like @nt{if_statement}s and other conditionals; we only allow String for the message in order to match @nt{raise_statement}s.]} @end{Reason} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[The @SynI<assertion_>@nt{aspect_mark} of a @nt{pragma} Assertion_Policy shall be one of Assert, Static_Predicate, Dynamic_Predicate, Pre, Pre'Class, Post, Post'Class, Type_Invariant, Type_Invariant'Class, or some implementation defined @nt{aspect_mark}. ],Old=[]}The @SynI<policy_>@nt<identifier>@Chg{Version=[3],New=[],Old=[ of a @nt{pragma} Assertion_Policy]} shall be either Check, Ignore, or @Chg{Version=[3],New=[some],Old=[an]} implementation-defined @nt{identifier}.]} @ChgImplDef{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@Chg{Version=[2],New=[Implementation-defined @SynI<policy_>@nt{identifier}s @Chg{Version=[3],New=[and @SynI<assertion_>@nt{aspect_mark}s ],Old=[]}allowed in a @nt{pragma} Assertion_Policy.],Old=[]}]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[A @nt{pragma} Assertion_Policy @Chg{Version=[3],New=[determines for each assertion aspect named in the @nt{pragma_argument_association}s whether assertions of the given aspect are to be enforced by a run-time check. The @SynI<policy_>@nt{identifier} Check requires that assertion expressions of the given aspect be checked that they evaluate to True at the points specified for the given aspect; the @SynI<policy_>@nt{identifier} Ignore requires that the assertion expression not be evaluated at these points, and the run-time checks not be performed. @Redundant[Note that for subtype predicate aspects (see @RefSecNum{Subtype Predicates}), even when the applicable Assertion_Policy is Ignore, the predicate will still be evaluated as part of membership tests and Valid @nt{attribute_reference}s, and if static, will still have an effect on loop iteration over the subtype, and the selection of @nt{case_statement_alternative}s and @nt{variant}s.]],Old=[is a configuration pragma that specifies the assertion policy in effect for the compilation units to which it applies. Different policies may apply to different compilation units within the same partition. The default assertion policy is implementation-defined.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If no @SynI<assertion_>@nt{aspect_mark}s are specified in the pragma, the specified policy applies to all assertion aspects.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Assertion_Policy applies to the named assertion aspects in a specific region, and applies to all assertion expressions specified in that region. A @nt{pragma} Assertion_Policy given in a @nt{declarative_part} or immediately within a @nt{package_specification} applies from the place of the pragma to the end of the innermost enclosing declarative region. The region for a @nt{pragma} Assertion_Policy given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If a @nt{pragma} Assertion_Policy applies to a @nt{generic_instantiation}, then the @nt{pragma} Assertion_Policy applies to the entire instance.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[This means that an Assertion_Policy pragma that occurs in a scope enclosing the declaration of a generic unit but not also enclosing the declaration of a given instance of that generic unit will not apply to assertion expressions occurring within the given instance.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[If multiple Assertion_Policy pragmas apply to a given construct for a given assertion aspect, the assertion policy is determined by the one in the innermost enclosing region of a @nt{pragma} Assertion_Policy specifying a policy for the assertion aspect. If no such Assertion_Policy pragma exists, the policy is implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The default assertion policy.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Assertions]}@key[package] Ada.Assertions @key[is] @key[pragma] Pure(Assertions);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Assertion_Error} : @key<exception>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Assert}(Check : @key<in> Boolean); @key<procedure> @AdaSubDefn{Assert}(Check : @key<in> Boolean; Message : @key<in> String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Assertions;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[A compilation unit containing a @Chg{Version=[3],New=[check for an assertion (including a ],Old=[]}@nt{pragma} Assert@Chg{Version=[3],New=[)],Old=[]} has a semantic dependence on the Assertions library unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The assertion policy that applies to a generic unit also applies to all its instances.]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[An assertion policy @defn{assertion policy}specifies how a @nt{pragma} Assert is interpreted by the implementation. If the assertion policy is Ignore at the point of a @nt{pragma} Assert, the pragma is ignored.]} If @Chg{Version=[3],New=[performing checks is required by ],Old=[]}the @Chg{Version=[3],New=[Assert ],Old=[]}assertion policy @Chg{Version=[3],New=[in effect],Old=[is Check]} at the @Chg{Version=[3],New=[place],Old=[point]} of a @nt{pragma} Assert, the elaboration of the pragma consists of evaluating the boolean expression, and if the result is False, evaluating the Message argument, if any, and raising the exception Assertions.Assertion_Error, with a message if the Message argument is provided.@Defn2{Term=[assertion policy],Sec=[Assert pragma]}@Defn2{Term=(Assertion_Error), Sec=(raised by failure of assertion)}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Calling the procedure Assertions.Assert without a Message parameter is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<if> Check = False @key<then> @key<raise> Ada.Assertions.Assertion_Error; @key{end} @key{if};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[Calling the procedure Assertions.Assert with a Message parameter is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<if> Check = False @key<then> @key<raise> Ada.Assertions.Assertion_Error @key<with> Message; @key{end} @key{if};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[The procedures Assertions.Assert have these effects independently of the assertion policy in effect.]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[It is a bounded error to invoke a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}) during the evaluation of an assertion expression associated with a call on, or return from, a protected operation. If the bounded error is detected, Program_Error is raised. If not detected, execution proceeds normally, but if it is invoked within a protected action, it might result in deadlock or a (nested) protected action.]} @end{Bounded} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Assertion_Error may be declared by renaming an implementation-defined exception from another package.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This permission is intended to allow implementations which had an implementation-defined Assert pragma to continue to use their originally defined exception. Without this permission, such an implementation would be incorrect, as Exception_Name would return the wrong name.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Implementations may define their own assertion policies.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[If the result of a function call in an assertion is not needed to determine the value of the assertion expression, an implementation is permitted to omit the function call. @Redundant[This permission applies even if the function has side effects.]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[An implementation need not allow the specification of an assertion expression if the evaluation of the expression has a side effect such that an immediate reevaluation of the expression could produce a different value. Similarly, an implementation need not allow the specification of an assertion expression that is checked as part of a call on or return from a callable entity @i<C>, if the evaluation of the expression has a side effect such that the evaluation of some other assertion expression associated with the same call of (or return from) @i<C> could produce a different value than it would if the first expression had not been evaluated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This allows an implementation to reject such assertions. To maximize portability, assertions should not include expressions that contain these sorts of side effects.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The intended effect of the second part of the rule (the part starting with @ldquote@;Similarly@rdquote) is that an evaluation of the involved assertion expressions (subtype predicates, type invariants, preconditions and postconditions) in any order yields identical results.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The rule is intended to apply to all of the assertion expressions that are evaluated at the start of call (and similarly for the assertion expressions that are evaluated during the return from a call), but not other assertions actually given in the body, nor between the assertions checked at the start and end of the call. Specifically, a side effect that alters a variable in a function called from a precondition expression that changes the result of a postcondition expression of the same subprogram does @i<not> trigger these rules unless it also changes the value of a reevaluation of the precondition expression.]} @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[Normally, the boolean expression in a @nt{pragma} Assert should not call functions that have significant side effects when the result of the expression is True, so that the particular assertion policy in effect will not affect normal operation of the program.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00286-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Pragmas Assert and Assertion_Policy, and package Assertions are new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0274-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} There now is an @ImplPermName to reject an assertion expression that calls a function that has a side effect such that an immediate reevalution of the expression could produce a different value. This means that a @nt{pragma} Assert that works in Ada 2005 might be illegal in Ada 2012 in the unlikely event that the compiler detected such an error. This should be unlikely to occur in practice and it is considered a good thing, as the original expression was tricky and probably was not portable (as order of evaluation is unspecified within an expression). Moreover, no compiler is @i<required> to reject such expressions, so there is no need for any compiler to change behavior.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Assertion_Policy pragmas are now allowed in more places and can specify behavior for invidivual kinds of assertions.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Example of Exception Handling} @begin{Examples} @Leading@;Exception handling may be used to separate the detection of an error from the response to that error: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @Chg{Version=[2],New=[],Old=[@key[with] Ada.Exceptions; @key[use] Ada; ]}@key[package] File_System @key[is] @key[type] File_Handle @key[is] @key[limited] @key[private]; File_Not_Found : @key[exception]; @key[procedure] Open(F : @key[in] @key[out] File_Handle; Name : String); --@RI{ raises File_Not_Found if named file does not exist} End_Of_File : @key[exception]; @key[procedure] Read(F : @key[in] @key[out] File_Handle; Data : @key[out] Data_Type); --@RI{ raises End_Of_File if the file is not open} ... @key[end] File_System; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[package] @key[body] File_System @key[is] @key[procedure] Open(F : @key[in] @key[out] File_Handle; Name : String) @key[is] @key[begin] @key[if] File_Exists(Name) @key[then] ... @key[else] @Chg{Version=[2],New=[@key[raise] ],Old=[Exceptions.Raise_Exception(]}File_Not_Found@Chg{Version=[2],New=[ @key[with] ],Old=['Identity, ]}"File not found: " & Name & "."@Chg{Version=[2],New=[],Old=[)]}; @key[end] @key[if]; @key[end] Open; @key[procedure] Read(F : @key[in] @key[out] File_Handle; Data : @key[out] Data_Type) @key[is] @key[begin] @key[if] F.Current_Position <= F.Last_Position @key[then] ... @key[else] @key[raise] End_Of_File; @key[end] @key[if]; @key[end] Read; ... @key[end] File_System; @key[with] Ada.Text_IO; @key[with] Ada.Exceptions; @key[with] File_System; @key[use] File_System; @key[use] Ada; @key[procedure] Main @key[is] @key[begin] ... --@RI{ call operations in File_System} @key[exception] @key[when] End_Of_File => Close(Some_File); @key[when] Not_Found_Error : File_Not_Found => Text_IO.Put_Line(Exceptions.Exception_Message(Not_Found_Error)); @key[when] The_Error : @key[others] => Text_IO.Put_Line("Unknown error:"); @key[if] Verbosity_Desired @key[then] Text_IO.Put_Line(Exceptions.Exception_Information(The_Error)); @key[else] Text_IO.Put_Line(Exceptions.Exception_Name(The_Error)); Text_IO.Put_Line(Exceptions.Exception_Message(The_Error)); @key[end] @key[if]; @key[raise]; @key[end] Main; @end{Example} In the above example, the File_System package contains information about detecting certain exceptional situations, but it does not specify how to handle those situations. Procedure Main specifies how to handle them; other clients of File_System might have different handlers, even though the exceptional situations arise from the same basic causes. @end{Examples} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The sections labeled @lquotes@;Exceptions Raised During ...@rquotes@; are subsumed by this @Chg{Version=[3],New=[subclause],Old=[clause]}, and by parts of @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Tasks and Synchronization}. @end{DiffWord83} @LabeledClause{Suppressing Checks} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @Chg{Version=[2],New=[@i{Checking pragmas}@Defn{checking pragmas} give instructions to an implementation on handling language-defined checks.],Old=[]} A @nt{pragma} Suppress gives permission to an implementation to omit certain language-defined checks@Chg{Version=[2], New=[, while a @nt<pragma> Unsuppress revokes the permission to omit checks.],Old=[]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Defn{language-defined check} @Defn2{Term=[check], Sec=(language-defined)} @IndexSee{Term=[run-time check],See=(language-defined check)} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} A @i{language-defined check} (or simply, a @lquotes@;check@rquotes@;) is one of the situations defined by this International Standard that requires a check to be made at run time to determine whether some condition is true. @Defn2{Term=[failure],Sec=(of a language-defined check)} A check @i{fails} when the condition being checked is @Chg{Version=[3],New=[False],Old=[false]}, causing an exception to be raised. @begin{Discussion} All such checks are defined under @lquotes@;@RunTimeTitle@rquotes@; in clauses and subclauses throughout the standard. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @Leading@Keepnext@;The form@Chg{Version=[2],New=[s of checking pragmas are],Old=[ of a @nt{pragma} Suppress is]} as follows: @end{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @PragmaSyn`@key{pragma} @prag(Suppress)(@Syn2{identifier}@Chg{Version=[2],New=<>,Old=( [, [On =>] @Syn2{name}])});' @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @AddedPragmaSyn<Version=[2],@ChgAdded{Version=[2], Text=<@key{pragma} @prag(Unsuppress)(@Syn2{identifier});>}> @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @PDefn2{Term=[configuration pragma], Sec=(Suppress)} @PDefn2{Term=[pragma, configuration], Sec=(Suppress)} @Chg{Version=[2],New=[@PDefn2{Term=[configuration pragma], Sec=(Unsuppress)} @PDefn2{Term=[pragma, configuration], Sec=(Unsuppress)}],Old=[]} A @Chg{Version=[2],New=<checking pragma>,Old=<@nt{pragma} Suppress>} is allowed only immediately within a @nt{declarative_part}, immediately within a @nt{package_@!specification}, or as a configuration pragma. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} The @nt{identifier} shall be the name of a check. @Chg{Version=[2],New=<>,Old=<The @nt{name} (if present) shall statically denote some entity.>} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00224-01]} @ChgDeleted{Version=[2],Text=<For a @nt{pragma} Suppress that is immediately within a @nt{package_specification} and includes a @nt<name>, the @nt<name> shall denote an entity (or several overloaded subprograms) declared immediately within the @nt{package_specification}.>} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A checking pragma applies to the named check in a specific region, and applies to all entities in that region. A checking pragma given in a @nt<declarative_part> or immediately within a @nt<package_specification> applies from the place of the @nt<pragma> to the end of the innermost enclosing declarative region. The region for a checking pragma given as a configuration pragma is the declarative region for the entire compilation unit (or units) to which it applies.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1],ARef=[AI05-0290-1]} @ChgAdded{Version=[2],Text=[If a checking pragma applies to a @Chg{Version=[3],New=[@nt{generic_instantiation}],Old=[generic instantiation]}, then the checking pragma also applies to the @Chg{Version=[3],New=[entire ],Old=[]}instance. @Chg{Version=[3],New=[],Old=[ If a checking pragma applies to a call to a subprogram that has a @nt<pragma> Inline applied to it, then the checking pragma also applies to the inlined subprogram body.]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[This means that a Suppress pragma that occurs in a scope enclosing the declaration of a generic unit but not also enclosing the declaration of a given instance of that generic unit will not apply to constructs within the given instance.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} A @nt{pragma} Suppress gives permission to an implementation to omit the named check @Chg{Version=[2],New=[(or every check in the case of All_Checks) for any entities to which it applies.],Old=[from the place of the @nt{pragma} to the end of the innermost enclosing declarative region, or, if the @nt{pragma} is given in a @nt{package_@!specification} and includes a @nt<name>, to the end of the scope of the named entity. If the @nt{pragma} includes a @nt{name}, the permission applies only to checks performed on the named entity, or, for a subtype, on objects and values of its type. Otherwise, the permission applies to all entities.]} @Defn{suppressed check} If permission has been given to suppress a given check, the check is said to be @i{suppressed}. @begin{Ramification} A check is suppressed even if the implementation chooses not to actually generate better code. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} This allows the implementation to raise Program_Error, for example, if the erroneousness is detected. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A @nt{pragma} Unsuppress revokes the permission to omit the named check (or every check in the case of All_Checks) given by any @nt{pragma} Suppress that applies at the point of the @nt{pragma} Unsuppress. The permission is revoked for the region to which the @nt{pragma} Unsuppress applies. If there is no such permission at the point of a @nt{pragma} Unsuppress, then the @nt{pragma} has no effect. A later @nt{pragma} Suppress can renew the permission.]} @Leading@Keepnext@;The following are the language-defined checks: @begin{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @Leading@Redundant[The following checks correspond to situations in which the exception Constraint_Error is raised upon failure.] @begin{Hang2List} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0036],ARef=[AI95-00176-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} @RootDefn{Access_Check} Access_Check @\@Redundant[When evaluating a dereference (explicit or implicit), check that the value of the @nt{name} is not @key{null}. @Chg{Version=[2],New=[When converting to a subtype that excludes null, check that the converted value is not @key{null}.], Old=[When passing an actual parameter to a formal access parameter, check that the value of the actual parameter is not @key{null}. @Chg{Version=[1],New=[When evaluating a @nt{discriminant_association} for an access discriminant, check that the value of the discriminant is not @key{null}.], Old=[]}]}] @RootDefn{Discriminant_Check} Discriminant_Check @\@Redundant[Check that the discriminants of a composite value have the values imposed by a discriminant constraint. Also, when accessing a record component, check that it exists for the current discriminant values.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @RootDefn{Division_Check} Division_Check @\@Redundant[Check that the second operand is not zero for the operations /, @Chg{Version=[2],New=[@key[rem]],Old=[rem]} and @Chg{Version=[2],New=[@key[mod]],Old=[mod]}.] @RootDefn{Index_Check} Index_Check @\@Redundant[Check that the bounds of an array value are equal to the corresponding bounds of an index constraint. Also, when accessing a component of an array object, check for each dimension that the given index value belongs to the range defined by the bounds of the array object. Also, when accessing a slice of an array object, check that the given discrete range is compatible with the range defined by the bounds of the array object.] @RootDefn{Length_Check} Length_Check @\@Redundant[Check that two arrays have matching components, in the case of array subtype conversions, and logical operators for arrays of boolean components.] @RootDefn{Overflow_Check} Overflow_Check @\@Redundant[Check that a scalar value is within the base range of its type, in cases where the implementation chooses to raise an exception instead of returning the correct mathematical result.] @RootDefn{Range_Check} Range_Check @\@Redundant[Check that a scalar value satisfies a range constraint. Also, for the elaboration of a @nt<subtype_indication>, check that the @nt<constraint> (if present) is compatible with the subtype denoted by the @nt{subtype_mark}. Also, for an @nt<aggregate>, check that an index or discriminant value belongs to the corresponding subtype. Also, check that when the result of an operation yields an array, the value of each component belongs to the component subtype.] @RootDefn{Tag_Check} Tag_Check @\@Redundant[Check that operand tags in a dispatching call are all equal. Check for the correct tag on tagged type conversions, for an @nt{assignment_statement}, and when returning a tagged limited object from a function.] @end{Hang2List} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Leading@Redundant[The following checks correspond to situations in which the exception Program_Error is raised upon failure.] @begin{Hang2List} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280]} @ChgAdded{Version=[2],Text=[@RootDefn{Accessibility_Check} Accessibility_Check @\@Redundant[Check the accessibility level of an entity or view.]]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00280]} @ChgAdded{Version=[2],Text=[@RootDefn{Allocation_Check} Allocation_Check @\@Redundant[For an @nt<allocator>, check that the master of any tasks to be created by the @nt{allocator} is not yet completed or some dependents have not yet terminated, and that the finalization of the collection has not started.]]} @RootDefn{Elaboration_Check} Elaboration_Check @\@Redundant[When a subprogram or protected entry is called, a task activation is accomplished, or a generic instantiation is elaborated, check that the body of the corresponding unit has already been elaborated.] @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00280]} @ChgNote{This item is not in alphabetical order} @ChgDeleted{Version=[2],Text=[@RootDefn{Accessibility_Check} Accessibility_Check @\@Redundant[Check the accessibility level of an entity or view.]]} @end{Hang2List} @Leading@Redundant[The following check corresponds to situations in which the exception Storage_Error is raised upon failure.] @begin{Hang2List} @RootDefn{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} Storage_Check @\@Redundant[Check that evaluation of an @nt{allocator} does not require more space than is available for a storage pool. Check that the space available for a task or subprogram has not been exceeded.] @begin{Reason} We considered splitting this out into three categories: Pool_Check (for @nt{allocator}s), Stack_Check (for stack usage), and Heap_Check (for implicit use of the heap @em use of the heap other than through an @nt{allocator}). Storage_Check would then represent the union of these three. However, there seems to be no compelling reason to do this, given that it is not feasible to split Storage_Error. @end{Reason} @end{Hang2List} @Leading@Redundant[The following check corresponds to all situations in which any predefined exception is raised.] @begin{Hang2List} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0290-1]} @RootDefn{All_Checks} All_Checks @\Represents the union of all checks; suppressing All_Checks suppresses all checks@Chg{Version=[3],New=[ other than those associated with assertions. In addition, an implementation is allowed (but not required) to behave as if a pragma Assertion_Policy(Ignore) applies to any region to which pragma Suppress(All_Checks) applies],Old=[]}. @begin{Ramification} All_Checks includes both language-defined and implementation-defined checks. @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[There are additional checks defined in various Specialized Needs Annexes that are not listed here. Nevertheless, they are included in All_Checks and named in a Suppress pragma on implementations that support the relevant annex. Look up @ldquote@;check, language-defined@rdquote in the index to find the complete list.]} @end{Honest} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[We don't want to say that assertions are suppressed, because we don't want the potential failure of an assertion to cause erroneous execution (see below). Thus they are excluded from the suppression part of the above rule and then handled with an implicit Ignore policy.]} @end{Discussion} @end{Hang2List} @end{Itemize} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a given check has been suppressed, and the corresponding error situation occurs, the execution of the program is erroneous. @end{Erron} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} An implementation is allowed to place restrictions on @Chg{Version=[2],New=[checking pragmas, subject only to the requirement that @nt{pragma} Unsuppress shall allow any check names supported by @nt{pragma} Suppress],Old=[Suppress @nt<pragma>s]}. An implementation is allowed to add additional check names, with implementation-defined semantics. @PDefn{unspecified} When Overflow_Check has been suppressed, an implementation may also suppress an unspecified subset of the Range_Checks. @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00224-01]} @ChgDeleted{Version=[2],Text=[The permission to restrict is given so the implementation can give an error message when the requested suppression is nonsense, such as suppressing a Range_Check on a task type. It would be verbose and pointless to list all the cases of nonsensical language-defined checks in the standard, and since the list of checks is open-ended, we can't list the restrictions for implementation-defined checks anyway.]} @end{Reason} @ImplDef{Implementation-defined check names.} @begin{Discussion} For Overflow_Check, the intention is that the implementation will suppress any Range_Checks that are implemented in the same manner as Overflow_Checks (unless they are free). @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation may support an additional parameter on @nt{pragma} Unsuppress similar to the one allowed for @nt{pragma} Suppress (see @RefSecNum{Specific Suppression of Checks}). The meaning of such a parameter is implementation-defined.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[Existence and meaning of second parameter of @nt{pragma} Unsuppress.],Old=[]}]} @end{ImplPerm} @begin{ImplAdvice} The implementation should minimize the code executed for checks that have been suppressed. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Code executed for checks that have been suppressed should be minimized.]}]} @begin{ImplNote} However, if a given check comes for free (for example, the hardware automatically performs the check in parallel with doing useful work) or nearly free (for example, the check is a tiny portion of an expensive run-time system call), the implementation should not bother to suppress the check. Similarly, if the implementation detects the failure at compile time and provides a warning message, there is no need to actually suppress the check. @end{ImplNote} @end{ImplAdvice} @begin{Notes} @Defn{optimization} @Defn{efficiency} There is no guarantee that a suppressed check is actually removed; hence a @nt{pragma} Suppress should be used only for efficiency reasons. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[It is possible to give both a @nt{pragma} Suppress and Unsuppress for the same check immediately within the same @nt{declarative_part}. In that case, the last @nt{pragma} given determines whether or not the check is suppressed. Similarly, it is possible to resuppress a check which has been unsuppressed by giving a @nt{pragma} Suppress in an inner declarative region.]} @end{Notes} @begin{Examples} @Leading@Keepnext@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @i{Examples of suppressing @Chg{Version=[2],New=[and unsuppressing ],Old=[]}checks:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00224-01]} @key[pragma] Suppress(@Chg{Version=[2],New=[Index_Check); @key[pragma] Unsuppress(Overflow_Check);],Old=[Range_Check); @key[pragma] Suppress(Index_Check, On => Table);]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} A @nt{pragma} Suppress is allowed as a configuration pragma. A @nt{pragma} Suppress without a @nt<name> is allowed in a @nt{package_specification}. Additional check names are added. We allow implementations to define their own checks. @end{Extend83} @begin{DiffWord83} We define the checks in a distributed manner. Therefore, the long list of what checks apply to what is merely a NOTE. We have removed the detailed rules about what is allowed in a @nt{pragma} Suppress, and allow implementations to invent their own. The RM83 rules weren't quite right, and such a change is necessary anyway in the presence of implementation-defined checks. We make it clear that the difference between a Range_Check and an Overflow_Check is fuzzy. This was true in Ada 83, given RM83-11.6, but it was not clear. We considered removing Overflow_Check from the language or making it obsolescent, just as we did for Numeric_Error. However, we kept it for upward compatibility, and because it may be useful on machines where range checking costs more than overflow checking, but overflow checking still costs something. Different compilers will suppress different checks when asked to suppress Overflow_Check @em the nonuniformity in this case is not harmful, and removing it would have a serious impact on optimizers. Under Access_Check, dereferences cover the cases of @nt{selected_component}, @nt{indexed_component}, @nt{slice}, and attribute that are listed in RM83, as well as the new @nt{explicit_dereference}, which was included in @nt{selected_component} in RM83. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95}Pragma Unsuppress is new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[Allocation_Check was added to support suppressing the new check on @nt{allocator}s (see @RefSecNum{Allocators}).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0036],ARef=[AI95-00176-01],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The description of Access_Check was corrected by the Corrigendum to include the discriminant case. This change was then replaced by the more general notion of checking conversions to subtypes that exclude null in Ada 2005.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The On parameter of pragma Suppress was moved to Annex J (see @RefSecNum{Specific Suppression of Checks}). This feature's effect is inherently nonportable, depending on the implementation's model of computation. Compiler surveys demonstrated this, showing that implementations vary widely in the interpretation of these parameters, even on the same target. While this is relatively harmless for Suppress (which is never required to do anything), it would be a significant problem for Unsuppress (we want the checks to be made for all implementations). By moving it, we avoid needing to define the meaning of Unsuppress with an On parameter.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00280-01]} @ChgAdded{Version=[2],Text=[The order of the Program_Error checks was corrected to be alphabetical.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0290-1]} @ChgAdded{Version=[3],Text=[The effect of a checking pragma no longer applies inside an inlined subprogram body. While this could change the behavior of a program that depends on a check being suppressed in an inlined body, such a program is erroneous and thus no behavior can be depended upon anyway. It's also likely to be very rare. We make this change so that inlining has no effect on the meaning of the subprogram body (since inlining is never requiring, this is necessary in order to be able to reason about the body), and so that assertion policies and suppress work the same way for inlining.]} @end{DiffWord2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Exceptions and Optimization} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[@Defn{language-defined check} @Defn2{Term=[check], Sec=(language-defined)} @Defn{run-time error} @Defn2{Term=[error], Sec=(run-time)} @Defn{optimization} @Defn{efficiency} This @Chg{Version=[3],New=[subclause],Old=[clause]} gives permission to the implementation to perform certain @lquotes@;optimizations@rquotes@; that do not necessarily preserve the canonical semantics.] @end{Intro} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{canonical semantics} The rest of this International Standard (outside this @Chg{Version=[3],New=[subclause],Old=[clause]}) defines the @i{canonical semantics} of the language. @Redundant[The canonical semantics of a given (legal) program determines a set of possible external effects that can result from the execution of the program with given inputs.] @begin{Ramification} Note that the canonical semantics is a set of possible behaviors, since some reordering, parallelism, and nondeterminism is allowed by the canonical semantics. @end{Ramification} @begin{Discussion} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The following parts of the canonical semantics are of particular interest to the reader of this @Chg{Version=[3],New=[subclause],Old=[clause]}: @begin{Itemize} Behavior in the presence of abnormal objects and objects with invalid representations (see @RefSecNum{Data Validity}). Various actions that are defined to occur in an arbitrary order. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Behavior in the presence of a misuse of Unchecked_Deallocation, Unchecked_Access, or imported or exported entity (see @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Representation Issues}). @end{Itemize} @end{Discussion} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[As explained in @RefSec{Conformity of an Implementation with the Standard}, the external effect of a program is defined in terms of its interactions with its external environment. Hence, the implementation can perform any internal actions whatsoever, in any order or in parallel, so long as the external effect of the execution of the program is one that is allowed by the canonical semantics, or by the rules of this @Chg{Version=[3],New=[subclause],Old=[clause]}.] @begin{Ramification} Note that an optimization can change the external effect of the program, so long as the changed external effect is an external effect that is allowed by the semantics. Note that the canonical semantics of an erroneous execution allows any external effect whatsoever. Hence, if the implementation can prove that program execution will be erroneous in certain circumstances, there need not be any constraints on the machine code executed in those circumstances. @end{Ramification} @end{RunTime} @begin{ImplPerm} @Leading@;The following additional permissions are granted to the implementation: @begin{Itemize} @Defn{extra permission to avoid raising exceptions} @Defn{undefined result} An implementation need not always raise an exception when a language-defined check fails. Instead, the operation that failed the check can simply yield an @i{undefined result}. The exception need be raised by the implementation only if, in the absence of raising it, the value of this undefined result would have some effect on the external interactions of the program. In determining this, the implementation shall not presume that an undefined result has a value that belongs to its subtype, nor even to the base range of its type, if scalar. @Redundant[Having removed the raise of the exception, the canonical semantics will in general allow the implementation to omit the code for the check, and some or all of the operation itself.] @begin{Ramification} Even without this permission, an implementation can always remove a check if it cannot possibly fail. @end{Ramification} @begin{Reason} We express the permission in terms of removing the raise, rather than the operation or the check, as it minimizes the disturbance to the canonical semantics (thereby simplifying reasoning). By allowing the implementation to omit the raise, it thereby does not need to "look" at what happens in the exception handler to decide whether the optimization is allowed. @end{Reason} @begin{Discussion} The implementation can also omit checks if they cannot possibly fail, or if they could only fail in erroneous executions. This follows from the canonical semantics. @end{Discussion} @begin{ImplNote} @Leading@;This permission is intended to allow normal "dead code removal" optimizations, even if some of the removed code might have failed some language-defined check. However, one may not eliminate the raise of an exception if subsequent code presumes in some way that the check succeeded. For example: @begin{Example} @key[if] X * Y > Integer'Last @key[then] Put_Line("X * Y overflowed"); @key[end] @key[if]; @key[exception] @key[when] @key[others] => Put_Line("X * Y overflowed"); @end{Example} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}If X*Y does overflow, you may not remove the raise of the exception if the code that does the comparison against Integer'Last presumes that it is comparing it with an in-range Integer value, and hence always yields False. @Leading@;As another example where a raise may not be eliminated: @begin{Example} @key[subtype] Str10 @key[is] String(1..10); @key[type] P10 @key[is] @key[access] Str10; X : P10 := @key[null]; @key[begin] @key[if] X.all'Last = 10 @key[then] Put_Line("Oops"); @key[end] @key[if]; @end{Example} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} In the above code, it would be wrong to eliminate the raise of Constraint_Error on the "X.all" (since X is null), if the code to evaluate 'Last always yields 10 by presuming that X.all belongs to the subtype Str10, without even "looking." @end{ImplNote} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{extra permission to reorder actions} If an exception is raised due to the failure of a language-defined check, then upon reaching the corresponding @nt<exception_handler> (or the termination of the task, if none), the external interactions that have occurred need reflect only that the exception was raised somewhere within the execution of the @nt<sequence_of_statements> with the handler (or the @nt<task_body>), possibly earlier (or later if the interactions are independent of the result of the checked operation) than that defined by the canonical semantics, but not within the execution of some abort-deferred operation or @i(independent) subprogram that does not dynamically enclose the execution of the construct whose check failed. @Defn{independent subprogram} An independent subprogram is one that is defined outside the library unit containing the construct whose check failed, and @Chg{Version=[3],New=[for which the],Old=[has no]} Inline @Chg{Version=[3],New=[aspect is False],Old=[@nt<pragma> applied to it]}. @Defn{normal state of an object} @PDefn{abnormal state of an object} @PDefn{disruption of an assignment} Any assignment that occurred outside of such abort-deferred operations or independent subprograms can be disrupted by the raising of the exception, causing the object or its parts to become abnormal, and certain subsequent uses of the object to be erroneous, as explained in @RefSecNum{Data Validity}. @begin{Reason} We allow such variables to become abnormal so that assignments (other than to atomic variables) can be disrupted due to @lquotes@;imprecise@rquotes@; exceptions or instruction scheduling, and so that assignments can be reordered so long as the correct results are produced in the end if no language-defined checks fail. @end{Reason} @begin{Ramification} If a check fails, no result dependent on the check may be incorporated in an external interaction. In other words, there is no permission to output meaningless results due to postponing a check. @end{Ramification} @end{Itemize} @begin{Discussion} We believe it is important to state the extra permission to reorder actions in terms of what the programmer can expect at run time, rather than in terms of what the implementation can assume, or what transformations the implementation can perform. Otherwise, how can the programmer write reliable programs? @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} has two conflicting goals: to allow as much optimization as possible, and to make program execution as predictable as possible (to ease the writing of reliable programs). The rules given above represent a compromise. Consider the two extremes: @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The extreme conservative rule would be to delete this @Chg{Version=[3],New=[subclause],Old=[clause]} entirely. The semantics of Ada would be the canonical semantics. This achieves the best predictability. It sounds like a disaster from the efficiency point of view, but in practice, implementations would provide modes in which less predictability but more efficiency would be achieved. Such a mode could even be the out-of-the-box mode. In practice, implementers would provide a compromise based on their customer's needs. Therefore, we view this as one viable alternative. The extreme liberal rule would be @lquotes@;the language does not specify the execution of a program once a language-defined check has failed; such execution can be unpredictable.@rquotes@; This achieves the best efficiency. It sounds like a disaster from the predictability point of view, but in practice it might not be so bad. A user would have to assume that exception handlers for exceptions raised by language-defined checks are not portable. They would have to isolate such code (like all nonportable code), and would have to find out, for each implementation of interest, what behaviors can be expected. In practice, implementations would tend to avoid going so far as to punish their customers too much in terms of predictability. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The most important thing about this @Chg{Version=[3],New=[subclause],Old=[clause]} is that users understand what they can expect at run time, and implementers understand what optimizations are allowed. Any solution that makes this @Chg{Version=[3],New=[subclause],Old=[clause]} contain rules that can interpreted in more than one way is unacceptable. We have chosen a compromise between the extreme conservative and extreme liberal rules. The current rule essentially allows arbitrary optimizations within a library unit and inlined subprograms reachable from it, but disallow semantics-disrupting optimizations across library units in the absence of inlined subprograms. This allows a library unit to be debugged, and then reused with some confidence that the abstraction it manages cannot be broken by bugs outside the library unit. @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The permissions granted by this @Chg{Version=[3],New=[subclause],Old=[clause]} can have an effect on the semantics of a program only if the program fails a language-defined check. @end{Notes} @begin{DiffWord83} @Leading@;RM83-11.6 was unclear. It has been completely rewritten here; we hope this version is clearer. Here's what happened to each paragraph of RM83-11.6: @begin{Itemize} Paragraphs 1 and 2 contain no semantics; they are merely pointing out that anything goes if the canonical semantics is preserved. We have similar introductory paragraphs, but we have tried to clarify that these are not granting any @lquotes@;extra@rquotes@; permission beyond what the rest of the document allows. Paragraphs 3 and 4 are reflected in the @lquotes@;extra permission to reorder actions@rquotes@;. Note that this permission now allows the reordering of assignments in many cases. Paragraph 5 is moved to @RefSec{Operators and Expression Evaluation}, where operator association is discussed. Hence, this is no longer an @lquotes@;extra permission@rquotes@; but is part of the canonical semantics. Paragraph 6 now follows from the general permission to store out-of-range values for unconstrained subtypes. Note that the parameters and results of all the predefined operators of a type are of the unconstrained subtype of the type. Paragraph 7 is reflected in the @lquotes@;extra permission to avoid raising exceptions@rquotes@;. @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} We moved @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSec{Suppressing Checks} from after 11.6 to before 11.6, in order to preserve the famous number @lquotes@;11.6@rquotes@; (given the changes to earlier @Chg{Version=[3],New=[subclauses],Old=[clauses]} in @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Exceptions}). @end{DiffWord83} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/12.mss���������������������������������������������������������������0000755�0001752�0001001�00000504614�12066652506�016405� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(12, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @LabeledSection{Generic Units} @Comment{$Source: e:\\cvsroot/ARM/Source/12.mss,v $} @Comment{$Revision: 1.93 $} @begin{Intro} @Defn{generic unit} A @i{generic unit} is a program unit that is either a generic subprogram or a generic package. @Defn{template} A generic unit is a @i{template}@Redundant[, which can be parameterized, and from which corresponding (nongeneric) subprograms or packages can be obtained]. The resulting program units are said to be @i{instances} of the original generic unit. @IndexSee{Term=[template],See=(generic unit)} @IndexSee{Term=[macro],See=(generic unit)} @IndexSee{Term=[parameter],See=[generic formal parameter]} @ToGlossary{Term=<Generic unit>, Text=<A generic unit is a template for a (nongeneric) program unit; the template can be parameterized by objects, types, subprograms, and packages. An instance of a generic unit is created by a @nt(generic_instantiation). The rules of the language are enforced when a generic unit is compiled, using a generic contract model; additional checks are performed upon instantiation to verify the contract is met. That is, the declaration of a generic unit represents a contract between the body of the generic and instances of the generic. Generic units can be used to perform the role that macros sometimes play in other languages.>}@ChgNote{Correction for AI-00024, no mechism to correct glossary entries.} @redundant[A generic unit is declared by a @nt{generic_declaration}. This form of declaration has a @nt{generic_@!formal_@!part} declaring any generic formal parameters. An instance of a generic unit is obtained as the result of a @nt{generic_instantiation} with appropriate generic actual parameters for the generic formal parameters. An instance of a generic subprogram is a subprogram. An instance of a generic package is a package. Generic units are templates. As templates they do not have the properties that are specific to their nongeneric counterparts. For example, a generic subprogram can be instantiated but it cannot be called. In contrast, an instance of a generic subprogram is a (nongeneric) subprogram; hence, this instance can be called but it cannot be used to produce further instances.] @end{Intro} @LabeledClause{Generic Declarations} @begin{Intro} @redundant[A @nt{generic_declaration} declares a generic unit, which is either a generic subprogram or a generic package. A @nt{generic_declaration} includes a @nt{generic_formal_part} declaring any generic formal parameters. A generic formal parameter can be an object; alternatively (unlike a parameter of a subprogram), it can be a type, a subprogram, or a package.] @end{Intro} @begin{Syntax} @Syn{lhs=<generic_declaration>,rhs="@Syn2{generic_subprogram_declaration} | @Syn2{generic_package_declaration}"} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<generic_subprogram_declaration>,rhs=" @Syn2{generic_formal_part} @Syn2{subprogram_specification}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<generic_package_declaration>,rhs=" @Syn2{generic_formal_part} @Syn2{package_specification};"} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[No syntax change is needed here to allow an @nt{aspect_specification}; a generic package can have an @nt{aspect_specification} because a @nt{package_specification} allows an @nt{aspect_specification}.]} @end{Ramification} @Syn{lhs=<generic_formal_part>,rhs="@key{generic} {@Syn2{generic_formal_parameter_declaration} | @Syn2{use_clause}}"} @Syn{lhs=<generic_formal_parameter_declaration>,rhs=" @Syn2{formal_object_declaration} | @Syn2{formal_type_declaration} | @Syn2{formal_subprogram_declaration} | @Syn2{formal_package_declaration}"} @begin{SyntaxText} The only form of @nt{subtype_indication} allowed within a @nt{generic_formal_part} is a @nt{subtype_mark} @Redundant[(that is, the @nt{subtype_indication} shall not include an explicit @nt{constraint})]. The defining name of a generic subprogram shall be an @nt{identifier} @Redundant[(not an @nt{operator_symbol})]. @begin{Reason} The reason for forbidding @nt{constraint}s in @nt{subtype_indication}s is that it simplifies the elaboration of @nt{generic_declaration}s (since there is nothing to evaluate), and that it simplifies the matching rules, and makes them more checkable at compile time. @end{Reason} @end{SyntaxText} @end{Syntax} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Defn{generic package} @Defn{generic subprogram} @Defn{generic procedure} @Defn{generic function} A @nt{generic_declaration} declares a generic unit @em a generic package, generic procedure@Chg{Version=[2],New=[,],Old=[]} or generic function, as appropriate. @Defn{generic formal} An entity is a @i{generic formal} entity if it is declared by a @nt<generic_formal_parameter_declaration>. @lquotes@;Generic formal,@rquotes@; or simply @lquotes@;formal,@rquotes@; is used as a prefix in referring to objects, subtypes (and types), functions, procedures and packages, that are generic formal entities, as well as to their respective declarations. @Redundant[Examples: @lquotes@;generic formal procedure@rquotes@; or a @lquotes@;formal integer type declaration.@rquotes@;] @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic_declaration)} The elaboration of a @nt{generic_declaration} has no effect. @end{RunTime} @begin{Notes} Outside a generic unit a @nt{name} that denotes the @nt{generic_declaration} denotes the generic unit. In contrast, within the declarative region of the generic unit, a @nt{name} that denotes the @nt{generic_declaration} denotes the current instance. @begin{TheProof} This is stated officially as part of the @lquotes@;current instance@rquotes@; rule in @RefSec{The Context of Overload Resolution}. See also @RefSec{Generic Instantiation}. @end{TheProof} Within a generic @nt{subprogram_body}, the name of this program unit acts as the name of a subprogram. Hence this name can be overloaded, and it can appear in a recursive call of the current instance. For the same reason, this name cannot appear after the reserved word @key{new} in a (recursive) @nt{generic_instantiation}. A @nt{default_expression} or @nt{default_name} appearing in a @nt{generic_formal_part} is not evaluated during elaboration of the @nt{generic_formal_part}; instead, it is evaluated when used. (The usual visibility rules apply to any @nt{name} used in a default: the denoted declaration therefore has to be visible at the place of the expression.) @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic formal parts:} @begin{Example} @key[generic] --@RI{ parameterless } @key[generic] Size : Natural; --@RI{ formal object } @key[generic] Length : Integer := 200; --@RI{ formal object with a default expression} Area : Integer := Length*Length; --@RI{ formal object with a default expression} @key[generic] @key[type] Item @key[is] @key[private]; --@RI{ formal type} @key[type] Index @key[is] (<>); --@RI{ formal type} @key[type] Row @key[is] @key[array](Index @key[range] <>) @key[of] Item; --@RI{ formal type} @key[with] @key[function] "<"(X, Y : Item) @key[return] Boolean; --@RI{ formal subprogram } @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of generic declarations declaring generic subprograms Exchange and Squaring:} @end{WideAbove} @begin{Example} @key[generic] @key[type] Elem @key[is] @key[private]; @key[procedure] Exchange(U, V : @key[in] @key[out] Elem); @key[generic] @key[type] Item @key[is] @key[private]; @key[with] @key[function] "*"(U, V : Item) @key[return] Item @key[is] <>; @key[function] Squaring(X : Item) @key[return] Item; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a generic declaration declaring a generic package:} @end{WideAbove} @begin{Example} @key[generic] @key[type] Item @key[is] @key[private]; @key[type] Vector @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; @key[with] @key[function] Sum(X, Y : Item) @key[return] Item; @key[package] On_Vectors @key[is] @key[function] Sum (A, B : Vector) @key[return] Vector; @key[function] Sigma(A : Vector) @key[return] Item; Length_Error : @key[exception]; @key[end] On_Vectors; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{generic_formal_parameter_declaration} is modified to allow the reserved words @key{tagged} and @key{abstract}, to allow formal derived types, and to allow formal packages. @nt{Use_clause}s are allowed in @nt{generic_formal_part}s. This is necessary in order to allow a @nt{use_clause} within a formal part to provide direct visibility of declarations within a generic formal package. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} The syntax for @nt{generic_formal_parameter_declaration} and @nt{formal_type_definition} is split up into more named categories. The rules for these categories are moved to the appropriate @Chg{Version=[3],New=[],Old=[clauses and ]}subclauses. The names of the categories are changed to be more intuitive and uniform. For example, we changed @ntf{generic_parameter_declaration} to @nt{generic_formal_parameter_declaration}, because the thing it declares is a generic formal, not a generic. In the others, we abbreviate @lquotes@;generic_formal@rquotes@; to just @lquotes@;formal@rquotes@;. We can't do that for @nt{generic_formal_parameter_declaration}, because of confusion with normal formal parameters of subprograms. @end{DiffWord83} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{generic_subprogram_declaration} (as well as a @nt{generic_package_declaration}). This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @RmNewPage@Comment{Insert page break so printed RM's look better.} @LabeledClause{Generic Bodies} @begin{Intro} @Defn{generic body} The body of a generic unit (a @i{generic body}) @Redundant[is a template for the instance bodies. The syntax of a generic body is identical to that of a nongeneric body]. @begin{Ramification} We also use terms like @lquotes@;generic function body@rquotes@; and @lquotes@;nongeneric package body.@rquotes@; @end{Ramification} @end{Intro} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic body)} The elaboration of a generic body has no other effect than to establish that the generic unit can from then on be instantiated without failing the Elaboration_Check. If the generic body is a child of a generic package, then its elaboration establishes that each corresponding declaration nested in an instance of the parent (see @RefSecNum{Compilation Units - Library Units}) can from then on be instantiated without failing the Elaboration_Check. @end{RunTime} @begin{Notes} The syntax of generic subprograms implies that a generic subprogram body is always the completion of a declaration. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a generic procedure body:} @begin{Example} @key[procedure] Exchange(U, V : @key[in] @key[out] Elem) @key[is] --@RI{ see @RefSecNum{Generic Declarations}} T : Elem; --@RI{ the generic formal type} @key[begin] T := U; U := V; V := T; @key[end] Exchange; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a generic function body:} @end{WideAbove} @begin{Example} @key[function] Squaring(X : Item) @key[return] Item @key[is] --@RI{ see @RefSecNum{Generic Declarations}} @key[begin] @key[return] X*X; --@RI{ the formal operator "*"} @key[end] Squaring; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a generic package body:} @end{WideAbove} @begin{Example} @key[package] @key[body] On_Vectors @key[is] --@RI{ see @RefSecNum{Generic Declarations}} @key[function] Sum(A, B : Vector) @key[return] Vector @key[is] Result : Vector(A'Range); --@RI{ the formal type Vector} Bias : @key[constant] Integer := B'First - A'First; @key[begin] @key[if] A'Length /= B'Length @key[then] @key[raise] Length_Error; @key[end] @key[if]; @key[for] N @key[in] A'Range @key[loop] Result(N) := Sum(A(N), B(N + Bias)); --@RI{ the formal function Sum} @key[end] @key[loop]; @key[return] Result; @key[end] Sum; @key[function] Sigma(A : Vector) @key[return] Item @key[is] Total : Item := A(A'First); --@RI{ the formal type Item} @key[begin] @key[for] N @key[in] A'First + 1 .. A'Last @key[loop] Total := Sum(Total, A(N)); --@RI{ the formal function Sum} @key[end] @key[loop]; @key[return] Total; @key[end] Sigma; @key[end] On_Vectors; @end{Example} @end{Examples} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledClause{Generic Instantiation} @begin{Intro} @redundant[@Defn2{Term=[instance], Sec=(of a generic unit)} An instance of a generic unit is declared by a @nt{generic_instantiation}.] @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{generic contract model} @Defn{contract model of generics} The legality of an instance should be determinable without looking at the generic body. Likewise, the legality of a generic body should be determinable without looking at any instances. Thus, the @nt{generic_declaration} forms a contract between the body and the instances; if each obeys the rules with respect to the @nt{generic_declaration}, then no legality problems will arise. This is really a special case of the @lquotes@;legality determinable via semantic dependences@rquotes@; @MetaRulesName (see @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Program Structure and Compilation Issues}), given that a @nt{generic_instantiation} does not depend semantically upon the generic body, nor vice-versa. Run-time issues are another story. For example, whether parameter passing is by copy or by reference is determined in part by the properties of the generic actuals, and thus cannot be determined at compile time of the generic body. Similarly, the contract model does not apply to @LinkTimeTitle. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00218-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<generic_instantiation>,rhs=" @key{package} @Syn2{defining_program_unit_name} @key{is} @key{new} @SynI{generic_package_}@Syn2{name} [@Syn2{generic_actual_part}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @Chg{Version=[2],New=<[@Syn2{overriding_indicator}] >,Old=<>}@key{procedure} @Syn2{defining_program_unit_name} @key{is} @key{new} @SynI{generic_procedure_}@Syn2{name} [@Syn2{generic_actual_part}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]}; | @Chg{Version=[2],New=<[@Syn2{overriding_indicator}] >,Old=<>}@key{function} @Syn2{defining_designator} @key{is} @key{new} @SynI{generic_function_}@Syn2{name} [@Syn2{generic_actual_part}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @Syn{lhs=<generic_actual_part>,rhs=" (@Syn2{generic_association} {, @Syn2{generic_association}})"} @Syn{lhs=<generic_association>,rhs=" [@SynI{generic_formal_parameter_}@Syn2{selector_name} =>] @Syn2{explicit_generic_actual_parameter}"} @Syn{lhs=<explicit_generic_actual_parameter>,rhs="@Syn2{expression} | @SynI{variable_}@Syn2{name} | @SynI{subprogram_}@Syn2{name} | @SynI{entry_}@Syn2{name} | @Syn2{subtype_mark} | @SynI{package_instance_}@Syn2{name}"} @begin{SyntaxText} @Defn{named association} @Defn{positional association} A @nt{generic_association} is @i{named} or @i{positional} according to whether or not the @i{generic_@!formal_@!parameter_}@!@nt<selector_@!name> is specified. Any positional associations shall precede any named associations. @end{SyntaxText} @end{Syntax} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @Defn{generic actual parameter} @Defn{generic actual} @Defn{actual} The @i{generic actual parameter} is either the @nt{explicit_generic_actual_parameter} given in a @Chg{Version=[3],New=[@nt{generic_@!association}],Old=[@ntf{generic_@!parameter_@!association}]} for each formal, or the corresponding @nt{default_@!expression} or @nt{default_@!name} if no @Chg{Version=[3],New=[@nt{generic_@!association}],Old=[@ntf{generic_@!parameter_@!association}]} is given for the formal. When the meaning is clear from context, the term @lquotes@;generic actual,@rquotes@; or simply @lquotes@;actual,@rquotes@; is used as a synonym for @lquotes@;generic actual parameter@rquotes@; and also for the view denoted by one, or the value of one. @end{Intro} @begin{Legality} In a @nt<generic_instantiation> for a particular kind of program unit @Redundant[(package, procedure, or function)], the @nt<name> shall denote a generic unit of the corresponding kind @Redundant[(generic package, generic procedure, or generic function, respectively)]. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0118-1]} The @SynI{generic_formal_parameter_}@nt{selector_name} of a@Chg{Version=[3],New=[ named],Old=[]} @nt{generic_association} shall denote a @nt{generic_formal_parameter_declaration} of the generic unit being instantiated. If two or more formal subprograms have the same defining name, then named associations are not allowed for the corresponding actuals. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0118-1]} @ChgAdded{Version=[3],Text=[The @nt{generic_formal_parameter_declaration} for a positional @nt{generic_association} is the parameter with the corresponding position in the @nt{generic_formal_part} of the generic unit being instantiated.]} A @nt{generic_instantiation} shall contain at most one @nt<generic_association> for each formal. Each formal without an association shall have a @nt{default_expression} or @nt{subprogram_default}. In a generic unit @LegalityName@;s are enforced at compile time of the @nt{generic_declaration} and generic body, given the properties of the formals. In the visible part and formal part of an instance, @LegalityName@;s are enforced at compile time of the @nt{generic_instantiation}, given the properties of the actuals. In other parts of an instance, @LegalityName@;s are not enforced; this rule does not apply when a given rule explicitly specifies otherwise. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Since rules are checked using the properties of the formals, and since these properties do not always carry over to the actuals, we need to check the rules again in the visible part of the instance. For example, only if a tagged type is limited may an extension of it have limited components in the @Chg{Version=[2],New=[@nt{record_extension_part}],Old=[@ntf<extension_part>]}. A formal tagged limited type is limited, but the actual might be nonlimited. Hence any rule that requires a tagged type to be limited runs into this problem. Such rules are rare; in most cases, the rules for matching of formals and actuals guarantee that if the rule is obeyed in the generic unit, then it has to be obeyed in the instance. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[Ada 2012 addendum: Such @LegalityTitle are not as rare as the authors of Ada 95 hoped; there are more than 30 of them known at this point. They are indexed under "generic contract issue" and are associated with the boilerplate "In addition to the places where @LegalityTitle normally apply...". Indeed, there is only one known rule where rechecking in the specification is needed and where rechecking in the private part is @i<not> wanted (it is in @RefSecNum{Derived Types and Classes}, but even it needs rechecking when tagged types are involved).]} @end{Reason} @begin{Ramification} @leading@;The @lquotes@;properties@rquotes@; of the formals are determined without knowing anything about the actuals: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0095],ARef=[AI95-00034-01]} A formal derived subtype is constrained if and only if the ancestor subtype is constrained. A formal array type is constrained if and only if the declarations @Chg{New=[say],Old=[says]} so.@Chg{New=[ A formal private type is constrained if it does not have a discriminant part.],Old=[]} Other formal subtypes are unconstrained, even though they might be constrained in an instance. A formal subtype can be indefinite, even though the copy might be definite in an instance. A formal object of mode @key[in] is not a static constant; in an instance, the copy is static if the actual is. A formal subtype is not static, even though the actual might be. Formal types are specific, even though the actual can be class-wide. The subtype of a formal object of mode @key[in out] is not static. (This covers the case of AI83-00878.) The subtype of a formal parameter of a formal subprogram does not provide an applicable index constraint. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The profile of a formal subprogram is not @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]} with any other profile. @Defn{subtype conformance} A generic formal function is not static. @end{Itemize} @end{Ramification} @begin{Ramification} @leading@;The exceptions to the above rule about when legality rules are enforced fall into these categories: @begin{Itemize} @leading@;Some rules are checked in the generic declaration, and then again in both the visible and private parts of the instance: @begin{InnerItemize} The parent type of a record extension has to be specific (see @RefSecNum{Type Extensions}). This rule is not checked in the instance body. The parent type of a private extension has to be specific (see @RefSecNum{Private Types and Private Extensions}). This rule is not checked in the instance body. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00402-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0093-1]} A type with an access discriminant @Chg{Version=[2],New=[with a @nt{default_expression} ],Old=[]}has to be @Chg{Version=[3],New=[immutably limited. In the generic body, the definition of immutably limited is adjusted in an assume-the-worst manner (thus the rule is checked that way)],Old=[a descendant of @Chg{Version=[2],New=[an explicitly limited record type],Old=[a type declared with @key[limited]]}, or be a task or protected type. This rule is irrelevant in the instance body]}. In the declaration of a record extension, if the parent type is nonlimited, then each of the components of the @nt{record_extension_part} have to be nonlimited (see @RefSecNum{Type Extensions}). In the generic body, this rule is checked in an assume-the-worst manner. A preelaborated library unit has to be preelaborable (see @RefSecNum{Elaboration Control}). In the generic body, this rule is checked in an assume-the-worst manner. @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00402-01]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The corrections made by the Corrigendum added a number of such rules, and the Amendment added many more. There doesn't seem to be much value in repeating all of these rules here (as of this writing, there are roughly 33 such rules). As noted below, all such rules are indexed in the AARM.]} @PDefn2{Term=[accessibility rule],Sec=(checking in generic units)} For the accessibility rules, the formals have nothing to say about the property in question. Like the above rules, these rules are checked in the generic declaration, and then again in both the visible and private parts of the instance. In the generic body, we have explicit rules that essentially assume the worst (in the cases of type extensions and access-to-subprogram types), and we have run-time checks (in the case of access-to-object types). See @RefSecNum{Type Extensions}, @RefSecNum{Operations of Access Types}, and @RefSecNum{Type Conversions}. @NoPrefix@;We considered run-time checks for access-to-subprogram types as well. However, this would present difficulties for implementations that share generic bodies. The rules requiring @lquotes@;reasonable@rquotes@; values for static expressions are ignored when the expected type for the expression is a descendant of a generic formal type other than a generic formal derived type, and do not apply in an instance. The rule forbidding two explicit homographs in the same declarative region does not apply in an instance of a generic unit, except that it @i{does} apply in the declaration of a record extension that appears in the visible part of an instance. @leading@;Some rules do not apply at all in an instance, not even in the visible part: @begin{InnerItemize} @nt{Body_stub}s are not normally allowed to be multiply nested, but they can be in instances. @end{InnerItemize} @end{Itemize} @RootDefn{generic contract issue} Each rule that is an exception is marked with @lquotes@;generic contract issue;@rquotes@; look that up in the index to find them all. @end{Ramification} @begin{Ramification} The @LegalityName@;s are the ones labeled @LegalityTitle. We are talking about all @LegalityName@;s in the entire language here. Note that, with some exceptions, the legality of a generic unit is checked even if there are no instantiations of the generic unit. @end{Ramification} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The @LegalityName@;s are described here, and the overloading rules were described earlier in this @Chg{Version=[3],New=[subclause],Old=[clause]}. Presumably, every @StaticSemName is sucked in by one of those. Thus, we have covered all the compile-time rules of the language. There is no need to say anything special about the @LinkTimeName@;s or the @RunTimeName@;s. @end{Ramification} @begin{Discussion} Here is an example illustrating how this rule is checked: @lquotes@;In the declaration of a record extension, if the parent type is nonlimited, then each of the components of the @nt{record_extension_part} shall be nonlimited.@rquotes@; @begin{Example} @key[generic] @key[type] Parent @key[is] @key[tagged] @key[private]; @key[type] Comp @key[is] @key[limited] @key[private]; @key[package] G1 @key[is] @key[type] Extension @key[is] @key[new] Parent @key[with] @key[record] C : Comp; --@RI{ Illegal!} @key[end] @key[record]; @key[end] G1; @end{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} The parent type is nonlimited, and the component type is limited, which is illegal. It doesn't matter that @Chg{New=[],Old=[an ]}one could imagine writing an instantiation with the actual for Comp being nonlimited @em we never get to the instance, because the generic itself is illegal. @leading@;On the other hand: @begin{Example} @key[generic] @key[type] Parent @key[is] @key[tagged] @key[limited] @key[private]; --@RI{ Parent is limited.} @key[type] Comp @key[is] @key[limited] @key[private]; @key[package] G2 @key[is] @key[type] Extension @key[is] @key[new] Parent @key[with] @key[record] C : Comp; --@RI{ OK.} @key[end] @key[record]; @key[end] G2; @key[type] Limited_Tagged @key[is] @key[tagged] @key[limited] @key[null] @key[record]; @key[type] Non_Limited_Tagged @key[is] @key[tagged] @key[null] @key[record]; @key[type] Limited_Untagged @key[is] @key[limited] @key[null] @key[record]; @key[type] Non_Limited_Untagged @key[is] @key[null] @key[record]; @key[package] Good_1 @key[is] @key[new] G2(Parent => Limited_Tagged, Comp => Limited_Untagged); @key[package] Good_2 @key[is] @key[new] G2(Parent => Non_Limited_Tagged, Comp => Non_Limited_Untagged); @key[package] Bad @key[is] @key[new] G2(Parent => Non_Limited_Tagged, Comp => Limited_Untagged); --@RI{ Illegal!} @end{Example} The first instantiation is legal, because in the instance the parent is limited, so the rule is not violated. Likewise, in the second instantiation, the rule is not violated in the instance. However, in the Bad instance, the parent type is nonlimited, and the component type is limited, so this instantiation is illegal. @end{Discussion} @end{Legality} @begin{StaticSem} A @nt{generic_instantiation} declares an instance; it is equivalent to the instance declaration (a @nt{package_@!declaration} or @nt{subprogram_@!declaration}) immediately followed by the instance body, both at the place of the instantiation. @begin{Ramification} The declaration and the body of the instance are not @lquotes@;implicit@rquotes@; in the technical sense, even though you can't see them in the program text. Nor are declarations within an instance @lquotes@;implicit@rquotes@; (unless they are implicit by other rules). This is necessary because implicit declarations have special semantics that should not be attached to instances. For a generic subprogram, the profile of a @nt{generic_instantiation} is that of the instance declaration, by the stated equivalence. @end{Ramification} @begin{Ramification} @PDefn2{Term=[visible part], Sec=(of an instance)} @PDefn2{Term=[private part], Sec=(of a package)} The visible and private parts of a package instance are defined in @RefSec{Package Specifications and Declarations} and @RefSec{Formal Packages}. The visible and private parts of a subprogram instance are defined in @RefSec{Scope of Declarations}. @end{Ramification} The instance is a copy of the text of the template. @Redundant[Each use of a formal parameter becomes (in the copy) a use of the actual, as explained below.] @Defn{package instance} @Defn{subprogram instance} @Defn{procedure instance} @Defn{function instance} @Defn2{Term=[instance], Sec=(of a generic package)} @Defn2{Term=[instance], Sec=(of a generic subprogram)} @Defn2{Term=[instance], Sec=(of a generic procedure)} @Defn2{Term=[instance], Sec=(of a generic function)} An instance of a generic package is a package, that of a generic procedure is a procedure, and that of a generic function is a function. @begin{Ramification} An instance is a package or subprogram (because we say so), even though it contains a copy of the @nt{generic_formal_part}, and therefore doesn't look like one. This is strange, but it's OK, since the syntax rules are overloading rules, and therefore do not apply in an instance. @end{Ramification} @begin{Discussion} We use a macro-expansion model, with some explicitly-stated exceptions (see below). The main exception is that the interpretation of each construct in a generic unit (especially including the denotation of each name) is determined when the declaration and body of the generic unit (as opposed to the instance) are compiled, and in each instance this interpretation is (a copy of) the template interpretation. In other words, if a construct is interpreted as a @nt{name} denoting a declaration D, then in an instance, the copy of the construct will still be a name, and will still denote D (or a copy of D). From an implementation point of view, overload resolution is performed on the template, and not on each copy. We describe the substitution of generic actual parameters by saying (in most cases) that the copy of each generic formal parameter declares a view of the actual. Suppose a name in a generic unit denotes a @nt{generic_formal_parameter_declaration}. The copy of that name in an instance will denote the copy of that @nt{generic_formal_parameter_declaration} in the instance. Since the @nt{generic_formal_parameter_declaration} in the instance declares a view of the actual, the name will denote a view of the actual. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Other properties of the copy (for example, staticness, @Chg{Version=[2],New=[categories],Old=[classes]} to which types belong) are recalculated for each instance; this is implied by the fact that it's a copy. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} Although the @nt{generic_formal_part} is included in an instance, the declarations in the @nt{generic_formal_part} are only visible outside the instance in the case of a generic formal package whose @nt{formal_package_actual_part} @Chg{Version=[2],New=[includes one or more <> indicators],Old=[is (<>)]} @em see @RefSecNum{Formal Packages}. @end{Discussion} The interpretation of each construct within a generic declaration or body is determined using the overloading rules when that generic declaration or body is compiled. In an instance, the interpretation of each (copied) construct is the same, except in the case of a name that denotes the @nt{generic_declaration} or some declaration within the generic unit; the corresponding name in the instance then denotes the corresponding copy of the denoted declaration. The overloading rules do not apply in the instance. @begin{Ramification} See @RefSec{The Context of Overload Resolution} for definitions of @lquotes@;interpretation@rquotes@; and @lquotes@;overloading rule.@rquotes@; Even the @nt{generic_formal_parameter_declaration}s have corresponding declarations in the instance, which declare views of the actuals. Although the declarations in the instance are copies of those in the generic unit, they often have quite different properties, as explained below. For example a constant declaration in the generic unit might declare a nonstatic constant, whereas the copy of that declaration might declare a static constant. This can happen when the staticness depends on some generic formal. This rule is partly a ramification of the @lquotes@;current instance@rquotes@; rule in @RefSec{The Context of Overload Resolution}. Note that that rule doesn't cover the @nt{generic_formal_part}. Although the overloading rules are not observed in the instance, they are, of course, observed in the @ntf{_instantiation} in order to determine the interpretation of the constituents of the @ntf{_instantiation}. Since children are considered to occur within their parent's declarative region, the above rule applies to a name that denotes a child of a generic unit, or a declaration inside such a child. Since the @SyntaxName@;s are overloading rules, it is possible (legal) to violate them in an instance. For example, it is possible for an instance body to occur in a @nt{package_specification}, even though the @SyntaxName@;s forbid bodies in @nt{package_specification}s. @end{Ramification} In an instance, a @nt{generic_formal_parameter_declaration} declares a view whose properties are identical to those of the actual, except as specified in @RefSec{Formal Objects} and @RefSec{Formal Subprograms}. Similarly, for a declaration within a @nt{generic_formal_parameter_declaration}, the corresponding declaration in an instance declares a view whose properties are identical to the corresponding declaration within the declaration of the actual. @begin{Ramification} In an instance, there are no @lquotes@;properties@rquotes@; of types and subtypes that come from the formal. The primitive operations of the type come from the formal, but these are declarations in their own right, and are therefore handled separately. Note that certain properties that come from the actuals are irrelevant in the instance. For example, if an actual type is of a class deeper in the derived-type hierarchy than the formal, it is impossible to call the additional operations of the deeper class in the instance, because any such call would have to be a copy of some corresponding call in the generic unit, which would have been illegal. However, it is sometimes possible to reach into the specification of the instance from outside, and notice such properties. For example, one could pass an object declared in the instance specification to one of the additional operations of the deeper type. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A @nt{formal_type_declaration} can contain @nt{discriminant_specification}s, a @nt{formal_subprogram_declaration} can contain @Chg{Version=[2],New=[@nt{parameter_specification}s],Old=[@ntf{formal_parameter_specification}s]}, and a @nt{formal_package_declaration} can contain many kinds of declarations. These are all inside the generic unit, and have corresponding declarations in the instance. This rule implies, for example, that if a subtype in a generic unit is a subtype of a generic formal subtype, then the corresponding subtype in the instance is a subtype of the corresponding actual subtype. For a @nt{generic_instantiation}, if a generic actual is a static @Redundant[(scalar or string)] subtype, then each use of the corresponding formal parameter within the specification of the instance is considered to be static. (See AI83-00409.) Similarly, if a generic actual is a static expression and the corresponding formal parameter has a static @Redundant[(scalar or string)] subtype, then each use of the formal parameter in the specification of the instance is considered to be static. (See AI83-00505.) @leading@;If a primitive subprogram of a type derived from a generic formal derived tagged type is not overriding (that is, it is a new subprogram), it is possible for the copy of that subprogram in an instance to override a subprogram inherited from the actual. For example: @begin{Example} @key[type] T1 @key[is] @key[tagged] @key[record] ... @key[end] @key[record]; @key[generic] @key[type] Formal @key[is] @key[new] T1; @key[package] G @key[is] @key[type] Derived_From_Formal @key[is] @key[new] Formal @key[with] @key[record] ... @key[end] @key[record]; @key[procedure] Foo(X : @key[in] Derived_From_Formal); --@RI{ Does not override anything.} @key[end] G; @key[type] T2 @key[is] @key[new] T1 @key[with] @key[record] ... @key[end] @key[record]; @key[procedure] Foo(X : @key[in] T2); @key[package] Inst @key[is] @key[new] G(Formal => T2); @end{Example} In the instance Inst, the declaration of Foo for Derived_From_Formal overrides the Foo inherited from T2. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} For formal types, an implementation that shares the code among multiple instances of the same generic unit needs to beware that things like parameter passing mechanisms (by-copy vs. by-reference) and @Chg{New=[@nt{aspect_clause}s],Old=[@nt{representation_clause}s]} are determined by the actual. @end{ImplNote} @redundant[Implicit declarations are also copied, and a name that denotes an implicit declaration in the generic denotes the corresponding copy in the instance. However, for a type declared within the visible part of the generic, a whole new set of primitive subprograms is implicitly declared for use outside the instance, and may differ from the copied set if the properties of the type in some way depend on the properties of some actual type specified in the instantiation. For example, if the type in the generic is derived from a formal private type, then in the instance the type will inherit subprograms from the corresponding actual type. @Defn{override} These new implicit declarations occur immediately after the type declaration in the instance, and override the copied ones. The copied ones can be called only from within the instance; the new ones can be called only from outside the instance, although for tagged types, the body of a new one can be executed by a call to an old one.] @begin{TheProof} This rule is stated officially in @RefSec{Visibility}. @end{TheProof} @begin{Ramification} The new ones follow from the class(es) of the formal types. For example, for a type T derived from a generic formal private type, if the actual is Integer, then the copy of T in the instance has a "+" primitive operator, which can be called from outside the instance (assuming T is declared in the visible part of the instance). AI83-00398. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Since an actual type is always in the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal, the new subprograms hide all of the copied ones, except for a declaration of "/=" that corresponds to an explicit declaration of "=". Such "/=" operators are special, because unlike other implicit declarations of primitive subprograms, they do not appear by virtue of the class, but because of an explicit declaration of "=". If the declaration of "=" is implicit (and therefore overridden in the instance), then a corresponding implicitly declared "/=" is also overridden. But if the declaration of "=" is explicit (and therefore not overridden in the instance), then a corresponding implicitly declared "/=" is not overridden either, even though it's implicit. Note that the copied ones can be called from inside the instance, even though they are hidden from all visibility, because the names are resolved in the generic unit @em visibility is irrelevant for calls in the instance. @end{Ramification} @Redundant[In the visible part of an instance, an explicit declaration overrides an implicit declaration if they are homographs, as described in @RefSecNum{Visibility}.] On the other hand, an explicit declaration in the private part of an instance overrides an implicit declaration in the instance, only if the corresponding explicit declaration in the generic overrides a corresponding implicit declaration in the generic. Corresponding rules apply to the other kinds of overriding described in @RefSecNum{Visibility}. @begin{Ramification} @leading@;For example: @begin{Example} @key[type] Ancestor @key[is] @key[tagged] @key[null] @key[record]; @key[generic] @key[type] Formal @key[is] @key[new] Ancestor @key[with] @key[private]; @key[package] G @key[is] @key[type] T @key[is] @key[new] Formal @key[with] @key[null] @key[record]; @key[procedure] P(X : @key[in] T); --@RI{ (1)} @key[private] @key[procedure] Q(X : @key[in] T); --@RI{ (2)} @key[end] G; @key[type] Actual @key[is] @key[new] Ancestor @key[with] @key[null] @key[record]; @key[procedure] P(X : @key[in] Actual); @key[procedure] Q(X : @key[in] Actual); @key[package] Instance @key[is] @key[new] G(Formal => Actual); @end{Example} In the instance, the copy of P at (1) overrides Actual's P, whereas the copy of Q at (2) does not override anything; in implementation terms, it occupies a separate slot in the type descriptor. @end{Ramification} @begin{Reason} The reason for this rule is so a programmer writing an @ntf{_instantiation} need not look at the private part of the generic in order to determine which subprograms will be overridden. @end{Reason} @end{StaticSem} @begin{LinkTime} Recursive generic instantiation is not allowed in the following sense: if a given generic unit includes an instantiation of a second generic unit, then the instance generated by this instantiation shall not include an instance of the first generic unit @Redundant[(whether this instance is generated directly, or indirectly by intermediate instantiations)]. @begin{Discussion} Note that this rule is not a violation of the generic contract model, because it is not a @LegalityName. Some implementations may be able to check this rule at compile time, but that requires access to all the bodies, so we allow implementations to check the rule at link time. @end{Discussion} @end{LinkTime} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(generic_instantiation)} For the elaboration of a @nt{generic_instantiation}, each @nt{generic_association} is first evaluated. If a default is used, an implicit @nt{generic_association} is assumed for this rule. These evaluations are done in an arbitrary order, except that the evaluation for a default actual takes place after the evaluation for another actual if the default includes a @nt{name} that denotes the other one.@PDefn2{Term=[arbitrary order],Sec=[allowed]} Finally, the instance declaration and body are elaborated. @begin{Ramification} Note that if the evaluation of a default depends on some side effect of some other evaluation, the order is still arbitrary. @end{Ramification} @PDefn2{Term=[evaluation], Sec=(generic_association)} For the evaluation of a @nt{generic_association} the generic actual parameter is evaluated. Additional actions are performed in the case of a formal object of mode @key{in} (see @RefSecNum{Formal Objects}). @begin{Honest} Actually, the actual is evaluated only if evaluation is defined for that kind of construct @em we don't actually @lquotes@;evaluate@rquotes@; @nt{subtype_mark}s. @end{Honest} @end{RunTime} @begin{Notes} If a formal type is not tagged, then the type is treated as an untagged type within the generic body. Deriving from such a type in a generic body is permitted; the new type does not get a new tag value, even if the actual is tagged. Overriding operations for such a derived type cannot be dispatched to from outside the instance. @begin{Ramification} If two overloaded subprograms declared in a generic package specification differ only by the (formal) type of their parameters and results, then there exist legal instantiations for which all calls of these subprograms from outside the instance are ambiguous. For example: @begin{Example} @key[generic] @key[type] A @key[is] (<>); @key[type] B @key[is] @key[private]; @key[package] G @key[is] @key[function] Next(X : A) @key[return] A; @key[function] Next(X : B) @key[return] B; @key[end] G; @key[package] P @key[is] @key[new] G(A => Boolean, B => Boolean); --@RI{ All calls of P.Next are ambiguous.} @end{Example} @end{Ramification} @begin{Ramification} @leading@;The following example illustrates some of the subtleties of the substitution of formals and actuals: @begin{Example} @key[generic] @key[type] T1 @key[is] @key[private]; --@RI{ A predefined "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : T1) return Boolean;} --@RI{ Call this "="@-{1}.} @key[package] G @key[is] @key[subtype] S1 @key[is] T1; --@RI{ So we can get our hands on the type from} --@RI{ outside an instance.} @key[type] T2 @key[is] @key[new] T1; --@RI{ An inherited "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : T2) return Boolean;} --@RI{ Call this "="@-{2}.} T1_Obj : T1 := ...; Bool_1 : Boolean := T1_Obj = T1_Obj; T2_Obj : T2 := ...; Bool_2 : Boolean := T2_Obj = T2_Obj; @key[end] G; ... @key[package] P @key[is] @key[type] My_Int @key[is] @key[new] Integer; --@RI{ A predefined "=" operator is implicitly declared here:} --@RI{ function "="(Left, Right : My_Int) return Boolean;} --@RI{ Call this "="@-{3}.} @key[function] "="(X, Y : My_Int) @key[return] Boolean; --@RI{ Call this "="@-{4}.} --@RI{ "="@-{3} is hidden from all visibility by "="@-{4}.} --@RI{ Nonetheless, "="@-{3} can @lquotes@;reemerge@rquotes@; in certain circumstances.} @key[end] P; @key[use] P; ... @key[package] I @key[is] @key[new] G(T1 => My_Int); --@RI{ "="@-{5} is declared in I (see below).} @key[use] I; Another_T1_Obj : S1 := 13; --@RI{ Can't denote T1, but S1 will do.} Bool_3 : Boolean := Another_T1_Obj = Another_T1_Obj; Another_T2_Obj : T2 := 45; Bool_4 : Boolean := Another_T2_Obj = Another_T2_Obj; Double : T2 := T2_Obj + Another_T2_Obj; @end{Example} In the instance I, there is a copy of "="@-{1} (call it "="@-{1i}) and "="@-{2} (call it "="@-{2i}). The "="@-{1i} and "="@-{2i} declare views of the predefined "=" of My_Int (that is, "="@-{3}). In the initialization of Bool_1 and Bool_2 in the generic unit G, the names "=" denote "="@-{1} and "="@-{2}, respectively. Therefore, the copies of these names in the instances denote "="@-{1i} and "="@-{2i}, respectively. Thus, the initialization of I.Bool_1 and I.Bool_2 call the predefined equality operator of My_Int; they will not call "="@-{4}. The declarations "="@-{1i} and "="@-{2i} are hidden from all visibility. This prevents them from being called from outside the instance. The declaration of Bool_3 calls "="@-{4}. The instance I also contains implicit declarations of the primitive operators of T2, such as "=" (call it "="@-{5}) and "+". These operations cannot be called from within the instance, but the declaration of Bool_4 calls "="@-{5}. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic instantiations (see @RefSecNum{Generic Declarations}):} @begin{Example} @tabclear()@tabset(P49) @key[procedure] Swap @key[is] @key[new] Exchange(Elem => Integer); @key[procedure] Swap @key[is] @key[new] Exchange(Character); @\--@RI{ Swap is overloaded } @key[function] Square @key[is] @key[new] Squaring(Integer); @\--@RI{ "*" of Integer used by default} @key[function] Square @key[is] @key[new] Squaring(Item => Matrix, "*" => Matrix_Product); @key[function] Square @key[is] @key[new] Squaring(Matrix, Matrix_Product); --@RI{ same as previous } @key[package] Int_Vectors @key[is] @key[new] On_Vectors(Integer, Table, "+"); @end{Example} @begin{WideAbove} @leading@keepnext@i{Examples of uses of instantiated units:} @end{WideAbove} @begin{Example} Swap(A, B); A := Square(A); T : Table(1 .. 5) := (10, 20, 30, 40, 50); N : Integer := Int_Vectors.Sigma(T); --@RI{ 150 (see @RefSec{Generic Bodies} for the body of Sigma)} @key[use] Int_Vectors; M : Integer := Sigma(T); --@RI{ 150} @end{Example} @end{Examples} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} In Ada 83, all explicit actuals are evaluated before all defaults, and the defaults are evaluated in the order of the formal declarations. This ordering requirement is relaxed in Ada 95. @end{Inconsistent83} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} We have attempted to remove every violation of the contract model. Any remaining contract model violations should be considered bugs in the RM95. The unfortunate property of reverting to the predefined operators of the actual types is retained for upward compatibility. (Note that fixing this would require subtype conformance rules.) However, tagged types do not revert in this sense. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @nt{explicit_generic_actual_parameter} is modified to allow a @SynI{package_instance_}@nt{name}. @end{Extend83} @begin{DiffWord83} The fact that named associations cannot be used for two formal subprograms with the same defining name is moved to AARM-only material, because it is a ramification of other rules, and because it is not of interest to the average user. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The rule that @lquotes@;An explicit @nt{explicit_generic_actual_parameter} shall not be supplied more than once for a given @Chg{Version=[2],New=[generic formal parameter], Old=[@ntf{generic_formal_parameter}]}@rquotes@; seems to be missing from RM83, although it was clearly the intent. In the explanation that the instance is a copy of the template, we have left out RM83-12.3(5)'s @lquotes@;apart from the generic formal part@rquotes@;, because it seems that things in the formal part still need to exist in instances. This is particularly true for generic formal packages, where you're sometimes allowed to reach in and denote the formals of the formal package from outside it. This simplifies the explanation of what each name in an instance denotes: there are just two cases: the declaration can be inside or outside (where inside needs to include the generic unit itself). Note that the RM83 approach of listing many cases (see RM83-12.5(5-14)) would have become even more unwieldy with the addition of generic formal packages, and the declarations that occur therein. We have corrected the definition of the elaboration of a @nt{generic_instantiation} (RM83-12.3(17)); we don't elaborate entities, and the instance is not @lquotes@;implicit.@rquotes@; In RM83, there is a rule saying the formal and actual shall match, and then there is much text defining what it means to match. Here, we simply state all the latter text as rules. For example, @lquotes@;A formal foo is matched by an actual greenish bar@rquotes@; becomes @lquotes@;For a formal foo, the actual shall be a greenish bar.@rquotes@; This is necessary to split the @ResolutionName@;s from the @LegalityName@;s. Besides, there's really no need to define the concept of matching for generic parameters. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00218-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} An @nt{overriding_indicator} (see @RefSecNum{Overriding Indicators}) is allowed on a subprogram instantiation.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{generic_instantiation}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0118-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a definition for positional parameters, as this is missing from Ada 95 and Ada 2005.]} @end{Diffword2005} @LabeledClause{Formal Objects} @begin{Intro} @redundant[@Defn{generic formal object} @Defn{formal object, generic} A generic formal object can be used to pass a value or variable to a generic unit.] @end{Intro} @begin{MetaRules} A generic formal object of mode @key{in} is like a constant initialized to the value of the @nt{explicit_generic_actual_parameter}. A generic formal object of mode @key{in out} is like a renaming of the @nt{explicit_generic_actual_parameter}. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00423-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1],ARef=[AI05-0183-1]} @Syn{lhs=<formal_object_declaration>,rhs=" @Syn2{defining_identifier_list} : @Syn2{mode} @Chg{Version=[2],New=<[@Syn2{null_exclusion}] >,Old=<>}@Syn2{subtype_mark} [:= @Syn2{default_expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};@Chg{Version=[2],New=< @Chg{Version=[3],New=[|],Old=[ ]} @Syn2{defining_identifier_list} : @Syn2{mode} @Syn2{access_definition} [:= @Syn2{default_expression}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(generic formal object default_expression)} The expected type for the @nt{default_expression}, if any, of a formal object is the type of the formal object. @PDefn2{Term=[expected type], Sec=(generic formal in object actual)} For a generic formal object of mode @key[in], the expected type for the actual is the type of the formal. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00423-01]} For a generic formal object of mode @key[in out], the type of the actual shall resolve to the type @Chg{Version=[2], New=[determined by the @nt{subtype_mark}, or for a @nt{formal_object_declaration} with an @nt{access_definition}, to a specific anonymous access type. If the anonymous access type is an access-to-object type, the type of the actual shall have the same designated type as that of the @nt{access_definition}. If the anonymous access type is an access-to-subprogram type, the type of the actual shall have a designated profile which is type conformant with that of the @nt{access_definition}. @Defn2{Term=[type conformance],Sec=(required)}],Old=[of the formal.]} @begin{Reason} See the corresponding rule for @nt{object_renaming_declaration}s for a discussion of the reason for this rule. @end{Reason} @end{Resolution} @begin{Legality} If a generic formal object has a @nt{default_expression}, then the mode shall be @key{in} @Redundant[(either explicitly or by default)]; otherwise, its mode shall be either @key{in} or @key{in out}. @begin{Ramification} Mode @key{out} is not allowed for generic formal objects. @end{Ramification} For a generic formal object of mode @key{in}, the actual shall be an @nt{expression}. For a generic formal object of mode @key{in out}, the actual shall be a @nt{name} that denotes a variable for which renaming is allowed (see @RefSecNum{Object Renaming Declarations}). @begin{Honest} The part of this that requires an @nt{expression} or @nt{name} is a @ResolutionName, but that's too pedantic to worry about. (The part about denoting a variable, and renaming being allowed, is most certainly @i{not} a @ResolutionName.) @end{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@ChgNote{Conditional leading} @Chg{Version=[2],New=[In the case where the type of the formal is defined by an @nt{access_definition}, the type of the actual and the type of the formal:], Old=[The type of a generic formal object of mode @key{in} shall be nonlimited.]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-object types with statically matching designated subtypes and with both or neither being access-to-constant types; or @PDefn2{Term=[statically matching],Sec=(required)}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[shall both be access-to-subprogram types with subtype conformant designated profiles. @Defn2{Term=[subtype conformance],Sec=(required)}]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a @nt{formal_object_declaration} with a @nt{null_exclusion} or an @nt{access_definition} that has a @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the actual matching the @nt{formal_object_declaration} denotes the generic formal object of another generic unit @i{G}, and the instantiation containing the actual occurs within the body of @i{G} or within the body of a generic unit declared within the declarative region of @i{G}, then the declaration of the formal object of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the actual matching the @nt{formal_object_declaration} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01],ARef=[AI95-00423-01]} @Chg{Version=[2],New=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of an object with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child units) when the subtype of the formal object excludes null implicitly.], Old=[Since a generic formal object is like a constant of mode @key{in} initialized to the value of the actual, a limited type would not make sense, since initializing a constant is not allowed for a limited type. That is, generic formal objects of mode @key{in} are passed by copy, and limited types are not supposed to be copied.]} @end{Reason} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00255-01],ARef=[AI95-00423-01]} A @nt{formal_object_declaration} declares a generic formal object. The default mode is @key{in}. @PDefn2{Term=[nominal subtype], Sec=(of a generic formal object)} For a formal object of mode @key{in}, the nominal subtype is the one denoted by the @nt{subtype_mark} @Chg{Version=[2],New=[or @nt{access_definition} ],Old=[]}in the declaration of the formal. @PDefn2{Term=[static], Sec=(subtype)} For a formal object of mode @key{in out}, its type is determined by the @nt<subtype_mark> @Chg{Version=[2], New=[or @nt{access_definition} ],Old=[]}in the declaration; its nominal subtype is nonstatic, even if the @nt<subtype_mark> denotes a static subtype@Chg{Version=[2], New=[; for a composite type, its nominal subtype is unconstrained if the first subtype of the type is unconstrained@Redundant[, even if the @nt{subtype_mark} denotes a constrained subtype]],Old=[]}. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00255-01]} @ChgAdded{Version=[2],Text=[We require that the subtype is unconstrained because a formal @key{in out} acts like a renaming, and thus the given subtype is ignored for purposes of matching; any value of the type can be passed. Thus we can assume only that the object is constrained if the first subtype is constrained (and thus there can be no unconstrained subtypes for the type). If we didn't do this, it would be possible to rename or take 'Access of components that could disappear due to an assignment to the whole object.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[The two @lquotes@;even if@rquotes clauses are OK even though they don't mention @nt{access_definition}s; an access subtype can neither be a static subtype nor be a composite type.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00269-01]} @Chg{Version=[2],New=[@Defn2{Term=[full constant declaration], Sec=(corresponding to a formal object of mode @key[in])}],Old=[]} @Defn2{Term=[stand-alone constant], Sec=(corresponding to a formal object of mode @key[in])} @PDefn{stand-alone object} In an instance, a @nt{formal_object_declaration} of mode @key{in} @Chg{Version=[2],New=[is a @i<full constant declaration> and ], Old=[]}declares a new stand-alone constant object whose initialization expression is the actual, whereas a @nt{formal_object_declaration} of mode @key{in out} declares a view whose properties are identical to those of the actual. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} These rules imply that generic formal objects of mode @key{in} are passed by copy@Chg{Version=[2],New=[ (or are built-in-place for a limited type)],Old=[]}, whereas generic formal objects of mode @key{in out} are passed by reference. Initialization and finalization happen for the constant declared by a @nt{formal_object_declaration} of mode @key{in} as for any constant; see @RefSec{Object Declarations} and @RefSec{Assignment and Finalization}. @PDefn2{Term=[subtype], Sec=(of a generic formal object)} In an instance, the subtype of a generic formal object of mode @key{in} is as for the equivalent constant. In an instance, the subtype of a generic formal object of mode @key{in out} is the subtype of the corresponding generic actual. @end{Ramification} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[evaluation], Sec=(generic_association for a formal object of mode @key{in})} @Defn2{Term=[assignment operation], Sec=(during evaluation of a @nt{generic_association} for a formal object of mode @key{in})} For the evaluation of a @nt{generic_association} for a formal object of mode @key{in}, a constant object is created, the value of the actual parameter is converted to the nominal subtype of the formal object, and assigned to the object@Redundant[, including any value adjustment @em see @RefSecNum{Assignment and Finalization}]. @PDefn2{Term=[implicit subtype conversion],Sec=(generic formal object of mode @key[in])} @begin{Ramification} This includes evaluating the actual and doing a subtype conversion, which might raise an exception. @end{Ramification} @begin{Discussion} The rule for evaluating a @nt<generic_association> for a formal object of mode @key{in out} is covered by the general Dynamic Semantics rule in @RefSecNum{Generic Instantiation}. @end{Discussion} @end{RunTime} @begin{Notes} The constraints that apply to a generic formal object of mode @key{in out} are those of the corresponding generic actual parameter (not those implied by the @nt{subtype_mark} that appears in the @nt{formal_object_declaration}). Therefore, to avoid confusion, it is recommended that the name of a first subtype be used for the declaration of such a formal object. @begin{Ramification} Constraint checks are done at instantiation time for formal objects of mode @key{in}, but not for formal objects of mode @key{in out}. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} In Ada 83, it is forbidden to pass a (nongeneric) formal parameter of mode @key{out}, or a subcomponent thereof, to a generic formal object of mode @key{in out}. This restriction is removed in Ada 95. @end{Extend83} @begin{DiffWord83} We make @lquotes@;@nt{mode}@rquotes@; explicit in the syntax. RM83 refers to the mode without saying what it is. This is also more uniform with the way (nongeneric) formal parameters are defined. We considered allowing mode @key{out} in Ada 95, for uniformity with (nongeneric) formal parameters. The semantics would be identical for modes @key{in out} and @key{out}. (Note that generic formal objects of mode @key{in out} are passed by reference. Note that for (nongeneric) formal parameters that are allowed to be passed by reference, the semantics of @key{in out} and @key{out} is the same. The difference might serve as documentation. The same would be true for generic formal objects, if @key{out} were allowed, so it would be consistent.) We decided not to make this change, because it does not produce any important benefit, and any change has some cost. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A generic formal @key{in} object can have a limited type. The actual for such an object must be built-in-place via a @nt{function_call} or @nt{aggregate}, see @RefSecNum{Limited Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[A generic formal object can have a @nt{null_exclusion} or an anonymous access type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00255-01]} @ChgAdded{Version=[2],Text=[Clarified that the nominal subtype of a composite formal @key{in out} object is unconstrained if the first subtype of the type is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00269-01]} @ChgAdded{Version=[2],Text=[Clarified that a formal @key{in} object can be static when referenced from outside of the instance (by declaring such an object to be a full constant declaration).]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{formal_object_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Formal Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @redundant[A generic formal subtype can be used to pass to a generic unit a subtype whose type is in a certain @Chg{Version=[2],New=[category], Old=[class]} of types.] @begin{Reason} We considered having intermediate syntactic categories @ntf{formal_integer_type_definition}, @ntf{formal_real_type_definition}, and @ntf{formal_fixed_point_definition}, to be more uniform with the syntax rules for non-generic-formal types. However, that would make the rules for formal types slightly more complicated, and it would cause confusion, since @nt{formal_discrete_type_definition} would not fit into the scheme very well. @end{Reason} @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} @Syn{lhs=<formal_type_declaration>,rhs=" @Chg{Version=[3],New=[ @Syn2{formal_complete_type_declaration} | @Syn2{formal_incomplete_type_declaration}],Old=<@key{type} @Syn2{defining_identifier}[@Syn2{discriminant_part}] @key{is} @Syn2{formal_type_definition};>}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1],ARef=[AI05-0213-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<formal_complete_type_declaration>,Old=<>}>,rhs="@Chg{Version=[3],New=< @key{type} @Syn2{defining_identifier}[@Syn2{discriminant_part}] @key{is} @Syn2{formal_type_definition} [@Syn2{aspect_specification}];>,Old=<>}"} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0213-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<formal_incomplete_type_declaration>,Old=<>}>,rhs="@Chg{Version=[3],New=< @key{type} @Syn2{defining_identifier}[@Syn2{discriminant_part}] [@key{is tagged}];>,Old=<>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} @Syn{lhs=<formal_type_definition>,rhs=" @Syn2{formal_private_type_definition} | @Syn2{formal_derived_type_definition} | @Syn2{formal_discrete_type_definition} | @Syn2{formal_signed_integer_type_definition} | @Syn2{formal_modular_type_definition} | @Syn2{formal_floating_point_definition} | @Syn2{formal_ordinary_fixed_point_definition} | @Syn2{formal_decimal_fixed_point_definition} | @Syn2{formal_array_type_definition} | @Syn2{formal_access_type_definition}@Chg{Version=[2],New=[ | @Syn2{formal_interface_type_definition}],Old=[]}"} @end{Syntax} @begin{Legality} @Defn{generic actual subtype} @Defn{actual subtype} @Defn{generic actual type} @Defn{actual type} For a generic formal subtype, the actual shall be a @nt{subtype_mark}; it denotes the @i{(generic) actual subtype}. @begin{Ramification} When we say simply @lquotes@;formal@rquotes@; or @lquotes@;actual@rquotes@; (for a generic formal that denotes a subtype) we're talking about the subtype, not the type, since a name that denotes a @nt{formal_type_declaration} denotes a subtype, and the corresponding actual also denotes a subtype. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{generic formal type} @Defn{formal type} @Defn{generic formal subtype} @Defn{formal subtype} A @nt{formal_type_declaration} declares a @i{(generic) formal type}, and its first subtype, the @i{(generic) formal subtype}. @begin{Ramification} A subtype (other than the first subtype) of a generic formal type is not a generic formal subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} @Chg{Version=[2],New=[@Defn{determined category for a formal type} @Defn{category determined for a formal type}], Old=[@Defn{determined class for a formal type} @Defn{class determined for a formal type}]} The form of a @nt{formal_type_definition} @i{determines a @Chg{Version=[2],New=[category (of types)],Old=[class]}} to which the formal type belongs. For a @nt{formal_private_type_definition} the reserved words @key{tagged} and @key{limited} indicate the @Chg{Version=[2],New=[category of types],Old=[class]} (see @RefSecNum{Formal Private and Derived Types}).@Chg{Version=[3],New=[ The reserved word @key{tagged} also plays this role in the case of a @nt{formal_incomplete_type_declaration}.],Old=[]} For a @nt{formal_derived_type_definition} the @Chg{Version=[2],New=[category of types],Old=[class]} is the derivation class rooted at the ancestor type. For other formal types, the name of the syntactic category indicates the @Chg{Version=[2],New=[category of types],Old=[class]}; a @nt{formal_discrete_type_definition} defines a discrete type, and so on. @begin{Reason} This rule is clearer with the flat syntax rule for @nt{formal_type_definition} given above. Adding @ntf{formal_integer_type_definition} and others would make this rule harder to state clearly. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We use @lquotes@;category@rquote rather than @lquotes@;class@rquotes above, because the requirement that classes are closed under derivation is not important here. Moreover, there are interesting categories that are not closed under derivation. For instance, limited and interface are categories that do not form classes.]} @end{Reason} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The actual type shall be in the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} For example, if the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal is the @Chg{Version=[2],New=[category],Old=[class]} of all discrete types, then the actual has to be discrete. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} Note that this rule does not require the actual to belong to every @Chg{Version=[2],New=[category],Old=[class]} to which the formal belongs. For example, formal private types are in the @Chg{Version=[2],New=[category],Old=[class]} of composite types, but the actual need not be composite. Furthermore, one can imagine an infinite number of @Chg{Version=[2], New=[categories],Old=[classes]} that are just arbitrary sets of types @Chg{Version=[2],New=[],Old=[that obey the closed-under-derivation rule, and are therefore technically classes]} (even though we don't give them names, since they are uninteresting). We don't want this rule to apply to @i{those} @Chg{Version=[2],New=[categories],Old=[classes]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01],ARef=[AI95-00442-01]} @lquotes@;Limited@rquotes@; is not @Chg{Version=[2],New=[an],Old=[a]} @lquotes@;interesting@rquotes@; @Chg{Version=[2],New=[category],Old=[class]}, but @lquotes@;nonlimited@rquotes@; is; it is legal to pass a nonlimited type to a limited formal type, but not the other way around. The reserved word @Chg{Version=[2],New=[@key[limited]],Old=[@ntf{limited}]} really represents a @Chg{Version=[2],New=[category],Old=[class]} containing both limited and nonlimited types. @lquotes@;Private@rquotes@; is not a @Chg{Version=[2],New=[category for this purpose], Old=[class]}; a generic formal private type accepts both private and nonprivate actual types. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} It is legal to pass a class-wide subtype as the actual if it is in the right @Chg{Version=[2],New=[category],Old=[class]}, so long as the formal has unknown discriminants. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0037],ARef=[AI95-00043-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01],ARef=[AI95-00442-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0029-1]} @Redundant[The formal type also belongs to each @Chg{Version=[2],New=[category],Old=[class]} that contains the determined @Chg{Version=[2],New=[category],Old=[class]}.] The primitive subprograms of the type are as for any type in the determined @Chg{Version=[2],New=[category],Old=[class]}. For a formal type other than a formal derived type, these are the predefined operators of the type@Chg{New=[. For an elementary formal type, the predefined operators are implicitly declared immediately after the declaration of the formal type. For a composite formal type, the predefined operators are implicitly declared either immediately after the declaration of the formal type, or later @Chg{Version=[2],New=[immediately within the declarative region in which the type is declared],Old=[in its immediate scope]} according to the rules of @RefSecNum(Private Operations).], Old=[; they are implicitly declared immediately after the declaration of the formal type.]} In an instance, the copy of such an implicit declaration declares a view of the predefined operator of the actual type, even if this operator has been overridden for the actual type@Chg{Version=[3],New=[ and even if it is never declared for the actual type],Old=[]}. @Redundant[The rules specific to formal derived types are given in @RefSecNum{Formal Private and Derived Types}.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} All properties of the type are as for any type in the @Chg{Version=[2],New=[category],Old=[class]}. Some examples: The primitive operations available are as defined by the language for each @Chg{Version=[2],New=[category],Old=[class]}. The form of @nt{constraint} applicable to a formal type in a @nt{subtype_indication} depends on the @Chg{Version=[2],New=[category],Old=[class]} of the type as for a nonformal type. The formal type is tagged if and only if it is declared as a tagged private type, or as a type derived from a (visibly) tagged type. (Note that the actual type might be tagged even if the formal type is not.) @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The somewhat cryptic phrase @ldquote@;even if it is never declared@rdquote@; is intended to deal with the following oddity:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] Q @key[is] @key[type] T @key[is limited private]; @key[private] @key[type] T @key[is range] 1 .. 10; @key[end] Q;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[type] A @key[is array] (Positive @key[range] <>) @key[of] T; @key[package] Q.G @key[is] A1, A2 : A (1 .. 1); @key[private] B : Boolean := A1 = A2; @key[end] Q.G;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Q.G; @key[package] R @key[is] @key[type] C @key[is array] (Positive @key[range] <>) @key[of] Q.T;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] I @key[is new] Q.G (C); --@RI{ Where is the predefined "=" for C?} @key[end] R;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An "=" is available for the formal type A in the private part of Q.G. However, no "=" operator is ever declared for type C, because its component type Q.T is limited. Still, in the instance I the name "=" declares a view of the "=" for C which exists-but-is-never-declared.]} @end{Reason} @end{StaticSem} @begin{Notes} Generic formal types, like all types, are not named. Instead, a @nt{name} can denote a generic formal subtype. Within a generic unit, a generic formal type is considered as being distinct from all other (formal or nonformal) types. @begin{TheProof} This follows from the fact that each @nt{formal_type_declaration} declares a type. @end{TheProof} A @nt{discriminant_part} is allowed only for certain kinds of types, and therefore only for certain kinds of generic formal types. See @RefSecNum{Discriminants}. @begin{Ramification} The term @lquotes@;formal floating point type@rquotes@; refers to a type defined by a @nt{formal_floating_point_definition}. It does not include a formal derived type whose ancestor is floating point. Similar terminology applies to the other kinds of @nt{formal_type_definition}. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of generic formal types:} @begin{Example} @key[type] Item @key[is] @key[private]; @key[type] Buffer(Length : Natural) @key[is] @key[limited] @key[private]; @key[type] Enum @key[is] (<>); @key[type] Int @key[is] @key[range] <>; @key[type] Angle @key[is] @key[delta] <>; @key[type] Mass @key[is] @key[digits] <>; @key[type] Table @key[is] @key[array] (Enum) @key[of] Item; @end{Example} @begin{WideAbove} @leading@keepnext@i{Example of a generic formal part declaring a formal integer type:} @end{WideAbove} @begin{Example} @key[generic] @key[type] Rank @key[is] @key[range] <>; First : Rank := Rank'First; Second : Rank := First + 1; --@RI{ the operator "+" of the type Rank } @end{Example} @end{Examples} @begin{DiffWord83} RM83 has separate sections @lquotes@;Generic Formal Xs@rquotes@; and @lquotes@;Matching Rules for Formal Xs@rquotes@; (for various X's) with most of the text redundant between the two. We have combined the two in order to reduce the redundancy. In RM83, there is no @lquotes@;Matching Rules for Formal Types@rquotes@; section; nor is there a @lquotes@;Generic Formal Y Types@rquotes@; section (for Y = Private, Scalar, Array, and Access). This causes, for example, the duplication across all the @lquotes@;Matching Rules for Y Types@rquotes@; sections of the rule that the actual passed to a formal type shall be a subtype; the new organization avoids that problem. The matching rules are stated more concisely. We no longer consider the multiplying operators that deliver a result of type @i{universal_fixed} to be predefined for the various types; there is only one of each in package Standard. Therefore, we need not mention them here as RM83 had to. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0037],ARef=[AI95-00043-01],ARef=[AI95-00233-01]} @ChgAdded{Version=[2],Text=[Corrigendum 1 corrected the wording to properly define the location where operators are defined for formal array types. The wording here was inconsistent with that in @RefSec{Private Operations}. For the Amendment, this wording was corrected again, because it didn't reflect the Corrigendum 1 revisions in @RefSecNum{Private Operations}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Formal interface types are defined; see @RefSec{Formal Interface Types}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We use @lquotes@;determines a category@rquotes rather than class, since not all interesting properties form a class.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{formal_type_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Text=[@b<Correction>: Updated the wording to acknowledge the possibility of operations that are never declared for an actual type but still can be used inside of a generic unit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Formal incomplete types are added; these are documented as an extension in the next subclause.]} @end{DiffWord2005} @LabeledSubClause{Formal Private and Derived Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} @Redundant[@Chg{Version=[2],New=[In its most general form, the category], Old=[The class]} determined for a formal private type @Chg{Version=[2],New=[is all types, but @Chg{Version=[3],New=[the category],Old=[it]} can be restricted to only nonlimited types or to only tagged types], Old=[can be either limited or nonlimited, and either tagged or untagged; no more specific class is known for such a type]}.@Chg{Version=[3],New=[ Similarly, the category for a formal incomplete type is all types but the category can be restricted to only tagged types; unlike other formal types, the actual type does not need to be able to be frozen (see @RefSecNum{Freezing Rules}).],Old=[]} The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal derived type is the derivation class rooted at the ancestor type.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} @ChgAdded{Version=[2],Text=[The first @Chg{Version=[3],New=[two rules are],Old=[rule is]} given normatively below, and the @Chg{Version=[3],New=[third],Old=[second]} rule is given normatively in @RefSecNum{Formal Types}; they are repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[Since the actual of a formal incomplete type does not need to be able to be frozen, the actual can be an incomplete type or a partial view before its completion.]} @end{Ramification} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_private_type_definition>, rhs="[[@key{abstract}] @key{tagged}] [@key{limited}] @key{private}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @Syn{lhs=<formal_derived_type_definition>, rhs="@Chg{Version=[2],New=[ ],Old=[]}[@key{abstract}] @Chg{Version=[2],New=<[@key{limited} | @key{synchronized}] >,Old=[]}@key{new} @Syn2{subtype_mark} [@Chg{Version=[2],New=<[@key{and} @Syn2{interface_list}]>,Old=<>}@key{with} @key{private}]"} @end{Syntax} @begin{Legality} If a generic formal type declaration has a @nt{known_discriminant_part}, then it shall not include a @nt{default_expression} for a discriminant. @begin{Ramification} Consequently, a generic formal subtype with a @nt{known_discriminant_part} is an indefinite subtype, so the declaration of a stand-alone variable has to provide a constraint on such a subtype, either explicitly, or by its initial value. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0237-1]} @Defn2{Term=[ancestor subtype], Sec=(of a formal derived type)} @PDefn{private extension} The @i(ancestor subtype) of a formal derived type is the subtype denoted by the @nt<subtype_mark> of the @nt<formal_derived_type_definition>. For a formal derived type declaration, the reserved words @key{with private} shall appear if and only if the ancestor type is a tagged type; in this case the formal derived type is a private extension of the ancestor type and the ancestor shall not be a class-wide type. @Redundant[Similarly, @Chg{Version=[2],New=[an @nt{interface_list} or ],Old=[]} the optional reserved @Chg{Version=[2],New=[words],Old=[word]} @key{abstract} @Chg{Version=[2],New=[or @key{synchronized} ],Old=[]}shall appear only if the ancestor type is a tagged type].@Chg{Version=[2], New=[ The reserved word @key{limited} or @key{synchronized} shall appear only if the ancestor type @Redundant[and any progenitor types] are limited types. The reserved word @key{synchronized} shall appear (rather than @key{limited}) if the ancestor type or any of the progenitor types are synchronized interfaces.],Old=[]}@Chg{Version=[3],New=[ The ancestor type shall be a limited interface if the reserved word @key{synchronized} appears.],Old=[]} @begin{Reason} We use the term @lquotes@;ancestor@rquotes@; here instead of @lquotes@;parent@rquotes@; because the actual can be any descendant of the ancestor, not necessarily a direct descendant. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00419-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[We require the ancestor type to be limited when @key{limited} appears so that we avoid @Chg{Version=[3],New=[oddities],Old=[oddies]} like limited integer types. Normally, @key{limited} means @lquotes@;match anything@rquotes for a generic formal, but it was felt that allowing limited elementary types to be declared was just too weird. Integer still matches a formal limited private type; it is only a problem when the type is known to be elementary. Note that the progenitors are required to be limited by rules in @RefSecNum{Interface Types}, thus that part of the rule is redundant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[We require that @key{synchronized} appear if the ancestor or any of the progenitors are synchronized, so that property is explicitly given in the program text @en it is not automatically inherited from the ancestors. However, it can be given even if neither the ancestor nor the progenitors are synchronized.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00443-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0087-1]} @ChgAdded{Version=[2],Text=[The actual type for a formal derived type shall be a descendant of @Redundant[the ancestor type and] every progenitor of the formal type. @Chg{Version=[3],New=[If the formal type is nonlimited, the actual type shall be nonlimited. ],Old=[]}If the reserved word @key[synchronized] appears in the declaration of the formal derived type, the actual type shall be a synchronized tagged type.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual type has to be a descendant of the ancestor type, in order that it be in the correct class. Thus, that part of the rule is redundant.]} @end{TheProof} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[For a nonformal private extension, we require the partial view to be synchronized if the full view is synchronized tagged. This does not apply to a formal private extension @em it is OK if the formal is not synchronized. Any attempt to extend the formal type will be rechecked in the instance, where the rule disallowing extending a @Chg{Version=[3],New=[synchronized],Old=[sychronized]} noninterface type will be enforced. This is consistent with the @lquotes@;no hidden interfaces@rquotes rule also applying only to nonformal private extensions, as well as the rule that a limited nonformal private extension implies a limited full type. Formal private extensions are exempted from all these rules to enable the construction of generics that can be used with the widest possible range of types. In particular, an indefinite tagged limited formal private type can match any @lquotes@;concrete@rquotes actual tagged type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0087-1]} @ChgAdded{Version=[3],Text=[A type (including formal types) derived from a limited interface could be nonlimited; we do not want a limited type derived from such an interface to match a nonlimited formal derived type. Otherwise, we could assign limited objects. Thus, we have to explicitly ban this case.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} If @Chg{Version=[3],New=[a],Old=[the]} formal@Chg{Version=[3],New=[ private or derived],Old=[]} subtype is definite, then the actual subtype shall also be definite. @begin{Ramification} On the other hand, for an indefinite formal subtype, the actual can be either definite or indefinite. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[A @nt{formal_incomplete_type_declaration} declares a formal incomplete type. The only view of a formal incomplete type is an incomplete view. @Redundant[Thus, a formal incomplete type is subject to the same usage restrictions as any other incomplete type @em see @RefSecNum{Incomplete Type Declarations}.]]} @leading@;For a generic formal derived type with no @nt<discriminant_part>: @begin(Itemize) If the ancestor subtype is constrained, the actual subtype shall be constrained, and shall be statically compatible with the ancestor; @begin{Ramification} In other words, any constraint on the ancestor subtype is considered part of the @lquotes@;contract.@rquotes@; @end{Ramification} If the ancestor subtype is an unconstrained access or composite subtype, the actual subtype shall be unconstrained. @begin{Reason} This rule ensures that if a composite constraint is allowed on the formal, one is also allowed on the actual. If the ancestor subtype is an unconstrained scalar subtype, the actual is allowed to be constrained, since a scalar constraint does not cause further constraints to be illegal. @end{Reason} If the ancestor subtype is an unconstrained discriminated subtype, then the actual shall have the same number of discriminants, and each discriminant of the actual shall correspond to a discriminant of the ancestor, in the sense of @RefSecNum{Discriminants}. @begin{Reason} This ensures that if a discriminant constraint is given on the formal subtype, the corresponding constraint in the instance will make sense, without additional run-time checks. This is not necessary for arrays, since the bounds cannot be overridden in a type extension. An @nt<unknown_discriminant_part> may be used to relax these matching requirements. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[If the ancestor subtype is an access subtype, the actual subtype shall exclude null if and only if the ancestor subtype excludes null.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require that the @lquotes@;excludes null@rquotes property match, because it would be difficult to write a correct generic for a formal access type without knowing this property. Many typical algorithms and techniques will not work for a subtype that excludes null (setting an unused component to @key{null}, default-initialized objects, and so on). We want this sort of requirement to be reflected in the contract of the generic.]} @end{Reason} @end(Itemize) @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} The declaration of a formal derived type shall not have a @nt{known_discriminant_part}. For a generic formal private @Chg{Version=[3],New=[or incomplete ],Old=[]}type with a @nt{known_discriminant_part}: @begin{Itemize} The actual type shall be a type with the same number of discriminants. The actual subtype shall be unconstrained. The subtype of each discriminant of the actual type shall statically match the subtype of the corresponding discriminant of the formal type. @PDefn2{Term=[statically matching],Sec=(required)} @begin{Reason} We considered defining the first and third rule to be called @lquotes@;subtype conformance@rquotes@; for @nt{discriminant_part}s. We rejected that idea, because it would require implicit (inherited) @nt{discriminant_part}s, which seemed like too much mechanism. @end{Reason} @end{Itemize} @Redundant[For a generic formal type with an @nt{unknown_discriminant_part}, the actual may, but need not, have discriminants, and may be definite or indefinite.] @end{Legality} @begin{StaticSem} @leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal private type is as follows: @ChgRef{Version=[2],Kind=[Revised]} @TabClear{}@Tabset(P32) @begin{Display} @i(Type Definition) @\@i(Determined @Chg{Version=[2],New=[Category],Old=[Class]})@* @key{limited private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all types @key{private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all nonlimited types @key{tagged limited private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all tagged types @key{tagged private} @\the @Chg{Version=[2],New=[category],Old=[class]} of all nonlimited tagged types @end{Display} @Redundant[The presence of the reserved word @key{abstract} determines whether the actual type may be abstract.] @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[The category determined for a formal incomplete type is the category of all types, unless the @nt{formal_type_declaration} includes the reserved word @key[tagged]; in this case, it is the category of all tagged types.]} A formal private or derived type is a private or derived type, respectively. A formal derived tagged type is a private extension. @Redundant[A formal private or derived type is abstract if the reserved word @key(abstract) appears in its declaration.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0110-1]} @Chg{Version=[3],New=[For a formal derived type, the characteristics],Old=[If the ancestor type is a composite type that is not an array type, the formal type inherits components from the ancestor type]} (including @Chg{Version=[3],New=[components, but excluding ],Old=[]}discriminants if @Chg{Version=[3],New=[there is ],Old=[]}a new @nt<discriminant_part>@Chg{Version=[3],New=[],Old=[ is not specified]}), @Chg{Version=[3],New=[predefined operators, and inherited user-defined primitive subprograms are determined by its ancestor type and its progenitor types (if any), in the same way that those of],Old=[as for]} a derived type @Chg{Version=[3],New=[are determined by those of its parent type and its progenitor types],Old=[defined by a @nt<derived_type_definition>]} (see @RefSecNum(Derived Types and Classes)@Chg{Version=[2],New=[ and @RefSecNum{Private Operations}],Old=[]}). @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0038],ARef=[AI95-00202]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00233-01],ARef=[AI95-00401-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0029-1],ARef=[AI05-0110-1]} @Chg{Version=[3],New=[],Old=[For a formal derived type, the predefined operators and inherited user-defined subprograms are determined by the ancestor type@Chg{Version=[2],New=[ and any progenitor types],Old=[]}, and are implicitly declared at the earliest place, if any, @Chg{Version=[2],New=[immediately within the declarative region in which], Old=[within the immediate scope of]} the formal type@Chg{Version=[2],New=[ is declared],Old=[]}, where the corresponding primitive subprogram of the ancestor @Chg{Version=[2],New=[or progenitor ],Old=[]}is visible (see @RefSecNum{Private Operations}). ]}In an instance, the copy of @Chg{Version=[3],New=[],Old=[such ]}an implicit declaration @Chg{Version=[3],New=[of a primitive subprogram of a formal derived type ], Old=[]}declares a view of the corresponding primitive subprogram of the ancestor@Chg{New=[@Chg{Version=[2], New=[ or progenitor],Old=[]} of the formal derived type],Old=[]}, even if this primitive has been overridden for the actual type@Chg{Version=[3],New=[ and even if it is never declared for the actual type],Old=[]}. @Chg{New=[When the ancestor@Chg{Version=[2], New=[ or progenitor],Old=[]} of the formal derived type is itself a formal type, the copy of the implicit declaration declares a view of the corresponding copied operation of the ancestor@Chg{Version=[2], New=[ or progenitor],Old=[]}.],Old=[]} @Redundant[In the case of a formal private extension, however, the tag of the formal type is that of the actual type, so if the tag in a call is statically determined to be that of the formal type, the body executed will be that corresponding to the actual type.] @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00401-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The above rule defining the properties of primitive subprograms in an instance applies even if the subprogram has been overridden or hidden for the actual type. This rule is necessary for untagged types, because their primitive subprograms might have been overridden by operations that are not @Chg{Version=[3],New=[subtype conformant],Old=[subtype-conformant]} with the operations defined for the class. For tagged types, the rule still applies, but the primitive subprograms will dispatch to the appropriate implementation based on the type and tag of the operands. Even for tagged types, the formal parameter names and @nt{default_expression}s are determined by those of the primitive subprograms of the specified ancestor type@Chg{Version=[2],New=[ (or progenitor type, for subprograms inherited from an interface type)],Old=[]}. @end{Ramification} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} S that denotes a formal indefinite subtype]}, the following attribute is defined: @begin{Description} @ChgAttribute{Version=[3],Kind=(Revised),ChginAnnex=[T],Leading=[F], Prefix=<S>, AttrName=<Definite>,ARef=[AI05-0264-1], Text=[S'Definite yields True if the actual subtype corresponding to S is definite; otherwise@Chg{Version=[3],New=[,],Old=[]} it yields False. The value of this attribute is of the predefined type Boolean.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Whether an actual subtype is definite or indefinite may have a major effect on the algorithm used in a generic. For example, in a generic I/O package, whether to use fixed-length or variable-length records could depend on whether the actual is definite or indefinite. This attribute is essentially a replacement for the Constrained attribute@Chg{Version=[2],New=[,],Old=[]} which is now considered obsolete. @end{Discussion} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0071-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case where a formal type @Chg{Version=[3],New=[has],Old=[is tagged with]} unknown discriminants, and the actual type is a class-wide type @i<T>'Class:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[For the purposes of defining the primitive operations of the formal type, each of the primitive operations of the actual type is considered to be a subprogram (with an intrinsic calling convention @em see @RefSecNum{Conformance Rules}) whose body consists of a dispatching call upon the corresponding operation of @i<T>, with its formal parameters as the actual parameters. If it is a function, the result of the dispatching call is returned.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[If the corresponding operation of @i<T> has no controlling formal parameters, then the controlling tag value is determined by the context of the call, according to the rules for tag-indeterminate calls (see @RefSecNum{Dispatching Operations of Tagged Types} and @RefSecNum{Assignment Statements}). In the case where the tag would be statically determined to be that of the formal type, the call raises Program_Error. If such a function is renamed, any call on the renaming raises Program_Error. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As it states in @RefSecNum{Conformance Rules}, the convention of an inherited subprogram of a generic formal tagged type with unknown discriminants is intrinsic.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[In the case of a corresponding primitive of T with no controlling formal parameters, the context of the call provides the controlling tag value for the dispatch. If no tag is provided by context, Program_Error is raised rather than resorting to a nondispatching call. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} NT(<>) @key{is new} T @key{with private}; -- @RI[Assume T has operation "]@key{function} Empty @key{return} T;@RI["] @key{package} G @key{is} @key{procedure} Test(X : @key{in out} NT); @key{end} G;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} G @key{is} @key{procedure} Test(X : @key{in out} NT) @key{is} @key{begin} X := Empty; -- @RI[Dispatching based on X'Tag takes] -- @RI[place if actual is class-wide.] @key{declare} Y : NT := Empty; -- @RI[If actual is class-wide, this raises Program_Error] -- @RI[as there is no tag provided by context.] @key{begin} X := Y; -- @RI[We never get this far.] @key{end}; @key{end} Test; @key{end} G;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} T1 @key{is new} T @key{with null record}; @key{package} I @key{is new} G(T1'Class);]} @end{Example} @end{Discussion} @end{RunTime} @begin{Notes} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} In accordance with the general rule that the actual type shall belong to the @Chg{Version=[2],New=[category],Old=[class]} determined for the formal (see @RefSec(Formal Types)): @begin(itemize) If the formal type is nonlimited, then so shall be the actual; For a formal derived type, the actual shall be in the class rooted at the ancestor subtype. @end(itemize) The actual type can be abstract only if the formal type is abstract (see @RefSecNum{Abstract Types and Subprograms}). @begin{Reason} This is necessary to avoid contract model problems, since one or more of its primitive subprograms are abstract; it is forbidden to create objects of the type, or to declare functions returning the type. @end{Reason} @begin{Ramification} On the other hand, it is OK to pass a nonabstract actual to an abstract formal @em @key[abstract] on the formal indicates that the actual might be abstract. @end{Ramification} If the formal has a @nt{discriminant_part}, the actual can be either definite or indefinite. Otherwise, the actual has to be definite. @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Ada 83 does not have @nt{unknown_discriminant_part}s, so it allows indefinite subtypes to be passed to definite formals, and applies a legality rule to the instance body. This is a contract model violation. Ada 95 disallows such cases at the point of the instantiation. The workaround is to add (<>) as the @nt{discriminant_part} of any formal subtype if it is intended to be used with indefinite actuals. If that's the intent, then there can't be anything in the generic body that would require a definite subtype. The check for discriminant subtype matching is changed from a run-time check to a compile-time check. @end{Incompatible83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00401-01],ARef=[AI95-00419-01],ARef=[AI95-00443-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} A generic formal derived type can include progenitors (interfaces) as well as a primary ancestor. It also may include @key{limited} to indicate that it is a limited type, and @key{synchronized} to indicate that it is a synchronized type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0038],ARef=[AI95-00202-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected wording to define the operations that are inherited when the ancestor of a formal type is itself a formal type to avoid anomalies.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00158-01]} @ChgAdded{Version=[2],Text=[Added a semantic description of the meaning of operations of an actual class-wide type, as such a type does not have primitive operations of its own.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a matching rule for access subtypes that exclude null.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00233-01]} @ChgAdded{Version=[2],Text=[The wording for the declaration of implicit operations is corrected to be consistent with @RefSecNum{Private Operations} as modified by Corrigendum 1.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0087-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added wording to prevent a limited type from being passed to a nonlimited formal derived type. While this was allowed, it would break the contract for the limited type, so hopefully no programs actually depend on that.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Formal incomplete types are a new kind of generic formal; these can be instantiated with incomplete types and unfrozen private types.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0029-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Updated the wording to acknowledge the possibility of operations that are never declared for an actual type but still can be used inside of a generic unit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0071-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Fixed hole that failed to define what happened for "=" for an untagged private type whose actual is class-wide.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0110-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the wording for inheritance of characteristics and operations of formal derived types to be reuse the rules as defined for derived types; this should eliminate holes in the wording which have plagued us since Ada 95 was defined (it has been "corrected" four previous times).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0237-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added missing rule for the ancestors of formal derived types. The added rule would formally be incompatible, but since it would be impossible to instantiate any such generic, this cannot happen outside of test suites and thus is not documented as an incompatibility.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Formal Scalar Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} A @i{formal scalar type} is one defined by any of the @nt{formal_type_definition}s in this subclause. @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal scalar type is @Chg{Version=[2],New=[the category of all ],Old=[]}discrete, signed integer, modular, floating point, ordinary fixed point, or decimal@Chg{Version=[2],New=[ types],Old=[]}.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The second rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[The @lquotes@;category of a type@rquotes includes any classes that the type belongs to.]} @end{Ramification} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_discrete_type_definition>,rhs="(<>)"} @Syn{lhs=<formal_signed_integer_type_definition>,rhs="@key{range} <>"} @Syn{lhs=<formal_modular_type_definition>,rhs="@key{mod} <>"} @Syn{lhs=<formal_floating_point_definition>,rhs="@key{digits} <>"} @Syn{lhs=<formal_ordinary_fixed_point_definition>,rhs="@key{delta} <>"} @Syn{lhs=<formal_decimal_fixed_point_definition>,rhs="@key{delta} <> @key{digits} <>"} @end{Syntax} @begin{Legality} The actual type for a formal scalar type shall not be a nonstandard numeric type. @begin{Reason} This restriction is necessary because nonstandard numeric types have some number of restrictions on their use, which could cause contract model problems in a generic body. Note that nonstandard numeric types can be passed to formal derived and formal private subtypes, assuming they obey all the other rules, and assuming the implementation allows it (being nonstandard means the implementation might disallow anything). @end{Reason} @end{Legality} @begin{Notes} The actual type shall be in the class of types implied by the syntactic category of the formal type definition (see @RefSec(Formal Types)). For example, the actual for a @nt<formal_modular_type_definition> shall be a modular type. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @LabeledSubClause{Formal Array Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal array type is the @Chg{Version=[2],New=[category],Old=[class]} of all array types.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_array_type_definition>,rhs="@Syn2{array_type_definition}"} @end{Syntax} @begin{Legality} The only form of @nt{discrete_subtype_definition} that is allowed within the declaration of a generic formal (constrained) array subtype is a @nt{subtype_mark}. @begin{Reason} The reason is the same as for forbidding @nt{constraint}s in @nt{subtype_indication}s (see @RefSecNum{Generic Declarations}). @end{Reason} @Leading@;For a formal array subtype, the actual subtype shall satisfy the following conditions: @begin{Itemize} The formal array type and the actual array type shall have the same dimensionality; the formal subtype and the actual subtype shall be either both constrained or both unconstrained. For each index position, the index types shall be the same, and the index subtypes (if unconstrained), or the index ranges (if constrained), shall statically match (see @RefSecNum{Statically Matching Constraints and Subtypes}). @PDefn2{Term=[statically matching],Sec=(required)} The component subtypes of the formal and actual array types shall statically match. @PDefn2{Term=[statically matching],Sec=(required)} If the formal type has aliased components, then so shall the actual. @begin{Ramification} On the other hand, if the formal's components are not aliased, then the actual's components can be either aliased or not. @end{Ramification} @end{Itemize} @end{Legality} @begin{Examples} @Leading@Keepnext@i{Example of formal array types:} @begin{Example} --@RI{ given the generic package } @key[generic] @key[type] Item @key[is] @key[private]; @key[type] Index @key[is] (<>); @key[type] Vector @key[is] @key[array] (Index @key[range] <>) @key[of] Item; @key[type] Table @key[is] @key[array] (Index) @key[of] Item; @key[package] P @key[is] ... @key[end] P; --@RI{ and the types } @key[type] Mix @key[is] @key[array] (Color @key[range] <>) @key[of] Boolean; @key[type] Option @key[is] @key[array] (Color) @key[of] Boolean; --@RI{ then Mix can match Vector and Option can match Table } @key[package] R @key[is] @key[new] P(Item => Boolean, Index => Color, Vector => Mix, Table => Option); --@RI{ Note that Mix cannot match Table and Option cannot match Vector} @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The check for matching of component subtypes and index subtypes or index ranges is changed from a run-time check to a compile-time check. The Ada 83 rule that @lquotes@;If the component type is not a scalar type, then the component subtypes shall be either both constrained or both unconstrained@rquotes@; is removed, since it is subsumed by static matching. Likewise, the rules requiring that component types be the same is subsumed. @end{Incompatible83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{Formal Access Types} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00442-01]} @Redundant[The @Chg{Version=[2],New=[category],Old=[class]} determined for a formal access type is the @Chg{Version=[2],New=[category],Old=[class]} of all access types.] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @end{Intro} @begin{Syntax} @Syn{lhs=<formal_access_type_definition>,rhs="@Syn2{access_type_definition}"} @end{Syntax} @begin{Legality} For a formal access-to-object type, the designated subtypes of the formal and actual types shall statically match. @PDefn2{Term=[statically matching],Sec=(required)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00231-01]} If and only if the @nt{general_access_modifier} @key{constant} applies to the formal, the actual shall be an access-to-constant type. If the @nt{general_access_modifier} @key{all} applies to the formal, then the actual shall be a general access-to-variable type (see @RefSecNum{Access Types}).@Chg{Version=[2],New=[ If and only if the formal subtype excludes null, the actual subtype shall exclude null.],Old=[]} @begin{Ramification} If no @ntf{_modifier} applies to the formal, then the actual type may be either a pool-specific or a general access-to-variable type. @end{Ramification} @begin{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0109],ARef=[AI95-00025-01]} @ChgAdded{Version=[1],Text=[Matching an access-to-variable to a formal access-to-constant type cannot be allowed. If it were allowed, it would be possible to create an access-to-variable value designating a constant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[We require that the @lquotes@;excludes null@rquotes property match, because it would be difficult to write a correct generic for a formal access type without knowing this property. Many typical algorithms and techniques will not work for a subtype that excludes null (setting an unused component to @key{null}, default-initialized objects, and so on). Even Ada.Unchecked_Deallocation would fail for a subtype that excludes null. Most generics would end up with comments saying that they are not intended to work for subtypes that exclude null. We would rather that this sort of requirement be reflected in the contract of the generic.]} @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1],ARef=[AI05-0288-1]} For a formal access-to-subprogram subtype, the designated profiles of the formal and the actual shall be @Chg{Version=[3],New=[subtype conformant],Old=[mode-conformant, and the calling convention of the actual shall be @i{protected} if and only if that of the formal is @i{protected}]}. @Chg{Version=[3],New=[@Defn2{Term=[subtype conformance],Sec=(required)}], Old=[@Defn2{Term=[mode conformance],Sec=(required)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0288-1]} @ChgDeleted{Version=[3],Text=[We considered requiring subtype conformance here, but mode conformance is more flexible, given that there is no way in general to specify the convention of the formal.]} @end{Reason} @end{Legality} @begin{Examples} @Leading@keepnext@i{Example of formal access types:} @begin{Example} --@RI{ the formal types of the generic package } @key[generic] @key[type] Node @key[is] @key[private]; @key[type] Link @key[is] @key[access] Node; @key[package] P @key[is] ... @key[end] P; --@RI{ can be matched by the actual types } @key[type] Car; @key[type] Car_Name @key[is] @key[access] Car; @key[type] Car @key[is] @key[record] Pred, Succ : Car_Name; Number : License_Number; Owner : Person; @key[end] @key[record]; --@RI{ in the following generic instantiation } @key[package] R @key[is] @key[new] P(Node => Car, Link => Car_Name); @end{Example} @end{Examples} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The check for matching of designated subtypes is changed from a run-time check to a compile-time check. The Ada 83 rule that @lquotes@;If the designated type is other than a scalar type, then the designated subtypes shall be either both constrained or both unconstrained@rquotes@; is removed, since it is subsumed by static matching. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Formal access-to-subprogram subtypes and formal general access types are new concepts. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00231-01]} @ChgAdded{Version=[2],Text=[Added a matching rule for subtypes that exclude null.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[We change to @lquotes@;determines a category@rquotes as that is the new terminology (it avoids confusion, since not all interesting properties form a class).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0288-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} @b<Correction:> Matching of formal access-to-subprogram types now uses subtype conformance rather than mode conformance, which is needed to plug a hole. This could cause some instantiations legal in Ada 95 and Ada 2005 to be rejected in Ada 2012. We believe that formal access-to-subprogram types occur rarely, and actuals that are not subtype conformant are rarer still, so this should not happen often. (In addition, one popular compiler has a bug that causes such instances to be rejected, so no code compiled with that compiler could have an incompatibility.)]} @end{Incompatible2005} @LabeledAddedSubClause{Version=[2],Name=[Formal Interface Types]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Redundant[The category determined for a formal interface type is the category of all interface types.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[This rule follows from the rule in @RefSecNum{Formal Types} that says that the category is determined by the one given in the name of the syntax production. The effect of the rule is repeated here to give a capsule summary of what this subclause is about.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Here we're taking advantage of our switch in terminology from @lquotes@;determined class@rquotes to @lquotes@;determined category@rquotes; by saying @lquotes@;category@rquotes rather than @lquotes@;class@rquotes, we require that any actual type be an interface type, not just some type derived from an interface type.]} @end{Ramification} @end{Intro} @begin{Syntax} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_interface_type_definition>,Old=<>}>, rhs="@Chg{Version=[2],New=<@Syn2{interface_type_definition}>,Old=<>}"} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251],ARef=[AI95-00401]} @ChgAdded{Version=[2],Text=[The actual type shall be a descendant of every progenitor of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345]} @ChgAdded{Version=[2],Text=[The actual type shall be a limited, task, protected, or synchronized interface if and only if the formal type is also, respectively, a limited, task, protected, or synchronized interface.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require the kind of interface type to match exactly because without that it is almost impossible to properly implement the interface.]} @end{Discussion} @end{Legality} @begin{Examples} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key{type} Root_Work_Item @key{is tagged private};]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Managed_Task @key{is task interface}; @key{type} Work_Item(<>) @key{is new} Root_Work_Item @key{with private}; @key{package} Server_Manager @key{is} @key{task type} Server @key{is new} Managed_Task @key{with} @key{entry} Start(Data : @key{in out} Work_Item); @key{end} Server; @key{end} Server_Manager;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Text=[This generic allows an application to establish a standard interface that all tasks need to implement so they can be managed appropriately by an application-specific scheduler.]} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01],ARef=[AI95-00345-01],ARef=[AI95-00401-01],ARef=[AI95-00442-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The formal interface type is new.]} @end{Extend95} @LabeledClause{Formal Subprograms} @begin{Intro} @redundant[@Defn{generic formal subprogram} @Defn{formal subprogram, generic} Formal subprograms can be used to pass callable entities to a generic unit.] @end{Intro} @begin{MetaRules} Generic formal subprograms are like renames of the @nt{explicit_generic_actual_parameter}. @end{MetaRules} @begin{Syntax} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} @Syn{lhs=<formal_subprogram_declaration>,rhs="@Chg{Version=[2], New=<@Syn2{formal_concrete_subprogram_declaration} | @Syn2{formal_abstract_subprogram_declaration}>, Old=<@key{with} @Syn2{subprogram_specification} [@key{is} @Syn2{subprogram_default}];>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_concrete_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< @key{with} @Syn2{subprogram_specification} [@key{is} @Syn2{subprogram_default}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_abstract_subprogram_declaration>,Old=<>}>, rhs="@Chg{Version=[2],New=< @key{with} @Syn2{subprogram_specification} @key{is abstract} [@Syn2{subprogram_default}]@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};>,Old=<>}"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00348-01]} @Syn{lhs=<subprogram_default>,rhs="@Syn2{default_name} | <>@Chg{Version=[2],New=< | @key{null}>,Old=<>}"} @Syn{lhs=<default_name>,rhs="@Syn2{name}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A @nt{subprogram_default} of @key{null} shall not be specified for a formal function or for a @nt{formal_abstract_subprogram_declaration}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no null functions because the return value has to be constructed somehow. We don't allow null for abstract formal procedures, as the operation is dispatching. It doesn't seem appropriate (or useful) to say that the implementation of something is null in the formal type and all possible descendants of that type. This also would define a dispatching operation that doesn't correspond to a slot in the tag of the controlling type, which would be a new concept. Finally, additional rules would be needed to define the meaning of a dispatching null procedure (for instance, the convention of such a subprogram should be intrinsic, but that's not what the language says). It doesn't seem worth the effort.]} @end{Reason} @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected profile], Sec=(formal subprogram default_name)} The expected profile for the @nt<default_name>, if any, is that of the formal subprogram. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This rule, unlike others in this @Chg{Version=[3],New=[subclause],Old=[clause]}, is observed at compile time of the @nt{generic_declaration}. The evaluation of the @nt{default_name} takes place during the elaboration of each instantiation that uses the default, as defined in @RefSec{Generic Instantiation}. @end{Ramification} @PDefn2{Term=[expected profile], Sec=(formal subprogram actual)} For a generic formal subprogram, the expected profile for the actual is that of the formal subprogram. @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The profiles of the formal and any named default shall be @Chg{Version=[3],New=[mode conformant],Old=[mode-conformant]}. @Defn2{Term=[mode conformance],Sec=(required)} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This rule, unlike others in this @Chg{Version=[3],New=[subclause],Old=[clause]}, is checked at compile time of the @nt{generic_declaration}. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0239-1]} The profiles of the formal and actual shall be @Chg{Version=[3],New=[mode conformant],Old=[mode-conformant]}. @Defn2{Term=[mode conformance],Sec=(required)} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a parameter or result subtype of a @nt{formal_subprogram_declaration} that has an explicit @nt{null_exclusion}:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[if the actual matching the @nt{formal_subprogram_declaration} denotes a generic formal object of another generic unit @i{G}, and the instantiation containing the actual that occurs within the body of a generic unit @i{G} or within the body of a generic unit declared within the declarative region of the generic unit @i{G}, then the corresponding parameter or result type of the formal subprogram of @i{G} shall have a @nt{null_exclusion};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[otherwise, the subtype of the corresponding parameter or result type of the actual matching the @nt{formal_subprogram_declaration} shall exclude null. @PDefn{generic contract issue} In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule prevents @lquotes@;lying@rquotes. @b<Null> must never be the value of a parameter or result with an explicit @nt{null_exclusion}. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child generics) when the formal subtype excludes null implicitly.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0296-1]} @ChgAdded{Version=[2],Text=[If a formal parameter of a @nt{formal_@!abstract_@!subprogram_@!declaration} is of a specific tagged type @i<T> or of an anonymous access type designating a specific tagged type @i<T>, @i<T> is called a @i<controlling type> of the @nt{formal_@!abstract_@!subprogram_@!declaration}. Similarly, if the result of a @nt{formal_@!abstract_@!subprogram_@!declaration} for a function is of a specific tagged type @i<T> or of an anonymous access type designating a specific tagged type @i<T>, @i<T> is called a controlling type of the @nt{formal_@!abstract_@!subprogram_@!declaration}. A @nt{formal_@!abstract_@!subprogram_@!declaration} shall have exactly one controlling type@Chg{Version=[3],New=[, and that type shall not be incomplete],Old=[]}. @Defn2{Term=[controlling type],Sec=[of a @nt{formal_abstract_subprogram_declaration}]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The specific tagged type could be any of a formal tagged private type, a formal derived type, a formal interface type, or a normal tagged type. While the last case doesn't seem to be very useful, there isn't any good reason for disallowing it. This rule ensures that the operation is a dispatching operation of some type, and that we unambiguously know what that type is.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We informally call a subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} an @i{abstract formal subprogram}, but we do not use this term in normative wording. @Defn{abstract formal subprogram} (We do use it often in these notes.)]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The actual subprogram for a @nt{formal_@!abstract_@!subprogram_@!declaration} shall be a dispatching operation of the controlling type or of the actual type corresponding to the controlling type.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We mean the controlling type of the @nt{formal_@!abstract_@!subprogram_@!declaration}, of course. Saying that gets unwieldy and redundant (so says at least one reviewer, anyway).]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This means that the actual is either a primitive operation of the controlling type, or an abstract formal subprogram. Also note that this prevents the controlling type from being class-wide (with one exception explained below), as only specific types have primitive operations (and a formal subprogram eventually has to have an actual that is a primitive of some type). This could happen in a case like:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} T(<>) @key{is tagged private}; @key{with procedure} Foo (Obj : @key{in} T) @key{is abstract}; @key{package} P ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} New_P @key{is new} P (Something'Class, Some_Proc);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The instantiation here is always illegal, because Some_Proc could never be a primitive operation of Something'Class (there are no such operations). That's good, because we want calls to Foo always to be dispatching calls.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Since it is possible for a formal tagged type to be instantiated with a class-wide type, it is possible for the (real) controlling type to be class-wide in one unusual case:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} NT(<>) @key{is new} T @key{with private}; -- @RI[Presume that T has the following primitive operation:] -- @key{with procedure} Bar (Obj : @key{in} T); @key{package} Gr ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package body} Gr @key{is} @key{package} New_P2 @key{is new} P (NT, Foo => Bar); @key{end} Gr;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} New_Gr @key{is new} Gr (Something'Class);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The instantiation of New_P2 is legal, since Bar is a dispatching operation of the actual type of the controlling type of the abstract formal subprogram Foo. This is not a problem, since the rules given in @RefSecNum{Formal Private and Derived Types} explain how this routine dispatches even though its parameter is class-wide.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that this legality rule never needs to be rechecked in an instance (that contains a nested instantiation). The rule only talks about the actual type of the instantiation; it does not require looking further; if the actual type is in fact a formal type, we do not intend looking at the actual for that formal.]} @end{Ramification} @end{Legality} @begin{StaticSem} A @nt{formal_subprogram_declaration} declares a generic formal subprogram. The types of the formal parameters and result, if any, of the formal subprogram are those determined by the @nt<subtype_mark>s given in the @nt{formal_subprogram_declaration}; however, independent of the particular subtypes that are denoted by the @nt<subtype_mark>s, the nominal subtypes of the formal parameters and result, if any, are defined to be nonstatic, and unconstrained if of an array type @Redundant[(no applicable index constraint is provided in a call on a formal subprogram)]. In an instance, a @nt{formal_subprogram_declaration} declares a view of the actual. The profile of this view takes its subtypes and calling convention from the original profile of the actual entity, while taking the formal parameter @nt{name}s and @nt{default_@!expression}s from the profile given in the @nt{formal_@!subprogram_@!declaration}. The view is a function or procedure, never an entry. @begin{Discussion} This rule is intended to be the same as the one for renamings-as-declarations, where the @nt{formal_subprogram_declaration} is analogous to a renaming-as-declaration, and the actual is analogous to the renamed view. @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0071-1],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If a @nt{subtype_mark} in the profile of the @nt{formal_subprogram_declaration} denotes a formal private or formal derived type and the actual type for this formal type is a class-wide type @i{T}'Class, then for the purposes of resolving the corresponding actual subprogram at the point of the instantiation, certain implicit declarations may be available as possible resolutions as follows:]} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[For each primitive subprogram of @i{T} that is directly visible at the point of the instantiation, and that has at least one controlling formal parameter, a corresponding implicitly declared subprogram with the same defining name, and having the same profile as the primitive subprogram except that @i{T} is systematically replaced by @i{T}'Class in the types of its profile, is potentially use-visible. The body of such a subprogram is as defined in @RefSecNum{Formal Private and Derived Types} for primitive subprograms of a formal type when the actual type is class-wide.@PDefn{potentially use-visible}]} @end{DescribeCode} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0071-1],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[This gives the same capabilities to formal subprograms as those that primitive operations of the formal type have when the actual type is class-wide. We do not want to discourage the use of explicit declarations for (formal) subprograms!]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0071-1],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[Although the above wording seems to require constructing implicit versions of all of the primitive subprograms of type @i{T}, it should be clear that a compiler only needs to consider those that could possibly resolve to the corresponding actual subprogram. For instance, if the formal subprogram is a procedure with two parameters, and the actual subprogram name is Bar (either given explicitly or by default), the compiler need not consider primitives that are functions, that have the wrong number of parameters, that have defining names other than Bar, and so on; thus it does not need to construct implicit declarations for those primitives.]} @end{ImplNote} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0071-1],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[Functions that only have a controlling result and do not have a controlling parameter of @i<T> are not covered by this rule, as any call would be required to raise Program_Error by @RefSecNum{Formal Private and Derived Types}. It is better to detect the error earlier than at run time.]} @end{Ramification} If a generic unit has a @nt<subprogram_default> specified by a box, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a usage name identical to the defining name of the formal. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[If a generic unit has a @nt{subprogram_default} specified by the reserved word @key{null}, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a null procedure having the profile given in the @nt{formal_@!subprogram_@!declaration}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} with a controlling type @i<T> is a dispatching operation of type @i<T>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is necessary to trigger all of the dispatching operation rules. It otherwise would not be considered a dispatching operation, as formal subprograms are never primitive operations.]} @end{Reason} @end{StaticSem} @begin{Notes} The matching rules for formal subprograms state requirements that are similar to those applying to @nt{subprogram_renaming_declaration}s (see @RefSecNum{Subprogram Renaming Declarations}). In particular, the name of a parameter of the formal subprogram need not be the same as that of the corresponding parameter of the actual subprogram; similarly, for these parameters, @nt{default_expression}s need not correspond. The constraints that apply to a parameter of a formal subprogram are those of the corresponding formal parameter of the matching actual subprogram (not those implied by the corresponding @nt{subtype_mark} in the @ntf{_specification} of the formal subprogram). A similar remark applies to the result of a function. Therefore, to avoid confusion, it is recommended that the @nt{name} of a first subtype be used in any declaration of a formal subprogram. The subtype specified for a formal parameter of a generic formal subprogram can be any visible subtype, including a generic formal subtype of the same @nt{generic_formal_part}. A formal subprogram is matched by an attribute of a type if the attribute is a function with a matching specification. An enumeration literal of a given type matches a parameterless formal function whose result type is the given type. A @nt{default_name} denotes an entity that is visible or directly visible at the place of the @nt{generic_declaration}; a box used as a default is equivalent to a name that denotes an entity that is directly visible at the place of the @ntf{_instantiation}. @begin{TheProof} Visibility and name resolution are applied to the equivalent explicit actual parameter. @end{TheProof} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00260-02]} The actual subprogram cannot be abstract@Chg{Version=[2],New=[ unless the formal subprogram is a @nt{formal_@!abstract_@!subprogram_@!declaration}], Old=[]} (see @RefSecNum{Abstract Types and Subprograms}). @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[The subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} is an abstract subprogram. All calls on a subprogram declared by a @nt{formal_@!abstract_@!subprogram_@!declaration} must be dispatching calls. See @RefSecNum{Abstract Types and Subprograms}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[A null procedure as a subprogram default has convention Intrinsic (see @RefSecNum{Conformance Rules}).]} @begin{TheProof} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This is an implicitly declared subprogram, so it has convention Intrinsic as defined in @RefSecNum{Conformance Rules}.]} @end{TheProof} @end{Notes} @begin{Examples} @Leading@Keepnext@i{Examples of generic formal subprograms:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00433-01]} @key[with] @key[function] "+"(X, Y : Item) @key[return] Item @key[is] <>; @key[with] @key[function] Image(X : Enum) @key[return] String @key[is] Enum'Image; @key[with] @key[procedure] Update @key[is] Default_Update;@Chg{Version=[2],New=[ @key[with] @key[procedure] Pre_Action(X : @key[in] Item) @key[is null]; --@RI[ defaults to no action] @key[with] @key[procedure] Write(S : @key[not null access] Root_Stream_Type'Class; Desc : Descriptor) @b<is abstract> Descriptor'Write; --@RI[ see @RefSecNum{Stream-Oriented Attributes}] --@RI[ Dispatching operation on Descriptor with default]],Old=[]} --@RI{ given the generic procedure declaration } @key[generic] @key[with] @key[procedure] Action (X : @key[in] Item); @key[procedure] Iterate(Seq : @key[in] Item_Sequence); --@RI{ and the procedure } @key[procedure] Put_Item(X : @key[in] Item); --@RI{ the following instantiation is possible } @key[procedure] Put_List @key[is] @key[new] Iterate(Action => Put_Item); @end{Example} @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00260-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The @nt{formal_abstract_subprogram_declaration} is new. It allows the passing of dispatching operations to generic units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00348-01]} @ChgAdded{Version=[2],Text=[ The formal subprogram default of @key{null} is new. It allows the default of a generic procedure to do nothing, such as for passing a debugging routine.]} @end{Extend95} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00423-01]} @ChgAdded{Version=[2],Text=[Added matching rules for @nt{null_exclusion}s.]} @end{Diffword95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0296-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}It is now illegal to declare a formal abstract subprogram whose controlling type is incomplete. It was never intended to allow that, and such a type would have to come from outside of the generic unit in Ada 2005, so it is unlikely to be useful. Moreover, a dispatching call on the subprogram is likely to fail in many implementations. So it is very unlikely that any code will need to be changed because of this new rule.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0071-1],ARef=[AI05-0131-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Added construction of implicit subprograms for primitives of class-wide actual types, to make it possible to import subprograms via formal subprograms as well as by implicit primitive operations of a formal type. (This is a @b<Correction> as it is very important for the usability of indefinite containers when instantiated with class-wide types; thus we want Ada 2005 implementations to support it.)]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[An optional @nt{aspect_specification} can be used in a @nt{formal_concrete_subprogram_declaration} and a @nt{formal_abstract_subprogram_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledClause{Formal Packages} @begin{Intro} @redundant[@Defn{generic formal package} @Defn{formal package, generic} Formal packages can be used to pass packages to a generic unit. The @nt{formal_package_declaration} declares that the formal package is an instance of a given generic package. Upon instantiation, the actual package has to be an instance of that generic package.] @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @Syn{lhs=<formal_package_declaration>,rhs=" @key{with} @key{package} @Syn2{defining_identifier} @key{is} @key{new} @SynI{generic_package_}@Syn2{name} @Syn2{formal_package_actual_part}@Chg{Version=[3],New=< [@Syn2{aspect_specification}]>,Old=[]};"} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @Syn{lhs=<formal_package_actual_part>,rhs=" @Chg{Version=[2],New=`([@key{others} =>] <>) | [@Syn2{generic_actual_part}] | (@Syn2{formal_package_association} {, @Syn2{formal_package_association}} [, @key{others} => <>])', Old=[(<>) | [@Syn2{generic_actual_part}]]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<formal_package_association>,Old=<>}>, rhs="@Chg{Version=[2],New={ @Syn2{generic_association} | @SynI{generic_formal_parameter_}@Syn2{selector_name} => <>},Old={}}"} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[Any positional @nt{formal_package_association}s shall precede any named @nt{formal_package_association}s.]} @end{SyntaxText} @end{Syntax} @begin{Legality} @Defn2{Term=[template], Sec=(for a formal package)} The @i(generic_package_)@nt<name> shall denote a generic package (the @i(template) for the formal package); the formal package is an instance of the template. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0025-1]} @ChgAdded{Version=[3],Text=[The @i(generic_formal_parameter_)@nt{selector_name} of a @nt{formal_package_association} shall denote a @nt{generic_formal_parameter_declaration} of the template. If two or more formal subprograms of the template have the same defining name, then named associations are not allowed for the corresponding actuals.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00398-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@Comment{Because this is renumbered by the above} @ChgAdded{Version=[2],Text=[A @nt<formal_package_actual_part> shall contain at most one @nt<formal_package_association> for each formal parameter. If the @nt<formal_package_actual_part> does not include @lquotes@key[others] => <>@rquotes, each formal parameter without an association shall have a @nt<default_expression> or @nt<subprogram_default>.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0200-1]} @ChgAdded{Version=[3],Text=[The rules for matching between @nt{formal_package_association}s and the generic formals of the template are as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If all of the @nt{formal_package_association}s are given by generic associations, the @nt{explicit_generic_actual_parameter}s of the @nt{formal_package_association}s shall be legal for an instantiation of the template.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[If a @nt{formal_package_association} for a formal type @i<T> of the template is given by <>, then the @nt{formal_package_association} for any other @nt{generic_formal_parameter_declaration} of the template that mentions @i<T> directly or indirectly must be given by <> as well.]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0200-1]} @ChgAdded{Version=[3],Text=[The above rule is simple to state, though it does not reflect the fact that the formal package functions like an instantiation of a special kind, where each box association for a @nt{generic_formal_parameter_declaration} @i<F> is replaced with a new entity @i<F>' that has the same characteristics as @i<F>: if @i<F> is a formal discrete type then @i<F>' is a discrete type, if @i<F> is a formal subprogram then @i<F>' is a subprogram with a similar signature, etc. In practice this is achieved by making the association into a copy of the declaration of the generic formal.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @Leading@;The actual shall be an instance of the template. If the @nt<formal_package_actual_part> is (<>)@Chg{Version=[2], New=[ or (@key{others} => <>)],Old=[]}, @Redundant[then the actual may be any instance of the template]; otherwise, @Chg{Version=[2],New=[certain of the actual parameters], Old=[each actual parameter]} of the actual instance shall match the corresponding actual @Chg{Version=[2],New=[parameters],Old=[parameter]} of the formal package@Chg{Version=[2],New=[, determined], Old=[ @Redundant[(whether the actual parameter is given explicitly or by default)],]} as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[If the @nt{formal_@!package_@!actual_@!part} includes @nt{generic_association}s as well as associations with <>, then only the actual parameters specified explicitly with @nt{generic_association}s are required to match;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[Otherwise, all actual parameters shall match@Redundant[, whether any actual parameter is given explicitly or by default].]} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The rules for matching of actual parameters between the actual instance and the formal package are as follows:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} For a formal object of mode @key[in]@Chg{Version=[2],New=[,],Old=[]} the actuals match if they are static expressions with the same value, or if they statically denote the same constant, or if they are both the literal @key[null]. @begin{Reason} We can't simply require full conformance between the two actual parameter expressions, because the two expressions are being evaluated at different times. @end{Reason} For a formal subtype, the actuals match if they denote statically matching subtypes. @PDefn2{Term=[statically matching],Sec=(required)} For other kinds of formals, the actuals match if they statically denote the same entity. @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0039],ARef=[AI95-00213-01]} @ChgAdded{Version=[1],Text=[For the purposes of matching, any actual parameter that is the name of a formal object of mode @key{in} is replaced by the formal object's actual expression (recursively).]} @end{Legality} @begin{StaticSem} A @nt{formal_package_declaration} declares a generic formal package. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} @PDefn2{Term=[visible part], Sec=(of a formal package)} The visible part of a formal package includes the first list of @nt{basic_declarative_item}s of the @nt{package_@!specification}. In addition, @Chg{Version=[2],New=[for each actual parameter that is not required to match, a copy of the declaration of the corresponding formal parameter of the template is included in the visible part of the formal package. If the copied declaration is for a formal type, copies of the implicit declarations of the primitive subprograms of the formal type are also included in the visible part of], Old=[if the @nt{formal_@!package_@!actual_@!part} is (<>), it also includes the @nt{generic_@!formal_@!part} of the template for]} the formal package. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00317-01]} If the @nt<formal_package_actual_part> is (<>), then the declarations that occur immediately within the @nt<generic_formal_part> of the template for the formal package are visible outside the formal package, and can be denoted by expanded names outside the formal package.@Chg{Version=[2],New=[If only some of the actual parameters are given by <>, then the declaration corresponding to those parameters (but not the others) are made visible.],Old=[]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} We always want either the actuals or the formals of an instance to be @Chg{Version=[3],New=[nameable],Old=[namable]} from outside, but never both. If both were @Chg{Version=[3],New=[nameable],Old=[namable]}, one would get some funny anomalies since they denote the same entity, but, in the case of types at least, they might have different and inconsistent sets of primitive operators due to predefined operator @lquotes@;reemergence.@rquotes@; Formal derived types exacerbate the difference. We want the implicit declarations of the @nt<generic_formal_part> as well as the explicit declarations, so we get operations on the formal types. @end{Reason} @begin{Ramification} A generic formal package is a package, and is an instance. Hence, it is possible to pass a generic formal package as an actual to another generic formal package. @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[ For the purposes of matching, if the actual instance @i<A> is itself a formal package, then the actual parameters of @i<A> are those specified explicitly or implicitly in the @nt{formal_package_actual_part} for @i<A>, plus, for those not specified, the copies of the formal parameters of the template included in the visible part of @i<A>.]} @end{StaticSem} @begin{Examples} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@i{Example of a generic package with formal package parameters:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Containers.Ordered_Maps; --@RI[ see @RefSecNum{The Generic Package Containers.Ordered_Maps}] @key[generic] @key[with package] Mapping_1 @key[is new] Ada.Containers.Ordered_Maps(<>); @key[with package] Mapping_2 @key[is new] Ada.Containers.Ordered_Maps (Key_Type => Mapping_1.Element_Type, @key[others] => <>); @key[package] Ordered_Join @key[is] --@RI[ Provide a "join" between two mappings]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[subtype] Key_Type @key[is] Mapping_1.Key_Type; @key[subtype] Element_Type @key[is] Mapping_2.Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] Lookup(Key : Key_Type) @key[return] Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key[end] Ordered_Join;]} @end{Example} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00433-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@i{Example of an instantiation of a package with formal packages:}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Containers.Ordered_Maps; @key[package] Symbol_Package @key[is]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[type] String_Id @key[is] ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[type] Symbol_Info @key[is] ...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] String_Table @key[is new] Ada.Containers.Ordered_Maps (Key_Type => String, Element_Type => String_Id);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] Symbol_Table @key[is new] Ada.Containers.Ordered_Maps (Key_Type => String_Id, Element_Type => Symbol_Info);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[package] String_Info @key[is new] Ordered_Join(Mapping_1 => String_Table, Mapping_2 => Symbol_Table);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Apple_Info : @key[constant] Symbol_Info := String_Info.Lookup("Apple");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[end] Symbol_Package;]} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Formal packages are new to Ada 95. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01],ARef=[AI95-00398-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} It's now allowed to mix actuals of a formal package that are specified with those that are not specified.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0039],ARef=[AI95-00213-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the description of formal package matching to say that formal parameters are always replaced by their actual parameters (recursively). This matches the actual practice of compilers, as the ACATS has always required this behavior.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00317-01]} @ChgAdded{Version=[2],Text=[The description of which operations are visible in a formal package has been clarified. We also specify how matching is done when the actual is a formal package.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0025-1],ARef=[AI05-0200-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added missing rules for parameters of generic formal package that parallel those in @RefSecNum{Generic Instantiation}, as well as some specific to <> parameters. These are technically incompatibilities because generic formal package parameters that Ada 95 and Ada 2005 would have considered legal now have to be rejected. But this should not be an issue in practice as such formal parameters could not have matched any actual generics. And it is quite likely that implementations already enforce some of these rules.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} An optional @nt{aspect_specification} can be used in a @nt{formal_package_declaration}. This is described in @RefSecNum{Aspect Specifications}.]} @end{Extend2005} @LabeledClause{Example of a Generic Package} @begin{Intro} The following example provides a possible formulation of stacks by means of a generic package. The size of each stack and the type of the stack elements are provided as generic formal parameters. @end{Intro} @begin{Examples} @Leading @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Example} @key[generic] Size : Positive; @key[type] Item @key[is] @key[private]; @key[package] Stack @key[is] @key[procedure] Push(E : @key[in] Item); @key[procedure] Pop (E : @key[out] Item); Overflow, Underflow : @key[exception]; @key[end] Stack; @key[package] @key[body] Stack @key[is] @key[type] Table @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; Space : Table(1 .. Size); Index : Natural := 0; @key[procedure] Push(E : @key[in] Item) @key[is] @key[begin] @key[if] Index >= Size @key[then] @key[raise] Overflow; @key[end] @key[if]; Index := Index + 1; Space(Index) := E; @key[end] Push; @key[procedure] Pop(E : @key[out] Item) @key[is] @key[begin] @key[if] Index = 0 @key[then] @key[raise] Underflow; @key[end] @key[if]; E := Space(Index); Index := Index - 1; @key[end] Pop; @key[end] Stack; @end{Example} @begin{WideAbove} @Leading@Keepnext@;Instances of this generic package can be obtained as follows: @end{WideAbove} @begin{Example} @key[package] Stack_Int @key[is] @key[new] Stack(Size => 200, Item => Integer); @key[package] Stack_Bool @key[is] @key[new] Stack(100, Boolean); @end{Example} @begin{WideAbove} @Leading@Keepnext@;Thereafter, the procedures of the instantiated packages can be called as follows: @end{WideAbove} @begin{Example} Stack_Int.Push(N); Stack_Bool.Push(True); @end{Example} @begin{WideAbove} @Leading@Keepnext@;Alternatively, a generic formulation of the type Stack can be given as follows (package body omitted): @end{WideAbove} @begin{Example} @key[generic] @key[type] Item @key[is] @key[private]; @key[package] On_Stacks @key[is] @key[type] Stack(Size : Positive) @key[is] @key[limited] @key[private]; @key[procedure] Push(S : @key[in] @key[out] Stack; E : @key[in] Item); @key[procedure] Pop (S : @key[in] @key[out] Stack; E : @key[out] Item); Overflow, Underflow : @key[exception]; @key[private] @key[type] Table @key[is] @key[array] (Positive @key[range] <>) @key[of] Item; @key[type] Stack(Size : Positive) @key[is] @key[record] Space : Table(1 .. Size); Index : Natural := 0; @key[end] @key[record]; @key[end] On_Stacks; @end{Example} @begin{WideAbove} @Leading@Keepnext@;In order to use such a package, an instance has to be created and thereafter stacks of the corresponding type can be declared: @end{WideAbove} @begin{Example} @key[declare] @key[package] Stack_Real @key[is] @key[new] On_Stacks(Real); @key[use] Stack_Real; S : Stack(100); @key[begin] ... Push(S, 2.54); ... @key[end]; @end{Example} @end{Examples} ��������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/13a.mss��������������������������������������������������������������0000755�0001752�0001001�00000657627�12066652506�016564� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(13, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @LabeledSection{Representation Issues} @Comment{$Source: e:\\cvsroot/ARM/Source/13a.mss,v $} @Comment{$Revision: 1.107 $} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[This @Chg{Version=[3],New=[clause],Old=[section]} describes features for querying and controlling @Chg{New=[certain aspects of entities], Old=[aspects of representation]} and for interfacing to hardware.] @end{Intro} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The @Chg{Version=[3],New=[subclauses],Old=[clauses]} of this @Chg{Version=[3],New=[clause],Old=[section]} have been reorganized. This was necessary to preserve a logical order, given the new Ada 95 semantics given in this section. @end{DiffWord83} @LabeledRevisedClause{Version=[3],New=[Operational and Representation Aspects],Old=[Representation Items]} @Comment{@LabeledRevisedClause{Version=[1],New=[Operational and Representation Items],Old=[Representation Items]} Don't have a way to include the middle title} @begin{Intro} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0295-1]} @ChgAdded{Version=[1],Text=[@Redundant[@Chg{Version=[3],New=[@Defn{aspect}], Old=[Representation and operational items can be used to specify aspects of entities. ]}Two kinds of aspects of entities can be specified: @Chg{Version=[3],New=[],Old=[aspects of ]}representation@Chg{Version=[3], New=[ aspects],Old=[]} and operational aspects. Representation @Chg{Version=[3],New=[aspects affect],Old=[items specify]} how the types and other entities of the language are to be mapped onto the underlying machine. Operational @Chg{Version=[3],New=[aspects determine], Old=[items specify]} other properties of entities.]]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1],ARef=[AI05-0295-1]} @ChgAdded{Version=[1],Text=[@Redundant[Either kind of aspect of an entity may be specified by means of an @nt{aspect_specification} (see @RefSecNum{Aspect Specifications}), which is an optional element of most kinds of declarations and applies to the entity or entities being declared. Aspects may also be specified by certain other constructs occurring subsequent to the declaration of the affected entity: a representation aspect value may be specified by means of a representation item and an operational aspect value may be specified by means of an operational item.]]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Defn{representation item} @RootDefn{representation pragma} @RootDefn{pragma, representation} There are @Chg{New=[six],Old=[three]} kinds of @i{representation items}: @Chg{New=[@nt{attribute_@!definition_@!clause}s for representation attributes, @nt{enumeration_@!representation_@!clause}s, @nt{record_@!representation_@!clause}s, @nt{at_clause}s, ], Old=[@nt{representation_@!clause}s, ]}@nt<component_clause>s, and @i{representation pragmas}. @Redundant[@Chg{New=[],Old=[Representation items specify how the types and other entities of the language are to be mapped onto the underlying machine.]} They can be provided to give more efficient representation or to interface with features that are outside the domain of the language (for example, peripheral hardware). @Chg{New=[],Old=[Representation items also specify other specifiable properties of entities. A representation item applies to an entity identified by a @nt<local_name>, which denotes an entity declared local to the current declarative region, or a library unit declared immediately preceding a representation pragma in a @nt<compilation>.]}] @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[An @Defn{operational item}@i<operational item> is an @nt<attribute_definition_clause> for an operational attribute.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[@Redundant[An operational item or a representation item applies to an entity identified by a @nt<local_name>, which denotes an entity declared local to the current declarative region, or a library unit declared immediately preceding a representation pragma in a @nt<compilation>.]]} @end{Intro} @begin{Metarules} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[1],Text=[@Chg{Version=[3],New=[Representation aspects],Old=[Aspects of representation]} are intended to refer to properties that need to be known before the compiler can generate code to create or access an entity. For instance, the size of an object needs to be known before the object can be created. Conversely, operational aspects are those that only need to be known before they can be used. For instance, how an object is read from a stream only needs to be known when a stream read is executed. Thus, @Chg{Version=[3],New=[],Old=[aspects of ]}representation@Chg{Version=[3], New=[ aspects],Old=[]} have stricter rules as to when they can be specified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[Confirming the value of an aspect @Chg{Version=[3],New=[],Old=[with an operational or representation item ]}should never change the semantics of the aspect. Thus Size = 8 (for example) means the same thing whether it was specified with a representation item or whether the compiler chose this value by default.]} @end{Metarules} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Aspect>, Text=<@ChgAdded{Version=[3],Text=[An aspect is a specifiable property of an entity. An aspect may be specified by an @nt{aspect_specification} on the declaration of the entity. Some aspects may be queried via attributes.]}>} @begin{Syntax} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Syn{lhs=<@Chg{New=[aspect_clause],Old=[representation_clause]}>,rhs="@Syn2{attribute_definition_clause} | @Syn2{enumeration_representation_clause} | @Syn2{record_representation_clause} | @Syn2{at_clause}"} @Syn{lhs=<local_name>,rhs="@Syn2{direct_name} | @Syn2{direct_name}@SingleQuote@Syn2{attribute_designator} | @SynI{library_unit_}@Syn2{name}"} @begin{SyntaxText} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} A representation pragma is allowed only at places where @Chg{New=[an @nt{aspect_clause}],Old=[a @nt{representation_clause}]} or @nt{compilation_unit} is allowed. @Chg{New=[@IndexSee(Term=(representation_clause),See=(aspect_clause))],Old=[]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} In @Chg{New=[an operational item or],Old=[a]} representation item, if the @nt<local_name> is a @nt<direct_name>, then it shall resolve to denote a declaration (or, in the case of a @nt{pragma}, one or more declarations) that occurs immediately within the same declarative region as the @Chg{New=[],Old=[representation ]}item. If the @nt<local_name> has an @nt<attribute_designator>, then it shall resolve to denote an implementation-defined component (see @RefSecNum{Record Representation Clauses}) or a class-wide type implicitly declared immediately within the same declarative region as the @Chg{New=[],Old=[representation ]}item. A @nt<local_name> that is a @i{library_unit_}@nt<name> (only permitted in a representation pragma) shall resolve to denote the @nt<library_item> that immediately precedes (except for other pragmas) the representation pragma. @begin{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} This is a @ResolutionName, because we don't want @Chg{New=[an operational or],Old=[a]} representation item for X to be ambiguous just because there's another X declared in an outer declarative region. It doesn't make much difference, since most @Chg{New=[operational or ],Old=[]}representation items are for types or subtypes, and type and subtype names can't be overloaded. @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The visibility rules imply that the declaration has to occur before the @Chg{New=[operational or ],Old=[]}representation item. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} For objects, this implies that @Chg{New=[operational or ],Old=[]}representation items can be applied only to stand-alone objects. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The @nt{local_name} of @Chg{New=[an @nt<aspect_clause>], Old=[a @nt<representation_clause>]} or representation pragma shall statically denote an entity (or, in the case of a @nt{pragma}, one or more entities) declared immediately preceding it in a @nt<compilation>, or within the same @nt{declarative_@!part}, @nt{package_@!specification}, @nt{task_@!definition}, @nt{protected_@!definition}, or @nt{record_@!definition} as the representation @Chg{New=[or operational ],Old=[]}item. If a @nt<local_name> denotes a @Redundant[local] callable entity, it may do so through a @Redundant[local] @nt<subprogram_@!renaming_@!declaration> @Redundant[(as a way to resolve ambiguity in the presence of overloading)]; otherwise, the @nt<local_name> shall not denote a @nt<renaming_@!declaration>. @begin{Ramification} The @lquotes@;statically denote@rquotes@; part implies that it is impossible to specify the representation of an object that is not a stand-alone object, except in the case of a representation item like pragma Atomic that is allowed inside a @nt{component_list} (in which case the representation item specifies the representation of components of all objects of the type). It also prevents the problem of renamings of things like @lquotes@;P.@key[all]@rquotes@; (where P is an access-to-subprogram value) or @lquotes@;E(I)@rquotes@; (where E is an entry family). The part about where the denoted entity has to have been declared appears twice @em once as a @ResolutionName, and once as a @LegalityName. Suppose P renames Q, and we have a representation item in a @nt{declarative_part} whose @nt<local_name> is P. The fact that the representation item has to appear in the same @nt{declarative_part} as P is a @ResolutionName, whereas the fact that the representation item has to appear in the same @nt{declarative_part} as Q is a @LegalityName. This is subtle, but it seems like the least confusing set of rules. @end{Ramification} @begin{Discussion} A separate @LegalityName applies for @nt<component_clause>s. See @RefSec{Record Representation Clauses}. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Defn{representation of an object} @Defn2{Term=[size], Sec=(of an object)}The @i{representation} of an object consists of a certain number of bits (the @i(size) of the object). @Chg{Version=[2],New=[For an object of an elementary type, these],Old=[These]} are the bits that are normally read or updated by the machine code when loading, storing, or operating-on the value of the object. @Chg{Version=[2],New=[For an object of a composite type, these are the bits reserved for this object, and include bits occupied by subcomponents of the object. If],Old=[This includes some padding bits, when]} the size of @Chg{Version=[2],New=[an],Old=[the]} object is greater than @Chg{Version=[2],New=[that],Old=[the size]} of its subtype@Chg{Version=[2], New=[, the additional bits are padding bits.],Old=[. @Defn{gaps}]} @Defn{padding bits} @Chg{Version=[2],New=[For an elementary object, these],Old=[Such]} padding bits @Chg{Version=[2],New=[],Old=[are considered to be part of the representation of the object, rather than being gaps between objects, if these bits ]}are normally read and updated@Chg{Version=[2],New=[ along with the others. For a composite object, padding bits might not be read or updated in any given composite operation, depending on the implementation],Old=[]}. @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @PDefn{contiguous representation} @PDefn{discontiguous representation} Discontiguous representations are allowed, but the ones we're interested in here are generally contiguous sequences of bits.@Chg{Version=[2],New=[ For a discontiguous representation, the size doesn't necessarily describe the @lquotes@;footprint@rquotes of the object in memory (that is, the amount of space taken in the address space for the object).],Old=[]} @end{Honest} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[In the case of composite objects, we want the implementation to have the flexibility to either do operations component-by-component, or with a block operation covering all of the bits. We carefully avoid giving a preference in the wording. There is no requirement for the choice to be documented, either, as the implementation can make that choice based on many factors, and could make a different choice for different operations on the same object.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[In the case of a properly aligned, contiguous object whose size is a multiple of the storage unit size, no other bits should be read or updated as part of operating on the object. We don't say this normatively because it would be difficult to normatively define @lquotes@;properly aligned@rquotes or @lquotes@;contiguous@rquotes.]} @end{Discussion} @begin{Ramification} @Leading@;Two objects with the same value do not necessarily have the same representation. For example, an implementation might represent False as zero and True as any odd value. Similarly, two objects (of the same type) with the same sequence of bits do not necessarily have the same value. For example, an implementation might use a biased representation in some cases but not others: @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[subtype] S @key[is] Integer @key[range] 1..256; @key[type] A @key[is] @key[array](Natural @key[range] 1..4) @key[of] S@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(A)]}; X : S := 3; Y : A := (1, 2, 3, 4); @end{Example} The implementation might use a biased-by-1 representation for the array elements, but not for X. X and Y(3) have the same value, but different representation: the representation of X is a sequence of (say) 32 bits: 0...011, whereas the representation of Y(3) is a sequence of 8 bits: 00000010 (assuming a two's complement representation). Such tricks are not required, but are allowed. @end{Ramification} @begin{Discussion} The value of any padding bits is not specified by the language, though for a numeric type, it will be much harder to properly implement the predefined operations if the padding bits are not either all zero, or a sign extension. @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For example, suppose S'Size = 2, and an object X is of subtype S. If the machine code typically uses a 32-bit load instruction to load the value of X, then X'Size should be 32, even though 30 bits of the value are just zeros or sign-extension bits. On the other hand, if the machine code typically masks out those 30 bits, then X'Size should be 2. Usually, such masking only happens for components of a composite type for which @Chg{Version=[3],New=[Pack],Old=[packing]}, Component_Size, or record layout is specified. Note, however, that the formal parameter of an instance of Unchecked_Conversion is a special case. Its Size is required to be the same as that of its subtype. Note that we don't generally talk about the representation of a value. A value is considered to be an amorphous blob without any particular representation. An object is considered to be more concrete. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0112-1],ARef=[AI05-0295-1]} @RootDefn{aspect of representation} @Defn{representation aspect} @Chg{Version=[3],New=[@Defn2{Term=[directly specified], Sec=(of a representation aspect of an entity)}], Old=[@Defn2{Term=[directly specified], Sec=(of an aspect of representation of an entity)}]} A representation item @i{directly specifies} @Chg{Version=[3],New=[a @i{representation aspect}], Old=[an @i{aspect of representation}]} of the entity denoted by the @nt{local_name}, except in the case of a type-related representation item, whose @nt{local_name} shall denote a first subtype, and which directly specifies an aspect of the subtype's type. @RootDefn2{Term=[type-related], Sec=(representation item)} @RootDefn2{term=[subtype-specific], Sec=(of a representation item)} @RootDefn2{Term=[type-related], Sec=(aspect)} @RootDefn2{term=[subtype-specific], Sec=(of an aspect)} A representation item that names a subtype is either @i(subtype-specific) (Size and Alignment clauses) or @i{type-related} (all others). @Redundant[Subtype-specific aspects may differ for different subtypes of the same type.] @begin{Honest} @i{Type-related} and @i{subtype-specific} are defined likewise for the corresponding aspects of representation. @end{Honest} @begin{Honest} Some representation items directly specify more than one aspect. @end{Honest} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For example, a @nt{pragma} Export @Chg{Version=[3],New=[(see @RefSecNum{Interfacing Pragmas}) ],Old=[]}specifies the convention of an entity, and also specifies that it is exported.@Chg{Version=[3],New=[ Such items are obsolescent; directly specifying the associated aspects is preferred.],Old=[]} @end{Discussion} @begin{Ramification} Each specifiable attribute constitutes a separate aspect. An @nt{enumeration_representation_clause} specifies the coding aspect. A @nt{record_representation_clause} (without the @nt{mod_clause}) specifies the record layout aspect. Each representation pragma specifies a separate aspect. @end{Ramification} @begin{Reason} We don't need to say that an @nt{at_clause} or a @nt{mod_clause} specify separate aspects, because these are equivalent to @nt{attribute_definition_clause}s. See @RefSec{At Clauses}, and @RefSec{Mod Clauses}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0112-1]} @ChgAdded{Version=[3],Text=[We give a default naming for representation aspects of representation pragmas so we don't have to do that for every pragma. Operational and representation attributes are given a default naming in @RefSecNum{Operational and Representation Attributes}. We don't want any anonymous aspects; that would make other rules more difficult to write and understand.]} @end{Reason} @begin{Ramification} @Leading@;The following representation items are type-related: @begin{Itemize} @nt{enumeration_representation_clause} @nt{record_representation_clause} Component_Size clause @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[External_Tag clause]} Small clause Bit_Order clause Storage_Pool clause Storage_Size clause @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[Stream_Size clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Read clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Write clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Input clause]} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgDeleted{Version=[1],Text=[Output clause]} Machine_Radix clause pragma Pack pragmas Import, Export, and Convention (when applied to a type) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} pragmas Atomic@Chg{Version=[3],New=[, Independent,],Old=[]} and Volatile (when applied to a type) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} pragmas Atomic_Components@Chg{Version=[3],New=[, Independent_Components,],Old=[]} and Volatile_Components (when applied to @Chg{Version=[3],New=[a],Old=[an array]} type) pragma Discard_Names (when applied to an enumeration or tagged type) @end{Itemize} @Leading@;The following representation items are subtype-specific: @begin{Itemize} Alignment clause (when applied to a first subtype) Size clause (when applied to a first subtype) @end{Itemize} @Leading@;The following representation items do not apply to subtypes, so they are neither type-related nor subtype-specific: @begin{Itemize} Address clause (applies to objects and program units) Alignment clause (when applied to an object) Size clause (when applied to an object) pragmas Import, Export, and Convention (when applied to anything other than a type) pragmas Atomic and Volatile (when applied to an object or a component) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} pragmas Atomic_Components@Chg{Version=[3],New=[, Independent_Components,],Old=[]} and Volatile_Components (when applied to an array object) pragma Discard_Names (when applied to an exception) pragma Asynchronous (applies to procedures) @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00414-01]} @ChgAdded{Version=[2],Text=[pragma No_Return (applies to subprograms)]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[While an @nt{aspect_specification} is not a representation item, a similar categorization applies to the aspect that corresponds to each of these representation items (along with aspects that do not have associated representation items).]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @ChgAdded{Version=[1],Text=[An operational item @i<directly specifies> an @i<operational aspect> of the @Chg{Version=[3],New=[entity],Old=[type of the subtype]} denoted by the @nt{local_name}@Chg{Version=[3],New=[, except in the case of a type-related operational item, whose @nt{local_name} shall denote a first subtype, and which directly specifies an aspect of the type of the subtype],Old=[. The @nt{local_name} of an operational item shall denote a first subtype. An operational item that names a subtype is type-related]}. @RootDefn{operational aspect} @Defn2{Term=[directly specified], Sec=(of an operational aspect of an entity)} @RootDefn2{Term=[type-related], Sec=(operational item)} @PDefn2{Term=[type-related], Sec=(aspect)}]} @begin{Ramification} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[The following operational items are type-related:]} @begin{Itemize} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[External_Tag clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Read clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Write clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Input clause]} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Output clause]} @end{Itemize} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} A representation item that directly specifies an aspect of a subtype or type shall appear after the type is completely defined (see @RefSecNum{Completions of Declarations}), and before the subtype or type is frozen (see @RefSecNum{Freezing Rules}). If a representation item @Chg{Version=[3],New=[or @nt{aspect_specification} ],Old=[]}is given that directly specifies an aspect of an entity, then it is illegal to give another representation item @Chg{Version=[3],New=[or @nt{aspect_specification} ],Old=[]}that directly specifies the same aspect of the entity. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The fact that a representation item @Chg{New=[(or operational item, see next paragraph) ],Old=[]}that directly specifies an aspect of an entity is required to appear before the entity is frozen prevents changing the representation of an entity after using the entity in ways that require the representation to be known. @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[The rule preventing multiple specification is also intended to cover other ways to specify representation aspects, such as obsolescent @nt{pragma} Priority. Priority is not a representation pragma, and as such is neither a representation item nor an @nt{aspect_specification}. Regardless, giving both a @nt{pragma} Priority and an @nt{aspect_specification} for Priority is illegal. We didn't want to complicate the wording solely to support obsolescent features.]} @end{Honest} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @ChgAdded{Version=[1],Text=[An operational item that directly specifies an aspect of @Chg{Version=[3],New=[an entity],Old=[a type]} shall appear before the @Chg{Version=[3],New=[entity],Old=[type]} is frozen (see @RefSecNum{Freezing Rules}). If an operational item @Chg{Version=[3],New=[or @nt{aspect_specification} ],Old=[]}is given that directly specifies an aspect of @Chg{Version=[3],New=[an entity],Old=[a type]}, then it is illegal to give another operational item @Chg{Version=[3],New=[or @nt{aspect_specification} ],Old=[]}that directly specifies the same aspect of the @Chg{Version=[3],New=[entity],Old=[type]}.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[AddedNormal]} @ChgAdded{Version=[1],Text=[Unlike representation items, operational items can be specified on partial views. Since they don't affect the representation, the full declaration need not be known to determine their legality.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0106-1],ARef=[AI05-0295-1]} @ChgAdded{Version=[3],Text=[Unless otherwise specified, it is illegal to specify an operational or representation aspect of a generic formal parameter.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Specifying an aspect on a generic formal parameter implies an added contract for a generic unit. That contract needs to be defined via generic parameter matching rules, and, as aspects vary widely, that has to be done for each such aspect. Since most aspects do not need this complexity (including all language-defined aspects as of this writing), we avoid the complexity by saying that such contract-forming aspect specifications are banned unless the rules defining them explicitly exist. Note that the method of specification does not matter: @nt{aspect_specification}s, representation items, and operational items are all covered by this (and similar) rules.]} @end{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} For an untagged derived type, @Chg{Version=[3],New=[it is illegal to specify a],Old=[no]} type-related representation @Chg{Version=[3],New=[aspect],Old=[items are allowed]} if the parent type is a by-reference type, or has any user-defined primitive subprograms. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} On the other hand, subtype-specific representation @Chg{Version=[3],New=[aspects],Old=[items]} may be @Chg{Version=[3],New=[specified],Old=[given]} for the first subtype of such a type@Chg{New=[, as can operational @Chg{Version=[3],New=[aspects],Old=[items]}],Old=[]}. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0295-1]} The reason for forbidding @Chg{Version=[3],New=[specification of ],Old=[]}type-related representation @Chg{Version=[3],New=[aspects],Old=[items]} on untagged by-reference types is because a change of representation is impossible when passing by reference (to an inherited subprogram). The reason for forbidding @Chg{Version=[3],New=[specification of ],Old=[]}type-related representation @Chg{Version=[3],New=[aspects],Old=[items]} on untagged types with user-defined primitive subprograms was to prevent implicit change of representation for type-related aspects of representation upon calling inherited subprograms, because such changes of representation are likely to be expensive at run time. Changes of subtype-specific representation attributes, however, are likely to be cheap. This rule is not needed for tagged types, because other rules prevent a type-related representation @Chg{Version=[3],New=[aspect],Old=[item]} from changing the representation of the parent part; we want to allow @Chg{Version=[3],New=[specifying ],Old=[]}a type-related representation @Chg{Version=[3],New=[aspect],Old=[item]} on a type extension to specify aspects of the extension part. For example, @Chg{Version=[3],New=[specifying aspect],Old=[a @nt{pragma}]} Pack will cause packing of the extension part, but not of the parent part. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01],Ref=[8652/0011],ARef=[AI95-00117-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @Chg{New=[Operational and representation],Old=[Representation]} aspects of a generic formal parameter are the same as those of the actual. @Chg{New=[Operational and representation aspects @Chg{Version=[2],New=[],Old=[of a partial view ]}are the same @Chg{Version=[2],New=[for all views of a type],Old=[as those of the full view]}.],Old=[]} @Chg{Version=[3],New=[Specification of a],Old=[A]} type-related representation @Chg{Version=[3],New=[aspect],Old=[item]} is not allowed for a descendant of a generic formal untagged type. @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @Chg{Version=[3],New=[Specifying representation aspects is],Old=[Representation items are]} allowed for types whose subcomponent types or index subtypes are generic formal types. @Chg{New=[@Chg{Version=[3],New=[Specifying operational aspects],Old=[Operational items]} and subtype-related representation @Chg{Version=[3],New=[aspects is],Old=[items are]} allowed on descendants of generic formal types.],Old=[]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} Since it is not known whether a formal type has user-defined primitive subprograms, specifying type-related representation @Chg{Version=[3],New=[aspects],Old=[items]} for them is not allowed, unless they are tagged (in which case only the extension part is affected in any case). @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[All views of a type, including the incomplete and partial views, have the same operational and representation aspects. That's important so that the properties don't change when changing views. While most aspects are not available for an incomplete view, we don't want to leave any holes by not saying that they are the same.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0083-1]} @ChgAdded{Version=[3],Text=[However, this does not apply to objects. Different views of an object can have different representation aspects. For instance, an actual object passed by reference and the associated formal parameter may have different values for Alignment even though the formal parameter is merely a view of the actual object. This is necessary to maintain the language design principle that Alignments are always known at compile time.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @Chg{Version=[3],New=[The specification of],Old=[A representation item that specifies]} the Size@Chg{Version=[3],New=[ aspect],Old=[]} for a given subtype, or the size or storage place for an object (including a component) of a given subtype, shall allow for enough storage space to accommodate any value of the subtype. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @Chg{Version=[3],New=[If a specification of a],Old=[A]} representation @Chg{New=[or operational ],Old=[]}@Chg{Version=[3],New=[aspect], Old=[item that]} is not supported by the implementation@Chg{Version=[3],New=[, it ],Old=[]}is illegal@Chg{Version=[3],New=[],Old=[,]} or raises an exception at run time. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[A @nt{type_declaration} is illegal if it has one or more progenitors, and a @Chg{Version=[3],New=[nonconfirming value was specified for a ],Old=[]}representation @Chg{Version=[3],New=[aspect of],Old=[item applies to]} an ancestor, and this@Chg{Version=[3],New=[],Old=[ representation item]} conflicts with the representation of some other ancestor. The cases that cause conflicts are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The cases that cause conflicts between the representation of the ancestors of a @nt{type_declaration}.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[This rule is needed because it may be the case that only the combination of types in a type declaration causes a conflict. Thus it is not possible, in general, to reject the original representation item@Chg{Version=[3],New=[ or @nt{aspect_specification}],Old=[]}. For instance:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Pkg1 @key{is} @key{type} Ifc @key{is interface}; @key{type} T @key{is tagged record} Fld : Integer; @key{end record}; @key{for} T @key{use record} Fld @key{at} 0 @key{range} 0 .. Integer'Size - 1; @key{end record}; @key{end} Pkg1;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Assume the implementation uses a single tag with a default offset of zero, and that it allows the use of nondefault locations for the tag (and thus accepts representation items like the one above). The representation item will force a nondefault location for the tag (by putting a component other than the tag into the default location). Clearly, this package will be accepted by the implementation. However, other declarations could cause trouble. For instance, the implementation could reject:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Pkg1; @key{package} Pkg2 @key{is} @key{type} NewT @key{is new} Pkg1.T @key{and} Pkg1.Ifc @key{with null record}; @key{end} Pkg2;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[because the declarations of T and Ifc have a conflict in their representation items. This is clearly necessary (it's hard to imagine how Ifc'Class could work with the tag at a location other than the one it is expecting@Chg{Version=[3],New=[ without introducing distributed overhead],Old=[]}).]}@Comment{Make Steve happy.} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[Conflicts will usually involve implementation-defined attributes (for specifying the location of the tag, for instance), although the example above shows that doesn't have to be the case. For this reason, we didn't try to specify exactly what causes a conflict; it will depend on the implementation's implementation model and what representation @Chg{Version=[3],New=[aspects],Old=[items]} it allows@Chg{Version=[3],New=[ to be changed],Old=[]}.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[An implementation can only use this rule to reject @nt{type_declaration}s where one of its ancestors @Chg{Version=[3],New=[had a nonconfirming],Old=[has a]} representation @Chg{Version=[3],New=[value specified],Old=[item]}. An implementation must ensure that the default representations of ancestors cannot conflict.]} @end{ImplNote} @end{Legality} @begin{StaticSem} If two subtypes statically match, then their subtype-specific aspects (Size and Alignment) are the same. @PDefn2{Term=[statically matching],Sec=(effect on subtype-specific aspects)} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} This is necessary because we allow (for example) conversion between access types whose designated subtypes statically match. Note that @Chg{Version=[3],New=[most aspects (including the subtype-specific aspects Size and Alignment) may not be specified for a nonfirst subtype. The only language-defined exceptions to this rule are the Static_Predicate and Dynamic_Predicate aspects.],Old=[it is illegal to specify an aspect (including a subtype-specific one) for a nonfirst subtype.]} @Leading@Keepnext@;Consider, for example: @begin{Example} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] P1 @key[is] @key[subtype] S1 @key[is] Integer @key[range] 0..2**16-1; @key[for] S1'Size @key[use] 16; --@RI{ Illegal!} --@RI{ S1'Size would be 16 by default.} @key[type] A1 @key[is] @key[access] @Chg{New=[@Key[all] ],Old=[]}S1; X1: A1; @key[end] P1; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @key[package] P2 @key[is] @key[subtype] S2 @key[is] Integer @key[range] 0..2**16-1; @key[for] S2'Size @key[use] 32; --@RI{ Illegal!} @key[type] A2 @key[is] @key[access] @Chg{New=[@Key[all] ],Old=[]}S2; X2: A2; @key[end] P2; @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00114} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[procedure] Q @key[is] @key[use] P1, P2; @key[type] Array1 @key[is] @key[array](Integer @key[range] <>) @key[of] @key[aliased] S1@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(Array1)]}; Obj1: Array1(1..100); @key[type] Array2 @key[is] @key[array](Integer @key[range] <>) @key[of] @key[aliased] S2@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(Array2)]}; Obj2: Array2(1..100); @key[begin] X1 := Obj2(17)'@Chg{New=[Unchecked_],Old=[]}Access; X2 := Obj1(17)'@Chg{New=[Unchecked_],Old=[]}Access; @key[end] Q; @end{Example} Loads and stores through X1 would read and write 16 bits, but X1 points to a 32-bit location. Depending on the endianness of the machine, loads might load the wrong 16 bits. Stores would fail to zero the other half in any case. Loads and stores through X2 would read and write 32 bits, but X2 points to a 16-bit location. Thus, adjacent memory locations would be trashed. Hence, the above is illegal. Furthermore, the compiler is forbidden from choosing different Sizes by default, for the same reason. The same issues apply to Alignment. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1],ARef=[AI05-0295-1]} A derived type inherits each type-related @Chg{Version=[3],New=[representation ],Old=[]}aspect @Chg{Version=[3],New=[],Old=[@Chg{New=[of representation ],Old=[]}]}of its parent type that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent type from the grandparent type. A derived subtype inherits each subtype-specific @Chg{Version=[3],New=[representation ],Old=[]}aspect @Chg{Version=[3],New=[],Old=[@Chg{New=[of representation ],Old=[]}]}of its parent subtype that was directly specified before the declaration of the derived type, or (in the case where the parent is derived) that was inherited by the parent subtype from the grandparent subtype, but only if the parent subtype statically matches the first subtype of the parent type. An inherited @Chg{Version=[3],New=[representation ],Old=[]}aspect @Chg{Version=[3],New=[],Old=[of representation ]}is overridden by a subsequent @Chg{Version=[3],New=[@nt{aspect_specification} or ],Old=[]}representation item that specifies @Chg{Version=[3],New=[a different value for ],Old=[]}the same aspect of the type or subtype. @begin{Honest} A @nt{record_representation_clause} for a record extension does not override the layout of the parent part; if the layout was specified for the parent type, it is inherited by the record extension. @end{Honest} @begin{Ramification} If a representation item for the parent appears after the @nt{derived_@!type_@!definition}, then inheritance does not happen for that representation item. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0009-1],ARef=[AI05-0295-1]} @ChgAdded{Version=[3],Text=[If an inherited aspect is confirmed by an @nt{aspect_specification} or a later representation item for a derived type, the confirming specification does not override the inherited one. Thus the derived type has both a specified confirming value and an inherited nonconfirming representation value @em this means that rules that apply only to nonconfirming representation values still apply to this type.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1],ARef=[AI05-0295-1]} @ChgAdded{Version=[1],Text=[In contrast, whether operational aspects are inherited by @Chg{Version=[3],New=[a],Old=[@Chg{Version=[2],New=[an untagged],Old=[a]}]} derived type depends on each specific aspect@Chg{Version=[3],New=[; unless specified, an operational aspect is not inherited],Old=[]}. @Chg{Version=[3],New=[], Old=[@Chg{Version=[2],New=[@Redundant[Operational aspects are never inherited for a tagged type.] ],Old=[]}]}When operational aspects are inherited by @Chg{Version=[3],New=[a],Old=[@Chg{Version=[2],New=[an untagged],Old=[a]}]} derived type, aspects that were directly specified @Chg{Version=[2],New=[by @Chg{Version=[3],New=[@nt{aspect_specification}s or ],Old=[]}operational items that are visible at the point],Old=[before the declaration]} of the derived type@Chg{Version=[2],New=[ declaration],Old=[]}, or (in the case where the parent is derived) that were inherited by the parent type from the grandparent type are inherited. An inherited operational aspect is overridden by a subsequent @Chg{Version=[3],New=[@nt{aspect_specification} or ],Old=[]}operational item that specifies the same aspect of the type.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[As with representation items, if an operational item for the parent appears after the @nt{derived_@!type_@!definition}, then inheritance does not happen for that operational item.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0183-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[1],New=[@Chg{Version=[2],New=[Only],Old=[Currently, only]} untagged types inherit operational aspects. @Chg{Version=[2],New=[Inheritance from tagged types causes problems, as the different views can have different visibility on operational items @em potentially leading to operational items that depend on the view. We want aspects to be the same for all views. Untagged types don't have this problem as plain private types don't have ancestors, and thus can't inherit anything. In addition, it seems unlikely that we'll need inheritance for tagged types, as usually we'll want to incorporate the parent's operation into a new one that also handles any extension components.],Old=[We considered writing this rule that way, but rejected it as that could be too specific for future operational aspects. (After all, that is precisely the problem that caused us to introduce @lquotes@;operational aspects@rquotes in the first place.)]}],Old=[]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[When an aspect that is a subprogram is inherited, the derived type inherits the aspect in the same way that a derived type inherits a user-defined primitive subprogram from its parent (see @RefSecNum{Derived Types and Classes}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This defines the parameter names and types, and the needed implicit conversions.]} @end{Reason} @Leading@;Each aspect of representation of an entity is as follows: @begin{Itemize} @Defn2{Term=[specified], Sec=(of an aspect of representation of an entity)} If the aspect is @i{specified} for the entity, meaning that it is either directly specified or inherited, then that aspect of the entity is as specified, except in the case of Storage_Size, which specifies a minimum. @begin{Ramification} This rule implies that queries of the aspect return the specified value. For example, if the user writes @lquotes@;@key{for} X'Size @key{use} 32;@rquotes@;, then a query of X'Size will return 32. @end{Ramification} @PDefn{unspecified} If an aspect of representation of an entity is not specified, it is chosen by default in an unspecified manner. @end{Itemize} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} Note that @Chg{New=[@Chg{Version=[3],New=[specifying a ],Old=[]}representation @Chg{Version=[3],New=[aspect],Old=[items]}],Old=[@nt{representation_clause}s]} can affect the semantics of the entity. The rules forbid things like @lquotes@;@key[for] S'Base'Alignment @key[use] ...@rquotes@; and @lquotes@;@key[for] S'Base @key[use] record ...@rquotes@;. @end{Ramification} @begin{Discussion} The intent is that implementations will represent the components of a composite value in the same way for all subtypes of a given composite type. Hence, Component_Size and record layout are type-related aspects. @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0083-1]} @ChgAdded{Version=[3],Text=[As noted previously, in the case of an object, the entity mentioned in this text is a specific view of an object. That means that only references to the same view of an object that has a specified value for a representation aspect @i<R> necessarily have that value for the aspect @i<R>. The value of the aspect @i<R> for a different view of that object is unspecified. In particular, this means that the representation values for by-reference parameters is unspecified; they do not have to be the same as those of the underlying object.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[specified], Sec=(of an operational aspect of an entity)} If an operational aspect is @i<specified> for an entity (meaning that it is either directly specified or inherited), then that aspect of the entity is as specified. Otherwise, the aspect of the entity has the default value for that aspect.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[An @nt{aspect_specification} or ],Old=[A]}representation item that specifies @Chg{Version=[3],New=[a],Old=[an aspect of]} representation@Chg{Version=[3],New=[ aspect],Old=[]} that would have been chosen in the absence of the @Chg{Version=[3],New=[@nt{aspect_specification} or ],Old=[]} representation item is said to be @i{confirming}.@Defn2{Term=[confirming], Sec=(representation item)}@Chg{Version=[3],New=[ The aspect value specified in this case is said to be a @i<confirming> representation aspect value. Other values of the aspect are said to be @i<nonconfirming>, as are the @nt{aspect_specification}s and representation items that specified them.@Defn2{Term=[confirming], Sec=(representation value)} @Defn2{Term=[confirming], Sec=(aspect specification)} @Defn2{Term=[nonconfirming], Sec=(representation value)} @Defn2{Term=[nonconfirming], Sec=(representation item)} @Defn2{Term=[nonconfirming], Sec=(aspect specification)}],Old=[]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[@PDefn2{Term=[elaboration], Sec=(aspect_clause)}], Old=[@PDefn2{Term=[elaboration], Sec=(representation_clause)}]} For the elaboration of @Chg{New=[an @nt{aspect_clause}], Old=[a @nt{representation_clause}]}, any evaluable constructs within it are evaluated. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Elaboration of representation pragmas is covered by the general rules for pragmas in @Chg{Version=[3],New=[@RefSecNum{Pragmas}],Old=[Section 2]}. @end{Ramification} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} An implementation may interpret @Chg{Version=[3],New=[],Old=[aspects of ]}representation@Chg{Version=[3],New=[ aspects],Old=[]} in an implementation-defined manner. An implementation may place implementation-defined restrictions on @Chg{Version=[3],New=[the specification of ],Old=[]}representation @Chg{Version=[3],New=[aspects],Old=[items]}. @RootDefn{recommended level of support} A @i{recommended level of support} is @Chg{Version=[3],New=[defined],Old=[specified]} for @Chg{Version=[3],New=[the specification of ],Old=[]}representation @Chg{Version=[3],New=[aspects],Old=[items]} and related features in each subclause. These recommendations are changed to requirements for implementations that support the Systems Programming Annex (see @RefSec{Required Representation Support}). @ChgImplDef{Version=[3],Kind=[Revised],InitialVersion=[0],Text=[The interpretation of each @Chg{Version=[3],New=[],Old=[aspect of ]}representation@Chg{Version=[3],New=[ aspect],Old=[]}.]} @ChgImplDef{Version=[3],Kind=[Revised],InitialVersion=[0],Text=[Any restrictions placed upon @Chg{Version=[3],New=[the specification of ],Old=[]}representation @Chg{Version=[3],New=[aspects],Old=[items]}.]} @begin{Ramification} Implementation-defined restrictions may be enforced either at compile time or at run time. There is no requirement that an implementation justify any such restrictions. They can be based on avoiding implementation complexity, or on avoiding excessive inefficiency, for example. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[1],Text=[There is no such permission for operational aspects.]} @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @PDefn2{Term=[recommended level of support], Sec=(with respect to nonstatic expressions)} The recommended level of support for @Chg{Version=[3],New=[the specification of ],Old=[]}all representation @Chg{Version=[3],New=[aspects],Old=[items]} is qualified as follows: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[A confirming @Chg{Version=[3],New=[specification for a ],Old=[]}representation @Chg{Version=[3],New=[aspect],Old=[item]} should be supported.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[A confirming representation @Chg{Version=[3],New=[aspect value],Old=[item]} might not be possible for some entities. For instance, consider an unconstrained array. The size of such a type is implementation-defined, and might not actually be a representable value, or might not be static.]} @end{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} An implementation need not support @Chg{Version=[3],New=[the specification for a ],Old=[]}representation @Chg{Version=[3],New=[aspect that contains],Old=[items containing]} nonstatic expressions, @Chg{Version=[3],New=[unless],Old=[except that an implementation should support a representation item for a given entity if]} each nonstatic expression@Chg{Version=[3],New=[],Old=[ in the representation item]} is a @Chg{Version=[3],New=[@nt{name}],Old=[name]} that statically denotes a constant declared before the entity. @begin{Reason} @Leading@;This is to avoid the following sort of thing: @begin{Example} X : Integer := F(...); Y : Address := G(...); @key[for] X'Address @key[use] Y; @end{Example} In the above, we have to evaluate the initialization expression for X before we know where to put the result. This seems like an unreasonable implementation burden. @Leading@;The above code should instead be written like this: @begin{Example} Y : @key[constant] Address := G(...); X : Integer := F(...); @key[for] X'Address @key[use] Y; @end{Example} This allows the expression @lquotes@;Y@rquotes@; to be safely evaluated before X is created. The constant could be a formal parameter of mode @key[in]. An implementation can support other nonstatic expressions if it wants to. Expressions of type Address are hardly ever static, but their value might be known at compile time anyway in many cases. @end{Reason} An implementation need not support a specification for the Size for a given composite subtype, nor the size or storage place for an object (including a component) of a given composite subtype, unless the constraints on the subtype and its composite subcomponents (if any) are all static constraints. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @Chg{Version=[2],New=[An implementation need not support @Chg{Version=[3],New=[specifying ],Old=[]}a nonconfirming representation @Chg{Version=[3],New=[aspect value],Old=[item]} if it could cause an aliased object or an object of a by-reference type to be allocated at a nonaddressable location or, when the alignment attribute of the subtype of such an object is nonzero, at an address that is not an integral multiple of that alignment.],Old=[An aliased component, or a component whose type is by-reference, should always be allocated at an addressable location.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-0079} The intent is that access types, type System.Address, and the pointer used for a by-reference parameter should be implementable as a single machine address @em bit-field pointers should not be required. (There is no requirement that this implementation be used @em we just want to make sure @Chg{New=[it's],Old=[its]} feasible.) @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Chg{Version=[2],New=[We want subprograms to be able to assume the properties of the types of their parameters inside of subprograms. While many objects can be copied to allow this (and thus do not need limitations), aliased or by-reference objects cannot be copied (their memory location is part of their identity). Thus,], Old=[Note that]} the above rule does not apply to types that merely allow by-reference parameter passing; for such types, a copy typically needs to be made at the call site when a bit-aligned component is passed as a parameter. @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[An implementation need not support @Chg{Version=[3],New=[specifying ],Old=[]}a nonconfirming representation @Chg{Version=[3],New=[aspect value],Old=[item]} if it could cause an aliased object of an elementary type to have a size other than that which would have been chosen by default.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since all bits of elementary objects participate in operations, aliased objects must not have a different size than that assumed by users of the access type.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[An implementation need not support @Chg{Version=[3],New=[specifying ],Old=[]}a nonconfirming representation @Chg{Version=[3],New=[aspect value],Old=[item]} if it could cause an aliased object of a composite type, or an object whose type is by-reference, to have a size smaller than that which would have been chosen by default.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike elementary objects, there is no requirement that all bits of a composite object participate in operations. Thus, as long as the object is the same or larger in size than that expected by the access type, all is well.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule presumes that the implementation allocates an object of a size specified to be larger than the default size in such a way that access of the default size suffices to correctly read and write the value of the object.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[An implementation need not support @Chg{Version=[3],New=[specifying ],Old=[]}a nonconfirming subtype-specific representation @Chg{Version=[3],New=[aspect value for],Old=[item specifying an aspect of representation of]} an indefinite or abstract subtype.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[Representation aspects], Old=[Aspects of representations]} are often not well-defined for such types.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{Presentation AI-00075} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[A type with the Pack aspect specified],Old=[A pragma Pack]} will typically not @Chg{Version=[3],New=[be packed],Old=[pack]} so tightly as to disobey the above @Chg{Version=[2],New=[rules],Old=[rule]}. A Component_Size clause or @nt{record_representation_clause} will typically @Chg{New=[be],Old=[by]} illegal if it disobeys the above @Chg{Version=[2],New=[rules],Old=[rule]}. Atomic components have similar restrictions (see @RefSec{Shared Variable Control}). @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0295-1]} @ChgAdded{Version=[2],Text=[For purposes of these rules, the determination of whether @Chg{Version=[3],New=[specifying ],Old=[]}a representation @Chg{Version=[3],New=[aspect value for],Old=[item applied to]} a type @i{could cause} an object to have some property is based solely on the properties of the type itself, not on any available information about how the type is used. In particular, it presumes that minimally aligned objects of this type might be declared at some point.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for all representation items should be followed.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Aspects that can be specified are defined throughout this International Standard, and are summarized in @RefSecNum{Language-Defined Aspects}.]} @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} It is now illegal for a representation item to cause a derived by-reference type to have a different record layout from its parent. This is necessary for by-reference parameter passing to be feasible. This only affects programs that specify the representation of types derived from types containing tasks; most by-reference types are new to Ada 95. For example, if A1 is an array of tasks, and A2 is derived from A1, it is illegal to apply a @nt{pragma} Pack to A2. @end{Incompatible83} @begin{Extend83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Defn{extensions to Ada 83} Ada 95 allows additional @Chg{New=[@nt{aspect_clause}s], Old=[@nt{representation_clause}s]} for objects. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} The syntax rule for @ntf{type_representation_clause} is removed; the right-hand side of that rule is moved up to where it was used, in @Chg{New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]}. There are two references to @lquotes@;type representation clause@rquotes@; in RM83, both in Section 13; these have been reworded. @Chg{New=[Also, the @ntf{representation_clause} has been renamed the @nt{aspect_clause} to reflect that it can be used to control more than just representation aspects.],Old=[]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We have defined a new term @lquotes@;representation item,@rquotes@; which includes @Chg{New=[all representation clauses], Old=[@nt{representation_clause}s]} and representation pragmas, as well as @nt<component_clause>s. This is convenient because the rules are almost identical for all @Chg{New=[of them], Old=[three]}. @Chg{New=[We have also defined the new terms @lquotes@;operational item@rquotes@; and @lquotes@;operational aspects@rquotes@; in order to conveniently handle new types of @Chg{Version=[2],New=[specifiable],Old=[specifable]} entities.],Old=[]} All of the forcing occurrence stuff has been moved into its own subclause (see @RefSecNum{Freezing Rules}), and rewritten to use the term @lquotes@;freezing@rquotes@;. RM83-13.1(10) requires implementation-defined restrictions on representation items to be enforced at compile time. However, that is impossible in some cases. If the user specifies a junk (nonstatic) address in an address clause, and the implementation chooses to detect the error (for example, using hardware memory management with protected pages), then it's clearly going to be a run-time error. It seems silly to call that @lquotes@;semantics@rquotes@; rather than @lquotes@;a restriction.@rquotes@; RM83-13.1(10) tries to pretend that @ntf{representation_clause}s don't affect the semantics of the program. One counter-example is the Small clause. Ada 95 has more counter-examples. We have noted the opposite above. Some of the more stringent requirements are moved to @RefSec{Required Representation Support}. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Confirming representation items are defined, and the recommended level of support is now that they always be supported.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added operational items in order to eliminate unnecessary restrictions and permissions on stream attributes. As part of this, @ntf{representation_clause} was renamed to @nt{aspect_clause}.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to say that the partial and full views have the same operational and representation aspects. Ada 2005 extends this to cover all views, including the incomplete view.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed operational items to have inheritance specified for each such aspect.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording to allow the rejection of types with progenitors that have conflicting representation items.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[The description of the representation of an object was clarified (with great difficulty reaching agreement). Added wording to say that representation items on aliased and by-reference objects never need be supported if they would not be implementable without distributed overhead even if other recommended level of support says otherwise. This wording matches the rules with reality.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00444-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[Added wording so that inheritance depends on whether operational items are visible rather than whether they occur before the declaration (we don't want to look into private parts). @Chg{Version=[3],New=[Also limited],Old=[Limited]} operational inheritance to untagged types to avoid @Chg{Version=[3],New=[anomalies],Old=[anomolies]} with private extensions (this is not incompatible, no existing operational attribute used this capability). Also added wording to clearly define that subprogram inheritance works like derivation of subprograms.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0106-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Specifying a language-defined aspect for a generic formal parameter is no longer allowed. Most aspects could not be specified on these anyway; moreover, this was not allowed in Ada 83, so it is unlikely that compilers are supporting this as a capability (and it is not likely that they have a consistent definition of what it means if it is allowed). Thus, we expect this to occur rarely in existing programs.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined that overriding of an representation aspect only happens for a nonconfirming representation item. This prevents a derived type from being considered to have only a confirming representation item when the value would be nonconfirming if given on a type that does not inherit any aspects of representation. This change just eliminates a wording confusion and ought not change any behavior.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0112-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined a default naming for representation aspects that are representation pragmas.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Added text ensuring that the rules for representational and operational items also apply appropriately to @nt{aspect_specification}s; generalized operational aspects so that they can be defined for entities other than types. Any extensions are documented elsewhere.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0295-1]} @ChgAdded{Version=[3],Text=[Rewrote many rules to be in terms of "specifying a representation aspect" rather than use of a "representation item". This better separates @i<how> an aspect is specified from @i<what> rules apply to the value of the aspect.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Aspect Specifications]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[@Redundant[Certain representation or operational aspects of an entity may be specified as part of its declaration using an @nt{aspect_specification}, rather than using a separate representation or operational item.] The declaration with the @nt{aspect_specification} is termed the @i{associated declaration}.@Defn2{Term=[associated declaration],Sec=[of an aspect specification]}]} @end{Intro} @begin{Syntax} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<aspect_specification>,Old=<>}>, rhs=`@Chg{Version=[3],New=" @key[with] @Syn2{aspect_mark} [=> @Syn2{aspect_definition}] {, @Syn2{aspect_mark} [=> @Syn2{aspect_definition}] }",Old=<>}'} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<aspect_mark>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI<aspect_>@Syn2<identifier>['Class]>,Old=<>}"} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<aspect_definition>,Old=<>}>, rhs="@Chg{Version=[3],New=<@Syn2<name> | @Syn2<expression> | @Syn2<identifier>>,Old=<>}"} @end{Syntax} @begin{Metarules} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[The @nt{aspect_specification} is an optional element in most kinds of declarations. Here is a list of all kinds of declarations and an indication of whether or not they allow aspect clauses, and in some cases a short discussion of why (* = allowed, NO = not allowed). Kinds of declarations with no indication are followed by their subdivisions (which have indications).]} @begin{Display} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@nt{basic_declaration} @nt{type_declaration} @nt{full_type_declaration} @i<type declaration syntax>* @nt{task_type_declaration}* @nt{protected_type_declaration}* @nt{incomplete_type_declaration} -- NO -- @Examcom{Incomplete type aspects cannot be read by an attribute or specified by @nt{attribute_definition_clause}s } -- @Examcom{(the attribute name is illegal), so it would not make sense to allow this in another way.} @nt{private_type_declaration}* @nt{private_extension_declaration}* @nt{subtype_declaration}* @nt{object_declaration} @i<object declaration syntax>* @nt{single_task_declaration}* @nt{single_protected_declaration}* @nt{number_declaration} -- NO @nt{subprogram_declaration}* @nt{abstract_subprogram_declaration}* @nt{null_procedure_declaration}* @nt{package_declaration}* -- @Examcom{via} @nt{package_specification} @nt{renaming_declaration}* -- @Examcom{There are no language-defined aspects that may be specified} -- @Examcom{on renames, but implementations might support some.} @nt{exception_declaration}* @nt{generic_declaration} @nt{generic_subprogram_declaration}* @nt{generic_package_declaration}* -- @Examcom{via} @nt{package_specification} @nt{generic_instantiation}* @nt{enumeration_literal_specification} -- NO @nt{discriminant_specification} -- NO @nt{component_declaration}* @nt{loop_parameter_specification} -- NO @nt{iterator_specification} -- NO @nt{parameter_specification} -- NO @nt{subprogram_body}* -- @Examcom{ - but language-defined aspects only if there is no explicit specification} @nt{entry_declaration}* @nt{entry_index_specification} -- NO @nt{subprogram_body_stub}* -- @Examcom{ - but language-defined aspects only if there is no explicit specification} @nt{choice_parameter_specification} -- NO @nt{generic_formal_parameter_declaration} -- @Examcom{There are no language-defined aspects that may be specified} -- @Examcom{on generic formals, but implementations might support some.} @nt{formal_object_declaration}* @nt{formal_type_declaration}* @nt{formal_subprogram_declaration} @nt{formal_concrete_subprogram_declaration}* @nt{formal_abstract_subprogram_declaration}* @nt{formal_package_declaration}* @nt{extended_return_statement} -- NO]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[-- @Examcom{We also allow @nt{aspect_specification}s on all kinds of bodies, but are no language-defined aspects} -- @Examcom{that may be specified on a body. These are allowed for implementation-defined aspects.} -- @Examcom{See above for subprogram bodies and stubs (as these can be declarations).} @nt{package_body}* @nt{task_body}* @nt{protected_body}* @nt{package_body_stub}* @nt{task_body_stub}* @nt{protected_body_stub}*]} @end{Display} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[Syntactically, @nt{aspect_specification}s generally are located at the end of declarations. When a declaration is all in one piece such as a @nt{null_procedure_declaration}, @nt{object_declaration}, or @nt{generic_instantiation} the @nt{aspect_specification} goes at the end of the declaration; it is then more visible and less likely to interfere with the layout of the rest of the structure. However, we make an exception for program units (other than subprogram specifications) and bodies, in which the @nt{aspect_specification} goes before the @key[is]. In these cases, the entity could be large and could contain other declarations that also have @nt{aspect_specification}s, so it is better to put the @nt{aspect_specification} toward the top of the declaration. (Some aspects @en such as Pure @en also affect the legality of the contents of a unit, so it would be annoying to only see those after reading the entire unit.)]} @end{Metarules} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An @nt{aspect_mark} identifies an aspect of the entity defined by the associated declaration (the @i<associated entity>@Defn2{Term=[associated entity],Sec=[of an aspect specification]}); the aspect denotes an object, a value, an expression, a subprogram, or some other kind of entity. If the @nt{aspect_mark} identifies:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an aspect that denotes an object, the @nt{aspect_definition} shall be a @nt{name}. The expected type for the @nt{name} is the type of the identified aspect of the associated entity;@PDefn2{Term=[expected type], Sec=[object in an @nt{aspect_specification}]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an aspect that is a value or an expression, the @nt{aspect_definition} shall be an @nt{expression}. The expected type for the @nt{expression} is the type of the identified aspect of the associated entity;@PDefn2{Term=[expected type], Sec=[@nt{name} in an @nt{aspect_specification}]}@PDefn2{Term=[expected type], Sec=[@nt{expression} in an @nt{aspect_specification}]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an aspect that denotes a subprogram, the @nt{aspect_definition} shall be a @nt{name}; the expected profile for the @nt{name} is the profile required for the aspect of the associated entity;@PDefn2{Term=[expected profile], Sec=[@nt{name} in an @nt{aspect_specification}]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an aspect that denotes some other kind of entity, the @nt{aspect_definition} shall be a @nt{name}, and the name shall resolve to denote an entity of the appropriate kind;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an aspect that is given by an identifier specific to the aspect, the @nt{aspect_definition} shall be an @nt{identifier}, and the @nt{identifier} shall be one of the identifiers specific to the identified aspect.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[The usage names in an @nt{aspect_definition} @Redundant[ are not resolved at the point of the associated declaration, but rather] are resolved at the end of the immediately enclosing declaration list.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[If the associated declaration is for a subprogram or entry, the names of the formal parameters are directly visible within the @nt{aspect_definition}, as are certain attributes, as specified elsewhere in this International Standard for the identified aspect. If the associated declaration is a @nt{type_declaration}, within the @nt{aspect_definition} the names of any components are directly visible, and the name of the first subtype denotes the current instance of the type (see @RefSecNum{The Context of Overload Resolution}). If the associated declaration is a @nt{subtype_declaration}, within the @nt{aspect_definition} the name of the new subtype denotes the current instance of the subtype.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[If the first freezing point of the associated entity comes before the end of the immediately enclosing declaration list, then each usage name in the @nt{aspect_definition} shall resolve to the same entity at the first freezing point as it does at the end of the immediately enclosing declaration list.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[At most one occurrence of each @nt{aspect_mark} is allowed within a single @nt{aspect_specification}. The aspect identified by the @nt{aspect_mark} shall be an aspect that can be specified for the associated entity (or view of the entity defined by the associated declaration).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[The @nt{aspect_definition} associated with a given @nt{aspect_mark} may be omitted only when the @nt{aspect_mark} identifies an aspect of a boolean type, in which case it is equivalent to the @nt{aspect_definition} being specified as True.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[If the @nt{aspect_mark} includes 'Class, then the associated entity shall be a tagged type or a primitive subprogram of a tagged type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[There are no language-defined aspects that may be specified on a @nt{renaming_declaration}, a @nt{generic_formal_parameter_declaration}, a @nt{subunit}, a @nt{package_body}, a @nt{task_body}, a @nt{protected_body}, or a @nt{body_stub} other than a @nt{subprogram_body_stub}.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Implementation-defined aspects can be allowed on these, of course; the implementation will need to define the semantics. In particular, the implementation will need to define actual type matching rules for any aspects allowed on formal types; there are no default matching rules defined by the language.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[A language-defined aspect shall not be specified in an @nt{aspect_specification} given on a @nt{subprogram_body} or @nt{subprogram_body_stub} that is a completion of another declaration.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Most language-defined aspects (for example, preconditions) are intended to be available to callers, and specifying them on a body that has a separate declaration hides them from callers. Specific language-defined aspects may allow this, but they have to do so explicitly (by defining an alternative @LegalityName), and provide any needed rules about visibility. Note that this rule does not apply to implementation-defined aspects, so implementers need to carefully define whether such aspects can be applied to bodies and stubs, and what happens if they are specified on both the declaration and body of a unit.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Depending on which aspect is identified by the @nt{aspect_mark}, an @nt{aspect_definition} specifies:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[a @nt{name} that denotes a subprogram, object, or other kind of entity;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an @nt{expression}, which is either evaluated to produce a single value, or which (as in a precondition) is to be evaluated at particular points during later execution; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[an @nt{identifier} specific to the aspect.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The identified aspect of the associated entity, or in some cases, the view of the entity defined by the declaration, is as specified by the @nt{aspect_definition} (or by the default of True when boolean). Whether an @nt{aspect_specification} @i<applies> to an entity or only to the particular view of the entity defined by the declaration is determined by the @nt{aspect_mark} and the kind of entity. The following aspects are view specific:@PDefn2{Term=[applies],Sec=[aspect]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An aspect specified on an @nt{object_declaration};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An aspect specified on a @nt{subprogram_declaration};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An aspect specified on a @nt{renaming_declaration}.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[All other @nt{aspect_specification}s are associated with the entity, and @i<apply> to all views of the entity, unless otherwise specified in this International Standard.@PDefn2{Term=[applies],Sec=[aspect]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If the @nt{aspect_mark} includes 'Class, then:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if the associated entity is a tagged type, the specification @i<applies> to all descendants of the type;@PDefn2{Term=[applies],Sec=[aspect]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if the associated entity is a primitive subprogram of a tagged type @i<T>, the specification @i<applies> to the corresponding primitive subprogram of all descendants of @i<T>.@PDefn2{Term=[applies],Sec=[aspect]}]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[All specifiable operational and representation attributes may be specified with an @nt{aspect_specification} instead of an @nt{attribute_definition_clause} (see @RefSecNum{Operational and Representation Attributes}).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The name of the aspect is the same as that of the attribute (see @RefSecNum{Operational and Representation Attributes}), so the @nt{aspect_mark} is the @nt{attribute_designator} of the attribute.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Any aspect specified by a representation pragma or library unit pragma that has a @nt{local_name} as its single argument may be specified by an @nt{aspect_specification}, with the entity being the @nt{local_name}. The @nt{aspect_definition} is expected to be of type Boolean. The expression shall be static.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The name of the aspect is the same as that of the pragma (see @RefSecNum{Operational and Representation Aspects}), so the @nt{aspect_mark} is the name of the pragma.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[In addition, other operational and representation aspects not associated with specifiable attributes or representation pragmas may be specified, as specified elsewhere in this International Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[If an aspect of a derived type is inherited from an ancestor type and has the boolean value True, the inherited value shall not be overridden to have the value False for the derived type, unless otherwise specified in this International Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[If a @LegalityName or @StaticSemTitle rule only applies when a particular aspect has been specified, the aspect is considered to have been specified only when the @nt{aspect_specification} or @nt{attribute_definition_clause} is visible (see @RefSecNum{Visibility}) at the point of the application of the rule.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Some rules only apply when an aspect has been specified (for instance, an indexable type is one that has aspect Variable_Indexing specified). In order to prevent privacy breaking, this can only be true when the specification of the aspect is visible. In particular, if the Variable_Indexing aspect is specified on the full view of a private type, the private type is not considered an indexable type.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Alternative legality and semantics rules may apply for particular aspects, as specified elsewhere in this International Standard.]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[At the freezing point of the associated entity, the @nt{aspect_specification} is elaborated. The elaboration of the @nt{aspect_specification} includes the evaluation of the @nt{name} or @nt{expression}, if any, unless the aspect itself is an expression. If the corresponding aspect represents an expression (as in a precondition), the elaboration has no effect; the expression is evaluated later at points within the execution as specified elsewhere in this International Standard for the particular aspect.]} @end{Runtime} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Implementations may support implementation-defined aspects. The @nt{aspect_specification} for an implementation-defined aspect may use an implementation-defined syntax for the @nt{aspect_definition}, and may follow implementation-defined legality and semantics rules.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The intent is to allow implementations to support aspects that are defined, for example, by a @nt{subtype_indication} rather than an @nt{expression} or a @nt{name}. We chose not to try to enumerate all possible @nt{aspect_definition} syntaxes, but to give implementations maximum freedom. Unrecognized aspects are illegal whether or not they use custom syntax, so this freedom does not reduce portability.]} @end{Discussion} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Implementation-defined aspects, inluding the syntax for specifying such aspects and the legality rules for such aspects.]}]} @end{ImplPerm} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1],ARef=[AI05-0229-1],ARef=[AI05-0267-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect specifications are new.]} @end{Extend2005} @LabeledRevisedClause{Version=[3],New=[Packed Types],Old=[Pragma Pack]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @redundant[@Chg{Version=[3],New=[The Pack aspect having the value True],Old=[A @nt{pragma} Pack]} specifies that storage minimization should be the main criterion when selecting the representation of a composite type.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 4 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Pack is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Pack)(@SynI{first_subtype_}@Syn2{local_name});]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The @SynI{first_subtype_}@nt{local_name} of a @nt{pragma} Pack shall denote a composite subtype.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{A fake to get a conditional Leading} @Chg{Version=[3],New=[For a full type declaration of a composite type, the following language-defined representation aspect may be specified:], Old=[@PDefn2{Term=[representation pragma], Sec=(Pack)} @PDefn2{Term=[pragma, representation], Sec=(Pack)} @Chg{Version=[3],New=[@PDefn2{Term=[representation aspect], Sec=(packing)}], Old=[@PDefn2{Term=[aspect of representation], Sec=(packing)} @Defn2{Term=[packing], Sec=(aspect of representation)}]} @Defn{packed} A @nt{pragma} Pack specifies the @i{packing} aspect of representation; the type (or the extension part) is said to be @i{packed}. For a type extension, the parent part is packed as for the parent type, and a @nt{pragma} Pack causes packing only of the extension part.]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Pack@\The type of aspect Pack is Boolean. When aspect Pack is True for a type, the type (or the extension part) is said to be @i{packed}. For a type extension, the parent part is packed as for the parent type, and specifying Pack causes packing only of the extension part. @Defn{packed}@AspectDefn{Pack}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Pack], Text=[@ChgAdded{Version=[3],Text=[Minimize storage when laying out records and arrays.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If directly specified, the @nt{aspect_definition} shall be a static expression. If not specified (including by inheritance), the aspect is False.]} @end{Description} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The only high level semantic effect of @Chg{Version=[3],New=[specifying the],Old=[a @nt{pragma}] Pack@Chg{Version=[3],New=[ aspect],Old=[]} is @Chg{Version=[3],New=[potential loss of ],Old=[]}independent addressability (see @RefSec{Shared Variables}).]} @end{Ramification} @end{StaticSem} @begin{ImplAdvice} If a type is packed, then the implementation should try to minimize storage allocated to objects of the type, possibly at the expense of speed of accessing components, subject to reasonable complexity in addressing calculations. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Storage allocated to objects of a packed type should be minimized.]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[Specifying the],Old=[A @nt{pragma}]} Pack@Chg{Version=[3],New=[ aspect],Old=[]} is for gaining space efficiency, possibly at the expense of time. If more explicit control over representation is desired, then a @nt{record_representation_clause}, a Component_Size clause, or a Size clause should be used instead of, or in addition to, @Chg{Version=[3],New=[the],Old=[a @nt{pragma}]} Pack@Chg{Version=[3],New=[ aspect],Old=[]}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[If a packed type has a component that is not of a by-reference type and has no aliased part, then such a component need not be aligned according to the Alignment of its subtype; in particular it need not be allocated on a storage element boundary.]} @Comment{No "should" here; thus no ImplAdvice entry. This really qualifies the item above} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[@PDefn2{Term=[recommended level of support], Sec=(aspect Pack)}], Old=[@PDefn2{Term=[recommended level of support], Sec=(pragma Pack)}]} The recommended level of support for @Chg{Version=[3],New=[the],Old=[@nt{pragma}]} Pack@Chg{Version=[3],New=[ aspect],Old=[]} is: @begin{Itemize} For a packed record type, the components should be packed as tightly as possible subject to the Sizes of the component subtypes, and subject to any @nt{record_representation_clause} that applies to the type; the implementation may, but need not, reorder components or cross aligned word boundaries to improve the packing. A component whose Size is greater than the word size may be allocated an integral number of words. @begin{Ramification} The implementation can always allocate an integral number of words for a component that will not fit in a word. The rule also allows small component sizes to be rounded up if such rounding does not waste space. For example, if Storage_Unit = 8, then a component of size 8 is probably more efficient than a component of size 7 plus a 1-bit gap (assuming the gap is needed anyway). @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} For a packed array type, if the @Chg{Version=[3],New=[], Old=[component subtype's ]}Size@Chg{Version=[3],New=[ of the component subtype],Old=[]} is less than or equal to the word size@Chg{Version=[3],New=[],Old=[, and Component_Size is not specified for the type]}, Component_Size should be less than or equal to the Size of the component subtype, rounded up to the nearest factor of the word size. @begin{Ramification} If a component subtype is aliased, its Size will generally be a multiple of Storage_Unit, so it probably won't get packed very tightly. @end{Ramification} @end{Itemize} @ChgImplAdvice{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for @Chg{Version=[3],New=[the],Old=[pragma]} Pack@Chg{Version=[3],New=[ aspect],Old=[]} should be followed.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[Added clarification that @Chg{Version=[3],New=[the],Old=[pragma]} Pack@Chg{Version=[3],New=[ aspect],Old=[]} can ignore alignment requirements on types that don't have by-reference or aliased parts. This was always intended, but there was no wording to that effect.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect Pack is new; @nt{pragma} Pack is now obsolescent.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Fixed so that the presence or absence of a confirming Component_Size representation clause does not change the meaning of the Pack aspect.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledRevisedClause{Version=[1],New=[Operational and Representation Attributes], Old=[Representation Attributes]} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @redundant[@Defn{representation attribute} @Defn2{Term=[attribute], Sec=(representation)} The values of certain implementation-dependent characteristics can be obtained by interrogating appropriate @Chg{New=[operational or ],Old=[]}representation attributes. @RootDefn2{Term=[attribute], Sec=(specifying)} Some of these attributes are specifiable via an @nt{attribute_definition_clause}.] @end{Intro} @begin{MetaRules} In general, the meaning of a given attribute should not depend on whether the attribute was specified via an @nt{attribute_definition_clause}, or chosen by default by the implementation. @end{MetaRules} @begin{Syntax} @Syn{lhs=<attribute_definition_clause>,rhs=" @key{for} @Syn2{local_name}@SingleQuote@Syn2{attribute_designator} @key{use} @Syn2{expression}; | @key{for} @Syn2{local_name}@SingleQuote@Syn2{attribute_designator} @key{use} @Syn2{name};"} @end{Syntax} @begin{Resolution} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a value, the form with an @nt{expression} shall be used. Otherwise, the form with a @nt{name} shall be used. @PDefn2{Term=[expected type], Sec=(attribute_definition_clause expression or name)} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a value or an object, the expected type for the expression or @nt{name} is that of the attribute. @PDefn2{Term=[expected profile], Sec=(attribute_definition_clause name)} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a subprogram, the expected profile for the @nt{name} is the profile required for the attribute. For an @nt{attribute_definition_clause} that specifies an attribute that denotes some other kind of entity, the @nt{name} shall resolve to denote an entity of the appropriate kind. @begin{Ramification} For example, the Size attribute is of type @i{universal_integer}. Therefore, the expected type for Y in @lquotes@;@key[for] X'Size @key[use] Y;@rquotes@; is @i{universal_integer}, which means that Y can be of any integer type. @end{Ramification} @begin{Discussion} For attributes that denote subprograms, the required profile is indicated separately for the individual attributes. @end{Discussion} @begin{Ramification} @Leading@;For an @nt{attribute_definition_clause} with a @nt{name}, the @nt{name} need not statically denote the entity it denotes. For example, the following kinds of things are allowed: @begin{Example} @key[for] Some_Access_Type'Storage_Pool @key[use] Storage_Pool_Array(I); @key[for] Some_Type'Read @key[use] Subprogram_Pointer.@key[all]; @end{Example} @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} @RootDefn{specifiable (of an attribute and for an entity)} @RootDefn2{Term=[attribute], Sec=(specifiable)} An @nt{attribute_designator} is allowed in an @nt{attribute_definition_clause} only if this International Standard explicitly allows it, or for an implementation-defined attribute if the implementation allows it. @Chg{Version=[3],New=[@PDefn2{Term=[representation aspect], Sec=(specifiable attributes)}], Old=[@PDefn2{Term=[aspect of representation], Sec=(specifiable attributes)}]} Each specifiable attribute constitutes an @Chg{New=[@PDefn2{Term=[operational aspect], Sec=(specifiable attributes)} operational aspect or ],Old=[]}aspect of representation@Chg{Version=[3],New=[; the name of the aspect is that of the attribute],Old=[]}. @begin{Discussion} For each specifiable attribute, we generally say something like, @lquotes@;The ... attribute may be specified for ... via an @nt{attribute_definition_clause}.@rquotes@; The above wording allows for T'Class'Alignment, T'Class'Size, T'Class'Input, and T'Class'Output to be specifiable. A specifiable attribute is not necessarily specifiable for all entities for which it is defined. For example, one is allowed to ask T'Component_Size for an array subtype T, but @lquotes@;@key[for] T'Component_Size @key[use] ...@rquotes@; is only allowed if T is a first subtype, because Component_Size is a type-related aspect. @end{Discussion} For an @nt{attribute_definition_clause} that specifies an attribute that denotes a subprogram, the profile shall be mode conformant with the one required for the attribute, and the convention shall be Ada. Additional requirements are defined for particular attributes. @Defn2{Term=[mode conformance],Sec=(required)} @begin{Ramification} @Leading@;This implies, for example, that if one writes: @begin{Example} @key[for] T'Read @key[use] R; @end{Example} R has to be a procedure with two parameters with the appropriate subtypes and modes as shown in @RefSecNum{Stream-Oriented Attributes}. @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00270-01]} @Defn{Address clause} @Defn{Alignment clause} @Defn{Size clause} @Defn{Component_Size clause} @Defn{External_Tag clause} @Defn{Small clause} @Defn{Bit_Order clause} @Defn{Storage_Pool clause} @Defn{Storage_Size clause}@Chg{Version=[2],New=[ @Defn{Stream_Size clause}],Old=[]} @Defn{Read clause} @Defn{Write clause} @Defn{Input clause} @Defn{Output clause} @Defn{Machine_Radix clause} A @i{Size clause} is an @nt{attribute_definition_clause} whose @nt{attribute_designator} is Size. Similar definitions apply to the other specifiable attributes. @begin{Honest} @PDefn2{Term=[type-related], Sec=(attribute_definition_clause)} @PDefn2{Term=[subtype-specific], Sec=(attribute_definition_clause)} An @nt{attribute_definition_clause} is type-related or subtype-specific if the @nt{attribute_designator} denotes a type-related or subtype-specific attribute, respectively. @end{Honest} @Defn{storage element} @IndexSee{Term=[byte],See=(storage element)} A @i{storage element} is an addressable element of storage in the machine. @Defn{word} A @i{word} is the largest amount of storage that can be conveniently and efficiently manipulated by the hardware, given the implementation's run-time model. A word consists of an integral number of storage elements. @begin{Discussion} A storage element is not intended to be a single bit, unless the machine can efficiently address individual bits. @end{Discussion} @begin{Ramification} For example, on a machine with 8-bit storage elements, if there exist 32-bit integer registers, with a full set of arithmetic and logical instructions to manipulate those registers, a word ought to be 4 storage elements @em that is, 32 bits. @end{Ramification} @begin{Discussion} The @lquotes@;given the implementation's run-time model@rquotes@; part is intended to imply that, for example, on an 80386 running MS-DOS, the word might be 16 bits, even though the hardware can support 32 bits. A word is what ACID refers to as a @lquotes@;natural hardware boundary@rquotes@;. Storage elements may, but need not be, independently addressable (see @RefSec{Shared Variables}). Words are expected to be independently addressable. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[@Defn{machine scalar} A @i{machine scalar} is an amount of storage that can be conveniently and efficiently loaded, stored, or operated upon by the hardware. Machine scalars consist of an integral number of storage elements. The set of machine scalars is implementation defined, but @Chg{Version=[3],New=[includes],Old=[must include]} at least the storage element and the word. Machine scalars are used to interpret @nt{component_clause}s when the nondefault bit ordering applies.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The set of machine scalars.]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0092-1]} @ChgAdded{Version=[3],Text=[A single storage element is a machine scalar in all Ada implementations. Similarly, a word is a machine scalar in all implementations (although it might be the same as a storage element). An implementation may define other machine scalars that make sense on the target (a half-word, for instance).]} @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0191-1]} @Chg{New=[The following representation attributes are defined: Address, Alignment, Size, Storage_Size, @Chg{Version=[3],New=[],Old=[and ]}Component_Size@Chg{Version=[3],New=[, Has_Same_Storage, and Overlaps_Storage],Old=[]}.], Old=[@Leading@;The following attributes are defined:]} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an object, program unit, or label]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Address>, Text=<Denotes the address of the first of the storage elements allocated to X. For a program unit or label, this value refers to the machine code associated with the corresponding body or @nt{statement}. The value of this attribute is of type System.Address.>} @begin{Ramification} Here, the @lquotes@;first of the storage elements@rquotes@; is intended to mean the one with the lowest address; the endianness of the machine doesn't matter. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0095-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[The prefix of X'Address shall not statically denote a subprogram that has convention Intrinsic. X'Address raises Program_Error if X denotes a subprogram that has convention Intrinsic.]} @NoPrefix@PDefn2{Term=[specifiable], Sec=(of Address for stand-alone objects and for program units)} @Defn{Address clause} @ChgNote{Removed Redundant here, as per AI-00114. Did not mark change, as it is AARM-only, not to the text of the item.}Address may be specified for stand-alone objects and for program units via an @nt{attribute_definition_clause}.@Chg{Version=[3],New=[@AspectDefn{Address}],Old=[]} @begin{Ramification} Address is not allowed for enumeration literals, predefined operators, derived task types, or derived protected types, since they are not program units. @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Address is not allowed for intrinsic subprograms, either. That can be checked statically unless the prefix is a generic formal subprogram and the attribute reference is in the body of a generic unit. We define that case to raise Program_Error, in order that the compiler does not have to build a wrapper for intrinsic subprograms.]} The validity of a given address depends on the run-time model; thus, in order to use Address clauses correctly, one needs intimate knowledge of the run-time model. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If the Address of an object is specified, any explicit or implicit initialization takes place as usual, unless @Chg{Version=[3],New=[the],Old=[a @nt{pragma}]} Import @Chg{Version=[3],New=[aspect ],Old=[]}is also specified for the object (in which case any necessary initialization is presumably done in the foreign language). Any compilation unit containing an @nt<attribute_reference> of a given type depends semantically on the declaration of the package in which the type is declared, even if not mentioned in an applicable @nt<with_clause> @em see @RefSecNum{Compilation Units - Library Units}. In this case, it means that if a compilation unit contains X'Address, then it depends on the declaration of System. Otherwise, the fact that the value of Address is of a type in System wouldn't make sense; it would violate the @lquotes@;legality determinable via semantic dependences@rquotes@; @MetaRulesName. AI83-00305 @em If X is a task type, then within the body of X, X denotes the current task object; thus, X'Address denotes the object's address. Interrupt entries and their addresses are described in @RefSec{Interrupt Entries}. If X is not allocated on a storage element boundary, X'Address points at the first of the storage elements that contains any part of X. This is important for the definition of the Position attribute to be sensible. @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Address], Text=[@ChgAdded{Version=[3],Text=[Machine address of an entity.]}]} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Erron} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} @PDefn2{Term=(erroneous execution),Sec=(cause)}If an Address is specified, it is the programmer's responsibility to ensure that the address is valid@Chg{Version=[3],New=[ and appropriate for the entity and its use],Old=[]}; otherwise, program execution is erroneous. @begin{Discussion} @ChgAdded{Version=[3],Text=[@ldquote@;Appropriate for the entity and its use@rdquote covers cases such as misaligned addresses, read-only code addresses for variable data objects (and nonexecutable data addresses for code units), and addresses which would force objects that are supposed to be independently addressable to not be. Such addresses may be @ldquote@;valid@rdquote as they designate locations that are accessible to the program, but the program execution is still erroneous (meaning that implementations do not have to worry about these cases).]} @end{Discussion} @end{Erron} @begin{ImplAdvice} For an array X, X'Address should point at the first component of the array, and not at the array bounds. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For an array X, X'Address should point at the first component of the array rather than the array bounds.]}]} @begin{Ramification} On the other hand, we have no advice to offer about discriminants and tag fields; whether or not the address points at them is not specified by the language. If discriminants are stored separately, then the Position of a discriminant might be negative, or might raise an exception. @end{Ramification} @PDefn2{Term=[recommended level of support], Sec=(Address attribute)} @Leading@;The recommended level of support for the Address attribute is: @begin{Itemize} X'Address should produce a useful result if X is an object that is aliased or of a by-reference type, or is an entity whose Address has been specified. @begin{Reason} Aliased objects are the ones for which the Unchecked_Access attribute is allowed; hence, these have to be allocated on an addressable boundary anyway. Similar considerations apply to objects of a by-reference type. An implementation need not go to any trouble to make Address work in other cases. For example, if an object X is not aliased and not of a by-reference type, and the implementation chooses to store it in a register, X'Address might return System.Null_Address (assuming registers are not addressable). For a subprogram whose calling convention is Intrinsic, or for a package, the implementation need not generate an out-of-line piece of code for it. @end{Reason} An implementation should support Address clauses for imported subprograms. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Text=[Objects (including subcomponents) that are aliased or of a by-reference type should be allocated on storage element boundaries.]} @Comment{There is a now a blanket permission to this effect} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[This is necessary for the Address attribute to be useful (since First_Bit and Last_Bit apply only to components). Implementations generally need to do this anyway, for tasking to work properly.]} @end{Reason} If the Address of an object is specified, or it is imported or exported, then the implementation should not perform optimizations based on assumptions of no aliases. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Address attribute should be followed.]}]} @end{ImplAdvice} @begin{Notes} The specification of a link name @Chg{Version=[3],New=[with the Link_Name aspect],Old=[in a @nt{pragma} Export]} (see @RefSecNum{Interfacing Aspects}) for a subprogram or object is an alternative to explicit specification of its link-time address, allowing a link-time directive to place the subprogram or object within memory. The rules for the Size attribute imply, for an aliased object X, that if X'Size = Storage_Unit, then X'Address points at a storage element containing all of the bits of X, and only the bits of X. @end{Notes} @begin{DiffWord83} The intended meaning of the various attributes, and their @nt{attribute_definition_clause}s, is more explicit. The @ntf{address_clause} has been renamed to @nt{at_clause} and moved to @RefSec{Obsolescent Features}. One can use an Address clause (@lquotes@;for T'Address @key[use] ...;@rquotes@;) instead. The attributes defined in RM83-13.7.3 are moved to @RefSecNum{Numerics}, @RefSecNum{Attributes of Floating Point Types}, and @RefSecNum{Attributes of Fixed Point Types}. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Defined that the names of aspects are the same as the name of the attribute; that gives a name to use in @nt{aspect_specification}s (see @RefSecNum{Aspect Specifications}).]} @end{DiffWord2005} @begin{MetaRules} By default, the Alignment of a subtype should reflect the @lquotes@;natural@rquotes@; alignment for objects of the subtype on the machine. The Alignment, whether specified or default, should be known at compile time, even though Addresses are generally not known at compile time. (The generated code should never need to check at run time the number of zero bits at the end of an address to determine an alignment). There are two symmetric purposes of Alignment clauses, depending on whether or not the implementation has control over object allocation. If the implementation allocates an object, the implementation should ensure that the Address and Alignment are consistent with each other. If something outside the implementation allocates an object, the implementation should be allowed to assume that the Address and Alignment are consistent, but should not assume stricter alignments than that. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes @Chg{Version=[2],New=[an], Old=[a subtype or]} object]}: @begin{Description} @ChgAttribute{Version=[2], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<X>, AttrName=<Alignment>, ARef=[AI95-00291-02], Text=[@Chg{Version=[2],New=[The value of this attribute is of type @i{universal_integer}, and nonnegative; zero means that the object is not necessarily aligned on a storage element boundary. If X'Alignment is not zero, then X is aligned on a storage unit boundary and X'Address], Old=[The Address of an object that is allocated under control of the implementation]} is an integral multiple of @Chg{Version=[2],New=[X'Alignment],Old=[the Alignment of the object]} (that is, the Address modulo the Alignment is zero).@Chg{Version=[2], New=[],Old=[The offset of a record component is a multiple of the Alignment of the component. For an object that is not allocated under control of the implementation (that is, one that is imported, that is allocated by a user-defined allocator, whose Address has been specified, or is designated by an access value returned by an instance of Unchecked_Conversion), the implementation may assume that the Address is an integral multiple of its Alignment. The implementation shall not assume a stricter alignment.]} @Comment{Deleted below causes trouble in the generated text for attributes, but no fix appears to be possible. And the trouble is much worse in the RTF version than the HTML version, so for now we're making a hand fix.} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[The value of this attribute is of type @i{universal_integer}, and nonnegative; zero means that the object is not necessarily aligned on a storage element boundary.]}]}@Comment{End X'Alignment} @EndPrefixType{} @begin{Ramification} The Alignment is passed by an @nt{allocator} to the Allocate operation; the implementation has to choose a value such that if the address returned by Allocate is aligned as requested, the generated code can correctly access the object. The above mention of @lquotes@;modulo@rquotes@; is referring to the "@key[mod]" operator declared in System.Storage_Elements; if X @key[mod] N = 0, then X is by definition aligned on an N-storage-element boundary. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @NoPrefix@Chg{Version=[2],New=[@PDefn2{Term=[specifiable], Sec=(of Alignment for objects)}], Old=[@PDefn2{Term=[specifiable], Sec=(of Alignment for first subtypes and objects)}]} @Defn{Alignment clause} Alignment may be specified for@Chg{Version=[2],New=[],Old=[ first subtypes and]} @Redundant[stand-alone] objects via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative.@Chg{Version=[2],New=[],Old=[If the Alignment of a subtype is specified, then the Alignment of an object of the subtype is at least as strict, unless the object's Alignment is also specified. The Alignment of an object created by an allocator is that of the designated subtype.@Chg{Version=[3],New=[@AspectDefn{Alignment (object)}],Old=[]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Alignment (object)], Text=[@ChgAdded{Version=[3],Text=[Alignment of an object.]}]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00247-01]} @ChgDeleted{Version=[2],NoPrefix=[T],Text=[If an Alignment is specified for a composite subtype or object, this Alignment shall be equal to the least common multiple of any specified Alignments of the subcomponent subtypes, or an integer multiple thereof.]} @end{Description} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Type=[Leading],KeepNext=[T], Text=[For @PrefixType{every subtype S}:]} @begin{Description} @ChgAttribute{Version=[2], Kind=[Added], ChginAnnex=[T], Leading=[F], Prefix=<S>, AttrName=<Alignment>, ARef=[AI95-00291-02], Text=[@Chg{Version=[2],New=[The value of this attribute is of type @i{universal_integer}, and nonnegative.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],NoPrefix=[T], Text=[For an object X of subtype S, if S'Alignment is not zero, then X'Alignment is a nonzero integral multiple of S'Alignment unless specified otherwise by a representation item.]}]}@Comment{End S'Alignment} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],NoPrefix=[T], Text=[@PDefn2{Term=[specifiable], Sec=(of Alignment for first subtypes)} @Defn{Alignment clause} Alignment may be specified for first subtypes via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative.@Chg{Version=[3],New=[@AspectDefn{Alignment (subtype)}],Old=[]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Alignment (subtype)], Text=[@ChgAdded{Version=[3],Text=[Alignment of a subtype.]}]} @end{Description} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if an Address clause is given that conflicts with the Alignment. @begin{Ramification} The user has to either give an Alignment clause also, or else know what Alignment the implementation will choose by default. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @PDefn2{Term=(erroneous execution),Sec=(cause)} @Chg{Version=[2],New=[For],Old=[If the Alignment is specified for]} an object that is not allocated under control of the implementation, execution is erroneous if the object is not aligned according to @Chg{Version=[2],New=[its],Old=[the]} Alignment. @end{Erron} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0116-1]} @ChgAdded{Version=[3],Text=[For any tagged specific subtype @i<S>, @i<S>'Class'Alignment should equal @i<S>'Alignment.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A tagged object should never be less aligned than the alignment of the type of its view, so for a class-wide type T'Class, the alignment should be no greater than that of any type covered by T'Class. If the implementation only supports alignments that are required by the recommended level of support (and this is most likely), then the alignment of any covered type has to be the same or greater than that of T @em which leaves the only reasonable value of T'Class'Alignment being T'Alignment. Thus we recommend this, but don't require it so that in the unlikely case that the implementation does support smaller alignments for covered types, it can select a smaller value for T'Class'Alignment.]} @end{Reason} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[For any tagged specific subtype @i<S>, @i<S>'Class'Alignment should equal @i<S>'Alignment.]}]} @PDefn2{Term=[recommended level of support], Sec=(Alignment attribute for subtypes)} @Leading@;The recommended level of support for the Alignment attribute for subtypes is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation should support @Chg{Version=[2],New=[an Alignment clause for a discrete type, fixed point type, record type, or array type, specifying an Alignment value that is zero or a power of two],Old=[specified Alignments that are factors and multiples of the number of storage elements per word]}, subject to the following: @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation need not support @Chg{Version=[2], New=[an Alignment clause for a signed integer type specifying an Alignment greater than the largest Alignment value that is ever chosen by default by the implementation for any signed integer type. A corresponding limitation may be imposed for modular integer types, fixed point types, enumeration types, record types, and array types],Old=[specified Alignments for combinations of Sizes and Alignments that cannot be easily loaded and stored by available machine instructions]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} An implementation need not support @Chg{Version=[2],New=[a nonconfirming Alignment clause which could enable the creation of an object of an elementary type which cannot be easily loaded and stored by available machine instructions.], Old=[specified Alignments that are greater than the maximum Alignment the implementation ever returns by default.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support an Alignment specified for a derived tagged type which is not a multiple of the Alignment of the parent type. An implementation need not support a nonconfirming Alignment specified for a derived untagged by-reference type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[There is no recommendation to support any nonconfirming Alignment clauses for types not mentioned above. Remember that @RefSecNum{Operational and Representation Aspects} requires support for confirming Alignment clauses for all types.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0116-1]} @ChgAdded{Version=[3],Text=[An implementation that tries to support other alignments for derived tagged types will need to allow inherited subprograms to be passed objects that are less aligned than expected by the parent subprogram and type. This is unlikely to work if alignment has any effect on code selection. Similar issues arise for untagged derived types whose parameters are passed by reference.]} @end{ImplNote} @end{Itemize} @Leading@PDefn2{Term=[recommended level of support], Sec=(Alignment attribute for objects)} The recommended level of support for the Alignment attribute for objects is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Text=[Same as above, for subtypes, but in addition:]} For stand-alone library-level objects of statically constrained subtypes, the implementation should support all Alignments supported by the target linker. For example, page alignment is likely to be supported for such objects, but not for subtypes. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[For other objects, an implementation should at least support the alignments supported for their subtype, subject to the following:]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[An implementation need not support Alignments specified for objects of a by-reference type or for objects of types containing aliased subcomponents if the specified Alignment is not a multiple of the Alignment of the subtype of the object.]} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Alignment attribute should be followed.]}]} @end{ImplAdvice} @begin{Notes} Alignment is a subtype-specific attribute. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00247-01]} @ChgDeleted{Version=[2],Text=[The Alignment of a composite object is always equal to the least common multiple of the Alignments of its components, or a multiple thereof.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[For default Alignments, this follows from the semantics of Alignment. For specified Alignments, it follows from a @LegalityName stated above.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} A @nt{component_clause}, Component_Size clause, or @Chg{Version=[3],New=[specifying the],Old=[a @nt{pragma}]} Pack @Chg{Version=[3],New=[aspect as True ],Old=[]}can override a specified Alignment. @begin{Discussion} Most objects are allocated by the implementation; for these, the implementation obeys the Alignment. The implementation is of course allowed to make an object @i{more} aligned than its Alignment requires @em an object whose Alignment is 4 might just happen to land at an address that's a multiple of 4096. For formal parameters, the implementation might want to force an Alignment stricter than the parameter's subtype. For example, on some systems, it is customary to always align parameters to 4 storage elements. Hence, one might initially assume that the implementation could evilly make all Alignments 1 by default, even though integers, say, are normally aligned on a 4-storage-element boundary. However, the implementation cannot get away with that @em if the Alignment is 1, the generated code cannot assume an Alignment of 4, at least not for objects allocated outside the control of the implementation. Of course implementations can assume anything they can prove, but typically an implementation will be unable to prove much about the alignment of, say, an imported object. Furthermore, the information about where an address @lquotes@;came from@rquotes@; can be lost to the compiler due to separate compilation. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The Alignment of an object that is a component of a packed composite object will usually be 0, to indicate that the component is not necessarily aligned on a storage element boundary. For a subtype, an Alignment of 0 means that objects of the subtype are not normally aligned on a storage element boundary at all. For example, an implementation might choose to make Component_Size be @Chg{Version=[2],New=[1],Old=[0]} for an array of Booleans, even when @Chg{Version=[3],New=[the],Old=[@nt{pragma}]} Pack @Chg{Version=[3],New=[aspect ],Old=[]}has not been specified for the array. In this case, Boolean'Alignment would be 0. (In the presence of tasking, this would in general be feasible only on a machine that had atomic test-bit and set-bit instructions.) If the machine has no particular natural alignments, then all subtype Alignments will probably be 1 by default. Specifying an Alignment of 0 in an @nt{attribute_definition_clause} does not require the implementation to do anything (except return 0 when the Alignment is queried). However, it might be taken as advice on some implementations. It is an error for an Address clause to disobey the object's Alignment. The error cannot be detected at compile time, in general, because the Address is not necessarily known at compile time (and is almost certainly not static). We do not require a run-time check, since efficiency seems paramount here, and Address clauses are treading on thin ice anyway. Hence, this misuse of Address clauses is just like any other misuse of Address clauses @em it's erroneous. A type extension can have a stricter Alignment than its parent. This can happen, for example, if the Alignment of the parent is 4, but the extension contains a component with Alignment 8. The Alignment of a class-wide type or object will have to be the maximum possible Alignment of any extension. The recommended level of support for the Alignment attribute is intended to reflect a minimum useful set of capabilities. An implementation can assume that all Alignments are multiples of each other @em 1, 2, 4, and 8 might be the only supported Alignments for subtypes. An Alignment of 3 or 6 is unlikely to be useful. For objects that can be allocated statically, we recommend that the implementation support larger alignments, such as 4096. We do not recommend such large alignments for subtypes, because the maximum subtype alignment will also have to be used as the alignment of stack frames, heap objects, and class-wide objects. Similarly, we do not recommend such large alignments for stack-allocated objects. If the maximum default Alignment is 8 (say, Long_Float'Alignment = 8), then the implementation can refuse to accept stricter alignments for subtypes. This simplifies the generated code, since the compiler can align the stack and class-wide types to this maximum without a substantial waste of space (or time). Note that the recommended level of support takes into account interactions between Size and Alignment. For example, on a 32-bit machine with 8-bit storage elements, where load and store instructions have to be aligned according to the size of the thing being loaded or stored, the implementation might accept an Alignment of 1 if the Size is 8, but might reject an Alignment of 1 if the Size is 32. On a machine where unaligned loads and stores are merely inefficient (as opposed to causing hardware traps), we would expect an Alignment of 1 to be supported for any Size. @end{Discussion} @end{Notes} @begin{DiffWord83} The nonnegative part is missing from RM83 (for @nt{mod_clause}s, nee @ntf{alignment_clause}s, which are an obsolete version of Alignment clauses). @end{DiffWord83} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an object]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Size>, Text=<Denotes the size in bits of the representation of the object. The value of this attribute is of the type @i{universal_integer}.>} @EndPrefixType{} @begin{Ramification} Note that Size is in bits even if Machine_Radix is 10. Each decimal digit (and the sign) is presumably represented as some number of bits. @end{Ramification} @NoPrefix@PDefn2{Term=[specifiable], Sec=(of Size for stand-alone objects)} @Defn{Size clause} Size may be specified for @Redundant[stand-alone] objects via an @nt{attribute_definition_clause}; the expression of such a clause shall be static and its value nonnegative.@Chg{Version=[3],New=[@AspectDefn{Size (object)}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Size (object)], Text=[@ChgAdded{Version=[3],Text=[Size in bits of an object.]}]} @end{Description} @end{StaticSem} @begin{ImplAdvice} @ChgNote{Moved from 13.9} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[The size of an array object should not include its bounds.]} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The Size of an array object should not include its bounds.]}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02],ARef=[AI95-00291-02]} @ChgDeleted{Version=[2],Type=[Leading],Text=[]}@Comment{A fake to get a conditional Leading} @PDefn2{Term=[recommended level of support], Sec=(Size attribute)} The recommended level of support for the Size attribute of objects is@Chg{Version=[2],New=[ the same as for subtypes (see below), except that only a confirming Size clause need be supported for an aliased elementary object.],Old=[:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00051-02]} @ChgDeleted{Version=[2],Text=[A Size clause should be supported for an object if the specified Size is at least as large as its subtype's Size, and corresponds to a size in storage elements that is a multiple of the object's Alignment (if the Alignment is nonzero).]} @Comment{No ImplDef summary here; there is no reason to separately mention it} @end{Itemize} @end{ImplAdvice} @begin{StaticSem} @Leading@Keepnext@;For @PrefixType{every subtype S}: @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Size>, Text=<If S is definite, denotes the size @Redundant{(in bits)} that the implementation would choose for the following objects of subtype S: @begin{Itemize} A record component of subtype S when the record type is packed. The formal parameter of an instance of Unchecked_Conversion that converts from subtype S to some other subtype. @end{Itemize} @NoPrefix@;If S is indefinite, the meaning is implementation defined. The value of this attribute is of the type @i{universal_integer}.>} @PDefn2{Term=[specifiable], Sec=(of Size for first subtypes)} @Defn{Size clause} The Size of an object is at least as large as that of its subtype, unless the object's Size is determined by a Size clause, a component_clause, or a Component_Size clause. Size may be specified for first subtypes via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static and its value nonnegative.@Chg{Version=[3],New=[@AspectDefn{Size (subtype)}],Old=[]} @ImplDef{The meaning of Size for indefinite subtypes.} @begin{Reason} @Leading@;The effects of specifying the Size of a subtype are: @begin{Itemize} Unchecked_Conversion works in a predictable manner. A composite type cannot be packed so tightly as to override the specified Size of a component's subtype. Assuming the @ImplAdviceName is obeyed, if the specified Size allows independent addressability, then the Size of certain objects of the subtype should be equal to the subtype's Size. This applies to stand-alone objects and to components (unless a @nt{component_clause} or a Component_Size clause applies). @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} A @nt{component_clause} or a Component_Size clause can cause an object to be smaller than its subtype's specified size. @Chg{Version=[3],New=[The aspect],Old=[A @nt{pragma}]} Pack cannot; if a component subtype's size is specified, this limits how tightly the composite object can be packed. The Size of a class-wide (tagged) subtype is unspecified, because it's not clear what it should mean; it should certainly not depend on all of the descendants that happen to exist in a given program. Note that this cannot be detected at compile time, because in a generic unit, it is not necessarily known whether a given subtype is class-wide. It might raise an exception on some implementations. @end{Reason} @begin{Ramification} @Leading@;A Size clause for a numeric subtype need not affect the underlying numeric type. For example, if I say: @begin{Example} @key[type] S @key[is] @key[range] 1..2; @key[for] S'Size @key[use] 64; @end{Example} I am not guaranteed that S'Base'Last >= 2**63@en@;1, nor that intermediate results will be represented in 64 bits. @end{Ramification} @begin{Reason} There is no need to complicate implementations for this sort of thing, because the right way to affect the base range of a type is to use the normal way of declaring the base range: @begin{Example} @key[type] Big @key[is] @key[range] -2**63 .. 2**63 - 1; @key[subtype] Small @key[is] Big @key[range] 1..1000; @end{Example} @end{Reason} @begin{Ramification} The Size of a large unconstrained subtype (e.g. String'Size) is likely to raise Constraint_Error, since it is a nonstatic expression of type @i{universal_integer} that might overflow the largest signed integer type. There is no requirement that the largest integer type be able to represent the size in bits of the largest possible object. @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Size (subtype)], Text=[@ChgAdded{Version=[3],Text=[Size in bits of a subtype.]}]} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplReq} In an implementation, Boolean'Size shall be 1. @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} @Leading@;If the Size of a subtype @Chg{Version=[2],New=[],Old=[is specified, and ]}allows for efficient independent addressability (see @RefSecNum{Shared Variables}) on the target architecture, then the Size of the following objects of the subtype should equal the Size of the subtype: @begin{Itemize} Aliased objects (including components). Unaliased components, unless the Size of the component is determined by a @nt{component_clause} or Component_Size clause. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If the Size of a subtype allows for efficient independent addressability, then the Size of most objects of the subtype should equal the Size of the subtype.]}]} @begin{Ramification} Thus, on a typical 32-bit machine, @lquotes@;@key[for] S'Size @key[use] 32;@rquotes@; will guarantee that aliased objects of subtype S, and components whose subtype is S, will have Size = 32 (assuming the implementation chooses to obey this @ImplAdviceTitle). On the other hand, if one writes, @lquotes@;@key[for] S2'Size @key[use] 5;@rquotes@; then stand-alone objects of subtype S2 will typically have their Size rounded up to ensure independent addressability. Note that @lquotes@;@key[for] S'Size @key[use] 32;@rquotes@; does not cause things like formal parameters to have Size = 32 @em the implementation is allowed to make all parameters be at least 64 bits, for example. Note that @lquotes@;@key[for] S2'Size @key[use] 5;@rquotes@; requires record components whose subtype is S2 to be exactly 5 bits if the record type is packed. The same is not true of array components; their Size may be rounded up to the nearest factor of the word size. @end{Ramification} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} @Defn{gaps} On most machines, arrays don't contain gaps between @Chg{Version=[2], New=[elementary ],Old=[]}components; if the Component_Size is greater than the Size of the component subtype, the extra bits are generally considered part of each component, rather than gaps between components. On the other hand, a record might contain gaps between @Chg{Version=[2], New=[elementary ],Old=[]}components, depending on what sorts of loads, stores, and masking operations are generally done by the generated code. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00291-02]} For an array, any extra bits stored for each @Chg{Version=[2], New=[elementary ],Old=[]}component will generally be part of the component @em the whole point of storing extra bits is to make loads and stores more efficient by avoiding the need to mask out extra bits. The PDP-10 is one counter-example; since the hardware supports byte strings with a gap at the end of each word, one would want to pack in that manner. @end{ImplNote} A Size clause on a composite subtype should not affect the internal layout of components. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[A Size clause on a composite subtype should not affect the internal layout of components.]}]} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} That's what Pack @Chg{Version=[3],New=[aspects],Old=[@nt{pragma}s]}, @nt{record_representation_clause}s, and Component_Size clauses are for. @end{Reason} @Leading@PDefn2{Term=[recommended level of support], Sec=(Size attribute)} The recommended level of support for the Size attribute of subtypes is: @begin{Itemize} The Size (if not specified) of a static discrete or fixed point subtype should be the number of bits needed to represent each value belonging to the subtype using an unbiased representation, leaving space for a sign bit only if the subtype contains negative values. If such a subtype is a first subtype, then an implementation should support a specified Size for it that reflects this representation. @begin{ImplNote} This applies to static enumeration subtypes, using the internal codes used to represent the values. For a two's-complement machine, this implies that for a static signed integer subtype S, if all values of S are in the range 0 .. 2@+{@i{n}}@en@;1, or all values of S are in the range @en@;2@+{@i{n@en@;1}} .. 2@+{@i{n@en@;1}}@en@;1, for some @i{n} less than or equal to the word size, then S'Size should be <= the smallest such @i{n}. For a one's-complement machine, it is the same except that in the second range, the lower bound @lquotes@;@en@;2@+{@i{n@en@;1}}@rquotes@; is replaced by @lquotes@;@en@;2@+{@i{n@en@;1}}+1@rquotes@;. If an integer subtype (whether signed or unsigned) contains no negative values, the Size should not include space for a sign bit. Typically, the implementation will choose to make the Size of a subtype be exactly the smallest such @i{n}. However, it might, for example, choose a biased representation, in which case it could choose a smaller value. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} On most machines, it is in general not a good idea to pack (parts of) multiple stand-alone objects into the same storage element, because (1) it usually doesn't save much space, and (2) it requires locking to prevent tasks from interfering with each other, since separate stand-alone objects are independently addressable. Therefore, if S'Size = 2 on a machine with 8-bit storage elements, the size of a stand-alone object of subtype S will probably not be 2. It might, for example, be 8, 16 or 32, depending on the availability and efficiency of various machine instructions. The same applies to components of composite types, unless @Chg{Version=[3],New=[Pack],Old=[packing]}, Component_Size, or record layout is specified. For an unconstrained discriminated object, if the implementation allocates the maximum possible size, then the Size attribute should return that maximum possible size. @end{ImplNote} @begin{Ramification} The Size of an object X is not usually the same as that of its subtype S. If X is a stand-alone object or a parameter, for example, most implementations will round X'Size up to a storage element boundary, or more, so X'Size might be greater than S'Size. On the other hand, X'Size cannot be less than S'Size, even if the implementation can prove, for example, that the range of values actually taken on by X during execution is smaller than the range of S. For example, if S is a first integer subtype whose range is 0..3, S'Size will be probably be 2 bits, and components of packed composite types of this subtype will be 2 bits (assuming Storage_Unit is a multiple of 2), but stand-alone objects and parameters will probably not have a size of 2 bits; they might be rounded up to 32 bits, for example. On the other hand, Unchecked_Conversion will use the 2-bit size, even when converting a stand-alone object, as one would expect. Another reason for making the Size of an object bigger than its subtype's Size is to support the run-time detection of uninitialized variables. @PDefn{uninitialized variables} The implementation might add an extra value to a discrete subtype that represents the uninitialized state, and check for this value on use. In some cases, the extra value will require an extra bit in the representation of the object. Such detection is not required by the language. If it is provided, the implementation has to be able to turn it off. For example, if the programmer gives a @nt{record_representation_clause} or Component_Size clause that makes a component too small to allow the extra bit, then the implementation will not be able to perform the checking (not using this method, anyway). @Leading@;The fact that the size of an object is not necessarily the same as its subtype can be confusing: @begin{Example} @key[type] Device_Register @key[is] @key[range] 0..2**8 - 1; @key[for] Device_Register'Size @key[use] 8; --@RI{ Confusing!} My_Device : Device_Register; @key[for] My_Device'Address @key[use] To_Address(16#FF00#); @end{Example} The programmer might think that My_Device'Size is 8, and that My_Device'Address points at an 8-bit location. However, this is not true. In Ada 83 (and in Ada 95), My_Device'Size might well be 32, and My_Device'Address might well point at the high-order 8 bits of the 32-bit object, which are always all zero bits. If My_Device'Address is passed to an assembly language subprogram, based on the programmer's assumption, the program will not work properly. @end{Ramification} @begin{Reason} It is not reasonable to require that an implementation allocate exactly 8 bits to all objects of subtype Device_Register. For example, in many run-time models, stand-alone objects and parameters are always aligned to a word boundary. Such run-time models are generally based on hardware considerations that are beyond the control of the implementer. (It is reasonable to require that an implementation allocate exactly 8 bits to all components of subtype Device_Register, if packed.) @end{Reason} @begin{Ramification} @Leading@;The correct way to write the above code is like this: @begin{Example} @key[type] Device_Register @key[is] @key[range] 0..2**8 - 1; My_Device : Device_Register; @key[for] My_Device'Size @key[use] 8; @key[for] My_Device'Address @key[use] To_Address(16#FF00#); @end{Example} If the implementation cannot accept 8-bit stand-alone objects, then this will be illegal. However, on a machine where an 8-bit device register exists, the implementation will probably be able to accept 8-bit stand-alone objects. Therefore, My_Device'Size will be 8, and My_Device'Address will point at those 8 bits, as desired. If an object of subtype Device_Register is passed to a foreign language subprogram, it will be passed according to that subprogram's conventions. Most foreign language implementations have similar run-time model restrictions. For example, when passing to a C function, where the argument is of the C type char* (that is, pointer to char), the C compiler will generally expect a full word value, either on the stack, or in a register. It will @i{not} expect a single byte. Thus, Size clauses for subtypes really have nothing to do with passing parameters to foreign language subprograms. @end{Ramification} For a subtype implemented with levels of indirection, the Size should include the size of the pointers, but not the size of what they point at. @begin{Ramification} For example, if a task object is represented as a pointer to some information (including a task stack), then the size of the object should be the size of the pointer. The Storage_Size, on the other hand, should include the size of the stack. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Type=[Leading],Text=[An implementation should support a Size clause for a discrete type, fixed point type, record type, or array type, subject to the following:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[An implementation need not support a Size clause for a signed integer type specifying a Size greater than that of the largest signed integer type supported by the implementation in the absence of a size clause (that is, when the size is chosen by default). A corresponding limitation may be imposed for modular integer types, fixed point types, enumeration types, record types, and array types.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[Note that the @lquotes@;corresponding limitation@rquotes for a record or array type implies that an implementation may impose some reasonable maximum size for records and arrays (e.g. 2**32 bits), which is an upper bound (@lquotes@;capacity@rquotes limit) on the size, whether chosen by default or by being specified by the user. The largest size supported for records need not be the same as the largest size supported for arrays.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0155-1]} @ChgAdded{Version=[3],Text=[Only Size clauses with a size greater than or equal to the Size that would be chosen by default may be safely presumed to be supported on nonstatic elementary subtypes. Implementations may choose to support smaller sizes, but only if the Size allows any value of the subtype to be represented, for any possible value of the bounds.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[A nonconfirming size clause for the first subtype of a derived untagged by-reference type need not be supported.]} @end{InnerItemize} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Size attribute should be followed.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[There is no recommendation to support any nonconfirming Size clauses for types not mentioned above. Remember that @RefSecNum{Operational and Representation Aspects} requires support for confirming Size clauses for all types.]} @end{Ramification} @end{ImplAdvice} @begin{Notes} Size is a subtype-specific attribute. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} A @nt{component_clause} or Component_Size clause can override a specified Size. @Chg{Version=[3],New=[Aspect],Old=[A @nt{pragma}]} Pack cannot. @end{Notes} @begin{Inconsistent83} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 83}We specify the meaning of Size in much more detail than Ada 83. This is not technically an inconsistency, but it is in practice, as most Ada 83 compilers use a different definition for Size than is required here. This should have been documented more explicitly during the Ada 9X process.]} @end{Inconsistent83} @begin{DiffWord83} The requirement for a nonnegative value in a Size clause was not in RM83, but it's hard to see how it would make sense. For uniformity, we forbid negative sizes, rather than letting implementations define their meaning. @end{DiffWord83} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} T that denotes a task object @Redundant[(after any implicit dereference)]]}: @begin{Description} @ChgAttribute{Version=[3], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<T>, AttrName=<Storage_Size>, ARef=[AI05-0229-1], Text=<Denotes the number of storage elements reserved for the task. The value of this attribute is of the type @i{universal_integer}. The Storage_Size includes the size of the task's stack, if any. The language does not specify whether or not it includes other storage associated with the task (such as the @lquotes@;task control block@rquotes@; used by some implementations.)>} If @Chg{Version=[3],New=[the aspect],Old=[a @nt{pragma}]} Storage_Size is @Chg{Version=[3],New=[specified for the type of the object],Old=[given]}, the value of the Storage_Size attribute is at least the value @Chg{Version=[3],New=[determined by the aspect],Old=[specified in the @nt{pragma}]}. @EndPrefixType{} @begin{Ramification} The value of this attribute is never negative, since it is impossible to @lquotes@;reserve@rquotes@; a negative number of storage elements. If the implementation chooses to allocate an initial amount of storage, and then increase this as needed, the Storage_Size cannot include the additional amounts (assuming the allocation of the additional amounts can raise Storage_Error); this is inherent in the meaning of @lquotes@;reserved.@rquotes@; The implementation is allowed to allocate different amounts of storage for different tasks of the same subtype. Storage_Size is also defined for access subtypes @em see @RefSecNum{Storage Management}. @end{Ramification} @end{Description} @end{StaticSem} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI95-0229-1]} @redundant[@Chg{Version=[3],New=[Aspect],Old=[@IndexSeeAlso{Term=[Storage_Size clause],See=[pragma Storage_Size]} A @nt{pragma}]} Storage_Size specifies the amount of storage to be reserved for the execution of a task.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 62 through 65 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Storage_Size is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Storage_Size)(@Syn2{expression});]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[A @nt{pragma} Storage_Size is allowed only immediately within a @nt{task_definition}.]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[expected type], Sec=(Storage_Size pragma argument)} The @nt{expression} of a @nt<pragma> Storage_Size is expected to be of any integer type.]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a task type (including the anonymous type of a @nt{single_task_declaration}), the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Storage_Size@\The Storage_Size aspect is an @nt{expression}, which shall be of any integer type.@AspectDefn{Storage_Size (task)}]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This definition somewhat conflicts with the "automatic" one for the obsolescent attribute Storage_Size (which can be specified). The only difference is where the given expression is evaluated. We intend for the above definition to supersede that "automatic" definition for this attribute.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that the value of the Storage_Size aspect @i<is> an @nt{expression}; it is not the @i<value> of an @nt{expression}. The @nt{expression} is evaluated for each object of the type (see below).]} @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Storage_Size (task)], Text=[@ChgAdded{Version=[3],Text=[Size in storage elements reserved for a task type or single task object.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The Storage_Size aspect shall not be specified for a task interface type.]} @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[When a task object is created, the @nt{expression} (if any) associated with the Storage_Size aspect of its type],Old=[A @nt<pragma> Storage_Size is elaborated when an object of the type defined by the immediately enclosing @nt<task_definition> is created. @PDefn2{Term=[elaboration],Sec=(Storage_Size pragma)} For the elaboration of a @nt<pragma> Storage_Size, the @nt<expression>]} is evaluated; the Storage_Size attribute of the newly created task object is at least the value of the @nt<expression>. @begin{Ramification} The implementation is allowed to round up a specified Storage_Size amount. For example, if the implementation always allocates in chunks of 4096 bytes, the number 200 might be rounded up to 4096. Also, if the user specifies a negative number, the implementation has to normalize this to 0, or perhaps to a positive number. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If the Storage_Size aspect is not specified for the type of the task object, the value of the Storage_Size attribute is unspecified.]} @end{Ramification} @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} At the point of task object creation, or upon task activation, Storage_Error is raised if there is insufficient free storage to accommodate the requested Storage_Size. @end{RunTime} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} X that denotes an array subtype or array object @Redundant[(after any implicit dereference)]]}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Component_Size>, Text=<Denotes the size in bits of components of the type of X. The value of this attribute is of type @i{universal_integer}.>} @EndPrefixType{} @NoPrefix@PDefn2{Term=[specifiable], Sec=(of Component_Size for array types)}@Defn{Component_Size clause} Component_Size may be specified for array types via an @nt{attribute_@!definition_@!clause}; the expression of such a clause shall be static, and its value nonnegative.@Chg{Version=[3],New=[@AspectDefn{Component_Size}],Old=[]} @begin{ImplNote} The intent is that the value of X'Component_Size is always nonnegative. If the array is stored @lquotes@;backwards@rquotes@; in memory (which might be caused by an implementation-defined pragma), X'Component_Size is still positive. @end{ImplNote} @begin{Ramification} For an array object A, A'Component_Size = A(I)'Size for any index I. @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Component_Size], Text=[@ChgAdded{Version=[3],Text=[Size in bits of a component of an array type.]}]} @end{Description} @end{StaticSem} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(Component_Size attribute)} The recommended level of support for the Component_Size attribute is: @begin{Itemize} An implementation need not support specified Component_Sizes that are less than the Size of the component subtype. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation should support specified Component_Sizes that are factors and multiples of the word size. For such Component_Sizes, the array should contain no gaps between components. For other Component_Sizes (if supported), the array should contain no gaps between components when @Chg{Version=[3],New=[Pack],Old=[packing]} is also specified; the implementation should forbid this combination in cases where it cannot support a no-gaps representation. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For example, if Storage_Unit = 8, and Word_Size = 32, then the user is allowed to specify a Component_Size of 1, 2, 4, 8, 16, and 32, with no gaps. In addition, @i{n}*32 is allowed for positive integers @i{n}, again with no gaps. If the implementation accepts Component_Size = 3, then it might allocate 10 components per word, with a 2-bit gap at the end of each word (unless @Chg{Version=[3],New=[Pack],Old=[packing]} is also specified), or it might not have any internal gaps at all. (There can be gaps at either end of the array.) @end{Ramification} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Component_Size attribute should be followed.]}]} @end{ImplAdvice} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For @PrefixType{a @nt{prefix} X that denotes an object}:]} @begin(description) @ChgAttribute{Version=[3],Kind=[Added],ChginAnnex=[T], Leading=<F>, Prefix=<X>, AttrName=<Has_Same_Storage>, ARef=[AI05-0191-1], Text=[@Chg{Version=[3],New=[X'Has_Same_Storage denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key(function) X'Has_Same_Storage (@RI{Arg} : @RI{any_type}) @key(return) Boolean]} @end(Descexample) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[The actual parameter shall be a name that denotes an object. The object denoted by the actual parameter can be of any type. This function evaluates the names of the objects involved and returns True if the representation of the object denoted by the actual parameter occupies exactly the same bits as the representation of the object denoted by X; otherwise, it returns False.]}]}@Comment{End of Annex text here.} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Has_Same_Storage means that, if the representation is contiguous, the objects sit at the same address and occupy the same length of memory.]} @end{Discussion} @end(description) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For @PrefixType{a @nt{prefix} X that denotes an object}:]} @begin(description) @ChgAttribute{Version=[3],Kind=[Added],ChginAnnex=[T], Leading=<F>, Prefix=<X>, AttrName=<Overlaps_Storage>, ARef=[AI05-0191-1], Text=[@Chg{Version=[3],New=[X'Overlaps_Storage denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key(function) X'Overlaps_Storage (@RI{Arg} : @RI{any_type}) @key(return) Boolean]} @end(Descexample) @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[The actual parameter shall be a name that denotes an object. The object denoted by the actual parameter can be of any type. This function evaluates the names of the objects involved and returns True if the representation of the object denoted by the actual parameter shares at least one bit with the representation of the object denoted by X; otherwise, it returns False.]}]}@Comment{End of Annex text here.} @end(description) @end{StaticSem} @begin{Notes} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1]} @ChgAdded{Version=[3],Text=[X'Has_Same_Storage(Y) implies X'Overlaps_Storage(Y).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0191-1]} @ChgAdded{Version=[3],Text=[X'Has_Same_Storage(Y) and X'Overlaps_Storage(Y) are not considered to be reads of X and Y.]} @end{Notes} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0183-1]} @ChgAdded{Version=[1],Text=[The following @Chg{Version=[3],New=[type-related ],Old=[]}operational attribute is defined: External_Tag.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Leading@;For @PrefixType{every subtype S of a tagged type @i(T) (specific or class-wide)}@Chg{New=[],Old=[, the following attribute is defined]}: @begin{Description} @Comment{Original. @ChgAttribute{Version=[1], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<External_Tag>, Ref=[8652/0040], ARef=[AI95-00108-01], ...} We don't have a way to change multiple versions for attributes.} @ChgAttribute{Version=[3], Kind=[Revised], ChginAnnex=[F], Leading=[F], Prefix=<S>, AttrName=<External_Tag>, Ref=[8652/0040], ARef=[AI95-00108-01], ARef=[AI05-0092-1], Text=[@Defn{External_Tag clause} @PDefn2{Term=(specifiable), Sec=(of External_Tag for a tagged type)} S'External_Tag denotes an external string representation for S'Tag; it is of the predefined type String. External_Tag may be specified for a specific tagged type via an @nt{attribute_definition_clause}; the expression of such a clause shall be static.@Chg{Version=[3],New=[@AspectDefn{External_Tag}],Old=[]} The default external tag representation is implementation defined. See @Chg{Version=[3],New=[],Old=[@RefSecNum{Dispatching Operations of Tagged Types} and ]}@RefSecNum{Stream-Oriented Attributes}.]} @Chg{New=[The value of External_Tag is never inherited@Redundant[; the default value is always used unless a new value is directly specified for a type].],Old=[]} @ImplDef{The default external representation for a type tag.} @end{Description} @EndPrefixType() @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[External_Tag], Text=[@ChgAdded{Version=[3],Text=[Unique identifier for a tagged type in streams.]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0113-1]} @ChgAdded{Version=[3],Text=[If a user-specified external tag S'External_Tag is the same as T'External_Tag for some other tagged type declared by a different declaration in the partition, Program_Error is raised by the elaboration of the @nt{attribute_definition_clause}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule does not depend on the visibility of the other tagged type, but it does depend on the existence of the other tagged type. The other tagged type could have the default external tag or a user-specified external tag.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule allows the same declaration to be elaborated multiple times. In that case, different types could have the same external tag. If that happens, Internal_Tag would return some unspecified tag, and Descendant_Tag probably would return the intended tag (using the given ancestor to determine which type is intended). However, in some cases (such as multiple instantiations of a derived tagged type declared in a generic body), Tag_Error might be raised by Descendant_Tag if multiple types are identified.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that while there is a race condition inherent in this definition (which attribute_definition_clause raises Program_Error depends on the order of elaboration), it doesn't matter as a program with two such clauses is simply wrong. Two types that both come from the same declaration are allowed, as noted previously.]} @end{Ramification} @end{RunTime} @begin{ImplReq} In an implementation, the default external tag for each specific tagged type declared in a partition shall be distinct, so long as the type is declared outside an instance of a generic body. If the compilation unit in which a given tagged type is declared, and all compilation units on which it semantically depends, are the same in two different partitions, then the external tag for the type shall be the same in the two partitions. What it means for a compilation unit to be the same in two different partitions is implementation defined. At a minimum, if the compilation unit is not recompiled between building the two different partitions that include it, the compilation unit is considered the same in the two partitions. @ImplDef{What determines whether a compilation unit is the same in two different partitions.} @begin{Reason} These requirements are important because external tags are used for input/output of class-wide types. These requirements ensure that what is written by one program can be read back by some other program so long as they share the same declaration for the type (and everything it depends on). The user may specify the external tag if (s)he wishes its value to be stable even across changes to the compilation unit in which the type is declared (or changes in some unit on which it depends). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We use a String rather than a @Chg{Version=[2], New=[Stream_Element_Array],Old=[Storage_Array]} to represent an external tag for portability. @end{Reason} @begin{Ramification} Note that the characters of an external tag need not all be graphic characters. In other words, the external tag can be a sequence of arbitrary 8-bit bytes. @end{Ramification} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0113-1]} @ChgAdded{Version=[3],Text=[If a user-specified external tag S'External_Tag is the same as T'External_Tag for some other tagged type declared by a different declaration in the partition, the partition may be rejected.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is, in general, a post-compilation check. This permission is intended for implementations that do link-time construction of the external tag lookup table; implementations that dynamically construct the table will likely prefer to raise Program_Error upon elaboration of the problem construct. We don't want this check to require any implementation complexity, as it will be very rare that there would be a problem.]} @end{Ramification} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00270-01]} The following language-defined attributes are specifiable, at least for some of the kinds of entities to which they apply: Address, @Chg{Version=[2],New=[],Old=[Size, Component_Size, ]}Alignment, @Chg{Version=[2],New=[Bit_Order, Component_Size, ],Old=[]} External_Tag, @Chg{Version=[2],New=[Input, Machine_Radix, Output, Read, Size, ],Old=[]} Small, @Chg{Version=[2],New=[],Old=[Bit_Order, ]} Storage_Pool, Storage_Size, @Chg{Version=[2],New=[Stream_Size, and ],Old=[]} Write@Chg{Version=[2],New=[],Old=[, Output, Read, Input, and Machine_Radix]}. It follows from the general rules in @RefSecNum{Operational and Representation Aspects} that if one writes @lquotes@;@key[for] X'Size @key[use] Y;@rquotes@; then the X'Size @nt{attribute_reference} will return Y (assuming the implementation allows the Size clause). The same is true for all of the specifiable attributes except Storage_Size. @begin{Ramification} An implementation may specify that an implementation-defined attribute is specifiable for certain entities. This follows from the fact that the semantics of implementation-defined attributes is implementation defined. An implementation is not allowed to make a language-defined attribute specifiable if it isn't. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Examples of attribute definition clauses:} @begin{Example} Byte : @key[constant] := 8; Page : @key[constant] := 2**12; @key[type] Medium @key[is] @key[range] 0 .. 65_000; @key[for] Medium'Size @key[use] 2*Byte; @key[for] Medium'Alignment @key[use] 2; Device_Register : Medium; @key[for] Device_Register'Size @key[use] Medium'Size; @key[for] Device_Register'Address @key[use] System.Storage_Elements.To_Address(16#FFFF_0020#); @key[type] Short @key[is] @key[delta] 0.01 @key[range] -100.0 .. 100.0; @key[for] Short'Size @key[use] 15; @key[for] Car_Name'Storage_Size @key[use] --@RI{ specify access type's storage pool size} 2000*((Car'Size/System.Storage_Unit) +1); --@RI{ approximately 2000 cars} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key[function] @Chg{Version=[2],New=[My_Input],Old=[My_Read]}(Stream : @key[@Chg{Version=[2],New=[not null ],Old=[]}access] Ada.Streams.Root_Stream_Type'Class) @key[return] T; @key(for) T'@Chg{Version=[2],New=[Input],Old=[Read]} @key(use) @Chg{Version=[2],New=[My_Input],Old=[My_Read]}; --@RI{ see @RefSecNum{Stream-Oriented Attributes}} @end{Example} @end{Examples} @begin{Notes} @i{Notes on the examples:} In the Size clause for Short, fifteen bits is the minimum necessary, since the type definition requires Short'Small <= 2**(@en@;7). @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The syntax rule for @ntf{length_clause} is replaced with the new syntax rule for @nt{attribute_definition_clause}, and it is modified to allow a @nt{name} (as well as an expression). @end{Extend83} @begin{DiffWord83} The syntax rule for @nt{attribute_definition_clause} now requires that the prefix of the attribute be a @nt{local_name}; in Ada 83 this rule was stated in the text. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} In Ada 83, the relationship between a @Chg{Version=[2],New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]} specifying a certain aspect and an attribute that queried that aspect was unclear. In Ada 95, they are the same, except for certain explicit exceptions. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify for each attribute whether it is an operational or representation attribute.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that External_Tag is never inherited.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-01],ARef=[AI95-00291-01]} @ChgAdded{Version=[2],Text=[Adjusted the Recommended Level of Support for Alignment to eliminate nonsense requirements and to ensure that useful capabilities are required.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-01],ARef=[AI95-00291-01]} @ChgAdded{Version=[2],Text=[Adjusted the Recommended Level of Support for Size to eliminate nonsense requirements and to ensure that useful capabilities are required. Also eliminated any dependence on whether an aspect was specified (a confirming representation item should not affect the semantics).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[Added the definition of machine scalar.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00247-01]} @ChgAdded{Version=[2],Text=[Removed the requirement that specified alignments for a composite type cannot override those for their components, because it was never intended to apply to components whose location was specified with a representation item. Moreover, it causes a difference in legality when a confirming alignment is specified for one of the composite types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Removed recommended level of support rules about types with by-reference and aliased parts, because there are now blanket rules covering all recommended level of support rules.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00291-02]} @ChgAdded{Version=[2],Text=[Split the definition of Alignment for subtypes and for objects. This simplified the wording and eliminated confusion about which rules applied to objects, which applied to subtypes, and which applied to both.]} @end{DiffWord95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0095-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} @b<Correction:> An address attribute with a prefix of a generic formal subprogram whose actual parameter has convention Intrinsic now raises Program_Error. Since it is unlikely that such an attribute would have done anything useful (a subprogram with convention Intrinsic is not expected to have a normal subprogram body), it is highly unlikely that any existing programs would notice the difference, and any that do probably are buggy.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-0113-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> User-specified external tags that conflict with other external tags raise Program_Error (or are optionally illegal). This was legal and did not raise an exception in the past, although the effects were not defined. So while a program might depend on such behavior, the results were not portable (even to different versions of the same implementation). Such programs should be rare.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0095-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b[Correction:] An address attribute with a prefix of a subprogram with convention Intrinsic is now illegal. Such attributes are very unlikely to have provided a useful answer (the intended meaning of convention Intrinsic is that there is no actual subprogram body for the operation), so this is highly unlikely to affect any existing programs unless they have a hidden bug.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0191-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Attributes Has_Same_Storage and Overlaps_Storage are new.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Aspect Storage_Size is new; @nt{pragma} Storage_Size is now obsolescent, joining attribute Storage_Size for task types.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Improved the description of erroneous execution for address clauses to make it clear that specifying an address inappropriate for the entity will lead to erroneous execution.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0116-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added @ImplAdviceTitle for the alignment of class-wide types.]} @end{DiffWord2005} @LabeledClause{Enumeration Representation Clauses} @begin{Intro} @redundant[An @nt{enumeration_representation_clause} specifies the internal codes for enumeration literals.] @end{Intro} @begin{Syntax} @Syn{lhs=<enumeration_representation_clause>,rhs=" @key{for} @SynI{first_subtype_}@Syn2{local_name} @key{use} @Syn2{enumeration_aggregate};"} @Syn{lhs=<enumeration_aggregate>,rhs="@Syn2{array_aggregate}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(enumeration_representation_clause expressions)} The @nt<enumeration_aggregate> shall be written as a one-dimensional @nt<array_aggregate>, for which the index subtype is the unconstrained subtype of the enumeration type, and each component expression is expected to be of any integer type. @begin{Ramification} The @lquotes@;full coverage rules@rquotes@; for @nt<aggregate>s applies. An @key{others} is not allowed @em there is no applicable index constraint in this context. @end{Ramification} @end{Resolution} @begin{Legality} The @SynI{first_subtype_}@nt{local_name} of an @nt{enumeration_representation_clause} shall denote an enumeration subtype. @begin{Ramification} As for all type-related representation items, the @nt{local_name} is required to denote a first subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00287-01]} @Chg{Version=[2],New=[Each component of the @nt{array_aggregate} shall be given by an @nt{expression} rather than a <>. ],Old=[]}The @Chg{Version=[2],New=[@nt{expression}s],Old=[expressions]} given in the @nt{array_aggregate} shall be static, and shall specify distinct integer codes for each value of the enumeration type; the associated integer codes shall satisfy the predefined ordering relation of the type. @begin{Reason} Each value of the enumeration type has to be given an internal code, even if the first subtype of the enumeration type is constrained to only a subrange (this is only possible if the enumeration type is a derived type). This @lquotes@;full coverage@rquotes@; requirement is important because one may refer to Enum'Base'First and Enum'Base'Last, which need to have defined representations. @end{Reason} @end{Legality} @begin{StaticSem} @Chg{Version=[3],New=[@PDefn2{Term=[representation aspect], Sec=(coding)}], Old=[@PDefn2{Term=[aspect of representation], Sec=(coding)} @Defn2{Term=[coding], Sec=(aspect of representation)}]} An @nt{enumeration_representation_clause} specifies the @i{coding} aspect of representation. @Defn{internal code} The coding consists of the @i{internal code} for each enumeration literal, that is, the integral value used internally to represent each literal.@Chg{Version=[3],New=[@AspectDefn{Coding}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Coding], Text=[@ChgAdded{Version=[3],Text=[Internal representation of enumeration literals. Specified by an @nt{enumeration_representation_clause}, not by an @nt{aspect_specification}.]}]} @end{StaticSem} @begin{ImplReq} For nonboolean enumeration types, if the coding is not specified for the type, then for each value of the type, the internal code shall be equal to its position number. @begin{Reason} This default representation is already used by all known Ada compilers for nonboolean enumeration types. Therefore, we make it a requirement so users can depend on it, rather than feeling obliged to supply for every enumeration type an enumeration representation clause that is equivalent to this default rule. @end{Reason} @begin{Discussion} For boolean types, it is relatively common to use all ones for True, and all zeros for False, since some hardware supports that directly. Of course, for a one-bit Boolean object (like in a packed array), False is presumably zero and True is presumably one (choosing the reverse would be extremely unfriendly!). @end{Discussion} @end{ImplReq} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(@nt{enumeration_representation_clause})} The recommended level of support for @nt{enumeration_representation_clause}s is: @begin{Itemize} An implementation should support at least the internal codes in the range System.Min_Int..System.Max_Int. An implementation need not support @nt{enumeration_@!representation_@!clause}s for boolean types. @begin{Ramification} The implementation may support numbers outside the above range, such as numbers greater than System.Max_Int. See AI83-00564. @end{Ramification} @begin{Reason} The benefits of specifying the internal coding of a boolean type do not outweigh the implementation costs. Consider, for example, the implementation of the logical operators on a packed array of booleans with strange internal codes. It's implementable, but not worth it. @end{Reason} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for @nt{enumeration_representation_clause}s should be followed.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Unchecked_Conversion may be used to query the internal codes used for an enumeration type. The attributes of the type, such as Succ, Pred, and Pos, are unaffected by the @Chg{New=[@nt{enumeration_representation_clause}],Old=[@nt{representation_clause}]}. For example, Pos always returns the position number, @i{not} the internal integer code that might have been specified in @Chg{New=[an @nt{enumeration_representation_clause}], Old=[a @nt{representation_clause}]}@Chg<Version=[3],New=[],Old=[}]>. @begin{Discussion} @Leading@;Suppose the enumeration type in question is derived: @begin{Example} @key[type] T1 @key[is] (Red, Green, Blue); @key[subtype] S1 @key[is] T1 @key[range] Red .. Green; @key[type] S2 @key[is] @key[new] S1; @key[for] S2 @key[use] (Red => 10, Green => 20, Blue => 30); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Leading@;The @Chg{New=[@nt{enumeration_representation_clause}],Old=[@nt{representation_clause}]} has to specify values for all enumerals, even ones that are not in S2 (such as Blue). The Base attribute can be used to get at these values. For example: @begin{Example} @key[for] I @key[in] S2'Base @key[loop] ... --@RI{ When I equals Blue, the internal code is 30.} @key[end] @key[loop]; @end{Example} We considered allowing or requiring @lquotes@;@key[for] S2'Base @key[use] ...@rquotes@; in cases like this, but it didn't seem worth the trouble. @end{Discussion} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of an enumeration representation clause:} @begin{Example} @key[type] Mix_Code @key[is] (ADD, SUB, MUL, LDA, STA, STZ); @key[for] Mix_Code @key[use] (ADD => 1, SUB => 2, MUL => 3, LDA => 8, STA => 24, STZ =>33); @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} As in other similar contexts, Ada 95 allows expressions of any integer type, not just expressions of type @i{universal_integer}, for the component expressions in the @nt<enumeration_aggregate>. The preference rules for the predefined operators of @i{root_integer} eliminate any ambiguity. For portability, we now require that the default coding for an enumeration type be the @lquotes@;obvious@rquotes@; coding using position numbers. This is satisfied by all known implementations. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Updated to reflect that we no longer have something called @ntf{representation_clause}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00287-01]} @ChgAdded{Version=[2],Text=[Added wording to prevent the use of <> in a @nt{enumeration_representation_clause}. (<> is newly added to @nt{array_aggregate}s.)]} @end{DiffWord95} @LabeledClause{Record Layout} @begin{Intro} @Chg{Version=[3],New=[@AspectDefn{Layout} @PDefn2{Term=[representation aspect], Sec=(layout)} @PDefn2{Term=[representation aspect], Sec=(record layout)} @AspectDefn{Record layout} @PDefn2{Term=[representation aspect], Sec=(storage place)} @Defn2{Term=[storage place], Sec=(representation aspect)} @Defn2{Term=[storage place], Sec=(of a component)}], Old=[@PDefn2{Term=[aspect of representation], Sec=(layout)} @Defn2{Term=[layout], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(record layout)} @Defn2{Term=[record layout], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(storage place)} @Defn2{Term=[storage place], Sec=(of a component)}]} The @i{(record) layout} aspect of representation consists of the @i{storage places} for some or all components, that is, storage place attributes of the components. The layout can be specified with a @nt{record_@!representation_@!clause}. @end{Intro} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Record Representation Clauses} @begin{Intro} @redundant[A @nt{record_representation_clause} specifies the storage representation of records and record extensions, that is, the order, position, and size of components (including discriminants, if any). @IndexSee{Term=[bit field],See=(record_representation_clause)}] @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} It should be feasible for an implementation to use negative offsets in the representation of composite types. However, no implementation should be forced to support negative offsets. Therefore@Chg{Version=[2],New=[, in the interest of uniformity],Old=[]}, negative offsets should be disallowed in @nt{record_representation_clause}s. @end{MetaRules} @begin{Syntax} @Syn{lhs=<record_representation_clause>,rhs=" @key{for} @SynI{first_subtype_}@Syn2{local_name} @key{use} @key{record} [@Syn2{mod_clause}] {@Syn2{component_clause}} @key{end} @key{record};"} @Syn{lhs=<component_clause>,rhs=" @SynI{component_}@Syn2{local_name} @key{at} @Syn2{position} @key{range} @Syn2{first_bit} .. @Syn2{last_bit};"} @Syn{lhs=<position>,rhs="@SynI{static_}@Syn2{expression}"} @Syn{lhs=<first_bit>,rhs="@SynI{static_}@Syn2{simple_expression}"} @Syn{lhs=<last_bit>,rhs="@SynI{static_}@Syn2{simple_expression}"} @begin{Reason} @nt{First_bit} and @nt{last_bit} need to be @nt{simple_expression} instead of @nt{expression} for the same reason as in @nt{range} (see @RefSec{Scalar Types}). @end{Reason} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(component_clause expressions)} @PDefn2{Term=[expected type], Sec=(position)} @PDefn2{Term=[expected type], Sec=(first_bit)} @PDefn2{Term=[expected type], Sec=(last_bit)} Each @nt{position}, @nt{first_bit}, and @nt{last_bit} is expected to be of any integer type. @begin{Ramification} These need not have the same integer type. @end{Ramification} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00436-01]} The @SynI{first_subtype_}@nt{local_name} of a @nt{record_representation_clause} shall denote a specific @Chg{Version=[2],New=[],Old=[nonlimited ]}record or record extension subtype. @begin{Ramification} As for all type-related representation items, the @nt{local_name} is required to denote a first subtype. @end{Ramification} If the @i{component_}@nt<local_name> is a @nt<direct_name>, the @nt{local_name} shall denote a component of the type. For a record extension, the component shall not be inherited, and shall not be a discriminant that corresponds to a discriminant of the parent type. If the @i{component_}@!@nt<local_@!name> has an @nt{attribute_@!designator}, the @nt{direct_@!name} of the @nt<local_@!name> shall denote either the declaration of the type or a component of the type, and the @nt{attribute_@!designator} shall denote an implementation-defined implicit component of the type. The @nt{position}, @nt{first_bit}, and @nt{last_bit} shall be static expressions. The value of @nt{position} and @nt{first_bit} shall be nonnegative. The value of @nt{last_bit} shall be no less than @nt{first_bit} @en 1. @begin{Ramification} A @nt{component_clause} such as @lquotes@;X @key{at} 4 @key{range} 0..@en@;1;@rquotes@; is allowed if X can fit in zero bits. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[If the nondefault bit ordering applies to the type, then either:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the value of @nt{last_bit} shall be less than the size of the largest machine scalar; or]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the value of @nt{first_bit} shall be zero and the value of @nt{last_bit} + 1 shall be a multiple of System.Storage_Unit.]} @end{Itemize} At most one @nt{component_clause} is allowed for each component of the type, including for each discriminant (@nt{component_clause}s may be given for some, all, or none of the components). Storage places within a @nt{component_list} shall not overlap, unless they are for components in distinct @nt{variant}s of the same @nt{variant_part}. A name that denotes a component of a type is not allowed within a @nt{record_representation_clause} for the type, except as the @SynI{component_}@nt<local_name> of a @nt{component_clause}. @begin{Reason} @Leading@;It might seem strange to make the @nt{record_representation_clause} part of the declarative region, and then disallow mentions of the components within almost all of the @nt{record_representation_clause}. The alternative would be to treat the @SynI{component_}@nt<local_name> like a formal parameter name in a subprogram call (in terms of visibility). However, this rule would imply slightly different semantics, because (given the actual rule) the components can hide other declarations. This was the rule in Ada 83, and we see no reason to change it. The following, for example, was and is illegal: @begin{Example} @key[type] T @key[is] @key[record] X : Integer; @key[end] @key[record]; X : @key[constant] := 31; --@RI{ Same defining name as the component.} @key[for] T @key[use] @key[record] X @key[at] 0 @key[range] 0..X; --@RI{ Illegal!} @key[end] @key[record]; @end{Example} The component X hides the named number X throughout the @nt{record_representation_clause}. @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} A @nt{record_representation_clause} (without the @nt{mod_clause}) specifies the layout.@Chg{Version=[2],New=[],Old=[ The storage place attributes (see @RefSecNum{Storage Place Attributes}) are taken from the values of the @nt{position}, @nt{first_bit}, and @nt{last_bit} expressions after normalizing those values so that @nt{first_bit} is less than Storage_Unit.@Chg{Version=[3],New=[@AspectDefn{Layout (record)}],Old=[]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Layout (record)], Text=[@ChgAdded{Version=[3],Text=[Layout of record components. Specified by a @nt{record_representation_clause}, not by an @nt{aspect_specification}.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Record layout], Text=[@ChgAdded{Version=[3],Text=[See Layout.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[If the default bit ordering applies to the type, the @nt{position}, @nt{first_bit}, and @nt{last_bit} of each @nt{component_clause} directly specify the position and size of the corresponding component.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the nondefault bit ordering applies to the type@Chg{Version=[3],New=[,],Old=[]} then the layout is determined as follows:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the @nt{component_clause}s for which the value of @nt{last_bit} is greater than or equal to the size of the largest machine scalar directly specify the position and size of the corresponding component;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[for other @nt{component_clause}s, all of the components having the same value of @nt{position} are considered to be part of a single machine scalar, located at that @nt{position}; this machine scalar has a size which is the smallest machine scalar size larger than the largest @nt{last_bit} for all @nt{component_clause}s at that @nt{position}; the @nt{first_bit} and @nt{last_bit} of each @nt{component_clause} are then interpreted as bit offsets in this machine scalar.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00133-01]} @ChgNote{We want the header title to remain, so we use @Chg instead if @ChgDeleted.} @Chg{Version=[2],New=[],Old=[For example, if Storage_Unit is 8, then @lquotes@;C @key[at] 0 @key[range] 24..31;@rquotes@; defines C'Position = 3, C'First_Bit = 0, and C'Last_Bit = 7. This is true of machines with either bit ordering.]} A @nt{component_clause} also determines the value of the Size attribute of the component, since this attribute is related to First_Bit and Last_Bit. @end{Ramification} @Redundant[A @nt{record_representation_clause} for a record extension does not override the layout of the parent part;] if the layout was specified for the parent type, it is inherited by the record extension. @end{StaticSem} @begin{ImplPerm} An implementation may generate implementation-defined components (for example, one containing the offset of another component). An implementation may generate names that denote such implementation-defined components; such names shall be implementation-defined @nt{attribute_reference}s. An implemen@!tation may allow such implementation-defined names to be used in @nt{record_@!representation_@!clause}s. An implementation can restrict such @nt{component_@!clause}s in any manner it sees fit. @ImplDef{Implementation-defined components.} @begin{Ramification} Of course, since the semantics of implementation-defined attributes is implementation defined, the implementation need not support these names in all situations. They might be purely for the purpose of @nt{component_clause}s, for example. The visibility rules for such names are up to the implementation. We do not allow such component names to be normal identifiers @em that would constitute blanket permission to do all kinds of evil things. @end{Ramification} @begin{Discussion} @Defn{dope} Such implementation-defined components are known in the vernacular as @lquotes@;dope.@rquotes@; Their main purpose is for storing offsets of components that depend on discriminants. @end{Discussion} If a @nt<record_representation_clause> is given for an untagged derived type, the storage place attributes for all of the components of the derived type may differ from those of the corresponding components of the parent type, even for components whose storage place is not specified explicitly in the @nt<record_@!representation_@!clause>. @begin{Reason} This is clearly necessary, since the whole record may need to be laid out differently. @end{Reason} @end{ImplPerm} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(@nt{record_representation_clause})} The recommended level of support for @nt{record_representation_clause}s is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[An implementation should support machine scalars that correspond to all of the integer, floating point, and address formats supported by the machine.]} An implementation should support storage places that can be extracted with a load, mask, shift sequence of machine code, and set with a load, shift, mask, store sequence, given the available machine instructions and run-time model. A storage place should be supported if its size is equal to the Size of the component subtype, and it starts and ends on a boundary that obeys the Alignment of the component subtype. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[For],Old=[If the default bit ordering applies to the declaration of a given type, then for]} a component @Chg{Version=[2],New=[with a subtype ],Old=[]}whose @Chg{Version=[2],New=[],Old=[subtype's ]}Size is less than the word size, any storage place that does not cross an aligned word boundary should be supported. @begin{Reason} The above recommendations are sufficient to define interfaces to most interesting hardware. This causes less implementation burden than the definition in ACID, which requires arbitrary bit alignments of arbitrarily large components. Since the ACID definition is neither enforced by the ACVC, nor supported by all implementations, it seems OK for us to weaken it. @end{Reason} An implementation may reserve a storage place for the tag field of a tagged type, and disallow other components from overlapping that place. @begin{Ramification} Similar permission for other dope is not granted. @end{Ramification} An implementation need not support a @nt{component_clause} for a component of an extension part if the storage place is not after the storage places of all components of the parent type, whether or not those storage places had been specified. @begin{Reason} These restrictions are probably necessary if block equality operations are to be feasible for class-wide types. For block comparison to work, the implementation typically has to fill in any gaps with zero (or one) bits. If a @lquotes@;gap@rquotes@; in the parent type is filled in with a component in a type extension, then this won't work when a class-wide object is passed by reference, as is required. @end{Reason} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for @nt{record_representation_clause}s should be followed.]}]} @end{ImplAdvice} @begin{Notes} If no @nt{component_clause} is given for a component, then the choice of the storage place for the component is left to the implementation. If @nt{component_clause}s are given for all components, the @nt{record_representation_clause} completely specifies the representation of the type and will be obeyed exactly by the implementation. @begin{Ramification} The visibility rules prevent the name of a component of the type from appearing in a @nt{record_representation_clause} at any place @i{except} for the @SynI{component_}@nt<local_name> of a @nt{component_clause}. However, since the @nt{record_representation_clause} is part of the declarative region of the type declaration, the component names hide outer homographs throughout. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} A @nt{record_representation_clause} cannot be given for a protected type, even though protected types, like record types, have components. The primary reason for this rule is that there is likely to be too much dope in a protected type @em entry queues, bit maps for barrier values, etc. In order to control the representation of the user-defined components, simply declare a record type, give it a @Chg{New=[@nt{record_@!representation_@!clause}],Old=[@nt{representation_clause}]}, and give the protected type one component whose type is the record type. Alternatively, if the protected object is protecting something like a device register, it makes more sense to keep the thing being protected outside the protected object (possibly with a pointer to it in the protected object), in order to keep implementation-defined components out of the way. @end{Ramification} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of specifying the layout of a record type:} @begin{Example} Word : @key[constant] := 4; --@RI{ storage element is byte, 4 bytes per word} @key[type] State @key[is] (A,M,W,P); @key[type] Mode @key[is] (Fix, Dec, Exp, Signif); @key[type] Byte_Mask @key[is] @key[array] (0..7) @key[of] Boolean; @key[type] State_Mask @key[is] @key[array] (State) @key[of] Boolean; @key[type] Mode_Mask @key[is] @key[array] (Mode) @key[of] Boolean; @key[type] Program_Status_Word @key[is] @key[record] System_Mask : Byte_Mask; Protection_Key : Integer @key[range] 0 .. 3; Machine_State : State_Mask; Interrupt_Cause : Interruption_Code; Ilc : Integer @key[range] 0 .. 3; Cc : Integer @key[range] 0 .. 3; Program_Mask : Mode_Mask; Inst_Address : Address; @key[end] @key[record]; @key[for] Program_Status_Word @key[use] @key[record] System_Mask @key[at] 0*Word @key[range] 0 .. 7; Protection_Key @key[at] 0*Word @key[range] 10 .. 11; --@RI{ bits 8,9 unused} Machine_State @key[at] 0*Word @key[range] 12 .. 15; Interrupt_Cause @key[at] 0*Word @key[range] 16 .. 31; Ilc @key[at] 1*Word @key[range] 0 .. 1; --@RI{ second word} Cc @key[at] 1*Word @key[range] 2 .. 3; Program_Mask @key[at] 1*Word @key[range] 4 .. 7; Inst_Address @key[at] 1*Word @key[range] 8 .. 31; @key[end] @key[record]; @key[for] Program_Status_Word'Size @key[use] 8*System.Storage_Unit; @key[for] Program_Status_Word'Alignment @key[use] 8; @end{Example} @end{Examples} @begin{Notes} @i{Note on the example:} The @nt{record_representation_clause} defines the record layout. The Size clause guarantees that (at least) eight storage elements are used for objects of the type. The Alignment clause guarantees that aliased, imported, or exported objects of the type will have addresses divisible by eight. @end{Notes} @begin{DiffWord83} The @ntf{alignment_clause} has been renamed to @nt{mod_clause} and moved to @RefSec{Obsolescent Features}. We have clarified that implementation-defined component names have to be in the form of an @nt{attribute_reference} of a component or of the first subtype itself; surely Ada 83 did not intend to allow arbitrary identifiers. The RM83-13.4(7) wording incorrectly allows components in nonvariant records to overlap. We have corrected that oversight. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The meaning of a @nt{record_representation_clause} for the nondefault bit order is now clearly defined. Thus, such clauses can be portably written. In order to do that though, the equivalence of bit 1 in word 1 to bit 9 in word 0 (for a machine with Storage_Unit = 8) had to be dropped for the nondefault bit order. Any @nt{record_representation_clause}s which depends on that equivalence will break (although such code would imply a noncontiguous representation for a component, and it seems unlikely that compilers were supporting that anyway).]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00436-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] The undocumented (and likely unintentional) incompatibility with Ada 83 caused by not allowing @nt{record_representation_clause}s on limited record types is removed.]} @end{Extend95} @LabeledSubClause{Storage Place Attributes} @begin{StaticSem} @Leading@Defn2{Term=[storage place attributes], Sec=(of a component)} For @PrefixType{a component C of a composite, non-array object R}, the @i{storage place attributes} are defined: @begin{Ramification} The storage place attributes are not (individually) specifiable, but the user may control their values by giving a @nt{record_representation_clause}. @end{Ramification} @begin{Description} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<Position>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{position} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the same value as R.C'Address @en@; R'Address. The value of this attribute is of the type @i{universal_integer}.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} Thus, @Chg{Version=[2],New=[for the default bit order, ],Old=[]}R.C'Position is the offset of C in storage elements from the beginning of the object, where the first storage element of an object is numbered zero. R'Address + R.C'Position = R.C'Address. For record extensions, the offset is not measured from the beginning of the extension part, but from the beginning of the whole object, as usual. In @lquotes@;R.C'Address @en@; R'Address@rquotes@;, the "@en@;" operator is the one in System.Storage_Elements that takes two Addresses and returns a Storage_Offset. @end{Ramification} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<First_Bit>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{first_bit} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the offset, from the start of the first of the storage elements occupied by C, of the first bit occupied by C. This offset is measured in bits. The first bit of a storage element is numbered zero. The value of this attribute is of the type @i{universal_integer}.>} @ChgAttribute{Version=[2],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<R.C>, AttrName=<Last_Bit>, ARef=[AI95-00133-01], Text=<@Chg{Version=[2],New=[If the nondefault bit ordering applies to the composite type, and if a @nt{component_clause} specifies the placement of C, denotes the value given for the @nt{last_bit} of the @nt{component_clause}; otherwise, denotes],Old=[Denotes]} the offset, from the start of the first of the storage elements occupied by C, of the last bit occupied by C. This offset is measured in bits. The value of this attribute is of the type @i{universal_integer}.>} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The ordering of bits in a storage element is @Chg{Version=[2],New=[],Old=[is ]}defined in @RefSec{Bit Ordering}. R.C'Size = R.C'Last_Bit @en@; R.C'First_Bit + 1. (Unless the implementation chooses an indirection representation.) If a @nt{component_clause} applies to a component, then that component will be at the same relative storage place in all objects of the type. Otherwise, there is no such requirement. @end{Ramification} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} @PDefn{contiguous representation} @PDefn{discontiguous representation} If a component is represented using some form of pointer (such as an offset) to the actual data of the component, and this data is contiguous with the rest of the object, then the storage place attributes should reflect the place of the actual data, not the pointer. If a component is allocated discontiguously from the rest of the object, then a warning should be generated upon reference to one of its storage place attributes. @begin{Reason} For discontiguous components, these attributes make no sense. For example, an implementation might allocate dynamic-sized components on the heap. For another example, an implementation might allocate the discriminants separately from the other components, so that multiple objects of the same subtype can share discriminants. Such representations cannot happen if there is a @nt{component_clause} for that component. @end{Reason} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If a component is represented using a pointer to the actual data of the component which is contiguous with the rest of the object, then the storage place attributes should reflect the place of the actual data. If a component is allocated discontiguously from the rest of the object, then a warning should be generated upon reference to one of its storage place attributes.]}]} @end{ImplAdvice} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The meaning of the storage place attributes for the nondefault bit order is now clearly defined, and can be different than that given by strictly following the Ada 95 wording. Any code which depends on the original Ada 95 values for a type using the nondefault bit order where they are different will break.]} @end{Incompatible95} @LabeledSubClause{Bit Ordering} @begin{Intro} @redundant[The Bit_Order attribute specifies the interpretation of the storage place attributes.] @begin{Reason} The intention is to provide uniformity in the interpretation of storage places across implementations on a particular machine by allowing the user to specify the Bit_Order. It is not intended to fully support data interoperability across different machines, although it can be used for that purpose in some situations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} We can't require all implementations on a given machine to use the same bit ordering by default; if the user cares, a @Chg{Version=[2],New=[],Old=[@nt{pragma} ]}Bit_Order @Chg{Version=[2],New=[@nt{attribute_definition_clause} ],Old=[]}can be used to force all implementations to use the same bit ordering. @end{Reason} @end{Intro} @begin{StaticSem} @Defn{bit ordering} A bit ordering is a method of interpreting the meaning of the storage place attributes. @Defn{High_Order_First} @Defn{big endian} @Defn2{Term=[endian], Sec=(big)} High_Order_First @Redundant[(known in the vernacular as @lquotes@;big endian@rquotes@;)] means that the first bit of a storage element (bit 0) is the most significant bit (interpreting the sequence of bits that represent a component as an unsigned integer value). @Defn{Low_Order_First} @Defn{little endian} @Defn2{Term=[endian], Sec=(little)} Low_Order_First @Redundant[(known in the vernacular as @lquotes@;little endian@rquotes@;)] means the opposite: the first bit is the least significant. @Leading@;For @PrefixType{every specific record subtype S}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<S>, AttrName=<Bit_Order>, Text=<Denotes the bit ordering for the type of S. The value of this attribute is of type System.Bit_Order.>} @EndPrefixType{} @PDefn2{Term=[specifiable], Sec=(of Bit_Order for record types and record extensions)} @Defn{Bit_Order clause} Bit_Order may be specified for specific record types via an @nt{attribute_definition_clause}; the expression of such a clause shall be static.@Chg{Version=[3],New=[@AspectDefn{Bit_Order}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Bit_Order], Text=[@ChgAdded{Version=[3],Text=[Order of bit numbering in a @nt{record_representation_clause}.]}]} @end{Description} If Word_Size = Storage_Unit, the default bit ordering is implementation defined. If Word_Size > Storage_Unit, the default bit ordering is the same as the ordering of storage elements in a word, when interpreted as an integer. @IndexSee{Term=[byte sex],See=(ordering of storage elements in a word)} @ImplDef{If Word_Size = Storage_Unit, the default bit ordering.} @begin{Ramification} Consider machines whose Word_Size = 32, and whose Storage_Unit = 8. Assume the default bit ordering applies. On a machine with big-endian addresses, the most significant storage element of an integer is at the address of the integer. Therefore, bit zero of a storage element is the most significant bit. On a machine with little-endian addresses, the least significant storage element of an integer is at the address of the integer. Therefore, bit zero of a storage element is the least significant bit. @end{Ramification} The storage place attributes of a component of a type are interpreted according to the bit ordering of the type. @begin{Ramification} This implies that the interpretation of the @nt{position}, @nt{first_bit}, and @nt{last_bit} of a @nt{component_clause} of a @nt{record_representation_clause} obey the bit ordering given in a representation item. @end{Ramification} @end{StaticSem} @begin{ImplAdvice} @Leading@PDefn2{Term=[recommended level of support], Sec=(bit ordering)} The recommended level of support for the nondefault bit ordering is: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[The],Old=[If Word_Size = Storage_Unit, then the]} implementation should support the nondefault bit ordering in addition to the default bit ordering. @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00133-01]} @Chg{Version=[2],New=[The],Old=[If Word_Size = Storage_Unit, the]} implementation should support both bit orderings. @Chg{Version=[2],New=[Implementations],Old=[We don't push for support of the nondefault bit ordering when Word_Size > Storage_Unit (except of course for upward compatibility with a preexisting implementation whose Ada 83 bit order did not correspond to the required Ada 95 default bit order), because implementations]} are required to support storage positions that cross storage element boundaries when Word_Size > Storage_Unit@Chg{Version=[2], New=[ but the definition of the storage place attributes for the nondefault bit order ensures that such],Old=[. Such]} storage positions will @Chg{Version=[2], New=[not ],Old=[]}be split into two or three pieces@Chg{Version=[2],New=[. Thus, there is no significant implementation burden to supporting the nondefault bit order, given that the set of machine scalars is implementation-defined], Old=[ if the nondefault bit ordering is used, which could be onerous to support. However, if Word_Size = Storage_Unit, there might not be a natural bit ordering, but the splitting problem need not occur]}. @end{Ramification} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the nondefault bit ordering should be followed.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[Bit_Order clauses make it possible to write @nt{record_representation_clause}s that can be ported between machines having different bit ordering. They do not guarantee transparent exchange of data between such machines.]} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The Bit_Order attribute is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00133-01]} @ChgAdded{Version=[2],Text=[We now suggest that all implementations support the nondefault bit order.]} @end{Diffword95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Change of Representation} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @redundant[@Defn{change of representation} @Defn2{Term=[representation], Sec=(change of)} A @nt{type_conversion} (see @RefSecNum{Type Conversions}) can be used to convert between two different representations of the same array or record. To convert an array from one representation to another, two array types need to be declared with matching component subtypes, and convertible index types. If one type has @Chg{Version=[3],New=[Pack],Old=[packing]} specified and the other does not, then explicit conversion can be used to pack or unpack an array. To convert a record from one representation to another, two record types with a common ancestor type need to be declared, with no inherited subprograms. Distinct representations can then be specified for the record types, and explicit conversion between the types can be used to effect a change in representation.] @begin{Ramification} This technique does not work if the first type is an untagged type with user-defined primitive subprograms. It does not work at all for tagged types. @end{Ramification} @end{Intro} @begin{Examples} @leading@keepnext@i{Example of change of representation:} @begin{Example} --@RI{ Packed_Descriptor and Descriptor are two different types} --@RI{ with identical characteristics, apart from their} --@RI{ representation} @key[type] Descriptor @key[is] @key[record] --@RI{ components of a descriptor} @key[end] @key[record]; @key[type] Packed_Descriptor @key[is] @key[new] Descriptor; @key[for] Packed_Descriptor @key[use] @key[record] --@RI{ component clauses for some or for all components} @key[end] @key[record]; @RI{-- Change of representation can now be accomplished by explicit type conversions:} D : Descriptor; P : Packed_Descriptor; P := Packed_Descriptor(D); --@RI{ pack D} D := Descriptor(P); --@RI{ unpack P} @end{Example} @end{Examples} ���������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/13b.mss��������������������������������������������������������������0000755�0001752�0001001�00001117330�12066652506�016544� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(13, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:04 $} @Comment{$Source: e:\\cvsroot/ARM/Source/13b.mss,v $} @Comment{$Revision: 1.100 $} @RMNewPage @LabeledClause{The Package System} @begin{Intro} @redundant[For each implementation there is a library package called System which includes the definitions of certain configuration-dependent characteristics.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The contents of the visible part of package System@Chg{Version=[2],New=[],Old=[and its language-defined children]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @RootLibUnit{System}@key[package] System @key[is] @key{pragma} @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(System); @key[type] @AdaTypeDefn{Name} @key[is] @RI{implementation-defined-enumeration-type}; @AdaObjDefn{System_Name} : @key[constant] Name := @RI{implementation-defined}; --@RI{ System-Dependent Named Numbers:} @AdaObjDefn{Min_Int} : @key[constant] := @RI{root_integer}'First; @AdaObjDefn{Max_Int} : @key[constant] := @RI{root_integer}'Last; @AdaObjDefn{Max_Binary_Modulus} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Nonbinary_Modulus} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Base_Digits} : @key[constant] := @RI{root_real}'Digits; @AdaObjDefn{Max_Digits} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Max_Mantissa} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Fine_Delta} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Tick} : @key[constant] := @RI{implementation-defined}; --@RI{ Storage-related Declarations:} @key[type] @AdaTypeDefn{Address} @key[is] @RI{implementation-defined}; @AdaObjDefn{Null_Address} : @key[constant] Address; @AdaObjDefn{Storage_Unit} : @key[constant] := @RI{implementation-defined}; @AdaObjDefn{Word_Size} : @key[constant] := @RI{implementation-defined} * Storage_Unit; @AdaObjDefn{Memory_Size} : @key[constant] := @RI{implementation-defined}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} --@RI{ @Defn2{Term=[address], Sec=(comparison)}Address Comparison:} @key(function) "<" (Left, Right : Address) @key(return) Boolean@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "<="(Left, Right : Address) @key(return) Boolean@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) ">" (Left, Right : Address) @key(return) Boolean@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) ">="(Left, Right : Address) @key(return) Boolean@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "=" (Left, Right : Address) @key(return) Boolean@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; -- @key(function) "/=" (Left, Right : Address) @key(return) Boolean; --@RI{ "/=" is implicitly defined}@Chg{Version=[3],New=[],Old=[ @key[pragma] Convention(Intrinsic, "<"); ... --@RI{ and so on for all language-defined subprograms in this package}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00221-01]} --@RI{ Other System-Dependent Declarations:} @key[type] @AdaTypeDefn{Bit_Order} @key[is] (@AdaObjDefn{High_Order_First}, @AdaObjDefn{Low_Order_First}); @AdaObjDefn{Default_Bit_Order} : @key[constant] Bit_Order@Chg{Version=[2],New=[ := @RI{implementation-defined}],Old=[]}; --@RI{ Priority-related declarations (see @RefSecNum{Task Priorities}):} @key{subtype} @AdaSubtypeDefn{Name=[Any_Priority],Of=[Integer]} @key{is} Integer @key{range} @RI{implementation-defined}; @key{subtype} @AdaSubtypeDefn{Name=[Priority],Of=[Any_Priority]} @key{is} Any_Priority @key{range} Any_Priority'First .. @RI{implementation-defined}; @key{subtype} @AdaSubtypeDefn{Name=[Interrupt_Priority],Of=[Any_Priority]} @key{is} Any_Priority @key{range} Priority'Last+1 .. Any_Priority'Last; @AdaObjDefn{Default_Priority} : @key{constant} Priority := (Priority'First + Priority'Last)/2; @key[private] ... -- @RI{not specified by the language} @key[end] System; @end{Example} Name is an enumeration subtype. Values of type Name are the names of alternative machine configura@!tions handled by the implementation. System_Name represents the current machine configuration. The named numbers Fine_Delta and Tick are of the type @i{universal_real}; the others are of the type @i{universal_integer}. @Leading@;The meanings of the named numbers are: @begin{Description} @Redundant[ Min_Int @\The smallest (most negative) value allowed for the expressions of a @nt{signed_@!integer_@!type_@!definition}. Max_Int @\The largest (most positive) value allowed for the expressions of a @nt{signed_@!integer_@!type_@!definition}. Max_Binary_Modulus @\A power of two such that it, and all lesser positive powers of two, are allowed as the modulus of a @nt<modular_type_definition>. Max_Nonbinary_Modulus @\A value such that it, and all lesser positive integers, are allowed as the modulus of a @nt<modular_type_definition>. @begin{Ramification} There is no requirement that Max_Nonbinary_Modulus be less than or equal to Max_Binary_Modulus, although that's what makes most sense. On a typical 32-bit machine, for example, Max_Binary_Modulus will be 2**32 and Max_Nonbinary_Modulus will be 2**31, because supporting nonbinary moduli in above 2**31 causes implementation difficulties. @end{Ramification} Max_Base_Digits @\The largest value allowed for the requested decimal precision in a @nt{floating_@!point_@!definition}. Max_Digits @\The largest value allowed for the requested decimal precision in a @nt{floating_@!point_@!definition} that has no @nt{real_@!range_@!specification}. Max_Digits is less than or equal to Max_Base_Digits. Max_Mantissa @\The largest possible number of binary digits in the mantissa of machine numbers of a user-defined ordinary fixed point type. (The mantissa is defined in @RefSecNum{Numerics}.) Fine_Delta @\The smallest delta allowed in an @nt{ordinary_fixed_point_definition} that has the @nt{real_@!range_@!specification} @key{range} @en@;1.0 .. 1.0. ] Tick @\A period in seconds approximating the real time interval during which the value of Calendar.Clock remains constant. @begin{Ramification} There is no required relationship between System.Tick and Duration'Small, other than the one described here. The inaccuracy of the @nt{delay_statement} has no relation to Tick. In particular, it is possible that the clock used for the @nt{delay_statement} is less accurate than Calendar.Clock. We considered making Tick a run-time-determined quantity, to allow for easier configurability. However, this would not be upward compatible, and the desired configurability can be achieved using functionality defined in @RefSec{Real-Time Systems}. @end{Ramification} Storage_Unit @\The number of bits per storage element. Word_Size @\The number of bits per word. Memory_Size @\An implementation-defined value @Redundant[that is intended to reflect the memory size of the configuration in storage elements.] @begin{Discussion} It is unspecified whether this refers to the size of the address space, the amount of physical memory on the machine, or perhaps some other interpretation of @lquotes@;memory size.@rquotes@; In any case, the value has to be given by a static expression, even though the amount of memory on many modern machines is a dynamic quantity in several ways. Thus, Memory_Size is not very useful. @end{Discussion} @end{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} Address is @Chg{Version=[2],New=[],Old=[of ]}a definite, nonlimited type@Chg{Version=[2],New=[ with preelaborable initialization (see @RefSecNum{Elaboration Control})],Old=[]}. Address represents machine addresses capable of addressing individual storage elements. Null_Address is an address that is distinct from the address of any object or program unit. @IndexSee{Term=[pointer],See=(type System.Address)} @begin{Ramification} The implementation has to ensure that there is at least one address that nothing will be allocated to; Null_Address will be one such address. @end{Ramification} @begin{Ramification} Address is the type of the result of the attribute Address. @end{Ramification} @begin{Reason} Address is required to be nonlimited and definite because it is important to be able to assign addresses, and to declare uninitialized address variables. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[If System.Address is defined as a private type (as suggested below), it might be necessary to add a pragma Preelaborable_Initialization to the specification of System in order that Address have preelaborable initialization as required.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00221-01]} @Chg{Version=[2],New=[ Default_Bit_Order shall be a static constant. ],Old=[]}See @RefSecNum{Bit Ordering} for an explanation of Bit_Order and Default_Bit_Order. @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} An implementation may add additional implementation-defined declarations to package System and its children. @Redundant[However, it is usually better for the implementation to provide additional functionality via implementation-defined children of System.]@Chg{Version=[2],New=[],Old=[ Package System may be declared pure.]} @begin{Ramification} The declarations in package System and its children can be implicit. For example, since Address is not limited, the predefined "=" and "/=" operations are probably sufficient. However, the implementation is not @i{required} to use the predefined "=". @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgNote{Version=[1],Kind=[Revised]}@ChgNote{Remove bogus "of"} Address should be @Chg{New=[],Old=[of ]}a private type. @begin{Reason} This promotes uniformity by avoiding having implementation-defined predefined operations for the type. We don't require it, because implementations may want to stick with what they have. @end{Reason} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Type System.Address should be a private type.]}]} @begin{ImplNote} It is not necessary for Address to be able to point at individual bits within a storage element. Nor is it necessary for it to be able to point at machine registers. It is intended as a memory address that matches the hardware's notion of an address. The representation of the @key{null} value of a general access type should be the same as that of Null_Address; instantiations of Unchecked_Conversion should work accordingly. If the implementation supports interfaces to other languages, the representation of the @key{null} value of a general access type should be the same as in those other languages, if appropriate. Note that the children of the Interfaces package will generally provide foreign-language-specific null values where appropriate. See UI-0065 regarding Null_Address. @end{ImplNote} @end{ImplAdvice} @begin{Notes} There are also some language-defined child packages of System defined elsewhere. @end{Notes} @begin{Extend83} @ChgRef{Version=[1],Kind=[Added]}@ChgNote{Presentation AI-00114} @ChgAdded{Version=[1],Text=[@Defn{extensions to Ada 83} The declarations Max_Binary_Modulus, Max_Nonbinary_Modulus, Max_Base_Digits, Null_Address, Word_Size, Bit_Order, Default_Bit_Order, Any_Priority, Interrupt_Priority, and Default_Priority are added to System in Ada 95. The presence of ordering operators for type Address is also guaranteed (the existence of these depends on the definition of Address in an Ada 83 implementation). We do not list these as incompatibilities, as the contents of System can vary between implementations anyway; thus a program that depends on the contents of System (by using @f{@key[use] System;} for example) is already at risk of being incompatible when moved between Ada implementations.]} @end{Extend83} @begin{DiffWord83} Much of the content of System is standardized, to provide more uniformity across implementations. Implementations can still add their own declarations to System, but are encouraged to do so via children of System. Some of the named numbers are defined more explicitly in terms of the standard numeric types. The pragmas System_Name, Storage_Unit, and Memory_Size are no longer defined by the language. However, the corresponding declarations in package System still exist. Existing implementations may continue to support the three pragmas as implementation-defined pragmas, if they so desire. Priority semantics, including subtype Priority, have been moved to the Real Time Annex. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Type Address is defined to have preelaborable initialization, so that it can be used without restriction in preelaborated units. (If Address is defined to be a private type, as suggested by the @ImplAdviceTitle, in Ada 95 it cannot be used in some contexts in a preelaborated units. This is an unnecessary portability issue.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00221-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] Default_Bit_Order is now a static constant.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Package System is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)]} @end{Extend95} @LabeledSubClause{The Package System.Storage_Elements} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[System],Child=[Storage_Elements]}@key[package] System.Storage_Elements @key[is] @key{pragma} @Chg{Version=[2],New=[Pure(],Old=[Preelaborate(System.]}Storage_Elements); @key[type] @AdaTypeDefn{Storage_Offset} @key[is] @key[range] @RI(implementation-defined); @key[subtype] @AdaSubtypeDefn{Name=[Storage_Count],Of=[Storage_Offset]} @key[is] Storage_Offset @key[range] 0..Storage_Offset'Last; @key[type] @AdaTypeDefn{Storage_Element} @key[is] @key[mod] @RI{implementation-defined}; @key[for] Storage_Element'Size @key[use] Storage_Unit; @key[type] @AdaTypeDefn{Storage_Array} @key[is] @key[array] (Storage_Offset @key[range] <>) @key[of] @key[aliased] Storage_Element; @key[for] Storage_Array'Component_Size @key[use] Storage_Unit; --@RI{ @Defn2{Term=[address], Sec=(arithmetic)}Address Arithmetic:} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(function) "+"(Left : Address; Right : Storage_Offset)@Chg{Version=[3],New=[],Old=[ ]} @key(return) Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "+"(Left : Storage_Offset; Right : Address)@Chg{Version=[3],New=[],Old=[ ]} @key(return) Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "-"(Left : Address; Right : Storage_Offset)@Chg{Version=[3],New=[],Old=[ ]} @key(return) Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "-"(Left, Right : Address)@Chg{Version=[3],New=[],Old=[ ]} @key(return) Storage_Offset@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(function) "@key(mod)"(Left : Address; Right : Storage_Offset) @key(return) Storage_Offset@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; --@RI{ Conversion to/from integers:} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[type] @AdaTypeDefn{Integer_Address} @key[is] @RI{implementation-defined}; @key[function] @AdaSubDefn{To_Address}(Value : Integer_Address) @key[return] Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key[function] @AdaSubDefn{To_Integer}(Value : Address) @key[return] Integer_Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[],Old=[ @key[pragma] Convention(Intrinsic, "+"); @RI(-- ...and so on for all language-defined subprograms declared in this package.) ]}@key[end] System.Storage_Elements; @end{Example} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The Convention @Chg{Version=[3],New=[aspects],Old=[@nt{pragma}s]} imply that the attribute Access is not allowed for those operations. The @key(mod) function is needed so that the definition of Alignment makes sense. @end{Reason} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The range of Storage_Elements.Storage_Offset, the modulus of Storage_Elements.Storage_Element, and the declaration of Storage_Elements.Integer_Address.]}.]} Storage_Element represents a storage element. Storage_Offset represents an offset in storage elements. Storage_Count represents a number of storage elements. @PDefn{contiguous representation} @PDefn{discontiguous representation} Storage_Array represents a contiguous sequence of storage elements. @begin{Reason} The index subtype of Storage_Array is Storage_Offset because we wish to allow maximum flexibility. Most Storage_Arrays will probably have a lower bound of 0 or 1, but other lower bounds, including negative ones, make sense in some situations. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[Note that there are some language-defined subprograms that fill part of a Storage_Array, and return the index of the last element filled as a Storage_Offset. The Read procedures in Streams (see @RefSecNum{The Package Streams}), Streams.Stream_IO (see @RefSecNum{The Package Streams.Stream_IO}), and System.RPC (see @RefSecNum{Partition Communication Subsystem}) behave in this manner. These will raise Constraint_Error if the resulting Last value is not in Storage_Offset. This implies that the Storage_Array passed to these subprograms should not have a lower bound of Storage_Offset'First, because then a read of 0 elements would always raise Constraint_Error. A better choice of lower bound is 1.]} @end{Reason} Integer_Address is a @Redundant[(signed or modular)] integer subtype. To_Address and To_Integer convert back and forth between this type and Address. @end{StaticSem} @begin{ImplReq} Storage_Offset'Last shall be greater than or equal to Integer'Last or the largest possible storage offset, whichever is smaller. Storage_Offset'First shall be <= (@en@;Storage_Offset'Last). @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00362-01]} @ChgDeleted{Version=[2],Text=[Package System.Storage_Elements may be declared pure.]} @end{ImplPerm} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraph 15 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{ImplAdvice} Operations in System and its children should reflect the target environment semantics as closely as is reasonable. For example, on most machines, it makes sense for address arithmetic to @lquotes@;wrap around.@rquotes@; @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Operations that do not make sense should raise Program_Error. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Operations in System and its children should reflect the target environment; operations that do not make sense should raise Program_Error.]}]} @begin{Discussion} For example, on a segmented architecture, X < Y might raise Program_Error if X and Y do not point at the same segment (assuming segments are unordered). Similarly, on a segmented architecture, the conversions between Integer_Address and Address might not make sense for some values, and so might raise Program_Error. @end{Discussion} @begin{Reason} We considered making Storage_Element a private type. However, it is better to declare it as a modular type in the visible part, since code that uses it is already low level, and might as well have access to the underlying representation. We also considered allowing Storage_Element to be any integer type, signed integer or modular, but it is better to have uniformity across implementations in this regard, and viewing storage elements as unsigned seemed to make the most sense. @end{Reason} @begin{ImplNote} To_Address is intended for use in Address clauses. Implementations should overload To_Address if appropriate. For example, on a segmented architecture, it might make sense to have a record type representing a segment/offset pair, and have a To_Address conversion that converts from that record type to type Address. @end{ImplNote} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package System.Storage_Elements is now Pure, so it can be portably used in more places. (Ada 95 allowed it to be Pure, but did not require that.)]} @end{Extend95} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledSubClause{The Package System.Address_To_Access_Conversions} @begin{StaticSem} @Leading@;The following language-defined generic library package exists: @begin{Example} @ChildUnit{Parent=[System],Child=[Address_@!To_@!Access_@!Conversions]}@key[generic] @key[type] Object(<>) @key[is] @key[limited] @key[private]; @key[package] System.Address_To_Access_Conversions @key[is] @key[pragma] Preelaborate(Address_To_Access_Conversions); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[type] Object_Pointer @key[is] @key[access] @key[all] Object; @key[function] @AdaSubDefn{To_Pointer}(Value : Address) @key[return] Object_Pointer@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key[function] @AdaSubDefn{To_Address}(Value : Object_Pointer) @key[return] Address@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[],Old=[ @key[pragma] Convention(Intrinsic, To_Pointer); @key[pragma] Convention(Intrinsic, To_Address); ]}@key[end] System.Address_To_Access_Conversions; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} The To_Pointer and To_Address subprograms convert back and forth between values of types Object_Pointer and Address. To_Pointer(X'Address) is equal to X'Unchecked_Access for any X that allows Unchecked_Access. To_Pointer(Null_Address) returns @key[null]. @PDefn{unspecified} For other addresses, the behavior is unspecified. To_Address(@key[null]) returns Null_Address@Chg{Version=[2],New=[],Old=[ (for @key[null] of the appropriate type)]}. To_Address(Y), where Y /= @key[null], returns Y.@key[all]'Address. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} The programmer should ensure that the address passed to To_Pointer is either Null_Address, or the address of an object of type Object. @Chg{Version=[2],New=[(If Object is not a @Chg{Version=[3],New=[],Old=[not ]}by-reference type, the object ought to be aliased; recall that the Address attribute is not required to provide a useful result @Chg{Version=[3],New=[for ],Old=[]}other objects.)],Old=[]} Otherwise, the behavior of the program is unspecified; it might raise an exception or crash, for example. @end{Discussion} @begin{Reason} Unspecified is almost the same thing as erroneous; they both allow arbitrarily bad behavior. We don't say erroneous here, because the implementation might allow the address passed to To_Pointer to point at some memory that just happens to @lquotes@;look like@rquotes@; an object of type Object. That's not necessarily an error; it's just not portable. However, if the actual type passed to Object is (for example) an array type, the programmer would need to be aware of any dope that the implementation expects to exist, when passing an address that did not come from the Address attribute of an object of type Object. One might wonder why To_Pointer and To_Address are any better than unchecked conversions. The answer is that Address does not necessarily have the same representation as an access type. For example, an access value might point at the bounds of an array when an address would point at the first element. Or an access value might be an offset in words from someplace, whereas an address might be an offset in bytes from the beginning of memory. @end{Reason} @end{StaticSem} @begin{ImplPerm} An implementation may place restrictions on instantiations of Address_To_Access_Conversions. @begin{Ramification} For example, if the hardware requires aligned loads and stores, then dereferencing an access value that is not properly aligned might raise an exception. For another example, if the implementation has chosen to use negative component offsets (from an access value), it might not be possible to preserve the semantics, since negative offsets from the Address are not allowed. (The Address attribute always points at @lquotes@;the first of the storage elements....@rquotes@;) Note that while the implementation knows how to convert an access value into an address, it might not be able to do the reverse. To avoid generic contract model violations, the restriction might have to be detected at run time in some cases. @end{Ramification} @end{ImplPerm} @LabeledClause{Machine Code Insertions} @begin{Intro} @redundant[@Defn{machine code insertion} A machine code insertion can be achieved by a call to a subprogram whose @nt{sequence_of_statements} contains @nt{code_statement}s.] @end{Intro} @begin{Syntax} @Syn{lhs=<code_statement>,rhs="@Syn2{qualified_expression};"} @begin{SyntaxText} A @nt{code_statement} is only allowed in the @nt{handled_sequence_of_@!statements} of a @nt{subprogram_@!body}. If a @nt{subprogram_@!body} contains any @nt{code_@!statement}s, then within this @nt{subprogram_@!body} the only allowed form of @nt{statement} is a @nt{code_@!statement} (labeled or not), the only allowed @nt{declarative_@!item}s are @nt{use_@!clause}s, and no @nt{exception_@!handler} is allowed (@nt{comment}s and @nt{pragma}s are allowed as usual). @end{SyntaxText} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(code_statement)} The @nt{qualified_expression} is expected to be of any type. @end{Resolution} @begin{Legality} The @nt{qualified_expression} shall be of a type declared in package System.Machine_Code. @begin{Ramification} This includes types declared in children of System.Machine_Code. @end{Ramification} A @nt<code_statement> shall appear only within the scope of a @nt<with_clause> that mentions package System.Machine_Code. @begin{Ramification} Note that this is not a note; without this rule, it would be possible to write machine code in compilation units which depend on System.Machine_Code only indirectly. @end{Ramification} @end{Legality} @begin{StaticSem} @Defn{System.Machine_Code} @ChildUnit{Parent=[System],Child=[Machine_Code]} The contents of the library package System.Machine_Code (if provided) are implementation defined. The meaning of @nt{code_statement}s is implementation defined. @Redundant{Typically, each @nt{qualified_expression} represents a machine instruction or assembly directive.} @begin{Discussion} For example, an instruction might be a record with an Op_Code component and other components for the operands. @end{Discussion} @ImplDef{The contents of the visible part of package System.Machine_Code, and the meaning of @nt{code_statement}s.} @end{StaticSem} @begin{ImplPerm} An implementation may place restrictions on @nt{code_statement}s. An implementation is not required to provide package System.Machine_Code. @end{ImplPerm} @begin{Notes} An implementation may provide implementation-defined pragmas specifying register conventions and calling conventions. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]} Machine code functions are exempt from the rule that a @Chg{Version=[2],New=[return statement],Old=[@nt{return_@!statement}]} is required. In fact, @Chg{Version=[2],New=[return statements],Old=[@nt{return_@!statement}s]} are forbidden, since only @nt{code_statement}s are allowed. @begin{Discussion} The idea is that the author of a machine code subprogram knows the calling conventions, and refers to parameters and results accordingly. The implementation should document where to put the result of a machine code function, for example, @lquotes@;Scalar results are returned in register 0.@rquotes@; @end{Discussion} Intrinsic subprograms (see @RefSec{Conformance Rules}) can also be used to achieve machine code insertions. Interface to assembly language can be achieved using the features in @RefSec{Interface to Other Languages}. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of a code statement:} @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} M : Mask; @key[procedure] Set_Mask@Chg{Version=[3],New=[ @key[with] Inline],Old=[]};@Chg{Version=[3],New=[],Old=[ @key[pragma] Inline(Set_Mask);]} @key[procedure] Set_Mask @key[is] @key[use] System.Machine_Code; --@RI{ assume @lquotes@;@key[with] System.Machine_Code;@rquotes@; appears somewhere above} @key[begin] SI_Format'(Code => SSM, B => M'Base_Reg, D => M'Disp); --@RI{ Base_Reg and Disp are implementation-defined attributes} @key[end] Set_Mask; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Machine code functions are allowed in Ada 95; in Ada 83, only procedures were allowed. @end{Extend83} @begin{DiffWord83} The syntax for @nt{code_statement} is changed to say @lquotes@;@nt{qualified_expression}@rquotes@; instead of @lquotes@;@Syn2{subtype_mark}'@Syn2{record_aggregate}@rquotes@;. Requiring the type of each instruction to be a record type is overspecification. @end{DiffWord83} @LabeledClause{Unchecked Type Conversions} @begin{Intro} @redundant[@Defn{unchecked type conversion} @Defn2{Term=[type conversion], Sec=(unchecked)} @Defn2{Term=[conversion], Sec=(unchecked)} @IndexSeeAlso{Term=[type_conversion],See=(unchecked type conversion)} @IndexSee{Term=[cast],See=(unchecked type conversion)} An unchecked type conversion can be achieved by a call to an instance of the generic function Unchecked_Conversion.] @end{Intro} @begin{StaticSem} @Leading@keepnext@;The following language-defined generic library function exists: @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[generic] @key[type] Source(<>) @key[is] @key[limited] @key[private]; @key[type] Target(<>) @key[is] @key[limited] @key[private]; @SubChildUnit{Parent=[Ada],Child=[Unchecked_Conversion]}@key[function] Ada.Unchecked_Conversion(S : Source) @key[return] Target@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]};@Chg{Version=[3],New=[],Old=[ @key[pragma] Convention(Intrinsic, Ada.Unchecked_Conversion);]} @key[pragma] Pure(Ada.Unchecked_Conversion); @end{Example} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The @Chg{Version=[3],New=[aspect],Old=[@nt{pragma}]} Convention implies that the attribute Access is not allowed for instances of Unchecked_Conversion. @end{Reason} @end{StaticSem} @begin{RunTime} The size of the formal parameter S in an instance of Unchecked_Conversion is that of its subtype. @Redundant[This is the actual subtype passed to Source, except when the actual is an unconstrained composite subtype, in which case the subtype is constrained by the bounds or discriminants of the value of the actual expression passed to S.] @Leading@;If all of the following are true, the effect of an unchecked conversion is to return the value of an object of the target subtype whose representation is the same as that of the source object S: @begin{Itemize} S'Size = Target'Size. @begin{Ramification} Note that there is no requirement that the Sizes be known at compile time. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0078-1]} S'Alignment @Chg{Version=[3],New=[is a multiple of],Old=[=]} Target'Alignment@Chg{Version=[3],New=[ or Target'Alignment is zero],Old=[]}. The target subtype is not an unconstrained composite subtype. @PDefn{contiguous representation} @PDefn{discontiguous representation} S and the target subtype both have a contiguous representation. The representation of S is a representation of an object of the target subtype. @end{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00426-01]} Otherwise, @Chg{Version=[2],New=[if the result type is scalar, the result of the function is implementation defined, and can have an invalid representation (see @RefSecNum{Data Validity}). If the result type is nonscalar, ],Old=[]}the effect is implementation defined; in particular, the result can be abnormal (see @RefSecNum{Data Validity}). @ChgImplDef{Version=[2],Kind=[Added],Text=[@Chg{Version=[2],New=[The result of unchecked conversion for instances with scalar result types whose result is not defined by the language.],Old=[]}]} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The effect of unchecked conversion@Chg{Version=[2],New=[ for instances with nonscalar result types whose effect is not defined by the language],Old=[]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Note the difference between these sentences; the first only says that the bits returned are implementation defined, while the latter allows any effect. The difference is because scalar objects should never be abnormal unless their assignment was disrupted or if they are a subcomponent of an abnormal composite object. Neither exception applies to instances of Unchecked_Conversion.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} Whenever unchecked conversions are used, it is the programmer's responsibility to ensure that these conversions maintain the properties that are guaranteed by the language for objects of the target type. @Chg{Version=[2],New=[For nonscalar types, this],Old=[This]} requires the user to understand the underlying run-time model of the implementation. The execution of a program that violates these properties by means of unchecked conversions @Chg{Version=[2],New=[returning a nonscalar type ], Old=[]}is erroneous.@Chg{Version=[2],New=[ Properties of scalar types can be checked by using the Valid attribute (see @RefSecNum{The Valid Attribute}); programs can avoid violating properties of the type (and erroneous execution) by careful use of this attribute.],Old=[]} An instance of Unchecked_Conversion can be applied to an object of a private type, assuming the implementation allows it. @end{Ramification} @end{RunTime} @begin{ImplPerm} An implementation may return the result of an unchecked conversion by reference, if the Source type is not a by-copy type. @Redundant[In this case, the result of the unchecked conversion represents simply a different (read-only) view of the operand of the conversion.] @begin{Ramification} In other words, the result object of a call on an instance of Unchecked_Conversion can occupy the same storage as the formal parameter S. @end{Ramification} An implementation may place restrictions on Unchecked_Conversion. @begin{Ramification} For example, an instantiation of Unchecked_Conversion for types for which unchecked conversion doesn't make sense may be disallowed. @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00051-02]} @Chg{Version=[2],New=[Since the],Old=[The]} Size of an array object @Chg{Version=[2],New=[generally does],Old=[should]} not include its bounds@Chg{Version=[2],New=[],Old=[; hence]}, the bounds should not be part of the converted data. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Since the Size of an array object generally does not include its bounds, the bounds should not be part of the converted data in an instance of Unchecked_Conversion.]}]} @begin{Ramification} On the other hand, we have no advice to offer about discriminants and tag fields. @end{Ramification} The implementation should not generate unnecessary run-time checks to ensure that the representation of S is a representation of the target type. It should take advantage of the permission to return by reference when possible. Restrictions on unchecked conversions should be avoided unless required by the target environment. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[There should not be unnecessary run-time checks on the result of an Unchecked_Conversion; the result should be returned by reference when possible. Restrictions on Unchecked_Conversions should be avoided.]}]} @begin{ImplNote} As an example of an unnecessary run-time check, consider a record type with gaps between components. The compiler might assume that such gaps are always zero bits. If a value is produced that does not obey that assumption, then the program might misbehave. The implementation should not generate extra code to check for zero bits (except, perhaps, in a special error-checking mode). @end{ImplNote} @Leading@PDefn2{Term=[recommended level of support], Sec=(unchecked conversion)} The recommended level of support for unchecked conversions is: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Unchecked conversions should be supported and should be reversible in the cases where this @Chg{Version=[3],New=[subclause],Old=[clause]} defines the result.@PDefn{contiguous representation} @PDefn{discontiguous representation} To enable meaningful use of unchecked conversion, a contiguous representation should be used for elementary subtypes, for statically constrained array subtypes whose component subtype is one of the subtypes described in this paragraph, and for record subtypes without discriminants whose component subtypes are described in this paragraph. @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for Unchecked_Conversion should be followed.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00051-02]} @ChgAdded{Version=[2],Text=[The implementation advice about the size of array objects was moved to 13.3 so that all of the advice about Size is in one place.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Clarified that the result of Unchecked_Conversion for scalar types can be invalid, but not abnormal.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0078-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Relaxed the alignment requirement slightly, giving a defined result in more cases.]} @ChgNote{This is not an extension, as a program taking advantage of this change was (and very well might have worked) legal before the change; it's just guaranteed to be portable now.} @end{Diffword2005} @LabeledSubClause{Data Validity} @begin{Intro} Certain actions that can potentially lead to erroneous execution are not directly erroneous, but instead can cause objects to become @i{abnormal}. Subsequent uses of abnormal objects can be erroneous. A scalar object can have an @i{invalid representation}, which means that the object's representation does not represent any value of the object's subtype. @RootDefn{uninitialized variables} The primary cause of invalid representations is uninitialized variables. Abnormal objects and invalid representations are explained in this subclause. @end{Intro} @begin{RunTime} @Leading@RootDefn{normal state of an object} @RootDefn{abnormal state of an object} When an object is first created, and any explicit or default initializations have been performed, the object and all of its parts are in the @i{normal} state. Subsequent operations generally leave them normal. However, an object or part of an object can become @i{abnormal} in the following ways: @begin{Itemize} @Defn{disruption of an assignment} An assignment to the object is disrupted due to an abort (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}) or due to the failure of a language-defined check (see @RefSecNum{Exceptions and Optimization}). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00426-01]} The object is not scalar, and is passed to an @key[in out] or @key[out] parameter of an imported procedure@Chg{Version=[2],New=[, the Read procedure of an instance of Sequential_IO, Direct_IO, or Storage_IO, or the stream attribute T'Read], Old=[ or language-defined input procedure]}, if after return from the procedure the representation of the parameter does not represent a value of the parameter's subtype. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The object is the return object of a function call of a nonscalar type, and the function is an imported function, an instance of Unchecked_Conversion, or the stream attribute T'Input, if after return from the function the representation of the return object does not represent a value of the function's subtype.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We explicitly list the routines involved in order to avoid future arguments. All possibilities are listed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We did not include Stream_IO.Read in the list above. A Stream_Element should include all possible bit patterns, and thus it cannot be invalid. Therefore, the parameter will always represent a value of its subtype. By omitting this routine, we make it possible to write arbitrary I/O operations without any possibility of abnormal objects.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[@Redundant[For an imported object, it is the programmer's responsibility to ensure that the object remains in a normal state.]]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This follows (and echos) the standard rule of interfacing; the programmer must ensure that Ada semantics are followed (see @RefSecNum{Interfacing Aspects}).]} @end{TheProof} @PDefn{unspecified} Whether or not an object actually becomes abnormal in these cases is not specified. An abnormal object becomes normal again upon successful completion of an assignment to the object as a whole. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to evaluate a @nt<primary> that is a @nt<name> denoting an abnormal object, or to evaluate a @nt{prefix} that denotes an abnormal object. @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @Comment{There appears to be no justification for this statement; everything can become abnormal. We leave the prefix for the next paragraph, so we use Chg rather than ChgDeleted.} @Chg{Version=[2],New=[],Old=[Although a composite object with no subcomponents of an access type, and with static constraints all the way down cannot become abnormal, a scalar subcomponent of such an object can become abnormal.]} The @key[in out] or @key[out] parameter case does not apply to scalars; bad scalars are merely invalid representations, rather than abnormal, in this case. @end{Ramification} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The reason we allow access objects, and objects containing subcomponents of an access type, to become abnormal is because the correctness of an access value cannot necessarily be determined merely by looking at the bits of the object. The reason we allow scalar objects to become abnormal is that we wish to allow the compiler to optimize assuming that the value of a scalar object belongs to the object's subtype, if the compiler can prove that the object is initialized with a value that belongs to the subtype. The reason we allow composite objects to become abnormal @Chg{Version=[2],New=[],Old=[if some constraints are nonstatic ]}is that such object might be represented with implicit levels of indirection; if those are corrupted, then even assigning into a component of the object, or simply asking for its Address, might have an unpredictable effect. The same is true if the discriminants have been destroyed. @end{Reason} @end{Erron} @begin{Bounded} @Leading@Defn{invalid representation}@PDefn2{Term=(bounded error),Sec=(cause)} If the representation of a scalar object does not represent a value of the object's subtype (perhaps because the object was not initialized), the object is said to have an @i{invalid representation}. It is a bounded error to evaluate the value of such an object. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the error is detected, either Constraint_Error or Program_Error is raised. Otherwise, execution continues using the invalid representation. The rules of the language outside this subclause assume that all objects have valid representations. The semantics of operations on invalid representations are as follows: @begin{Discussion} The AARM is more explicit about what happens when the value of the case expression is an invalid representation. @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[This includes the result object of functions, including the result of Unchecked_Conversion, T'Input, and imported functions.]} @end{Ramification} @begin{Itemize} If the representation of the object represents a value of the object's type, the value of the type is used. If the representation of the object does not represent a value of the object's type, the semantics of operations on such representations is implementation-defined, but does not by itself lead to erroneous or unpredictable execution, or to other objects becoming abnormal. @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[This means that the implementation must take care not to use an invalid representation in a way that might cause erroneous execution. For instance, the exception mandated for @nt{case_statement}s must be raised. Array indexing must not cause memory outside of the array to be written (and usually, not read either). These cases and similar cases may require explicit checks by the implementation.]} @end{ImplNote} @end{Itemize} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0279-1]} @PDefn2{Term=(erroneous execution),Sec=(cause)} A call to an imported function or an instance of Unchecked_Conversion is erroneous if the result is scalar, @Chg{Version=[2],New=[],Old=[and ]}the result object has an invalid representation@Chg{Version=[2],New=[, and the result is used other than as the @nt{expression} of an @nt{assignment_statement} or an @nt{object_declaration},@Chg{Version=[3],New=[ as the @SynI{object_}@nt{name} of an @nt{object_renaming_declaration},],Old=[]} or as the @nt{prefix} of a Valid attribute. If such a result object is used as the source of an assignment, and the assigned value is an invalid representation for the target of the assignment, then any use of the target object prior to a further assignment to the target object, other than as the @nt{prefix} of a Valid attribute reference, is erroneous],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} In a typical implementation, every bit pattern that fits in an object of @Chg{Version=[2],New=[a signed],Old=[an]} integer subtype will represent a value of the type, if not of the subtype. However, for an enumeration or floating point type,@Chg{Version=[2],New=[ as well as some modular types,],Old=[]} there are typically bit patterns that do not represent any value of the type. In such cases, the implementation ought to define the semantics of operations on the invalid representations in the obvious manner (assuming the bounded error is not detected): a given representation should be equal to itself, a representation that is in between the internal codes of two enumeration literals should behave accordingly when passed to comparison operators and membership tests, etc. We considered @i{requiring} such sensible behavior, but it resulted in too much arcane verbiage, and since implementations have little incentive to behave irrationally, such verbiage is not important to have. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} If a stand-alone scalar object is initialized to a an in-range value, then the implementation can take advantage of the fact that @Chg{Version=[2],New=[the use of ],Old=[]}any out-of-range value has to be @Chg{Version=[2],New=[erroneous],Old=[abnormal]}.@ChgNote{Do you see "abnormal" in the rules above? Thought not.} Such an out-of-range value can be produced only by things like unchecked conversion, @Chg{Version=[2],New=[imported functions],Old=[input]}, and @Chg{Version=[2],New=[abnormal values caused by ],Old=[]}disruption of an assignment due to abort or to failure of a language-defined check. This depends on out-of-range values being checked before assignment (that is, checks are not optimized away unless they are proven redundant). @Leading@;Consider the following example: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01]} @key[type] My_Int @key[is] @key[range] 0..99; @key[function] Safe_Convert @key[is] @key[new] Unchecked_Conversion(My_Int, Integer); @key[function] Unsafe_Convert @key[is] @key[new] Unchecked_Conversion(My_Int, Positive); X : Positive := Safe_Convert(0); --@RI{ Raises Constraint_Error.} Y : Positive := Unsafe_Convert(0); --@Chg{Version=[2],New=[@RI{ Bounded Error, may be invalid.} B : Boolean := Y'Valid; --@RI{ OK, B = False.} Z : Positive := Y+1; --@RI{ Erroneous to use Y.}],Old=[@RI{ Erroneous.}]} @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00167-01],ARef=[AI95-00426-01]} The call to Unsafe_Convert @Chg{Version=[2],New=[ is a bounded error, which might raise Constraint_Error, Program_Error, or return an invalid value. Moreover, if an exception is not raised, most uses of that invalid value (including the use of Y) cause],Old=[causes]} erroneous execution. The call to Safe_Convert is not erroneous. The result object is an object of subtype Integer containing the value 0. The assignment to X is required to do a constraint check; the fact that the conversion is unchecked does not obviate the need for subsequent checks required by the language rules. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00167-01],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The reason for delaying erroneous execution until the object is used is so that the invalid representation can be tested for validity using the Valid attribute (see @RefSecNum{The Valid Attribute}) without causing execution to become erroneous. Note that this delay does not imply an exception will not be raised; an implementation could treat both conversions in the example in the same way and raise Constraint_Error.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0279-1]} @ChgAdded{Version=[3],Text=[The rules are defined in terms of the result object, and thus the name used to reference that object is irrelevant. That is why we don't need any special rules to describe what happens when the function result is renamed.]} @end{Ramification} @begin{ImplNote} If an implementation wants to have a @lquotes@;friendly@rquotes@; mode, it might always assign an uninitialized scalar a default initial value that is outside the object's subtype (if there is one), and check for this value on some or all reads of the object, so as to help detect references to uninitialized scalars. Alternatively, an implementation might want to provide an @lquotes@;unsafe@rquotes@; mode where it presumed even uninitialized scalars were always within their subtype. @end{ImplNote} @begin{Ramification} The above rules imply that it is a bounded error to apply a predefined operator to an object with a scalar subcomponent having an invalid representation, since this implies reading the value of each subcomponent. Either Program_Error or Constraint_Error is raised, or some result is produced, which if composite, might have a corresponding scalar subcomponent still with an invalid representation. Note that it is not an error to assign, convert, or pass as a parameter a composite object with an uninitialized scalar subcomponent. In the other hand, it is a (bounded) error to apply a predefined operator such as =, <, and @key(xor) to a composite operand with an invalid scalar subcomponent. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0054-2]} @PDefn2{Term=(erroneous execution),Sec=(cause)} The dereference of an access value is erroneous if it does not designate an object of an appropriate type or a subprogram with an appropriate profile, if it designates a nonexistent object, or if it is an access-to-variable value that designates a constant object@Chg{Version=[3],New=[ and it did not originate from an attribute_reference applied to an aliased variable view of a controlled or immutably limited object],Old=[]}. @Redundant[@Chg{Version=[3],New=[An],Old=[Such an]} access value @Chg{Version=[3],New=[whose dereference is erroneous ],Old=[]}can exist, for example, because of Unchecked_Deallocation, Unchecked_Access, or Unchecked_Conversion.] @begin{Ramification} The above mentioned Unchecked_... features are not the only causes of such access values. For example, interfacing to other languages can also cause the problem. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0054-2]} @Chg{Version=[3],New=[We permit the use of access-to-variable values that designate constant objects so long as they originate from an aliased variable view of a controlled or immutably limited constant, such as during the initialization of a constant (both via the @ldquote@;current instance@rdquote and during a call to Initialize) or during an assignment (during a call to Adjust).],Old=[One obscure example is if the Adjust subprogram of a controlled type uses Unchecked_Access to create an access-to-variable value designating a subcomponent of its controlled parameter, and saves this access value in a global object. When Adjust is called during the initialization of a constant object of the type, the end result will be an access-to-variable value that designates a constant object.]} @end{Ramification} @end{Erron} @begin{Notes} Objects can become abnormal due to other kinds of actions that directly update the object's representation; such actions are generally considered directly erroneous, however. @end{Notes} @begin{DiffWord83} In order to reduce the amount of erroneousness, we separate the concept of an undefined value into objects with invalid representation (scalars only) and abnormal objects. Reading an object with an invalid representation is a bounded error rather than erroneous; reading an abnormal object is still erroneous. In fact, the only safe thing to do to an abnormal object is to assign to the object as a whole. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00167-01]} @ChgAdded{Version=[2],Text=[The description of erroneous execution for Unchecked_Conversion and imported objects was tightened up so that using the Valid attribute to test such a value is not erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Clarified the definition of objects that can become abnormal; made sure that all of the possibilities are included.]} @end{DiffWord95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0054-2]} @ChgAdded{Version=[3],Text=[@b<Correction:> Common programming techniques such as squirreling away@Defn{squirrel away} an access to a controlled object during initialization and using a self-referencing discriminant (the so-called @ldquote@;Rosen trick@rdquote@Defn{Rosen trick}) no longer are immediately erroneous if the object is declared constant, so these techniques can be used portably and safely. Practically, these techniques already worked as compilers did not take much advantage of this rule, so the impact of this change will be slight.]} @ChgNote{This is not an extension, as such a program was already legal (although erroneous).} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0279-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The description of erroneous execution for Unchecked_Conversion and imported objects was adjusted to clarify that renaming such an object is not, by itself, erroneous.]} @end{Diffword2005} @LabeledSubClause{The Valid Attribute} @begin{Intro} The Valid attribute can be used to check the validity of data produced by unchecked conversion, input, interface to foreign languages, and the like. @end{Intro} @begin{StaticSem} @Leading@;For @PrefixType{a @nt<prefix> X that denotes a scalar object @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin(description) @ChgAttribute{Version=[3],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<X>, AttrName=<Valid>, ARef=[AI05-0153-3], Text=<Yields True if and only if the object denoted by X is normal@Chg{Version=[3],New=[,],Old=[ and]} has a valid representation@Chg{Version=[3],New=[, and the predicate@Defn2{Term=[predicate evaluated],Sec=[Valid attribute]} of the nominal subtype of X evaluates to True],Old=[]}. The value of this attribute is of the predefined type Boolean.>} @begin{Ramification} Having checked that X'Valid is True, it is safe to read the value of X without fear of erroneous execution caused by abnormality, or a bounded error caused by an invalid representation. Such a read will produce a value in the subtype of X. @end{Ramification} @end{description} @EndPrefixType{} @end{StaticSem} @begin{Notes} @Leading@;Invalid data can be created in the following cases (not counting erroneous or unpredictable execution): @begin{Itemize} an uninitialized scalar object, the result of an unchecked conversion, input, interface to another language (including machine code), aborting an assignment, disrupting an assignment due to the failure of a language-defined check (see @RefSecNum{Exceptions and Optimization}), and use of an object whose Address has been specified. @end{Itemize} X'Valid is not considered to be a read of X; hence, it is not an error to check the validity of invalid data. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[The Valid attribute may be used to check the result of calling an instance of Unchecked_Conversion (or any other operation that can return invalid values). However, an exception handler should also be provided because implementations are permitted to raise Constraint_Error or Program_Error if they detect the use of an invalid representation (see @RefSecNum{Data Validity}).]} @begin{Ramification} If X is of an enumeration type with a representation clause, then X'Valid checks that the value of X when viewed as an integer is one of the specified internal codes. @end{Ramification} @begin{Reason} Valid is defined only for scalar objects because the implementation and description burden would be too high for other types. For example, given a typical run-time model, it is impossible to check the validity of an access value. The same applies to composite types implemented with internal pointers. One can check the validity of a composite object by checking the validity of each of its scalar subcomponents. The user should ensure that any composite types that need to be checked for validity are represented in a way that does not involve implementation-defined components, or gaps between components. Furthermore, such types should not contain access subcomponents. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgNote{This was never true, even in Ada 95} @ChgDeleted{Version=[2],Text=[Note that one can safely check the validity of a composite object with an abnormal value only if the constraints on the object and all of its subcomponents are static. Otherwise, evaluation of the @nt{prefix} of the @nt{attribute_reference} causes erroneous execution (see @RefSecNum{Names}).]} @end{Reason} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} X'Valid is new in Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00426-01]} @ChgAdded{Version=[2],Text=[Added a note explaining that handlers for Constraint_Error and Program_Error are needed in the general case of testing for validity. (An implementation could document cases where these are not necessary, but there is no language requirement.)]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[The validity check now also includes a check of the predicate aspects (see @RefSecNum{Subtype Predicates}), if any, of the subtype of the object.]} @end{DiffWord2005} @LabeledClause{Unchecked Access Value Creation} @begin{Intro} @redundant[The attribute Unchecked_Access is used to create access values in an unsafe manner @em the programmer is responsible for preventing @lquotes@;dangling references.@rquotes@;] @end{Intro} @begin{StaticSem} @Leading@;The following attribute is defined for @PrefixType{a @nt{prefix} X that denotes an aliased view of an object}: @begin{Description} @Attribute{Prefix=<X>, AttrName=<Unchecked_Access>, Text=<All rules and semantics that apply to X'Access (see @RefSecNum{Operations of Access Types}) apply also to X'Unchecked_Access, except that, for the purposes of accessibility rules and checks, it is as if X were declared immediately within a library package.>} @IndexSeeAlso{Term=[Access attribute],See=(Unchecked_Access attribute)} @end{Description} @EndPrefixType{} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[We say @ldquote@;rules and semantics@rdquote@; here so that library-level accessibility applies to the value created by X'Unchecked_Access as well as to the checks needed for the attribute itself. This means that any anonymous access values that inherit the accessibility of this attribute (such as access parameters) also act as if they have library-level accessibility. We don't want the "real" accessibility of the created value re-emerging at a later point @en that would create hard-to-understand bugs.]} @end{Ramification} @end{StaticSem} @begin{Notes} This attribute is provided to support the situation where a local object is to be inserted into a global linked data structure, when the programmer knows that it will always be removed from the data structure prior to exiting the object's scope. The Access attribute would be illegal in this case (see @RefSec{Operations of Access Types}). @begin{Ramification} @PDefn2{Term=[expected type], Sec=(Unchecked_Access attribute)} The expected type for X'Unchecked_Access is as for X'Access. If an @nt<attribute_reference> with Unchecked_Access is used as the actual parameter for an access parameter, an Accessibility_Check can never fail on that access parameter. @end{Ramification} There is no Unchecked_Access attribute for subprograms. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00254-01]} Such an attribute would allow @Chg{Version=[2],New=[unsafe ], Old=[]}@lquotes@;downward closures@rquotes@;, where an access value designating a more nested subprogram is passed to a less nested subprogram.@Chg{Version=[2],New=[ (Anonymous access-to-subprogram parameters provide safe @lquotes@;downward closures@rquotes@;.)],Old=[]} This requires some means of reconstructing the global environment for the more nested subprogram, so that it can do up-level references to objects. The two methods of implementing up-level references are displays and static links. If @Chg{Version=[2],New=[unsafe ],Old=[]}downward closures were supported, each access-to-subprogram value would have to carry the static link or display with it. @Chg{Version=[2],New=[We don't want to require the space and time overhead of requiring the extra information for all access-to-subprogram types, especially as including it would make interfacing to other languages (like C) harder],Old=[In the case of displays, this was judged to be infeasible, and we don't want to disrupt implementations by forcing them to use static links if they already use displays]}. If desired, an instance of Unchecked_Conversion can be used to create an access value of a global access-to-subprogram type that designates a local subprogram. The semantics of using such a value are not specified by the language. In particular, it is not specified what happens if such subprograms make up-level references; even if the frame being referenced still exists, the up-level reference might go awry if the representation of a value of a global access-to-subprogram type doesn't include a static link. @end{Reason} @end{Notes} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Storage Management} @begin{Intro} @Redundant[ @Defn{user-defined storage management} @Defn2{Term=[storage management], Sec=(user-defined)} @Defn{user-defined heap management} @Defn2{Term=[heap management], Sec=(user-defined)} Each access-to-object type has an associated storage pool. The storage allocated by an @nt{allocator} comes from the pool; instances of Unchecked_Deallocation return storage to the pool. Several access types can share the same pool.] @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00435-01]} @Redundant[A storage pool is a variable of a type in the class rooted at Root_Storage_Pool, which is an abstract limited controlled type. By default, the implementation chooses a @i{standard storage pool} for each access@Chg{Version=[2],New=[-to-object],Old=[]} type. The user may define new pool types, and may override the choice of pool for an access@Chg{Version=[2],New=[-to-object],Old=[]} type by specifying Storage_Pool for the type.] @begin{Ramification} By default, the implementation might choose to have a single global storage pool, which is used (by default) by all access types, which might mean that storage is reclaimed automatically only upon partition completion. Alternatively, it might choose to create a new pool at each accessibility level, which might mean that storage is reclaimed for an access type when leaving the appropriate scope. Other schemes are possible. @end{Ramification} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Storage pool>, Text=<@ChgAdded{Version=[3],Text=[Each access-to-object type has an associated storage pool object. The storage for an object created by an @nt{allocator} comes from the storage pool of the type of the @nt{allocator}. Some storage pools may be partitioned into subpools in order to support finer-grained storage management.]}>} @end{Intro} @begin{Legality} If Storage_Pool is specified for a given access type, Storage_Size shall not be specified for it. @begin{Reason} The Storage_Pool determines the Storage_Size; hence it would not make sense to specify both. Note that this rule is simplified by the fact that the aspects in question cannot be specified for derived types, nor for nonfirst subtypes, so we don't have to worry about whether, say, Storage_Pool on a derived type overrides Storage_Size on the parent type. For the same reason, @lquotes@;specified@rquotes@; means the same thing as @lquotes@;directly specified@rquotes@; here. @end{Reason} @end{Legality} @begin{StaticSem} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @key[with] Ada.Finalization; @key[with] System.Storage_Elements; @ChildUnit{Parent=[System],Child=[Storage_Pools]}@key[package] System.Storage_Pools @key[is] @key{pragma} Preelaborate(System.Storage_Pools); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Root_Storage_Pool} @key[is] @key[abstract] @key[new] Ada.Finalization.Limited_Controlled @key[with] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Root_Storage_Pool);],Old=[]} @key[procedure] @AdaSubDefn{Allocate}( Pool : @key[in] @key[out] Root_Storage_Pool; Storage_Address : @key[out] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count) @key[is] @key[abstract]; @key[procedure] @AdaSubDefn{Deallocate}( Pool : @key[in] @key[out] Root_Storage_Pool; Storage_Address : @key[in] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count) @key[is] @key[abstract]; @key[function] @AdaSubDefn{Storage_Size}(Pool : Root_Storage_Pool) @key[return] Storage_Elements.Storage_Count @key[is] @key[abstract]; @key[private] ... -- @RI{not specified by the language} @key[end] System.Storage_Pools; @end{Example} @begin{Reason} The Alignment parameter is provided to Deallocate because some allocation strategies require it. If it is not needed, it can be ignored. @end{Reason} @Defn{storage pool type} @Defn{pool type} A @i{storage pool type} (or @i{pool type}) is a descendant of Root_Storage_Pool. @Defn{storage pool element} @Defn{pool element} @Defn2{Term=[element], Sec=(of a storage pool)} The @i{elements} of a storage pool are the objects allocated in the pool by @nt{allocator}s. @begin{Discussion} In most cases, an element corresponds to a single memory block allocated by Allocate. However, in some cases the implementation may choose to associate more than one memory block with a given pool element. @end{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00435-01]} @Leading@;For @PrefixType{every access@Chg{Version=[2],New=[-to-object],Old=[]} subtype S}, the following @Chg{New=[representation ],Old=[]}attributes are defined: @begin{Description} @Attribute{Prefix=<S>, AttrName=<Storage_Pool>, Text=<Denotes the storage pool of the type of S. The type of this attribute is Root_@!Storage_@!Pool'Class.>} @Attribute{Prefix=<S>, AttrName=<Storage_Size>, Text=<Yields the result of calling Storage_Size(S'Storage_Pool)@Redundant{, which is intended to be a measure of the number of storage elements reserved for the pool.} The type of this attribute is @i{universal_integer}.>} @EndPrefixType{} @begin{Ramification} Storage_Size is also defined for task subtypes and objects @em see @RefSecNum{Operational and Representation Attributes}. Storage_Size is not a measure of how much un-allocated space is left in the pool. That is, it includes both allocated and unallocated space. Implementations and users may provide a Storage_Available function for their pools, if so desired. @end{Ramification} @end{Description} @PDefn2{Term=[specifiable], Sec=(of Storage_Size for a nonderived access-to-object type)} @PDefn2{Term=[specifiable], Sec=(of Storage_Pool for a nonderived access-to-object type)} @Defn{Storage_Pool clause} @Defn{Storage_Size clause} Storage_Size or Storage_Pool may be specified for a nonderived access-to-object type via an @nt{attribute_@!definition_@!clause}; the @nt{name} in a Storage_Pool clause shall denote a variable.@Chg{Version=[3],New=[@AspectDefn{Storage_Pool}@AspectDefn{Storage_Size (access)}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Storage_Pool], Text=[@ChgAdded{Version=[3],Text=[Pool of memory from which @key[new] will allocate for a given access type.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Storage_Size (access)], Text=[@ChgAdded{Version=[3],Text=[Sets memory size for allocations for an access type.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0107-1],ARef=[AI05-0111-3],ARef=[AI05-0116-1]} An @nt{allocator} of @Chg{Version=[3],New=[a ],Old=[]}type @i<T> @Chg{Version=[3],New=[that does not support subpools ],Old=[]}allocates storage from @i<T>'s storage pool. If the storage pool is a user-defined object, then the storage is allocated by calling Allocate@Chg{Version=[3],New=[ as described below. @nt{Allocator}s for types that support subpools are described in @RefSecNum{Storage Subpools}.],Old=[, passing T'Storage_Pool as the Pool parameter. The Size_In_Storage_Elements parameter indicates the number of storage elements to be allocated, and is no more than D'Max_Size_In_Storage_Elements, where D is the designated subtype. The Alignment parameter is D'Alignment. @PDefn{contiguous representation} @PDefn{discontiguous representation} The result returned in the Storage_Address parameter is used by the @nt{allocator} as the address of the allocated storage, which is a contiguous block of memory of Size_In_@!Storage_@!Elements storage elements. @Redundant[Any exception propagated by Allocate is propagated by the @nt{allocator}.]]} @begin{Ramification} If the implementation chooses to represent the designated subtype in multiple pieces, one @nt{allocator} evaluation might result in more than one call upon Allocate. In any case, @nt{allocator}s for the access type obtain all the required storage for an object of the designated type by calling the specified Allocate procedure. @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0107-1]} @ChgDeleted{Version=[3],Text=[Note that the implementation does not turn other exceptions into Storage_Error.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0111],ARef=[AI95-00103-01]} @ChgAdded{Version=[1],Text=[If @i<D> (the designated type of @i<T>) includes subcomponents of other access types, they will be allocated from the storage pools for those types, even if those @nt{allocator}s are executed as part of the @nt{allocator} of @i<T> (as part of the initialization of the object). For instance, an access-to-task type @i<TT> may allocate the data structures used to implement the task value from other storage pools. (In particular, the task stack does not necessarily need to be allocated from the storage pool for @i<TT>.)]} @end{Ramification} @Defn{standard storage pool} If Storage_Pool is not specified for a type defined by an @nt{access_to_object_definition}, then the implementation chooses a standard storage pool for it in an implementation-defined manner. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} In this case, the exception Storage_Error is raised by an @nt{allocator} if there is not enough storage. It is implementation defined whether or not the implementation provides user-accessible names for the standard pool type(s). @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2],Text=[The manner of choosing a storage pool for an access type when Storage_Pool is not specified for the type.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The manner of choosing a storage pool is covered by a @DocReqName below, so it is not summarized here.]} @end{Discussion} @ImplDef{Whether or not the implementation provides user-accessible names for the standard pool type(s).} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @ChgNote{This was never true.}@Chg{Version=[2],New=[],Old=[An anonymous access type has no pool. ]}An access-to-object type defined by a @nt{derived_type_definition} inherits its pool from its parent type, so all access-to-object types in the same derivation class share the same pool. Hence the @lquotes@;defined by an @nt{access_to_object_definition}@rquotes@; wording above. @PDefn{contiguous representation} @PDefn{discontiguous representation} There is no requirement that all storage pools be implemented using a contiguous block of memory (although each allocation returns a pointer to a contiguous block of memory). @end{Ramification} If Storage_Size is specified for an access type, then the Storage_Size of this pool is at least that requested, and the storage for the pool is reclaimed when the master containing the declaration of the access type is left. @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If the implementation cannot satisfy the request, Storage_Error is raised at the point of the @nt{attribute_@!definition_@!clause}. If neither Storage_Pool nor Storage_Size are specified, then the meaning of Storage_Size is implementation defined. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0],Text=[The meaning of Storage_Size@Chg{Version=[2], New=[ when neither the Storage_Size nor the Storage_Pool is specified for an access type],Old=[]}.]} @begin{Ramification} The Storage_Size function and attribute will return the actual size, rather than the requested size. Comments about rounding up, zero, and negative on task Storage_Size apply here, as well. See also AI83-00557, AI83-00558, and AI83-00608. The expression in a Storage_Size clause need not be static. The reclamation happens after the master is finalized. @end{Ramification} @begin{ImplNote} For a pool allocated on the stack, normal stack cut-back can accomplish the reclamation. For a library-level pool, normal partition termination actions can accomplish the reclamation. @end{ImplNote} If Storage_Pool is specified for an access type, then the specified pool is used. @PDefn{unspecified} The effect of calling Allocate and Deallocate for a standard storage pool directly (rather than implicitly via an @nt{allocator} or an instance of Unchecked_Deallocation) is unspecified. @begin{Ramification} For example, an @nt{allocator} might put the pool element on a finalization list. If the user directly Deallocates it, instead of calling an instance of Unchecked_Deallocation, then the implementation would probably try to finalize the object upon master completion, which would be bad news. Therefore, the implementation should define such situations as erroneous. @end{Ramification} @end{StaticSem} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If Storage_Pool is specified for an access type, then if Allocate can satisfy the request, it should allocate a contiguous block of memory, and return the address of the first storage element in Storage_Address. The block should contain Size_In_Storage_Elements storage elements, and should be aligned according to Alignment. The allocated storage should not be used for any other purpose while the pool element remains in existence. If the request cannot be satisfied, then Allocate should propagate an exception @Redundant[(such as Storage_Error)]. If Allocate behaves in any other manner, then the program execution is erroneous. @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0107-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The Allocate procedure of a user-defined storage pool object @i<P> may be called by the implementation only to allocate storage for a type @i<T> whose pool is @i<P>, only at the following points:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[During the execution of an @nt{allocator} of type @i<T>;]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This includes during the evaluation of the initializing expression such as an @nt{aggregate}; this is important if the initializing expression is built in place. We need to allow allocation to be deferred until the size of the object is known.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[During the execution of a return statement for a function whose result is built-in-place in the result of an @nt{allocator} of type @i<T>;]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We need this bullet as well as the preceding one in order that exceptions that propagate from such a call to Allocate can be handled within the return statement. We don't want to require the generation of special handling code in this unusual case, as it would add overhead to most return statements of composite types.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[During the execution of an assignment operation with a target of an allocated object of type @i<T> with a part that has an unconstrained discriminated subtype with defaults.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We allow Allocate to be called during assignment of objects with mutable parts so that mutable objects can be implemented with reallocation on assignment. (Unfortunately, the term "mutable" is only defined in the AARM, so we have to use the long-winded wording shown here.)]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Of course, explicit calls to Allocate are also allowed and are not bound by any of the rules found here.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0107-1],ARef=[AI05-0116-1],ARef=[AI05-0193-1],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[For each of the calls of Allocate described above, @i{P} (equivalent to @i{T}'Storage_Pool) is passed as the Pool parameter. The Size_In_Storage_Elements parameter indicates the number of storage elements to be allocated, and is no more than @i{D}'Max_Size_In_Storage_Elements, where @i{D} is the designated subtype of @i{T}. The Alignment parameter is a nonzero integral multiple of @i{D}'Alignment if @i{D} is a specific type, and otherwise is a nonzero integral multiple of the alignment of the specific type identified by the tag of the object being created; it is unspecified if there is no such value. The Alignment parameter is no more than @i{D}'Max_Alignment_For_Allocation. The result returned in the Storage_Address parameter is used as the address of the allocated storage, which is a contiguous block of memory of Size_In_Storage_Elements storage elements. @Redundant[Any exception propagated by Allocate is propagated by the construct that contained the call.]]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that the implementation does not turn other exceptions into Storage_Error.]}@ChgNote{Moved from 13.11(16).} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@ldquote@;Nonzero integral multiple@rdquote of an alignment includes the alignment value itself, of course. The value is unspecified if the alignment of the specific type is zero.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[The number of calls to Allocate needed to implement an @nt{allocator} for any particular type is unspecified.@PDefn{unspecified} @PDefn{contiguous representation} @PDefn{discontiguous representation} The number of calls to Deallocate needed to implement an instance of Unchecked_Deallocation (see @RefSecNum{Unchecked Storage Deallocation}) for any particular object is the same as the number of Allocate calls for that object.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This supports objects that are allocated in one or more parts. The second sentence prevents extra or missing calls to Deallocate.]} @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[The number of calls to Deallocate from all sources for an object always will be the same as the number of calls to Allocate from all sources for that object. However, in unusual cases, not all of those Deallocate calls may be made by an instance of Unchecked_Deallocation. Specifically, in the unusual case of assigning to an object of a mutable variant record type such that the variant changes, some of the Deallocate calls may be made by the assignment (as may some of the Allocate calls).]} @end{Honest} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not define the relative order of multiple calls used to deallocate the same object @em that is, if the @nt{allocator} allocated two pieces @i{x} and @i{y}, then an instance of Unchecked_Deallocation might deallocate @i{x} and then @i{y}, or it might deallocate @i{y} and then @i{x}.]}@ChgNote{Moved from 13.11.2} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[The Deallocate procedure of a user-defined storage pool object @i{P} may be called by the implementation to deallocate storage for a type @i{T} whose pool is @i{P} only at the places when an Allocate call is allowed for @i{P}, during the execution of an instance of Unchecked_Deallocation for @i{T}, or as part of the finalization of the collection of @i{T}. For such a call of Deallocate, @i{P} (equivalent to @i{T}'Storage_Pool) is passed as the Pool parameter. The value of the Storage_Address parameter for a call to Deallocate is the value returned in the Storage_Address parameter of the corresponding successful call to Allocate. The values of the Size_In_Storage_Elements and Alignment parameters are the same values passed to the corresponding Allocate call. Any exception propagated by Deallocate is propagated by the construct that contained the call.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We allow Deallocate to be called anywhere that Allocate is, in order to allow the recovery of storage from failed allocations (that is, those that raise exceptions); from extended return statements that exit via a goto, exit, or locally handled exception; and from objects that are reallocated when they are assigned. In each of these cases, we would have a storage leak if the implementation did not recover the storage (there is no way for the programmer to do it). We do not require such recovery, however, as it could be a serious performance drag on these operations.]} @end{Reason} @end{ImplReq} @begin{DocReq} An implementation shall document the set of values that a user-defined Allocate procedure needs to accept for the Alignment parameter. An implementation shall document how the standard storage pool is chosen, and how storage is allocated by standard storage pools. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of storage pools.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The set of values that a user-defined Allocate procedure needs to accept for the Alignment parameter. How the standard storage pool is chosen, and how storage is allocated by standard storage pools.]}]} @end{DocReq} @begin{ImplAdvice} An implementation should document any cases in which it dynamically allocates heap storage for a purpose other than the evaluation of an @nt{allocator}. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any cases in which heap storage is dynamically allocated other than as part of the evaluation of an @nt{allocator} should be documented.]}]} @begin{Reason} This is @lquotes@;@ImplAdviceTitle@rquotes@; because the term @lquotes@;heap storage@rquotes@; is not formally definable; therefore, it is not testable whether the implementation obeys this advice. @end{Reason} A default (implementation-provided) storage pool for an access-to-constant type should not have overhead to support deallocation of individual objects. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[A default storage pool for an access-to-constant type should not have overhead to support deallocation of individual objects.]}]} @begin{Ramification} Unchecked_Deallocation is not defined for such types. If the access-to-constant type is library-level, then no deallocation (other than at partition completion) will ever be necessary, so if the size needed by an @nt{allocator} of the type is known at link-time, then the allocation should be performed statically. If, in addition, the initial value of the designated object is known at compile time, the object can be allocated to read-only memory. @end{Ramification} @begin{ImplNote} If the Storage_Size for an access type is specified, the storage pool should consist of a contiguous block of memory, possibly allocated on the stack. The pool should contain approximately this number of storage elements. These storage elements should be reserved at the place of the Storage_Size clause, so that @nt{allocator}s cannot raise Storage_Error due to running out of pool space until the appropriate number of storage elements has been used up. This approximate (possibly rounded-up) value should be used as a maximum; the implementation should not increase the size of the pool on the fly. If the Storage_Size for an access type is specified as zero, then the pool should not take up any storage space, and any @nt{allocator} for the type should raise Storage_Error. @end{ImplNote} @begin{Ramification} Note that most of this is approximate, and so cannot be (portably) tested. That's why we make it an Implementation Note. There is no particular number of allocations that is guaranteed to succeed, and there is no particular number of allocations that is guaranteed to fail. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @ChgNote{Use ChgAdded to get conditional Leading}@ChgAdded{Version=[2], Type=[Leading],Text=[]}@Chg{Version=[2],New=[The],Old=[A]} storage pool @Chg{Version=[2],New=[used ],Old=[]}for @Chg{Version=[2],New=[an @nt{allocator} of ],Old=[]}an anonymous access type should be @Chg{Version=[2],New=[determined as follows:],Old=[created at the point of an allocator for the type, and be reclaimed when the designated object becomes inaccessible;]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[If the @nt{allocator} is defining a coextension (see @RefSecNum{Operations of Access Types}) of an object being created by an outer @nt{allocator}, then the storage pool used for the outer @nt{allocator} should also be used for the coextension;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For other access discriminants and access parameters, the storage pool should be created at the point of the @nt{allocator}, and be reclaimed when the allocated object becomes inaccessible;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0051-1]} @ChgAdded{Version=[3],Text=[If the @nt{allocator} defines the result of a function with an access result, the storage pool is determined as though the @nt{allocator} were in place of the call of the function. If the call is the operand of a type conversion, the storage pool is that of the target access type of the conversion. If the call is itself defining the result of a function with an access result, this rule is applied recursively;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Otherwise, a default storage pool should be created at the point where the anonymous access type is elaborated; such a storage pool need not support deallocation of individual objects.]} @end{Itemize} @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Usually, a storage pool for an access discriminant or access parameter should be created at the point of an @nt{allocator}, and be reclaimed when the designated object becomes inaccessible. For other anonymous access types, the pool should be created at the point where the type is elaborated and need not support deallocation of individual objects.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00230-01]} @Chg{Version=[2],New=[For access parameters and access discriminants,], Old=[Normally]} the "storage pool" for an anonymous access type would not @Chg{Version=[2],New=[normally ],Old=[]}exist as a separate entity. Instead, the designated object of the allocator would be allocated, in the case of an access parameter, as a local aliased variable at the call site, and in the case of an access discriminant, contiguous with the object containing the discriminant. This is similar to the way storage for @nt{aggregate}s is typically managed. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[For other sorts of anonymous access types, this implementation is not possible in general, as the accessibility of the anonymous access type is that of its declaration, while the @nt{allocator} could be more nested. In this case, a "real" storage pool is required. Note, however, that this storage pool need not support (separate) deallocation, as it is not possible to instantiate Unchecked_Deallocation with an anonymous access type. (If deallocation is needed, the object should be allocated for a named access type and converted.) Thus, deallocation only need happen when the anonymous access type itself goes out of scope; this is similar to the case of an access-to-constant type.]} @end{ImplNote} @end{ImplAdvice} @begin{Notes} A user-defined storage pool type can be obtained by extending the Root_Storage_Pool type, and overriding the primitive subprograms Allocate, Deallocate, and Storage_Size. A user-defined storage pool can then be obtained by declaring an object of the type extension. The user can override Initialize and Finalize if there is any need for nontrivial initialization and finalization for a user-defined pool type. For example, Finalize might reclaim blocks of storage that are allocated separately from the pool object itself. @Leading@;The writer of the user-defined allocation and deallocation procedures, and users of @nt{allocator}s for the associated access type, are responsible for dealing with any interactions with tasking. In particular: @begin{itemize} If the @nt{allocator}s are used in different tasks, they require mutual exclusion. If they are used inside protected objects, they cannot block. If they are used by interrupt handlers (see @RefSec{Interrupt Support}), the mutual exclusion mechanism has to work properly in that context. @end{itemize} The primitives Allocate, Deallocate, and Storage_Size are declared as abstract (see @RefSecNum{Abstract Types and Subprograms}), and therefore they have to be overridden when a new (nonabstract) storage pool type is declared. @begin{Ramification} Note that the Storage_Pool attribute denotes an object, rather than a value, which is somewhat unusual for attributes. The calls to Allocate, Deallocate, and Storage_Size are dispatching calls @em this follows from the fact that the actual parameter for Pool is T'Storage_Pool, which is of type Root_Storage_Pool'Class. In many cases (including all cases in which Storage_Pool is not specified), the compiler can determine the tag statically. However, it is possible to construct cases where it cannot. All access types in the same derivation class share the same pool, whether implementation defined or user defined. This is necessary because we allow type conversions among them (even if they are pool-specific), and we want pool-specific access values to always designate an element of the right pool. @end{Ramification} @begin{ImplNote} If an access type has a standard storage pool, then the implementation doesn't actually have to follow the pool interface described here, since this would be semantically invisible. For example, the allocator could conceivably be implemented with inline code. @end{ImplNote} @end{Notes} @begin{Examples} @Leading@;To associate an access type with a storage pool object, the user first declares a pool object of some type derived from Root_Storage_Pool. Then, the user defines its Storage_Pool attribute, as follows: @begin{Example} Pool_Object : Some_Storage_Pool_Type; @key[type] T @key[is] @key[access] Designated; @key[for] T'Storage_Pool @key[use] Pool_Object; @end{Example} @begin{WideAbove} @Leading@;Another access type may be added to an existing storage pool, via: @end{WideAbove} @begin{Example} @key[for] T2'Storage_Pool @key[use] T'Storage_Pool; @end{Example} The semantics of this is implementation defined for a standard storage pool. @begin{Reason} For example, the implementation is allowed to choose a storage pool for T that takes advantage of the fact that T is of a certain size. If T2 is not of that size, then the above will probably not work. @end{Reason} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} As usual, a derivative of Root_Storage_Pool may define additional operations. For example, @Chg{Version=[3],New=[consider the],Old=[presuming that]} Mark_Release_Pool_Type @Chg{Version=[3],New=[defined in @RefSecNum{Storage Subpool Example}, that ],Old=[]}has two additional operations, Mark and Release, the following is a possible use: @begin{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0041],ARef=[AI95-00066-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} @key[type] Mark_Release_Pool_Type (Pool_Size : Storage_Elements.Storage_Count@Chg{Version=[3],New=[],Old=[; Block_Size : Storage_Elements.Storage_Count]}) @key[is] @key[new] @Chg{Version=[3],New=[Subpools.Root_Storage_Pool_With_Subpools],Old=[Root_Storage_Pool]} @key[with @Chg{New=[],Old=[limited ]}private];@Chg{Version=[3],New=[ -- @Examcom{As defined in package MR_Pool, see @RefSecNum{Storage Subpool Example}}],Old=[]} ... @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} @Chg{Version=[3],New=[Our_Pool],Old=[MR_Pool]} : Mark_Release_Pool_Type (Pool_Size => 2000@Chg{Version=[3],New=[],Old=[, Block_Size => 100]}); @Chg{Version=[3],New=[My_Mark : MR_Pool.Subpool_Handle; -- @Examcom{See @RefSecNum{Storage Subpool Example}}],Old=[]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} @key[type] Acc @key[is] @key[access] ...; @key[for] Acc'Storage_Pool @key[use] @Chg{Version=[3],New=[Our_Pool],Old=[MR_Pool]}; ... @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0111-3]} @Chg{Version=[3],New=[My_Mark := ],Old=[]}Mark(@Chg{Version=[3],New=[Our_Pool],Old=[MR_Pool]}); ... --@RI{ Allocate objects using @lquotes@;@key[new] @Chg{Version=[3],New=[(My_Mark) ],Old=[]}Designated(...)@rquotes@;.} Release(@Chg{Version=[3],New=[My_Mark],Old=[MR_Pool]}); --@RI{ @Chg{Version=[3],New=[Finalize objects and reclaim],Old=[Reclaim the]} storage.} @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} User-defined storage pools are new to Ada 95. @end{Extend83} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1],ARef=[AI05-0190-1]} Ada 83 @Chg{Version=[3],New=[originally introduced the],Old=[had a]} concept called a @lquotes@;collection,@rquotes@; which is similar to what we call a storage pool. All access types in the same derivation class @Chg{Version=[3],New=[share],Old=[shared]} the same collection. @Chg{Version=[3],New=[],Old=[In ]}Ada 95@Chg{Version=[3],New=[ introduces the storage pool, which is similar in that],Old=[,]} all access types in the same derivation class share the same storage pool, but other (unrelated) access types can also share the same storage pool, either by default, or as specified by the user. A collection @Chg{Version=[3],New=[is],Old=[was]} an amorphous @Chg{Version=[3],New=[grouping],Old=[collection]} of objects@Chg{Version=[3],New=[ (mainly used to describe finalization of access types)],Old=[]}; a storage pool is a more concrete concept @em hence the different name. RM83 states the erroneousness of reading or updating deallocated objects incorrectly by missing various cases. @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00435-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b<Amendment Correction:> Storage pools (and Storage_Size) are not defined for access-to-subprogram types. The original Ada 95 wording defined the attributes, but said nothing about their values. If a program uses attributes Storage_Pool or Storage_Size on an access-to-subprogram type, it will need to be corrected for Ada 2005. That's a good thing, as such a use is a bug @em the concepts never were defined for such types.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type Root_Storage_Pool, so that extensions of it can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that these are representation attributes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that an @nt{allocator} for a coextension nested inside an outer @nt{allocator} shares the pool with the outer @nt{allocator}.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0051-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added the missing definition of the storage pool of an @nt{allocator} for an anonymous access result type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified when an implementation is allowed to call Allocate and Deallocate, and the requirements on such calls.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[Added wording to support subpools and refer to the subpool example, see @RefSecNum{Storage Subpools}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0116-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to specify that the alignment for an @nt{allocator} with a class-wide designated type comes from the specific type that is allocated.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0193-1]} @ChgAdded{Version=[3],Text=[Added wording to allow larger alignments for calls to Allocate made by @nt{allocator}s, up to Max_Alignment_For_Allocation. This eases implementation in some cases.]} @end{DiffWord2005} @LabeledRevisedSubClause{Version=[3],New=[Storage Allocation Attributes], Old=[The Max_Size_In_Storage_Elements Attribute]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0193-1]} @redundant[The Max_Size_In_Storage_Elements @Chg{Version=[3],New=[and Max_Alignment_For_Allocation attributes may be],Old=[attribute is]} useful in writing user-defined pool types.] @end{Intro} @begin{StaticSem} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0193-1]} For @PrefixType{every subtype S}, the following @Chg{Version=[3],New=[attributes are],Old=[attribute is]} defined: @begin{Description} @ChgAttribute{Version=[3],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<S>, AttrName=<Max_Size_In_Storage_Elements>, ARef=[AI95-00256-01],ARef=[AI95-00416-01],ARef=[AI05-0193-1], Text=<Denotes the maximum value for Size_In_Storage_Elements that @Chg{Version=[2],New=[could],Old=[will]} be requested @Chg{Version=[2], New=[by the implementation ],Old=[]}via Allocate for an access type whose designated subtype is S.@Chg{Version=[2],New=[@Chg{Version=[3],New=[],Old=[ For a type with access discriminants, if the implementation allocates space for a coextension in the same pool as that of the object having the access discriminant, then this accounts for any calls on Allocate that could be performed to provide space for such coextensions.]}],Old=[]} The value of this attribute is of type @i{universal_integer}.>} @begin{Ramification} If S is an unconstrained array subtype, or an unconstrained subtype with discriminants, S'Max_Size_In_Storage_Elements might be very large. @end{Ramification} @ChgAttribute{Version=[3], Kind=[AddedNormal], ChginAnnex=[T], Leading=[F], Prefix=<S>, AttrName=<Max_Alignment_For_Allocation>, ARef=[AI05-0193-1], Text=<@Chg{Version=[3],New=[Denotes the maximum value for Alignment that could be requested by the implementation via Allocate for an access type whose designated subtype is S. The value of this attribute is of type @i{universal_integer}.],Old=[]}>} @EndPrefixType{} @end{Description} @end{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0193-1]} @ChgAdded{Version=[3],Text=[For a type with access discriminants, if the implementation allocates space for a coextension in the same pool as that of the object having the access discriminant, then these attributes account for any calls on Allocate that could be performed to provide space for such coextensions.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0193-1]} @ChgAdded{Version=[3],Text=[The values of these attributes should reflect only the calls that might be made to the pool specified for an access type with designated type S. Thus, if the coextensions would normally be allocated from a different pool than the one used for the main object (that is, the @ImplAdviceName of @RefSecNum{Storage Management} for determining the pool of an anonymous access discriminant is not followed), then these attributes should not reflect any calls on Allocate used to allocate the coextensions.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0193-1]} @ChgAdded{Version=[3],Text=[Coextensions of coextensions of this type (and so on) are included in the values of these attributes if they are allocated from the same pool.]} @end{Ramification} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Corrected the wording so that a fortune-telling compiler that can see the future execution of the program is not required.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0193-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}The Max_Alignment_For_Allocation attribute is new.]} @end{Extend2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{Unchecked Storage Deallocation} @begin{Intro} @redundant[@Defn{unchecked storage deallocation} @Defn2{Term=[storage deallocation], Sec=(unchecked)} @Defn{deallocation of storage} @Defn{reclamation of storage} @Defn{freeing storage} Unchecked storage deallocation of an object designated by a value of an access type is achieved by a call to an instance of the generic procedure Unchecked_Deallocation.] @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined generic library procedure exists: @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[generic] @key[type] Object(<>) @key[is] @key[limited] @key[private]; @key[type] Name @key[is] @key[access] Object; @SubChildUnit{Parent=[Ada],Child=[Unchecked_Deallocation]}@key[procedure] Ada.Unchecked_Deallocation(X : @key[in] @key[out] Name)@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic;],Old=[; @key[pragma] Convention(Intrinsic, Ada.Unchecked_Deallocation);]} @key[pragma] Preelaborate(Ada.Unchecked_Deallocation); @end{Example} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The @Chg{Version=[3],New=[aspect],Old=[@nt{pragma}]} Convention implies that the attribute Access is not allowed for instances of Unchecked_Deallocation. @end{Reason} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0157-1]} @ChgAdded{Version=[3],Text=[A call on an instance of Unchecked_Deallocation is illegal if the actual access type of the instance is a type for which the Storage_Size has been specified by a static expression with value zero or is defined by the language to be zero. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule applies also in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This rule is the same as the rule for @nt{allocator}s. We could have left the last sentence out, as a call to Unchecked_Deallocation cannot occur in a specification as it is a procedure call, but we left it for consistency and to avoid future maintenance hazards.]} @end{Discussion} @end{Legality} @begin{RunTime} @Leading@;Given an instance of Unchecked_Deallocation declared as follows: @begin{Example} @key[procedure] Free @key[is] @key[new] Ada.Unchecked_Deallocation( @RI[object_subtype_name], @RI[access_to_variable_subtype_name]); @end{Example} @begin{WideAbove} @Leading@Keepnext@;Procedure Free has the following effect: @end{WideAbove} @begin{Enumerate} After executing Free(X), the value of X is @key{null}. Free(X), when X is already equal to @key{null}, has no effect. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0107-1]} Free(X), when X is not equal to @key{null} first performs finalization@Chg{Version=[2],New=[ of the object designated by X (and any coextensions of the object @em see @RefSecNum{Operations of Access Types})], Old=[]}, as described in @Chg{Version=[2],New=[@RefSecNum{Completion and Finalization}], Old=[@RefSecNum{Assignment and Finalization}]}. It then deallocates the storage occupied by the object designated by X@Chg{Version=[2],New=[ (and any coextensions)],Old=[]}. If the storage pool is a user-defined object, then the storage is deallocated by calling Deallocate@Chg{Version=[3],New=[ as described in @RefSecNum{Storage Management}],Old=[, passing @i[access_to_@!variable_@!subtype_name]'Storage_Pool as the Pool parameter. Storage_Address is the value returned in the Storage_Address parameter of the corresponding Allocate call. Size_In_@!Storage_@!Elements and Alignment are the same values passed to the corresponding Allocate call]}. There is one exception: if the object being freed contains tasks, the object might not be deallocated. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0107-1]} Free calls only the specified Deallocate procedure to do deallocation.@Chg{Version=[3],New=[],Old=[ For any given object deallocation, the number of calls to Free (usually one) will be equal to the number of Allocate calls it took to allocate the object. We do not define the relative order of multiple calls used to deallocate the same object @em that is, if the @nt{allocator} allocated two pieces @i{x} and @i{y}, then Free might deallocate @i{x} and then @i{y}, or it might deallocate @i{y} and then @i{x}.]} @end{Ramification} @end{Enumerate} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00416-01]} @IndexSee{Term=[freed],See=(nonexistent)} @Defn{nonexistent} @PDefn2{Term=[exist],Sec=[cease to]} @PDefn2{Term=[cease to exist],Sec=[object]} After Free(X), the object designated by X, and any subcomponents @Chg{Version=[2],New=[(and coextensions) ],Old=[]}thereof, no longer exist; their storage can be reused for other purposes. @end{RunTime} @begin{Bounded} @Leading@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to free a discriminated, unterminated task object. The possible consequences are: @begin{Reason} This is an error because the task might refer to its discriminants, and the discriminants might be deallocated by freeing the task object. @end{Reason} @begin{Itemize} No exception is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Program_Error or Tasking_Error is raised at the point of the deallocation. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Program_Error or Tasking_Error is raised in the task the next time it references any of the discriminants. @begin{ImplNote} This last case presumes an implementation where the task references its discriminants indirectly, and the pointer is nulled out when the task object is deallocated. @end{ImplNote} @end{Itemize} In the first two cases, the storage for the discriminants (and for any enclosing object if it is designated by an access discriminant of the task) is not reclaimed prior to task termination. @begin{Ramification} The storage might never be reclaimed. @end{Ramification} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0033-1],ARef=[AI05-0262-1]} @Defn{nonexistent}@PDefn2{Term=(erroneous execution),Sec=(cause)} Evaluating a name that denotes a nonexistent object@Chg{Version=[3], New=[, or a protected subprogram or subprogram renaming whose associated object (if any) is nonexistent, ],Old=[]}is erroneous. The execution of a call to an instance of Unchecked_Deallocation is erroneous if the object was created other than by an @nt<allocator> for an access type whose pool is Name'Storage_Pool. @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The part about a protected subprogram is intended to cover the case of an access-to-protected-subprogram where the associated object has been deallocated. The part about a subprogram renaming is intended to cover the case of a renaming of a prefixed view where the prefix object has been deallocated, or the case of a renaming of an entry or protected subprogram where the associated task or protected object has been deallocated.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0157-1]} @ChgAdded{Version=[3],Text=[This text does not cover the case of a name that contains a null access value, as @key[null] does not denote an object (rather than denoting a nonexistent object).]} @end{Ramification} @end{Erron} @begin{ImplAdvice} For a standard storage pool, Free should actually reclaim the storage. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For a standard storage pool, an instance of Unchecked_Deallocation should actually reclaim the storage.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This is not a testable property, since we do not @Chg{Version=[2],New=[know ],Old=[]}how much storage is used by a given pool element, nor whether fragmentation can occur. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0157-1]} @ChgAdded{Version=[3],Text=[A call on an instance of Unchecked_Deallocation with a nonnull access value should raise Program_Error if the actual access type of the instance is a type for which the Storage_Size has been specified to be zero or is defined by the language to be zero.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[A call on an instance of Unchecked_Deallocation with a nonnull access value should raise Program_Error if the actual access type of the instance is a type for which the Storage_Size has been specified to be zero or is defined by the language to be zero.]}]} @begin{Discussion} @ChgAdded{Version=[3],Text=[If the call is not illegal (as in a generic body), we recommend that it raise Program_Error. Since the execution of this call is erroneous (any allocator from the pool will have raised Storage_Error, so the nonnull access value must have been allocated from a different pool or be a stack-allocated object), we can't require any behavior @em anything at all would be a legitimate implementation.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} The rules here that refer to Free apply to any instance of Unchecked_Deallocation. Unchecked_Deallocation cannot be instantiated for an access-to-constant type. This is implied by the rules of @RefSecNum{Formal Access Types}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00416-01]} @ChgAdded{Version=[2],Text=[The rules for coextensions are clarified (mainly by adding that term). In theory, this reflects no change from Ada 95 (coextensions existed in Ada 95, they just didn't have a name).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a rule that using an access-to-protected-subprogram is erroneous if the associated object no longer exists. It is hard to imagine an alternative meaning here, and this has no effect on correct programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0107-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Moved the requirements on an implementation-generated call to Deallocate to @RefSecNum{Storage Management}, in order to put all of the rules associated with implementation-generated calls to Allocate and Deallocate together.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0157-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording so that calling an instance of Unchecked_Deallocation is treated similarly to @nt{allocator}s for access types where @nt{allocator}s would be banned.]} @end{DiffWord2005} @LabeledRevisedSubClause{Version=[3],New=[Default Storage Pools], Old=[Pragma Controlled]} @begin{Intro} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@Redundant[Pragma Controlled is used to prevent any automatic reclamation of storage (garbage collection) for the objects created by @nt<allocator>s of a given access type.]]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} The form of a @nt{pragma} @Chg{Version=[3],New=[Default_Storage_Pool],Old=[Controlled]} is as follows: @end{SyntaxText} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @AddedPragmaSyn<Version=[3],@Chg{Version=[3], New=[@key{pragma} @prag<Default_Storage_Pool> (@Syn2{storage_pool_indicator});],Old=[]}> @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@Chg{Version=[3],New=[], Old=[@key{pragma} @prag(Controlled)(@SynI{first_subtype_}@Syn2{local_name});]}> @begin{Discussion} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[Not to be confused with type Finalization.Controlled.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @AddedSyn{Version=[3],lhs=<@Chg{Version=[3],New=<storage_pool_indicator>,Old=<>}>, rhs="@Chg{Version=[3],New=<@SynI{storage_pool_}@Syn2{name} | @key[null]>,Old=<>}"} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Default_Storage_Pool is allowed immediately within the visible part of a @nt{package_specification}, immediately within a @nt{declarative_part}, or as a configuration pragma.]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[The @SynI{storage_pool_}@nt{name} is expected to be of type Root_Storage_Pool'Class.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The @SynI{storage_pool_}@nt{name} shall denote a variable.], Old=[The @SynI{first_subtype_}@nt<local_name> of a @nt{pragma} Controlled shall denote a nonderived access subtype.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[If the @nt{pragma} is used as a configuration pragma, the @nt{storage_pool_indicator} shall be @key[null], and it defines the @i<default pool>@Defn{default pool}@Defn2{Term=[storage pool],Sec=[default]}@Defn2{Term=[pool],Sec=[default]} to be @b<null> within all applicable compilation units (see @RefSecNum{Pragmas and Program Units}), except within the immediate scope of another @nt{pragma} Default_Storage_Pool. Otherwise, @Redundant[the pragma occurs immediately within a sequence of declarations, and] it defines the default pool within the immediate scope of the pragma to be either @key[null] or the pool denoted by the @SynI{storage_pool_}@nt{name}, except within the immediate scope of a later pragma Default_Storage_Pool. @Redundant[Thus, an inner pragma overrides an outer one.]]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Default_Storage_Pool shall not be used as a configuration pragma that applies to a compilation unit that is within the immediate scope of another @nt{pragma} Default_Storage_Pool.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This is to prevent confusion in cases like this:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] Parent @key[is] pragma Default_Storage_Pool(...); ... @key[end] Parent;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[pragma] Default_Storage_Pool(...); --@examcom{ Illegal!} @key[package] Parent.Child @key[is] ... @key[end] Parent.Child;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[where the Default_Storage_Pool on Parent.Child would not (if it were legal) override the one in Parent.]} @end{Reason} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The language-defined aspect Default_Storage_Pool may be specified for a generic instance; it defines the default pool for access types within an instance.@AspectDefn{Default_Storage_Pool} The expected type for the Default_Storage_Pool aspect is Root_Storage_Pool'Class. The @nt{aspect_definition} must be a name that denotes a variable. This aspect overrides any Default_Storage_Pool pragma that might apply to the generic unit; if the aspect is not specified, the default pool of the instance is that defined for the generic unit], Old=[@PDefn2{Term=[representation pragma], Sec=(Controlled)} @PDefn2{Term=[pragma, representation], Sec=(Controlled)} A @nt{pragma} Controlled is a representation pragma @PDefn2{Term=[aspect of representation], Sec=(controlled)} @Defn2{Term=[controlled], Sec=(aspect of representation)} that specifies the @i{controlled} aspect of representation]}. @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Default_Storage_Pool], Text=[@ChgAdded{Version=[3],Text=[Default storage pool for a generic instance.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{Conditional leading} @Chg{Version=[3],New=[For nonderived access types declared in places where the default pool is defined by the pragma or aspect, their Storage_Pool or Storage_Size attribute is determined as follows, unless Storage_Pool or Storage_Size is specified for the type:], Old=[@Defn{garbage collection} @i{Garbage collection} is a process that automatically reclaims storage, or moves objects to a different address, while the objects still exist.]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[If the default pool is @key[null], the Storage_Size attribute is defined by the language to be zero. @Redundant[Therefore, an @nt{allocator} for such a type is illegal.]]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[If the default pool is nonnull, the Storage_Pool attribute is that pool.]} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Redundant[Otherwise, there is no default pool; the standard storage pool is used for the type as described in @RefSecNum{Storage Management}.]]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[Default_Storage_Pool is the only way to specify the storage pool for an anonymous access type], Old=[Storage reclamation upon leaving a master is not considered garbage collection]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} Note that @Chg{Version=[3],New=[coextensions should be allocated in the same pool (or on the stack) as the outer object (see @RefSecNum{Storage Management}); the Storage_Pool of the access discriminant (and hence the Default_Storage_Pool) is supposed to be ignored for coextensions. This matches the required finalization point for coextensions], Old=[garbage collection includes compaction of a pool (@lquotes@;moved to a different Address@rquotes@;), even if storage reclamation is not done]}. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[The default storage pool for an allocator that occurs within an instance of a generic is defined by the Default_Storage_Pool aspect of the instantiation (if specified), or by the Default_Storage_Pool pragma that applied to the generic; the Default_Storage_Pool pragma that applies to the instantiation is irrelevant.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[It is possible to specify the Default_Storage_Pool aspect for an instantiation such that allocations will fail. For example, the generic unit might be expecting a pool that supports certain sizes and alignments, and the one on the instance might be more restrictive. It is the programmer's responsibility to get this right.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[The semantics of the Default_Storage_Pool aspect are similar to passing a pool object as a generic formal, and putting pragma Default_Storage_Pool at the top of the generic's visible part, specifying that formal.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[Programs that will be damaged by automatic storage reclamation are just as likely to be damaged by having objects moved to different locations in memory. A @nt{pragma} Controlled should turn off both flavors of garbage collection.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[If garbage collection reclaims the storage of a controlled object, it should first finalize it. Finalization is not done when moving an object; any self-relative pointers will have to be updated by the garbage collector. If an implementation provides garbage collection for a storage pool containing controlled objects (see @RefSecNum{Assignment and Finalization}), then it should provide a means for deferring garbage collection of those controlled objects.]} @end{ImplNote} @begin{Reason} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[This allows the manager of a resource released by a Finalize operation to defer garbage collection during its critical regions; it is up to the author of the Finalize operation to do so. Garbage collection, at least in some systems, can happen asynchronously with respect to normal user code. Note that it is not enough to defer garbage collection during Initialize, Adjust, and Finalize, because the resource in question might be used in other situations as well. For example:]} @begin{Example} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@key[with] Ada.Finalization; @key[package] P @key[is]]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[ @key[type] My_Controlled @key[is] @key[new] Ada.Finalization.Limited_Controlled @key[with] @key[private]; @key[procedure] Finalize(Object : @key[in] @key[out] My_Controlled); @key[type] My_Controlled_Access @key[is] @key[access] My_Controlled;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[ @key[procedure] Non_Reentrant;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@key[private] ... @key[end] P;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@key[package] @key[body] P @key[is] X : Integer := 0; A : @key[array](Integer @key[range] 1..10) @key[of] Integer;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[ @key[procedure] Non_Reentrant @key[is] @key[begin] X := X + 1; --@Examcom{ If the system decides to do a garbage collection here,} --@Examcom{ then we're in trouble, because it will call Finalize on} --@Examcom{ the collected objects; we essentially have two threads} --@Examcom{ of control erroneously accessing shared variables.} --@Examcom{ The garbage collector behaves like a separate thread} --@Examcom{ of control, even though the user hasn't declared} --@Examcom{ any tasks.} A(X) := ...; @key[end] Non_Reentrant;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[ @key[procedure] Finalize(Object : @key[in] @key[out] My_Controlled) @key[is] @key[begin] Non_Reentrant; @key[end] Finalize; @key[end] P;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@key[with] P; @key[use] P; @key[procedure] Main @key[is] @key[begin] ... @key[new] My_Controlled ... --@Examcom{ allocate some objects} ... @Examcom{ forget the pointers to some of them, so they become garbage} Non_Reentrant; @key[end] Main;]} @end{Example} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[It is the user's responsibility to protect against this sort of thing, and the implementation's responsibility to provide the necessary operations.]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[We do not give these operations names, nor explain their exact semantics, because different implementations of garbage collection might have different needs, and because garbage collection is not supported by most Ada implementations, so portability is not important here. Another reason not to turn off garbage collection during each entire Finalize operation is that it would create a serial bottleneck; it might be only part of the Finalize operation that conflicts with some other resource. It is the intention that the mechanisms provided be finer-grained than pragma Controlled.]} @end{Reason} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[If a @nt{pragma} Controlled is specified for an access type with a standard storage pool, then garbage collection is not performed for objects in that pool.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[If Controlled is not specified, the implementation may, but need not, perform garbage collection. If Storage_Pool is specified, then a @nt{pragma} Controlled for that type is ignored.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[Controlled means that implementation-provided garbage collection is turned off; if the Storage_Pool is specified, the pool controls whether garbage collection is done.]} @end{Reason} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0190-1],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[An object created by an @nt{allocator} that is passed as the actual parameter to an access parameter may be allocated on the stack, and automatically reclaimed, regardless of the default pool.], Old=[An implementation need not support garbage collection, in which case, a pragma Controlled has no effect]}. @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[This matches the required finalization point for such an allocated object.]} @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[Default_Storage_Pool may be used with restrictions No_Coextensions and No_Access_Parameter_Allocators (see @RefSecNum{High Integrity Restrictions}) to ensure that all @nt{allocator}s use the default pool.]} @end{Notes} @begin{DiffWord83} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[Ada 83 used the term @lquotes@;automatic storage reclamation@rquotes@; to refer to what is known traditionally as @lquotes@;garbage collection@rquotes@;. Because of the existence of storage pools (see @RefSecNum{Storage Management}), we need to distinguish this from the storage reclamation that might happen upon leaving a master. Therefore, we now use the term @lquotes@;garbage collection@rquotes@; in its normal computer-science sense. This has the additional advantage of making our terminology more accessible to people outside the Ada world.]} @end{DiffWord83} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 95}Pragma Controlled has been dropped from Ada, as it has no effect in any known Ada implementations and it seems to promise capabilities not expected in Ada implementations. This is usually not an incompatibility, as the pragma merely becomes unrecognized (with a warning) and can be implemented as an implementation-defined pragma if desired. However, it is incompatible if it is (now) implemented as an implementation-defined pragma, someone used this pragma in a unit, and they also used restriction No_Implementation_Pragmas on that unit. In that case, the pragma would now violate the restriction; but use of this pragma (which does nothing) should be very rare, so this is not a significant issue.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}The pragma Default_Storage_Pool is new.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The entire discussion of garbage collection (and especially that of controlled objects) is deleted. Ada 2012 provides subpools (see @RefSecNum{Storage Subpools}) for storage management of objects, including controlled objects, a mechanism which is much more predictable than garbage collection. Note that no version of Ada allows early finalization of controlled objects (other than via the use of Unchecked_Deallocation or Unchecked_Deallocate_Subpool), so that garbage collection of such objects would be ineffective in the standard mode anyway.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Storage Subpools]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[This subclause defines a package to support the partitioning of a storage pool into subpools. A subpool may be specified as the default to be used for allocation from the associated storage pool, or a particular subpool may be specified as part of an @nt{allocator} (see @RefSecNum{Allocators}).]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[System.Storage_Pools],Child=[Subpools]}@key[package] System.Storage_Pools.Subpools @key[is] @key[pragma] Preelaborate (Subpools);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Root_Storage_Pool_With_Subpools} @key[is] @key[abstract new] Root_Storage_Pool @key[with private];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Root_Subpool} @key[is abstract tagged limited private];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Subpool_Handle} @key[is access all] Root_Subpool'Class; @key[for] Subpool_Handle'Storage_Size @key[use] 0;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Create_Subpool} (Pool : @key[in out] Root_Storage_Pool_With_Subpools) @key[return not null] Subpool_Handle @key[is abstract];]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0252-1]} @ChgAdded{Version=[3],Text=[ -- @Examcom{The following operations are intended for pool implementers:}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Pool_of_Subpool} (Subpool : @key[not null] Subpool_Handle) @key[return access] Root_Storage_Pool_With_Subpools'Class;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Set_Pool_of_Subpool} ( Subpool : @key[in not null] Subpool_Handle; To : @key[in out] Root_Storage_Pool_With_Subpools'Class);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Allocate_From_Subpool} ( Pool : @key[in out] Root_Storage_Pool_With_Subpools; Storage_Address : @key[out] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count; Subpool : @key[in not null] Subpool_Handle) @key[is abstract] @key[with] Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Deallocate_Subpool} ( Pool : @key[in out] Root_Storage_Pool_With_Subpools; Subpool : @key[in out] Subpool_Handle) @key[is abstract] @key[with] Pre'Class => Pool_of_Subpool(Subpool) = Pool'Access;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Default_Subpool_for_Pool} ( Pool : @key[in out] Root_Storage_Pool_With_Subpools) @key[return not null] Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[procedure] @AdaSubDefn{Allocate} ( Pool : @key[in out] Root_Storage_Pool_With_Subpools; Storage_Address : @key[out] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[procedure] @AdaSubDefn{Deallocate} ( Pool : @key[in out] Root_Storage_Pool_With_Subpools; Storage_Address : @key[in] Address; Size_In_Storage_Elements : @key[in] Storage_Elements.Storage_Count; Alignment : @key[in] Storage_Elements.Storage_Count) @key[is null];]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] @AdaSubDefn{Storage_Size} (Pool : Root_Storage_Pool_With_Subpools) @key[return] Storage_Elements.Storage_Count @key[is] (Storage_Elements.Storage_Count'Last);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[private ... -- @Examcom{not specified by the language} end System.Storage_Pools.Subpools;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[@Defn{subpool}@Defn2{Term=[pool],Sec={subpool}} @Defn{subpool handle}@Defn2{Term=[handle],Sec=[subpool]} @Defn{storage pool that supports subpools}A @i<subpool> is a separately reclaimable portion of a storage pool, identified by an object of type Subpool_Handle (a @i<subpool handle>). A subpool handle also identifies the enclosing storage pool, a @i<storage pool that supports subpools>, which is a storage pool whose type is descended from Root_Storage_Pool_With_Subpools. A subpool is created by calling Create_Subpool or a similar constructor; the constructor returns the subpool handle.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[A @i<subpool object> is an object of a type descended from Root_Subpool. @Redundant[Typically, subpool objects are managed by the containing storage pool; only the handles need be exposed to clients of the storage pool. Subpool objects are designated by subpool handles, and are the run-time representation of a subpool.]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We know that subpool handles designate subpool objects because the declaration of Subpool_Handle says so.]} @end{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[Each subpool @i<belongs>@Defn2{Term=[belongs],Sec=[subpool to a pool]} to a single storage pool @Redundant[(which will always be a pool that supports subpools)]. An access to the pool that a subpool belongs to can be obtained by calling Pool_of_Subpool with the subpool handle. Set_Pool_of_Subpool causes the subpool of the subpool handle to belong to the given pool@Redundant[; this is intended to be called from subpool constructors like Create_Subpool.] Set_Pool_of_Subpool propagates Program_Error if the subpool already belongs to a pool.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Pool_of_Subpool and Set_Pool_of_Subpool are provided by the Ada implementation and typically will not be overridden by the pool implementer.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[When an @nt{allocator} for a type whose storage pool supports subpools is evaluated, a call is made on Allocate_From_Subpool passing in a Subpool_Handle, in addition to the parameters as defined for calls on Allocate (see @RefSecNum{Storage Management}). The subpool designated by the @Syni{subpool_handle_}@nt{name} is used, if specified in an @nt{allocator}. Otherwise, Default_Subpool_for_Pool of the Pool is used to provide a subpool handle. All requirements on the Allocate procedure also apply to Allocate_from_Subpool.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Deallocate_Subpool is expected to do whatever is needed to deallocate all of the objects contained in the subpool; it is called from Unchecked_Deallocate_Subpool (see @RefSecNum{Subpool Reclamation}).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Typically, the pool implementer will not override Allocate. In the canonical definition of the language, it will never be called for a pool that supports subpools (there is an @ImplPermName below that allows it to be called in certain rare cases).]} @end{Discussion} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[If a storage pool that supports subpools is specified as the Storage_Pool for an access type, the access type is called a @i<subpool access type>.@Defn{subpool access type}@Defn2{Term=[access type],Sec=[subpool]} A subpool access type shall be a pool-specific access type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3],ARef=[AI05-0252-1]} @ChgAdded{Version=[3],Text=[The accessibility level of a subpool access type shall not be statically deeper than that of the storage pool object. If the specified storage pool object is a storage pool that supports subpools, then the @nt{name} that denotes the object shall not denote part of a formal parameter, nor shall it denote part of a dereference of a value of a non-library-level general access type. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @end{Legality} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3],ARef=[AI05-0252-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[When an access type with a specified storage pool is frozen (see @RefSecNum{Freezing Rules}), if the tag of the storage pool object identifies a storage pool that supports subpools, the following checks are made:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the @nt{name} used to specify the storage pool object does not denote part of a formal parameter nor part of a dereference of a value of a non-library-level general access type; and@IndexCheck{Accessibility_Check}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[the accessibility level of the access type is not deeper than that of the storage pool object.@IndexCheck{Accessibility_Check}]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0252-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Program_Error is raised if either of these checks fail.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This check (and its static counterpart) ensures that the type of the allocated objects exists at least as long as the storage pool object, so that the subpools are finalized (which finalizes any remaining allocated objects) before the type of the objects ceases to exist. The access type itself (and the associated collection) will cease to exist before the storage pool ceases to exist.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We also disallow the use of formal parameters and dereferences of non-library-level general access types when specifying a storage pool object if it supports subpools, because the "apparent" accessibility level is potentially deeper than that of the underlying object. Neither of these cases is very likely to occur in practice.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[A call to Subpools.Allocate(P, Addr, Size, Align) does the following:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Allocate_From_Subpool (Root_Storage_Pool_With_Subpools'Class(P), Addr, Size, Align, Subpool => Default_Subpool_for_Pool (Root_Storage_Pool_With_Subpools'Class(P)));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[An @nt{allocator} that allocates in a subpool raises Program_Error if the allocated object has task parts.@IndexCheck{Allocation_Check}@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is to ease implementation. We envision relaxing this restriction in a future version of Ada, once implementation experience has been gained. At this time, we are unable to come up with a set of rules for task termination that is both useful, and surely feasible to implement.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[Unless overridden, Default_Subpool_for_Pool propagates Program_Error.]} @end{Runtime} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[When an allocator for a type whose storage pool is of type Root_Storage_Pool'Class is evaluated, but supports subpools, the implementation may call Allocate rather than Allocate_From_Subpool. @Redundant[This will have the same effect, so long as Allocate has not been overridden.]]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This ensures either of two implementation models are possible for an @nt{allocator} with no @nt{subpool_specification}. Note that the "supports subpools" property is not known at compile time for a pool of the class-wide type.]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The implementation can dispatch to Storage_Pools.Allocate. If the pool supports subpools, this will call Allocate_From_Subpool with the default subpool so long as Allocate has not been overridden.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The implementation can declare Allocate_From_Subpool as a primitive of Root_Storage_Pool in the private part of Storage_Pools. This means that the Allocate_From_Subpool for Root_Storage_Pool_With_Subpools overrides that private one. The implementation can thus call the private one, which will call Allocate for non-subpool-supporting pools. The effect of this implementation does not change if Allocate is overridden for a pool that supports subpools.]} @end{Itemize} @end{Reason} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[A user-defined storage pool type that supports subpools can be implemented by extending the Root_Storage_Pool_With_Subpools type, and overriding the primitive subprograms Create_Subpool, Allocate_From_Subpool, and Deallocate_Subpool. Create_Subpool should call Set_Pool_Of_Subpool before returning the subpool handle. To make use of such a pool, a user would declare an object of the type extension, use it to define the Storage_Pool attribute of one or more access types, and then call Create_Subpool to obtain subpool handles associated with the pool.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[A user-defined storage pool type that supports subpools may define additional subpool constructors similar to Create_Subpool (these typically will have additional parameters).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[The pool implementor should override Default_Subpool_For_Pool if the pool is to support a default subpool for the pool. The implementor can override Deallocate if individual object reclamation is to be supported, and can override Storage_Size if there is some limit on the total size of the storage pool. The implementor can override Initialize and Finalize if there is any need for nontrivial initialization and finalization for the pool as a whole. For example, Finalize might reclaim blocks of storage that are allocated over and above the space occupied by the pool object itself. The pool implementor may extend the Root_Subpool type as necessary to carry additional information with each subpool provided by Create_Subpool.]} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3],ARef=[AI05-0252-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Subpools and the package System.Storage_Pools.Subpools are new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[Subpool Reclamation]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[A subpool may be explicitly deallocated using Unchecked_Deallocate_Subpool.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following language-defined library procedure exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System.Storage_Pools.Subpools; @SubChildUnit{Parent=[Ada],Child=[Ada.Unchecked_Deallocate_Subpool]}@key[procedure] Ada.Unchecked_Deallocate_Subpool (Subpool : @key[in out] System.Storage_Pools.Subpools.Subpool_Handle);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[If Subpool is @key[null], a call on Unchecked_Deallocate_Subpool has no effect. Otherwise, the subpool is finalized, and Subpool is set to @key[null].]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[Finalization of a subpool has the following effects:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The subpool no longer belongs to any pool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Any of the objects allocated from the subpool that still exist are finalized in an arbitrary order;@PDefn2{Term=[arbitrary order],Sec=[allowed]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following @Redundant[dispatching] call is then made:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[ Deallocate_Subpool(Pool_of_Subpool(Subpool).@key[all], Subpool);]} @end{Example} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[Finalization of a Root_Storage_Pool_With_Subpools object finalizes all subpools that belong to that pool that have not yet been finalized.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There is no need to call Unchecked_Deallocation on an object allocated in a subpool. Such objects are deallocated all at once, when Unchecked_Deallocate_Subpool is called.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If Unchecked_Deallocation is called, the object is finalized, and then Deallocate is called on the Pool, which typically will do nothing. If it wants to free memory, it will need some way to get from the address of the object to the subpool.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There is no Deallocate_From_Subpool. There is no efficient way for the implementation to determine the subpool for an arbitrary object, and if the pool implementer can determinate that, they can use that as part of the implementation of Deallocate.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If Unchecked_Deallocation is not called (the usual case), the object will be finalized when Unchecked_Deallocate_Subpool is called.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If that's never called, then the object will be finalized when the Pool_With_Subpools is finalized (by permission @em it might happen when the collection of the access type is finalized).]} @end{Discussion} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Unchecked_Deallocate_Subpool is new.]} @end{Extend2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledAddedSubClause{Version=[3],Name=[Storage Subpool Example]} @begin{Examples} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following example is a simple but complete implementation of the classic Mark/Release pool using subpools:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System.Storage_Pools.Subpools; @key[with] System.Storage_Elements; @key[with] Ada.Unchecked_Deallocate_Subpool; @key[package] MR_Pool @key[is]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[use] System.Storage_Pools; -- @Examcom{For uses of Subpools.} @key[use] System.Storage_Elements; -- @Examcom{For uses of Storage_Count and Storage_Array.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Mark and Release work in a stack fashion, and allocations are not allowed} -- @Examcom{from a subpool other than the one at the top of the stack. This is also} -- @Examcom{the default pool.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[subtype] Subpool_Handle @key[is] Subpools.Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] Mark_Release_Pool_Type (Pool_Size : Storage_Count) @key[is new] Subpools.Root_Storage_Pool_With_Subpools @key[with private];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] Mark (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] Release (Subpool : @key[in out] Subpool_Handle) @key[renames] Ada.Unchecked_Deallocate_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[private]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] MR_Subpool @key[is new] Subpools.Root_Subpool @key[with record] Start : Storage_Count; @key[end record]; @key[subtype] Subpool_Indexes @key[is] Positive @key[range] 1 .. 10; @key[type] Subpool_Array @key[is array] (Subpool_Indexes) @key[of aliased] MR_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[type] Mark_Release_Pool_Type (Pool_Size : Storage_Count) @key[is new] Subpools.Root_Storage_Pool_With_Subpools @key[with record] Storage : Storage_Array (0 .. Pool_Size-1); Next_Allocation : Storage_Count := 0; Markers : Subpool_Array; Current_Pool : Subpool_Indexes := 1; @key[end record];]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] Create_Subpool (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] Mark (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle @key[renames] Create_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[procedure] Allocate_From_Subpool ( Pool : @key[in out] Mark_Release_Pool_Type; Storage_Address : @key[out] System.Address; Size_In_Storage_Elements : @key[in] Storage_Count; Alignment : @key[in] Storage_Count; Subpool : @key[not null] Subpool_Handle);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[procedure] Deallocate_Subpool ( Pool : @key[in out] Mark_Release_Pool_Type; Subpool : @key[in out] Subpool_Handle);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] Default_Subpool_for_Pool (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[procedure] Initialize (Pool : @key[in out] Mark_Release_Pool_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{We don't need Finalize.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] MR_Pool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[package body] MR_Pool @key[is]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[use type] Subpool_Handle;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] Initialize (Pool : @key[in out] Mark_Release_Pool_Type) @key[is] -- @Examcom{Initialize the first default subpool.} @key[begin] Pool.Markers(1).Start := 1; Subpools.Set_Pool_of_Subpool (Pool.Markers(1)'Unchecked_Access, Pool); @key[end] Initialize;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] Create_Subpool (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle @key[is] -- @Examcom{Mark the current allocation location.} @key[begin] @key[if] Pool.Current_Pool = Subpool_Indexes'Last @key[then] @key[raise] Storage_Error; -- @Examcom{No more subpools.} @key[end if]; Pool.Current_Pool := Pool.Current_Pool + 1; -- @Examcom{Move to the next subpool}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[return] Result : @key[constant not null] Subpool_Handle := Pool.Markers(Pool.Current_Pool)'Unchecked_Access @key[do] Pool.Markers(Pool.Current_Pool).Start := Pool.Next_Allocation; Subpools.Set_Pool_of_Subpool (Result, Pool); @key[end return]; @key[end] Create_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] Deallocate_Subpool ( Pool : @key[in out] Mark_Release_Pool_Type; Subpool : @key[in out] Subpool_Handle) @key[is] @key[begin] @key[if] Subpool /= Pool.Markers(Pool.Current_Pool)'Unchecked_Access @key[then] @key[raise] Program_Error; -- @Examcom{Only the last marked subpool can be released.} @key[end if]; @key[if] Pool.Current_Pool /= 1 @key[then] Pool.Next_Allocation := Pool.Markers(Pool.Current_Pool).Start; Pool.Current_Pool := Pool.Current_Pool - 1; -- @Examcom{Move to the previous subpool} @key[else] -- @Examcom{Reinitialize the default subpool:} Pool.Next_Allocation := 1; Subpools.Set_Pool_of_Subpool (Pool.Markers(1)'Unchecked_Access, Pool); @key[end if]; @key[end] Deallocate_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[ @key[function] Default_Subpool_for_Pool (Pool : @key[in out] Mark_Release_Pool_Type) @key[return not null] Subpool_Handle @key[is] @key[begin] @key[return] Pool.Markers(Pool.Current_Pool)'Unchecked_Access; @key[end] Default_Subpool_for_Pool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] Allocate_From_Subpool ( Pool : @key[in out] Mark_Release_Pool_Type; Storage_Address : @key[out] System.Address; Size_In_Storage_Elements : @key[in] Storage_Count; Alignment : @key[in] Storage_Count; Subpool : @key[not null] Subpool_Handle) @key[is] @key[begin] @key[if] Subpool /= Pool.Markers(Pool.Current_Pool)'Unchecked_Access @key[then] @key[raise] Program_Error; -- @Examcom{Only the last marked subpool can be used for allocations.} @key[end if];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Correct the alignment if necessary:} Pool.Next_Allocation := Pool.Next_Allocation + ((-Pool.Next_Allocation) @key[mod] Alignment); @key[if] Pool.Next_Allocation + Size_In_Storage_Elements > Pool.Pool_Size @key[then] @key[raise] Storage_Error; -- @Examcom{Out of space.} @key[end if]; Storage_Address := Pool.Storage (Pool.Next_Allocation)'Address; Pool.Next_Allocation := Pool.Next_Allocation + Size_In_Storage_Elements; @key[end] Allocate_From_Subpool;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] MR_Pool;]} @end{Example} @end{Examples} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0111-3]} @ChgAdded{Version=[3],Text=[This example of subpools is new.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[3],New=[Pragma Restrictions and Pragma Profile],Old=[Pragma Restrictions]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0246-1]} @redundant[A @nt{pragma} Restrictions expresses the user's intent to abide by certain restrictions.@Chg{Version=[3],New=[ A @nt{pragma} Profile expresses the user's intent to abide by a set of Restrictions or other specified run-time policies.],Old=[]} @Chg{Version=[3],New=[These],Old=[This]} may facilitate the construction of simpler run-time environments.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@keepnext@;The form of a @nt{pragma} Restrictions is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Restrictions)(@Syn2{restriction}{, @Syn2{restriction}});' @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00381-01]} @Syn{lhs=(restriction), rhs="@SynI{restriction_}@Syn2{identifier} | @SynI{restriction_parameter_}@Syn2{identifier} => @Chg{Version=[2],New=[@Syn2{restriction_parameter_argument}],Old=[@Syn2{expression}]}"} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00381-01]} @AddedSyn{Version=[2],lhs=<@Chg{Version=[2],New=<restriction_parameter_argument>,Old=<>}>, rhs="@Chg{Version=[2],New=<@Syn2{name} | @Syn2{expression}>,Old=<>}"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(restriction parameter expression)} Unless otherwise specified for a particular restriction, the @nt{expression} is expected to be of any integer type. @end{Resolution} @begin{Legality} Unless otherwise specified for a particular restriction, the @nt{expression} shall be static, and its value shall be nonnegative. @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0269-1]} @ChgDeleted{Version=[3],Text=[The set of @Chg{Version=[2],New=[restrictions],Old=[@ntf{restrictions}]} is implementation defined.]} @ChgImplDef{Version=[3],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[3],Text=[The set of @Chg{Version=[2],New=[restrictions],Old=[@ntf{restrictions}]} allowed in a @nt{pragma} Restrictions.]}]} @end{StaticSem} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 7 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{LinkTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0013-1]} @ChgNote{Use ChgAdded to get conditional Leading}@ChgAdded{Version=[3], Type=[Leading],Text=[]}@PDefn2{Term=[configuration pragma], Sec=(Restrictions)} @PDefn2{Term=[pragma, configuration], Sec=(Restrictions)} A @nt{pragma} Restrictions is a configuration pragma@Chg{Version=[3], New=[. If a @nt{pragma} Restrictions applies to any compilation unit included in the partition, this may impose either (or both) of two kinds of requirements, as], Old=[; unless otherwise]} specified for @Chg{Version=[3],New=[the],Old=[a]} particular restriction@Chg{Version=[3],New=[:],Old=[, a partition shall obey the restriction if a @nt{pragma} Restrictions applies to any compilation unit included in the partition.]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[A restriction may impose requirements on some or all of the units comprising the partition. Unless otherwise specified for a particular restriction, such a requirement applies to all of the units comprising the partition and is enforced via a post-compilation check.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[A restriction may impose requirements on the run-time behavior of the program, as indicated by the specification of run-time behavior associated with a violation of the requirement.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In this latter case, there is no post-compilation check needed for the requirement.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[For the purpose of checking whether a partition contains constructs that violate any restriction (unless specified otherwise for a particular restriction):]} @begin{itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[Generic instances are logically expanded at the point of instantiation;]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[If an object of a type is declared or allocated and not explicitly initialized, then all expressions appearing in the definition for the type and any of its ancestors are presumed to be used;]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[A @nt{default_expression} for a formal parameter or a generic formal object is considered to be used if and only if the corresponding actual parameter is not provided in a given call or instantiation.]} @end{itemize} @end{LinkTime} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[An implementation may provide implementation-defined restrictions; the identifier for an implementation-defined restriction shall differ from those of the language-defined restrictions.]} @ChgImplDef{Version=[3],Kind=[Added], Text=[@ChgAdded{Version=[3],Text=[Implementation-defined restrictions allowed in a @nt{pragma} Restrictions.]}]} An implementation may place limitations on the values of the @nt{expression} that are supported, and limitations on the supported combinations of restrictions. The consequences of violating such limitations are implementation defined. @ImplDef{The consequences of violating limitations on Restrictions @nt{pragma}s.} @begin{Ramification} Such limitations may be enforced at compile time or at run time. Alternatively, the implementation is allowed to declare violations of the restrictions to be erroneous, and not enforce them at all. @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[1],Text=[An implementation is permitted to omit restriction checks for code that is recognized at compile time to be unreachable and for which no code is generated.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0043],ARef=[AI95-00190-01]} @ChgAdded{Version=[1],Text=[Whenever enforcement of a restriction is not required prior to execution, an implementation may nevertheless enforce the restriction prior to execution of a partition to which the restriction applies, provided that every execution of the partition would violate the restriction.]} @end{ImplPerm} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Profile is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn{Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Profile> (@SynI{profile_}@Syn2{identifier} {, @SynI{profile_}@Syn2{pragma_argument_association}});]}} @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[The @SynI{profile_}@nt{identifier} shall be the name of a usage profile. The semantics of any @SynI{profile_}@nt{pragma_@!argument_@!association}s are defined by the usage profile specified by the @SynI{profile_}@nt{identifier}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[A profile is equivalent to the set of configuration pragmas that is defined for each usage profile.]} @end{StaticSem} @begin{Linktime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[configuration pragma], Sec=(Profile)} @PDefn2{Term=[pragma, configuration], Sec=(Profile)} A @nt{pragma} Profile is a configuration pragma. There may be more than one @nt{pragma} Profile for a partition.]} @end{Linktime} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[An implementation may provide implementation-defined usage profiles; the identifier for an implementation-defined usage profile shall differ from those of the language-defined usage profiles.]} @ChgImplDef{Version=[3],Kind=[Added], Text=[@ChgAdded{Version=[3],Text=[Implementation-defined usage profiles allowed in a @nt{pragma} Profile.]}]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00347-01]} Restrictions intended to facilitate the construction of efficient tasking run-time systems are defined in @RefSecNum{Tasking Restrictions}. @Chg{Version=[2],New=[Restrictions intended for use when constructing high integrity systems],Old=[Safety- and security-related restrictions]} are defined in @RefSecNum{High Integrity Restrictions}. An implementation has to enforce the restrictions in cases where enforcement is required, even if it chooses not to take advantage of the restrictions in terms of efficiency. @begin{Discussion} It is not the intent that an implementation will support a different run-time system for every possible combination of restrictions. An implementation might support only two run-time systems, and document a set of restrictions that is sufficient to allow use of the more efficient and safe one. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Pragma Restrictions is new to Ada 95. @end{Extend83} @begin{Extend95} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI05-0246-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Profile is new; it was moved here by Ada 2012 and renamed to a "usage profile" but was otherwise unchanged.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording so that restrictions are checked inside of generic instantiations and in default expressions. Since not making these checks would violate the purpose of restrictions, we are not documenting this as an incompatibility.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0043],ARef=[AI95-00190-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added a permission that restrictions can be enforced at compile-time. While this is technically incompatible, documenting it as such would be unnecessarily alarming - there should not be any programs depending on the runtime failure of restrictions.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[The syntax of a @nt{restriction_parameter_argument} has been defined to better support restriction No_Dependence (see @RefSecNum{Language-Defined Restrictions and Profiles}).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[@b<Correction>: When restrictions are checked has been clarified.]} @end{DiffWord2005} @LabeledRevisedSubClause{Version=[3],InitialVersion=[2],New=[Language-Defined Restrictions and Profiles],Old=[Language-Defined Restrictions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_}@nt{identifier}s are language defined (additional restrictions are defined in the Specialized Needs Annexes):]} @begin{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0241-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Implementation_Aspect_Specifications)}@Chg{Version=[3],New=[@Defn{No_Implementation_Aspect_Specifications restriction}], Old=[]}No_Implementation_Aspect_Specifications @\There are no implementation-defined aspects specified by an @nt{aspect_specification}. This restriction applies only to the current compilation or environment, not the entire partition.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0241-1]} @ChgAdded{Version=[3],Text=[This restriction (as well as others below) applies only to the current compilation, because it is likely that the runtime (and possibly user-written low-level code) will need to use implementation-defined aspects. But a partition-wide restriction applies everywhere, including the runtime.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(No_Implementation_Attributes)}@Chg{Version=[3],New=[@Defn{No_Implementation_Attributes restriction}], Old=[]}No_Implementation_Attributes @\There are no implementation-defined attributes. This restriction applies only to the current compilation or environment, not the entire partition.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0241-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[This restriction (as well as No_Implementation_Pragmas) only applies to the current compilation, because it is likely that the runtime (and possibly user-written low-level code) will need to use implementation-defined entities. But a partition-wide restriction applies everywhere, including the runtime.],Old=[]}]} @end{Discussion} @Comment{The end part of this and the bullets are Redundant, but that would cause bad nesting, so we don't mark it} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0246-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Implementation_Identifiers)}@Defn{No_Implementation_Identifiers restriction}No_Implementation_Identifiers @\There are no usage names that denote declarations with implementation-defined identifiers that occur within language-defined packages or instances of language-defined generic packages. Such identifiers can arise as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following language-defined packages and generic packages allow implementation-defined identifiers:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package System (see @RefSecNum{The Package System});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Standard (see @RefSecNum{The Package Standard});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Ada.Command_Line (see @RefSecNum{The Package Command_Line});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces.C (see @RefSecNum{Interfacing with C and C++});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces.C.Strings (see @RefSecNum{The Package Interfaces.C.Strings});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces.C.Pointers (see @RefSecNum{The Generic Package Interfaces.C.Pointers});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces.COBOL (see @RefSecNum{Interfacing with COBOL});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces.Fortran (see @RefSecNum{Interfacing with Fortran});]} @end{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following language-defined packages contain only implementation-defined identifiers:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package System.Machine_Code (see @RefSecNum{Machine Code Insertions});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Ada.Directories.Information (see @RefSecNum{The Package Directories});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[nested Implementation packages of the Queue containers (see @RefSecNum{The Generic Package Containers.Unbounded_Synchronized_Queues}-31);]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Interfaces (see @RefSecNum{The Package Interfaces});]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[package Ada.Interrupts.Names (see @RefSecNum{The Package Interrupts}).]} @end{InnerItemize} @end{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[For package Standard, Standard.Long_Integer and Standard.Long_Float are considered language-defined identifiers, but identifiers such as Standard.Short_Short_Integer are considered implementation-defined.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[This restriction applies only to the current compilation or environment, not the entire partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(No_Implementation_Pragmas)}@Chg{Version=[3], New=[@Defn{No_Implementation_Pragmas restriction}], Old=[]}No_Implementation_Pragmas @\There are no implementation-defined pragmas or pragma arguments. This restriction applies only to the current compilation or environment, not the entire partition.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0242-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Implementation_Units)}@Defn{No_Implementation_Units restriction}No_Implementation_Units @\There is no mention in the @nt{context_clause} of any implementation-defined descendants of packages Ada, Interfaces, or System. This restriction applies only to the current compilation or environment, not the entire partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00368-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(No_Obsolescent_Features)}@Chg{Version=[3],New=[@Defn{No_Obsolescent_Features restriction}], Old=[]}No_Obsolescent_Features @\There is no use of language features defined in Annex J. It is @Chg{Version=[3],New=[implementation defined whether], Old=[implementation-defined if]} uses of the renamings of @RefSecNum{Renamings of Library Units} @Chg{Version=[3],New=[and of the @nt{pragma}s of @RefSecNum{Aspect-related Pragmas} ],Old=[]}are detected by this restriction. This restriction applies only to the current compilation or environment, not the entire partition.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[A user could compile a rename like]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Text_IO; @key{package} Text_IO @key{renames} Ada.Text_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Such a rename must not be disallowed by this restriction, nor should the compilation of such a rename be restricted by an implementation. Many implementations implement the renames of @RefSecNum{Renamings of Library Units} by compiling them normally; we do not want to require implementations to use a special mechanism to implement these renames.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The pragmas have the same functionality as the corresponding aspect (unlike the typical obsolescent feature), and rejecting them could be a significant portability problem for existing code.]} @end{Reason} @end{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0241-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_parameter_}@nt{identifier}@Chg{Version=[3],New=[s are],Old=[is]} language defined:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Dependence)}@Defn{No_Dependence restriction}No_Dependence @\Specifies a library unit on which there are no semantic dependences.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0241-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Specification_of_Aspect)}@Defn{No_Specification_of_Aspect restriction}No_Specification_of_Aspect @\Identifies an aspect for which no @nt{aspect_specification}, @nt{attribute_definition_clause}, or @nt{pragma} is given.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Use_Of_Attribute)}@Defn{No_Use_Of_Attribute restriction}No_Use_Of_Attribute @\Identifies an attribute for which no @nt{attribute_reference} or @nt{attribute_definition_clause} is given.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Use_Of_Pragma)}@Defn{No_Use_Of_Pragma restriction}No_Use_Of_Pragma @\Identifies a @nt{pragma} which is not to be used.]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[The @nt{restriction_parameter_argument} of a No_Dependence restriction shall be a @nt{name}; the @nt{name} shall have the form of a full expanded name of a library unit, but need not denote a unit present in the environment.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This @nt{name} is not resolved.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0241-1]} @ChgAdded{Version=[3],Text=[The @nt{restriction_parameter_argument} of a No_Specification_of_Aspect restriction shall be an @nt{identifier}; this is an identifier specific to a pragma (see @RefSecNum{Pragmas}) and does not denote any declaration.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This @nt{restriction_parameter_argument} is not resolved as it is an identifier specific to a pragma. As for No_Dependence, there is no check that the aspect @nt{identifier} is meaningful; it might refer to an implementation-defined aspect on one implementation, but nothing at all on another implementation.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[The @nt{restriction_parameter_argument} of a No_Use_Of_Attribute restriction shall be an @nt{identifier} or one of the reserved words Access, Delta, Digits, Mod, or Range; this is an identifier specific to a pragma.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This @nt{restriction_parameter_argument} is not resolved as it is an identifier specific to a pragma. There is no check that the attribute identifier refers to a known @nt{attribute_designator}; it might refer to an implementation-defined attribute on one implementation, but nothing at all on another implementation.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[The @nt{restriction_parameter_argument} of a No_Use_Of_Pragma restriction shall be an @nt{identifier} or the reserved word Interface; this is an identifier specific to a pragma.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This @nt{restriction_parameter_argument} is not resolved as it is an identifier specific to a pragma. There is no check that the pragma identifier refers to a known @nt{pragma}; it might refer to an implementation-defined pragma on one implementation, but nothing at all on another implementation.]} @end{Ramification} @end{Legality} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0241-1]} @ChgAdded{Version=[2],Text=[No compilation unit included in the partition shall depend semantically on the library unit identified by the @nt{name}@Chg{Version=[3],New=[ of a No_Dependence restriction],Old=[]}.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no requirement that the library unit actually exist. One possible use of the pragma is to prevent the use of implementation-defined units; when the program is ported to a different compiler, it is perfectly reasonable that no unit with the name exist.]} @end{Ramification} @end{LinkTime} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following @SynI{profile_}@nt{identifier} is language defined:]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[profile],Sec=(No_Implementation_Extensions)}No_Implementation_Extensions @\]} @end{Description} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[For usage profile No_Implementation_Extensions, there shall be no @SynI{profile_}@nt{pragma_argument_association}s.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The No_Implementation_Extensions usage profile is equivalent to the following restrictions:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[No_Implementation_Aspect_Specifications, No_Implementation_Attributes, No_Implementation_Identifiers, No_Implementation_Pragmas, No_Implementation_Units.]} @end{Example} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00257-01],ARef=[AI95-00368-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Restrictions No_Implementation_Attributes, No_Implementation_Pragmas, and No_Obsolescent_Features are new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00381-01]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence is new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0241-1],ARef=[AI05-0242-1],ARef=[AI05-0246-1],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Restrictions No_Implementation_Aspect_Specifications, No_Implementation_Identifiers, No_Implementation_Units, No_Specification_of_Aspect, No_Use_of_Attribute, and No_Use_of_Pragma are new.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[Profile No_Implementation_Extensions is new.]} @end{Extend2005} @LabeledClause{Streams} @begin{Intro} @Defn{stream} @Defn{stream type} A @i{stream} is a sequence of elements comprising values from possibly different types and allowing sequential access to these values. A @i{stream type} is a type in the class whose root type is Streams.Root_Stream_Type. A stream type may be implemented in various ways, such as an external sequential file, an internal buffer, or a network channel. @begin{Discussion} A stream element will often be the same size as a storage element, but that is not required. @end{Discussion} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Stream>, Text=<@ChgAdded{Version=[3],Text=[A stream is a sequence of elements that can be used, along with the stream-oriented attributes, to support marshalling and unmarshalling of values of most types.]}>} @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} Streams are new in Ada 95. @end{Extend83} @LabeledSubClause{The Package Streams} @begin{StaticSem} The abstract type Root_Stream_Type is the root type of the class of stream types. The types in this class represent different kinds of streams. A new stream type is defined by extending the root type (or some other stream type), overriding the Read and Write operations, and optionally defining additional primitive subprograms, according to the requirements of the particular kind of stream. The predefined stream-oriented attributes like T'Read and T'Write make dispatching calls on the Read and Write procedures of the Root_Stream_Type. (User-defined T'Read and T'Write attributes can also make such calls, or can call the Read and Write attributes of other types.) @begin{example} @ChildUnit{Parent=[Ada],Child=[Streams]}@key[package] Ada.Streams @key[is] @key[pragma] Pure(Streams)@Defn{unpolluted};@Comment{This *must* be a Duff joke} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Root_Stream_Type} @key[is] @key[abstract tagged limited private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Root_Stream_Type);],Old=[]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0044],ARef=[AI95-00181-01]} @key[type] @AdaTypeDefn{Stream_Element} @key[is] @key[mod] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Stream_Element_Offset} @key[is] @key[range] @RI{implementation-defined}; @key[subtype] @AdaSubtypeDefn{Name=[Stream_Element_Count],Of=[Stream_Element_Offset]} @key[is] Stream_Element_Offset @key[range] 0..Stream_Element_Offset'Last; @key[type] @AdaTypeDefn{Stream_Element_Array} @key[is] @key[array](Stream_Element_Offset @key[range] <>) @key[of]@Chg{New=[@key[ aliased]],Old=[]} Stream_Element; @key[procedure] @AdaSubDefn{Read}( Stream : @key[in] @key[out] Root_Stream_Type; Item : @key[out] Stream_Element_Array; Last : @key[out] Stream_Element_Offset) @key[is abstract]; @key[procedure] @AdaSubDefn{Write}( Stream : @key[in] @key[out] Root_Stream_Type; Item : @key[in] Stream_Element_Array) @key[is abstract]; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Streams; @end{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00227-01]} The Read operation transfers @Chg{Version=[2],New=[],Old=[Item'Length ]}stream elements from the specified stream to fill the array Item. @Chg{Version=[2],New=[Elements are transferred until Item'Length elements have been transferred, or until the end of the stream is reached. If any elements are transferred, the],Old=[The]} index of the last stream element transferred is returned in Last. @Chg{Version=[2],New=[Otherwise, Item'First - 1 is returned in Last. ],Old=[]}Last is less than Item'Last only if the end of the stream is reached.@Comment{This last sentence should be marked Redundant.} The Write operation appends Item to the specified stream. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgNote{This was moved from 13.7.1.} @ChgAdded{Version=[2],Text=[The index subtype of Stream_Element_Array is Stream_Element_Offset because we wish to allow maximum flexibility. Most Stream_Element_Arrays will probably have a lower bound of 0 or 1, but other lower bounds, including negative ones, make sense in some situations.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgNote{This was moved from 13.7.1, where it was totally bogus.} @ChgAdded{Version=[2],Text=[Note that there are some language-defined subprograms that fill part of a Stream_Element_Array, and return the index of the last element filled as a Stream_Element_Offset. The Read procedures declared here, Streams.Stream_IO (see @RefSecNum{The Package Streams.Stream_IO}), and System.RPC (see @RefSecNum{Partition Communication Subsystem}) behave in this manner. These will raise Constraint_Error if the resulting Last value is not in Stream_Element_Offset. This implies that the Stream_Element_Array passed to these subprograms should not have a lower bound of Stream_Element_Offset'First, because then a read of 0 elements would always raise Constraint_Error. A better choice of lower bound is @Chg{Version=[3],New=[0 or ],Old=[]}1.]} @end{Discussion} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0044],ARef=[AI95-00181-01]} @ChgAdded{Version=[1],Text=[If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_@!Element_@!Array need not be aliased.]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00114-01]} @ChgAdded{Version=[1],Text=[If the Stream_Element'Size is less than the size of System.Storage_Unit, then components of Stream_@!Element_@!Array need not be aliased. This is necessary as the components of type Stream_Element size might not be addressable on the target @Chg{Version=[2],New=[architecture],Old=[architechture]}.]} @end{Ramification} @end{ImplPerm} @begin{Notes} See @RefSec{The Package Streams.Stream_IO} for an example of extending type Root_Stream_Type. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00227-01]} @ChgAdded{Version=[2],Text=[If the end of stream has been reached, and Item'First is Stream_Element_Offset'First, Read will raise Constraint_Error.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Thus, Stream_Element_Arrays should start at 0 or 1, not Stream_Element_Offset'First.]} @end{Ramification} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type Root_Stream_Type.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0044],ARef=[AI95-00181-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Stream elements are aliased presuming that makes sense.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00227-01]} @ChgAdded{Version=[2],Text=[Fixed the wording for Read to properly define the result in Last when no stream elements are transfered.]} @end{DiffWord95} @LabeledSubClause{Stream-Oriented Attributes} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0183-1]} The @Chg{Version=[3],New=[type-related ],Old=[]}@Chg{New=[operational attributes ],Old=[]}Write, Read, Output, and Input @Chg{New=[],Old=[attributes ]}convert values to a stream of elements and reconstruct values from a stream. @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For @PrefixType{every subtype S of an elementary type @i(T)}, the following representation attribute is defined:]} @begin{Description} @Comment{Originally Version=[2],Kind=[Added], but we don't have a way to do both; also, Kind should be RevisedAdded, but that changes the attribute name to not inserted.} @ChgAttribute{Version=[3],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Stream_Size>, ARef=[AI95-00270-01], ARef=[AI05-0194-1], Text=[@Chg{Version=[2],New=[Denotes the number of bits @Chg{Version=[3],New=[read from or written to a stream by the default implementations of S'Read and S'Write],Old=[occupied in a stream by items of subtype S]}. Hence, the number of stream elements required per item of elementary type @i<T> is:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@i<T>'Stream_Size / Ada.Streams.Stream_Element'Size]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The value of this attribute is of type @i{universal_integer} and is a multiple of Stream_Element'Size.]}]}@Comment{end attribute Stream_Size} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[Stream_Size may be specified for first subtypes via an @nt{attribute_definition_clause}; the @nt{expression} of such a clause shall be static, nonnegative, and a multiple of Stream_Element'Size.@Chg{Version=[3],New=[@AspectDefn{Stream_Size}],Old=[]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Stream_Size], Text=[@ChgAdded{Version=[3],Text=[Size in bits used to represent elementary objects in a stream.]}]} @end{Description} @EndPrefixType{} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Stream_Size is a type-related attribute (see @RefSecNum{Operational and Representation Aspects}).]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal], ARef=[AI05-0194-1]} @ChgAdded{Version=[3],Text=[The value of S'Stream_Size is unaffected by the presence or absence of any @nt{attribute_definition_clause}s or @nt{aspect_specification}s specifying the Read or Write attributes of any ancestor of S. S'Stream_Size is defined in terms of the behavior of the default implementations of S'Read and S'Write even if those default implementations are overridden.]} @end{Ramification} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[If not specified, the value of Stream_Size for an elementary type should be the number of bits that corresponds to the minimum number of stream elements required by the first subtype of the type, rounded up to the nearest factor or multiple of the word size that is also a multiple of the stream element size.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If not specified, the value of Stream_Size for an elementary type should be the number of bits that corresponds to the minimum number of stream elements required by the first subtype of the type, rounded up to the nearest factor or multiple of the word size that is also a multiple of the stream element size.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[This is @ImplAdviceTitle because we want to allow implementations to remain compatible with their Ada 95 implementations, which may have a different handling of the number of stream elements. Users can always specify Stream_Size if they need a specific number of stream elements.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[@PDefn2{Term=[recommended level of support], Sec=(Stream_Size attribute)} The recommended level of support for the Stream_Size attribute is:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[A Stream_Size clause should be supported for a discrete or fixed point type @i<T> if the specified Stream_Size is a multiple of Stream_Element'Size and is no less than the size of the first subtype of @i<T>, and no greater than the size of the largest type of the same elementary class (signed integer, modular integer, enumeration, ordinary fixed point, or decimal fixed point).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The recommended level of support for the Stream_Size attribute should be followed.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are no requirements beyond supporting confirming Stream_Size clauses for floating point and access types. Floating point and access types usually only have a handful of defined formats, streaming anything else makes no sense for them.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For discrete and fixed point types, this may require support for sizes other than the @lquotes@;natural@rquotes ones. For instance, on a typical machine with 32-bit integers and a Stream_Element'Size of 8, setting Stream_Size to 24 must be supported. This is required as such formats can be useful for interoperability with unusual machines, and there is no difficulty with the implementation (drop extra bits on output, sign extend on input).]} @end{Ramification} @end{Itemize} @end{ImplAdvice} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @begin{StaticSem} For @PrefixType{every subtype S of a specific type @i(T)}, the following attributes are defined. @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Write>, Text=<S'Write denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Write( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)) @end{DescExample} @noprefix@;S'Write writes the value of @i{Item} to @i{Stream}.>} @AttributeLeading{Prefix=<S>, AttrName=<Read>, Text=<S'Read denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Read( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{out} @RI(T)) @end{DescExample} @noprefix@;S'Read reads the value of @i{Item} from @i{Stream}.>} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00444-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0192-1]} @ChgAdded{Version=[1],Text=[For @Chg{Version=[2],New=[an ],Old=[]}untagged derived @Chg{Version=[2],New=[type],Old=[types]}, the Write @Chg{Version=[2],New=[(resp.],Old=[and]} Read@Chg{Version=[2],New=[) attribute is],Old=[ attributes are]} inherited @Chg{Version=[2],New=[according to the rules given],Old=[as specified]} in @RefSecNum{Operational and Representation Aspects}@Chg{Version=[2], New=[ if the attribute is @Chg{Version=[3],New=[@Redundant[specified and] ], Old=[]}available for the parent type at the point where @i{T} is declared. For a tagged derived type, these attributes are not inherited, but rather],Old=[; otherwise,]} the default implementations @Chg{Version=[2],New=[],Old=[of these attributes ]}are used.@Chg{Version=[2],New=[],Old=[The default implementations of Write and Read attributes execute as follows:]}]} @begin{TheProof} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0192-1]} @ChgAdded{Version=[3],Text=[The inheritance rules of @RefSecNum{Operational and Representation Aspects} say that only specified or inherited aspects are inherited; we mention it again here as a clarification.]} @end{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The default implementations of the Write and Read attributes, where available, execute as follows:]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01],ARef=[AI95-00251-01],ARef=[AI95-00270-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0139-2]} For elementary types, @Chg{Version=[2],New=[Read reads (and Write writes) the number of stream elements implied by the Stream_Size for the type @i<T>;], Old=[]} the representation @Chg{Version=[2],New=[],Old=[in terms ]}of@Chg{Version=[2], New=[ those],Old=[]} stream elements is implementation defined. For composite types, the Write or Read attribute for each component is called in @Chg{New=[],Old=[a ]}canonical order@Chg{New=[, which], Old=[. The canonical order of components]} is last dimension varying fastest for an array@Chg{Version=[3],New=[ (unless the convention of the array is Fortran, in which case it is first dimension varying fastest)],Old=[]}, and positional aggregate order for a record. Bounds are not included in the stream if @i(T) is an array type. If @i(T) is a discriminated type, discriminants are included only if they have defaults. If @i(T) is a tagged type, the tag is not included. @Chg{New=[For type extensions, the Write or Read attribute for the parent type is called, followed by the Write or Read attribute of each component of the extension part, in canonical order. For a limited type extension, if the attribute of @Chg{Version=[2],New=[the parent],Old=[any ancestor]} type @Chg{Version=[2],New=[or any progenitor type ],Old=[]}of @i(T) @Chg{Version=[2],New=[is available anywhere within the immediate scope of @i<T>,],Old=[has been directly specified]} and the attribute of @Chg{Version=[2],New=[the parent type or],Old=[any ancestor type of]} the type of any of the extension components @Chg{Version=[2],New=[is not available at the freezing point of @i<T>, then], Old=[which are of a limited type has not been specified,]} the attribute of @i(T) shall be directly specified.],Old=[]} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The @Chg{Version=[2],New=[contents of the stream elements read and written],Old=[representation used]} by the Read and Write attributes of elementary types@Chg{Version=[2],New=[],Old=[ in terms of stream elements]}.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0023-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[If @i<T> is a discriminated type and its discriminants have defaults, then S'Read first reads the discriminants from the stream without modifying @i<Item>. S'Read then creates an object of type @i<T> constrained by these discriminants. The value of this object is then converted to the subtype of @i<Item> and is assigned to @i<Item>. Finally, the Read attribute for each nondiscriminant component of @i<Item> is called in canonical order as described above. Normal default initialization and finalization take place for the created object.]} @begin{Reason} A discriminant with a default value is treated simply as a component of the object. On the other hand, an array bound or a discriminant without a default value, is treated as @lquotes@;descriptor@rquotes@; or @lquotes@;dope@rquotes@; that must be provided in order to create the object and thus is logically separate from the regular components. Such @lquotes@;descriptor@rquotes@; data are written by 'Output and produced as part of the delivered result by the 'Input function, but they are not written by 'Write nor read by 'Read. A tag is like a discriminant without a default. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[For limited type extensions, we must have a definition of 'Read and 'Write if the parent type has one, as it is possible to make a dispatching call through the attributes. The rule is designed to automatically do the right thing in as many cases as possible.]} @ChgRef{Version=[1],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[1],Text=[Similarly, a type that has a progenitor with an available attribute must also have that attribute, for the same reason.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0023-1]} @ChgAdded{Version=[3],Text=[The semantics of S'Read for a discriminated type with defaults involves an anonymous object so that the point of required initialization and finalization is well-defined, especially for objects that change shape and have controlled components. The creation of this anonymous object often can be omitted (see the @ImplPermTitle below).]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} For a composite object, the subprogram denoted by the Write or Read attribute of each component is called, whether it is the default or is user-specified.@Chg{Version=[2],New=[ Implementations are allowed to optimize these calls (see below), presuming the properties of the attributes are preserved.],Old=[]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00270-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[Constraint_Error is raised by the predefined Write attribute if the value of the elementary item is outside the range of values representable using Stream_Size bits. For a signed integer type, an enumeration type, or a fixed point type, the range is unsigned only if the integer code for the lower bound of the first subtype is nonnegative, and a (symmetric) signed range that covers all values of the first subtype would require more than Stream_Size bits; otherwise@Chg{Version=[3],New=[,],Old=[]} the range is signed.]} @Leading@;For @PrefixType{every subtype S'Class of a class-wide type @i(T)'Class}: @begin{Description} @AttributeLeading{Prefix=<S'Class>, AttrName=<Write>, Text=<S'Class'Write denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Write( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)'Class) @end{DescExample} @noprefix@;Dispatches to the subprogram denoted by the Write attribute of the specific type identified by the tag of Item.>} @AttributeLeading{Prefix=<S'Class>, AttrName=<Read>, Text=<S'Class'Read denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Read( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{out} @RI(T)'Class) @end{DescExample} @noprefix@;Dispatches to the subprogram denoted by the Read attribute of the specific type identified by the tag of Item.>} @begin{Reason} It is necessary to have class-wide versions of Read and Write in order to avoid generic contract model violations; in a generic, we don't necessarily know at compile time whether a given type is specific or class-wide. @end{Reason} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00270-01]} @ChgDeleted{Version=[2],Text=[If a stream element is the same size as a storage element, then the normal in-memory representation should be used by Read and Write for scalar objects. Otherwise, Read and Write should use the smallest number of stream elements needed to represent all values in the base range of the scalar type.]} @ChgNote{We don't add an Implementation Advice tag here, as we're deleting this.} @end{ImplAdvice} @begin{NotIso} @ChgAdded{Version=[2],Noparanum=[T],Text=[@Shrink{@i<Paragraph 17 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{StaticSem} For @PrefixType{every subtype S of a specific type @i(T)}, the following attributes are defined. @begin{Description} @AttributeLeading{Prefix=<S>, AttrName=<Output>, Text=<S'Output denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Output( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)) @end{DescExample} @noprefix@;S'Output writes the value of @i{Item} to @i{Stream}, including any bounds or discriminants.>} @begin{Ramification} Note that the bounds are included even for an array type whose first subtype is constrained. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Input>, Text=<S'Input denotes a function with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(function) S'Input( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class) @key(return) @RI(T) @end{DescExample} @noprefix@;S'Input reads and returns one value from @i{Stream}, using any bounds or discriminants written by a corresponding S'Output to determine how much to read.>} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00444-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0192-1]} @Chg{New=[For @Chg{Version=[2],New=[an ],Old=[]}untagged derived @Chg{Version=[2],New=[type],Old=[types]}, the Output @Chg{Version=[2],New=[(resp.],Old=[and]} Input@Chg{Version=[2],New=[) attribute is],Old=[attributes of the parent type are]} inherited @Chg{Version=[2],New=[according to the rules given], Old=[as specified]} in @RefSecNum{Operational and Representation Aspects}@Chg{Version=[2], New=[ if the attribute is @Chg{Version=[3],New=[@Redundant[specified and] ], Old=[]}available for the parent type at the point where @i{T} is declared. For a tagged derived type, these attributes are not inherited, but rather],Old=[; otherwise,]} the default implementations@Chg{Version=[2],New=[],Old=[ of these attributes]} are used.@Chg{Version=[2],New=[],Old=[ The default implementations of Output and Input attributes execute as follows:]}], Old=[Unless overridden by an @nt<attribute_definition_clause>, these subprograms execute as follows:]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0192-1]} @ChgAdded{Version=[3],Text=[See the note following the inheritance rules for the Write attribute, above.]} @end{TheProof} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The default implementations of the Output and Input attributes, where available, execute as follows:]} @begin(Itemize) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0269-1]} If @i(T) is an array type, S'Output first writes the bounds, and S'Input first reads the bounds. If @i(T) has discriminants without defaults, S'Output first writes the discriminants (using @Chg{Version=[3],New=[the Write attribute of the discriminant type],Old=[S'Write]} for each), and S'Input first reads the discriminants (using @Chg{Version=[3],New=[the Read attribute of the discriminant type],Old=[S'Read]} for each). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0023-1]} S'Output then calls S'Write to write the value of @i{Item} to the stream. S'Input then creates an object @Chg{Version=[3],New=[of type @i<T>, ],Old=[(]}with the bounds or @Chg{Version=[3],New=[(when without defaults) the ],Old=[]}discriminants, if any, taken from the stream@Chg{Version=[3],New=[],Old=[)]}, @Chg{Version=[2],New=[passes],Old=[initializes]} it @Chg{Version=[2],New=[to],Old=[with]} S'Read, and returns the value of the object.@Chg{Version=[3],New=[ If @i<T> has discriminants, then this object is unconstrained if and only the discriminants have defaults.],Old=[]}@Chg{Version=[2],New=[ Normal default initialization and finalization take place for this object (see @RefSecNum{Object Declarations}, @RefSecNum{Assignment and Finalization}, and @RefSecNum{Completion and Finalization}).],Old=[]} @end(Itemize) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[If @i<T> is an abstract type, then S'Input is an abstract function.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For an abstract type @i<T>, S'Input can be called in a dispatching call, or passed to an abstract formal subprogram. But it cannot be used in nondispatching contexts, because we don't allow objects of abstract types to exist. The designation of this function as abstract has no impact on descendants of @i<T>, as @i<T>'Input is not inherited for tagged types, but rather recreated (and the default implementation of @i<T>'Input calls @i<T>'Read, not the parent type's @i<T>'Input). Note that @i<T>'Input cannot be specified in this case, as any function with the proper profile is necessarily abstract, and specifying abstract subprograms in an @nt{attribute_definition_clause} is illegal.]} @end{Ramification} @Leading@;For @PrefixType{every subtype S'Class of a class-wide type @i(T)'Class}: @begin{Description} @AttributeLeading{Prefix=<S'Class>, AttrName=<Output>, Text=<S'Class'Output denotes a procedure with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(procedure) S'Class'Output( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class; @RI{Item} : @key{in} @RI(T)'Class) @end{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00344-01]} @noprefix@;First writes the external tag of @i{Item} to @i{Stream} (by calling String'Output(@Chg{Version=[2],New=[@I{Stream}, ],Old=[]}Tags.@!External_Tag(@i{Item}'Tag)@Chg{Version=[2],New=[)],Old=[]} @em see @RefSecNum{Tagged Types and Type Extensions}) and then dispatches to the subprogram denoted by the Output attribute of the specific type identified by the tag.@Chg{Version=[2],New=[ Tag_Error is raised if the tag of Item identifies a type declared at an accessibility level deeper than that of S.],Old=[]}>}@Comment{End of S'Class'Output attribute} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[We raise Tag_Error here for nested types as such a type cannot be successfully read with S'Class'Input, and it doesn't make sense to allow writing a value that cannot be read.]} @end{Reason} @AttributeLeading{Prefix=<S'Class>, AttrName=<Input>, Text=<S'Class'Input denotes a function with the following specification: @begin{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key(function) S'Class'Input( @RI{Stream} : @key{@Chg{Version=[2],New=[not null ],Old=[]}access} Ada.Streams.Root_Stream_Type'Class) @key{return} @RI(T)'Class @end{DescExample} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0109-1]} @noprefix@;First reads the external tag from @i{Stream} and determines the corresponding internal tag (by calling Tags.@Chg{Version=[2],New=[Descendant_Tag], Old=[Internal_Tag]}(String'Input(@i{Stream})@Chg{Version=[2],New=[, S'Tag],Old=[]}) @Chg{Version=[2],New=[which might raise Tag_Error ],Old=[]}@em see @RefSecNum{Tagged Types and Type Extensions}) and then dispatches to the subprogram denoted by the Input attribute of the specific type identified by the internal tag; returns that result.@Chg{Version=[2],New=[ If the specific type identified by the internal tag @Chg{Version=[3],New=[],Old=[is not covered by @i<T>'Class or ]}is abstract, Constraint_Error is raised.],Old=[]}>}@Comment{End S'Class'Input attribute} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0109-1]} @ChgAdded{Version=[3],Text=[Descendant_Tag will ensure that the tag it returns is covered by T'Class; Tag_Error will be raised if it would not cover T'Class.]} @end{Ramification} @end{Description} @EndPrefixType{} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0228-1]} @IndexCheck{Range_Check} In the default implementation of Read and Input for a composite type, for each scalar component that is a discriminant or @Chg{Version=[3],New=[that has an implicit initial value],Old=[whose @nt{component_declaration} includes a @nt{default_expression}]}, a check is made that the value returned by Read for the component belongs to its subtype. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. For other scalar components, no check is made. For each component that is of an access type, if the implementation can detect that the value returned by Read for the component is not a value of its subtype, Constraint_Error is raised. If the value is not a value of its subtype and this error is not detected, the component has an abnormal value, and erroneous execution can result (see @RefSecNum{Data Validity}).@Chg{Version=[2],New=[ In the default implementation of Read for a composite type with defaulted discriminants, if the actual parameter of Read is constrained, a check is made that the discriminants read from the stream are equal to those of the actual parameter. Constraint_Error is raised if this check fails.],Old=[]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[The check for scalar components that have an implicit initial value is to preserve our @MetaRulesName that all objects that have an implicit initial value do not become "deinitialized".]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[A scalar component can have an implicit initial value if it has a default_expression, if the component's type has the Default_Value aspect specified, or if the component is that of an array type that has the Default_Component_Value aspect specified.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0228-1]} @ChgAdded{Version=[3],Text=[An implementation should always be able to detect the error for a null value read into a component of an access subtype with a null exclusion; the "if the implementation can detect" is intended to cover nonnull access values.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[@PDefn{unspecified}It is unspecified at which point and in which order these checks are performed. In particular, if Constraint_Error is raised due to the failure of one of these checks, it is unspecified how many stream elements have been read from the stream.]} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0045],ARef=[AI95-00132-01]} @ChgAdded{Version=[1],Text=[@Defn2{Term=[End_Error],Sec=(raised by failure of run-time check)} In the default implementation of Read and Input for a type, End_Error is raised if the end of the stream is reached before the reading of a value of the type is completed.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00195-01],ARef=[AI95-00251-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0039-1]} @PDefn2{Term=[specifiable], Sec=(of Read for a type)} @PDefn2{Term=[specifiable], Sec=(of Write for a type)} @PDefn2{Term=[specifiable], Sec=(of Input for a type)} @PDefn2{Term=[specifiable], Sec=(of Output for a type)} @Defn{Read clause} @Defn{Write clause} @Defn{Input clause} @Defn{Output clause} The stream-oriented attributes may be specified for any type via an @nt{attribute_definition_clause}. @Chg{Version=[2],New=[The subprogram name given in such a clause shall @Chg{Version=[3],New=[statically denote a subprogram that is not],Old=[not denote]} an abstract subprogram. Furthermore, if a stream-oriented attribute is specified for an interface type by an @nt{attribute_definition_clause}, the subprogram name given in the clause shall statically denote a null procedure.], Old=[All nonlimited types have default implementations for these operations. An @nt{attribute_reference} for one of these attributes is illegal if the type is limited, unless the attribute has been specified by an @nt{attribute_@!definition_@!clause}@Chg{New=[ or @Redundant[(for a type extension)] the attribute has been specified for an ancestor type],Old=[]}. For an @nt{attribute_@!definition_@!clause} specifying one of these attributes, the subtype of the Item parameter shall be the base subtype if scalar, and the first subtype otherwise. The same rule applies to the result of the Input function.]} @ChgNote{Most of the old text is moved down} @Chg{Version=[3],New=[@AspectDefn{Read}@AspectDefn{Write}@AspectDefn{Input}@AspectDefn{Output}],Old=[]} @begin{Reason}@ChgNote{This belongs below} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00195-01]} @ChgDeleted{Version=[2],Text=[This is to simplify implementation.]} @end{Reason} @begin{Discussion}@ChgNote{This is junk} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00195-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[@lquotes@;Specified@rquotes includes inherited attributes, and default implementations are never inherited. So, for untagged limited types, the second part of the @nt{attribute_reference} rule has the same meaning as the first part. However, tagged types never inherit attributes, so the second rule is needed so that the default implementations for the attributes can be called when those are constructed from a directly specified ancestor.],Old=[]}]} @end{Discussion} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Stream attributes (other than Input) are always null procedures for interface types (they have no components). We need to allow explicit setting of the Read and Write attributes in order that the class-wide attributes like LI'Class'Input can be made available. (In that case, any descendant of the interface type would require available attributes.) But we don't allow any concrete implementation because these don't participate in extensions (unless the interface is the parent type). If we didn't ban concrete implementations, the order of declaration of a pair of interfaces would become significant. For example, if Int1 and Int2 are interfaces with concrete implementations of 'Read, then the following declarations would have different implementations for 'Read:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Con1 @key{is new} Int1 @key{and} Int2 @key{with null record}; @key{type} Con2 @key{is new} Int2 @key{and} Int1 @key{with null record};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[This would violate our design principle that the order of the specification of the interfaces in a @nt{derived_type_definition} doesn't matter.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The Input attribute cannot be specified for an interface. As it is a function, a null procedure is impossible; a concrete function is not possible anyway as any function returning an abstract type must be abstract. And we don't allow specifying stream attributes to be abstract subprograms. This has no impact, as the availability of Int'Class'Input (where Int is a limited interface) depends on whether Int'Read (not Int'Input) is specified. There is no reason to allow Int'Output to be specified, either, but there is equally no reason to disallow it, so we don't have a special rule for that.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Limited types generally do not have default implementations of the stream-oriented attributes. The rules defining when a stream-oriented attribute is available (see below) determine when an attribute of a limited type is in fact well defined and usable. The rules are designed to maximize the number of cases in which the attributes are usable. For instance, when the language provides a default implementation of an attribute for a limited type based on a specified attribute for the parent type, we want to be able to call that attribute.]} @end{Discussion} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Read], Text=[@ChgAdded{Version=[3],Text=[Procedure to read a value from a stream for a given type.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Write], Text=[@ChgAdded{Version=[3],Text=[Procedure to write a value to a stream for a given type.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Input], Text=[@ChgAdded{Version=[3],Text=[Function to read a value from a stream for a given type, including any bounds and discriminants.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Output], Text=[@ChgAdded{Version=[3],Text=[Procedure to write a value to a stream for a given type, including any bounds and discriminants.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A stream-oriented attribute for a subtype of a specific type @i<T> is @i<available> at places where one of the following conditions is true: @Defn2{Term=[available],Sec=[stream attribute]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T> is nonlimited.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @nt{attribute_designator} is Read (resp. Write) and @i<T> is a limited record extension, and the attribute Read (resp. Write) is available for the parent type of @i<T> and for the types of all of the extension components.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, the language provides a well-defined default implementation, which we want to be able to call.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{T} is a limited untagged derived type, and the attribute was inherited for the type.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Attributes are only inherited for untagged derived types, and surely we want to be able to call inherited attributes.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @nt{attribute_designator} is Input (resp. Output), and @i<T> is a limited type, and the attribute Read (resp. Write) is available for @i<T>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The default implementation of Input and Output are based on Read and Write; so if the implementation of Read or Write is good, so is the matching implementation of Input or Output.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The attribute has been specified via an @nt{attribute_definition_clause}, and the @nt{attribute_definition_clause} is visible.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We always want to allow calling a specified attribute. But we don't want availability to break privacy. Therefore, only attributes whose specification can be seen count. Yes, we defined the visibility of an @nt{attribute_definition_clause} (see @RefSecNum{Visibility}).]} @end{Reason} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A stream-oriented attribute for a subtype of a class-wide type @i<T>'Class is available at places where one of the following conditions is true:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T> is nonlimited;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the attribute has been specified via an @nt{attribute_definition_clause}, and the @nt{attribute_definition_clause} is visible; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the corresponding attribute of @i<T> is available, provided that if @i<T> has a partial view, the corresponding attribute is available at the end of the visible part where @i<T> is declared.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rules are stricter for class-wide attributes because (for the default implementation) we must ensure that any specific attribute that might ever be dispatched to is available. Because we require specification of attributes for extensions of limited parent types with available attributes, we can in fact know this. Otherwise, we would not be able to use default class-wide attributes with limited types, a significant limitation.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[An @nt{attribute_reference} for one of the stream-oriented attributes is illegal unless the attribute is available at the place of the @nt{attribute_reference}. Furthermore, an @nt{attribute_reference} for @i<T>'Input is illegal if @i<T> is an abstract type.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Stream attributes always exist. It is illegal to call them in some cases. Having the attributes not be defined for some limited types would seem to be a cleaner solution, but it would lead to contract model problems for limited private types.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<T>'Input is available for abstract types so that @i<T>'Class'Input is available. But we certainly don't want to allow calls that could create an object of an abstract type. Remember that @i<T>'Class is never abstract, so the above legality rule doesn't apply to it. We don't have to discuss whether the attribute is specified, as it cannot be: any function returning the type would have to be abstract, and we do not allow specifying an attribute with an abstract subprogram.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0192-1]} @ChgAdded{Version=[2],Text=[In the @nt{parameter_and_result_profile}s for @Chg{Version=[3],New=[the default implementations of ],Old=[]}the stream-oriented attributes, the subtype of the Item parameter is the base subtype of @i<T> if @i<T> is a scalar type, and the first subtype otherwise. The same rule applies to the result of the Input attribute.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0192-1]} @ChgAdded{Version=[3],Text=[An inherited stream attribute has a profile as determined by the rules for inheriting primitive subprograms (see @RefSecNum{Operational and Representation Aspects} and @RefSecNum{Derived Types and Classes}).]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0007-1]} @ChgAdded{Version=[2],Text=[For an @nt{attribute_definition_clause} specifying one of these attributes, the subtype of the @Chg{Version=[3],New=[@i<Item>],Old=[Item]} parameter shall be the @Chg{Version=[3],New=[first subtype or the ],Old=[]}base subtype if scalar, and the first subtype @Chg{Version=[3],New=[if not scalar],Old=[otherwise]}. The same rule applies to the result of the Input function.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is to simplify implementation.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The view of the type at the point of the @nt{attribute_definition_clause} determines whether the @Chg{Version=[3], New=[],Old=[first subtype or ]}base subtype is @Chg{Version=[3],New=[allowed],Old=[required]}. Thus, for a scalar type with a partial view (which is never scalar), whether the @Chg{Version=[3], New=[],Old=[first subtype or the ]} base subtype is @Chg{Version=[3], New=[allowed],Old=[required]} is determined by whether the @nt{attribute_definition_clause} occurs before or after the full definition of the scalar type.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0065-1]} @ChgAdded{Version=[2],Text=[@Defn{support external streaming} @Defn2{Term=[external streaming],Sec={type supports}} @Redundant[A type is said to @i{support external streaming} if Read and Write attributes are provided for sending values of such a type between active partitions, with Write marshalling the representation, and Read unmarshalling the representation.] A limited type supports external streaming only if it has available Read and Write attributes. A type with a part that is of @Chg{Version=[3],New=[a nonremote],Old=[an]} access type supports external streaming only if that access type or the type of some part that includes the access type component, has Read and Write attributes that have been specified via an @nt{attribute_definition_clause}, and that @nt{attribute_definition_clause} is visible. @Redundant[An anonymous access type does not support external streaming. ]All other types @Chg{Version=[3],New=[(including remote access types, see @RefSecNum{Remote Types Library Units}) ],Old=[]}support external streaming.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised]} @ChgAdded{Version=[2],Text=[A limited type with a part that is of @Chg{Version=[3],New=[a nonremote],Old=[an]} access type needs to satisfy both rules.]} @end{Ramification} @end{StaticSem} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the internal tag returned by Descendant_Tag to T'Class'Input identifies a type that is not library-level and whose tag has not been created, or does not exist in the partition at the time of the call, execution is erroneous.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The definition of Descendant_Tag prevents such a tag from being provided to T'Class'Input if T is a library-level type. However, this rule is needed for nested tagged types.]} @end{Ramification} @end{Erron} @begin{ImplReq} @ChgRef{Version=[1],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[1],Text=[For every subtype @i<S> of a language-defined nonlimited specific type @i<T>, the output generated by S'Output or S'Write shall be readable by S'Input or S'Read, respectively. This rule applies across partitions if the implementation conforms to the Distributed Systems Annex.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[If Constraint_Error is raised during a call to Read because of failure of one the above checks, the implementation @Chg{Version=[3],New=[shall],Old=[must]} ensure that the discriminants of the actual parameter of Read are not modified.]} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[The number of calls performed by the predefined implementation of the stream-oriented attributes on the Read and Write operations of the stream type is unspecified. An implementation may take advantage of this permission to perform internal buffering. However, all the calls on the Read and Write operations of the stream type needed to implement an explicit invocation of a stream-oriented attribute @Chg{Version=[3],New=[shall],Old=[must]} take place before this invocation returns. An explicit invocation is one appearing explicitly in the program text, possibly through a generic instantiation (see @RefSecNum{Generic Instantiation}).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0023-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[If @i<T> is a discriminated type and its discriminants have defaults, then in two cases an execution of the default implementation of S'Read is not required to create an anonymous object of type @i<T>: If the discriminant values that are read in are equal to the corresponding discriminant values of @i<Item>, then no object of type @i<T> need be created and @i<Item> may be used instead. If they are not equal and @i<Item> is a constrained variable, then Constraint_Error may be raised at that point, before any further values are read from the stream and before the object of type @i<T> is created.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0023-1]} @ChgAdded{Version=[3],Text=[A default implementation of S'Input that calls the default implementation of S'Read may create a constrained anonymous object with discriminants that match those in the stream.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[This allows the combined executions of S'Input and S'Read to create one object of type @i<T> instead of two. If this option is exercised, then:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The discriminants are read from the stream by S'Input, not S'Read.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[S'Input declares an object of type @i<T> constrained by the discriminants read from the stream, not an unconstrained object.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The discriminant values that S'Read would normally have read from the stream are read from Item instead.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The permissions of the preceding paragraph then apply and no object of type @i<T> need be created by the execution of S'Read.]} @end{Itemize} @end{ImplNote} @end{ImplPerm} @begin{Notes} For a definite subtype S of a type @i(T), only @i(T)'Write and @i(T)'Read are needed to pass an arbitrary value of the subtype through a stream. For an indefinite subtype S of a type @i(T), @i(T)'Output and @i(T)'Input will normally be needed, since @i(T)'Write and @i(T)'Read do not pass bounds, discriminants, or tags. User-specified attributes of S'Class are not inherited by other class-wide types descended from S. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of user-defined Write attribute:} @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00441-01]} @key[procedure] My_Write( Stream : @key[@Chg{Version=[2],New=[not null ],Old=[]}access] Ada.Streams.Root_Stream_Type'Class;@Chg{Version=[2],New=[ ],Old=[]}Item@Chg{Version=[2],New=[ ],Old=[]} : My_Integer'Base); @key(for) My_Integer'Write @key(use) My_Write; @end{Example} @begin{Discussion} @leading@keepnext@i{Example of network input/output using input output attributes:} @begin{Example} @key(with) Ada.Streams; @key(use) Ada.Streams; @key(generic) @key(type) Msg_Type(<>) @key(is private); @key(package) Network_IO @key(is) --@RI[ Connect/Disconnect are used to establish the stream] @key(procedure) Connect(...); @key(procedure) Disconnect(...); --@RI[ Send/Receive transfer messages across the network] @key(procedure) Send(X : @key[in] Msg_Type); @key(function) Receive @key(return) Msg_Type; @key(private) @key(type) Network_Stream @key(is new) Root_Stream_Type @key(with) ... @key(procedure) Read(...); --@RI[ define Read/Write for Network_Stream] @key(procedure) Write(...); @key(end) Network_IO; @key(with) Ada.Streams; @key(use) Ada.Streams; @key(package body) Network_IO @key(is) Current_Stream : @key(aliased) Network_Stream; . . . @key(procedure) Connect(...) @key(is) ...; @key(procedure) Disconnect(...) @key(is) ...; @key(procedure) Send(X : @key[in] Msg_Type) @key(is) @key(begin) Msg_Type'Output(Current_Stream'Access, X); @key(end) Send; @key(function) Receive @key(return) Msg_Type @key(is) @key(begin) @key(return) Msg_Type'Input(Current_Stream'Access); @key(end) Receive; @key(end) Network_IO; @end{Example} @end{Discussion} @end{Examples} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b<Corrigendum:> Clarified how the default implementation for stream attributes is determined (eliminating conflicting language). The new wording provides that attributes for type extensions are created by composing the parent's attribute with those for the extension components if any. If a program was written assuming that the extension components were not included in the stream (as in original Ada 95), it would fail to work in the language as corrected by the Corrigendum.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[@B[Amendment Correction:] Explicitly provided a permission that the number of calls to the underlying stream Read and Write operations may differ from the number determined by the canonical operations. If Ada 95 code somehow depended on the number of calls to Read or Write, it could fail with an Ada 2005 implementation. Such code is likely to be very rare; moreover, such code is really wrong, as the permission applies to Ada 95 as well.]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00270-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Stream_Size attribute is new. It allows specifying the number of bits that will be streamed for a type. The @ImplAdviceTitle involving this also was changed; this is not incompatible because @ImplAdviceTitle does not have to be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0040],ARef=[AI95-00108-01],ARef=[AI95-00195-01],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Limited types may have default constructed attributes if all of the parent and (for extensions) extension components have available attributes. Ada 2005 adds the notion of availability to patch up some holes in the Corrigendum model.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that these are operational attributes.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0045],ARef=[AI95-00132-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that End_Error is raised by the default implementation of Read and Input if the end of the stream is reached. (The result could have been abnormal without this clarification, thus this is not an inconsistency, as the programmer could not have depended on the previous behavior.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Clarified that the default implementation of S'Input does normal initialization on the object that it passes to S'Read.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00195-01]} @ChgAdded{Version=[2],Text=[Explicitly stated that what is read from a stream when a required check fails is unspecified.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Defined availability and default implementations for types with progenitors.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[Specified that Constraint_Error is raised if the internal tag retrieved for S'Class'Input is for some type not covered by S'Class or is abstract. We also explicitly state that the program is erroneous if the tag has not been created or does not currently exist in the partition. (Ada 95 did not specify what happened in these cases; it's very unlikely to have provided some useful result, so this is not considered an inconsistency.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00344-01]} @ChgAdded{Version=[2],Text=[Added wording to support nested type extensions. S'Input and S'Output always raise Tag_Error for such extensions, and such extensions were not permitted in Ada 95, so this is neither an extension nor an incompatibility.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Defined @i<supports external streaming> to put all of the rules about @lquotes@;good@rquotes stream attributes in one place. This is used for distribution and for defining pragma Pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00441-01]} @ChgAdded{Version=[2],Text=[Added the @key[not null] qualifier to the first parameter of all of the stream attributes, so that the semantics doesn't change between Ada 95 and Ada 2005. This change is compatible, because mode conformance is required for subprograms specified as stream attributes, and @nt{null_exclusion}s are not considered for mode conformance.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00444-01]} @ChgAdded{Version=[2],Text=[Improved the wording to make it clear that we don't define the default implementations of attributes that cannot be called (that is, aren't @lquotes@;available@rquotes@;). Also clarified when inheritance takes place.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0039-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added a requirement that stream attributes be specified by a static subprogram name rather than a dynamic expression. Expressions cannot provide any useful functionality because of the freezing rules, and the possibility of them complicates implementations. Only pathological programs should be affected.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0007-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Stream attributes for scalar types can be specified with subprograms that take the first subtype as well as the base type. This eliminates confusion about which subtype is appropriate for attributes specified for partial views whose full type is a scalar type. It also eliminates a common user error (forgetting 'Base).]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0023-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the definition of the default version S'Read and S'Input to be well-defined if S is a discriminated type with defaulted discriminants and some components require initialization and/or finalizations.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0065-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined remote access types to support external streaming, since that is their purpose.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0109-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Removed a misleading phrase which implies that Constraint_Error is raised for internal tags of the wrong type, when Tag_Error should be raised for such tags.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0139-2]} @ChgAdded{Version=[3],Text=[Clarified that arrays with convention Fortran are written in column-major order, rather then row-major order. This is necessary in order that streaming of Fortran arrays is efficient.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0192-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that the profile of an inherited stream attribute is as defined for an inherited primitive subprogram, while the default implementation of the same attribute might have a different profile.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0194-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that Stream_Size has no effect on and is not effected by user-defined stream attributes.]} @end{DiffWord2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledClause{Freezing Rules} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines a place in the program text where each declared entity becomes @lquotes@;frozen.@rquotes@; A use of an entity, such as a reference to it by name, or (for a type) an expression of the type, causes freezing of the entity in some contexts, as described below. The @LegalityTitle forbid certain kinds of uses of an entity in the region of text where it is frozen.] @begin{Reason} This concept has two purposes: a compile-time one and a run-time one. The compile-time purpose of the freezing rules comes from the fact that the evaluation of static expressions depends on overload resolution, and overload resolution sometimes depends on the value of a static expression. (The dependence of static evaluation upon overload resolution is obvious. The dependence in the other direction is more subtle. There are three rules that require static expressions in contexts that can appear in declarative places: The expression in an @nt{attribute_designator} shall be static. In a record aggregate, variant-controlling discriminants shall be static. In an array aggregate with more than one named association, the choices shall be static. The compiler needs to know the value of these expressions in order to perform overload resolution and legality checking.) We wish to allow a compiler to evaluate static expressions when it sees them in a single pass over the @nt{compilation_unit}. The freezing rules ensure that. The run-time purpose of the freezing rules is called the @lquotes@;linear elaboration model.@rquotes@; This means that declarations are elaborated in the order in which they appear in the program text, and later elaborations can depend on the results of earlier ones. The elaboration of the declarations of certain entities requires run-time information about the implementation details of other entities. The freezing rules ensure that this information has been calculated by the time it is used. For example, suppose the initial value of a constant is the result of a function call that takes a parameter of type @i(T). In order to pass that parameter, the size of type @i(T) has to be known. If @i(T) is composite, that size might be known only at run time. (Note that in these discussions, words like @lquotes@;before@rquotes@; and @lquotes@;after@rquotes@; generally refer to places in the program text, as opposed to times at run time.) @end{Reason} @begin{Discussion} @leading@;The @lquotes@;implementation details@rquotes@; we're talking about above are: @begin{Itemize} For a tagged type, the implementations of all the primitive subprograms of the type @em that is (in the canonical implementation model), the contents of the type descriptor, which contains pointers to the code for each primitive subprogram. For a type, the full type declaration of any parts (including the type itself) that are private. For a deferred constant, the full constant declaration, which gives the constant's value. (Since this information necessarily comes after the constant's type and subtype are fully known, there's no need to worry about its type or subtype.) For any entity, representation information specified by the user via representation items. Most representation items are for types or subtypes; however, various other kinds of entities, such as objects and subprograms, are possible. @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Similar issues arise for incomplete types. However, we do not use freezing @Chg{Version=[3], New=[to prevent premature access],Old=[there]}; incomplete types have different, more severe, restrictions. Similar issues also arise for subprograms, protected operations, tasks and generic units. However, we do not use freezing @Chg{Version=[3], New=[to prevent premature access for those,],Old=[there]} either; @RefSecNum{Declarative Parts} prevents problems with run-time Elaboration_Checks.@Chg{Version=[3],New=[ Even so, freezing is used for these entities to prevent giving representation items too late (that is, after uses that require representation information, such as calls).],Old=[]} @end{Discussion} @end{Intro} @begin{MetaRules} An evaluable construct should freeze anything that's needed to evaluate it. However, if the construct is not evaluated where it appears, let it cause freezing later, when it is evaluated. This is the case for @nt{default_expression}s and @nt{default_name}s. (Formal parameters, generic formal parameters, and components can have @nt{default_expression}s or @nt{default_name}s.) The compiler should be allowed to evaluate static expressions without knowledge of their context. (I.e. there should not be any special rules for static expressions that happen to occur in a context that requires a static expression.) Compilers should be allowed to evaluate static expressions (and record the results) using the run-time representation of the type. For example, suppose Color'Pos(Red) = 1, but the internal code for Red is 37. If the value of a static expression is Red, some compilers might store 1 in their symbol table, and other compilers might store 37. Either compiler design should be feasible. Compilers should never be required to detect erroneousness or exceptions at compile time (although it's very nice if they do). This implies that we should not require code-generation for a nonstatic expression of type @i(T) too early, even if we can prove that that expression will be erroneous, or will raise an exception. @Leading@;Here's an example (modified from AI83-00039, Example 3): @begin{example} @key[type] T @key[is] @key[record] ... @key[end] @key[record]; @key[function] F @key[return] T; @key[function] G(X : T) @key[return] Boolean; Y : Boolean := G(F); --@RI{ doesn't force T in Ada 83} @key[for] T @key[use] @key[record] ... @key[end] @key[record]; @end{example} @Leading@;AI83-00039 says this is legal. Of course, it raises Program_Error because the function bodies aren't elaborated yet. A one-pass compiler has to generate code for an expression of type T before it knows the representation of T. Here's a similar example, which AI83-00039 also says is legal: @begin{example} @key[package] P @key[is] @key[type] T @key[is] @key[private]; @key[function] F @key[return] T; @key[function] G(X : T) @key[return] Boolean; Y : Boolean := G(F); --@RI{ doesn't force T in Ada 83} @key[private] @key[type] T @key[is] @key[record] ... @key[end] @key[record]; @key[end] P; @end{example} If T's size were dynamic, that size would be stored in some compiler-generated dope; this dope would be initialized at the place of the full type declaration. However, the generated code for the function calls would most likely allocate a temp of the size specified by the dope @i{before} checking for Program_Error. That dope would contain uninitialized junk, resulting in disaster. To avoid doing that, the compiler would have to determine, at compile time, that the expression will raise Program_Error. This is silly. If we're going to require compilers to detect the exception at compile time, we might as well formulate the rule as a legality rule. Compilers should not be required to generate code to load the value of a variable before the address of the variable has been determined. After an entity has been frozen, no further requirements may be placed on its representation (such as by a representation item or a @nt{full_type_declaration}). @end{MetaRules} @begin{Intro} @RootDefn2{Term=[freezing], Sec=(entity)} @Defn2{Term=[freezing points], Sec=(entity)} The @i(freezing) of an entity occurs at one or more places (@i{freezing points}) in the program text where the representation for the entity has to be fully determined. Each entity is frozen from its first freezing point to the end of the program text (given the ordering of compilation units defined in @RefSecNum{The Compilation Process}). @begin{Ramification} The @lquotes@;representation@rquotes@; for a subprogram includes its calling convention and means for referencing the subprogram body, either a @lquotes@;link-name@rquotes@; or specified address. It does not include the code for the subprogram body itself, nor its address if a link-name is used to reference the body. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0019-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[freezing], Sec=(profile)}This subclause also defines a place in the program text where the profile of each declared callable entity becomes @i{frozen}. A use of a callable entity causes freezing of its profile in some contexts, as described below. At the place where the profile of a callable entity becomes frozen, the entity itself becomes frozen.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0014]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0017-1],ARef=[AI05-0019-1]} @Defn2{Term=[freezing], Sec=(entity caused by the end of an enclosing construct)} The end of a @nt{declarative_part}, @nt{protected_body}, or a declaration of a library package or generic library package, causes @i(freezing) of each entity @Chg{Version=[3],New=[and profile ],Old=[]}declared within it, except for incomplete types. @Defn2{Term=[freezing], Sec=(entity caused by a body)} A noninstance body@Chg{New=[ other than a renames-as-body],Old=[]} causes freezing of each entity @Chg{Version=[3],New=[and profile ],Old=[]}declared before it within the same @nt{declarative_part}@Chg{Version=[3], New=[ that is not an incomplete type; it only causes freezing of an incomplete type if the body is within the immediate scope of the incomplete type],Old=[]}. @begin{Discussion} This is worded carefully to handle nested packages and private types. Entities declared in a nested @nt{package_specification} will be frozen by some containing construct. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0017-1]} An incomplete type declared in the private part of a library @nt{package_specification} can be completed in the body.@Chg{Version=[3],New=[ For other incomplete types (and in the bodies of library packages), the completion of the type will be frozen at the end of the package or @nt{declarative_part}, and that will freeze the incomplete view as well.],Old=[]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0017-1]} @ChgAdded{Version=[3],Text=[The reason we have to worry about freezing of incomplete types is to prevent premature uses of the types in dispatching calls. Such uses may need access to the tag of the type, and the type has to be frozen to know where the tag is stored.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The part about bodies does not say @i{immediately} within. A renaming-as-body does not have this property. Nor does @Chg{Version=[3],New=[an imported body],Old=[a @nt{pragma} Import.]} @end{Ramification} @begin{Reason} The reason bodies cause freezing is because we want @ntf{proper_bodies} and @nt{body_stub}s to be interchangeable @em one should be able to move a @nt{proper_body} to a @nt{subunit}, and vice-versa, without changing the semantics. Clearly, anything that should cause freezing should do so even if it's inside a @nt{proper_body}. However, if we make it a @nt{body_stub}, then the compiler can't see that thing that should cause freezing. So we make @nt{body_stub}s cause freezing, just in case they contain something that should cause freezing. But that means we need to do the same for @ntf{proper_bodies}. Another reason for bodies to cause freezing, there could be an added implementation burden if an entity declared in an enclosing @nt<declarative_part> is frozen within a nested body, since some compilers look at bodies after looking at the containing @nt{declarative_part}. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Note that @ldquote@;body@rdquote includes @nt{null_procedure_declaration}s and @nt{expression_function_declaration}s when those are used as completions, as well as @nt{entry_body}s (see @RefSecNum{Completions of Declarations}). These all cause freezing, along with @nt{proper_body}s and @nt{body_stub}s.]} @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0046],ARef=[AI95-00106-01]} @Leading@RootDefn2{Term=[freezing], Sec=(entity caused by a construct)} A construct that (explicitly or implicitly) references an entity can cause the @i(freezing) of the entity, as defined by subsequent paragraphs. @PDefn2{Term=[freezing], Sec=(by a constituent of a construct)} At the place where a construct causes freezing, each @nt<name>, @Chg{New=[@nt<expression>, @nt<implicit_dereference>], Old=[expression]}@Redundant[, or @nt{range}] within the construct causes freezing: @begin{Ramification} Note that in the sense of this paragraph, a @nt{subtype_mark} @lquotes@;references@rquotes@; the denoted subtype, but not the type. @end{Ramification} @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0213-1]} @PDefn2{Term=[freezing], Sec=(generic_instantiation)} The occurrence of a @nt{generic_instantiation} causes freezing@Chg{Version=[3],New=[, except that a @nt{name} which is a generic actual parameter whose corresponding generic formal parameter is a formal incomplete type (see @RefSecNum{Formal Private and Derived Types}) does not cause freezing. In addition, if],Old=[; also, if]} a parameter of the instantiation is defaulted, the @nt{default_expression} or @nt{default_name} for that parameter causes freezing. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[Thus, an actual parameter corresponding to a formal incomplete type parameter may denote an incomplete or private type which is not completely defined at the point of the @nt{generic_instantiation}.]} @end{Ramification} @PDefn2{Term=[freezing], Sec=(object_declaration)} The occurrence of an @nt<object_declaration> that has no corresponding completion causes freezing. @begin{Ramification} Note that this does not include a @nt{formal_object_declaration}. @end{Ramification} @PDefn2{Term=[freezing], Sec=(subtype caused by a record extension)} The declaration of a record extension causes freezing of the parent subtype. @begin{Ramification} This combined with another rule specifying that primitive subprogram declarations shall precede freezing ensures that all descendants of a tagged type implement all of its dispatching operations. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00251-01]} The declaration of a private extension does not cause freezing. The freezing is deferred until the full type declaration, which will necessarily be for a record extension@Chg{Version=[2],New=[, task, or protected type (the latter only for a limited private extension derived from an interface)], Old=[]}. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[The declaration of a record extension, interface type, task unit, or protected unit causes freezing of any progenitor types specified in the declaration.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[This rule has the same purpose as the one above: ensuring that all descendants of an interface tagged type implement all of its dispatching operations. As with the previous rule, a private extension does not freeze its progenitors; the full type declaration (which must have the same progenitors) will do that.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[An interface type can be a parent as well as a progenitor; these rules are similar so that the location of an interface in a record extension does not have an effect on the freezing of the interface type.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[At the freezing point of the entity associated with an @nt{aspect_specification}, any @nt{expression}s or @nt{name}s within the @nt{aspect_specification} cause freezing. Any static expressions within an @nt{aspect_specification} also cause freezing at the end of the immediately enclosing declaration list.]} @end{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0177-1],ARef=[AI05-0183-1]} @PDefn2{Term=[freezing], Sec=(by an expression)} A static expression @Chg{Version=[3],New=[(other than within an @nt{aspect_specification}) ],Old=[]}causes freezing where it occurs. @Chg{New=[@PDefn2{Term=[freezing], Sec=(by an object name)} An object name or],Old=[A]} nonstatic expression causes freezing where it occurs, unless the @Chg{New=[name or ],Old=[]}expression is part of a @nt<default_expression>, a @nt<default_name>, @Chg{Version=[3],New=[the @nt{expression} of an expression function, an @nt{aspect_specification}, ],Old=[]}or a per-object expression of a component's @nt{constraint}, in which case, the freezing occurs later as part of another construct@Chg{Version=[3],New=[ or at the freezing point of an associated entity],Old=[]}. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0019-1]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=[freezing], Sec=(by an implicit call)} An implicit call freezes the same entities @Chg{Version=[3],New=[and profiles ],Old=[]}that would be frozen by an explicit call. This is true even if the implicit call is removed via implementation permissions.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=[freezing], Sec=(subtype caused by an implicit conversion)} If an expression is implicitly converted to a type or subtype @i(T), then at the place where the expression causes freezing, @i(T) is frozen.]} @Leading@;The following rules define which entities are frozen at the place where a construct causes freezing: @begin{Itemize} @Leading@PDefn2{Term=[freezing], Sec=(type caused by an expression)} At the place where an expression causes freezing, the type of the expression is frozen, unless the expression is an enumeration literal used as a @nt{discrete_choice} of the @nt{array_@!aggregate} of an @nt{enumeration_@!representation_@!clause}. @begin{Reason} We considered making enumeration literals never cause freezing, which would be more upward compatible, but examples like the variant record aggregate (Discrim => Red, ...) caused us to change our mind. Furthermore, an enumeration literal is a static expression, so the implementation should be allowed to represent it using its representation. @end{Reason} @begin{Ramification} @Leading@;The following pathological example was legal in Ada 83, but is illegal in Ada 95: @begin{Example} @key[package] P1 @key[is] @key[type] T @key[is] @key[private]; @key[package] P2 @key[is] @key[type] Composite(D : Boolean) @key[is] @key[record] @key[case] D @key[is] @key[when] False => Cf : Integer; @key[when] True => Ct : T; @key[end] @key[case]; @key[end] @key[record]; @key[end] P2; X : Boolean := P2."="( (False,1), (False,1) ); @key[private] @key[type] T @key[is] @key[array](1..Func_Call) @key[of] Integer; @key[end]; @end{Example} In Ada 95, the declaration of X freezes Composite (because it contains an expression of that type), which in turn freezes T (even though Ct does not exist in this particular case). But type T is not completely defined at that point, violating the rule that a type shall be completely defined before it is frozen. In Ada 83, on the other hand, there is no occurrence of the name T, hence no forcing occurrence of T. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0019-1],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[freezing], Sec=(profile of a function call)} @PDefn2{Term=[freezing], Sec=(expression of an expression function by a call)} At the place where a function call causes freezing, the profile of the function is frozen. Furthermore, if a parameter of the call is defaulted, the @nt{default_expression} for that parameter causes freezing. If the function call is to an expression function, the @nt{expression} of the expression function causes freezing.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0019-1]} @ChgAdded{Version=[3],Text=[This is the important rule for profile freezing: a call freezes the profile. That's because generating the call will need to know how the parameters are passed, and that will require knowing details of the types. Other uses of subprograms do not need to know about the parameters, and thus only freeze the subprogram, and not the profile.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that we don't need to consider procedure or entry calls, since a body freezes everything that precedes it, and the end of a declarative part freezes everything in the declarative part.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Freezing of the @nt{expression} of an expression function only needs to be considered when the expression function is in the same compilation unit and there are no intervening bodies; the end of a declarative_part or library package freezes everything in it, and a body freezes everything declared before it.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0019-1],ARef=[AI05-0177-1],ARef=[AI05-0296-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[freezing], Sec=(profile of a callable entity by an instantiation)} @PDefn2{Term=[freezing], Sec=(expression of an expression function by an instantiation)} At the place where a @nt{generic_instantiation} causes freezing of a callable entity, the profile of that entity is frozen unless the formal subprogram corresponding to the callable entity has a parameter or result of a formal untagged incomplete type; if the callable entity is an expression function, the @nt{expression} of the expression function causes freezing.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Elaboration of the generic might call the actual for one of its formal subprograms, so we need to know the profile and (for an expression function) @nt{expression}.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[freezing], Sec=(expression of an expression function by Access attribute)} At the place where a use of the Access or Unchecked_Access attribute whose @nt{prefix} denotes an expression function causes freezing, the @nt{expression} of the expression function causes freezing.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[This is needed to avoid calls to unfrozen expressions. Consider:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] Pack @key[is]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] Flub @key[is range] 0 .. 100;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] Foo (A : @key[in] Natural) @key[return] Natural @key[is] (A + Flub'Size); -- @Examcom[The expression is not frozen here.]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] Bar @key[is access function] Foo (A : @key[in] Natural) @key[return] Natural;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ P : Bar := Foo'Access; -- @Examcom[(A)]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ Val : Natural := P.@key[all](5); -- @Examcom[(B)]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[end Pack;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If point (A) did not freeze the expression of Foo (which freezes Flub), then the call at point (B) would be depending on the aspects of the unfrozen type Flub. That would be bad.]} @end{Reason} @Leading@PDefn2{Term=[freezing], Sec=(entity caused by a name)} At the place where a @nt<name> causes freezing, the entity denoted by the @nt<name> is frozen, unless the @nt<name> is a @nt<prefix> of an expanded name; @PDefn2{Term=[freezing], Sec=(nominal subtype caused by a name)} at the place where an object @nt{name} causes freezing, the nominal subtype associated with the @nt<name> is frozen. @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This only matters in the presence of deferred constants or access types; an @nt{object_declaration} other than a @Chg{Version=[2],New=[deferred constant declaration],Old=[@ntf{deferred_constant_declaration}]} causes freezing of the nominal subtype, plus all component junk. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgDeleted{Version=[1],Text=[@nt{Implicit_dereference}s are covered by @nt{expression}.]} @Comment{This statement is just plain wrong.} @end{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0046],ARef=[AI95-00106-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[@PDefn2{Term=[freezing], Sec=(subtype caused by an implicit dereference)} At the place where an @nt{implicit_dereference} causes freezing, the nominal subtype associated with the @nt{implicit_dereference} is frozen.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule ensures that X.D freezes the same entities that X.@key{all}.D does. Note that an @nt{implicit_dereference} is neither a @nt{name} nor @nt{expression} by itself, so it isn't covered by other rules.]} @end{Discussion} @Leading@Redundant[@PDefn2{Term=[freezing], Sec=(type caused by a range)} At the place where a @nt{range} causes freezing, the type of the @nt<range> is frozen.] @begin{TheProof} This is consequence of the facts that expressions freeze their type, and the Range attribute is defined to be equivalent to a pair of expressions separated by @lquotes@;..@rquotes@;.} @end{TheProof} @Leading@PDefn2{Term=[freezing], Sec=(designated subtype caused by an allocator)} At the place where an @nt<allocator> causes freezing, the designated subtype of its type is frozen. If the type of the @nt<allocator> is a derived type, then all ancestor types are also frozen. @begin{Ramification} @nt{Allocator}s also freeze the named subtype, as a consequence of other rules. @Leading@;The ancestor types are frozen to prevent things like this: @begin{Example} @key[type] Pool_Ptr @key[is] @key[access] System.Storage_Pools.Root_Storage_Pool'Class; @key[function] F @key[return] Pool_Ptr; @key[package] P @key[is] @key[type] A1 @key[is] @key[access] Boolean; @key[type] A2 @key[is] @key[new] A1; @key[type] A3 @key[is] @key[new] A2; X : A3 := @key[new] Boolean; --@RI{ Don't know what pool yet!} @key[for] A1'Storage_Pool @key[use] F.all; @key[end] P; @end{Example} This is necessary because derived access types share their parent's pool. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0019-1]} @Leading@PDefn2{Term=[freezing], Sec=(subtypes of the profile of a callable entity)} At the place where a @Chg{Version=[3],New=[profile],Old=[callable entity]} is frozen, each subtype of @Chg{Version=[3],New=[the],Old=[its]} profile is frozen. If the @Chg{Version=[3],New=[corresponding ],Old=[]}callable entity is a member of an entry family, the index subtype of the family is frozen.@Chg{Version=[3],New=[],Old=[ @PDefn2{Term=[freezing], Sec=(function call)} At the place where a function call causes freezing, if a parameter of the call is defaulted, the @nt{default_@!expression} for that parameter causes freezing.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Deleted]}@Comment{Moved above with rule} @ChgDeleted{Version=[3],Text=[We don't worry about freezing for procedure calls or entry calls, since a body freezes everything that precedes it, and the end of a declarative part freezes everything in the declarative part.]} @end{Discussion} @Leading@PDefn2{Term=[freezing], Sec=[type caused by the freezing of a subtype]} At the place where a subtype is frozen, its type is frozen. @PDefn2{Term=[freezing], Sec=(constituents of a full type definition)} @PDefn2{Term=[freezing], Sec=(first subtype caused by the freezing of the type)} At the place where a type is frozen, any expressions or @nt<name>s within the full type definition cause freezing; the first subtype, and any component subtypes, index subtypes, and parent subtype of the type are frozen as well. @PDefn2{Term=[freezing], Sec=(class-wide type caused by the freezing of the specific type)} @PDefn2{Term=[freezing], Sec=(specific type caused by the freezing of the class-wide type)} For a specific tagged type, the corresponding class-wide type is frozen as well. For a class-wide type, the corresponding specific type is frozen as well. @begin{Ramification} Freezing a type needs to freeze its first subtype in order to preserve the property that the subtype-specific aspects of statically matching subtypes are the same. Freezing an access type does not freeze its designated subtype. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00341-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0019-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[At the place where a specific tagged type is frozen, the primitive subprograms of the type are frozen.@Chg{Version=[3],New=[ At the place where a type is frozen, any subprogram named in an @nt{attribute_definition_clause} for the type is frozen.],Old=[]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have a language design principle that all of the details of a specific tagged type are known at its freezing point. But that is only true if the primitive subprograms are frozen at this point as well. Late changes of Import and address clauses violate the principle.]} @end{Reason} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule means that no implicit call to Initialize or Adjust can freeze a subprogram (the type and thus subprograms would have been frozen at worst at the same point).]} @end{ImplNote} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0019-1]} @ChgAdded{Version=[3],Text=[The second sentence is the rule that makes it possible to check that only subprograms with convention Ada are specified in @nt{attribute_definition_clause}s without jumping through hoops.]} @end{Discussion} @end{Itemize} @end{Intro} @begin{Legality} @Comment{"Leading" below is to get the last paragraph onto the page with everything else.} @Leading@Redundant[The explicit declaration of a primitive subprogram of a tagged type shall occur before the type is frozen (see @RefSecNum{Dispatching Operations of Tagged Types}).] @begin{Reason} This rule is needed because (1) we don't want people dispatching to things that haven't been declared yet, and (2) we want to allow tagged type descriptors to be static (allocated statically, and initialized to link-time-known symbols). Suppose T2 inherits primitive P from T1, and then overrides P. Suppose P is called @i{before} the declaration of the overriding P. What should it dispatch to? If the answer is the new P, we've violated the first principle above. If the answer is the old P, we've violated the second principle. (A call to the new one necessarily raises Program_Error, but that's beside the point.) Note that a call upon a dispatching operation of type @i(T) will freeze @i(T). We considered applying this rule to all derived types, for uniformity. However, that would be upward incompatible, so we rejected the idea. As in Ada 83, for an untagged type, the above call upon P will call the old P (which is arguably confusing). @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0222-1]} @ChgAdded{Version=[3],Text=[This rule only applies to "original" declarations and not to the completion of a primitive subprogram, even though a completion is technically an explicit declaration, and it may declare a primitive subprogram.]} @end{Honest} @Leading@Redundant[A type shall be completely defined before it is frozen (see @RefSecNum{Completions of Declarations} and @RefSecNum{Private Types and Private Extensions}).] @Leading@Redundant[The completion of a deferred constant declaration shall occur before the constant is frozen (see @RefSecNum{Deferred Constants}).] @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The above @LegalityTitle are stated @lquotes@;officially@rquotes@; in the referenced @Chg{Version=[3],New=[subclauses],Old=[clauses]}.]} @end{TheProof} @Leading@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[An operational or],Old=[A]} representation item that directly specifies an aspect of an entity shall appear before the entity is frozen (see @RefSecNum{Operational and Representation Aspects}). @ChgNote{A last minute change (requested by WG9) moved this rule to 13.1(9). However, the rule there only covers types and subtypes. So this rule is not redundant, and I removed the @Redundant for it. I don't have a way to mark that as a change, so it is just gone. RLB-29-08-00} @begin{Discussion} @comment{The following is a "fix" to keep consistent with v. 5.95; appearently 6.0 is different. @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Old @b{Change}.]}} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} From RM83-13.1(7). The wording here forbids freezing within the @Chg{New=[@nt{aspect_clause}],Old=[@nt{representation_clause}]} itself, which was not true of the Ada 83 wording. The wording of this rule is carefully written to work properly for type-related representation items. For example, an @nt{enumeration_@!representation_@!clause} is illegal after the type is frozen, even though the @ntf{_clause} refers to the first subtype. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[The above @LegalityName is stated for types and subtypes in @RefSecNum{Operational and Representation Aspects}, but the rule here covers all other entities as well.]} @end{Discussion} @begin{TheProof} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[The above @LegalityTitle are stated @lquotes@;officially@rquotes@; in the referenced clauses.]} @end{TheProof} @begin{Discussion} @Leading@;Here's an example that illustrates when freezing occurs in the presence of defaults: @begin{Example} @key[type] T @key[is] ...; @key[function] F @key[return] T; @key[type] R @key[is] @key[record] C : T := F; D : Boolean := F = F; @key[end] @key[record]; X : R; @end{Example} Since the elaboration of R's declaration does not allocate component C, there is no need to freeze C's subtype at that place. Similarly, since the elaboration of R does not evaluate the @nt{default_expression} @lquotes@;F = F@rquotes@;, there is no need to freeze the types involved at that point. However, the declaration of X @i{does} need to freeze these things. Note that even if component C did not exist, the elaboration of the declaration of X would still need information about T @em even though D is not of type T, its @nt{default_expression} requires that information. @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Although we define freezing in terms of the program text as a whole (i.e. after applying the rules of @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Program Structure and Compilation Issues}), the freezing rules actually have no effect beyond compilation unit boundaries. @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} That is important, because @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Program Structure and Compilation Issues} allows some implementation definedness in the order of things, and we don't want the freezing rules to be implementation defined. @end{Reason} @begin{Ramification} These rules also have no effect in @nt{statement}s @em they only apply within a single @nt{declarative_part}, @nt{package_specification}, @nt{task_definition}, @nt{protected_definition}, or @nt{protected_body}. @end{Ramification} @begin{ImplNote} An implementation may choose to generate code for @nt{default_expression}s and @nt{default_name}s in line at the place of use. @Defn{thunk} Alternatively, an implementation may choose to generate thunks (subprograms implicitly generated by the compiler) for evaluation of defaults. Thunk generation cannot, in general, be done at the place of the declaration that includes the default. Instead, they can be generated at the first freezing point of the type(s) involved. (It is impossible to write a purely one-pass Ada compiler, for various reasons. This is one of them @em the compiler needs to store a representation of defaults in its symbol table, and then walk that representation later, no earlier than the first freezing point.) In implementation terms, the linear elaboration model can be thought of as preventing uninitialized dope. For example, the implementation might generate dope to contain the size of a private type. This dope is initialized at the place where the type becomes completely defined. It cannot be initialized earlier, because of the order-of-elaboration rules. The freezing rules prevent elaboration of earlier declarations from accessing the size dope for a private type before it is initialized. @RefSecNum{Pragmas} overrides the freezing rules in the case of unrecognized @nt{pragma}s. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0009],ARef=[AI95-00137-01]} @Chg{New=[An @nt{aspect_clause}],Old=[A @nt{representation_clause}]} for an entity should most certainly @i{not} be a freezing point for the entity. @end{ImplNote} @end{Legality} @begin{RunTime} @ChgNote{This is the last normative paragraph in the subclause} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[The tag (see @RefSecNum{Tagged Types and Type Extensions}) of a tagged type T is created at the point where T is frozen.@PDefn2{Term=[creation],Sec=[of a tag]}]} @end{RunTime} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} RM83 defines a forcing occurrence of a type as follows: @lquotes@;A forcing occurrence is any occurrence [of the name of the type, subtypes of the type, or types or subtypes with subcomponents of the type] other than in a type or subtype declaration, a subprogram specification, an entry declaration, a deferred constant declaration, a @nt{pragma}, or a @ntf{representation_clause} for the type itself. In any case, an occurrence within an expression is always forcing.@rquotes@; @Leading@;It seems like the wording allows things like this: @begin{Example} @key[type] A @key[is] @key[array](Integer @key[range] 1..10) @key[of] Boolean; @key[subtype] S @key[is] Integer @key[range] A'Range; --@RI{ not forcing for A} @end{Example} Occurrences within @nt{pragma}s can cause freezing in Ada 95. (Since such @nt{pragma}s are ignored in Ada 83, this will probably fix more bugs than it causes.) @end{Incompatible83} @begin{Extend83} @Leading@;@Defn{extensions to Ada 83} In Ada 95, @nt{generic_formal_parameter_declaration}s do not normally freeze the entities from which they are defined. For example: @begin{example} @key[package] Outer @key[is] @key[type] T @key[is] @key[tagged] @key[limited] @key[private]; @key[generic] @key[type] T2 @key[is] @key[new] T @key[with] @key[private]; --@RI{ Does not freeze T} --@RI{ in Ada 95.} @key[package] Inner @key[is] ... @key[end] Inner; @key[private] @key[type] T @key[is] ...; @key[end] Outer; @end{example} This is important for the usability of generics. The above example uses the Ada 95 feature of formal derived types. Examples using the kinds of formal parameters already allowed in Ada 83 are well known. See, for example, comments 83-00627 and 83-00688. The extensive use expected for formal derived types makes this issue even more compelling than described by those comments. Unfortunately, we are unable to solve the problem that @nt{explicit_generic_actual_parameter}s cause freezing, even though a package equivalent to the instance would not cause freezing. This is primarily because such an equivalent package would have its body in the body of the containing program unit, whereas an instance has its body right there. @end{Extend83} @begin{DiffWord83} The concept of freezing is based on Ada 83's concept of @lquotes@;forcing occurrences.@rquotes@; The first freezing point of an entity corresponds roughly to the place of the first forcing occurrence, in Ada 83 terms. The reason for changing the terminology is that the new rules do not refer to any particular @lquotes@;occurrence@rquotes@; of a name of an entity. Instead, we refer to @lquotes@;uses@rquotes@; of an entity, which are sometimes implicit. In Ada 83, forcing occurrences were used only in rules about @ntf{representation_clause}s. We have expanded the concept to cover private types, because the rules stated in RM83-7.4.1(4) are almost identical to the forcing occurrence rules. @Leading@;The Ada 83 rules are changed in Ada 95 for the following reasons: @begin{Itemize} The Ada 83 rules do not work right for subtype-specific aspects. In an earlier version of Ada 9X, we considered allowing representation items to apply to subtypes other than the first subtype. This was part of the reason for changing the Ada 83 rules. However, now that we have dropped that functionality, we still need the rules to be different from the Ada 83 rules. The Ada 83 rules do not achieve the intended effect. In Ada 83, either with or without the AIs, it is possible to force the compiler to generate code that references uninitialized dope, or force it to detect erroneousness and exception raising at compile time. It was a goal of Ada 83 to avoid uninitialized access values. However, in the case of deferred constants, this goal was not achieved. The Ada 83 rules are not only too weak @em they are also too strong. They allow loopholes (as described above), but they also prevent certain kinds of @nt{default_expression}s that are harmless, and certain kinds of @nt{generic_declaration}s that are both harmless and very useful. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Ada 83 had a case where @Chg{Version=[2],New=[an @nt{aspect_clause}], Old=[a @nt{representation_clause}]} had a strong effect on the semantics of the program @em 'Small. This caused certain semantic anomalies. There are more cases in Ada 95, because the @Chg{Version=[2],New=[@nt{attribute_definition_clause}], Old=[@ntf{attribute_representation_clause}]} has been generalized. @end{Itemize} @end{DiffWord83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0046],ARef=[AI95-00106-01],ARef=[AI95-00341-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b<Corrigendum:> Various freezing rules were added to fix holes in the rules. Most importantly, implicit calls are now freezing, which make some representation clauses illegal in Ada 2005 that were legal (but dubious) in Ada 95. @b[Amendment Correction:] Similarly, the primitive subprograms of a specific tagged type are frozen when the type is frozen, preventing dubious convention changes (and address clauses) after the freezing point. In both cases, the code is dubious and the workaround is easy.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0009],ARef=[AI95-00137-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to specify that both operational and representation attributes must be specified before the type is frozen.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00251-01]} @ChgAdded{Version=[2],Text=[Added wording that declaring a specific descendant of an interface type freezes the interface type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00279-01]} @ChgAdded{Version=[2],Text=[Added wording that defines when a tag is created for a type (at the freezing point of the type). This is used to specify checking for uncreated tags (see @RefSecNum{Tagged Types and Type Extensions}).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0019-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 95}@b<Correction:> Separated the freezing of the profile from the rest of a subprogram, in order to reduce the impact of the Ada 95 incompatibility noted above. (The effects were much more limiting than expected.)]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0017-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Reworded so that incomplete types with a deferred completion aren't prematurely frozen.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0177-1]} @ChgAdded{Version=[3],Text=[Added freezing rules for expression functions; these are frozen at the point of call, not the point of declaration, like default expressions.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0183-1]} @ChgAdded{Version=[3],Text=[Added freezing rules for @nt{aspect_specification}s; these are frozen at the freezing point of the associated entity, not the point of declaration.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0213-1]} @ChgAdded{Version=[3],Text=[Added freezing rules for formal incomplete types; the corresponding actual is not frozen.]} @end{DiffWord2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/aarm.msm�������������������������������������������������������������0000755�0001752�0001001�00000014545�12273462240�017066� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the AARM} @Comment{Global properties} @Comment{@ShowIndexEntries @Comment{To match the Ada 95 AARM}} @HideIndexEntries @Comment{As recommended by the ARG (Feb. 2011)} @ShowAnnotations @HideISO @NumberParagraphs @LinkNonTerminals @Title{Version=[0],Text=[Annotated Ada Reference Manual]}@Comment{Same title for all versions} @FilePrefix{AA} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @SubdivisionNames{Clause}@Comment{For Ada 95 and 2005, use "section" instead} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @RTFHeaderPrefix{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @RTFHeaderPrefix{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]} @RTFHeaderPrefix{Version=[3],Text=[ISO/IEC 8652:2012(E)]} @RTFFooter{UseDate=[T],UseClauseName=[T],UseISOFormat=[F]}@Comment{RM style footers} @RTFPageSize{Letter} @RTFFonts{Serif=[Times],SansSerif=[Arial]} @RTFVersionName{Version=[0],Text=[Original Text]} @RTFVersionName{Version=[1],Text=[Technical Corrigendum 1]} @RTFVersionName{Version=[2],Text=[Amendment 1]} @RTFVersionName{Version=[3],Text=[Ada 2012]} @Comment{HTML properties} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]}@Comment{Was "4Comp" for the Consolidated AARM} @HTMLNavBar{RefName=[AA-STDS.html],SrchName=[AA-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><B><SPAN Style="font-size:200%; color: rgb(0,51,153)">Annotated</SPAN><SPAN Style="font-size:200%; color: rgb(0,0,102)"> Ada Reference Manual</SPAN></B> — <A HREF="AA-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="vertical-align: middle; font-size:120%">Ada 2005 and 2012 Editions sponsored in part by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Con2.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Locales.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO used to require skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO used to require skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} �����������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/ansi_cover.mss�������������������������������������������������������0000755�0001752�0001001�00000005020�12066652506�020276� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(ansicover, Root="ada.mss") @Define(I2Title, Copy TitlePage, Sink 8.5in, Font HeadingFont) @Define(I2TBox, Copy TitleBox, Fixed 2.5inches) @Define(I2Credit, Copy ResearchCredit, Fixed 9inches) @Define(I2CRNotice, Copy CopyrightNotice, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @Define(I2CR, Copy Copyright, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @comment{$Source: e:\\cvsroot/ARM/Source/ansi_cover.mss,v $} @comment{$Revision: 1.12 $ $Date: 2000/05/27 04:44:03 $} @begin(I2Title) @begin{FlushRight, Fixed 0.75inch} @Case{DocumentNickname, RM9X= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], ISO= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], else= [ISO/IEC JTC1/SC22 WG9 N 193]} @end{FlushRight} @begin(I2TBox) @String{OfficialPrefix="Proposed ANSI/ISO Standard" for Information Technology Programming Languages"} @Case{DocumentNickname, RM9X=[@Heading{@Value{OfficialPrefix}}], ISO=[@Heading{@Value{OfficialPrefix}}], else=[@Value{OfficialPrefix}]} @MajorHeading{Programming Language Ada} @Comment{We got the above mouthful in a mail message from Bob Mathis on 8 Sep 1993.} @Heading{Language and Standard Libraries} @Case{DocumentNickname, RM9X=[@i{Draft}], ISO=[@i{Draft}], AARM=[@i{Annotated Draft}], Syntax9X=[@i{Syntax Only Draft}]} Version @Value(Version) @Value(Date) @Value(IRno) @end(I2TBox) Ada 9X Mapping/Revision Team Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 (617) 661-1840 @end(I2Title) @PageHeading() @PageFooting() @comment{case statement: If draft/=2 then it's a public document and use the reprinting permitted copyright. Otherwise use the restricted copyright.} @Case{Draft, 2=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) @end(Center) FOR OFFICIAL USE ONLY in performance of Contract F08635-90-C-0066. This report has been produced under the sponsorship of the Ada 9X Project Office under contract F08635-90-C-0066.", else=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) Reprinting permitted if accompanied by this statement. This work is sponsored by the Ada 9X Project Office under contract F08635-90-C-0066. @end(Center) "}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/ansi_title.mss�������������������������������������������������������0000755�0001752�0001001�00000005036�12066652506�020310� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(ansititle, Root="ada.mss") @Define(I2Title, Copy TitlePage, Sink 8.5in, Font HeadingFont) @Define(I2TBox, Copy TitleBox, Fixed 2.5inches) @Define(I2Credit, Copy ResearchCredit, Fixed 9inches) @Define(I2CRNotice, Copy CopyrightNotice, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @Define(I2CR, Copy Copyright, Fixed 8.5inches, AfterExit "Reprinting permitted if accompanied by this statement") @comment{$Source: e:\\cvsroot/ARM/Source/ansi_title.mss,v $} @comment{$Revision: 1.12 $ $Date: 2000/05/27 04:44:03 $} @begin(I2Title) @begin{FlushRight, Fixed 0.75inch} @Case{DocumentNickname, RM9X= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], ISO= [ANSI/ISO/IEC CD 8652 ISO/IEC JTC1/SC22 N 1451 ISO/IEC JTC1/SC22 WG9 N 191], else= [ISO/IEC JTC1/SC22 WG9 N 193]} @end{FlushRight} @begin(I2TBox) @String{OfficialPrefix="@i(proposed) American National Standard for Information Technology - Programming Languages"} @Case{DocumentNickname, RM9X=[@Heading{@Value{OfficialPrefix}}], ISO=[@Heading{@Value{OfficialPrefix}}], else=[@Value{OfficialPrefix}]} @MajorHeading{Programming Language Ada} @Comment{We got the above mouthful in a mail message from Bob Mathis on 8 Sep 1993.} @Heading{Language and Standard Libraries} @Case{DocumentNickname, RM9X=[@i{Draft}], ISO=[@i{Draft}], AARM=[@i{Annotated Draft}], Syntax9X=[@i{Syntax Only Draft}]} Version @Value(Version) @Value(Date) @Value(IRno) @end(I2TBox) Ada 9X Mapping/Revision Team Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 (617) 661-1840 @end(I2Title) @PageHeading() @PageFooting() @comment{case statement: If draft/=2 then it's a public document and use the reprinting permitted copyright. Otherwise use the restricted copyright.} @Case{Draft, 2=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) @end(Center) FOR OFFICIAL USE ONLY in performance of Contract F08635-90-C-0066. This report has been produced under the sponsorship of the Ada 9X Project Office under contract F08635-90-C-0066.", else=" @PrefaceSection() @begin(center) @BlankSpace(4in) @i(Published by) Intermetrics, Inc. 733 Concord Avenue Cambridge, Massachusetts 02138 @BlankSpace(2.5in) @CopyRightNotice(Intermetrics, Inc.) Reprinting permitted if accompanied by this statement. This work is sponsored by the Ada 9X Project Office under contract F08635-90-C-0066. @end(Center) "}��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/attribs.mss����������������������������������������������������������0000755�0001752�0001001�00000002740�12066652506�017624� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(attribs, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledRevisedInformativeAnnex{Version=[2],New=[Language-Defined Aspects and Attributes],Old=[Language-Defined Attributes]} @comment{$Source: e:\\cvsroot/ARM/Source/attribs.mss,v $} @comment{$Revision: 1.16 $} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[This annex summarizes the definitions given elsewhere of the language-defined aspects and attributes. Some aspects have corresponding attributes, as noted.]} @end{Intro} @LabeledAddedClause{Version=[3],Name=[Language-Defined Aspects]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[@Defn{aspect}This subclause summarizes the definitions given elsewhere of the language-defined aspects. Aspects are properties of entities that can be specified by the Ada program; unless otherwise specified below, aspects can be specified using an @nt{aspect_specification}.]} @AddedAspectList{Version=[3]} @end{Intro} @LabeledAddedClause{Version=[3],Name=[Language-Defined Attributes]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @Defn{attribute}This @Chg{Version=[3],New=[subclause],Old=[annex]} summarizes the definitions given elsewhere of the language-defined attributes.@Chg{Version=[3],New=[ Attributes are properties of entities that can be queried by an Ada program.],Old=[]} @AttributeList @end{Intro}��������������������������������org.adaic.arm_form/source_2012/ds.mss���������������������������������������������������������������0000755�0001752�0001001�00000305324�12066652506�016566� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/ds.mss,v $ } @comment{ $Revision: 1.67 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(dist, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledNormativeAnnex{Distributed Systems} @begin{Intro} @redundant[This Annex defines facilities for supporting the implementation of distributed systems using multiple partitions working cooperatively as part of a single Ada program.] @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{LinkTime} @Defn{processing node} @Defn{storage node} @Defn{distributed system} A @i{distributed system} is an interconnection of one or more @i{processing nodes} (a system resource that has both computational and storage capabilities), and zero or more @i{storage nodes} (a system resource that has only storage capabilities, with the storage addressable by one or more processing nodes). @Defn{distributed program} A @i{distributed program} comprises one or more partitions that execute independently (except when they communicate) in a distributed system. @Defn2{Term=[configuration], Sec=(of the partitions of a program)} The process of mapping the partitions of a program to the nodes in a distributed system is called @i{configuring the partitions of the program}. @end{LinkTime} @begin{ImplReq} The implementation shall provide means for explicitly assigning library units to a partition and for the configuring and execution of a program consisting of multiple partitions on a distributed system; the means are implementation defined. @ImplDef{The means for creating and executing distributed programs.} @end{ImplReq} @begin{ImplPerm} An implementation may require that the set of processing nodes of a distributed system be homogeneous. @end{ImplPerm} @begin{Notes} The partitions comprising a program may be executed on differently configured distributed systems or on a nondistributed system without requiring recompilation. A distributed program may be partitioned differently from the same set of library units without recompilation. The resulting execution is semantically equivalent. A distributed program retains the same type safety as the equivalent single partition program. @end{Notes} @LabeledClause{Partitions} @begin{Intro} @redundant[The partitions of a distributed program are classified as either active or passive.] @end{Intro} @begin{LinkTime} @Defn{active partition} @Defn{passive partition} An @i{active partition} is a partition as defined in @RefSecNum{Program Execution}. A @i{passive partition} is a partition that has no thread of control of its own, whose library units are all preelaborated, and whose data and subprograms are accessible to one or more active partitions. @begin{Discussion} In most situations, a passive partition does not execute, and does not have a @lquotes@;real@rquotes@; environment task. Any execution involved in its elaboration and initialization occurs before it comes into existence in a distributed program (like most preelaborated entities). Likewise, there is no concrete meaning to passive partition termination. @end{Discussion} A passive partition shall include only @nt{library_item}s that either are declared pure or are shared passive (see @RefSecNum{Elaboration Control} and @RefSecNum{Shared Passive Library Units}). An active partition shall be configured on a processing node. A passive partition shall be configured either on a storage node or on a processing node. The configuration of the partitions of a program onto a distributed system shall be consistent with the possibility for data references or calls between the partitions implied by their semantic dependences. @Defn{remote access} Any reference to data or call of a subprogram across partitions is called a @i{remote access}. @begin{Discussion} For example, an active partition that includes a unit with a semantic dependence on the declaration of another RCI package of some other active partition has to be connected to that other partition by some sort of a message passing mechanism. A passive partition that is accessible to an active partition should have its storage addressable to the processor(s) of the active partition. The processor(s) should be able to read and write from/to that storage, as well as to perform @lquotes@;read-modify-write@rquotes@; operations (in order to support entry-less protected objects). @end{Discussion} @end{LinkTime} @begin{RunTime} @Defn2{Term=[elaboration], Sec=(partition)} A @nt{library_item} is elaborated as part of the elaboration of each partition that includes it. If a normal library unit (see @RefSecNum{Categorization of Library Units}) has state, then a separate copy of the state exists in each active partition that elaborates it. @Redundant[The state evolves independently in each such partition.] @begin{Ramification} Normal library units cannot be included in passive partitions. @end{Ramification} @Defn2{Term=[termination], Sec=(of a partition)} @Defn2{Term=[abort], Sec=(of a partition)} @Defn{inaccessible partition} @Defn{accessible partition} @Redundant[An active partition @i{terminates} when its environment task terminates.] A partition becomes @i{inaccessible} if it terminates or if it is @i{aborted}. An active partition is aborted when its environment task is aborted. In addition, if a partition fails during its elaboration, it becomes inaccessible to other partitions. Other implementation-defined events can also result in a partition becoming inaccessible. @ImplDef{Any events that can result in a partition becoming inaccessible.} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} D that denotes a library-level declaration, excepting a declaration of or within a declared-pure library unit]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<D>, AttrName=<Partition_Id>, Text=[Denotes a value of the type @i{universal_integer} that identifies the partition in which D was elaborated. If D denotes the declaration of a remote call interface library unit (see @RefSecNum{Remote Call Interface Library Units}) the given partition is the one where the body of D was elaborated.]} @end{Description} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00226-01]} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for there to be cyclic elaboration dependences between the active partitions of a single distributed program. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The possible effects@Chg{Version=[2],New=[, in each of the partitions involved,],Old=[]} are deadlock during elaboration, or the raising of @Chg{Version=[2],New=[Communication_Error or ],Old=[]}Program_Error@Chg{Version=[2], New=[],Old=[ in one or all of the active partitions involved]}. @end{Bounded} @begin{ImplPerm} An implementation may allow multiple active or passive partitions to be configured on a single processing node, and multiple passive partitions to be configured on a single storage node. In these cases, the scheduling policies, treatment of priorities, and management of shared resources between these partitions are implementation defined. @ImplDef{The scheduling policies, treatment of priorities, and management of shared resources between partitions in certain cases.} An implementation may allow separate copies of an active partition to be configured on different processing nodes, and to provide appropriate interactions between the copies to present a consistent state of the partition to other active partitions. @begin{Ramification} The language does not specify the nature of these interactions, nor the actual level of consistency preserved. @end{Ramification} In an implementation, the partitions of a distributed program need not be loaded and elaborated all at the same time; they may be loaded and elaborated one at a time over an extended period of time. An implementation may provide facilities to abort and reload a partition during the execution of a distributed program. An implementation may allow the state of some of the partitions of a distributed program to persist while other partitions of the program terminate and are later reinvoked. @end{ImplPerm} @begin{Notes} Library units are grouped into partitions after compile time, but before run time. At compile time, only the relevant library unit properties are identified using categorization pragmas. The value returned by the Partition_Id attribute can be used as a parameter to implementation-provided subprograms in order to query information about the partition. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00226-01]} @ChgAdded{Version=[2],Text=[Corrected wording so that a partition that has an elaboration problem will either deadlock or raise an exception. While an Ada 95 implementation could allow some partitions to continue to execute, they could be accessing unelaborated data, which is very bad (and erroneous in a practical sense). Therefore, this isn't listed as an inconsistency.]} @end{DiffWord95} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Categorization of Library Units} @begin{Intro} @redundant[Library units can be categorized according to the role they play in a distributed program. Certain restrictions are associated with each category to ensure that the semantics of a distributed program remain close to the semantics for a nondistributed program.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} @RootDefn{categorization pragma} @RootDefn{pragma, categorization} @PDefn2{Term=[library unit pragma], Sec=(categorization pragmas)} @PDefn2{Term=[pragma, library unit], Sec=(categorization pragmas)} @Chg{Version=[3],New=[@Defn{categorization aspect}],Old=[]}@Defn{categorized library unit} A @i{categorization pragma} is a library unit pragma (see @RefSecNum{Pragmas and Program Units}) that @Chg{Version=[3],New=[specifies a corresponding @i{categorization aspect}. A categorization aspect ],Old=[]}restricts the declarations, child units, or semantic dependences of the library unit to which it applies. A @i{categorized library unit} is a library unit @Chg{Version=[3],New=[that has a categorization aspect that is True],Old=[to which a categorization pragma applies]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} The pragmas Shared_Passive, Remote_Types, and Remote_Call_Interface are categorization pragmas@Chg{Version=[3],New=[, and the associated aspects are categorization aspects],Old=[]}. In addition, for the purposes of this Annex, the @Chg{Version=[3],New=[aspect Pure (see @RefSecNum{Elaboration Control}) is considered a categorization aspect and the],Old=[]} pragma Pure @Chg{Version=[3],New=[],Old=[(see @RefSecNum{Elaboration Control}) ]}is considered a categorization pragma. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} @Redundant[@Defn{shared passive library unit} A library package or generic library package is called a @i{shared passive} library unit if @Chg{Version=[3],New=[the],Old=[a]} Shared_Passive @Chg{Version=[3],New=[aspect of the unit is True],Old=[pragma applies to it]}. @Defn{remote types library unit} A library package or generic library package is called a @i{remote types} library unit if @Chg{Version=[3],New=[the],Old=[a]} Remote_Types @Chg{Version=[3],New=[aspect of the unit is True],Old=[pragma applies to it]}. @Defn{remote call interface} A library @Chg{New=[unit],Old=[package or generic library package]} is called a @i{remote call interface} if @Chg{Version=[3],New=[the],Old=[a]} Remote_Call_Interface @Chg{Version=[3],New=[aspect of the unit is True],Old=[pragma applies to it]}.] @Defn{normal library unit} A @i{normal library unit} is one @Chg{Version=[3],New=[for],Old=[to]} which no categorization @Chg{Version=[3],New=[aspect is True],Old=[pragma applies]}. @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[These terms (other than @ldquote@;normal library unit@rdquote) are really defined in the following subclauses.]} @end{TheProof} @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[1],Text=[A library subprogram can be a remote call interface, but it cannot be a remote types or shared passive library unit.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0206-1],ARef=[AI05-0243-1],ARef=[AI05-0269-1],ARef=[AI05-0299-1]} @redundant[The various categories of library units and the associated restrictions are described in this @Chg{Version=[3],New=[and the following], Old=[clause and its]} subclauses. The categories are related hierarchically in that the library units of one category can depend semantically only on library units of that category or an earlier one@Chg{Version=[3],New=[ in the hierarchy],Old=[]}, except that the body of a remote types or remote call interface library unit is unrestricted@Chg{Version=[3],New=[, the declaration of a remote types or remote call interface library unit may depend on preelaborated normal library units that are mentioned only in private with clauses, and all categories can depend on limited views],Old=[]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1],ARef=[AI05-0269-1]} @Leading@;The overall hierarchy (including declared pure) is as follows@Chg{Version=[3],New=[, with a lower-numbered category being @ldquote@;earlier in the hierarchy@rdquote in the sense of the previous paragraph],Old=[]}: @begin{Enumerate} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Declared Pure]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Shared Passive]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Remote Types]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Remote Call Interface]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Normal (no restrictions)]} @end{Enumerate} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 7 through 11 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Description} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0243-1]} @ChgDeleted{Version=[3],Text=[Declared Pure @\Can depend only on other declared pure library units;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0243-1]} @ChgDeleted{Version=[3],Text=[Shared Passive @\Can depend only on other shared passive or declared pure library units;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0206-1],ARef=[AI05-0243-1]} @ChgDeleted{Version=[3],Text=[Remote Types @\The declaration of the library unit can depend only on other remote types library units, or one of the above library unit categories, or limited views, or preelaborated normal library units that are mentioned only in private with clauses; the body of the library unit is unrestricted;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0206-1],ARef=[AI05-0243-1]} @ChgDeleted{Version=[3],Text=[Remote Call Interface @\The declaration of the library unit can depend only on other remote call interfaces, or one of the above; the body of the library unit is unrestricted;]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0243-1]} @ChgDeleted{Version=[3],Text=[Normal @\Unrestricted.]} @end{Description} Declared pure and shared passive library units are preelaborated. The declaration of a remote types or remote call interface library unit is required to be preelaborable. ] @end{Intro} @begin{ImplReq} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0079],ARef=[AI95-00208-01]} @ChgDeleted{Version=[1],Text=[For a given library-level type declared in a preelaborated library unit or in the declaration of a remote types or remote call interface library unit, the implementation shall choose the same representation for the type upon each elaboration of the type's declaration for different partitions of the same program.]} @end{ImplReq} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 13 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{ImplPerm} Implementations are allowed to define other categorization pragmas. @end{ImplPerm} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that a library subprogram can be a remote call interface unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0079],ARef=[AI95-00208-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Removed the requirement that types be represented the same in all partitions, because it prevents the definition of heterogeneous distributed systems and goes much further than required.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0206-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[We now allow private withs of preelaborated units in Remote Types and Remote Call Interface units; this is documented as an extension in the subclauses where this is defined normatively.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[We have introduced categorization aspects; these are documented as extensions in the subclauses where they actually are defined.]} @end{DiffWord2005} @LabeledSubClause{Shared Passive Library Units} @begin{Intro} @redundant[A shared passive library unit is used for managing global data shared between active partitions. The restrictions on shared passive library units prevent the data or tasks of one active partition from being accessible to another active partition through references implicit in objects declared in the shared passive library unit.] @end{Intro} @begin{MetaRules} The restrictions governing a shared passive library unit are designed to ensure that objects and subprograms declared in the package can be used safely from multiple active partitions, even though the active partitions live in different address spaces, and have separate run-time systems. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Shared_Passive)} @PDefn2{Term=[pragma, categorization], Sec=(Shared_Passive)} The form of a @nt{pragma} Shared_Passive is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Shared_Passive)[(@SynI{library_unit_}@Syn2{name})];' @end{Syntax} @begin{Legality} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} @Defn{shared passive library unit} A@Chg{Version=[3],New=[ @nt{pragma} Shared_Passive is used to specify that a library unit is a],Old=[]} @i{shared passive library unit}@Chg{Version=[3],New=[, namely that the],Old=[ is a library unit to which a]} Shared_Passive @Chg{Version=[3],New=[aspect@AspectDefn{Shared_Passive} of the library unit is True],Old=[pragma applies]}. The following restrictions apply to such a library unit: @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Shared_Passive], Text=[@ChgAdded{Version=[3],Text=[A given package is used to represent shared memory in a distributed system.]}]} @begin{itemize} @Redundant[it shall be preelaborable (see @RefSecNum{Elaboration Control});] @begin{Ramification} It cannot contain library-level declarations of protected objects with entries, nor of task objects. Task objects are disallowed because passive partitions don't have any threads of control of their own, nor any run-time system of their own. Protected objects with entries are disallowed because an entry queue contains references to calling tasks, and that would require in effect a pointer from a passive partition back to a task in some active partition. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} it shall depend semantically only upon declared pure or shared passive @Chg{Version=[3],New=[@nt{library_item}s],Old=[library units]}; @begin{Reason} Shared passive packages cannot depend semantically upon remote types packages because the values of an access type declared in a remote types package refer to the local heap of the active partition including the remote types package. @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[We say @nt{library_item} here, so that limited views are allowed; those are not library units, but they are @nt{library_item}.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0080],ARef=[AI95-00003-01]} it shall not contain a library-level declaration of an access type that designates a class-wide type, task type, or protected type with @nt{entry_declaration}s@Chg{New=[], Old=[; if the shared passive library unit is generic, it shall not contain a declaration for such an access type unless the declaration is nested within a body other than a @nt<package_body>]}. @begin{Reason} These kinds of access types are disallowed because the object designated by an access value of such a type could contain an implicit reference back to the active partition on whose behalf the designated object was created. @end{Reason} @end{itemize} @PDefn2{Term=[accessibility], Sec=(from shared passive library units)} @Defn{notwithstanding} Notwithstanding the definition of accessibility given in @RefSecNum(Operations of Access Types), the declaration of a library unit P1 is not accessible from within the declarative region of a shared passive library unit P2, unless the shared passive library unit P2 depends semantically on P1. @begin{Discussion} We considered a more complex rule, but dropped it. This is the simplest rule that recognizes that a shared passive package may outlive some other library package, unless it depends semantically on that package. In a nondistributed program, all library packages are presumed to have the same lifetime. Implementations may define additional pragmas that force two library packages to be in the same partition, or to have the same lifetime, which would allow this rule to be relaxed in the presence of such pragmas. @end{Discussion} @end{Legality} @begin{StaticSem} @PDefn{preelaborated} A shared passive library unit is preelaborated. @end{StaticSem} @begin{LinkTime} A shared passive library unit shall be assigned to at most one partition within a given program. @PDefn2{Term=[compilation units needed], Sec=(shared passive library unit)} @PDefn2{Term=[needed], Sec=(shared passive library unit)} @Defn{notwithstanding} Notwithstanding the rule given in @RefSecNum{Program Execution}, a compilation unit in a given partition does not @i{need} (in the sense of @RefSecNum{Program Execution}) the shared passive library units on which it depends semantically to be included in that same partition; they will typically reside in separate passive partitions. @end{LinkTime} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0080],ARef=[AI95-00003-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to allow access types in blocks in shared passive generic packages.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Shared_Passive is now a categorization aspect, so it can be specified by an @nt{aspect_specification} @em although the pragma is still preferred by the Standard.]} @end{Extend2005} @LabeledSubClause{Remote Types Library Units} @begin{Intro} @redundant[A remote types library unit supports the definition of types intended for use in communication between active partitions.] @end{Intro} @begin{MetaRules} The restrictions governing a remote types package are similar to those for a declared pure package. However, the restrictions are relaxed deliberately to allow such a package to contain declarations that violate the stateless property of pure packages, though it is presumed that any state-dependent properties are essentially invisible outside the package. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Remote_Types)} @PDefn2{Term=[pragma, categorization], Sec=(Remote_Types)} The form of a @nt{pragma} Remote_Types is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Remote_Types)[(@SynI{library_unit_}@Syn2{name})];' @end{Syntax} @begin{Legality} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} @Defn{remote types library unit} A@Chg{Version=[3],New=[ @nt{pragma} Remote_Types is used to specify that a library unit is a],Old=[]} @i{remote types library unit}@Chg{Version=[3],New=[, namely that the],Old=[ is a library unit to which the pragma]} Remote_Types @Chg{Version=[3],New=[aspect@AspectDefn{Remote_Types} of the library unit is True],Old=[applies]}. The following restrictions apply to the declaration of such a library unit: @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Remote_Types], Text=[@ChgAdded{Version=[3],Text=[Types in a given package may be used in remote procedure calls.]}]} @begin{itemize} @Redundant[it shall be preelaborable;] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0206-1],ARef=[AI05-0243-1]} it shall depend semantically only on declared pure@Chg{Version=[3],New=[ @nt{library_item}s],Old=[]}, shared passive@Chg{Version=[3],New=[ library units],Old=[]}, @Chg{Version=[3],New=[],Old=[or ]}other remote types library units@Chg{Version=[3],New=[, or preelaborated normal library units that are mentioned only in private with clauses],Old=[]}; @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[We say declared pure @nt{library_item} here, so that (all) limited views are allowed; those are not library units, but they are declared pure @nt{library_item}s.]} @end{Ramification} it shall not contain the declaration of any variable within the visible part of the library unit; @begin{Reason} This is essentially a @lquotes@;methodological@rquotes@; restriction. A separate copy of a remote types package is included in each partition that references it, just like a normal package. Nevertheless, a remote types package is thought of as an @lquotes@;essentially pure@rquotes@; package for defining types to be used for interpartition communication, and it could be misleading to declare visible objects when no remote data access is actually being provided. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} @Chg{Version=[2],New=[],Old=[if ]}the full view of @Chg{Version=[2],New=[each],Old=[a]} type declared in the visible part of the library unit @Chg{Version=[2],New=[that has any available stream attributes shall support external streaming (see @RefSecNum{Stream-Oriented Attributes})], Old=[has a part that is of a nonremote access type, then that access type, or the type of some part that includes the access type subcomponent, shall have user-specified Read and Write attributes]}. @begin{Reason} This is to prevent the use of the predefined Read and Write attributes of an access type as part of the Read and Write attributes of a visible type. @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Types that do not have available stream attributes are excluded from this rule; that means that attributes do not need to be specified for most limited types. It is only necessary to specify attributes for nonlimited types that have a part that is of any access type, and for extensions of limited types with available stream attributes where the @nt{record_extension_part} includes a subcomponent of an access type, where the access type does not have specified attributes.]} @end{Ramification} @end{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0060-1]} @ChgAdded{Version=[1],Type=[Leading],Text=[]}@ChgNote{Use ChgAdded to get conditional Leading}@Defn{remote access type} @Chg{Version=[3],New=[A named],Old=[An]} access type declared in the visible part of a remote types or remote call interface library unit is called a @i{remote access type}. @Defn{remote access-to-subprogram type} @Defn{remote access-to-class-wide type} Such a type shall be@Chg{New=[:],Old=[ either an access-to-subprogram type or a general access type that designates a class-wide limited private type.]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgAdded{Version=[1],Text=[an access-to-subprogram type, or]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0060-1]} @ChgAdded{Version=[1],Text=[a general access type that designates a class-wide limited private type@Chg{Version=[3],New=[, a class-wide limited interface type,],Old=[]} or a class-wide private @Chg{Version=[3],New=[],Old=[type ]}extension all of whose ancestors are either private @Chg{Version=[3],New=[],Old=[type ]}extensions@Chg{Version=[3],New=[, limited interface types,],Old=[]} or limited private types.]} @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0081],ARef=[AI95-00004-01]} @ChgAdded{Version=[1],Text=[A type that is derived from a remote access type is also a remote access type.]} @Leading@;The following restrictions apply to the use of a remote access-to-subprogram type: @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00431-01]} A value of a remote access-to-subprogram type shall be converted only to @Chg{Version=[2],New=[or from ],Old=[]}another (subtype-conformant) remote access-to-subprogram type; The @nt<prefix> of an Access @nt<attribute_reference> that yields a value of a remote access-to-subprogram type shall statically denote a (subtype-conformant) remote subprogram. @end{Itemize} @Leading@;The following restrictions apply to the use of a remote access-to-class-wide type: @begin{Itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0083],ARef=[AI95-00047-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0060-1],ARef=[AI05-0101-1]} The primitive subprograms of the corresponding specific @Chg{Version=[3],New=[],Old=[limited private ]}type shall only have access parameters if they are controlling formal parameters@Chg{Version=[3],New=[. The primitive functions of the corresponding specific type shall only have an access result if it is a controlling access result.],Old=[;]} @Chg{New=[@Chg{Version=[3],New=[Each],Old=[each]} noncontrolling formal parameter],Old=[the types of all the noncontrolling formal parameters]} @Chg{Version=[3],New=[and noncontrolling result type ],Old=[]}shall @Chg{Version=[2],New=[support external streaming (see @RefSecNum{Stream-Oriented Attributes});], Old=[have @Chg{New=[either a nonlimited type or a type with],Old=[]} Read and Write attributes@Chg{New=[ specified via an @nt{attribute_definition_clause};],Old=[.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0060-1],ARef=[AI05-0215-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The corresponding specific type shall not have a primitive procedure with the Synchronization aspect specified unless the @nt{synchronization_kind} is Optional (see @RefSecNum{Intertask Communication});]} A value of a remote access-to-class-wide type shall be explicitly converted only to another remote access-to-class-wide type; A value of a remote access-to-class-wide type shall be dereferenced (or implicitly converted to an anonymous access type) only as part of a dispatching call where the value designates a controlling operand of the call (see @RefSec{Remote Subprogram Calls}); @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0101-1]} @ChgAdded{Version=[3],Text=[A controlling access result value for a primitive function with any controlling operands of the corresponding specific type shall either be explicitly converted to a remote access-to-class-wide type or be part of a dispatching call where the value designates a controlling operand of the call;]} @ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00366-01]} The Storage_Pool @Chg{Version=[2],New=[attribute is],Old=[and Storage_Size attributes are]} not defined for@Chg{Version=[2],New=[ a],Old=[]} remote access-to-class-wide @Chg{Version=[2],New=[type],Old=[types]}; the expected type for an @nt{allocator} shall not be a remote access-to-class-wide type@Chg{Version=[2],New=[. A],Old=[; a]} remote access-to-class-wide type shall not be an actual parameter for a generic formal access type@Chg{New=[.],Old=[;]}@Chg{Version=[2],New=[ The Storage_Size attribute of a remote access-to-class-wide type yields 0; it is not allowed in an @nt{attribute_definition_clause}.],Old=[]} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} All @Chg{Version=[3],New=[three ],Old=[]}@ChgNote{There are more than three!}of these restrictions are because there is no storage pool associated with a remote access-to-class-wide type.@Chg{Version=[2],New=[ The Storage_Size is defined to be 0 so that there is no conflict with the rules for pure units.],Old=[]} @end{Reason} @end{Itemize} @end{Legality} @begin{Notes} A remote types library unit need not be pure, and the types it defines may include levels of indirection implemented by using access types. User-specified Read and Write attributes (see @RefSecNum{Stream-Oriented Attributes}) provide for sending values of such a type between active partitions, with Write marshalling the representation, and Read unmarshalling any levels of indirection. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0060-1]} @ChgAdded{Version=[3],Text=[The value of a remote access-to-class-wide limited interface can designate an object of a nonlimited type derived from the interface.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0060-1]} @ChgAdded{Version=[3],Text=[A remote access type may designate a class-wide synchronized, protected, or task interface type.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Synchronized, protected, and task interfaces are all considered limited interfaces, see @RefSecNum{Interface types}.]} @end{TheProof} @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00240-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The wording was changed from @lquotes@;user-specified@rquotes to @lquotes@;available@rquotes @Chg{Version=[3],New=[read and write ],Old=[]}attributes. (This was then further changed, see below.) This means that an access type with the attributes specified in the private part would originally have been sufficient to allow the access type to be used in a remote type, but that is no longer allowed. Similarly, the attributes of a remote type that has access components have to be specified in the visible part. These changes were made so that the rules were consistent with the rules introduced for the Corrigendum for stream attributes; moreover, legality should not depend on the contents of the private part.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Remote types that cannot be streamed (that is, have no available stream attributes) do not require the specification of stream attributes. This is necessary so that most extensions of Limited_Controlled do not need stream attributes defined (otherwise there would be a @Chg{Version=[3],New=[significant],Old=[signficant]} incompatibility, as Limited_Controlled would need stream attributes, and then all extensions of it also would need stream attributes).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0081],ARef=[AI95-00004-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added missing wording so that a type derived from a remote access type is also a remote access type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0083],ARef=[AI95-00047-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that user-defined Read and Write attributes are required for the primitive subprograms corresponding to a remote access-to-class-wide type.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0082],ARef=[AI95-00164-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added missing wording so that a remote access type can designate an appropriate private extension.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the newly defined term @i<type that supports external streaming>, so that various issues with access types in pure units and implicitly declared attributes for type extensions are properly handled.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Defined Storage_Size to be 0 for remote access-to-class-wide types, rather than having it undefined. This eliminates issues with pure units requiring a defined storage size.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00431-01]} @ChgAdded{Version=[2],Text=[Corrected the wording so that a value of a local access-to-subprogram type cannot be converted to a remote access-to-subprogram type, as intended (and required by the ACATS).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0101-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added rules for returning of remote access-to-classwide types; this had been missed in the past. While programs that returned unstreamable types from RCI functions were legal, it is not clear what they could have done (as the results could not be marshalled). Similarly, RCI functions that return remote controlling access types could try to save those values, but it is unlikely that a compiler would know how to do that usefully. Thus, it seems unlikely that any real programs will be impacted by these changes.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0060-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}@b<Correction:> Clarified that anonymous access types are never remote access types (and can be used in remote types units subject to the normal restrictions). Added wording to allow limited class-wide interfaces to be designated by remote access types.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0206-1]} @ChgAdded{Version=[3],Text=[Added wording to allow private withs of preelaborated normal units in the specification of a remote types unit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Remote_Types is now a categorization aspect, so it can be specified by an @nt{aspect_specification} @em although the pragma is still preferred by the Standard.]} @end{Extend2005} @LabeledSubClause{Remote Call Interface Library Units} @begin{Intro} @redundant[A remote call interface library unit can be used as an interface for remote procedure calls (RPCs) (or remote function calls) between active partitions.] @end{Intro} @begin{MetaRules} The restrictions governing a remote call interface library unit are intended to ensure that the values of the actual parameters in a remote call can be meaningfully sent between two active partitions. @end{MetaRules} @begin{Syntax} @begin{SyntaxText} @Leading@PDefn2{Term=[categorization pragma], Sec=(Remote_Call_Interface)} @PDefn2{Term=[pragma, categorization], Sec=(Remote_Call_Interface)} The form of a @nt{pragma} Remote_Call_Interface is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Remote_Call_Interface)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @Leading@;The form of a @nt{pragma} All_Calls_Remote is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(All_Calls_Remote)[(@SynI{library_unit_}@Syn2{name})];' @begin{SyntaxText} @PDefn2{Term=[library unit pragma], Sec=(All_Calls_Remote)} @PDefn2{Term=[pragma, library unit], Sec=(All_Calls_Remote)} A @nt{pragma} All_Calls_Remote is a library unit pragma. @end{SyntaxText} @end{Syntax} @begin{Legality} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} @Defn{remote call interface} @Defn2{Term=[RCI],Sec=(library unit)} @Defn2{Term=[RCI],Sec=(package)} @Defn2{Term=[RCI],Sec=(generic)} @Defn{remote subprogram} A@Chg{Version=[3],New=[ @nt{pragma} Remote_Call_Interface is used to specify that a library unit is a],Old=[]} @i{remote call interface (RCI)}@Chg{Version=[3],New=[, namely that the],Old=[ is a library unit to which the pragma]} Remote_Call_Interface @Chg{Version=[3],New=[aspect@AspectDefn{Remote_Call_Interface} of the library unit is True],Old=[applies]}. A subprogram declared in the visible part of such a library unit@Chg{New=[, or declared by such a library unit,],Old=[]} is called a @i{remote subprogram}. @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Remote_Call_Interface], Text=[@ChgAdded{Version=[3],Text=[Subprograms in a given package may be used in remote procedure calls.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0206-1],ARef=[AI05-0243-1]} The declaration of an RCI library unit shall be preelaborable (see @RefSecNum{Elaboration Control}), and shall depend semantically only upon declared pure@Chg{Version=[3],New=[ @nt{library_item}s],Old=[]}, shared passive@Chg{Version=[3],New=[ library units],Old=[]}, remote types@Chg{Version=[3],New=[ library units],Old=[]}, @Chg{Version=[3],New=[],Old=[or ]}other remote call interface library units@Chg{Version=[3],New=[, or preelaborated normal library units that are mentioned only in private with clauses],Old=[]}. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[We say declared pure @nt{library_item} here, so that (all) limited views are allowed; those are not library units, but they are declared pure @nt{library_item}s.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @Leading@;In addition, the following restrictions apply to @Chg{New=[],Old=[the visible part of ]}an RCI library unit: @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain the declaration of a variable; @begin{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} Remote call interface @Chg{New=[units],Old=[packages]} do not provide remote data access. A shared passive package has to be used for that. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain the declaration of a limited type; @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} We disallow the declaration of task and protected types, since calling an entry or a protected subprogram implicitly passes an object of a limited type (the target task or protected object). We disallow other limited types since we require that such types have @Chg{Version=[2],New=[available],Old=[user-defined]} Read and Write attributes, but we certainly don't want the Read and Write attributes themselves to involve remote calls (thereby defeating their purpose of marshalling the value for remote calls). @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} it@Chg{New=[s visible part],Old=[]} shall not contain a nested @nt{generic_declaration}; @begin{Reason} This is disallowed because the body of the nested generic would presumably have access to data inside the body of the RCI package, and if instantiated in a different partition, remote data access might result, which is not supported. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} it shall not @Chg{New=[be, nor shall its visible part],Old=[]} contain@Chg{New=[,],Old=[]} the declaration of a subprogram @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[aspect],Old=[a pragma]} Inline @Chg{Version=[3],New=[is True], Old=[applies]}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00240-01],ARef=[AI95-00366-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0101-1]} it shall not @Chg{New=[be, nor shall its visible part], Old=[]} contain@Chg{New=[,],Old=[]} a subprogram (or access-to-subprogram) declaration whose profile has @Chg{Version=[2],New=[@Chg{Version=[3],New=[], Old=[@Redundant[an access parameter or]]} a parameter @Chg{Version=[3],New=[or result ],Old=[]}of a type that does not support external streaming (see @RefSecNum{Stream-Oriented Attributes})], Old=[an access parameter, or a formal parameter of a limited type unless that limited type has user-specified Read and Write attributes]}; @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0101-1]} @ChgAdded{Version=[3],Text=[No anonymous access types support external streaming, so they are never allowed as parameters or results of RCI subprograms.]} @end{Ramification} any public child of the library unit shall be a remote call interface library unit. @begin{Reason} No restrictions apply to the private part of an RCI package, and since a public child can @lquotes@;see@rquotes@; the private part of its parent, such a child must itself have a Remote_Call_Interface pragma, and be assigned to the same partition (see below). @end{Reason} @begin{Discussion} We considered making the public child of an RCI package implicitly RCI, but it seemed better to require an explicit pragma to avoid any confusion. Note that there is no need for a private child to be an RCI package, since it can only be seen from the body of its parent or its siblings, all of which are required to be in the same active partition. @end{Discussion} @end{itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[A],Old=[If a]} pragma All_Calls_Remote @Chg{Version=[3],New=[sets the All_Calls_Remote representation aspect of @AspectDefn{All_Calls_Remote}the],Old=[applies to a]} library unit@Chg{Version=[3],New=[ to which the pragma applies to the value True. If the All_Calls_Remote aspect of a library unit is True], Old=[]}, the library unit shall be a remote call interface. @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[All_Calls_Remote], Text=[@ChgAdded{Version=[3],Text=[All remote procedure calls should use the Partition Communication Subsystem, even if they are local.]}]} @end{Legality} @begin{LinkTime} A remote call interface library unit shall be assigned to at most one partition of a given program. A remote call interface library unit whose parent is also an RCI library unit shall be assigned only to the same partition as its parent. @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} The declaration of an RCI @Chg{New=[unit],Old=[package]}, with a calling-stub body, is automatically included in all active partitions with compilation units that depend on it. However the whole RCI library unit, including its (non-stub) body, will only be in one of the active partitions. @end{ImplNote} @PDefn2{Term=[compilation units needed], Sec=(remote call interface)} @PDefn2{Term=[needed], Sec=(remote call interface)} @Defn{notwithstanding} Notwithstanding the rule given in @RefSecNum{Program Execution}, a compilation unit in a given partition that semantically depends on the declaration of an RCI library unit, @i{needs} (in the sense of @RefSecNum{Program Execution}) only the declaration of the RCI library unit, not the body, to be included in that same partition. @Redundant[Therefore, the body of an RCI library unit is included only in the partition to which the RCI library unit is explicitly assigned.] @end{LinkTime} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If @Chg{Version=[3],New=[aspect],Old=[a pragma]} All_Calls_Remote @Chg{Version=[3],New=[is True for],Old=[applies to]} a given RCI library @Chg{New=[unit],Old=[package]}, then the implementation shall route any call to a subprogram of the RCI @Chg{New=[unit],Old=[package]} from outside the declarative region of the @Chg{New=[unit],Old=[package]} through the Partition Communication Subsystem (PCS); see @RefSecNum{Partition Communication Subsystem}. Calls to such subprograms from within the declarative region of the @Chg{New=[unit],Old=[package]} are defined to be local and shall not go through the PCS. @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[When this aspect is False (or not used)],Old=[Without this pragma]}, it is presumed that most implementations will make direct calls if the call originates in the same partition as that of the RCI @Chg{New=[unit],Old=[package]}. @Chg{Version=[3],New=[When this aspect is True],Old=[With this pragma]}, all calls from outside the subsystem rooted at the RCI @Chg{New=[unit],Old=[package]} are treated like calls from outside the partition, ensuring that the PCS is involved in all such calls (for debugging, redundancy, etc.). @end{Discussion} @begin{Reason} There is no point to force local calls (or calls from children) to go through the PCS, since on the target system, these calls are always local, and all the units are in the same active partition. @end{Reason} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1]} An implementation need not support the Remote_Call_Interface pragma @Chg{Version=[3],New=[or aspect ],Old=[]}nor the All_Calls_Remote pragma. @Redundant[Explicit message-based communication between active partitions can be supported as an alternative to RPC.] @begin{Ramification} Of course, it is pointless to support the All_Calls_Remote pragma if the Remote_Call_Interface pragma (or some approximate equivalent) is not supported. @end{Ramification} @end{ImplPerm} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00240-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The wording was changed from @lquotes@;user-specified@rquotes to @lquotes@;available@rquotes @Chg{Version=[3],New=[read and write ],Old=[]}attributes. (This was then further changed, see below.) This means that a type with the attributes specified in the private part would originally have been allowed as a formal parameter of an RCI subprogram, but that is no longer allowed. This change was made so that the rules were consistent with the rules introduced for the Corrigendum for stream attributes; moreover, legality should not depend on the contents of the private part.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0078],ARef=[AI95-00048-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed the wording to allow a library subprogram to be a remote call interface unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00366-01]} @ChgAdded{Version=[2],Text=[Changed the wording to use the newly defined term @i<type that supports external streaming>, so that various issues with access types in pure units and implicitly declared attributes for type extensions are properly handled.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0101-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added a rule to ensure that function results are streamable; this was missing in previous versions of Ada. While programs that returned unstreamable types from RCI functions were legal, it is not clear what they could have done (as the results could not be marshalled). Thus, it seems unlikely that any real programs will be impacted by this change.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0206-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Added wording to allow private withs of preelaborated normal units in the specification of a remote call interface unit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[All_Calls_Remote is now a representation aspect, so it can be specified by an @nt{aspect_specification} @em although the pragma is still preferred by the Standard.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0243-1]} @ChgAdded{Version=[3],Text=[Remote_Call_Interface is now a categorization aspect, so it can be specified by an @nt{aspect_specification} @em although the pragma is still preferred by the Standard.]} @end{Extend2005} @LabeledClause{Consistency of a Distributed System} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines attributes and rules associated with verifying the consistency of a distributed program.] @end{Intro} @begin{MetaRules} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} The rules guarantee that remote call interface and shared passive @Chg{Version=[3],New=[library units],Old=[packages]} are consistent among all partitions prior to the execution of a distributed program, so that the semantics of the distributed program are well defined. @end{MetaRules} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised]}@ChgNote{To be consistent with 8652/0006} @Leading@;For @ChgPrefixType{Version=[1],Kind=[Revised],Text=[a @Chg{New=[@nt{prefix}],Old=[prefix]} P that statically denotes a program unit]}, the following attributes are defined: @begin{Description} @Attribute{Prefix=<P>, AttrName=<Version>, Text=[Yields a value of the predefined type String that identifies the version of the compilation unit that contains the declaration of the program unit.]} @Attribute{Prefix=<P>, AttrName=<Body_Version>, Text=[Yields a value of the predefined type String that identifies the version of the compilation unit that contains the body (but not any subunits) of the program unit.]} @end{Description} @EndPrefixType{} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0084],ARef=[AI95-00104-01]} @Defn2{Term=[version], Sec=(of a compilation unit)} The @i{version} of a compilation unit changes whenever the @Chg{New=[],Old=[version changes for any ]}compilation unit @Chg{New=[changes in a semantically significant way. This International Standard does not define the exact meaning of "semantically significant"], Old=[on which it depends semantically. The version also changes whenever the compilation unit itself changes in a semantically significant way]}. It is @Chg{New=[unspecified],Old=[implementation defined]} whether there are other events (such as recompilation) that result in the version of a compilation unit changing. @Chg{New=[@PDefn{unspecified}],Old=[]} @ChgImplDef{Version=[1],Kind=[Deleted],InitialVersion=[0], Text=[@Chg{New=[],Old=[Events that cause the version of a compilation unit to change.]}]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0084],ARef=[AI95-00104-01]} @ChgAdded{Version=[1],Text=[If P is not a library unit, and P has no completion, then P'Body_Version returns the Body_Version of the innermost program unit enclosing the declaration of P. If P is a library unit, and P has no completion, then P'Body_Version returns a value that is different from Body_Version of any version of P that has a completion.]} @end{StaticSem} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} @Defn{unit consistency} In a distributed program, a library unit is @i{consistent} if the same version of its declaration is used throughout. It is a bounded error to elaborate a partition of a distributed program that contains a compilation unit that depends on a different version of the declaration of a shared passive or RCI library unit than that included in the partition to which the shared passive or RCI library unit was assigned. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} As a result of this error, Program_Error can be raised in one or both partitions during elaboration; in any case, the partitions become inaccessible to one another. @begin{Ramification} Because a version changes if anything on which it depends undergoes a version change, requiring consistency for shared passive and remote call interface library units is sufficient to ensure consistency for the declared pure and remote types library units that define the types used for the objects and parameters through which interpartition communication takes place. Note that we do not require matching Body_Versions; it is irrelevant for shared passive and remote call interface packages, since only one copy of their body exists in a distributed program (in the absence of implicit replication), and we allow the bodies to differ for declared pure and remote types packages from partition to partition, presuming that the differences are due to required error corrections that took place during the execution of a long-running distributed program. The Body_Version attribute provides a means for performing stricter consistency checks. @end{Ramification} @end{Bounded} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0084],ARef=[AI95-00104-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of 'Version and 'Body_Version.]} @end{DiffWord95} @LabeledClause{Remote Subprogram Calls} @begin{Intro} @Defn{remote subprogram call} @RootDefn{asynchronous remote procedure call} @Defn{calling partition} @Defn{called partition} @Defn{remote subprogram binding} A @i{remote subprogram call} is a subprogram call that invokes the execution of a subprogram in another partition. The partition that originates the remote subprogram call is the @i{calling partition}, and the partition that executes the corresponding subprogram body is the @i{called partition}. Some remote procedure calls are allowed to return prior to the completion of subprogram execution. These are called @i{asynchronous remote procedure calls}. @Leading@;There are three different ways of performing a remote subprogram call: @begin{Itemize} As a direct call on a (remote) subprogram explicitly declared in a remote call interface; As an indirect call through a value of a remote access-to-subprogram type; As a dispatching call with a controlling operand designated by a value of a remote access-to-class-wide type. @end{Itemize} The first way of calling corresponds to a @i(static) binding between the calling and the called partition. The latter two ways correspond to a @i(dynamic) binding between the calling and the called partition. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0101-1]} @Chg{Version=[3],New=[Remote types library units (see @RefSecNum{Remote Types Library Units}) and],Old=[A]} remote call interface library @Chg{Version=[3],New=[units],Old=[unit]} (see @RefSecNum{Remote Call Interface Library Units}) @Chg{Version=[3],New=[define],Old=[defines]} the remote subprograms or remote access types used for remote subprogram calls. @end{Intro} @begin{MetaRules} Remote subprogram calls are standardized since the RPC paradigm is widely-used, and establishing an interface to it in the annex will increase the portability and reusability of distributed programs. @end{MetaRules} @begin{Legality} In a dispatching call with two or more controlling operands, if one controlling operand is designated by a value of a remote access-to-class-wide type, then all shall be. @end{Legality} @begin{RunTime} @Defn{marshalling} @Defn{unmarshalling} @PDefn2{Term=[execution], Sec=(remote subprogram call)} For the execution of a remote subprogram call, subprogram parameters (and later the results, if any) are passed using a stream-oriented representation (see @RefSecNum{The Package Streams}) @Redundant[which is suitable for transmission between partitions]. This action is called @i{marshalling}. @i{Unmarshalling} is the reverse action of reconstructing the parameters or results from the stream-oriented representation. @redundant[Marshalling is performed initially as part of the remote subprogram call in the calling partition; unmarshalling is done in the called partition. After the remote subprogram completes, marshalling is performed in the called partition, and finally unmarshalling is done in the calling partition.] @Defn{calling stub} @Defn{receiving stub} A @i{calling stub} is the sequence of code that replaces the subprogram body of a remotely called subprogram in the calling partition. A @i{receiving stub} is the sequence of code (the @lquotes@;wrapper@rquotes@;) that receives a remote subprogram call on the called partition and invokes the appropriate subprogram body. @begin{Discussion} The use of the term @i{stub} in this annex should not be confused with @nt{body_stub} as defined in @RefSecNum{Subunits of Compilation Units}. The term @i{stub} is used here because it is a commonly understood term when talking about the RPC paradigm. @end{Discussion} @Defn{at-most-once execution} Remote subprogram calls are executed at most once, that is, if the subprogram call returns normally, then the called subprogram's body was executed exactly once. The task executing a remote subprogram call blocks until the subprogram in the called partition returns, unless the call is asynchronous. For an asynchronous remote procedure call, the calling task can become ready before the procedure in the called partition returns. @Defn{cancellation of a remote subprogram call} If a construct containing a remote call is aborted, the remote subprogram call is @i{cancelled}. Whether the execution of the remote subprogram is immediately aborted as a result of the cancellation is implemen@!tation defined. @ImplDef{Whether the execution of the remote subprogram is immediately aborted as a result of cancellation.} If a remote subprogram call is received by a called partition before the partition has completed its elaboration, the call is kept pending until the called partition completes its elaboration (unless the call is cancelled by the calling partition prior to that). If an exception is propagated by a remotely called subprogram, and the call is not an asynchronous call, the corresponding exception is reraised at the point of the remote subprogram call. For an asynchronous call, if the remote procedure call returns prior to the completion of the remotely called subprogram, any exception is lost. The exception Communication_Error (see @RefSecNum{Partition Communication Subsystem}) is raised if a remote call cannot be completed due to difficulties in communicating with the called partition. @PDefn2{Term=[potentially blocking operation],Sec=(remote subprogram call)} @PDefn2{Term=[blocking, potentially],Sec=(remote subprogram call)} All forms of remote subprogram calls are potentially blocking operations (see @RefSecNum{Protected Subprograms and Protected Actions}). @begin{Reason} Asynchronous remote procedure calls are potentially blocking since the implementation may require waiting for the availability of shared resources to initiate the remote call. @end{Reason} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0085],ARef=[AI95-00215-01]} @IndexCheck{Accessibility_Check} In a remote subprogram call with a formal parameter of a class-wide type, a check is made that the tag of the actual parameter identifies a tagged type declared in a declared-pure or shared passive library unit, or in the visible part of a remote types or remote call interface library unit. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if this check fails. @Chg{New=[In a remote function call which returns a class-wide type, the same check is made on the function result.],Old=[]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0085],ARef=[AI95-00215-01]} This check makes certain that the specific type passed@Chg{New=[ or returned], Old=[]} in an RPC satisfies the rules for a "communicable" type. Normally this is guaranteed by the compile-time restrictions on remote call interfaces. However, with class-wide types, it is possible to pass an object whose tag identifies a type declared outside the "safe" packages. This is considered an accessibility_check since only the types declared in "safe" packages are considered truly "global" (cross-partition). Other types are local to a single partition. This is analogous to the "accessibility" of global vs. local declarations in a single-partition program. This rule replaces a rule from an early version of Ada 9X which was given in the subclause on Remote Types Library Units (now @RefSec{Remote Types Library Units}). That rule tried to prevent "bad" types from being sent by arranging for their tags to mismatch between partitions. However, that interfered with other uses of tags. The new rule allows tags to agree in all partitions, even for those types which are not "safe" to pass in an RPC. @end{Discussion} @IndexCheck{Partition_Check} In a dispatching call with two or more controlling operands that are designated by values of a remote access-to-class-wide type, a check is made @Redundant[(in addition to the normal Tag_Check @em see @RefSecNum{Suppressing Checks})] that all the remote access-to-class-wide values originated from Access @nt<attribute_reference>s that were evaluated by tasks of the same active partition. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Constraint_Error is raised if this check fails. @begin{ImplNote} When a remote access-to-class-wide value is created by an Access @nt<attribute_reference>, the identity of the active partition that evaluated the @nt<attribute_reference> should be recorded in the representation of the remote access value. @end{ImplNote} @end{RunTime} @begin{ImplReq} The implementation of remote subprogram calls shall conform to the PCS interface as defined by the specification of the language-defined package System.RPC (see @RefSecNum{Partition Communication Subsystem}). The calling stub shall use the Do_RPC procedure unless the remote procedure call is asynchronous in which case Do_APC shall be used. On the receiving side, the corresponding receiving stub shall be invoked by the RPC-receiver. @begin{ImplNote} One possible implementation model is as follows: The code for calls to subprograms declared in an RCI package is generated normally, that is, the call-site is the same as for a local subprogram call. The code for the remotely callable subprogram bodies is also generated normally. Subprogram's prologue and epilogue are the same as for a local call. When compiling the specification of an RCI package, the compiler generates calling stubs for each visible subprogram. Similarly, when compiling the body of an RCI package, the compiler generates receiving stubs for each visible subprogram together with the appropriate tables to allow the RPC-receiver to locate the correct receiving stub. For the statically bound remote calls, the identity of the remote partition is statically determined (it is resolved at configuration/link time). @Leading@;The calling stub operates as follows: @begin(Itemize) It allocates (or reuses) a stream of Params_Stream_Type of Initial_Size, and initializes it by repeatedly calling Write operations, first to identify which remote subprogram in the receiving partition is being called, and then to pass the incoming value of each of the @b(in) and @b(in out) parameters of the call. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} It allocates (or reuses) a stream for the Result, unless @Chg{Version=[3],New=[an aspect],Old=[a pragma]} Asynchronous is @Chg{Version=[3],New=[specified as True for],Old=[applied to]} the procedure. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} It calls Do_RPC unless @Chg{Version=[3],New=[an aspect],Old=[a pragma]} Asynchronous @Chg{Version=[3],New=[is specified as True for],Old=[applied to]} the procedure in which case it calls Do_APC. An access value designating the message stream allocated and initialized above is passed as the Params parameter. An access value designating the Result stream is passed as the Result parameter. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If the @Chg{Version=[3],New=[aspect],Old=[pragma]} Asynchronous is not specified for the procedure, Do_RPC blocks until a reply message arrives, and then returns to the calling stub. The stub returns after extracting from the Result stream, using Read operations, the @b(in out) and @b(out) parameters or the function result. If the reply message indicates that the execution of the remote subprogram propagated an exception, the exception is propagated from Do_RPC to the calling stub, and thence to the point of the original remote subprogram call. If Do_RPC detects that communication with the remote partition has failed, it propagates Communication_Error. @end(Itemize) @Leading@;On the receiving side, the RPC-receiver procedure operates as follows: @begin(Itemize) It is called from the PCS when a remote-subprogram-call message is received. The call originates in some remote call receiver task executed and managed in the context of the PCS. It extracts information from the stream to identify the appropriate receiving stub. The receiving stub extracts the @b(in) and @b(in out) parameters using Read from the stream designated by the Params parameter. The receiving stub calls the actual subprogram body and, upon completion of the subprogram, uses Write to insert the results into the stream pointed to by the Result parameter. The receiving stub returns to the RPC-receiver procedure which in turn returns to the PCS. If the actual subprogram body propagates an exception, it is propagated by the RPC-receiver to the PCS, which handles the exception, and indicates in the reply message that the execution of the subprogram body propagated an exception. The exception occurrence can be represented in the reply message using the Write attribute of Ada.Exceptions.Exception_Occurrence. @end(Itemize) For remote access-to-subprogram types: A value of a remote access-to-subprogram type can be represented by the following components: a reference to the remote partition, an index to the package containing the remote subprogram, and an index to the subprogram within the package. The values of these components are determined at run time when the remote access value is created. These three components serve the same purpose when calling Do_APC/RPC, as in the statically bound remote calls; the only difference is that they are evaluated dynamically. For remote access-to-class-wide types: For each remote access-to-class-wide type, a calling stub is generated for each dispatching operation of the designated type. In addition, receiving stubs are generated to perform the remote dispatching operations in the called partition. The appropriate @nt{subprogram_body} is determined as for a local dispatching call once the receiving stub has been reached. A value of a remote access-to-class-wide type can be represented with the following components: a reference to the remote partition, an index to a table (created one per each such access type) containing addresses of all the dispatching operations of the designated type, and an access value designating the actual remote object. Alternatively, a remote access-to-class-wide value can be represented as a normal access value, pointing to a "stub" object which in turn contains the information mentioned above. A call on any dispatching operation of such a stub object does the remote call, if necessary, using the information in the stub object to locate the target partition, etc. This approach has the advantage that less special-casing is required in the compiler. All access values can remain just a simple address. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} For a call to Do_RPC or Do_APC: The partition ID of all controlling operands are checked for equality (a Constraint_Error is raised if this check fails). The partition ID value is used for the Partition parameter. An index into the @i{tagged-type-descriptor} is created. This index points to the receiving stub of the class-wide operation. This index and the index to the table (described above) are written to the stream. Then, the actual parameters are marshalled into the message stream. For a controlling operand, only the access value designating the remote object is required (the other two components are already present in the other parameters). On the called partition (after the RPC-receiver has transferred control to the appropriate receiving stub) the parameters are first unmarshalled. Then, the tags of the controlling operands (obtained by dereferencing the pointer to the object) are checked for equality. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the check fails Constraint_Error is raised and propagated back to the calling partition, unless it is a result of an asynchronous call. Finally, a dispatching call to the specific subprogram (based on the controlling object's tag) is made. Note that since this subprogram is not in an RCI package, no specific stub is generated for it, it is called normally from the @i{dispatching stub}. @end{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0086],ARef=[AI95-00159-01]} @ChgAdded{Version=[1],Text=[With respect to shared variables in shared passive library units, the execution of the corresponding subprogram body of a synchronous remote procedure call is considered to be part of the execution of the calling task. The execution of the corresponding subprogram body of an asynchronous remote procedure call proceeds in parallel with the calling task and does not signal the next action of the calling task (see @RefSecNum{Shared Variables}).]} @end{ImplReq} @begin{Notes} A given active partition can both make and receive remote subprogram calls. Thus, an active partition can act as both a client and a server. If a given exception is propagated by a remote subprogram call, but the exception does not exist in the calling partition, the exception can be handled by an @key(others) choice or be propagated to and handled by a third partition. @begin{Discussion} This situation can happen in a case of dynamically nested remote subprogram calls, where an intermediate call executes in a partition that does not include the library unit that defines the exception. @end{Discussion} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0086],ARef=[AI95-00159-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added rules so that tasks can safely access shared passive objects.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0085],ARef=[AI95-00215-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the check on class-wide types also applies to values returned from remote subprogram call functions.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0101-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected the text to note that remote access types can be defined in remote types units.]} @end{DiffWord2005} @LabeledRevisedSubClause{Version=[3],New=[Asynchronous Remote Calls],Old=[Pragma Asynchronous]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @redundant[This subclause introduces the @Chg{Version=[3],New=[aspect],Old=[pragma]} Asynchronous which @Chg{Version=[3],New=[can be specified to allow],Old=[allows]} a remote subprogram call to return prior to completion of the execution of the corresponding remote subprogram body.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 7 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Asynchronous is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Asynchronous)(@Syn2{local_name});]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[The @nt<local_name> of a pragma Asynchronous shall denote either:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[One or more remote procedures; the formal parameters of the procedure(s) shall all be of mode @key{in};]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[The first subtype of a remote access-to-procedure type; the formal parameters of the designated profile of the type shall all be of mode @key{in};]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[The first subtype of a remote access-to-class-wide type.]} @end{Itemize} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[]}@Comment{Fake to get conditional Leading} @Chg{Version=[3],New=[For a remote procedure, the following language-defined representation aspect may be specified:], Old=[@PDefn2{Term=[representation pragma], Sec=(Asynchronous)} @PDefn2{Term=[pragma, representation], Sec=(Asynchronous)} A pragma Asynchronous is a representation pragma. When applied to a type, it specifies the type-related @i{asynchronous} aspect of the type.]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Asynchronous@\The type of aspect Asynchronous is Boolean. If directly specified, the @nt{aspect_definition} shall be a static expression. If not specified, the aspect is False.@AspectDefn{Asynchronous}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Asynchronous], Text=[@ChgAdded{Version=[3],Text=[Remote procedure calls are asynchronous; the caller continues without waiting for the call to return.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a remote access type, the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Asynchronous@\The type of aspect Asynchronous is Boolean. If directly specified, the @nt{aspect_definition} shall be a static expression. If not specified (including by inheritance), the aspect is False.]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If aspect Asynchronous is specified for a remote procedure, the formal parameters of the procedure shall all be of mode @key[in].]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If aspect Asynchronous is specified for a remote access type, the type shall be a remote access-to-class-wide type, or the type shall be a remote access-to-procedure type with the formal parameters of the designated profile of the type all of mode @key[in].]} @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[remote procedure call],Sec=(asynchronous)} @Defn2{Term=[asynchronous], Sec=(remote procedure call)} A remote call is @i{asynchronous} if it is a call to a procedure, or a call through a value of an access-to-procedure type, @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[aspect],Old=[a pragma]} Asynchronous @Chg{Version=[3],New=[is True],Old=[applies]}. In addition, if @Chg{Version=[3],New=[aspect],Old=[a pragma]} Asynchronous @Chg{Version=[3],New=[is True for],Old=[applies to]} a remote access-to-class-wide type, then a dispatching call on a procedure with a controlling operand designated by a value of the type is asynchronous if the formal parameters of the procedure are all of mode @key{in}. @end{RunTime} @begin{ImplReq} Asynchronous remote procedure calls shall be implemented such that the corresponding body executes at most once as a result of the call. @begin{Honest} It is not clear that this rule can be tested or even defined formally. @end{Honest} @end{ImplReq} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect Asynchronous is new; @nt{pragma} Asynchronous is now obsolescent.]} @end{Extend2005} @LabeledSubClause{Example of Use of a Remote Access-to-Class-Wide Type} @begin{Examples} @Leading@i{Example of using a remote access-to-class-wide type to achieve dynamic binding across active partitions:} @begin{example} @key{package} Tapes @key{is} @key{pragma} Pure(Tapes); @key{type} Tape @key{is abstract tagged limited private}; @RI{-- Primitive dispatching operations where} @RI{-- Tape is controlling operand} @key{procedure} Copy (From, To : @key{access} Tape; Num_Recs : @key[in] Natural) @key{is} @key{abstract}; @key{procedure} Rewind (T : @key{access} Tape) @key{is} @key{abstract}; @RI{-- More operations} @key{private} @key{type} Tape @key{is} ... @key{end} Tapes; @key{with} Tapes; @key{package} Name_Server @key{is} @key{pragma} Remote_Call_Interface; @RI{-- Dynamic binding to remote operations is achieved} @RI{-- using the access-to-limited-class-wide type Tape_Ptr} @key{type} Tape_Ptr @key{is access all} Tapes.Tape'Class; @RI{-- The following statically bound remote operations} @RI{-- allow for a name-server capability in this example} @key{function} Find (Name : String) @key{return} Tape_Ptr; @key{procedure} Register (Name : @key[in] String; T : @key[in] Tape_Ptr); @key{procedure} Remove (T : @key[in] Tape_Ptr); @RI{-- More operations} @key{end} Name_Server; @key{package} Tape_Driver @key{is} @RI{-- Declarations are not shown, they are irrelevant here} @key{end} Tape_Driver; @key{with} Tapes, Name_Server; @key{package body} Tape_Driver @key{is} @key{type} New_Tape @key{is new} Tapes.Tape @key{with} ... @key{procedure} Copy (From, To : @key{access} New_Tape; Num_Recs: @key[in] Natural) @key{is} @key{begin} . . . @key{end} Copy; @key{procedure} Rewind (T : @key{access} New_Tape) @key{is} @key{begin} . . . @key{end} Rewind; @RI{-- Objects remotely accessible through use} @RI{-- of Name_Server operations} Tape1, Tape2 : @key[aliased] New_Tape; @key{begin} Name_Server.Register ("NINE-TRACK", Tape1'Access); Name_Server.Register ("SEVEN-TRACK", Tape2'Access); @key{end} Tape_Driver; @key{with} Tapes, Name_Server; @RI{-- Tape_Driver is not needed and thus not mentioned in the @nt{with_clause}} @key{procedure} Tape_Client @key{is} T1, T2 : Name_Server.Tape_Ptr; @key{begin} T1 := Name_Server.Find ("NINE-TRACK"); T2 := Name_Server.Find ("SEVEN-TRACK"); Tapes.Rewind (T1); Tapes.Rewind (T2); Tapes.Copy (T1, T2, 3); @key{end} Tape_Client; @end{example} @leading@keepnext@i{Notes on the example}: @begin{Discussion} The example does not show the case where tapes are removed from or added to the system. In the former case, an appropriate exception needs to be defined to instruct the client to use another tape. In the latter, the Name_Server should have a query function visible to the clients to inform them about the availability of the tapes in the system. @end{Discussion} @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{itemize} The package Tapes provides the necessary declarations of the type and its primitive operations. Name_Server is a remote call interface package and is elaborated in a separate active partition to provide the necessary naming services (such as Register and Find) to the entire distributed program through remote subprogram calls. Tape_Driver is a normal package that is elaborated in a partition configured on the processing node that is connected to the tape device(s). The abstract operations are overridden to support the locally declared tape devices (Tape1, Tape2). The package is not visible to its clients, but it exports the tape devices (as remote objects) through the services of the Name_Server. This allows for tape devices to be dynamically added, removed or replaced without requiring the modification of the clients' code. The Tape_Client procedure references only declarations in the Tapes and Name_Server packages. Before using a tape for the first time, it needs to query the Name_Server for a system-wide identity for that tape. From then on, it can use that identity to access the tape device. Values of remote access type Tape_Ptr include the necessary information to complete the remote dispatching operations that result from dereferencing the controlling operands T1 and T2. @end{itemize} @end{Examples} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Partition Communication Subsystem} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00273-01]} @Defn{partition communication subsystem (PCS)} @Defn{PCS (partition communication subsystem)} @redundant[The @i{Partition Communication Subsystem} (PCS) provides facilities for supporting communication between the active partitions of a distributed program. The package System.RPC is a language-defined interface to the PCS.]@Chg{Version=[2],New=[],Old=[ An implementation conforming to this Annex shall use the RPC interface to implement remote subprogram calls.]} @begin{Reason} The prefix RPC is used rather than RSC because the term remote procedure call and its acronym are more familiar. @end{Reason} @end{Intro} @begin{StaticSem} @leading@keepnext@;The following language-defined library package exists: @begin{example} @b(with) Ada.Streams; @RI{-- see @RefSecNum[The Package Streams]} @key(package) System.RPC @key(is)@ChildUnit{Parent=[System],Child=[RPC]} @key(type) @AdaTypeDefn{Partition_Id} @key(is range) 0 .. @RI(implementation-defined); @AdaExcDefn{Communication_Error} : @key(exception); @key(type) @AdaTypeDefn{Params_Stream_Type} ( Initial_Size : Ada.Streams.Stream_Element_Count) @key(is) @key(new) Ada.Streams.Root_Stream_Type @key(with) @key(private); @key(procedure) @AdaSubDefn{Read}( Stream : @key(in out) Params_Stream_Type; Item : @key(out) Ada.Streams.Stream_Element_Array; Last : @key(out) Ada.Streams.Stream_Element_Offset); @key(procedure) @AdaSubDefn{Write}( Stream : @key(in out) Params_Stream_Type; Item : @key(in) Ada.Streams.Stream_Element_Array); @RI(-- Synchronous call) @key(procedure) @AdaSubDefn{Do_RPC}( Partition : @key(in) Partition_Id; Params : @key(access) Params_Stream_Type; Result : @key(access) Params_Stream_Type); @RI(-- Asynchronous call) @key(procedure) @AdaSubDefn{Do_APC}( Partition : @key(in) Partition_Id; Params : @key(access) Params_Stream_Type); @RI(-- The handler for incoming RPCs) @key(type) @AdaTypeDefn{RPC_Receiver} @key(is access procedure)( Params : @key(access) Params_Stream_Type; Result : @key(access) Params_Stream_Type); @key(procedure) @AdaSubDefn{Establish_RPC_Receiver}( Partition : @key(in) Partition_Id; Receiver : @key(in) RPC_Receiver); @key[private] ... -- @RI{not specified by the language} @b(end) System.RPC; @end{example} A value of the type Partition_Id is used to identify a partition. @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The range of type System.RPC.Partition_Id.]}]} An object of the type Params_Stream_Type is used for identifying the particular remote subprogram that is being called, as well as marshalling and unmarshalling the parameters or result of a remote subprogram call, as part of sending them between partitions. @redundant[The Read and Write procedures override the corresponding abstract operations for the type Params_Stream_Type.] @end{StaticSem} @begin{RunTime} The Do_RPC and Do_APC procedures send a message to the active partition identified by the Partition parameter. @begin{ImplNote} It is assumed that the RPC interface is above the message-passing layer of the network protocol stack and is implemented in terms of it. @end{ImplNote} After sending the message, Do_RPC blocks the calling task until a reply message comes back from the called partition or some error is detected by the underlying communication system in which case Communication_Error is raised at the point of the call to Do_RPC. @begin{Reason} Only one exception is defined in System.RPC, although many sources of errors might exist. This is so because it is not always possible to distinguish among these errors. In particular, it is often impossible to tell the difference between a failing communication link and a failing processing node. Additional information might be associated with a particular Exception_Occurrence for a Communication_Error. @end{Reason} Do_APC operates in the same way as Do_RPC except that it is allowed to return immediately after sending the message. Upon normal return, the stream designated by the Result parameter of Do_RPC contains the reply message. @PDefn2{Term=[elaboration], Sec=(partition)} The procedure System.RPC.Establish_RPC_Receiver is called once, immediately after elaborating the library units of an active partition (that is, right after the @i{elaboration of the partition}) if the partition includes an RCI library unit, but prior to invoking the main subprogram, if any. The Partition parameter is the Partition_Id of the active partition being elaborated. @Defn{RPC-receiver} The Receiver parameter designates an implementation-provided procedure called the @i{RPC-receiver} which will handle all RPCs received by the partition from the PCS. Establish_RPC_Receiver saves a reference to the RPC-receiver; when a message is received at the called partition, the RPC-receiver is called with the Params stream containing the message. When the RPC-receiver returns, the contents of the stream designated by Result is placed in a message and sent back to the calling partition. @begin{ImplNote} It is defined by the PCS implementation whether one or more threads of control should be available to process incoming messages and to wait for their completion. @end{ImplNote} @begin{ImplNote} At link-time, the linker provides the RPC-receiver and the necessary tables to support it. A call on Establish_RPC_Receiver is inserted just before the call on the main subprogram. @end{ImplNote} @begin{Reason} The interface between the PCS (the System.RPC package) and the RPC-receiver is defined to be dynamic in order to allow the elaboration sequence to notify the PCS that all packages have been elaborated and that it is safe to call the receiving stubs. It is not guaranteed that the PCS units will be the last to be elaborated, so some other indication that elaboration is complete is needed. @end{Reason} If a call on Do_RPC is aborted, a cancellation message is sent to the called partition, to request that the execution of the remotely called subprogram be aborted. @begin{Honest} The full effects of this message are dependent on the implementation of the PCS. @end{Honest} @PDefn2{Term=[potentially blocking operation],Sec=(RPC operations)} @PDefn2{Term=[blocking, potentially],Sec=(RPC operations)} The subprograms declared in System.RPC are potentially blocking operations. @end{RunTime} @begin{ImplReq} The implementation of the RPC-receiver shall be reentrant@Redundant[, thereby allowing concurrent calls on it from the PCS to service concurrent remote subprogram calls into the partition]. @begin{Reason} There seems no reason to allow the implementation of RPC-receiver to be nonreentrant, even though we don't require that every implementation of the PCS actually perform concurrent calls on the RPC-receiver. @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[1],Text=[An implementation shall not restrict the replacement of the body of System.RPC. An implementation shall not restrict children of System.RPC. @Redundant[The related implementation permissions in the introduction to Annex A do not apply.]]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The point of System.RPC is to let the user tailor the communications mechanism without requiring changes to or other cooperation from the compiler. However, implementations can restrict the replacement of language-defined units. This requirement overrides that permission for System.RPC.]} @end{Reason} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[1],Text=[If the implementation of System.RPC is provided by the user, an implementation shall support remote subprogram calls as specified.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00273-01]} @ChgAdded{Version=[2],Text=[If the implementation takes advantage of the implementation permission to use a different specification for System.RPC, it still needs to use it for remote subprogram calls, and allow the user to replace the body of System.RPC. It just isn't guaranteed to be portable to do so in Ada 2005 - an advantage which was more theoretical than real anyway.]} @end{Discussion} @end{ImplReq} @begin{DocReq} The implementation of the PCS shall document whether the RPC-receiver is invoked from concurrent tasks. If there is an upper limit on the number of such tasks, this limit shall be documented as well, together with the mechanisms to configure it (if this is supported). @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of the PCS.]}]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Whether the RPC-receiver is invoked from concurrent tasks, and if so, the number of such tasks.]}]} @end{DocReq} @begin{ImplPerm} The PCS is allowed to contain implementation-defined interfaces for explicit message passing, broadcasting, etc. Similarly, it is allowed to provide additional interfaces to query the state of some remote partition (given its partition ID) or of the PCS itself, to set timeouts and retry parameters, to get more detailed error status, etc. These additional interfaces should be provided in child packages of System.RPC. @ImplDef{Implementation-defined interfaces in the PCS.} A body for the package System.RPC need not be supplied by the implementation. @begin{Reason} It is presumed that a body for the package System.RPC might be extremely environment specific. Therefore, we do not require that a body be provided by the (compiler) implementation. The user will have to write a body, or acquire one, appropriate for the target environment. @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00273-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[An alternative declaration is allowed for package System.RPC as long as it provides a set of operations that is substantially equivalent to the specification defined in this @Chg{Version=[3],New=[subclause],Old=[clause]}.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Experience has proved that the definition of System.RPC given here is inadequate for interfacing to existing distribution mechanisms (such as CORBA), especially on heterogeneous systems. Rather than mandate a change in the mechanism (which would break existing systems), require implementations to support multiple mechanisms (which is impractical), or prevent the use of Annex E facilities with existing systems (which would be silly), we simply make this facility optional.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[One of the purposes behind System.RPC was that knowledgeable users, rather than compiler vendors, could create this package tailored to their networks. Experience has shown that users get their RPC from vendors anyway; users have not taken advantage of the flexibility provided by this defined interface. Moreover, one could compare this defined interface to requiring Ada compilers to use a defined interface to implement tasking. No one thinks that the latter is a good idea, why should anyone believe that the former is?]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[Therefore, this @Chg{Version=[3],New=[subclause],Old=[clause]} is made optional. We considered deleting the @Chg{Version=[3],New=[subclause],Old=[clause]} outright, but we still require that users may replace the package (whatever its interface). Also, it still provides a useful guide to the implementation of this feature.]} @end{Reason} @end{ImplPerm} @begin{ImplAdvice} Whenever possible, the PCS on the called partition should allow for multiple tasks to call the RPC-receiver with different messages and should allow them to block until the corresponding subprogram body returns. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The PCS should allow for multiple tasks to call the RPC-receiver.]}]} The Write operation on a stream of type Params_Stream_Type should raise Storage_Error if it runs out of space trying to write the Item into the stream. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The System.RPC.Write operation should raise Storage_Error if it runs out of space when writing an item.]}]} @begin{ImplNote} An implementation could also dynamically allocate more space as needed, only propagating Storage_Error if the @nt<allocator> it calls raises Storage_Error. This storage could be managed through a controlled component of the stream object, to ensure that it is reclaimed when the stream object is finalized. @end{ImplNote} @end{ImplAdvice} @begin{Notes} The package System.RPC is not designed for direct calls by user programs. It is instead designed for use in the implementation of remote subprograms calls, being called by the calling stubs generated for a remote call interface library unit to initiate a remote call, and in turn calling back to an RPC-receiver that dispatches to the receiving stubs generated for the body of a remote call interface, to handle a remote call received from elsewhere. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00273-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The specification of System.RPC can now be tailored for an implementation. If a program replaces the body of System.RPC with a user-defined body, it might not compile in a given implementation of Ada 2005 (if the specification of System.RPC has been changed).]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0087],ARef=[AI95-00082-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the user can replace System.RPC.]} @end{DiffWord95} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/front_matter.mss�����������������������������������������������������0000755�0001752�0001001�00000212425�12066652506�020663� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(frontmatter, root="ada.mss") @comment{$Source: e:\\cvsroot/ARM/Source/front_matter.mss,v $} @comment{$Revision: 1.80 $ $Date: 2012/12/14 04:10:49 $} @comment{@begin{Comment} (*Removed the below for Ada 2012, which is supposely going to be processed as a revision*) @ChgNote{Following is a foreword for the consolidated edition of the RM/AARM.} @UnNumberedSection(Foreword to this version of the Ada Reference Manual) @ChgNote{The above has to be manually commented out if creating "original" RMs. We shouldn't need to do that again.} @ChgNote{We needed boilerplate like this to avoid objections from various outside parties. It seems unlikely that the same objections won't be raised again.} @begin{Intro} @begin{NotISO} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The International Standard for the programming language Ada is ISO/IEC 8652:1995(E).]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The Ada Working Group ISO/IEC JTC 1/SC 22/WG 9 is tasked by ISO with the work item to interpret and maintain the International Standard and to produce Technical Corrigenda, as appropriate. The technical work on the International Standard is performed by the Ada Rapporteur Group (ARG) of WG 9. In September 2000, WG 9 approved and forwarded Technical Corrigendum 1 to SC 22 for ISO approval, which was granted in February 2001. Technical Corrigendum 1 was published in June 2001.]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @ChgAdded{Version=[2],Text=[In October 2002, WG 9 approved a schedule and guidelines for the preparation of an Amendment to the International Standard. WG 9 approved the scope of the Amendment in June 2004. In April 2006, WG 9 approved and forwarded the Amendment to SC 22 for approval, which was granted in August 2006. Final ISO/IEC approval @Chg{Version=[3],New=[came in January 2007, and the Amendment was published as ISO/IEC 8652:1995/Amd 1:2007(E) in March],Old=[is expected by early]} 2007.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[In November 2008, WG 9 requested the preparation of a second Amendment to the International Standard. The completion of Amendment 2 is expected at the end of 2010, with final approval in 2011.]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[The Technical Corrigendum lists the individual changes that need to be made to the text of the International Standard to correct errors, omissions or inconsistencies. The corrections specified in Technical Corrigendum 1 are part of the International Standard ISO/IEC 8652:1995(E).]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @ChgAdded{Version=[2],Text=[Similarly, Amendment 1 @Chg{Version=[3],New=[and Amendment 2 list],Old=[lists]} the individual changes that need to be made to the text of the International Standard to add new features as well as correct errors.]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[When ISO published Technical Corrigendum 1, it did not also publish a document that merges the @Chg{Version=[2],New=[changes from the ],Old=[]}Technical Corrigendum @Chg{Version=[2],New=[],Old=[changes ]}into the text of the International Standard.@Chg{Version=[2],New=[ @Chg{Version=[3], New=[Similarly,],Old=[It is not known whether]} ISO @Chg{Version=[3],New=[did not],Old=[will]} publish a document that merges the changes from Technical Corrigendum and Amendment 1 into the text of the International Standard.],Old=[]}@Chg{Version=[3],New=[ It is not known whether ISO will publish a document that merges the changes from Technical Corrigendum 1, Amendment 1, and Amendment 2 into the text of the International Standard.],Old=[]} However, ISO rules require that the project editor for the @Chg{Version=[2],New=[International Standard], Old=[Technical Corrigendum]} be able to produce such a document on demand.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[This version of the Ada Reference Manual is what the project editor would provide to ISO in response to such a request. It incorporates the changes specified in the Technical Corrigendum @Chg{Version=[2],New=[and @Chg{Version=[3],New=[Amendments 1 and 2],Old=[Amendment]} ],Old=[]}into the text of ISO/IEC 8652:1995(E). It should be understood that the publication of any ISO document involves changes in general format, boilerplate, headers, etc., as well as a review by professional editors that may introduce editorial changes to the text. This version of the Ada Reference Manual is therefore neither an official ISO document, nor a version guaranteed to be identical to an official ISO document, should ISO decide to reprint the International Standard incorporating an approved Technical Corrigendum@Chg{Version=[2],New=[ and @Chg{Version=[3],New=[Amendments],Old=[Amendment]}], Old=[]}. It is nevertheless a best effort to be as close as possible to the technical content of such an updated document. In the case of a conflict between this document and @Chg{Version=[2],New=[Amendment],Old=[Technical Corrigendum]} @Chg{Version=[3],New=[2],Old=[1]} as approved by ISO (or between this document and@Chg{Version=[3],New=[ Amendment 1 in the case of paragraphs not changed by Amendment 2; or between this document and],Old=[]} @Chg{Version=[2],New=[Technical Corrigendum 1 in the case of paragraphs not changed by @Chg{Version=[3],New=[either ],Old=[]}Amendment@Chg{Version=[3],New=[],Old=[ 1]}; or between this document and ],Old=[]}the original 8652:1995 in the case of paragraphs not changed by @Chg{Version=[2], New=[either Amendment@Chg{Version=[3],New=[],Old=[ 1]} or ], Old=[]}Technical Corrigendum 1), the other documents contain the official text of the International Standard ISO/IEC 8652:1995(E)@Chg{Version=[2],New=[ and its @Chg{Version=[3],New=[Amendments],Old=[Amendment]}],Old=[]}.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[As it is very inconvenient to have the Reference Manual for Ada specified in @Chg{Version=[2],New=[@Chg{Version=[3],New=[four],Old=[three]}], Old=[two]} documents, this consolidated version of the Ada Reference Manual is made available to the public.],Old=[]} @end{NotISO} @end{Intro} (*End of Foreword Foreword, not needed for Ada 2012*) @end{Comment}} @UnNumberedSection(Foreword) @begin{Intro} @ChgRef{Version=[3],Kind=[Revised]}@ChgNote{Updated boilerplate} ISO (the International Organization for Standardization) and IEC (the International Electrotechnical Commission) form the specialized system for worldwide standardization. National bodies that are members of ISO or IEC participate in the development of International Standards through technical committees established by the respective organization to deal with particular fields of technical activity. ISO and IEC technical committees collaborate in fields of mutual interest. Other international organizations, governmental and non-governmental, in liaison with ISO and IEC, also take part in the work.@Chg{Version=[3],New=[ In the field of information technology, ISO and IEC have established a joint technical committee, ISO/IEC JTC 1.],Old=[]} @ChgRef{Version=[3],Kind=[Added]}@ChgNote{Updated boilerplate} @ChgAdded{Version=[3],Text=[International Standards are drafted in accordance with the rules given in the ISO/IEC Directives, Part 2.]} @ChgRef{Version=[3],Kind=[Revised]}@ChgNote{Updated boilerplate} @Chg{Version=[3],New=[The main task of the],Old=[In the field of information technology, ISO and IEC have established a]} joint technical committee@Chg{Version=[3],New=[ is to prepare International Standards],Old=[, ISO/IEC JTC 1]}. Draft International Standards adopted by the joint technical committee are circulated to national bodies for voting. Publication as an International Standard requires approval by at least 75 % of the national bodies casting a vote. @ChgRef{Version=[3],Kind=[Added]}@ChgNote{Updated boilerplate} @ChgAdded{Version=[3],Text=[Attention is drawn to the possibility that some of the elements of this document may be the subject of patent rights. ISO and IEC shall not be held responsible for identifying any or all such patent rights.]} @ChgRef{Version=[3],Kind=[Revised]} International Standard ISO/IEC 8652 was prepared by Joint Technical Committee ISO/IEC JTC 1, @i{Information Technology}@Chg{Version=[3],New=[ Subcommittee SC22, @i{Programming languages, their environments and system software interfaces}],Old=[]}. @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[third],Old=[@Chg{Version=[2],New=[consolidated],Old=[second]}]} edition @Chg{Version=[3],New=[cancels and replaces],Old=[@Chg{Version=[2], New=[updates],Old=[cancels and replaces]}]} the @Chg{Version=[2],New=[second],Old=[first]} edition (ISO@Chg{Version=[3],New=[/IEC],Old=[]} 8652:@Chg{Version=[2],New=[1995)],Old=[1987), of which it constitutes a technical revision]}@Chg{Version=[3],New=[, which has been technically revised. It also incorporates the Technical Corrigendum ISO/IEC 8652:1995:COR.1:2001 and Amendment ISO/IEC 8652:1995:AMD 1:2007],Old=[]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The above is unofficial wording added just to avoid confusion. If ISO decides to publish a new standard, the above would be replaced by @ldquote@;This third edition cancels and replaces the second edition (ISO 8652:1995), of which it constitutes a technical revision@rdquote. The first three paragraphs in this section also would be replaced by the current ISO boilerplate.]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0299-1]} @ChgDeleted{Version=[3],Text=[Annexes A to J form an integral part of this International Standard. Annexes K to @Chg{Version=[2],New=[Q],Old=[P]} are for information only.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised]} This document is the Annotated Ada Reference Manual (AARM). It contains the entire text of the Ada @Chg{Version=[3],New=[2012],Old=[95]} standard (ISO/IEC 8652:@Chg{Version=[3],New=[201x],Old=[1995]}), plus various annotations. It is intended primarily for compiler writers, validation test writers, and other language lawyers. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. @end{Discussion} @end{Intro} @begin{Comment} (*Was Syntax9XOnly - We don't generate this document anymore*) This document lists the syntax rules of Ada 95. @end{Comment} @begin{Comment} (*Was Chg839XOnly - We don't generate this document anymore*) This document lists in detail the changes introduced in the second (Ada 95) edition of the Ada standard (ISO/IEC 8652:1995) with respect to the first (Ada 83) edition (ISO 8652:1987). @end{Comment} @UnNumberedSection{Introduction} @begin{Intro} @begin{NotISO} @begin{AARMOnly} This is the Annotated Ada Reference Manual. @end{AARMOnly} @begin{RMOnly} This is the Ada Reference Manual. @end{RMOnly} @Leading@;Other available Ada documents include: @comment{We have to put the itemize inside of the AARMOnly, because otherwise the formatter thinks this is a nested bullet, making a mess. Since this is the only place this is used, it is easier to fix the text than the program. RLB - 2000-05-17} @begin{AARMOnly} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0245-1]} @Chg{Version=[3],New=[Ada 2012 Rationale. This gives an introduction to the changes and new features in Ada 2012, and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth. Rationales for Ada 83, Ada 95, and Ada 2005 are also available.],Old=[@Chg{Version=[2],New=[Ada 95 Rationale. This],Old=[Rationale for the Ada Programming Language @em 1995 edition, which]} gives an introduction to the new features of Ada@Chg{Version=[2],New=[ incorporated in the 1995 edition of this Standard],Old=[]}, and explains the rationale behind them. Programmers @Chg{Version=[2],New=[unfamiliar with Ada 95 ], Old=[]}should read this first.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0245-1]} @ChgAdded{Version=[3],Text=[As of this writing (December 2012), only five chapters of the Ada 2012 Rationale have been published. Additional chapters are in development and should be published during 2013.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0245-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Ada 2005 Rationale. This gives an introduction to the changes and new features in Ada 2005 (compared with the 1995 edition), and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth.]}]} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1],Text=[Changes to Ada @em 1987 to 1995. This document lists in detail the changes made to the 1987 edition of the standard.]} @ChgRef{Version=[3],Kind=[Revised]} The Ada Reference Manual (RM). This is the International Standard @em ISO/IEC 8652:@Chg{Version=[3],New=[201x],Old=[1995]}. @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Technical Corrigendum 1 @em ISO/IEC 8652:1995:COR.1:2001. This document lists corrections to the International Standard.]}]}@ChgNote{This is consolidated into the Ada 2012 RM} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Amendment 1 @em ISO/IEC 8652:1995:AMD 1:2007. This document outlines additional features and corrections to the International Standard.]}]}@ChgNote{This is consolidated into the Ada 2012 RM} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The consolidated Ada Reference Manual. An @i{unofficial} document combining the above three documents into a single document.]}]} @end{Itemize} @end{AARMOnly} @begin{RMOnly} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0245-1]} @Chg{Version=[3],New=[Ada 2012 Rationale. This gives an introduction to the changes and new features in Ada 2012, and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth. Rationales for Ada 83, Ada 95, and Ada 2005 are also available.],Old=[@Chg{Version=[2],New=[Ada 95 Rationale. This],Old=[Rationale for the Ada Programming Language @em 1995 edition, which]} gives an introduction to the new features of Ada@Chg{Version=[2],New=[ incorporated in the 1995 edition of this Standard],Old=[]}, and explains the rationale behind them. Programmers @Chg{Version=[2],New=[unfamiliar with Ada 95 ], Old=[]}should read this first.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0245-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Ada 2005 Rationale. This gives an introduction to the changes and new features in Ada 2005 (compared with the 1995 edition), and explains the rationale behind them. Programmers should read this rationale before reading this Standard in depth.]}]} @ChgRef{Version=[1],Kind=[Deleted]} @ChgDeleted{Version=[1], Text=[Changes to Ada @em 1987 to 1995. This document lists in detail the changes made to the 1987 edition of the standard.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[Revised]} The Annotated Ada Reference Manual (AARM).@Defn{Annotated Ada Reference Manual} @Defn{AARM}The AARM contains all of the text in @Chg{Version=[3],New=[this International Standard], Old=[@Chg{Version=[2],New=[the consolidated Ada Reference Manual],Old=[the RM95]}]}, @ChgNote{Version=[2]: John had "this International Standard", but it's really related to the unofficial document. Change it back if ISO decides to publish this consolidated RM.} @ChgNote{Version=[3]: Changed back for Ada 2012.} plus various annotations. It is intended primarily for compiler writers, validation test writers, and others who wish to study the fine details. The annotations include detailed rationale for individual rules and explanations of some of the more arcane interactions among the rules. @end{Itemize} @end{RMOnly} @end{NotISO} @end{Intro} @SubHeading(Design Goals) @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[Revised]} Ada was originally designed with three overriding concerns: program reliability and maintenance, programming as a human activity, and efficiency. @Chg{Version=[2],New=[The 1995],Old=[This]} revision to the language was designed to provide greater flexibility and extensibility, additional control over storage management and synchronization, and standardized packages oriented toward supporting important application areas, while at the same time retaining the original emphasis on reliability, maintainability, and efficiency.@Chg{Version=[2],New=[ This @Chg{Version=[3],New=[third edition],Old=[amended version]} provides further flexibility and adds more standardized packages within the framework provided by the 1995 revision.],Old=[]} The need for languages that promote reliability and simplify maintenance is well established. Hence emphasis was placed on program readability over ease of writing. For example, the rules of the language require that program variables be explicitly declared and that their type be specified. Since the type of a variable is invariant, compilers can ensure that operations on variables are compatible with the properties intended for objects of the type. Furthermore, error-prone notations have been avoided, and the syntax of the language avoids the use of encoded forms in favor of more English-like constructs. Finally, the language offers support for separate compilation of program units in a way that facilitates program development and maintenance, and which provides the same degree of checking between units as within a unit. Concern for the human programmer was also stressed during the design. Above all, an attempt was made to keep to a relatively small number of underlying concepts integrated in a consistent and systematic way while continuing to avoid the pitfalls of excessive involution. The design especially aims to provide language constructs that correspond intuitively to the normal expectations of users. Like many other human activities, the development of programs is becoming ever more decentralized and distributed. Consequently, the ability to assemble a program from independently produced software components continues to be a central idea in the design. The concepts of packages, of private types, and of generic units are directly related to this idea, which has ramifications in many other aspects of the language. An allied concern is the maintenance of programs to match changing requirements; type extension and the hierarchical library enable a program to be modified while minimizing disturbance to existing tested and trusted components. No language can avoid the problem of efficiency. Languages that require over-elaborate compilers, or that lead to the inefficient use of storage or execution time, force these inefficiencies on all machines and on all programs. Every construct of the language was examined in the light of present implementation techniques. Any proposed construct whose implementation was unclear or that required excessive machine resources was rejected. @end{Intro} @SubHeading{Language Summary} @begin{Intro} An Ada program is composed of one or more program units. Program units may be subprograms (which define executable algorithms), packages (which define collections of entities), task units (which define concurrent computations), protected units (which define operations for the coordinated sharing of data between tasks), or generic units (which define parameterized forms of packages and subprograms). Each program unit normally consists of two parts: a specification, containing the information that must be visible to other units, and a body, containing the implementation details, which need not be visible to other units. Most program units can be compiled separately. This distinction of the specification and body, and the ability to compile units separately, allows a program to be designed, written, and tested as a set of largely independent software components. An Ada program will normally make use of a library of program units of general utility. The language provides means whereby individual organizations can construct their own libraries. All libraries are structured in a hierarchical manner; this enables the logical decomposition of a subsystem into individual components. The text of a separately compiled program unit must name the library units it requires. @keepnext@i(Program Units) A subprogram is the basic unit for expressing an algorithm. There are two kinds of subprograms: procedures and functions. A procedure is the means of invoking a series of actions. For example, it may read data, update variables, or produce some output. It may have parameters, to provide a controlled means of passing information between the procedure and the point of call. A function is the means of invoking the computation of a value. It is similar to a procedure, but in addition will return a result. A package is the basic unit for defining a collection of logically related entities. For example, a package can be used to define a set of type declarations and associated operations. Portions of a package can be hidden from the user, thus allowing access only to the logical properties expressed by the package specification. Subprogram and package units may be compiled separately and arranged in hierarchies of parent and child units giving fine control over visibility of the logical properties and their detailed implementation. A task unit is the basic unit for defining a task whose sequence of actions may be executed concurrently with those of other tasks. Such tasks may be implemented on multicomputers, multiprocessors, or with interleaved execution on a single processor. A task unit may define either a single executing task or a task type permitting the creation of any number of similar tasks. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} A protected unit is the basic unit for defining protected operations for the coordinated use of data shared between tasks. Simple mutual exclusion is provided automatically, and more elaborate sharing protocols can be defined. A protected operation can either be a subprogram or an entry. A protected entry specifies a Boolean expression (an entry barrier) that must be @Chg{Version=[2],New=[True],Old=[true]} before the body of the entry is executed. A protected unit may define a single protected object or a protected type permitting the creation of several similar objects. @keepnext@i(Declarations and Statements) The body of a program unit generally contains two parts: a declarative part, which defines the logical entities to be used in the program unit, and a sequence of statements, which defines the execution of the program unit. The declarative part associates names with declared entities. For example, a name may denote a type, a constant, a variable, or an exception. A declarative part also introduces the names and parameters of other nested subprograms, packages, task units, protected units, and generic units to be used in the program unit. The sequence of statements describes a sequence of actions that are to be performed. The statements are executed in succession (unless a transfer of control causes execution to continue from another place). An assignment statement changes the value of a variable. A procedure call invokes execution of a procedure after associating any actual parameters provided at the call with the corresponding formal parameters. Case statements and if statements allow the selection of an enclosed sequence of statements based on the value of an expression or on the value of a condition. The loop statement provides the basic iterative mechanism in the language. A loop statement specifies that a sequence of statements is to be executed repeatedly as directed by an iteration scheme, or until an exit statement is encountered. A block statement comprises a sequence of statements preceded by the declaration of local entities used by the statements. Certain statements are associated with concurrent execution. A delay statement delays the execution of a task for a specified duration or until a specified time. An entry call statement is written as a procedure call statement; it requests an operation on a task or on a protected object, blocking the caller until the operation can be performed. A called task may accept an entry call by executing a corresponding accept statement, which specifies the actions then to be performed as part of the rendezvous with the calling task. An entry call on a protected object is processed when the corresponding entry barrier evaluates to true, whereupon the body of the entry is executed. The requeue statement permits the provision of a service as a number of related activities with preference control. One form of the select statement allows a selective wait for one of several alternative rendezvous. Other forms of the select statement allow conditional or timed entry calls and the asynchronous transfer of control in response to some triggering event. Execution of a program unit may encounter error situations in which normal program execution cannot continue. For example, an arithmetic computation may exceed the maximum allowed value of a number, or an attempt may be made to access an array component by using an incorrect index value. To deal with such error situations, the statements of a program unit can be textually followed by exception handlers that specify the actions to be taken when the error situation arises. Exceptions can be raised explicitly by a raise statement. @keepnext@i(Data Types) Every object in the language has a type, which characterizes a set of values and a set of applicable operations. The main classes of types are elementary types (comprising enumeration, numeric, and access types) and composite types (including array and record types). @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00387-01]} An enumeration type defines an ordered set of distinct enumeration literals, for example a list of states or an alphabet of characters. The enumeration types Boolean, Character, @Chg{Version=[2],New=[], Old=[and ]}Wide_Character@Chg{Version=[2],New=[, and Wide_Wide_Character], Old=[]} are predefined. Numeric types provide a means of performing exact or approximate numerical computations. Exact computations use integer types, which denote sets of consecutive integers. Approximate computations use either fixed point types, with absolute bounds on the error, or floating point types, with relative bounds on the error. The numeric types Integer, Float, and Duration are predefined. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00387-01]} Composite types allow definitions of structured objects with related components. The composite types in the language include arrays and records. An array is an object with indexed components of the same type. A record is an object with named components of possibly different types. Task and protected types are also forms of composite types. The array types String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2], New=[, and Wide_Wide_String],Old=[]} are predefined. Record, task, and protected types may have special components called discriminants which parameterize the type. Variant record structures that depend on the values of discriminants can be defined within a record type. Access types allow the construction of linked data structures. A value of an access type represents a reference to an object declared as aliased or to an object created by the evaluation of an allocator. Several variables of an access type may designate the same object, and components of one object may designate the same or other objects. Both the elements in such linked data structures and their relation to other elements can be altered during program execution. Access types also permit references to subprograms to be stored, passed as parameters, and ultimately dereferenced as part of an indirect call. Private types permit restricted views of a type. A private type can be defined in a package so that only the logically necessary properties are made visible to the users of the type. The full structural details that are externally irrelevant are then only available within the package and any child units. From any type a new type may be defined by derivation. A type, together with its derivatives (both direct and indirect) form a derivation class. Class-wide operations may be defined that accept as a parameter an operand of any type in a derivation class. For record and private types, the derivatives may be extensions of the parent type. Types that support these object-oriented capabilities of class-wide operations and type extension must be tagged, so that the specific type of an operand within a derivation class can be identified at run time. When an operation of a tagged type is applied to an operand whose specific type is not known until run time, implicit dispatching is performed based on the tag of the operand. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgAdded{Version=[2],Text=[ Interface types provide abstract models from which other interfaces and types may be composed and derived. This provides a reliable form of multiple inheritance. Interface types may also be implemented by task types and protected types thereby enabling concurrent programming and inheritance to be merged.]} The concept of a type is further refined by the concept of a subtype, whereby a user can constrain the set of allowed values of a type. Subtypes can be used to define subranges of scalar types, arrays with a limited set of index values, and records and private types with particular discriminant values. @keepnext@i(Other Facilities) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[Aspect],Old=[Representation]} clauses can be used to specify the mapping between types and features of an underlying machine. For example, the user can specify that objects of a given type must be represented with a given number of bits, or that the components of a record are to be represented using a given storage layout. Other features allow the controlled use of low level, nonportable, or implementation-dependent aspects, including the direct insertion of machine code. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} The predefined environment of the language provides for input-output and other capabilities @Chg{Version=[2],New=[],Old=[(such as string manipulation and random number generation) ]}by means of standard library packages. Input-output is supported for values of user-defined as well as of predefined types. Standard means of representing values in display form are also provided.@Chg{Version=[2],New=[],Old=[ Other standard library packages are defined in annexes of the standard to support systems with specialized requirements.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[The predefined standard library packages provide facilities such as string manipulation, containers of various kinds (vectors, lists, maps, etc.), mathematical functions, random number generation, and access to the execution environment.],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @Chg{Version=[2],New=[The specialized annexes define further predefined library packages and facilities with emphasis on areas such as real-time scheduling, interrupt handling, distributed systems, numerical computation, and high-integrity systems.],Old=[]} Finally, the language provides a powerful means of parameterization of program units, called generic program units. The generic parameters can be types and subprograms (as well as objects and packages) and so allow general algorithms and data structures to be defined that are applicable to all types of a given class. @end{Intro} @SubHeading{Language Changes} @begin{Intro} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 44 through 57 have been removed as they described differences from the first edition of Ada (Ada 83).>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Type=[Leading],Text=[This @Chg{Version=[2],New=[amended ],Old=[]}International Standard @Chg{Version=[2],New=[updates the edition of 1995 which replaced], Old=[replaces]} the first edition of 1987. In @Chg{Version=[2],New=[the 1995],Old=[this]} edition, the following major language changes @Chg{Version=[2],New=[were],Old=[have been]} incorporated:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[Support for standard 8-bit and 16-bit character@Chg{Version=[2],New=[s was added],Old=[ sets]}. See @Chg{Version=[2],New=[clauses @RefSecNum{Character Set}],Old=[Section 2]}, @RefSecNum{Character Types}, @RefSecNum{String Types}, @RefSecNum{The Package Standard}, @RefSecNum{Character Handling}, and @RefSecNum{String Handling}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[The type model was extended to include facilities for o],Old=[O]}bject-oriented programming with @Chg{Version=[2],New=[dynamic],Old=[run-time]} polymorphism. See the discussions of classes, derived types, tagged types, record extensions, and private extensions in clauses @RefSecNum{Derived Types and Classes}, @RefSecNum{Tagged Types and Type Extensions}, and @RefSecNum{Private Types and Private Extensions}. @Chg{Version=[2],New=[Additional],Old=[See also the new]} forms of generic formal parameters @Chg{Version=[2],New=[were],Old=[that are]} allowed @Chg{Version=[2],New=[as described in clauses @RefSecNum{Formal Private and Derived Types} and @RefSecNum{Formal Packages}], Old=[by @RefSec{Formal Private and Derived Types} and @RefSec{Formal Packages}]}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[Access types @Chg{Version=[2],New=[were],Old=[have been]} extended to allow an access value to designate a subprogram or an object declared by an object declaration @Chg{Version=[2],New=[],Old=[(]}as opposed to just @Chg{Version=[2],New=[an object ],Old=[a heap-]}allocated @Chg{Version=[2],New=[on a heap],Old=[object)]}. See @Chg{Version=[2],New=[clause ],Old=[]}@RefSecNum{Access Types}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[Efficient data-oriented synchronization @Chg{Version=[2],New=[was], Old=[is]} provided @Chg{Version=[2],New=[by the introduction of], Old=[via]} protected types. See @Chg{Version=[2], New=[clause @RefSecNum{Protected Units and Protected Objects}],Old=[Section 9]}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[The library @Chg{Version=[2],New=[structure was extended to allow library units to],Old=[units of a library may]} be organized into a hierarchy of parent and child units. See @Chg{Version=[2], New=[clause @RefSecNum{Separate Compilation}], Old=[Section 10]}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[Additional support @Chg{Version=[2],New=[was],Old=[has been]} added for interfacing to other languages. See @RefSecNum{Interface to Other Languages}.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Type=[Leading],Text=[The Specialized Needs Annexes @Chg{Version=[2],New=[were],Old=[have been]} added to provide specific support for certain application areas:]} @begin{InnerItemize} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{Systems Programming}]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{Real-Time Systems}]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{Distributed Systems}]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{Information Systems}]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{Numerics}]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[3],Text=[@RefSec{High Integrity Systems}]} @end{InnerItemize} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[This International Standard replaces the second edition of 1995. It],Old=[Amendment 1]} modifies the @Chg{Version=[3],New=[previous edition],Old=[1995 International Standard]} by making changes and additions that improve the capability of the language and the reliability of programs written in the language.@Chg{Version=[3],New=[ This edition incorporates the changes from Amendment 1 (ISO/IEC 8652:1995:AMD 1:2007), which],Old=[In particular the changes]} were designed to improve the portability of programs, interfacing to other languages, and both the object-oriented and real-time capabilities.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00387-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[Significant], Old=[The following significant]} changes@Chg{Version=[3],New=[ originating in Amendment 1],Old=[with respect to the 1995 edition]} are incorporated:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[Support for program text is extended to cover the entire ISO/IEC 10646:2003 repertoire. Execution support now includes the 32-bit character set. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Character Set}, @RefSecNum{Character Types}, @RefSecNum{String Types}, @RefSecNum{The Package Standard}, @RefSecNum{Character Handling}, and @RefSecNum{String Handling}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ The object-oriented model has been improved by the addition of an interface facility which provides multiple inheritance and additional flexibility for type extensions. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Derived Types and Classes}, @RefSecNum{Tagged Types and Type Extensions}, and @RefSecNum{Private Types and Private Extensions}. An alternative notation for calling operations more akin to that used in other languages has also been added. See @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Selected Components}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ Access types have been further extended to unify properties such as the ability to access constants and to exclude null values. See clause @RefSecNum{Access Types}. Anonymous access types are now permitted more freely and anonymous access-to-subprogram types are introduced. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Objects and Named Numbers}, @RefSecNum{Array Types}, @RefSecNum{Access Types}, and @RefSecNum{Object Renaming Declarations}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ The control of structure and visibility has been enhanced to permit mutually dependent references between units and finer control over access from the private part of a package. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Incomplete Type Declarations} and @RefSecNum{Context Clauses - With Clauses}. In addition, limited types have been made more useful by the provision of aggregates, constants, and constructor functions. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Aggregates}, @RefSecNum{Return Statements}, and @RefSecNum{Limited Types}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ The predefined environment has been extended to include additional time and calendar operations, improved string handling, a comprehensive container library, file and directory management, and access to environment variables. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Formatting, Time Zones, and other operations for Time}, @RefSecNum{String Handling}, @RefSecNum{The Package Directories}, @RefSecNum{The Package Environment_Variables}, and @RefSecNum{Containers}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ Two of the Specialized Needs Annexes have been considerably enhanced:],Old=[]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[ The Real-Time Systems Annex now includes the Ravenscar profile for high-integrity systems, further dispatching policies such as Round Robin and Earliest Deadline First, support for timing events, and support for control of CPU time utilization. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Priority Scheduling}, @RefSecNum{The Ravenscar Profile}, @RefSecNum{Execution Time}, and @RefSecNum{Timing Events}.],Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ The Numerics Annex now includes support for real and complex vectors and matrices as previously defined in ISO/IEC 13813:1997 plus further basic operations for linear algebra. See @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Vector and Matrix Manipulation}.],Old=[]} @end{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=[ The overall reliability of the language has been enhanced by a number of improvements. These include new syntax which detects accidental overloading, as well as pragmas for making assertions and giving better control over the suppression of checks. See @Chg{Version=[3],New=[subclauses],Old=[clauses]} @RefSecNum{Subprogram Declarations}, @RefSecNum{Pragmas Assert and Assertion_Policy}, and @RefSecNum{Suppressing Checks}.],Old=[]} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0245-1]} @ChgAdded{Version=[3],Text=[In addition, this third edition makes enhancements to address two important issues, namely, the particular problems of multiprocessor architectures, and the need to further increase the capabilities regarding assertions for correctness. It also makes additional changes and additions that improve the capability of the language and the reliability of programs written in the language.]} @ChgNote{The original "Amendment 2" version of this text follows: Amendment 2 modifies the 1995 International Standard by making changes and additions that improve the capability of the language and the reliability of programs written in the language. In particular, enhancements are made to address two important issues, namely, the particular problems of multiprocessor architectures, and the need to further increase the capabilities regarding assertions for correctness.} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0245-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following significant changes with respect to the 1995 edition as amended by Amendment 1 are incorporated:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[New syntax (the aspect specification) is introduced to enable properties to be specified for various entities in a more structured manner than through pragmas. See subclause @RefSecNum{Aspect Specifications}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The concept of assertions introduced in the 2005 edition is extended with the ability to specify preconditions and postconditions for subprograms, and invariants for private types. The concept of constraints in defining subtypes is supplemented with subtype predicates that enable subsets to be specified other than as simple ranges. These properties are all indicated using aspect specifications. See subclauses @RefSecNum{Subtype Predicates}, @RefSecNum{Preconditions and Postconditions}, and @RefSecNum{Type Invariants}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[New forms of expressions are introduced. These are if expressions, case expressions, quantified expressions, and expression functions. As well as being useful for programming in general by avoiding the introduction of unnecessary assignments, they are especially valuable in conditions and invariants since they avoid the need to introduce auxiliary functions. See subclauses @RefSecNum{Conditional Expressions}, @RefSecNum{Quantified Expressions}, and @RefSecNum{Expression Functions}. Membership tests are also made more flexible. See subclauses @RefSecNum{Expressions} and @RefSecNum{Relational Operators and Membership Tests}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[A number of changes are made to subprogram parameters. Functions may now have parameters of all modes. In order to mitigate consequent (and indeed existing) problems of inadvertent order dependence, rules are introduced to reduce aliasing. A parameter may now be explicitly marked as aliased and the type of a parameter may be incomplete in certain circumstances. See subclauses @RefSecNum{Incomplete Type Declarations}, @RefSecNum{Subprogram Declarations}, and @RefSecNum{Parameter Associations}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The use of access types is now more flexible. The rules for accessibility and certain conversions are improved. See subclauses @RefSecNum{Operations of Access Types}, @RefSecNum{Relational Operators and Membership Tests}, @RefSecNum{Type Conversions}, and @RefSecNum{The Context of Overload Resolution}. Furthermore, better control of storage pools is provided. See subclause @RefSecNum{Storage Subpools}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The Real-Time Systems Annex now includes facilities for defining domains of processors and assigning tasks to them. Improvements are made to scheduling and budgeting facilities. See subclauses @RefSecNum{Synchronous Barriers}, @RefSecNum{Execution Time}, and @RefSecNum{Multiprocessor Implementation}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[A number of important improvements are made to the standard library. These include packages for conversions between strings and UTF encodings, and classification functions for wide and wide wide characters. Internationalization is catered for by a package giving locale information. See subclauses @RefSecNum{Character Handling}, @RefSecNum{String Encoding}, and @RefSecNum{The Package Locales}. The container library is extended to include bounded forms of the existing containers and new containers for indefinite objects, multiway trees, and queues. See subclause @RefSecNum{Containers}.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Finally, certain features are added primarily to ease the use of containers, such as the ability to iterate over all elements in a container without having to encode the iteration. These can also be used for iteration over arrays, and within quantified expressions. See subclauses @RefSecNum{User-Defined References}, @RefSecNum{User-Defined Indexing}, @RefSecNum{User-Defined Iterator Types}, and @RefSecNum{Generalized Loop Iteration}.]} @end{Itemize} @end{Intro} @NewPage @SubHeading(Instructions for Comment Submission) @begin{Intro} @ChgRef{Version=[1],Kind=[Revised]} @Defn{instructions for comment submission} @Defn{comments, instructions for submission} Informal comments on this International Standard may be sent via e-mail to @Chg{New=[@b(ada-comment@@ada-auth.org)], Old=[@b(ada-comment@@sw-eng.falls-church.va.us)]}. If appropriate, the Project Editor will initiate the defect correction procedure. Comments should use the following format: @begin(display) @ChgRef{Version=[2],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised]} @TabSet(L6)@\@b(!topic) @i[Title summarizing comment] @\@b(!reference) @Chg{Version=[2],New=[Ada @Chg{Version=[3],New=[2012],Old=[2005]} RM],Old=[RM95-]}@i{ss.ss(pp)} @\@b(!from) @i{Author Name yy-mm-dd} @\@b(!keywords) @i{keywords related to topic} @\@b(!discussion) @comment{Blank line} @\@i{text of discussion} @end(display) @ChgRef{Version=[3],Kind=[Revised]} where @i(ss.ss) is the @Chg{Version=[3],New=[],Old=[section, ]}clause or subclause number, @i(pp) is the paragraph number where applicable, and @i(yy-mm-dd) is the date the comment was sent. The date is optional, as is the @b(!keywords) line. @ChgRef{Version=[1],Kind=[Revised]} @Chg{New=[], Old=[Multiple comments per e-mail message are acceptable.]} Please use a descriptive @lquotes@;Subject@rquotes@; in your e-mail message@Chg{New=[, and limit each message to a single comment.], Old=[.]} When correcting typographical errors or making minor wording suggestions, please put the correction directly as the topic of the comment; use square brackets [ ] to indicate text to be omitted and curly braces { } to indicate text to be added, and provide enough context to make the nature of the suggestion self-evident or put additional information in the body of the comment, for example: @begin{Display} @TabSet(L6)@\@b(!topic) [c]{C}haracter @\@b(!topic) it[']s meaning is not defined @end{Display} Formal requests for interpretations and for reporting defects in this International Standard may be made in accordance with the ISO/IEC JTC 1 Directives and the ISO/IEC JTC 1/SC 22 policy for interpretations. National Bodies may submit a Defect Report to ISO/IEC JTC 1/SC 22 for resolution under the JTC 1 procedures. A response will be provided and, if appropriate, a Technical Corrigendum will be issued in accordance with the procedures. @end{Intro} @begin{NotISO} @NewPage @AddedSubHeading{Version=[3],Acknowledgements for the Ada 83 edition} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Ada is the result of a collective effort to design a common language for programming large scale and real-time systems.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The common high order language program began in 1974. The requirements of the United States Department of Defense were formalized in a series of documents which were extensively reviewed by the Services, industrial organizations, universities, and foreign military departments. The Ada language was designed in accordance with the final (1978) form of these requirements, embodied in the Steelman specification.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The Ada design team was led by Jean D. Ichbiah and has included Bernd Krieg-Brueckner, Brian A. Wichmann, Henry F. Ledgard, Jean-Claude Heliard, Jean-Loup Gailly, Jean-Raymond Abrial, John G.P. Barnes, Mike Woodger, Olivier Roubine, Paul N. Hilfinger, and Robert Firth.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[At various stages of the project, several people closely associated with the design team made major contributions. They include J.B. Goodenough, R.F. Brender, M.W. Davis, G. Ferran, K. Lester, L. MacLaren, E. Morel, I.R. Nassi, I.C. Pyle, S.A. Schuman, and S.C. Vestal.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Two parallel efforts that were started in the second phase of this design had a deep influence on the language. One was the development of a formal definition using denotational semantics, with the participation of V. Donzeau-Gouge, G. Kahn, and B. Lang. The other was the design of a test translator with the participation of K. Ripken, P. Boullier, P. Cadiou, J. Holden, J.F. Hueras, R.G. Lange, and D.T. Cornhill. The entire effort benefitted from the dedicated assistance of Lyn Churchill and Marion Myers, and the effective technical support of B. Gravem, W.L. Heimerdinger, and P. Cleve. H.G. Schmitz served as program manager.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Over the five years spent on this project, several intense week-long design reviews were conducted, with the participation of P. Belmont, B. Brosgol, P. Cohen, R. Dewar, A. Evans, G. Fisher, H. Harte, A.L. Hisgen, P. Knueven, M. Kronental, N. Lomuto, E. Ploedereder, G. Seegmueller, V. Stenning, D. Taffs, and also F. Belz, R. Converse, K. Correll, A.N. Habermann, J. Sammet, S. Squires, J. Teller, P. Wegner, and P.R. Wetherall.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Several persons had a constructive influence with their comments, criticisms and suggestions. They include P. Brinch Hansen, G. Goos, C.A.R. Hoare, Mark Rain, W.A. Wulf, and also E. Boebert, P. Bonnard, H. Clausen, M. Cox, G. Dismukes, R. Eachus, T. Froggatt, H. Ganzinger, C. Hewitt, S. Kamin, R. Kotler, O. Lecarme, J.A.N. Lee, J.L. Mansion, F. Minel, T. Phinney, J. Roehrich, V. Schneider, A. Singer, D. Slosberg, I.C. Wand, the reviewers of Ada-Europe, AdaTech, Afcet, those of the LMSC review team, and those of the Ada Tokyo Study Group.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[These reviews and comments, the numerous evaluation reports received at the end of the first and second phase, the nine hundred language issue reports and test and evaluation reports received from fifteen different countries during the third phase of the project, the thousands of comments received during the ANSI Canvass, and the on-going work of the IFIP Working Group 2.4 on system implementation languages and that of the Purdue Europe LTPL-E committee, all had a substantial influence on the final definition of Ada.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The Military Departments and Agencies have provided a broad base of support including funding, extensive reviews, and countless individual contributions by the members of the High Order Language Working Group and other interested personnel. In particular, William A. Whitaker provided leadership for the program during the formative stages. David A. Fisher was responsible for the successful development and refinement of the language requirement documents that led to the Steelman specification.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The Ada 83 language definition was developed by Cii Honeywell Bull and later Alsys, and by Honeywell Systems and Research Center, under contract to the United States Department of Defense. William E. Carlson and later Larry E. Druffel served as the technical representatives of the United States Government and effectively coordinated the efforts of all participants in the Ada program.]} @SubHeading(Acknowledgements@Chg{Version=[2],New=[ for the Ada 95 edition],Old=[]}) @begin{Intro} This International Standard was prepared by the Ada 9X Mapping/Revision Team based at Intermetrics, Inc., which has included: W. Carlson, Program Manager; T. Taft, Technical Director; J. Barnes (consultant); B. Brosgol (consultant); R. Duff (Oak Tree Software); M. Edwards; C. Garrity; R. Hilliard; O. Pazy (consultant); D. Rosenfeld; L. Shafer; W. White; M. Woodger. The following consultants to the Ada 9X Project contributed to the Specialized Needs Annexes: T. Baker (Real-Time/Systems Programming @em SEI, FSU); K. Dritz (Numerics @em Argonne National Laboratory); A. Gargaro (Distributed Systems @em Computer Sciences); J. Goodenough (Real-Time/Systems Programming @em SEI); J. McHugh (Secure Systems @em consultant); B. Wichmann (Safety-Critical Systems @em NPL: UK). This work was regularly reviewed by the Ada 9X Distinguished Reviewers and the members of the Ada 9X Rapporteur Group (XRG): E. Ploedereder, Chairman of DRs and XRG (University of Stuttgart: Germany); B. Bardin (Hughes); J. Barnes (consultant: UK); @Comment{XRG - UK} B. Brett (DEC); B. Brosgol (consultant); R. Brukardt (RR Software); N. Cohen (IBM); R. Dewar (NYU); G. Dismukes (TeleSoft); A. Evans (consultant); A. Gargaro (Computer Sciences); M. Gerhardt (ESL); J. Goodenough (SEI); @Comment{Also XRG - U.S.} S. Heilbrunner (University of Salzburg: Austria); @Comment{Also XRG - Belgium} P. Hilfinger (UC/Berkeley); @Comment{No longer a DR.} B. K@latin1(228)llberg (CelsiusTech: Sweden); @Comment{XRG - Sweden} M. Kamrad II (Unisys); J. van Katwijk (Delft University of Technology: The Netherlands); @Comment{XRG - The Netherlands} V. Kaufman (Russia); @Comment{XRG - Russia} P. Kruchten (Rational); @Comment{Also XRG - France} R. Landwehr (CCI: Germany); @Comment{Also XRG - Germany} C. Lester (Portsmouth Polytechnic: UK); L. M@latin1(229)nsson (TELIA Research: Sweden); @Comment{No longer a DR.} S. Michell (Multiprocessor Toolsmiths: Canada); @Comment{Also XRG - Canada} M. Mills (US Air Force); D. Pogge (US Navy); K. Power (Boeing); O. Roubine (Verdix: France); A. Strohmeier (Swiss Fed Inst of Technology: Switzerland); @Comment{XRG - Switzerland} W. Taylor (consultant: UK); J. Tokar (Tartan); E. Vasilescu (Grumman); J. Vladik (Prospeks s.r.o.: Czech Republic); @Comment{XRG - Czech Republic} S. Van Vlierberghe (OFFIS: Belgium). @Comment{XRG - Belgium} Other valuable feedback influencing the revision process was provided by the Ada 9X Language Precision Team (Odyssey Research Associates), the Ada 9X User/Implementer Teams (AETECH, Tartan, TeleSoft), the Ada 9X Implementation Analysis Team (New York University) and the Ada community-at-large. Special thanks go to R. Mathis, Convenor of ISO/IEC JTC 1/SC 22 Working Group 9. @Comment{Also XRG - U.S.} The Ada 9X Project was sponsored by the Ada Joint Program Office. Christine M. Anderson at the Air Force Phillips Laboratory (Kirtland AFB, NM) was the project manager. @AddedSubHeading{Version=[1],Acknowledgements for the Corrigendum version} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=<The editor [R. Brukardt (USA)] would like to thank the many people whose hard work and assistance has made this @Chg{Version=[3],New=[update],Old=[revision]} possible.>,Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Thanks go out to all of the members of the ISO/IEC JTC 1/SC 22/WG 9 Ada Rapporteur Group, whose work on creating and editing the wording corrections was critical to the entire process. Especially valuable contributions came from the chairman of the ARG, E. Ploedereder (Germany), who kept the process moving; J. Barnes (UK) and K. Ishihata (Japan), whose extremely detailed reviews kept the editor on his toes; G. Dismukes (USA), M. Kamrad (USA), P. Leroy (France), S. Michell (Canada), T. Taft (USA), J. Tokar (USA), and other members too numerous to mention.],Old=[]} @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[Special thanks go to R. Duff (USA) for his explanations of the previous system of formatting of these documents during the tedious conversion to more modern formats. Special thanks also go to the convenor of ISO/IEC JTC 1/SC 22/WG 9, J. Moore (USA), without whose help and support the Corrigendum and this consolidated reference manual would not have been possible.],Old=[]} @AddedSubHeading{Version=[2],Acknowledgements for the Amendment 1 version} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{Version=[2],New=<The editor [R. Brukardt (USA)] would like to thank the many people whose hard work and assistance has made this @Chg{Version=[3],New=[update],Old=[revision]} possible.>,Old=[]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Thanks go out to all of the members of the ISO/IEC JTC 1/SC 22/WG 9 Ada Rapporteur Group, whose work on creating and editing the wording corrections was critical to the entire process. Especially valuable contributions came from the chairman of the ARG, P. Leroy (France), who kept the process on schedule; J. Barnes (UK) whose careful reviews found many typographical errors; T. Taft (USA), who always seemed to have a suggestion when we were stuck, and who also was usually able to provide the valuable service of explaining why things were as they are; S. Baird (USA), who found many obscure problems with the proposals; and A. Burns (UK), who pushed many of the real-time proposals to completion. Other ARG members who contributed were: R. Dewar (USA), G. Dismukes (USA), R. Duff (USA), K. Ishihata (Japan), S. Michell (Canada), E. Ploedereder (Germany), J.P. Rosen (France), E. Schonberg (USA), J. Tokar (USA), and T. Vardanega (Italy).]} @ChgRef{Version=[2],Kind=[Added]} @Chg{Version=[2],New=[Special thanks go to Ada-Europe and the Ada Resource Association, without whose help and support the Amendment and this consolidated reference manual would not have been possible. M. Heaney (USA) requires special thanks for his tireless work on the containers packages. Finally, special thanks go to the convenor of ISO/IEC JTC 1/SC 22/WG 9, J. Moore (USA), who guided the document through the standardization process.],Old=[]} @end{Intro} @AddedSubHeading{Version=[3],Acknowledgements for the Ada 2012 edition} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=<The editor [R. Brukardt (USA)] would like to thank the many people whose hard work and assistance has made this revision possible.>} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Thanks go out to all of the members of the ISO/IEC JTC 1/SC 22/WG 9 Ada Rapporteur Group, whose work on creating and editing the wording changes was critical to the entire process. Especially valuable contributions came from the chairman of the ARG, E. Schonberg (USA), who guided the work; T. Taft (USA), whose insights broke many logjams, both in design and wording; J. Barnes (UK) whose careful reviews uncovered many editorial errors; S. Baird (USA), who repeatedly found obscure interactions with the proposals that the rest of us missed. Other ARG members who substantially contributed were: A. Burns (UK), J. Cousins (UK), R. Dewar (USA), G. Dismukes (USA), R. Duff (USA), P. Leroy (France), B. Moore (Canada), E. Ploedereder (Germany), J.P. Rosen (France), B. Thomas (USA), and T. Vardanega (Italy).]}@Comment{Pascal Leroy worked extensively on this work in the early days, although he hasn't participated recently.} @ChgRef{Version=[3],Kind=[Added]} @Chg{Version=[3],New=[Special thanks go to Ada-Europe and the Ada Resource Association, without whose help and support this third edition of the Ada Standard would not have been possible. A special mention has to go to A. Beneschan (USA) for his efforts in eliminating sloppiness in our wording. M. Heaney (USA) also deserves a mention for his efforts to improve the containers packages. Finally, special thanks go to the convenor of ISO/IEC JTC 1/SC 22/WG 9, J. Tokar (USA), who guided the document through the standardization process.],Old=[]} @Comment{The other financial contributors wanted to remain anonymous, so they are not mentioned here.} @NewPage @SubHeading{Changes} @begin{Intro} @Leading@;The International Standard is the same as this version of the Reference Manual, except: @begin{Itemize} This list of Changes is not included in the International Standard. The @lquotes@;Acknowledgements@rquotes@; page is not included in the International Standard. The text in the running headers and footers on each page is slightly different in the International Standard. The title page(s) are different in the International Standard. This document is formatted for 8.5-by-11-inch paper, whereas the International Standard is formatted for A4 paper (210-by-297mm); thus, the page breaks are in different places. @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAdded]} @ChgDeleted{Version=[3],Text=[@Chg{New=[The @lquotes@;Foreword to this version of the Ada Reference Manual@rquotes clause is not included in the International Standard.],Old=[]}]} @Comment{This subclause is not used in this revision.} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The @lquotes@;Using this version of the Ada Reference Manual@rquotes @Chg{Version=[3],New=[subclause],Old=[clause]} is not included in the International Standard.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Paragraph numbers are not included in the International Standard.]} @end{Itemize} @end{Intro} @end{NotISO} @begin{NotISO} @begin{Intro} @AddedSubHeading{Version=[1],Using this version of the Ada Reference Manual} @begin{RMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[This document has been revised with the corrections specified in Technical Corrigendum 1 (ISO/IEC 8652:1995/COR.1:2001)@Chg{Version=[2],New=[ and Amendment 1 (ISO/IEC 8652/AMD 1:2007)@Chg{Version=[3],New=[, along with changes specifically for this third edition],Old=[]}],Old=[]}. In addition, a variety of editorial errors have been corrected.],Old=[]} @end{RMOnly} @begin{AARMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[This document has been revised with the corrections specified in Technical Corrigendum 1 (ISO/IEC 8652:1995/COR.1:2001)@Chg{Version=[2],New=[ and Amendment 1 (ISO/IEC 8652/AMD 1:2007)@Chg{Version=[3],New=[, along with changes specifically for this third edition],Old=[]}],Old=[]}. In addition, @Chg{Version=[3],New=[more],Old=[additional]} annotations have been added and a variety of editorial errors have been corrected.],Old=[]} @end{AARMOnly} @begin{RMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[Changes to the original 8652:1995 can be identified by the version number @Chg{Version=[2],New=[],Old=[/1 ]}following the paragraph number.@Chg{Version=[2],New=[ Paragraphs with a version number of /1 were changed by Technical Corrigendum 1 or were editorial corrections at that time, while paragraphs with a version number of /2 were changed by Amendment 1 or were more recent editorial corrections@Chg{Version=[3],New=[, and paragraphs with a version number of /3 were changed by the third (2012) edition of the Standard or were still more recent editorial corrections],Old=[]}.],Old=[]} Paragraphs not so marked are unchanged by @Chg{Version=[2],New=[@Chg{Version=[3],New=[the third edition, ],Old=[]}Amendment 1, ],Old=[]}Technical Corrigendum 1@Chg{Version=[2],New=[,],Old=[]} or editorial corrections. Paragraph numbers of unchanged paragraphs are the same as in the @Chg{Version=[3],New=[1995 edition of the],Old=[original]} Ada Reference Manual. In addition, some versions of this document include revision bars near the paragraph numbers. Where paragraphs are inserted, the paragraph numbers are of the form pp.nn, where pp is the number of the preceding paragraph, and nn is an insertion number. For instance, the first paragraph inserted after paragraph 8 is numbered 8.1, the second paragraph inserted is numbered 8.2, and so on. Deleted paragraphs are indicated by the text @i{@shrink{This paragraph was deleted.}} Deleted paragraphs include empty paragraphs that were numbered in the @Chg{Version=[3],New=[1995 edition of the],Old=[original]} Ada Reference Manual.],Old=[]} @end{RMOnly} @begin{AARMOnly} @ChgRef{Version=[1],Kind=[Added]} @ChgRef{Version=[2],Kind=[RevisedAdded]} @ChgRef{Version=[3],Kind=[RevisedAdded]} @Chg{New=[Changes to the original 8652:1995 can be identified by the version number @Chg{Version=[2],New=[],Old=[/1 ]}following the paragraph number.@Chg{Version=[2],New=[ Paragraphs with a version number of /1 were changed by Technical Corrigendum 1 or were editorial corrections at that time, while paragraphs with a version number of /2 were changed by Amendment 1 or were more recent editorial corrections@Chg{Version=[3],New=[, and paragraphs with a version number of /3 were changed by the third (2012) edition of the Standard or were still more recent editorial corrections],Old=[]}.],Old=[]} Paragraphs not so marked are unchanged by @Chg{Version=[2],New=[@Chg{Version=[3],New=[the third edition, ],Old=[]}Amendment 1, ],Old=[]}Technical Corrigendum 1@Chg{Version=[2],New=[,],Old=[]} or editorial corrections. Paragraph numbers of unchanged paragraphs are the same as in the @Chg{Version=[3],New=[1995 edition of the],Old=[original]} Ada Reference Manual. Inserted text is indicated by underlining, and deleted text is indicated by strikethroughs. @Chg{Version=[2],New=[Some versions also use color to indicate the version of the change.],Old=[]}Where paragraphs are inserted, the paragraph numbers are of the form pp.nn, where pp is the number of the preceding paragraph, and nn is an insertion number. For instance, the first paragraph inserted after paragraph 8 is numbered 8.1, the second paragraph inserted is numbered 8.2, and so on. Deleted paragraphs are indicated by the text @i{@shrink{This paragraph was deleted.}} Deleted paragraphs include empty paragraphs that were numbered in the @Chg{Version=[3],New=[1995 edition of the],Old=[original]} Ada Reference Manual. Similar markings and numbering @Chg{Version=[3],New=[are],Old=[is]} used for changes to annotations.],Old=[]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The paragraph number is considered part of the paragraph; when a paragraph is moved to a different paragraph number, it is marked as changed even if the contents have not changed.]} @end{Honest} @end{AARMOnly} @end{Intro} @end{NotISO} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/glossary.mss���������������������������������������������������������0000755�0001752�0001001�00000001211�12066652506�020007� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(glossary, Root="ada.mss") @Comment{$Date: 2005/11/24 02:15:07 $} @LabeledInformativeAnnex{Glossary} @comment{$Source: e:\\cvsroot/ARM/Source/glossary.mss,v $} @comment{$Revision: 1.16 $} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00437-01]} @Defn{Glossary} This Annex contains informal descriptions of some @Chg{Version=[2], New=[of the ],Old=[]}terms used in this International Standard. @Chg{Version=[2],New=[The index provides references to more formal definitions of all of the terms used in this International Standard], Old=[To find more formal definitions, look the term up in the index]}. @GlossaryList @end{Intro}���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/impldef.mss����������������������������������������������������������0000755�0001752�0001001�00000006222�12066652506�017573� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(impldef, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledRevisedInformativeAnnex{Version=[2],New=[Summary of Documentation Requirements],Old=[Implementation-Defined Characteristics]} @comment{$Source: e:\\cvsroot/ARM/Source/impldef.mss,v $} @comment{$Revision: 1.17 $} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Defn{documentation requirements} The Ada language allows for certain target machine dependences in a controlled manner. Each Ada implementation must document many characteristics and properties of the target system. This International Standard contains specific documentation requirements. In addition, many characteristics that require documentation are identified throughout this International Standard as being implementation defined. Finally, this International Standard requires documentation of whether implementation advice is followed. The following @Chg{Version=[3],New=[subclauses],Old=[clauses]} provide summaries of these documentation requirements.]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Specific Documentation Requirements]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[documentation requirements], Sec=(summary of requirements)} @Defn{documentation (required of an implementation)} In addition to implementation-defined characteristics, each Ada implementation must document various properties of the implementation:]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Most of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes.]} @end{Ramification} @AddedDocReqList{Version=[2]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Implementation-Defined Characteristics]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised]} @Defn2{Term=[implementation defined], Sec=(summary of characteristics)} The Ada language allows for certain machine dependences in a controlled manner. @Defn{documentation (required of an implementation)} Each Ada implementation must document all implementation-defined characteristics: @begin{Ramification} @Defn{unspecified} @Defn{specified (not!)} It need not document unspecified characteristics. Some of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes. @end{Ramification} @ImplDefList @end{Intro} @LabeledAddedClause{Version=[2],Name=[Implementation Advice]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[implementation advice], Sec=(summary of advice)} @Defn{documentation (required of an implementation)} This International Standard sometimes gives advice about handling certain target machine dependences. Each Ada implementation must document whether that advice is followed:]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Some of the items in this list require documentation only for implementations that conform to Specialized Needs Annexes.]} @end{Ramification} @AddedImplAdviceList{Version=[2]} @end{Intro} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/index.mss������������������������������������������������������������0000755�0001752�0001001�00000002101�11776511201�017243� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(index, Root="ada.mss") @Comment{$Date: 2006/01/17 07:20:58 $} @comment{$Source: e:\\cvsroot/ARM/Source/index.mss,v $} @comment{$Revision: 1.1 $} @UnnumberedSection{Index} @begin{ISOOnly} @noparanum@;Index entries are given by subclause.@Chg{Version=[2],New=[], Old=[ A list of all language-defined library units may be found under Language-Defined Library Units. A list of all language-defined types may be found under Language-Defined Types.@Chg{Version=[2],New=[ A list of all language-defined subprograms may be found under Language-Defined Subprograms.],Old=[]}]} @end{ISOOnly} @begin{NotISO} @noparanum@;Index entries are given by paragraph number.@Chg{Version=[2],New=[], Old=[ A list of all language-defined library units may be found under Language-Defined Library Units. A list of all language-defined types may be found under Language-Defined Types.@Chg{Version=[2],New=[ A list of all language-defined subprograms may be found under Language-Defined Subprograms.],Old=[]}]} @end{NotISO} @noparanum@ @*@Comment{Blank paragraph} @IndexList@Comment{Generate the index} ���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/infosys.mss����������������������������������������������������������0000755�0001752�0001001�00000154200�12066652506�017645� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/infosys.mss,v $ } @comment{ $Revision: 1.44 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(infosys, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledNormativeAnnex{Information Systems} @begin{Intro} @Defn{information systems} @Leading@;This Annex provides a set of facilities relevant to Information Systems programming. These fall into several categories: @begin{itemize} an attribute definition clause specifying Machine_Radix for a decimal subtype; the package Decimal, which declares a set of constants defining the implementation's capacity for decimal types, and a generic procedure for decimal division; and @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} the child packages Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]}, which support formatted and localized output of decimal data, based on @lquotes@;picture String@rquotes@; values. @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} See also: @RefSec{Fixed Point Types}; @RefSec{Operations of Fixed Point Types}; @RefSec{Type Conversions}; @RefSec{Operational and Representation Attributes}; @RefSec(Input-Output for Real Types);@Chg{Version=[2], New=[],Old=[@RefSec{Interfacing with COBOL};]} @RefSec{Interfacing with C and C++};@Chg{Version=[2], New=[ @RefSec{Interfacing with COBOL};],Old=[]} @RefSec{Numerics}. The character and string handling packages in @RefSec{Predefined Language Environment} are also relevant for Information Systems. @end{Intro} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If COBOL (respectively, C) is widely supported in the target environment, implementations supporting the Information Systems Annex should provide the child package Interfaces.COBOL (respectively, Interfaces.C) specified in @RefSecNum{Interface to Other Languages} and should support a @i{convention_}@nt{identifier} of COBOL (respectively, C) @Chg{Version=[3],New=[for],Old=[in]} the @Chg{Version=[3],New=[Convention aspect],Old=[interfacing pragmas]} (see @RefSecNum{Interface to Other Languages}), thus allowing Ada programs to interface with programs written in that language. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If COBOL (respectively, C) is supported in the target environment, then interfacing to COBOL (respectively, C) should be supported as specified in @RefSecNum{Interface to Other Languages}.]}]} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Added a mention of Wide_Wide_Text_IO.Editing, part of the support for 32-bit characters.]} @end{DiffWord95} @LabeledClause{Machine_Radix Attribute Definition Clause} @begin{StaticSem} @PDefn2{Term=[specifiable], Sec=(of Machine_Radix for decimal first subtypes)} @Defn{Machine_Radix clause} Machine_Radix may be specified for a decimal first subtype (see @RefSecNum{Fixed Point Types}) via an @nt{attribute_definition_clause}; the expression of such a clause shall be static, and its value shall be 2 or 10. A value of 2 implies a binary base range; a value of 10 implies a decimal base range.@Chg{Version=[3],New=[@AspectDefn{Machine_Radix}],Old=[]} @begin{Ramification} In the absence of a Machine_Radix clause, the choice of 2 versus 10 for S'Machine_Radix is not specified. @end{Ramification} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Machine_Radix], Text=[@ChgAdded{Version=[3],Text=[Radix (2 or 10) that is used to represent a decimal fixed point type.]}]} @end{StaticSem} @begin{ImplAdvice} Packed decimal should be used as the internal representation for objects of subtype S when S'Machine_Radix = 10. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Packed decimal should be used as the internal representation for objects of subtype @i<S> when @i<S>'Machine_Radix = 10.]}]} @end{ImplAdvice} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The intent of a decimal Machine_Radix attribute definition clause is to allow the programmer to declare an Ada decimal data object whose representation matches a particular COBOL implementation's representation of packed decimal items. The Ada object may then be passed to an interfaced COBOL program that takes a packed decimal data item as a parameter, assuming that convention COBOL has been specified for the Ada object's type @Chg{Version=[3],New=[with an aspect],Old=[in a @nt[pragma]]} Convention. Additionally, the Ada compiler may choose to generate arithmetic instructions that exploit the packed decimal representation. @end{discussion} @begin{Examples} @Leading@Keepnext@i{Example of Machine_Radix attribute definition clause:} @begin{example} @key[type] Money @key[is] @key[delta] 0.01 @key[digits] 15; @key[for] Money'Machine_Radix @key[use] 10; @end{example} @end{Examples} @LabeledClause{The Package Decimal} @begin{StaticSem} @Leading@Keepnext@;The library package Decimal has the following declaration: @begin{Example} @key(package) Ada.Decimal @key(is)@ChildUnit{Parent=[Ada],Child=[Decimal]} @key(pragma) Pure(Decimal); @AdaObjDefn{Max_Scale} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Min_Scale} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Min_Delta} : @key(constant) := 10.0**(-Max_Scale); @AdaObjDefn{Max_Delta} : @key(constant) := 10.0**(-Min_Scale); @AdaObjDefn{Max_Decimal_Digits} : @key(constant) := @RI{implementation-defined}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(generic) @key(type) Dividend_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Divisor_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Quotient_Type @key(is) @key(delta) <> @key(digits) <>; @key(type) Remainder_Type @key(is) @key(delta) <> @key(digits) <>; @key(procedure) @AdaSubDefn{Divide} (Dividend : @key(in) Dividend_Type; Divisor : @key(in) Divisor_Type; Quotient : @key(out) Quotient_Type; Remainder : @key(out) Remainder_Type)@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[; @key[pragma] Convention(Intrinsic, Divide)]}; @key(end) Ada.Decimal; @end{Example} @ImplDef{The values of named numbers in the package Decimal.} Max_Scale is the largest N such that 10.0**(@en@;N) is allowed as a decimal type's delta. Its type is @i{universal_integer}. Min_Scale is the smallest N such that 10.0**(@en@;N) is allowed as a decimal type's delta. Its type is @i{universal_integer}. Min_Delta is the smallest value allowed for @i{delta} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_real}. Max_Delta is the largest value allowed for @i{delta} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_real}. Max_Decimal_Digits is the largest value allowed for @i{digits} in a @nt{decimal_fixed_point_definition}. Its type is @i{universal_integer}. @begin{reason} The name is Max_Decimal_Digits versus Max_Digits, in order to avoid confusion with the named number System.Max_Digits relevant to floating point. @end{reason} @end{StaticSem} @begin{StaticSem} The effect of Divide is as follows. The value of Quotient is Quotient_Type(Dividend/Divisor). The value of Remainder is Remainder_Type(Intermediate), where Intermediate is the difference between Dividend and the product of Divisor and Quotient; this result is computed exactly. @end{StaticSem} @begin(ImplReq) Decimal.Max_Decimal_Digits shall be at least 18. Decimal.Max_Scale shall be at least 18. Decimal.Min_Scale shall be at most 0. @end{ImplReq} @begin(Notes) The effect of division yielding a quotient with control over rounding versus truncation is obtained by applying either the function attribute Quotient_Type'Round or the conversion Quotient_Type to the expression Dividend/Divisor. @end(Notes) @LabeledClause{Edited Output for Decimal Types} @begin{Intro} @Leading@; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The child packages Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]} provide localizable formatted text output, known as @i{edited output}@Defn{edited output}, for decimal types. An edited output string is a function of a numeric value, program-specifiable locale elements, and a format control value. The numeric value is of some decimal type. The locale elements are: @begin{itemize} the currency string; the digits group separator character; the radix mark character; and the fill character that replaces leading zeros of the numeric value. @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} For Text_IO.Editing the edited output and currency strings are of type String, and the locale characters are of type Character. For Wide_@!Text_IO.@!Editing their types are Wide_@!String and Wide_@!Character, respectively.@Chg{Version=[2],New=[ For Wide_Wide_@!Text_IO.@!Editing their types are Wide_Wide_@!String and Wide_Wide_@!Character, respectively.],Old=[]} Each of the locale elements has a default value that can be replaced or explicitly overridden. A format-control value is of the private type Picture; it determines the composition of the edited output string and controls the form and placement of the sign, the position of the locale elements and the decimal digits, the presence or absence of a radix mark, suppression of leading zeros, and insertion of particular character values. @Leading@;A Picture object is composed from a String value, known as a @i{picture String}, that serves as a template for the edited output string, and a Boolean value that controls whether a string of all space characters is produced when the number's value is zero. A picture String comprises a sequence of one- or two-Character symbols, each serving as a placeholder for a character or string at a corresponding position in the edited output string. The picture String symbols fall into several categories based on their effect on the edited output string: @TabClear() @begin{Display} @TabSet{3, 21, 27, 33, 39, 45, 51} @\Decimal Digit: @\'9' @\Radix Control: @\'.' @\'V' @\Sign Control: @\'+' @\'@en@;' @\'<' @\'>' @\"CR" @\"DB" @\Currency Control: @\'$' @\'#' @\Zero Suppression: @\'Z' @\'*' @\Simple Insertion: @\'_' @\'B' @\'0' @\'/' @end{Display} The entries are not case-sensitive. Mixed- or lower-case forms for "CR" and "DB", and lower-case forms for 'V', 'Z', and 'B', have the same effect as the upper-case symbols shown. An occurrence of a '9' Character in the picture String represents a decimal digit position in the edited output string. A radix control Character in the picture String indicates the position of the radix mark in the edited output string: an actual character position for '.', or an assumed position for 'V'. A sign control Character in the picture String affects the form of the sign in the edited output string. The '<' and '>' Character values indicate parentheses for negative values. A Character '+', '@en@;', or '<' appears either singly, signifying a fixed-position sign in the edited output, or repeated, signifying a floating-position sign that is preceded by zero or more space characters and that replaces a leading 0. A currency control Character in the picture String indicates an occurrence of the currency string in the edited output string. The '$' Character represents the complete currency string; the '#' Character represents one character of the currency string. A '$' Character appears either singly, indicating a fixed-position currency string in the edited output, or repeated, indicating a floating-position currency string that occurs in place of a leading 0. A sequence of '#' Character values indicates either a fixed- or floating-position currency string, depending on context. A zero suppression Character in the picture String allows a leading zero to be replaced by either the space character (for 'Z') or the fill character (for '*'). A simple insertion Character in the picture String represents, in general, either itself (if '/' or '0'), the space character (if 'B'), or the digits group separator character (if '_'). In some contexts it is treated as part of a floating sign, floating currency, or zero suppression string. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} An example of a picture String is "<###Z_ZZ9.99>". If the currency string is "@Chg{Version=[2],New=[kr],Old=[FF]}", the separator character is ',', and the radix mark is '.' then the edited output string values for the decimal values 32.10 and @en@;5432.10 are "bb@Chg{Version=[2],New=[kr],Old=[FF]}bbb32.10b" and "(b@Chg{Version=[2],New=[kr],Old=[FF]}5,432.10)", respectively, where 'b' indicates the space character. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The generic packages Text_IO.Decimal_IO@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Decimal_IO@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Decimal_IO],Old=[]} (see @RefSec(Input-Output for Real Types)) provide text input and nonedited text output for decimal types. @end{Intro} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} A picture String is of type Standard.String, @Chg{Version=[2],New=[for all of], Old=[both for]} Text_IO.Editing@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO.Editing@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Editing],Old=[]}. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Added descriptions of Wide_Wide_Text_IO.Editing; see @RefSecNum{The Package Wide_Wide_Text_IO.Editing}.]} @end{DiffWord95} @LabeledSubClause{Picture String Formation} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @begin{Intro} @Defn2{term=[picture String],sec=[for edited output]} @Defn2{term=[well-formed picture String],sec=[for edited output]} A @i{well-formed picture String}, or simply @i{picture String}, is a String value that conforms to the syntactic rules, composition constraints, and character replication conventions specified in this @Chg{Version=[3],New=[subclause],Old=[clause]}. @end{Intro} @begin{RunTime} @TabClear() @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Display} @ntf{picture_string} ::= @ntf{fixed_$_picture_string} | @ntf{fixed_#_picture_string} | @ntf{floating_currency_picture_string} | @ntf{non_currency_picture_string} @comment{Blank Line} @end{Display} @begin{display} @ntf{fixed_$_picture_string} ::= [@ntf{fixed_LHS_sign}] @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{zero_suppression}] @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] [@ntf{zero_suppression}] @ntf{number} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{floating_LHS_sign} @ntf{number} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{fixed_$_char} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{all_sign_number} {@ntf{direct_insertion}} @ntf{fixed_$_char} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_#_picture_string} ::= [@ntf{fixed_LHS_sign}] @ntf{single_#_currency} {@ntf{direct_insertion}} [@ntf{zero_suppression}] @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{multiple_#_currency} {@ntf{direct_insertion}} @ntf{zero_suppression} @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] [@ntf{zero_suppression}] @ntf{number} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{floating_LHS_sign} @ntf{number} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{single_#_currency} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign}] @ntf{multiple_#_currency} {@ntf{direct_insertion}} @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} | @ntf{all_sign_number} {@ntf{direct_insertion}} @ntf{fixed_#_currency} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{floating_currency_picture_string} ::= [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{floating_$_currency} @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{floating_#_currency} @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign}] {@ntf{direct_insertion}} @ntf{all_currency_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{non_currency_picture_string} ::= [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{zero_suppression} @ntf{number} [@ntf{RHS_sign}] | [@ntf{floating_LHS_sign}] @ntf{number} [@ntf{RHS_sign}] | [@ntf{fixed_LHS_sign} {@ntf{direct_insertion}}] @ntf{all_zero_suppression_number} {@ntf{direct_insertion}} [@ntf{RHS_sign}] | @ntf{all_sign_number} {@ntf{direct_insertion}} | @ntf{fixed_LHS_sign} @ntf{direct_insertion} {@ntf{direct_insertion}} @ntf{number} [@ntf{RHS_sign}] @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_LHS_sign} ::= @ntf{LHS_Sign} @end{display} @begin{display} @ntf{LHS_Sign} ::= + | @en | < @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_$_char} ::= $ @comment{Blank Line} @end{display} @begin{display} @ntf{direct_insertion} ::= @ntf{simple_insertion} @end{display} @begin{display} @ntf{simple_insertion} ::= _ | B | 0 | / @comment{Blank Line} @end{display} @begin{display} @ntf{zero_suppression} ::= Z {Z | @ntf{context_sensitive_insertion}} | @ntf{fill_string} @end{display} @begin{display} @ntf{context_sensitive_insertion} ::= @ntf{simple_insertion} @comment{Blank Line} @end{display} @begin{display} @ntf{fill_string} ::= * {* | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{number} ::= @ntf{fore_digits} [@ntf{radix} [@ntf{aft_digits}] {@ntf{direct_insertion}}] | @ntf{radix} @ntf{aft_digits} {@ntf{direct_insertion}} @end{display} @begin{display} @ntf{fore_digits} ::= 9 {9 | @ntf{direct_insertion}} @end{display} @begin{display} @ntf{aft_digits} ::= {9 | @ntf{direct_insertion}} 9 @end{display} @begin{display} @ntf{radix} ::= . | V @comment{Blank Line} @end{display} @begin{display} @ntf{RHS_sign} ::= + | @en | > | CR | DB @comment{Blank Line} @end{display} @begin{display} @ntf{floating_LHS_sign} ::= @ntf{LHS_Sign} {@ntf{context_sensitive_insertion}} @ntf{LHS_Sign} {@ntf{LHS_Sign} | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{single_#_currency} ::= # @end{display} @begin{display} @ntf{multiple_#_currency} ::= ## {#} @comment{Blank Line} @end{display} @begin{display} @ntf{fixed_#_currency} ::= @ntf{single_#_currency} | @ntf{multiple_#_currency} @comment{Blank Line} @end{display} @begin{display} @ntf{floating_$_currency} ::= $ {@ntf{context_sensitive_insertion}} $ {$ | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{floating_#_currency} ::= # {@ntf{context_sensitive_insertion}} # {# | @ntf{context_sensitive_insertion}} @comment{Blank Line} @end{display} @begin{display} @ntf{all_sign_number} ::= @ntf{all_sign_fore} [@ntf{radix} [@ntf{all_sign_aft}]] [>] @end{display} @begin{display} @ntf{all_sign_fore} ::= @ntf{sign_char} {@ntf{context_sensitive_insertion}} @ntf{sign_char} {@ntf{sign_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_sign_aft} ::= {@ntf{all_sign_aft_char}} @ntf{sign_char} @comment{Blank Line} @ntf{all_sign_aft_char} ::= @ntf{sign_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @ntf{sign_char} ::= + | @en | < @comment{Blank Line} @end{display} @begin{display} @ntf{all_currency_number} ::= @ntf{all_currency_fore} [@ntf{radix} [@ntf{all_currency_aft}]] @end{display} @begin{display} @ntf{all_currency_fore} ::= @ntf{currency_char} {@ntf{context_sensitive_insertion}} @ntf{currency_char} {@ntf{currency_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_currency_aft} ::= {@ntf{all_currency_aft_char}} @ntf{currency_char} @comment{Blank Line} @ntf{all_currency_aft_char} ::= @ntf{currency_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @ntf{currency_char} ::= $ | # @comment{Blank Line} @end{display} @begin{display} @ntf{all_zero_suppression_number} ::= @ntf{all_zero_suppression_fore} [ @ntf{radix} [@ntf{all_zero_suppression_aft}]] @end{display} @begin{display} @ntf{all_zero_suppression_fore} ::= @ntf{zero_suppression_char} {@ntf{zero_suppression_char} | @ntf{context_sensitive_insertion}} @end{display} @begin{display} @ntf{all_zero_suppression_aft} ::= {@ntf{all_zero_suppression_aft_char}} @ntf{zero_suppression_char} @comment{Blank Line} @ntf{all_zero_suppression_aft_char} ::= @ntf{zero_suppression_char} | @ntf{context_sensitive_insertion} @end{display} @begin{display} @trailing@ntf{zero_suppression_char} ::= Z | * @end{Display} @Leading@;The following composition constraints apply to a picture String: @begin{Itemize} A @ntf{floating_LHS_sign} does not have occurrences of different @ntf{LHS_Sign} Character values. If a picture String has '<' as @ntf{fixed_LHS_sign}, then it has '>' as @ntf{RHS_sign}. If a picture String has '<' in a @ntf{floating_LHS_sign} or in an @ntf{all_sign_number}, then it has an occurrence of '>'. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0088],ARef=[AI95-00153]} If a picture String has '+' or '@en@;' as @ntf{fixed_LHS_sign}, in a @ntf{floating_LHS_sign}, or in an @ntf{all_sign_number}, then it has no @ntf{RHS_sign}@Chg{New=[ or '>' character],Old=[]}. An instance of @ntf{all_sign_number} does not have occurrences of different @ntf{sign_char} Character values. An instance of @ntf{all_currency_number} does not have occurrences of different @ntf{currency_@!char} Character values. An instance of @ntf{all_zero_suppression_number} does not have occurrences of different @ntf{zero_@!suppression_@!char} Character values, except for possible case differences between 'Z' and 'z'. @end{Itemize} A @i{replicable Character} is a Character that, by the above rules, can occur in two consecutive positions in a picture String. @Leading@;A @i{Character replication} is a String @begin{example} @RI{char} & '(' & @RI{spaces} & @RI{count_string} & ')' @end{example} where @i{char} is a replicable Character, @i{spaces} is a String (possibly empty) comprising only space Character values, and @i{count_string} is a String of one or more decimal digit Character values. A Character replication in a picture String has the same effect as (and is said to be @i{equivalent to}) a String comprising @i[n] consecutive occurrences of @i{char}, where @i[n]=Integer'Value(@i{count_string}). An @i{expanded picture String} is a picture String containing no Character replications. @begin{Discussion} Since 'B' is not allowed after a RHS sign, there is no need for a special rule to disallow "9.99DB(2)" as an abbreviation for "9.99DBB" @end{discussion} @end{RunTime} @begin{Notes} Although a sign to the left of the number can float, a sign to the right of the number is in a fixed position. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0088],ARef=[AI95-00153-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> The picture string rules for numbers were tightened.]} @end{DiffWord95} @LabeledSubClause{Edited Output Generation} @begin{RunTime} @Leading@;The contents of an edited output string are based on: @begin{Itemize} A value, Item, of some decimal type Num, An expanded picture String Pic_String, A Boolean value, Blank_When_Zero, A Currency string, A Fill character, A Separator character, and A Radix_Mark character. @end{Itemize} The combination of a True value for Blank_When_Zero and a '*' character in Pic_String is inconsistent; no edited output string is defined. @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00114-01]} @ChgAdded{Version=[2],Text=[Such a Pic_String is invalid, and any attempt to use such a string will raise Picture_Error.]} @end{Reason} A layout error is identified in the rules below if leading nonzero digits of Item, character values of the Currency string, or a negative sign would be truncated; in such cases no edited output string is defined. The edited output string has lower bound 1 and upper bound N where N = Pic_String'Length + Currency_Length_Adjustment @en Radix_Adjustment, and @begin{Itemize} Currency_Length_Adjustment = Currency'Length @en@; 1 if there is some occurrence of '$' in Pic_String, and 0 otherwise. Radix_Adjustment = 1 if there is an occurrence of 'V' or 'v' in Pic_Str, and 0 otherwise. @end{Itemize} @Leading@defn{displayed magnitude (of a decimal value)} Let the magnitude of Item be expressed as a base-10 number I@-(p)@Times@Times@Times@;I@-(1).F@-(1)@Times@Times@Times@;F@-(q), called the @i{displayed} @i{magnitude} of Item, where: @begin{Itemize} q = Min(Max(Num'Scale, 0), n) where n is 0 if Pic_String has no @ntf{radix} and is otherwise the number of digit positions following @ntf{radix} in Pic_String, where a digit position corresponds to an occurrence of '9', a @ntf{zero_suppression_char} (for an @ntf{all_zero_suppression_number}), a @ntf{currency_char} (for an @ntf{all_currency_number}), or a @ntf{sign_char} (for an @ntf{all_sign_number}). I@-(p) /= 0 if p>0. @end{Itemize} If n < Num'Scale, then the above number is the result of rounding (away from 0 if exactly midway between values). If Blank_When_Zero = True and the displayed magnitude of Item is zero, then the edited output string comprises all space character values. Otherwise, the picture String is treated as a sequence of instances of syntactic categories based on the rules in @RefSecNum[Picture String Formation], and the edited output string is the concatenation of string values derived from these categories according to the following mapping rules. Table F-1 shows the mapping from a sign control symbol to a corresponding character or string in the edited output. In the columns showing the edited output, a lower-case 'b' represents the space character. If there is no sign control symbol but the value of Item is negative, a layout error occurs and no edited output string is produced. @Table{Columns=<3>,Alignment=<AllCenter>,FirstColWidth=[1],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{Table F-1: Edited Output for Sign Control Symbols}>, Headers=<@b{Sign Control Symbol}@\@b{Edited Output for @*Nonnegative Number}@\@b{Edited Output for @*Negative Number}>, Body=['+'@\'+'@\'@en@;' '@en@;'@\'b'@\'@en@;' '<'@\'b'@\'(' '>'@\'b'@\')' "CR"@\"bb"@\"CR"@Last "DB"@\"bb"@\"DB"]} An instance of @ntf{fixed_LHS_sign} maps to a character as shown in Table F-1. An instance of @ntf{fixed_$_char} maps to Currency. An instance of @ntf{direct_insertion} maps to Separator if @ntf{direct_insertion} = '_', and to the @ntf{direct_insertion} Character otherwise. @Leading@;An instance of @ntf{number} maps to a string @i{integer_part} & @i{radix_part} & @i{fraction_part} where: @begin{Itemize} The string for @i{integer_part} is obtained as follows: @begin{Enumerate} Occurrences of '9' in @ntf{fore_digits} of @ntf{number} are replaced from right to left with the decimal digit character values for I@-(1), ..., I@-(p), respectively. Each occurrence of '9' in @ntf{fore_digits} to the left of the leftmost '9' replaced according to rule 1 is replaced with '0'. If p exceeds the number of occurrences of '9' in @ntf{fore_digits} of @ntf{number}, then the excess leftmost digits are eligible for use in the mapping of an instance of @ntf{zero_suppression}, @ntf{floating_LHS_sign}, @ntf{floating_$_currency}, or @ntf{floating_#_currency} to the left of @ntf{number}; if there is no such instance, then a layout error occurs and no edited output string is produced. @end{Enumerate} @leading@;The @i{radix_part} is: @begin{InnerItemize} "" if @ntf{number} does not include a @ntf{radix}, if @ntf{radix} = 'V', or if @ntf{radix} = 'v' Radix_Mark if @ntf{number} includes '.' as @ntf{radix} @end{InnerItemize} @leading@;The string for @i{fraction_part} is obtained as follows: @begin{Enumerate} Occurrences of '9' in @ntf{aft_digits} of @ntf{number} are replaced from left to right with the decimal digit character values for F@-(1), ... F@-(q). Each occurrence of '9' in @ntf{aft_digits} to the right of the rightmost '9' replaced according to rule 1 is replaced by '0'. @end{Enumerate} @end{Itemize} @leading@;An instance of @ntf{zero_suppression} maps to the string obtained as follows: @begin{Enumerate} The rightmost 'Z', 'z', or '*' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{zero_suppression} instance, A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of some 'Z', 'z', or '*' in @ntf{zero_suppression} that has been mapped to an excess digit, @leading@;Each Character to the left of the leftmost Character replaced according to rule 1 above is replaced by: @begin{InnerItemize} the space character if the zero suppression Character is 'Z' or 'z', or the Fill character if the zero suppression Character is '*'. @end{InnerItemize} A layout error occurs if some excess digits remain after all 'Z', 'z', and '*' Character values in @ntf{zero_suppression} have been replaced via rule 1; no edited output string is produced. @end{Enumerate} An instance of @ntf{RHS_sign} maps to a character or string as shown in Table F-1. An instance of @ntf{floating_LHS_sign} maps to the string obtained as follows. @begin{Enumerate} Up to all but one of the rightmost @ntf{LHS_Sign} Character values are replaced by the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_LHS_sign} instance. The next Character to the left is replaced with the character given by the entry in Table F-1 corresponding to the @ntf{LHS_Sign} Character. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost @ntf{LHS_Sign} character replaced according to rule 1. Any other Character is replaced by the space character.. A layout error occurs if some excess digits remain after replacement via rule 1; no edited output string is produced. @end{Enumerate} An instance of @ntf{fixed_#_currency} maps to the Currency string with n space character values concatenated on the left (if the instance does not follow a @ntf{radix}) or on the right (if the instance does follow a @ntf{radix}), where n is the difference between the length of the @ntf{fixed_#_currency} instance and Currency'Length. A layout error occurs if Currency'Length exceeds the length of the @ntf{fixed_#_currency} instance; no edited output string is produced. @Leading@;An instance of @ntf{floating_$_currency} maps to the string obtained as follows: @begin{Enumerate} Up to all but one of the rightmost '$' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_$_currency} instance. The next Character to the left is replaced by the Currency string. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost '$' Character replaced via rule 1. Each other Character is replaced by the space character. A layout error occurs if some excess digits remain after replacement by rule 1; no edited output string is produced. @end{Enumerate} @leading@;An instance of @ntf{floating_#_currency} maps to the string obtained as follows: @begin{Enumerate} Up to all but one of the rightmost '#' Character values are replaced with the excess digits (if any) from the @i{integer_part} of the mapping of the @ntf{number} to the right of the @ntf{floating_#_currency} instance. The substring whose last Character occurs at the position immediately preceding the leftmost Character replaced via rule 1, and whose length is Currency'Length, is replaced by the Currency string. A @ntf{context_sensitive_insertion} Character is replaced as though it were a @ntf{direct_insertion} Character, if it occurs to the right of the leftmost '#' replaced via rule 1. Any other Character is replaced by the space character. A layout error occurs if some excess digits remain after replacement rule 1, or if there is no substring with the required length for replacement rule 2; no edited output string is produced. @end{Enumerate} @leading@;An instance of @ntf{all_zero_suppression_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero, the @ntf{zero_suppression_char} is 'Z' or 'z', and the instance of @ntf{all_zero_suppression_number} does not have a @ntf{radix} at its last character position; a string containing the Fill character in each position except for the character (if any) corresponding to @ntf{radix}, if @ntf{zero_suppression_char} = '*' and the displayed magnitude of Item is zero; otherwise, the same result as if each @ntf{zero_suppression_char} in @ntf{all_zero_suppression_aft} were '9', interpreting the instance of @ntf{all_zero_suppression_number} as either @ntf{zero_suppression} @ntf{number} (if a @ntf{radix} and @ntf{all_zero_suppression_aft} are present), or as @ntf{zero_suppression} otherwise. @end{Itemize} @leading@;An instance of @ntf{all_sign_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero and the instance of @ntf{all_sign_number} does not have a @ntf{radix} at its last character position; otherwise, the same result as if each @ntf{sign_char} in @ntf{all_sign_number_aft} were '9', interpreting the instance of @ntf{all_sign_number} as either @ntf{floating_LHS_sign} @ntf{number} (if a @ntf{radix} and @ntf{all_sign_number_aft} are present), or as @ntf{floating_LHS_sign} otherwise. @end{Itemize} @leading@;An instance of @ntf{all_currency_number} maps to: @begin{Itemize} a string of all spaces if the displayed magnitude of Item is zero and the instance of @ntf{all_currency_number} does not have a @ntf{radix} at its last character position; otherwise, the same result as if each @ntf{currency_char} in @ntf{all_currency_number_aft} were '9', interpreting the instance of @ntf{all_currency_number} as @ntf{floating_$_currency} @ntf{number} or @ntf{floating_#_currency} @ntf{number} (if a @ntf{radix} and @ntf{all_currency_number_aft} are present), or as @ntf{floating_$_currency} or @ntf{floating_#_currency} otherwise. @end{Itemize} @end{RunTime} @begin{Examples} In the result string values shown below, 'b' represents the space character. @begin{Example} Item: Picture and Result Strings: @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} 123456.78 Picture: "-###**_***_**9.99" @Chg{New=[Result:],Old=[ ]} "bbb$***123,456.78" "bbFF***123.456,78" (currency = "FF", separator = '.', radix mark = ',') @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0089],ARef=[AI95-00070]} 123456.78 Picture: "-@Chg{New=[],Old=[$$]}$**_***_**9.99" Result: "@Chg{New=[],Old=[bb]}b$***123,456.78" "b@Chg{New=[],Old=[bb]}FF***123.456,78" (currency = "FF", @Chg{New=[],Old=[ ]} separator = '.', @Chg{New=[],Old=[ ]} radix mark = ',') 0.0 Picture: "-$$$$$$.$$" Result: "bbbbbbbbbb" 0.20 Picture: "-$$$$$$.$$" Result: "bbbbbb$.20" -1234.565 Picture: "<<<<_<<<.<<###>" Result: "bb(1,234.57DMb)" (currency = "DM") 12345.67 Picture: "###_###_##9.99" Result: "bbCHF12,345.67" (currency = "CHF") @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0089],ARef=[AI95-00070-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the picture string example.]} @end{DiffWord95} @LabeledSubClause{The Package Text_IO.Editing} @begin{Intro} The package Text_IO.Editing provides a private type Picture with associated operations, and a generic package Decimal_Output. An object of type Picture is composed from a well-formed picture String (see @RefSecNum(Picture String Formation)) and a Boolean item indicating whether a zero numeric value will result in an edited output string of all space characters. The package Decimal_Output contains edited output subprograms implementing the effects defined in @RefSecNum(Edited Output Generation). @end{Intro} @begin{StaticSem} @leading@;The library package Text_IO.Editing has the following declaration: @begin{Example} @key(package) Ada.Text_IO.Editing @key(is)@ChildUnit{Parent=[Ada.Text_IO],Child=[Editing]} @key(type) @AdaTypeDefn{Picture} @key(is) @key(private); @key(function) @AdaSubDefn{Valid} (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Boolean; @key(function) @AdaSubDefn{To_Picture} (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Picture; @key(function) @AdaSubDefn{Pic_String} (Pic : @key(in) Picture) @key(return) String; @key(function) @AdaSubDefn{Blank_When_Zero} (Pic : @key(in) Picture) @key(return) Boolean; @AdaObjDefn{Max_Picture_Length} : @key(constant) := @RI{implementation_defined}; @AdaExcDefn{Picture_Error} : @key(exception); @AdaObjDefn{Default_Currency} : @key(constant) String := "$"; @AdaObjDefn{Default_Fill} : @key(constant) Character := '*'; @AdaObjDefn{Default_Separator} : @key(constant) Character := ','; @AdaObjDefn{Default_Radix_Mark} : @key(constant) Character := '.'; @key(generic) @key(type) Num @key(is) @key(delta) <> @key(digits) <>; Default_Currency : @key(in) String := Text_IO.Editing.Default_Currency; Default_Fill : @key(in) Character := Text_IO.Editing.Default_Fill; Default_Separator : @key(in) Character := Text_IO.Editing.Default_Separator; Default_Radix_Mark : @key(in) Character := Text_IO.Editing.Default_Radix_Mark; @key(package) @AdaPackDefn{Decimal_Output} @key(is) @key(function) @AdaSubDefn{Length} (Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Natural; @key(function) @AdaSubDefn{Valid} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Boolean; @key(function) @AdaSubDefn{Image} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark) @key(return) String; @key(procedure) @AdaSubDefn{Put} (File : @key(in) File_Type; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @key(procedure) @AdaSubDefn{Put} (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @trailing@; @key(procedure) @AdaSubDefn{Put} (To : @key(out) String; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @key(end) Decimal_Output; @key(private) ... @RI{-- not specified by the language} @key(end) Ada.Text_IO.Editing; @end{Example} @ImplDef{The value of Max_Picture_Length in the package Text_IO.Editing} @Trailing@;The exception Constraint_Error is raised if the Image function or any of the Put procedures is invoked with a null string for Currency. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Valid (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Boolean; @end{Example} @Trailing@;Valid returns True if Pic_String is a well-formed picture String (see @RefSecNum(Picture String Formation)) the length of whose expansion does not exceed Max_Picture_Length, and if either Blank_When_Zero is False or Pic_String contains no '*'. @begin{Example}@Keepnext @key(function) To_Picture (Pic_String : @key(in) String; Blank_When_Zero : @key(in) Boolean := False) @key(return) Picture; @end{Example} @Trailing@;To_Picture returns a result Picture such that the application of the function Pic_String to this result yields an expanded picture String equivalent to Pic_String, and such that Blank_When_Zero applied to the result Picture is the same value as the parameter Blank_When_Zero. Picture_Error is raised if not Valid(Pic_String, Blank_When_Zero). @begin{Example} @key(function) Pic_String (Pic : @key(in) Picture) @key(return) String; @Comment{Blank line} @key(function) Blank_When_Zero (Pic : @key(in) Picture) @key(return) Boolean; @end{Example} @Leading@;If Pic is To_Picture(String_Item, Boolean_Item) for some String_Item and Boolean_Item, then: @begin[itemize] Pic_String(Pic) returns an expanded picture String equivalent to String_Item and with any lower-case letter replaced with its corresponding upper-case form, and Blank_When_Zero(Pic) returns Boolean_Item. @end[Itemize] @Leading@;If Pic_1 and Pic_2 are objects of type Picture, then "="(Pic_1, Pic_2) is True when @begin[itemize] Pic_String(Pic_1) = Pic_String(Pic_2), and @Trailing@;Blank_When_Zero(Pic_1) = Blank_When_Zero(Pic_2). @end[Itemize] @begin{Example}@Keepnext @key(function) Length (Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Natural; @end{Example} @Leading@;Length returns Pic_String(Pic)'Length + Currency_Length_Adjustment @en Radix_Adjustment where @begin[itemize] @Leading@;Currency_Length_Adjustment = @begin[Inneritemize] Currency'Length @en@; 1 if there is some occurrence of '$' in Pic_String(Pic), and 0 otherwise. @end[Inneritemize] @Leading@;Radix_Adjustment = @begin[Inneritemize] 1 if there is an occurrence of 'V' or 'v' in Pic_Str(Pic), and @Trailing@;0 otherwise. @end[Inneritemize] @end[itemize] @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency) @key(return) Boolean; @end{Example} @Trailing@;Valid returns True if Image(Item, Pic, Currency) does not raise Layout_Error, and returns False otherwise. @begin{Example} @key(function) Image (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark) @key(return) String; @end{Example} @Trailing@;Image returns the edited output String as defined in @RefSecNum(Edited Output Generation) for Item, Pic_String(Pic), Blank_When_Zero(Pic), Currency, Fill, Separator, and Radix_Mark. If these rules identify a layout error, then Image raises the exception Layout_Error. @begin{Example} @key(procedure) Put (File : @key(in) File_Type; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @Comment{Blank line} @key(procedure) Put (Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @end{Example} @Trailing@;Each of these Put procedures outputs Image(Item, Pic, Currency, Fill, Separator, Radix_Mark) consistent with the conventions for Put for other real types in case of bounded line length (see @RefSec{Get and Put Procedures}). @begin{Example} @key(procedure) Put (To : @key(out) String; Item : @key(in) Num; Pic : @key(in) Picture; Currency : @key(in) String := Default_Currency; Fill : @key(in) Character := Default_Fill; Separator : @key(in) Character := Default_Separator; Radix_Mark : @key(in) Character := Default_Radix_Mark); @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Put copies Image(Item, Pic, Currency, Fill, Separator, Radix_Mark) to the given string, right justified. Otherwise@Chg{Version=[3],New=[,],Old=[]} unassigned Character values in To are assigned the space character. If To'Length is less than the length of the string resulting from Image, then Layout_Error is raised. @end{DescribeCode} @end{StaticSem} @begin{ImplReq} Max_Picture_Length shall be at least 30. The implementation shall support currency strings of length up to at least 10, both for Default_Currency in an instantiation of Decimal_Output, and for Currency in an invocation of Image or any of the Put procedures. @begin{Discussion} This implies that a picture string with character replications need not be supported (i.e., To_Picture will raise Picture_Error) if its expanded form exceeds 30 characters. @end{Discussion} @end{ImplReq} @begin{Notes} @Leading@;The rules for edited output are based on COBOL (ANSI X3.23:1985, endorsed by ISO as ISO 1989-1985), with the following differences: @begin{Itemize} The COBOL provisions for picture string localization and for 'P' format are absent from Ada. @Leading@;The following Ada facilities are not in COBOL: @begin{InnerItemize} currency symbol placement after the number, localization of edited output string for multi-character currency string values, including support for both length-preserving and length-expanding currency symbols in picture strings localization of the radix mark, digits separator, and fill character, and parenthesization of negative values. @end{InnerItemize} @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@NoPrefix @Chg{New=[],Old=[@Noparanum@;]}The value of 30 for Max_Picture_Length is the same limit as in COBOL. @end{Notes} @begin{Reason} There are several reasons we have not adopted the COBOL-style permission to provide a single-character replacement in the picture string for the `$' as currency symbol, or to interchange the roles of `.' and `,' in picture strings @begin{Itemize} It would have introduced considerable complexity into Ada, as well as confusion between run-time and compile-time character interpretation, since picture Strings are dynamically computable in Ada, in contrast with COBOL Ada's rules for real literals provide a natural interpretation of `_' as digits separator and `.' for radix mark; it is not essential to allow these to be localized in picture strings, since Ada does not allow them to be localized in real literals. The COBOL restriction for the currency symbol in a picture string to be replaced by a single character currency symbol is a compromise solution. For general international usage a mechanism is needed to localize the edited output to be a multi-character currency string. Allowing a single-Character localization for the picture Character, and a multiple-character localization for the currency string, would be an unnecessary complication. @end{Itemize} @end{Reason} @LabeledSubClause{The Package Wide_Text_IO.Editing} @begin{StaticSem} @Leading@;@Defn{Ada.Wide_@!Text_IO.Editing} @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Editing]} The child package Wide_Text_IO.Editing has the same contents as Text_IO.Editing, except that: @begin{Itemize} each occurrence of Character is replaced by Wide_Character, each occurrence of Text_IO is replaced by Wide_Text_IO, the subtype of Default_Currency is Wide_String rather than String, and each occurrence of String in the generic package Decimal_Output is replaced by Wide_String. @end{Itemize} @ImplDef{The value of Max_Picture_Length in the package Wide_Text_IO.Editing} @end{StaticSem} @begin{Notes} Each of the functions Wide_Text_IO.Editing.Valid, To_Picture, and Pic_String has String (versus Wide_String) as its parameter or result subtype, since a picture String is not localizable. @end{Notes} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Editing]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{Ada.Wide_@!Wide_@!Text_IO.Editing} @ChildUnit{Parent=[Ada.Wide_@!Wide_@!Text_IO],Child=[Editing]} The child package Wide_Wide_Text_IO.Editing has the same contents as Text_IO.Editing, except that:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of Character is replaced by Wide_Wide_Character,]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of Text_IO is replaced by Wide_Wide_Text_IO,]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the subtype of Default_Currency is Wide_Wide_String rather than String, and]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[each occurrence of String in the generic package Decimal_Output is replaced by Wide_Wide_String.]} @end{Itemize} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The value of Max_Picture_Length in the package Wide_Wide_Text_IO.Editing],Old=[]}]} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Each of the functions Wide_Wide_Text_IO.Editing.Valid, To_Picture, and Pic_String has String (versus Wide_Wide_String) as its parameter or result subtype, since a picture String is not localizable.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Editing is new; it supports 32-bit character strings. (Shouldn't it have been @lquotes@;Widest_Text_IO.Editing@rquotes@;? :-)]} @end{Extend95} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/interface.mss��������������������������������������������������������0000755�0001752�0001001�00000465452�12066652506�020131� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/interface.mss,v $ } @comment{ $Revision: 1.68 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(interface, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledNormativeAnnex{Interface to Other Languages} @begin{Intro} @Defn{interface to other languages} @Defn2{Term=[language], Sec=(interface to non-Ada)} @Defn{mixed-language programs} This Annex describes features for writing mixed-language programs. General interface support is presented first; then specific support for C, COBOL, and Fortran is defined, in terms of language interface packages for each of these languages. @begin{Ramification} This Annex is not a @lquotes@;Specialized Needs@rquotes@; annex. Every implementation must support all nonoptional features defined here (mainly the package Interfaces). @end{Ramification} @end{Intro} @begin{MetaRules} Ada should have strong support for mixed-language programming. @end{MetaRules} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0262-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[Support for interfacing to any foreign language is optional. However, an implementation shall not provide any optional aspect, attribute, library unit, or pragma having the same name as an aspect, attribute, library unit, or pragma (respectively) specified in the subclauses of this Annex unless the provided construct is either as specified in those subclauses or is more limited in capability than that required by those subclauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The intent is that the same rules apply for the optional parts of language interfacing as apply for Specialized Needs Annexes. See @RefSecNum{Conformity of an Implementation with the Standard} for a discussion of the purpose of these rules.]} @end{Discussion} @end{ImplReq} @begin{Extend83} @Defn{extensions to Ada 83} Much of the functionality in this Annex is new to Ada 95. @end{Extend83} @begin{DiffWord83} This Annex contains what used to be RM83-13.8. @end{DiffWord83} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Moved the clarification that interfacing to foreign languages is optional and has the same restrictions as a Specialized Needs Annex here.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[3],New=[Interfacing Aspects],Old=[Interfacing Pragmas]} @begin{Intro} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[An @i<interfacing> aspect is a representation aspect that is one of the aspects Import, Export, Link_Name, External_Name, or Convention.@Defn{interfacing aspect}@Defn2{Term=[aspect],Sec=[interfacing]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @Chg{Version=[3],New=[@AspectDefn{Import}Specifying the],Old=[A @nt{pragma}]} Import @Chg{Version=[3],New=[aspect to have the value True ],Old=[]}is used to import an entity defined in a foreign language into an Ada program, thus allowing a foreign-language subprogram to be called from Ada, or a foreign-language variable to be accessed from Ada. In contrast, @Chg{Version=[3],New=[@AspectDefn{Export}specifying the],Old=[a @nt{pragma}]} Export @Chg{Version=[3],New=[aspect to have the value True ],Old=[]}is used to export an Ada entity to a foreign language, thus allowing an Ada subprogram to be called from a foreign language, or an Ada object to be accessed from a foreign language. The@Chg{Version=[3],New=[],Old=[ @nt[pragma]s]} Import and Export@Chg{Version=[3],New=[ aspects],Old=[]} are intended primarily for objects and subprograms, although implementations are allowed to support other entities.@Chg{Version=[3],New=[ The Link_Name and External_Name aspects are used to specify the link name and external name, respectively, to be used to identify imported or exported entities in the external environment.@AspectDefn{Link_Name}@AspectDefn{External_Name} @PDefn2{Term=[representation aspect], Sec=(convention, calling convention)} @PDefn2{Term=[representation aspect], Sec=(import)} @PDefn2{Term=[representation aspect], Sec=(export)} @PDefn2{Term=[representation aspect], Sec=(external_name)} @PDefn2{Term=[representation aspect], Sec=(link_name)}],Old=[]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Import], Text=[@ChgAdded{Version=[3],Text=[Entity is imported from another language.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Export], Text=[@ChgAdded{Version=[3],Text=[Entity is exported to another language.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[External_Name], Text=[@ChgAdded{Version=[3],Text=[Name used to identify an imported or exported entity.]}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Link_Name], Text=[@ChgAdded{Version=[3],Text=[Linker symbol used to identify an imported or exported entity.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The],Old=[A @nt{pragma}]} Convention @Chg{Version=[3],New=[aspect@AspectDefn{Convention} ],Old=[]}is used to @Chg{Version=[3],New=[indicate],Old=[specify]} that an Ada entity should use the conventions of another language. It is intended primarily for types and @lquotes@;callback@rquotes@; subprograms. For example, @lquotes@;@Chg{Version=[3],New=[@key{with}],Old=[@key{pragma}]} Convention@Chg{Version=[3],New=[ => ],Old=[(]}Fortran@Chg{Version=[3],New=[],Old=[, Matrix);]}@rquotes@; @Chg{Version=[3],New=[on the declaration of an array type Matrix ],Old=[]}implies that Matrix should be represented according to the conventions of the supported Fortran implementation, namely column-major order. @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Convention], Text=[@ChgAdded{Version=[3],Text=[Calling convention or other convention used for interfacing to other languages.]}]} A @nt{pragma} Linker_Options is used to specify the system linker parameters needed when a given compilation unit is included in a partition. @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The form of a],Old=[@RootDefn{interfacing pragma} @PDefn2{Term=[interfacing pragma], Sec=(Import)} @PDefn2{Term=[pragma, interfacing], Sec=(Import)} @PDefn2{Term=[interfacing pragma], Sec=(Export)} @PDefn2{Term=[pragma, interfacing], Sec=(Export)} @PDefn2{Term=[interfacing pragma], Sec=(Convention)} @PDefn2{Term=[pragma, interfacing], Sec=(Convention)} @PDefn2{Term=[pragma, interfacing], Sec=(Linker_Options)} An @i{interfacing pragma} is a representation @nt[pragma] that is one of the @nt{pragma}s Import, Export, or Convention. Their forms, together with that of the related]} @nt[pragma] Linker_Options@Chg{Version=[3],New=[ is],Old=[, are]} as follows: @end{SyntaxText} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 5 through 7 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @DeletedPragmaSyn`Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text="@key{pragma} @prag(Import)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{string_}@Syn2{expression}] [, [Link_Name =>] @SynI{string_}@Syn2{expression}]);"}' @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @DeletedPragmaSyn`Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text="@key{pragma} @prag(Export)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{string_}@Syn2{expression}] [, [Link_Name =>] @SynI{string_}@Syn2{expression}]);"}' @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @DeletedPragmaSyn`Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text="@key{pragma} @prag(Convention)([Convention =>] @SynI{convention_}@Syn2{identifier},[Entity =>] @Syn2{local_name});"}' @PragmaSyn`@key{pragma} @prag(Linker_Options)(@SynI{string_}@Syn2{expression});' @begin{SyntaxText} A @nt[pragma] Linker_Options is allowed only at the place of a @nt[declarative_item]. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0058],ARef=[AI95-00036-01]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[1],Text=[@Chg{Version=[3],New=[],Old=[For @nt{pragma}s Import and Export, the argument for Link_Name shall not be given without the @i{pragma_@!argument_}@!@nt{identifier} unless the argument for External_Name is given.]}]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The Import and Export aspects are of type Boolean.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The @Chg{Version=[3],New=[Link_Name and External_Name aspects are of],Old=[expected]} type @Chg{Version=[3],New=[],Old=[for a @SynI{string_}@Syn2{expression}@PDefn2{Term=[expected type], Sec=(link name)} in an interfacing pragma or in pragma Linker_Options is ]}String. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised]} There is no language-defined support for external or link names of type Wide_String, or of other string types. Implementations may, of course, have additional @Chg{Version=[3],New=[aspects],Old=[pragmas]} for that purpose. Note that allowing both String and Wide_String in the same @Chg{Version=[3],New=[@nt{aspect_definition}],Old=[@nt{pragma}]} would cause ambiguities. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[expected type],Sec=(linker options)} The expected type for the @SynI{string_}@Syn2{expression} in pragma Linker_Options is String.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{convention} The @Chg{Version=[3],New=[aspect Convention shall be specified by a ],Old=[]}@SynI{convention_}@nt{identifier} @Chg{Version=[3],New=[which],Old=[of an interfacing pragma]} shall be the name of a @i{convention}. The convention names are implementation defined, except for certain language-defined ones, such as Ada and Intrinsic, as explained in @RefSec{Conformance Rules}. @Redundant[Additional convention names generally represent the calling conventions of foreign languages, language implementations, or specific run-time models.] @Defn{calling convention} The convention of a callable entity is its @i{calling convention}. @ImplDef{Implementation-defined convention names.} @begin{Discussion} We considered representing the convention names using an enumeration type declared in System. Then, @SynI{convention_}@nt{identifier} would be changed to @SynI{convention_}@nt{name}, and we would make its expected type be the enumeration type. We didn't do this because it seems to introduce extra complexity, and because the list of available languages is better represented as the list of children of package Interfaces @em a more open-ended sort of list. @end{Discussion} @Leading@Defn2{Term=[compatible],Sec=[a type, with a convention]} If @i[L] is a @i[convention_]@nt[identifier] for a language, then a type T is said to be @i{compatible with convention L}, (alternatively, is said to be an @i[L-compatible type]) if any of the following conditions are met: @begin[itemize] T is declared in a language interface package corresponding to @i[L] and is defined to be @i[L]-compatible (see @refsecnum(Interfacing with C and C++), @refsecnum(The Package Interfaces.C.Strings), @refsecnum(The Generic Package Interfaces.C.Pointers), @refsecnum(Interfacing with COBOL), @refsecnum(Interfacing with Fortran)), @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[eligible],Sec=[a type, for a convention]} Convention @i[L] has been specified for T@Chg{Version=[3],New=[],Old=[ in a @nt[pragma] Convention]}, and T is @i{eligible for convention @i[L]}; that is: @begin[inneritemize] T is an array type with either an unconstrained or statically-constrained first subtype, and its component type is @i[L]-compatible, T is a record type that has no discriminants and that only has components with statically-constrained subtypes, and each component type is @i[L]-compatible, @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0002-1]} T is an access-to-object type, @Chg{Version=[3],New=[],Old=[and ]}its designated type is @i[L]-compatible,@Chg{Version=[3],New=[ and its designated subtype is not an unconstrained array subtype,],Old=[]} T is an access-to-subprogram type, and its designated profile's parameter and result types are all @i[L]-compatible. @end[inneritemize] T is derived from an @i[L]-compatible type, The implementation permits T as an @i[L]-compatible type. @begin{discussion} For example, an implementation might permit Integer as a C-compatible type, though the C type to which it corresponds might be different in different environments. @end{discussion} @end[itemize] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If @Chg{Version=[3],New=[the],Old=[@nt[pragma]]} Convention @Chg{Version=[3],New=[aspect is specified for],Old=[applies to]} a type, then the type shall either be compatible with or eligible for the @Chg{Version=[3],New=[specified ],Old=[]}convention@Chg{Version=[3], New=[],Old=[ specified in the pragma]}. @begin[ramification] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If a type is derived from an @i[L]-compatible type, the derived type is by default @i[L]-compatible, but it is also permitted to specify @Chg{Version=[3],New=[the],Old=[pragma]} Convention @Chg{Version=[3],New=[aspect ],Old=[]}for the derived type. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} It is permitted to specify @Chg{Version=[3],New=[the],Old=[pragma]} Convention @Chg{Version=[3],New=[aspect ],Old=[]}for an incomplete type, but in the complete declaration each component must be @i[L]-compatible. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If each component of a record type is @i[L]-compatible, then the record type itself is only @i[L]-compatible if it has @Chg{Version=[3],New=[a specified],Old=[a pragma]} Convention. @end[Ramification] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[],Old=[A @nt{pragma} Import shall be the completion of a declaration.]}@Defn{notwithstanding} Notwithstanding any rule to the contrary, @Chg{Version=[3],New=[a declaration with a True],Old=[a @nt{pragma}]} Import @Chg{Version=[3],New=[aspect shall not have a],Old=[may serve as the]} completion@Chg{Version=[3],New=[],Old=[ of any kind of (explicit) declaration if supported by an implementation for that kind of declaration. If a completion is a @nt{pragma} Import, then it shall appear in the same @nt{declarative_part}, @nt{package_specification}, @nt{task_definition} or @nt{protected_definition} as the declaration. For a library unit, it shall appear in the same @nt{compilation}, before any subsequent @nt{compilation_unit}s other than @nt{pragma}s. If the @nt{local_name} denotes more than one entity, then the @nt{pragma} Import is the completion of all of them]}. @begin(Discussion) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For declarations of deferred constants and subprograms, we @Chg{Version=[3],New=[explicitly ],Old=[]}mention @Chg{Version=[3],New=[that no completion is allowed when aspect], Old=[pragma]} Import @Chg{Version=[3],New=[is True],Old=[explicitly as a possible completion]}. For other declarations that require completions, we ignore the possibility of @Chg{Version=[3],New=[the aspect],Old=[pragma]} Import@Chg{Version=[3],New=[ being True],Old=[]}. Nevertheless, if an implementation chooses to allow @Chg{Version=[3],New=[specifying aspect],Old=[a @nt{pragma}]} Import to @Chg{Version=[3],New=[be True for],Old=[complete]} the declaration of a task, protected type, incomplete type, private type, etc., it may do so, and the normal completion is then not allowed for that declaration. @end(Discussion) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{imported entity} @Defn{exported entity} An entity @Chg{Version=[3],New=[with a True],Old=[specified as the Entity argument to a @nt[pragma]]} Import@Chg{Version=[3],New=[ aspect],Old=[]} (or @Chg{Version=[3],New=[],Old=[@nt[pragma] ]}Export@Chg{Version=[3],New=[ aspect],Old=[]}) is said to be @i{imported} (respectively, @i{exported}).@Chg{Version=[3],New=[ An entity shall not be both imported and exported.],Old=[]} The declaration of an imported object shall not include an explicit initialization expression. @Redundant[Default initializations are not performed.] @begin{TheProof} This follows from the @lquotes@;Notwithstanding ...@rquotes@; wording in the Dynamics Semantics paragraphs below. @end{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The type of an imported or exported object shall be compatible with the @Chg{Version=[3],New=[specified Convention aspect, if any], Old=[convention specified in the corresponding @nt{pragma}]}. @begin[Ramification] This implies, for example, that importing an Integer object might be illegal, whereas importing an object of type Interfaces.C.int would be permitted. @end[Ramification] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For an imported or exported subprogram, the result and parameter types shall each be compatible with the @Chg{Version=[3],New=[specified Convention aspect, if any], Old=[convention specified in the corresponding pragma]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The @nt{aspect_definition} (if any) used to directly specify an],Old=[The external name and link name @SynI{string_}@nt[expression]s of a @nt{pragma}]} Import@Chg{Version=[3],New=[,],Old=[ or]} Export, @Chg{Version=[3],New=[External_Name, or Link_Name aspect shall be a static expression. The],Old=[and the]} @SynI[string_]@nt[expression] of a @nt[pragma] Linker_Options@Chg{Version=[3],New=[],Old=[,]} shall be static.@Chg{Version=[3],New=[ An External_Name or Link_Name aspect shall be specified only for an entity that is either imported or exported.],Old=[]} @end{Legality} @begin{StaticSem} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 28 and 29 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[representation pragma], Sec=(Import)} @PDefn2{Term=[pragma, representation], Sec=(Import)} @PDefn2{Term=[representation pragma], Sec=(Export)} @PDefn2{Term=[pragma, representation], Sec=(Export)} @PDefn2{Term=[representation pragma], Sec=(Convention)} @PDefn2{Term=[pragma, representation], Sec=(Convention)} @PDefn2{Term=[aspect of representation], Sec=(convention, calling convention)} @Defn2{Term=[convention], Sec=(aspect of representation)} Import, Export, and Convention @nt{pragma}s are representation pragmas that specify the @i{convention} aspect of representation. @PDefn2{Term=[aspect of representation], Sec=(imported)} @Defn2{Term=[imported], Sec=(aspect of representation)} @PDefn2{Term=[aspect of representation], Sec=(exported)} @Defn2{Term=[exported], Sec=(aspect of representation)} In addition, Import and Export @nt{pragma}s specify the @i{imported} and @i{exported} aspects of representation, respectively.]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[program unit pragma], Sec=(Import)} @PDefn2{Term=[pragma, program unit], Sec=(Import)} @PDefn2{Term=[program unit pragma], Sec=(Export)} @PDefn2{Term=[pragma, program unit], Sec=(Export)} @PDefn2{Term=[program unit pragma], Sec=(Convention)} @PDefn2{Term=[pragma, program unit], Sec=(Convention)} An interfacing pragma is a program unit pragma when applied to a program unit (see @RefSecNum{Pragmas and Program Units}).]} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[],Old=[An interfacing pragma defines the convention of the entity denoted by the @nt{local_name}. ]}The @Chg{Version=[3],New=[Convention aspect],Old=[convention]} represents the calling convention or representation convention of the entity. For an access-to-subprogram type, it represents the calling convention of designated subprograms. In addition: @begin{Itemize} @ChgRef{Version=[3],Kind=[Revised]} A @Chg{Version=[3],New=[True],Old=[@nt{pragma}]} Import @Chg{Version=[3],New=[aspect indicates],Old=[specifies]} that the entity is defined externally (that is, outside the Ada program).@Chg{Version=[3],New=[ This aspect is never inherited; if not directly specified, the Import aspect is False.],Old=[]} @ChgRef{Version=[3],Kind=[Revised]} A @Chg{Version=[3],New=[True],Old=[@nt{pragma}]} Export @Chg{Version=[3],New=[aspect indicates],Old=[specifies]} that the entity is used externally.@Chg{Version=[3],New=[ This aspect is never inherited; if not directly specified, the Export aspect is False.],Old=[]} @ChgRef{Version=[3],Kind=[Revised]} @Chg{Version=[3],New=[For an entity with a True],Old=[A @nt{pragma}]} Import or Export @Chg{Version=[3],New=[aspect, an],Old=[optionally specifies an entity's]} external name, link name, or both@Chg{Version=[3],New=[ may also be specified],Old=[]}. @end{Itemize} @Defn{external name} An @i{external name} is a string value for the name used by a foreign language program either for an entity that an Ada program imports, or for referring to an entity that an Ada program exports. @Defn{link name} A @i[link name] is a string value for the name of an exported or imported entity, based on the conventions of the foreign language's compiler in interfacing with the system's linker tool. The meaning of link names is implementation defined. If neither a link name nor the Address attribute of an imported or exported entity is specified, then a link name is chosen in an implementation-defined manner, based on the external name if one is specified. @ImplDef{The meaning of link names.} @begin{Ramification} For example, an implementation might always prepend "_", and then pass it to the system linker. @end{Ramification} @ImplDef{The manner of choosing link names when neither the link name nor the address of an imported or exported entity is specified.} @begin{Ramification} Normally, this will be the entity's defining name, or some simple transformation thereof. @end{Ramification} Pragma Linker_Options has the effect of passing its string argument as a parameter to the system linker (if one exists), if the immediately enclosing compilation unit is included in the partition being linked. The interpretation of the string argument, and the way in which the string arguments from multiple Linker_Options pragmas are combined, is implementation defined. @ImplDef(The effect of pragma Linker_Options.) @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[@PDefn2{Term=[elaboration], Sec=(declaration with a True Import aspect)}], Old=[@PDefn2{Term=[elaboration], Sec=(declaration named by a @nt{pragma} Import)}]} @Defn{notwithstanding} Notwithstanding what this International Standard says elsewhere, the elaboration of a declaration @Chg{Version=[3],New=[with a True Import aspect],Old=[denoted by the @nt{local_name} of a @nt{pragma} Import]} does not create the entity. Such an elaboration has no other effect than to allow the defining name to denote the external entity. @begin{Ramification} This implies that default initializations are skipped. (Explicit initializations are illegal.) For example, an imported access object is @i{not} initialized to @key[null]. @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[Note that the @nt{local_name} in a @nt{pragma} Import might denote more than one declaration; in that case, the entity of all of those declarations will be the external entity.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} This @lquotes@;notwithstanding@rquotes@; wording is better than saying @lquotes@;unless @Chg{Version=[3],New=[aspect],Old=[named by a @nt{pragma}]} Import@Chg{Version=[3],New=[ is True],Old=[]}@rquotes@; on every definition of elaboration. It says we recognize the contradiction, and this rule takes precedence. @end{Discussion} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00320-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} It is the programmer's responsibility to ensure that the use of interfacing @Chg{Version=[3],New=[aspects],Old=[pragmas]} does not violate Ada semantics; otherwise, program execution is erroneous.]} @end{Erron} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If an implementation supports @Chg{Version=[3],New=[],Old=[pragma ]}Export @Chg{Version=[3],New=[for],Old=[to]} a given language, then it should also allow the main subprogram to be written in that language. It should support some mechanism for invoking the elaboration of the Ada library units included in the system, and for invoking the finalization of the environment task. On typical systems, the recommended mechanism is to provide two subprograms whose link names are "adainit" and "adafinal". Adainit should contain the elaboration code for library units. Adafinal should contain the finalization code. These subprograms should have no effect the second and subsequent time they are called. @Chg{New=[@Defn{adainit}@Defn{adafinal}@Defn2{Term=[Elaboration], Sec=[of library units for a foreign language main subprogram]} @Defn2{Term=[Finalization], Sec=[of environment task for a foreign language main subprogram]}], Old=[]}@ChgNote{Presentation AI-00052. Index entries only; no real change, so no Chgref} @ChgImplAdvice{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[If @Chg{Version=[3],New=[],Old=[@nt{pragma} ]} Export is supported for a language, the main program should be able to be written in that language. Subprograms named "adainit" and "adafinal" should be provided for elaboration and finalization of the environment task.]}]} @begin{ramification} For example, if the main subprogram is written in C, it can call adainit before the first call to an Ada subprogram, and adafinal after the last. @end{ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} Automatic elaboration of preelaborated packages should be provided when @Chg{Version=[3],New=[specifying the],Old=[@nt[pragma]]} Export @Chg{Version=[3],New=[aspect as True ],Old=[]}is supported. @ChgImplAdvice{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[Automatic elaboration of preelaborated packages should be provided when @Chg{Version=[3],New=[specifying the],Old=[@nt[pragma]]} Export @Chg{Version=[3],New=[aspect as True ],Old=[]}is supported.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For each supported convention @i[L] other than Intrinsic, an implementation should support @Chg{Version=[3],New=[specifying the ],Old=[]}Import and Export @Chg{Version=[3],New=[aspects],Old=[@nt{pragma}s]} for objects of @i[L]-compatible types and for subprograms, and @Chg{Version=[3],New=[the],Old=[@nt(pragma)]} Convention @Chg{Version=[3],New=[aspect ],Old=[]}for @i[L]-eligible types and for subprograms, presuming the other language has corresponding features. @Chg{Version=[3],New=[Specifying the ],Old=[@nt{Pragma}]} Convention @Chg{Version=[3],New=[aspect ],Old=[]}need not be supported for scalar types. @ChgImplAdvice{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[For each supported convention @i[L] other than Intrinsic, @Chg{Version=[3],New=[specifying the aspects],Old=[@nt{pragma}s]} Import and Export should be supported for objects of @i[L]-compatible types and for subprograms, and @Chg{Version=[3],New=[aspect],Old=[@nt(pragma)]} Convention should be supported for @i[L]-eligible types and for subprograms.]}]} @begin{reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[Specifying aspect],Old=[Pragma]} Convention is not necessary for scalar types, since the language interface packages declare scalar types corresponding to those provided by the respective foreign languages. @end[reason] @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} If an implementation supports interfacing to @Chg{Version=[2],New=[the ], Old=[]}C++@Chg{Version=[2],New=[ entities not supported by @RefSecNum{Interfacing with C and C++}],Old=[]}, it should do so via the convention identifier C_Plus_Plus (in additional to any C++-implementation-specific ones). @end{ImplNote} @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The reason for giving the advice about C++ is to encourage uniformity among implementations, given that the name of the language is not syntactically legal as an @nt{identifier}.@Chg{Version=[2],New=[],Old=[ We place this advice in the AARM, rather than the RM95 proper, because (as of this writing) C++ is not an international standard, and we don't want to refer to a such a language from an international standard.]} @end{Reason} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Implementations may place restrictions on interfacing @Chg{Version=[3],New=[aspects],Old=[pragmas]}; for example, requiring each exported entity to be declared at the library level. @begin{TheProof} Arbitrary restrictions are allowed by @RefSecNum{Operational and Representation Aspects}. @end{TheProof} @begin{Ramification} Such a restriction might be to disallow them altogether. Alternatively, the implementation might allow them only for certain kinds of entities, or only for certain conventions. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The Convention aspect in combination with the],Old=[A @nt{pragma}]} Import @Chg{Version=[3],New=[aspect indicates],Old=[specifies]} the conventions for accessing external entities. It is possible that the actual entity is written in assembly language, but reflects the conventions of a particular language. For example, @Chg{Version=[3],New=[@exam{@key[with] Convention => Ada}],Old=[@key{pragma} Import(Ada, ...)]} can be used to interface to an assembly language routine that obeys the Ada compiler's calling conventions. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} To obtain @lquotes@;call-back@rquotes@; to an Ada subprogram from a foreign language environment, @Chg{Version=[3],New=[the],Old=[@key(pragma)]} Convention @Chg{Version=[3],New=[aspect ],Old=[]}should be specified both for the access-to-subprogram type and the specific subprogram(s) to which 'Access is applied. @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 45 and 46 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[It is illegal to specify more than one of Import, Export, or Convention for a given entity.]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The @nt{local_name} in an interfacing pragma can denote more than one entity in the case of overloading. Such a @nt{pragma} applies to all of the denoted entities.]} See also @RefSec{Machine Code Insertions}. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The Intrinsic convention (see @refsecnum(Conformance Rules)) implies that the entity is somehow @lquotes@;built in@rquotes@; to the implementation. Thus, it generally does not make sense for users to specify Intrinsic @Chg{Version=[3],New=[along with specifying that the entity is imported], Old=[in a @nt{pragma} Import]}. The intention is that only implementations will specify Intrinsic @Chg{Version=[3],New=[for an imported entity],Old=[in a @nt{pragma} Import]}. The language also defines certain subprograms to be Intrinsic. @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} There are many imaginable interfacing @Chg{Version=[3],New=[aspects], Old=[pragmas]} that don't make any sense. For example, setting the Convention of a protected procedure to Ada is probably wrong. Rather than enumerating all such cases, however, we leave it up to implementations to decide what is sensible. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If both External_Name and Link_Name are specified for @Chg{Version=[3], New=[a given entity],Old=[an Import or Export pragma]}, then the External_Name is ignored. @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00320-01]} @ChgDeleted{Version=[2],Text=[An interfacing pragma might result in an effect that violates Ada semantics.]} @end{Notes} @begin{Examples} @leading@keepnext@i{Example of interfacing pragmas:} @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @key[package] Fortran_Library @key[is] @key[function] Sqrt (X : Float) @key[return] Float@Chg{Version=[3],New=[ @key[with] Import => True, Convention => Fortran],Old=[]}; @Chg{Version=[3],New=[@key[type] Matrix @key[is array] (Natural @key[range] <>, Natural @key[range] <>) @key[of] Float @key[with] Convention => Fortran; ],Old=[]}@key[function] @Chg{Version=[3],New=[Invert (M : Matrix],Old=[Exp (X : Float]}) @key[return] @Chg{Version=[3],New=[Matrix @key[with] Import => True, Convention => Fortran],Old=[Float]};@Chg{Version=[3],New=[],Old=[ @key[private] @key[pragma] Import(Fortran, Sqrt); @key[pragma] Import(Fortran, Exp);]} @key[end] Fortran_Library; @end{Example} @end{Examples} @begin{Extend83} @Defn{extensions to Ada 83} Interfacing pragmas are new to Ada 95. Pragma Import replaces Ada 83's pragma Interface. Existing implementations can continue to support pragma Interface for upward compatibility. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0058],ARef=[AI95-00036-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that @nt{pragma}s Import and Export work like a subprogram call; parameters cannot be omitted unless named notation is used. (Reordering is still not permitted, however.)]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00320-01]} @ChgAdded{Version=[2],Text=[Added wording to say all bets are off if foreign code doesn't follow the semantics promised by the Ada specifications.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0002-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Access types that designate unconstrained arrays are no longer defined to be @i[L]-compatible. Such access-to-arrays require bounds information, which is likely to be incompatible with a foreign language. The change will allow (but not require) compilers to reject bad uses, which probably will not work anyway. Note that implementations can still support any type that it wants as @i[L]-compatible; such uses will not be portable, however. As such, there should be little existing code that will be impacted (compilers probably already rejected cases that could not be translated, whether or not the language allowed doing so formally).]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspects Convention, Import, Export, Link_Name, and External_Name are new; @nt{pragma}s Convention, Import, and Export are now obsolescent.]} @end{Extend2005} @LabeledClause{The Package Interfaces} @begin{Intro} Package Interfaces is the parent of several library packages that declare types and other entities useful for interfacing to foreign languages. It also contains some implementation-defined types that are useful across more than one language (in particular for interfacing to assembly language). @ImplDef{The contents of the visible part of package Interfaces and its language-defined descendants.} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces has the following skeletal declaration: @begin{Example} @RootLibUnit{Interfaces} @key[package] Interfaces @key[is] @key[pragma] Pure(Interfaces); @key[type] Integer_@RI{n} @key[is] @key[range] -2**(@RI{n}-1) .. 2**(@RI{n}-1) - 1; --@RI{2's complement} @key[type] Unsigned_@RI{n} @key[is] @key[mod] 2**@RI{n}; @key[function] Shift_Left (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Shift_Right (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Shift_Right_Arithmetic (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Rotate_Left (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; @key[function] Rotate_Right (Value : Unsigned_@RI{n}; Amount : Natural) @key[return] Unsigned_@RI{n}; ... @key[end] Interfaces; @end{Example} @end{StaticSem} @begin{ImplReq} @Leading@;An implementation shall provide the following declarations in the visible part of package Interfaces: @begin{Itemize} Signed and modular integer types of @i{n} bits, if supported by the target architecture, for each @i{n} that is at least the size of a storage element and that is a factor of the word size. The names of these types are of the form Integer_@i{n} for the signed types, and Unsigned_@i{n} for the modular types; @begin{Ramification} For example, for a typical 32-bit machine the corresponding types might be Integer_8, Unsigned_8, Integer_16, Unsigned_16, Integer_32, and Unsigned_32. The wording above implies, for example, that Integer_16'Size = Unsigned_16'Size = 16. Unchecked conversions between same-Sized types will work as expected. @end{Ramification} @Defn{shift}@Defn{rotate} For each such modular type in Interfaces, shifting and rotating subprograms as specified in the declaration of Interfaces above. These subprograms are Intrinsic. They operate on a bit-by-bit basis, using the binary representation of the value of the operands to yield a binary representation for the result. The Amount parameter gives the number of bits by which to shift or rotate. For shifting, zero bits are shifted in, except in the case of Shift_Right_Arithmetic, where one bits are shifted in if Value is at least half the modulus. @begin{Reason} We considered making shifting and rotating be primitive operations of all modular types. However, it is a design principle of Ada that all predefined operations should be operators (not functions named by identifiers). (Note that an early version of Ada had "@key[abs]" as an identifier, but it was changed to a reserved word operator before standardization of Ada 83.) This is important because the implicit declarations would hide nonoverloadable declarations with the same name, whereas operators are always overloadable. Therefore, we would have had to make shift and rotate into reserved words, which would have been upward incompatible, or else invent new operator symbols, which seemed like too much mechanism. @end{Reason} Floating point types corresponding to each floating point format fully supported by the hardware. @begin{ImplNote} The names for these floating point types are not specified. @Defn{IEEE floating point arithmetic} However, if IEEE arithmetic is supported, then the names should be IEEE_Float_32 and IEEE_Float_64 for single and double precision, respectively. @end{ImplNote} @end{Itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00204-01]} @ChgRef{Version=[3],Kind=[DeletedAddedNoDelMsg],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Support for interfacing to any foreign language is optional. However, an implementation shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in the following clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The intent is that the same rules apply for language interfacing as apply for Specialized Needs Annexes. See @RefSecNum{Conformity of an Implementation with the Standard} for a discussion of the purpose of these rules.]}]} @end{Discussion} @end{ImplReq} @begin{ImplPerm} An implementation may provide implementation-defined library units that are children of Interfaces, and may add declarations to the visible part of Interfaces in addition to the ones defined above. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[Implementation-defined children of package Interfaces.@Chg{Version=[2],New=[],Old=[ The contents of the visible part of package Interfaces.]}]} @ChgNote{The latter sentence is given previously!} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00204-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[A child package of package Interfaces with the name of a convention may be provided independently of whether the convention is supported by the @Chg{Version=[3],New=[],Old=[pragma ]}Convention @Chg{Version=[3],New=[aspect ],Old=[]}and vice versa. Such a child package should contain any declarations that would be useful for interfacing to the language (implementation) represented by the convention. Any declarations useful for interfacing to any language on the given hardware architecture should be provided directly in Interfaces.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]}@ChgNote{Moved from below} @ChgAdded{Version=[2],Text=[For example, package Interfaces.XYZ_Pascal might contain declarations of types that match the data types provided by the XYZ implementation of Pascal, so that it will be more convenient to pass parameters to a subprogram whose convention is XYZ_Pascal.]} @end{Ramification} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00204-01]} @ChgDeleted{Version=[2],Text=[For each implementation-defined convention identifier, there should be a child package of package Interfaces with the corresponding name. This package should contain any declarations that would be useful for interfacing to the language (implementation) represented by the convention. Any declarations useful for interfacing to any language on the given hardware architecture should be provided directly in Interfaces.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[For example, package Interfaces.XYZ_Pascal might contain declarations of types that match the data types provided by the XYZ implementation of Pascal, so that it will be more convenient to pass parameters to a subprogram whose convention is XYZ_Pascal.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} An implementation supporting an interface to C, COBOL, or Fortran should provide the corresponding package or packages described in the following @Chg{Version=[3],New=[subclauses],Old=[clauses]}. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If an interface to C, COBOL, or Fortran is provided, the corresponding package or packages described in @RefSec{Interface to Other Languages} should also be provided.]}]} @begin{ImplNote} @Leading@;The intention is that an implementation might support several implementations of the foreign language: Interfaces.This_Fortran and Interfaces.That_Fortran might both exist. The @lquotes@;default@rquotes@; implementation, overridable by the user, should be declared as a renaming: @begin{Example} @key[package] Interfaces.Fortran @key[renames] Interfaces.This_Fortran; @end{Example} @end{ImplNote} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00204-01]} @ChgAdded{Version=[2],Text=[Clarified that interfacing to foreign languages is optional and has the same restrictions as a Specialized Needs Annex.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Move the restrictions on implementations of optional features to the start of this Annex.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[2],New=[Interfacing with C and C++], Old=[Interfacing with C]} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00376-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{interface to C} @Defn{C interface} The facilities relevant to interfacing with the C language @Chg{Version=[2],New=[and the corresponding subset of the C++ language ],Old=[]}are the package Interfaces.C and its children@Chg{Version=[3],New=[, and ],Old=[; @Chg{New=[],Old=[and ]}]}support for @Chg{Version=[3],New=[specifying ],Old=[]}the @Chg{Version=[3],New=[],Old=[Import, Export, and]} Convention @Chg{Version=[3],New=[aspect],Old=[pragmas]} with @Chg{Version=[3],New=[@SynI{convention_}@nt{identifier}s],Old=[@SynI{convention_}@nt{identifier}]} C@Chg{New=[@Chg{Version=[3],New=[ and],Old=[; and support for the Convention pragma with @SynI{convention_}@nt{identifier}]} C_Pass_By_Copy],Old=[]}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00376-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI95-0262-1],ARef=[AI95-0299-1]} The package Interfaces.C contains the basic types, constants@Chg{Version=[3],New=[,],Old=[]} and subprograms that allow an Ada program to pass scalars and strings to C @Chg{Version=[2],New=[and C++ ],Old=[]}functions.@Chg{Version=[2],New=[ When this @Chg{Version=[3],New=[subclause],Old=[clause]} mentions a C entity, the reference also applies to the corresponding entity in C++.],Old=[]} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.C has the following declaration: @begin{Example} @key(package) Interfaces.C @key(is)@ChildUnit{Parent=[Interfaces],Child=[C]} @key(pragma) Pure(C); @RI{-- Declarations based on C's <limits.h>} @AdaObjDefn{CHAR_BIT} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 8} @AdaObjDefn{SCHAR_MIN} : @key(constant) := @RI{implementation-defined}; @RI{-- typically @en@;128} @AdaObjDefn{SCHAR_MAX} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 127} @AdaObjDefn{UCHAR_MAX} : @key(constant) := @RI{implementation-defined}; @RI{-- typically 255} @RI{-- Signed and Unsigned Integers} @key(type) @AdaTypeDefn{int} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{short} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{long} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{signed_char} @key(is) @key(range) SCHAR_MIN .. SCHAR_MAX; @key(for) signed_char'Size @key(use) CHAR_BIT; @key(type) @AdaTypeDefn{unsigned} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_short} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_long} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{unsigned_char} @key(is) @key(mod) (UCHAR_MAX+1); @key(for) unsigned_char'Size @key(use) CHAR_BIT; @key(subtype) @AdaTypeDefn{plain_char} @key(is) @RI{implementation-defined}; @key(type) @AdaTypeDefn{ptrdiff_t} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{size_t} @key(is) @key(mod) @RI{implementation-defined}; @RI{-- Floating Point} @key(type) @AdaTypeDefn{C_float} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{double} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{long_double} @key(is) @key(digits) @RI{implementation-defined}; @RI{-- Characters and Strings } @key(type) @AdaTypeDefn{char} @key(is) @RI{<implementation-defined character type>}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @AdaObjDefn{nul} : @key(constant) char := @Chg{New=[@RI{implementation-defined}],Old=[char'First]}; @key[function] @AdaSubDefn{To_C} (Item : @key[in] Character) @key[return] char; @key[function] @AdaSubDefn{To_Ada} (Item : @key[in] char) @key[return] Character; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @key(type) @AdaTypeDefn{char_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @key[aliased] char@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(char_array)]}; @key(for) char_array'Component_Size @key(use) CHAR_BIT; @key(function) @AdaSubDefn{Is_Nul_Terminated} (Item : @key(in) char_array) @key(return) Boolean; @key(function) @AdaSubDefn{To_C} (Item : @key(in) String; Append_Nul : @key(in) Boolean := True) @key(return) char_array; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) char_array; Trim_Nul : @key(in) Boolean := True) @key(return) String; @key(procedure) @AdaSubDefn{To_C} (Item : @key(in) String; Target : @key(out) char_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) char_array; Target : @key(out) String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @RI{-- Wide Character and Wide String} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @key(type) @AdaTypeDefn{wchar_t} @key(is) @Chg{New=[@RI{<implementation-defined character type>}], Old=[@RI{implementation-defined}]}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0060],ARef=[AI95-00037-01]} @AdaObjDefn{wide_nul} : @key(constant) wchar_t := @Chg{New=[@RI{implementation-defined}],Old=[wchar_t'First]}; @key(function) @AdaSubDefn{To_C} (Item : @key(in) Wide_Character) @key(return) wchar_t; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_t ) @key(return) Wide_Character; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) @AdaTypeDefn{wchar_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @key(aliased) wchar_t@Chg{Version=[3],New=[ @key[with] Pack],Old=[]}; @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[ @key(pragma) Pack(wchar_array);]} @key(function) @AdaSubDefn{Is_Nul_Terminated} (Item : @key(in) wchar_array) @key(return) Boolean; @key(function) @AdaSubDefn{To_C} (Item : @key(in) Wide_String; Append_Nul : @key(in) Boolean := True) @key(return) wchar_array; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_array; Trim_Nul : @key(in) Boolean := True) @key(return) Wide_String; @key(procedure) @AdaSubDefn{To_C} (Item : @key(in) Wide_String; Target : @key(out) wchar_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) wchar_array; Target : @key(out) Wide_String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ -- @RI[ISO/IEC 10646:2003 compatible types defined by ISO/IEC TR 19769:2004.]]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char16_t} @key<is> @RI{<implementation-defined character type>};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{char16_nul} : @key<constant> char16_t := @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Character) @key<return> char16_t; @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char16_t) @key<return> Wide_Character;]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char16_array} @key<is array> (size_t @key<range> <>) @key<of aliased> char16_t@Chg{Version=[3],New=[ @key[with] Pack],Old=[]};]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key<pragma> Pack(char16_array);]}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Nul_Terminated} (Item : @key<in> char16_array) @key<return> Boolean; @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char16_array;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char16_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_String;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_C} (Item : @key<in> Wide_String; Target : @key<out> char16_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_Ada} (Item : @key<in> char16_array; Target : @key<out> Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char32_t} @key<is> @RI{<implementation-defined character type>};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{char32_nul} : @key<constant> char32_t := @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_Character) @key<return> char32_t; @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char32_t) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{char32_array} @key<is array> (size_t @key<range> <>) @key<of aliased> char32_t@Chg{Version=[3],New=[ @key[with] Pack],Old=[]};]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key<pragma> Pack(char32_array);]}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Nul_Terminated} (Item : @key<in> char32_array) @key<return> Boolean; @key<function> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char32_array;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ada} (Item : @key<in> char32_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_C} (Item : @key<in> Wide_Wide_String; Target : @key<out> char32_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True);]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{To_Ada} (Item : @key<in> char32_array; Target : @key<out> Wide_Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @AdaExcDefn{Terminator_Error} : @key(exception); @key(end) Interfaces.C; @end{Example} @ChgImplDef{Version=[2],Kind=[Added],InitialVersion=[1], Text=[@Chg{New=[The definitions of @Chg{Version=[2],New=[certain ],Old=[]}types and constants in Interfaces.C.],Old=[]}]} Each of the types declared in Interfaces.C is C-compatible. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The types int, short, long, unsigned, ptrdiff_t, size_t, double, char, @Chg{Version=[2],New=[],Old=[and ]}wchar_t@Chg{Version=[2],New=[, char16_t, and char32_t],Old=[]} correspond respectively to the C types having the same names. The types signed_char, unsigned_@!short, unsigned_@!long, unsigned_@!char, C_float, and long_@!double correspond respectively to the C types signed char, unsigned short, unsigned long, unsigned char, float, and long double. @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The C types wchar_t and char16_t seem to be the same. However, wchar_t has an implementation-defined size, whereas char16_t is guaranteed to be an unsigned type of at least 16 bits. Also, char16_t and char32_t are encouraged to have UTF-16 and UTF-32 representations; that means that they are not directly the same as the Ada types, which most likely don't use any UTF encoding.]} @end{Discussion} @Trailing@;The type of the subtype plain_char is either signed_char or unsigned_char, depending on the C implementation. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) Character) @key(return) char; @key(function) To_Ada (Item : @key(in) char ) @key(return) Character; @end{Example} @Trailing@;The functions To_C and To_Ada map between the Ada type Character and the C type char. @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0114],ARef=[AI95-00038-01]} @ChgAdded{Version=[1],Text=[The To_C and To_Ada functions map between corresponding characters, not necessarily between characters with the same internal representation. Corresponding characters are characters defined by the same enumeration literal, if such exist; otherwise, the correspondence is unspecified.@PDefn{Unspecified}]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Type=[Leading],Text=[The following definition is equivalent to the above summary:]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@f{To_C (Latin_1_Char) = char'Value(Character'Image(Latin_1_Char))}@* provided that char'Value does not raise an exception; otherwise the result is unspecified.]} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[@f{To_Ada (Native_C_Char) = Character'Value(char'Image(Native_C_Char))}@* provided that Character'Value does not raise an exception; otherwise the result is unspecified.]} @end{ImplNote} @begin{Example}@Keepnext @key(function) Is_Nul_Terminated (Item : @key(in) char_array) @key(return) Boolean; @end{Example} @Trailing@;The result of Is_Nul_Terminated is True if Item contains nul, and is False otherwise. @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) String; Append_Nul : @key(in) Boolean := True) @key(return) char_array; @Comment{Blank line} @key(function) To_Ada (Item : @key(in) char_array; Trim_Nul : @key(in) Boolean := True) @key(return) String; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00258-01]} The result of To_C is a char_array value of length Item'Length (if Append_Nul is False) or Item'Length+1 (if Append_Nul is True). The lower bound is 0. For each component Item(I), the corresponding component in the result is To_C applied to Item(I). The value nul is appended if Append_Nul is True.@Chg{Version=[2],New=[ If Append_Nul is False and Item'Length is 0, then To_C propagates Constraint_Error.],Old=[]} @Trailing@;The result of To_Ada is a String whose length is Item'Length (if Trim_Nul is False) or the length of the slice of Item preceding the first nul (if Trim_Nul is True). The lower bound of the result is 1. If Trim_Nul is False, then for each component Item(I) the corresponding component in the result is To_Ada applied to Item(I). If Trim_Nul is True, then for each component Item(I) before the first nul the corresponding component in the result is To_Ada applied to Item(I). The function propagates Terminator_Error if Trim_Nul is True and Item does not contain nul. @begin{Example}@Keepnext @key(procedure) To_C (Item : @key(in) String; Target : @key(out) char_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @Comment{Blank line} @key(procedure) To_Ada (Item : @key(in) char_array; Target : @key(out) String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @end{Example} For procedure To_C, each element of Item is converted (via the To_C function) to a char, which is assigned to the corresponding element of Target. If Append_Nul is True, nul is then assigned to the next element of Target. In either case, Count is set to the number of Target elements assigned. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Target is not long enough, Constraint_Error is propagated. @Trailing@;For procedure To_Ada, each element of Item (if Trim_Nul is False) or each element of Item preceding the first nul (if Trim_Nul is True) is converted (via the To_Ada function) to a Character, which is assigned to the corresponding element of Target. Count is set to the number of Target elements assigned. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Target is not long enough, Constraint_Error is propagated. If Trim_Nul is True and Item does not contain nul, then Terminator_Error is propagated. @begin{Example}@Keepnext @key(function) Is_Nul_Terminated (Item : @key(in) wchar_array) @key(return) Boolean; @end{Example} @Trailing@;The result of Is_Nul_Terminated is True if Item contains wide_nul, and is False otherwise. @begin{Example}@Keepnext @key(function) To_C (Item : @key(in) Wide_Character) @key(return) wchar_t; @key(function) To_Ada (Item : @key(in) wchar_t ) @key(return) Wide_Character; @end{Example} @Trailing@;To_C and To_Ada provide the mappings between the Ada and C wide character types. @begin{Example} @key(function) To_C (Item : @key(in) Wide_String; Append_Nul : @key(in) Boolean := True) @key(return) wchar_array; @Comment{Blank line} @key(function) To_Ada (Item : @key(in) wchar_array; Trim_Nul : @key(in) Boolean := True) @key(return) Wide_String; @Comment{Blank line} @key(procedure) To_C (Item : @key(in) Wide_String; Target : @key(out) wchar_array; Count : @key(out) size_t; Append_Nul : @key(in) Boolean := True); @Comment{Blank line} @key(procedure) To_Ada (Item : @key(in) wchar_array; Target : @key(out) Wide_String; Count : @key(out) Natural; Trim_Nul : @key(in) Boolean := True); @end{Example} The To_C and To_Ada subprograms that convert between Wide_String and wchar_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that wide_nul is used instead of nul. @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> Is_Nul_Terminated (Item : @key<in> char16_array) @key<return> Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> To_C (Item : @key<in> Wide_Character) @key<return> char16_t; @key<function> To_Ada (Item : @key<in> char16_t ) @key<return> Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[To_C and To_Ada provide mappings between the Ada and C 16-bit character types.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> To_C (Item : @key<in> Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char16_array; @Comment{Blank line} @key<function> To_Ada (Item : @key<in> char16_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_String; @Comment{Blank line} @key<procedure> To_C (Item : @key<in> Wide_String; Target : @key<out> char16_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True); @Comment{Blank line} @key<procedure> To_Ada (Item : @key<in> char16_array; Target : @key<out> Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The To_C and To_Ada subprograms that convert between Wide_String and char16_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char16_nul is used instead of nul.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> Is_Nul_Terminated (Item : @key<in> char32_array) @key<return> Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The result of Is_Nul_Terminated is True if Item contains char16_nul, and is False otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key<function> To_C (Item : @key<in> Wide_Wide_Character) @key<return> char32_t; @key<function> To_Ada (Item : @key<in> char32_t ) @key<return> Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[To_C and To_Ada provide mappings between the Ada and C 32-bit character types.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key<function> To_C (Item : @key<in> Wide_Wide_String; Append_Nul : @key<in> Boolean := True) @key<return> char32_array; @Comment{Blank line} @key<function> To_Ada (Item : @key<in> char32_array; Trim_Nul : @key<in> Boolean := True) @key<return> Wide_Wide_String; @Comment{Blank line} @key<procedure> To_C (Item : @key<in> Wide_Wide_String; Target : @key<out> char32_array; Count : @key<out> size_t; Append_Nul : @key<in> Boolean := True); @Comment{Blank line} @key<procedure> To_Ada (Item : @key<in> char32_array; Target : @key<out> Wide_Wide_String; Count : @key<out> Natural; Trim_Nul : @key<in> Boolean := True);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The To_C and To_Ada subprograms that convert between Wide_Wide_String and char32_array have analogous effects to the To_C and To_Ada subprograms that convert between String and char_array, except that char32_nul is used instead of nul.]} @begin{Discussion} The Interfaces.C package provides an implementation-defined character type, char, designed to model the C run-time character set, and mappings between the types char and Character. @Leading@;One application of the C interface package is to compose a C string and pass it to a C function. One way to do this is for the programmer to declare an object that will hold the C array, and then pass this array to the C function. This is realized via the type char_array: @begin{Example} @key(type) char_array @key(is) @key(array) (size_t @key(range) <>) of Char; @end{Example} The programmer can declare an Ada String, convert it to a char_array, and pass the char_array as actual parameter to the C function that is expecting a char *. An alternative approach is for the programmer to obtain a C char pointer from an Ada String (or from a char_array) by invoking an allocation function. The package Interfaces.C.Strings (see below) supplies the needed facilities, including a private type chars_ptr that corresponds to C's char *, and two allocation functions. To avoid storage leakage, a Free procedure releases the storage that was allocated by one of these allocate functions. It is typical for a C function that deals with strings to adopt the convention that the string is delimited by a nul char. The C interface packages support this convention. A constant nul of type Char is declared, and the function Value(Chars_Ptr) in Interfaces.C.Strings returns a char_array up to and including the first nul in the array that the chars_ptr points to. The Allocate_Chars function allocates an array that is nul terminated. Some C functions that deal with strings take an explicit length as a parameter, thus allowing strings to be passed that contain nul as a data element. Other C functions take an explicit length that is an upper bound: the prefix of the string up to the char before nul, or the prefix of the given length, is used by the function, whichever is shorter. The C Interface packages support calling such functions. @end{Discussion} @end{DescribeCode} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[1],Text=[@Chg{Version=[3],New=[The],Old=[A]} Convention @Chg{Version=[3],New=[aspect],Old=[pragma]} with @SynI{convention_}@nt{identifier} C_Pass_By_Copy shall only be @Chg{Version=[3],New=[specified for],Old=[applied to]} a type.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00216-01]} @ChgAdded{Version=[1],Text=[The eligibility rules in @RefSecNum(Interfacing Aspects) do not apply to convention C_Pass_By_Copy. Instead, a type T is eligible for convention C_Pass_By_Copy @Chg{Version=[2],New=[if T is an unchecked union type or ], Old=[]}if T is a record type that has no discriminants and that only has components with statically constrained subtypes, and each component is C-compatible.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[1],Text=[If a type is C_Pass_By_Copy-compatible@Chg{Version=[3],New=[,],Old=[]} then it is also C-compatible.]} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation shall support @Chg{Version=[3],New=[specifying aspect],Old=[pragma]} Convention with a C @SynI{convention_}@nt{identifier} for a C-eligible type (see @refsecnum(Interfacing Aspects))@Chg{New=[. An implementation shall support @Chg{Version=[3],New=[specifying aspect],Old=[pragma]} Convention with a C_Pass_By_Copy @SynI{convention_}@nt{identifier} for a C_Pass_By_Copy-eligible type.],Old=[]} @end{ImplReq} @begin{ImplPerm} An implementation may provide additional declarations in the C interface packages. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0002-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An implementation need not support specifying the Convention aspect with @SynI<convention_>@nt{identifier} C in the following cases:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[for a subprogram that has a parameter of an unconstrained array subtype, unless the Import aspect has the value True for the subprogram;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[for a function with an unconstrained array result subtype;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[for an object whose nominal subtype is an unconstrained array subtype.]} @end{Itemize} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0002-1]} @ChgAdded{Version=[3],Text=[These rules ensure that an implementation never needs to create bounds for an unconstrained array that originates in C (and thus does not have bounds). An implementation can do so if it wishes, of course. Note that these permissions do not extend to passing an unconstrained array as a parameter to a C function; in this case, the bounds can simply be dropped and thus support is required.]} @end{ImplNote} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0060],ARef=[AI95-00037-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@ChgNote{No change, just a new paragraph number} @ChgAdded{Version=[1],Text=[The constants nul@Chg{Version=[2],New=[,],Old=[ and]} wide_nul@Chg{Version=[2],New=[, char16_nul, and char32_nul],Old=[]} should have a representation of zero.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The constants nul, wide_nul, char16_nul, and char32_nul in package Interfaces.C should have a representation of zero.]}]} An implementation should support the following interface correspondences between Ada and C. @begin[itemize] An Ada procedure corresponds to a void-returning C function. @begin{discussion} The programmer can also choose an Ada procedure when the C function returns an int that is to be discarded.@end{discussion} An Ada function corresponds to a non-void C function. An Ada @key[in] scalar parameter is passed as a scalar argument to a C function. An Ada @key[in] parameter of an access-to-object type with designated type T is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. An Ada @key[access] T parameter, or an Ada @key[out] or @key[in out] parameter of an elementary type T, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. In the case of an elementary @key[out] or @key[in out] parameter, a pointer to a temporary copy is used to preserve by-copy semantics. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00343-01]} @ChgAdded{Version=[1],Text=[An Ada parameter of a @Chg{Version=[2], New=[(record) type T of convention ],Old=[]}C_Pass_By_Copy@Chg{Version=[2], New=[],Old=[-compatible (record) type T]}, of mode @key{in}, is passed as a t argument to a C function, where t is the C struct corresponding to the Ada type T.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00343-01]} An Ada parameter of a record type T, of any mode, @Chg{New=[other than an @key{in} parameter of a @Chg{Version=[2], New=[type of convention ],Old=[]}C_Pass_By_Copy@Chg{Version=[2], New=[],Old=[-compatible type]},],Old=[]} is passed as a t* argument to a C function, where t is the C struct corresponding to the Ada type T. An Ada parameter of an array type with component type T, of any mode, is passed as a t* argument to a C function, where t is the C type corresponding to the Ada type T. An Ada parameter of an access-to-subprogram type is passed as a pointer to a C function whose prototype corresponds to the designated subprogram's specification. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0002-1]} @ChgAdded{Version=[3],Text=[An Ada parameter of a private type is passed as specified for the full view of the type.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0002-1]} @ChgAdded{Version=[3],Text=[The rules of correspondence given above for parameters of mode @key[in] also apply to the return object of a function.]} @end[itemize] @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00337-01]} @ChgRef{Version=[3],Kind=[DeletedAdded],ARef=[AI05-0002-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[An Ada parameter of a private type is passed as specified for the full view of the type.],Old=[]}]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If C interfacing is supported, the interface correspondences between Ada and C should be supported.]}]} @end{ImplAdvice} @begin{Notes} Values of type char_array are not implicitly terminated with nul. If a char_array is to be passed as a parameter to an imported C function requiring nul termination, it is the programmer's responsibility to obtain this effect. To obtain the effect of C's sizeof(item_type), where Item_Type is the corresponding Ada type, evaluate the expression: size_t(Item_Type'Size/CHAR_BIT). @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00216-01]} @ChgDeleted{Version=[2],Text=[There is no explicit support for C's union types. Unchecked conversions can be used to obtain the effect of C unions.]} A C function that takes a variable number of arguments can correspond to several Ada subprograms, taking various specific numbers and types of parameters. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of using the Interfaces.C package:} @begin{Example} @RI{--Calling the C Library Function strcpy} @key(with) Interfaces.C; @key(procedure) Test @key(is) @key(package) C @key(renames) Interfaces.C; @key(use) @key(type) C.char_array; @RI{-- Call <string.h>strcpy:} @RI{-- C definition of strcpy: char *strcpy(char *s1, const char *s2);} @RI{-- This function copies the string pointed to by s2 (including the terminating null character)} @RI{-- into the array pointed to by s1. If copying takes place between objects that overlap, } @RI{-- the behavior is undefined. The strcpy function returns the value of s1.} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @RI{-- Note: since the C function's return value is of no interest, the Ada interface is a procedure} @key(procedure) Strcpy (Target : @key(out) C.char_array; Source : @key(in) C.char_array)@Chg{Version=[3],New=[ @key(with) Import => True, Convention => C, External_Name => "strcpy"],Old=[]}; @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[ @key(pragma) Import(C, Strcpy, "strcpy");]} Chars1 : C.char_array(1..20); Chars2 : C.char_array(1..20); @key(begin) Chars2(1..6) := "qwert" & C.nul; Strcpy(Chars1, Chars2); @RI{-- Now Chars1(1..6) = "qwert" & C.Nul} @key(end) Test; @end{Example} @end{Examples} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Types char16_t and char32_t and their related types and operations are @Chg{Version=[3],New=[],Old=[newly ]}added to Interfaces.C. If Interfaces.C is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Interfaces.C is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0059],ARef=[AI95-00131-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b<Corrigendum:> Convention C_Pass_By_Copy is new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0060],ARef=[AI95-00037-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the intent for Nul and Wide_Nul.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Specified that an unchecked union type (see @RefSecNum{Unchecked Union Types}) is eligible for convention C_Pass_By_Copy.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00258-01]} @ChgAdded{Version=[2],Text=[Specified what happens if the To_C function tries to return a null string.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00337-01]} @ChgAdded{Version=[2],Text=[Clarified that the interface correspondences also apply to private types whose full types have the specified characteristics.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00343-01]} @ChgAdded{Version=[2],Text=[Clarified that a type must have convention C_Pass_By_Copy in order to be passed by copy (not just a type that could have that convention).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00376-01]} @ChgAdded{Version=[2],Text=[Added wording to make it clear that these facilities can also be used with C++.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0002-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added a definition of correspondences for function results. Also added wording to make it clear that we do not expect the implementation to conjure bounds for unconstrained arrays out of thin air. These changes allow (but don't require) compilers to reject unreasonable uses of array types. Such uses probably didn't work anyway (and probably were rejected, no matter what the language definition said), so little existing code should be impacted.]} @end{Incompatible2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{The Package Interfaces.C.Strings} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The package Interfaces.C.Strings declares types and subprograms allowing an Ada program to allocate, reference, update, and free C-style strings. In particular, the private type chars_ptr corresponds to a common use of @lquotes@;char *@rquotes@; in C programs, and an object of this type can be passed to a subprogram to which @Chg{Version=[3],New=[@exam{@key[with] Import => True, Convention => C}],Old=[@nt(pragma) Import(C,...)]} has been @Chg{Version=[3],New=[specified],Old=[applied]}, and for which @lquotes@;char *@rquotes@; is the type of the argument of the C function. @end{Intro} @begin{StaticSem} @Leading@;The library package Interfaces.C.Strings has the following declaration: @begin{example} @key(package) Interfaces.C.Strings @key(is)@ChildUnit{Parent=[Interfaces.C],Child=[Strings]} @key[pragma] Preelaborate(Strings); @key(type) @AdaTypeDefn{char_array_access} @key(is) @key(access) @key(all) char_array; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key(type) @AdaTypeDefn{chars_ptr} @key(is) @key(private);@Chg{Version=[2],New=[ @key(pragma) Preelaborable_Initialization(chars_ptr);],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00276-01]} @key(type) @AdaTypeDefn{chars_ptr_array} @key(is) @key(array) (size_t @key(range) <>) @key(of) @Chg{Version=[2],New=[@key(aliased) ],Old=[]}chars_ptr; @AdaObjDefn{Null_Ptr} : @key(constant) chars_ptr; @key(function) @AdaSubDefn{To_Chars_Ptr} (Item : @key(in) char_array_access; Nul_Check : @key(in) Boolean := False) @key(return) chars_ptr; @key(function) @AdaSubDefn{New_Char_Array} (Chars : @key(in) char_array) @key(return) chars_ptr; @key(function) @AdaSubDefn{New_String} (Str : @key(in) String) @key(return) chars_ptr; @key(procedure) @AdaSubDefn{Free} (Item : @key(in) @key(out) chars_ptr); @AdaSubDefn{Dereference_Error} : @key(exception); @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr) @key(return) char_array; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) char_array; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr) @key(return) String; @key(function) @AdaSubDefn{Value} (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) String; @key(function) @AdaSubDefn{Strlen} (Item : @key(in) chars_ptr) @key(return) size_t; @key(procedure) @AdaSubDefn{Update} (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Chars : @key(in) char_array; Check : @key(in) Boolean := True); @key(procedure) @AdaSubDefn{Update} (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Str : @key(in) String; Check : @key(in) Boolean := True); @AdaSubDefn{Update_Error} : @key(exception); @key(private) ... -- @RI{not specified by the language} @key(end) Interfaces.C.Strings; @end{Example} @begin{discussion} The string manipulation types and subprograms appear in a child of Interfaces.C versus being there directly, since it is useful to have Interfaces.C specified as @nt(pragma) Pure. Differently named functions New_String and New_Char_Array are declared, since if there were a single overloaded function a call with a string literal as actual parameter would be ambiguous. @end{discussion} The type chars_ptr is C-compatible and corresponds to the use of C's @lquotes@;char *@rquotes@; for a pointer to the first char in a char array terminated by nul. When an object of type chars_ptr is declared, its value is by default set to Null_Ptr, unless the object is imported (see @RefSecNum(Interfacing Aspects)). @begin{discussion} The type char_array_access is not necessarily C-compatible, since an object of this type may carry @lquotes@;dope@rquotes@; information. The programmer should convert from char_array_access to chars_ptr for objects imported from, exported to, or passed to C.@end{discussion} @begin{DescribeCode} @begin{Example}@Keepnext @key(function) To_Chars_Ptr (Item : @key(in) char_array_access; Nul_Check : @key(in) Boolean := False) @key(return) chars_ptr; @end{Example} @Trailing@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0061],ARef=[AI95-00140-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If Item is @key(null), then To_Chars_Ptr returns Null_Ptr. @Chg{New=[If Item is not @key(null),], Old=[Otherwise, if]} Nul_Check is True@Chg{New=[,],Old=[]} and Item.@key(all) does not contain nul, then the function propagates Terminator_Error; @Chg{New=[otherwise@Chg{Version=[3],New=[,],Old=[]}], Old=[if Nul_Check is True and Item.@key(all) does contain nul,]} To_Chars_Ptr performs a pointer conversion with no allocation of memory. @begin{Example}@Keepnext @key(function) New_Char_Array (Chars : @key(in) char_array) @key(return) chars_ptr; @end{Example} This function returns a pointer to an allocated object initialized to Chars(Chars'First .. Index) & nul, where @begin{itemize} Index = Chars'Last if Chars does not contain nul, or Index is the smallest size_t value I such that Chars(I+1) = nul. @end{itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@Trailing @Chg{New=[],Old=[@Noparanum@;]}Storage_Error is propagated if the allocation fails. @begin{Example}@Keepnext @key(function) New_String (Str : @key(in) String) @key(return) chars_ptr; @end{Example} @Trailing@;This function is equivalent to New_Char_Array(To_C(Str)). @begin{Example}@Keepnext @key(procedure) Free (Item : @key(in) @key(out) chars_ptr); @end{Example} @Trailing@;If Item is Null_Ptr, then Free has no effect. Otherwise, Free releases the storage occupied by Value(Item), and resets Item to Null_Ptr. @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr) @key(return) char_array; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If Item = Null_Ptr@Chg{Version=[3],New=[,],Old=[]} then Value propagates Dereference_Error. Otherwise@Chg{Version=[3],New=[,],Old=[]} Value returns the prefix of the array of chars pointed to by Item, up to and including the first nul. The lower bound of the result is 0. If Item does not point to a nul-terminated string, then execution of Value is erroneous. @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) char_array; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0062],ARef=[AI95-00139-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Trailing@;If Item = Null_Ptr@Chg{Version=[3],New=[,],Old=[]} then Value@Chg{New=[],Old=[(Item)]} propagates Dereference_Error. Otherwise@Chg{Version=[3],New=[,],Old=[]} Value returns the shorter of two arrays@Chg{New=[, either],Old=[:]} the first Length chars pointed to by Item, @Chg{New=[or],Old=[and]} Value(Item). The lower bound of the result is 0. @Chg{New=[If Length is 0, then Value propagates Constraint_Error.],Old=[]} @begin{Ramification} Value(New_Char_Array(Chars)) = Chars if Chars does not contain nul; else Value(New_Char_Array( Chars)) is the prefix of Chars up to and including the first nul. @end{Ramification} @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr) @key(return) String; @end{Example} @Trailing@;Equivalent to To_Ada(Value(Item), Trim_Nul=>True). @begin{Example}@Keepnext @key(function) Value (Item : @key(in) chars_ptr; Length : @key(in) size_t) @key(return) String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0063],ARef=[AI95-00177-01]} @Trailing@;Equivalent to To_Ada(Value(Item, Length)@Chg{New=[ & nul],Old=[]}, Trim_Nul=>True). @begin{Example}@Keepnext @key(function) Strlen (Item : @key(in) chars_ptr) @key(return) size_t; @end{Example} @Trailing@;Returns @i[Val]'Length@en@;1 where @i[Val] = Value(Item); propagates Dereference_Error if Item = Null_Ptr. @begin{ramification} Strlen returns the number of chars in the array pointed to by Item, up to and including the char immediately before the first nul. Strlen has the same possibility for erroneous execution as Value, in cases where the string has not been nul-terminated. Strlen has the effect of C's strlen function. @end{Ramification} @begin{Example}@Keepnext @key(procedure) Update (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Chars : @key(in) char_array; Check : Boolean := True); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0064],ARef=[AI95-00039-01]} @Leading@;@Chg{New=[If Item = Null_Ptr, then Update propagates Dereference_Error. Otherwise, t],Old=[T]}his procedure updates the value pointed to by Item, starting at position Offset, using Chars as the data to be copied into the array. Overwriting the nul terminator, and skipping with the Offset past the nul terminator, are both prevented if Check is True, as follows: @begin[itemize] Let N = Strlen(Item). If Check is True, then: @begin{inneritemize} If Offset+Chars'Length>N, propagate Update_Error. Otherwise, overwrite the data in the array pointed to by Item, starting at the char at position Offset, with the data in Chars. @end{inneritemize} @Trailing@;If Check is False, then processing is as above, but with no check that Offset+Chars'Length>N. @begin{Ramification} If Chars contains nul, Update's effect may be to @lquotes@;shorten@rquotes@; the pointed-to char array.@end{ramification} @end[itemize] @begin{Example}@Keepnext @key(procedure) Update (Item : @key(in) chars_ptr; Offset : @key(in) size_t; Str : @key(in) String; Check : @key(in) Boolean := True); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00242-01]} Equivalent to Update(Item, Offset, To_C(Str@Chg{Version=[2], New=[, Append_Nul => False],Old=[]}), Check). @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00242-01]} @ChgAdded{Version=[2],Text=[To truncate the Item to the length of Str, use Update(Item, Offset, To_C(Str), Check) instead of Update(Item, Offset, Str, Check). Note that when truncating Item, Item must be longer than Str.]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of any of the following is erroneous if the Item parameter is not null_ptr and Item does not point to a nul-terminated array of chars. @begin[itemize] a Value function not taking a Length parameter, the Free procedure, the Strlen function. @end[itemize] @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Free(X) is also erroneous if the chars_ptr X was not returned by New_Char_Array or New_String. @PDefn2{Term=(erroneous execution),Sec=(cause)} Reading or updating a freed char_array is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Update is erroneous if Check is False and a call with Check equal to True would have propagated Update_Error. @end{erron} @begin{Notes} New_Char_Array and New_String might be implemented either through the allocation function from the C environment (@lquotes@;malloc@rquotes@;) or through Ada dynamic memory allocation (@lquotes@;new@rquotes@;). The key points are @begin{itemize} the returned value (a chars_ptr) is represented as a C @lquotes@;char *@rquotes@; so that it may be passed to C functions; the allocated object should be freed by the programmer via a call of Free, not by a called C function. @end{itemize} @end{Notes} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00242-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] Update for a String parameter is now defined to not add a nul character. It did add a nul in Ada 95. This means that programs that used this behavior of Update to truncate a string will no longer work (the string will not be truncated). This change makes Update for a string consistent with Update for a char_array (no implicit nul is added to the end of a char_array).]} @end{Inconsistent95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to type chars_ptr, so that it can be used in preelaborated units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00276-01]} @ChgAdded{Version=[2],Text=[@b[Amendment Correction:] The components of chars_ptr_array are aliased so that it can be used to instantiate Interfaces.C.Pointers (that is its intended purpose, which is otherwise mysterious as it has no operations).]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0061],ARef=[AI95-00140-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of To_Char_Ptr when Nul_Check is False.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0062],ARef=[AI95-00139-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of Value when the Length is 0.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0063],ARef=[AI95-00177-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of Value to avoid raising Terminator_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0064],ARef=[AI95-00039-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Fixed the missing semantics of Update when Item is Null_Ptr.]} @end{DiffWord95} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{The Generic Package Interfaces.C.Pointers} @begin{Intro} The generic package Interfaces.C.Pointers allows the Ada programmer to perform C-style operations on pointers. It includes an access type Pointer, Value functions that dereference a Pointer and deliver the designated array, several pointer arithmetic operations, and @lquotes@;copy@rquotes@; procedures that copy the contents of a source pointer into the array designated by a destination pointer. As in C, it treats an object Ptr of type Pointer as a pointer to the first element of an array, so that for example, adding 1 to Ptr yields a pointer to the second element of the array. The generic allows two styles of usage: one in which the array is terminated by a special terminator element; and another in which the programmer needs to keep track of the length. @end{Intro} @begin{StaticSem} @Leading@;The generic library package Interfaces.C.Pointers has the following declaration: @begin{Example} @key(generic) @key(type) Index @key(is) (<>); @key(type) Element @key(is) @key(private); @key(type) Element_Array @key(is) @key(array) (Index @key(range) <>) @key(of) @key(aliased) Element; Default_Terminator : Element; @key(package) Interfaces.C.Pointers @key(is)@ChildUnit{Parent=[Interfaces.C],Child=[Pointers]} @key[pragma] Preelaborate(Pointers); @key(type) @AdaTypeDefn{Pointer} @key(is) @key(access) @key(all) Element; @key(function) @AdaSubDefn{Value}(Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) Element_Array; @key(function) @AdaSubDefn{Value}(Ref : @key(in) Pointer; Length : @key(in) ptrdiff_t) @key(return) Element_Array; @AdaExcDefn{Pointer_Error} : @key(exception); @RI{-- C-style Pointer arithmetic} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(function) "+" (Left : @key(in) Pointer; Right : @key(in) ptrdiff_t) @key(return) Pointer@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "+" (Left : @key(in) ptrdiff_t; Right : @key(in) Pointer) @key(return) Pointer@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "-" (Left : @key(in) Pointer; Right : @key(in) ptrdiff_t) @key(return) Pointer@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(function) "-" (Left : @key(in) Pointer; Right : @key(in) Pointer) @key(return) ptrdiff_t@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(procedure) @AdaSubDefn{Increment} (Ref : @key(in) @key(out) Pointer)@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @key(procedure) @AdaSubDefn{Decrement} (Ref : @key(in) @key(out) Pointer)@Chg{Version=[3],New=[ @key(with) Convention => Intrinsic],Old=[]}; @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[ @key(pragma) Convention (Intrinsic, "+"); @key(pragma) Convention (Intrinsic, "-"); @key(pragma) Convention (Intrinsic, Increment); @key(pragma) Convention (Intrinsic, Decrement);]} @key(function) @AdaSubDefn{Virtual_Length} (Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) ptrdiff_t; @key(procedure) @AdaSubDefn{Copy_Terminated_Array} (Source : @key(in) Pointer; Target : @key(in) Pointer; Limit : @key(in) ptrdiff_t := ptrdiff_t'Last; Terminator : @key(in) Element := Default_Terminator); @key(procedure) @AdaSubDefn{Copy_Array} (Source : @key(in) Pointer; Target : @key(in) Pointer; Length : @key(in) ptrdiff_t); @key(end) Interfaces.C.Pointers; @end{Example} @Leading@;The type Pointer is C-compatible and corresponds to one use of C's @lquotes@;Element *@rquotes@;. An object of type Pointer is interpreted as a pointer to the initial Element in an Element_Array. Two styles are supported: @begin{Itemize} Explicit termination of an array value with Default_Terminator (a special terminator value); @Trailing@;Programmer-managed length, with Default_Terminator treated simply as a data element. @end{Itemize} @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Value(Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) Element_Array; @end{Example} @Trailing@;This function returns an Element_Array whose value is the array pointed to by Ref, up to and including the first Terminator; the lower bound of the array is Index'First. Interfaces.C.Strings.Dereference_Error is propagated if Ref is @key(null). @begin{Example}@Keepnext @key(function) Value(Ref : @key(in) Pointer; Length : @key(in) ptrdiff_t) @key(return) Element_Array; @end{Example} @Trailing@;This function returns an Element_Array comprising the first Length elements pointed to by Ref. The exception Interfaces.C.Strings.Dereference_Error is propagated if Ref is @key(null). @end{DescribeCode} @Trailing@;The "+" and "@en@;" functions perform arithmetic on Pointer values, based on the Size of the array elements. In each of these functions, Pointer_Error is propagated if a Pointer parameter is @key(null). @begin{DescribeCode} @begin{Example}@Keepnext @key(procedure) Increment (Ref : @key(in) @key(out) Pointer); @end{Example} @Trailing@;Equivalent to Ref := Ref+1. @begin{Example}@Keepnext @key(procedure) Decrement (Ref : @key(in) @key(out) Pointer); @end{Example} @Trailing@;Equivalent to Ref := Ref@en@;1. @begin{Example}@Keepnext @key(function) Virtual_Length (Ref : @key(in) Pointer; Terminator : @key(in) Element := Default_Terminator) @key(return) ptrdiff_t; @end{Example} @Trailing@;Returns the number of Elements, up to the one just before the first Terminator, in Value(Ref, Terminator). @begin{Example}@Keepnext @key(procedure) Copy_Terminated_Array (Source : @key(in) Pointer; Target : @key(in) Pointer; Limit : @key(in) ptrdiff_t := ptrdiff_t'Last; Terminator : @key(in) Element := Default_Terminator); @end{Example} @Trailing@;This procedure copies Value(Source, Terminator) into the array pointed to by Target; it stops either after Terminator has been copied, or the number of elements copied is Limit, whichever occurs first. Dereference_Error is propagated if either Source or Target is @key(null). @begin{ramification} It is the programmer's responsibility to ensure that elements are not copied beyond the logical length of the target array. @end{ramification} @begin{ImplNote} The implementation has to take care to check the Limit first. @end{ImplNote} @begin{Example}@Keepnext @key(procedure) Copy_Array (Source : @key(in) Pointer; Target : @key(in) Pointer; Length : @key(in) ptrdiff_t); @end{Example} This procedure copies the first Length elements from the array pointed to by Source, into the array pointed to by Target. Dereference_Error is propagated if either Source or Target is @key(null). @end{DescribeCode} @end{StaticSem} @begin{erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to dereference a Pointer that does not designate an aliased Element. @begin{Discussion} Such a Pointer could arise via "+", "@en@;", Increment, or Decrement.@end{discussion} @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Value(Ref, Terminator) is erroneous if Ref does not designate an aliased Element in an Element_Array terminated by Terminator. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Value(Ref, Length) is erroneous if Ref does not designate an aliased Element in an Element_Array containing at least Length Elements between the designated Element and the end of the array, inclusive. @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Virtual_Length(Ref, Terminator) is erroneous if Ref does not designate an aliased Element in an Element_Array terminated by Terminator. @Leading@PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Copy_Terminated_Array(Source, Target, Limit, Terminator) is erroneous in either of the following situations: @begin[itemize] Execution of both Value(Source, Terminator) and Value(Source, Limit) are erroneous, or Copying writes past the end of the array containing the Element designated by Target. @end[Itemize] @PDefn2{Term=(erroneous execution),Sec=(cause)} Execution of Copy_Array(Source, Target, Length) is erroneous if either Value(Source, Length) is erroneous, or copying writes past the end of the array containing the Element designated by Target. @end{erron} @begin{Notes} @Leading@;To compose a Pointer from an Element_Array, use 'Access on the first element. For example (assuming appropriate instantiations): @begin{example} Some_Array : Element_Array(0..5) ; Some_Pointer : Pointer := Some_Array(0)'Access; @end{example} @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of Interfaces.C.Pointers:} @begin{Example} @key(with) Interfaces.C.Pointers; @key(with) Interfaces.C.Strings; @key(procedure) Test_Pointers @key(is) @key(package) C @key(renames) Interfaces.C; @key(package) Char_Ptrs @key(is) @key(new) C.Pointers (Index => C.size_t, Element => C.char, Element_Array => C.char_array, Default_Terminator => C.nul); @key(use) @key(type) Char_Ptrs.Pointer; @key(subtype) Char_Star @key(is) Char_Ptrs.Pointer; @key(procedure) Strcpy (Target_Ptr, Source_Ptr : Char_Star) @key(is) Target_Temp_Ptr : Char_Star := Target_Ptr; Source_Temp_Ptr : Char_Star := Source_Ptr; Element : C.char; @key(begin) @key(if) Target_Temp_Ptr = @key(null) @key(or) Source_Temp_Ptr = @key(null) @key(then) @key(raise) C.Strings.Dereference_Error; @key(end if); @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0065],ARef=[AI95-00142-01]} @key(loop) Element := Source_Temp_Ptr.@key(all); Target_Temp_Ptr.@key(all) := Element; @key(exit) @key(when) @Chg{New=[C."="(Element, C.nul)],Old=[Element = C.nul]}; Char_Ptrs.Increment(Target_Temp_Ptr); Char_Ptrs.Increment(Source_Temp_Ptr); @key(end) @key(loop); @key(end) Strcpy; @key(begin) ... @key(end) Test_Pointers; @end{Example} @end{Examples} @LabeledRevisedSubClause{Version=[3],InitialVersion=[2],New=[Unchecked Union Types],Old=[Pragma Unchecked_Union]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[union],Sec=[C]} @Redundant[@Chg{Version=[3],New=[Specifying aspect],Old=[A pragma]} Unchecked_Union @Chg{Version=[3],New=[to have the value True defines],Old=[specifies]} an interface correspondence between a given discriminated type and some C union. The @Chg{Version=[3],New=[aspect requires],Old=[pragma specifies]} that the associated type shall be given a representation that @Chg{Version=[3],New=[allocates],Old=[leaves]} no space for its discriminant(s).]]} @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 3 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[ @Chg{Version=[2],New=[The form of a pragma Unchecked_Union is as follows:],Old=[]}]} @Comment{We'd like a conditional insert of Leading, etc., but we don't have that.} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[2],@ChgDeleted{Version=[3], Text=[@Chg{Version=[2],New=[@key{pragma} @prag{Unchecked_Union} (@Syni<first_subtype_>@Syn2<local_name>);],Old=[]}]}> @end{Syntax} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a discriminated record type having a @nt{variant_part}, the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Unchecked_Union@\The type of aspect Unchecked_Union is Boolean. If directly specified, the @nt{aspect_definition} shall be a static expression. If not specified (including by inheritance), the aspect is False.@AspectDefn{Unchecked_Union}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Unchecked_Union], Text=[@ChgAdded{Version=[3],Text=[Type is used to interface to a C union type.]}]} @end{Description} @end{StaticSem} @begin{Legality} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 4 and 5 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[Unchecked_Union is a representation pragma, specifying the unchecked union aspect of representation.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[The @SynI{first_subtype_}@nt{local_name} of a @nt{pragma} Unchecked_Union shall denote an unconstrained discriminated record subtype having a @nt{variant_part}.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Defn{unchecked union type} @Defn{unchecked union subtype} @Defn{unchecked union object} A type @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[aspect],Old=[a pragma]} Unchecked_Union @Chg{Version=[3],New=[is True],Old=[applies]} is called an @i<unchecked union type>. A subtype of an unchecked union type is defined to be an @i<unchecked union subtype>. An object of an unchecked union type is defined to be an @i<unchecked union object>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[All component subtypes of an unchecked union type shall be C-compatible.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[If a component subtype of an unchecked union type is subject to a per-object constraint, then the component subtype shall be an unchecked union subtype.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0026-1]} @ChgAdded{Version=[2],Text=[Any name that denotes a discriminant of an object of an unchecked union type shall occur within the declarative region of the type@Chg{Version=[3],New=[, and shall not occur within a @nt{record_representation_clause}],Old=[]}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0026-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[The type of a],Old=[A]} component declared in a @nt{variant_part} of an unchecked union type shall not @Chg{Version=[3],New=[need finalization. In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule also applies in the private part of an instance of a generic unit.@PDefn{generic contract issue} For an unchecked union type declared within the body of a generic unit, or within the body of any of its descendant library units, no part of the type of a component declared in a @nt{variant_part} of the unchecked union type shall be of a formal private type or formal private extension declared within the formal part of the generic unit],Old=[have a controlled, protected, or task part]}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0026-1]} @ChgAdded{Version=[3],Text=[The last part is a classic assume-the-worst rule that avoids dependence on the actuals in a generic body. We did not include this in the definition of @ldquote@;needs finalization@rdquote as it has a bad interaction with the use of that term for the No_Nested_Finalization restriction.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[The completion of an incomplete or private type declaration having a @nt{known_discriminant_part} shall not be an unchecked union type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An unchecked union subtype shall only be passed as a generic actual parameter if the corresponding formal type has no known discriminants or is an unchecked union type.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This includes formal private types without a @nt{known_discriminant_part}, formal derived types that do not inherit any discriminants (formal derived types do not have @nt{known_discriminant_part}s), and formal derived types that are unchecked union types.]} @end{Ramification} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An unchecked union type is eligible for convention C.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[All objects of an unchecked union type have the same size.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[Discriminants of objects of an unchecked union type are of size zero.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[Any check which would require reading a discriminant of an unchecked union object is suppressed (see @RefSecNum{Suppressing Checks}). These checks include:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check performed when addressing a variant component (i.e., a component that was declared in a variant part) of an unchecked union object that the object has this component (see @RefSecNum{Selected Components}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Any checks associated with a type or subtype conversion of a value of an unchecked union type (see @RefSecNum{Type Conversions}). This includes, for example, the check associated with the implicit subtype conversion of an assignment statement.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The subtype membership check associated with the evaluation of a qualified expression (see @RefSecNum{Qualified Expressions}) or an uninitialized allocator (see @RefSecNum{Allocators}).]} @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a suppressed check would have failed, execution is erroneous (see @RefSecNum{Suppressing Checks}). An implementation is always allowed to make a suppressed check if it can somehow determine the discriminant value.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[A view of an unchecked union object (including a type conversion or function call) has @i<inferable discriminants> if it has a constrained nominal subtype, unless the object is a component of an enclosing unchecked union object that is subject to a per-object constraint and the enclosing object lacks inferable discriminants.@Defn{inferable discriminants}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[An expression of an unchecked union type has inferable discriminants if it is either a name of an object with inferable discriminants or a qualified expression whose @nt{subtype_mark} denotes a constrained subtype.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[Program_Error is raised in the following cases:@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of the predefined equality operator for an unchecked union type if either of the operands lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of the predefined equality operator for a type which has a subcomponent of an unchecked union type whose nominal subtype is unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Evaluation of a membership test if the @nt{subtype_mark} denotes a constrained unchecked union subtype and the expression lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Conversion from a derived unchecked union type to an unconstrained non-unchecked-union type if the operand of the conversion lacks inferable discriminants.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Write or Read attribute of an unchecked union type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Output or Input attribute of an unchecked union type if the type lacks default discriminant values.]} @end{Itemize} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[An implementation may require that @nt{pragma} Controlled be specified for the type of an access subcomponent of an unchecked union type.]}]} @end{ImplPerm} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 29 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T], Text=[The use of an unchecked union to obtain the effect of an unchecked conversion results in erroneous execution (see @RefSecNum{Suppressing Checks}). Execution of the following example is erroneous even if Float'Size = Integer'Size:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@key<type> T (Flag : Boolean := False) @key<is> @key<record> @key<case> Flag @key<is> @key<when> False => F1 : Float := 0.0; @key<when> True => F2 : Integer := 0; @key<end case>; @key<end record>@Chg{Version=[3],New=[ @key[with] Unchecked_Union],Old=[; @key<pragma> Unchecked_Union (T)]};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[X : T; Y : Integer := X.F2; -- @RI[erroneous]]} @end{Example} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00216-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Unchecked_Union is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0026-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> The use of discriminants on Unchecked_Union types is now illegal in @nt{record_representation_clause}s, as it makes no sense to specify a position for something that is not supposed to exist. It is very unlikely that this change will have any impact on existing code.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect Unchecked_Union is new; @nt{pragma} Unchecked_Union is now obsolescent.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0026-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the rules to use the @ldquote@;needs finalization@rdquote definition, and eliminated generic contract issues.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledClause{Interfacing with COBOL} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{interface to COBOL} @Defn{COBOL interface} The facilities relevant to interfacing with the COBOL language are the package Interfaces.COBOL and support for @Chg{Version=[3],New=[specifying ],Old=[]}the @Chg{Version=[3],New=[],Old=[Import, Export and ]}Convention @Chg{Version=[3],New=[aspect],Old=[pragmas]} with @SynI{convention_}@nt{identifier} COBOL. @Leading@;The COBOL interface package supplies several sets of facilities: @begin{itemize} A set of types corresponding to the native COBOL types of the supported COBOL implementation (so-called @lquotes@;internal COBOL representations@rquotes@;), allowing Ada data to be passed as parameters to COBOL programs A set of types and constants reflecting external data representations such as might be found in files or databases, allowing COBOL-generated data to be read by an Ada program, and Ada-generated data to be read by COBOL programs A generic package for converting between an Ada decimal type value and either an internal or external COBOL representation @end{itemize} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.COBOL has the following declaration: @begin{Example} @key(package) Interfaces.COBOL @key(is)@ChildUnit{Parent=[Interfaces],Child=[COBOL]} @key[pragma] Preelaborate(COBOL); @RI{-- Types and operations for internal data representations} @key(type) @AdaTypeDefn{Floating} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Long_Floating} @key(is) @key(digits) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Binary} @key(is) @key(range) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Long_Binary} @key(is) @key(range) @RI{implementation-defined}; @AdaObjDefn{Max_Digits_Binary} : @key(constant) := @RI{implementation-defined}; @AdaObjDefn{Max_Digits_Long_Binary} : @key(constant) := @RI{implementation-defined}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) @AdaTypeDefn{Decimal_Element} @key(is) @key(mod) @RI{implementation-defined}; @key(type) @AdaTypeDefn{Packed_Decimal} @key(is) @key(array) (Positive @key(range) <>) @key(of) Decimal_Element@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key(pragma) Pack(Packed_Decimal)]}; @key(type) @AdaTypeDefn{COBOL_Character} @key(is) @RI{implementation-defined character type}; @AdaObjDefn{Ada_To_COBOL} : @key(array) (Character) @key(of) COBOL_Character := @RI{implementation-defined}; @AdaObjDefn{COBOL_To_Ada} : @key(array) (COBOL_Character) @key(of) Character := @RI{implementation-defined}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) @AdaTypeDefn{Alphanumeric} @key(is) @key(array) (Positive range <>) @key(of) COBOL_Character@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key(pragma) Pack(Alphanumeric)]}; @key(function) @AdaSubDefn{To_COBOL} (Item : @key(in) String) @key(return) Alphanumeric; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) Alphanumeric) @key(return) String; @key(procedure) @AdaSubDefn{To_COBOL} (Item : @key(in) String; Target : @key(out) Alphanumeric; Last : @key(out) Natural); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) Alphanumeric; Target : @key(out) String; Last : @key(out) Natural); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) @AdaTypeDefn{Numeric} @key(is) @key(array) (Positive @key[range] <>) @key(of) COBOL_Character@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key(pragma) Pack(Numeric)]}; @RI{-- Formats for COBOL data representations} @key(type) @AdaTypeDefn{Display_Format} @key(is) @key(private); @AdaObjDefn{Unsigned} : @key(constant) Display_Format; @AdaObjDefn{Leading_Separate} : @key(constant) Display_Format; @AdaObjDefn{Trailing_Separate} : @key(constant) Display_Format; @AdaObjDefn{Leading_Nonseparate} : @key(constant) Display_Format; @AdaObjDefn{Trailing_Nonseparate} : @key(constant) Display_Format; @key(type) @AdaTypeDefn{Binary_Format} @key(is) @key(private); @AdaObjDefn{High_Order_First} : @key(constant) Binary_Format; @AdaObjDefn{Low_Order_First} : @key(constant) Binary_Format; @AdaObjDefn{Native_Binary} : @key(constant) Binary_Format; @key(type) @AdaTypeDefn{Packed_Format} @key(is) @key(private); @AdaObjDefn{Packed_Unsigned} : @key(constant) Packed_Format; @AdaObjDefn{Packed_Signed} : @key(constant) Packed_Format; @RI{-- Types for external representation of COBOL binary data} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) @AdaTypeDefn{Byte} @key(is) @key(mod) 2**COBOL_Character'Size; @key(type) @AdaTypeDefn{Byte_Array} @key(is) @key(array) (Positive @key(range) <>) @key(of) Byte@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key(pragma) Pack (Byte_Array)]}; @AdaExcDefn{Conversion_Error} : @key(exception); @key(generic) @key(type) Num @key(is) @key(delta) <> @key(digits) <>; @key(package) @AdaPackDefn{Decimal_Conversions} @key(is) @RI{-- Display Formats: data values are represented as Numeric} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Display_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Display} (Item : @key(in) Num; Format : @key(in) Display_Format) @key(return) Numeric; @RI{-- Packed Formats: data values are represented as Packed_Decimal} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Packed_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Packed} (Item : @key(in) Num; Format : @key(in) Packed_Format) @key(return) Packed_Decimal; @RI{-- Binary Formats: external data values are represented as Byte_Array} @key(function) @AdaSubDefn{Valid} (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Boolean; @key(function) @AdaSubDefn{Length} (Format : @key(in) Binary_Format) @key(return) Natural; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Num; @key(function) @AdaSubDefn{To_Binary} (Item : @key(in) Num; Format : @key(in) Binary_Format) @key(return) Byte_Array; @RI{-- Internal Binary formats: data values are of type Binary or Long_Binary} @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Binary) @key(return) Num; @key(function) @AdaSubDefn{To_Decimal} (Item : @key(in) Long_Binary) @key(return) Num; @key(function) @AdaSubDefn{To_Binary} (Item : @key(in) Num) @key(return) Binary; @key(function) @AdaSubDefn{To_Long_Binary} (Item : @key(in) Num) @key(return) Long_Binary; @key(end) Decimal_Conversions; @key(private) ... -- @RI{not specified by the language} @key(end) Interfaces.COBOL; @end{Example} @ChgImplDef{Version=[1],Kind=[Revised],InitialVersion=[0], Text=[The types Floating, Long_Floating, Binary, Long_Binary, Decimal_Element, and COBOL_Character; and the initializations of the variables Ada_To_COBOL and COBOL_To_Ada, in Interfaces.COBOL@Chg{New=[.],Old=[]}]} Each of the types in Interfaces.COBOL is COBOL-compatible. The types Floating and Long_Floating correspond to the native types in COBOL for data items with computational usage implemented by floating point. The types Binary and Long_Binary correspond to the native types in COBOL for data items with binary usage, or with computational usage implemented by binary. Max_Digits_Binary is the largest number of decimal digits in a numeric value that is represented as Binary. Max_Digits_Long_Binary is the largest number of decimal digits in a numeric value that is represented as Long_Binary. The type Packed_Decimal corresponds to COBOL's packed-decimal usage. The type COBOL_Character defines the run-time character set used in the COBOL implementation. Ada_To_COBOL and COBOL_To_Ada are the mappings between the Ada and COBOL run-time character sets. @begin{reason} The character mappings are visible variables, since the user needs the ability to modify them at run time. @end{reason} Type Alphanumeric corresponds to COBOL's alphanumeric data category. Each of the functions To_COBOL and To_Ada converts its parameter based on the mappings Ada_To_COBOL and COBOL_To_Ada, respectively. The length of the result for each is the length of the parameter, and the lower bound of the result is 1. Each component of the result is obtained by applying the relevant mapping to the corresponding component of the parameter. Each of the procedures To_COBOL and To_Ada copies converted elements from Item to Target, using the appropriate mapping (Ada_To_COBOL or COBOL_To_Ada, respectively). The index in Target of the last element assigned is returned in Last (0 if Item is a null array). @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Item'Length exceeds Target'Length, Constraint_Error is propagated. Type Numeric corresponds to COBOL's numeric data category with display usage. @Trailing@;The types Display_Format, Binary_Format, and Packed_Format are used in conversions between Ada decimal type values and COBOL internal or external data representations. The value of the constant Native_Binary is either High_Order_First or Low_Order_First, depending on the implementation. @begin{DescribeCode} @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Boolean; @end{Example} @Leading@;The function Valid checks that the Item parameter has a value consistent with the value of Format. If the value of Format is other than Unsigned, Leading_Separate, and Trailing_Separate, the effect is implementation defined. If Format does have one of these values, the following rules apply: @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Format=Unsigned: if Item comprises @Chg{New=[],Old=[zero or more leading space characters followed by ]}one or more decimal digit characters@Chg{Version=[3],New=[,],Old=[]} then Valid returns True, else it returns False. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} Format=Leading_Separate: if Item comprises @Chg{New=[],Old=[zero or more leading space characters, followed by ]}a single occurrence of the plus or minus sign character, and then one or more decimal digit characters, then Valid returns True, else it returns False. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0066],ARef=[AI95-00071-01]} @Trailing@;Format=Trailing_Separate: if Item comprises @Chg{New=[],Old=[zero or more leading space characters, followed by ]}one or more decimal digit characters and finally a plus or minus sign character, then Valid returns True, else it returns False. @end{itemize} @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Display_Format) @key(return) Natural; @end{Example} @Trailing@;The Length function returns the minimal length of a Numeric value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Numeric; Format : @key(in) Display_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. The number of digits after the assumed radix point in Item is Num'Scale. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{discussion} There is no issue of truncation versus rounding, since the number of decimal places is established by Num'Scale.@end{discussion} @begin{Example}@Keepnext @key(function) To_Display (Item : @key(in) Num; Format : @key(in) Display_Format) @key(return) Numeric; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Numeric value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1. ],Old=[]}Conversion_Error is propagated if Num is negative and Format is Unsigned. @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Boolean; @end{Example} @Trailing@;This function returns True if Item has a value consistent with Format, and False otherwise. The rules for the formation of Packed_Decimal values are implementation defined. @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Packed_Format) @key(return) Natural; @end{Example} @Trailing@;This function returns the minimal length of a Packed_Decimal value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Packed_Decimal; Format : @key(in) Packed_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. Num'Scale is the number of digits after the assumed radix point in Item. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{Example}@Keepnext @key(function) To_Packed (Item : @key(in) Num; Format : @key(in) Packed_Format) @key(return) Packed_Decimal; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Packed_Decimal value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1. ],Old=[]}Conversion_Error is propagated if Num is negative and Format is Packed_Unsigned. @begin{Example}@Keepnext @key(function) Valid (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Boolean; @end{Example} @Trailing@;This function returns True if Item has a value consistent with Format, and False otherwise. @begin{ramification} This function returns False only when the represented value is outside the range of Num.@end{ramification} @begin{Example}@Keepnext @key(function) Length (Format : @key(in) Binary_Format) @key(return) Natural; @end{Example} @Trailing@;This function returns the minimal length of a Byte_Array value sufficient to hold any value of type Num when represented as Format. @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Byte_Array; Format : @key(in) Binary_Format) @key(return) Num; @end{Example} @Trailing@;Produces a value of type Num corresponding to Item as represented by Format. Num'Scale is the number of digits after the assumed radix point in Item. Conversion_Error is propagated if the value represented by Item is outside the range of Num. @begin{Example}@Keepnext @key(function) To_Binary (Item : @key(in) Num; Format : @key(in) Binary_Format) @key(return) Byte_Array; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0067],ARef=[AI95-00072-01]} @Trailing@;This function returns the Byte_Array value for Item, represented in accordance with Format. @Chg{New=[The length of the returned value is Length(Format), and the lower bound is 1.],Old=[]} @begin{Example}@Keepnext @key(function) To_Decimal (Item : @key(in) Binary) @key(return) Num; @comment{Blank line} @key(function) To_Decimal (Item : @key(in) Long_Binary) @key(return) Num; @end{Example} @Trailing@;These functions convert from COBOL binary format to a corresponding value of the decimal type Num. Conversion_Error is propagated if Item is too large for Num. @begin{Ramification} There is no rescaling performed on the conversion. That is, the returned value in each case is a @lquotes@;bit copy@rquotes@; if Num has a binary radix. The programmer is responsible for maintaining the correct scale. @end{ramification} @begin{Example}@Keepnext @key(function) To_Binary (Item : @key(in) Num) @key(return) Binary; @comment{Blank line} @key(function) To_Long_Binary (Item : @key(in) Num) @key(return) Long_Binary; @end{Example} These functions convert from Ada decimal to COBOL binary format. Conversion_Error is propagated if the value of Item is too large to be represented in the result type. @begin{discussion} One style of interface supported for COBOL, similar to what is provided for C, is the ability to call and pass parameters to an existing COBOL program. Thus the interface package supplies types that can be used in an Ada program as parameters to subprograms whose bodies will be in COBOL. These types map to COBOL's alphanumeric and numeric data categories. Several types are provided for support of alphanumeric data. Since COBOL's run-time character set is not necessarily the same as Ada's, Interfaces.COBOL declares an implementation-defined character type COBOL_Character, and mappings between Character and COBOL_Character. These mappings are visible variables (rather than, say, functions or constant arrays), since in the situation where COBOL_Character is EBCDIC, the flexibility of dynamically modifying the mappings is needed. Corresponding to COBOL's alphanumeric data is the string type Alphanumeric. Numeric data may have either a @lquotes@;display@rquotes@; or @lquotes@;computational@rquotes@; representation in COBOL. On the Ada side, the data is of a decimal fixed point type. Passing an Ada decimal data item to a COBOL program requires conversion from the Ada decimal type to some type that reflects the representation expected on the COBOL side. @begin{Itemize} Computational Representation @NoPrefix@;Floating point representation is modeled by Ada floating point types, Floating and Long_Floating. Conversion between these types and Ada decimal types is obtained directly, since the type name serves as a conversion function. @NoPrefix@;Binary representation is modeled by an Ada integer type, Binary, and possibly other types such as Long_Binary. Conversion between, say, Binary and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. @NoPrefix@;Packed decimal representation is modeled by the Ada array type Packed_Decimal. Conversion between packed decimal and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. Display Representation @NoPrefix@;Display representation for numeric data is modeled by the array type Numeric. Conversion between display representation and a decimal type is through functions from an instantiation of the generic package Decimal_Conversions. A parameter to the conversion function indicates the desired interpretation of the data (e.g., signed leading separate, etc.) @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The],Old=[Pragma]} Convention@Chg{Version=[3],New=[ of],Old=[(COBOL, T) may be applied to]} a record type @Chg{Version=[3],New=[may be specified as COBOL],Old=[T]} to direct the compiler to choose a COBOL-compatible representation for objects of the type. The package Interfaces.COBOL allows the Ada programmer to deal with data from files (or databases) created by a COBOL program. For data that is alphanumeric, or in display or packed decimal format, the approach is the same as for passing parameters (instantiate Decimal_Conversions to obtain the needed conversion functions). For binary data, the external representation is treated as a Byte array, and an instantiation of Decimal_IO produces a package that declares the needed conversion functions. A parameter to the conversion function indicates the desired interpretation of the data (e.g., high- versus low-order byte first). @end{discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation shall support @Chg{Version=[3],New=[specifying aspect],Old=[pragma]} Convention with a COBOL @i[convention]_@nt[identifier] for a COBOL-eligible type (see @RefSecNum(Interfacing Aspects)). @begin{ramification} An implementation supporting this package shall ensure that if the bounds of a Packed_Decimal, Alphanumeric, or Numeric variable are static, then the representation of the object comprises solely the array components (that is, there is no implicit run-time @lquotes@;descriptor@rquotes@; that is part of the object). @end{ramification} @end{ImplReq} @begin{ImplPerm} An implementation may provide additional constants of the private types Display_Format, Binary_Format, or Packed_Format. @begin{Reason} This is to allow exploitation of other external formats that may be available in the COBOL implementation.@end{reason} An implementation may provide further floating point and integer types in Interfaces.COBOL to match additional native COBOL types, and may also supply corresponding conversion functions in the generic package Decimal_Conversions. @end{ImplPerm} @begin{ImplAdvice} An Ada implementation should support the following interface correspondences between Ada and COBOL. @begin[itemize] An Ada @key[access] T parameter is passed as a @lquotes@;BY REFERENCE@rquotes@; data item of the COBOL type corresponding to T. An Ada @key[in] scalar parameter is passed as a @lquotes@;BY CONTENT@rquotes@; data item of the corresponding COBOL type. Any other Ada parameter is passed as a @lquotes@;BY REFERENCE@rquotes@; data item of the COBOL type corresponding to the Ada parameter type; for scalars, a local copy is used if necessary to ensure by-copy semantics. @end[itemize] @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If COBOL interfacing is supported, the interface correspondences between Ada and COBOL should be supported.]}]} @end{ImplAdvice} @begin[Notes] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation is not required to support @Chg{Version=[3],New=[specifying aspect],Old=[pragma]} Convention for access types, nor is it required to support @Chg{Version=[3],New=[specifying aspects],Old=[pragma]} Import, Export@Chg{Version=[3],New=[,],Old=[]} or Convention for functions. @begin{reason} COBOL does not have a pointer facility, and a COBOL program does not return a value.@end{reason} If an Ada subprogram is exported to COBOL, then a call from COBOL call may specify either @lquotes@;BY CONTENT@rquotes@; or @lquotes@;BY REFERENCE@rquotes@;. @end[Notes] @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @begin{Examples} @Leading@Keepnext@i{Examples of Interfaces.COBOL:} @begin{Example} @key(with) Interfaces.COBOL; @key(procedure) Test_Call @key(is) @RI{-- Calling a foreign COBOL program} @RI{-- Assume that a COBOL program PROG has the following declaration} @RI{-- in its LINKAGE section:} @RI{-- 01 Parameter-Area} @RI{-- 05 NAME PIC X(20).} @RI{-- 05 SSN PIC X(9).} @RI{-- 05 SALARY PIC 99999V99 USAGE COMP.} @RI{-- The effect of PROG is to update SALARY based on some algorithm} @key(package) COBOL @key(renames) Interfaces.COBOL; @key(type) Salary_Type @key(is) @key(delta) 0.01 @key(digits) 7; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) COBOL_Record @key(is) @key(record) Name : COBOL.Numeric(1..20); SSN : COBOL.Numeric(1..9); Salary : COBOL.Binary; @RI{-- Assume Binary = 32 bits} @key(end) @key(record)@Chg{Version=[3],New=[ @key[with] Convention => COBOL],Old=[; @key(pragma) Convention (COBOL, COBOL_Record)]}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(procedure) Prog (Item : @key(in) @key(out) COBOL_Record)@Chg{Version=[3],New=[ @key[with] Import => True, Convention => COBOL],Old=[; @key(pragma) Import (COBOL, Prog, "PROG")]}; @key(package) Salary_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Salary_Type); Some_Salary : Salary_Type := 12_345.67; Some_Record : COBOL_Record := (Name => "Johnson, John ", SSN => "111223333", Salary => Salary_Conversions.To_Binary(Some_Salary)); @key(begin) Prog (Some_Record); ... @key(end) Test_Call; @end{Example} @begin{Example} @key(with) Interfaces.COBOL; @key(with) COBOL_Sequential_IO; @RI{-- Assumed to be supplied by implementation} @key(procedure) Test_External_Formats @key(is) @RI{-- Using data created by a COBOL program} @RI{-- Assume that a COBOL program has created a sequential file with} @RI{-- the following record structure, and that we need to} @RI{-- process the records in an Ada program} @RI{-- 01 EMPLOYEE-RECORD} @RI{-- 05 NAME PIC X(20).} @RI{-- 05 SSN PIC X(9).} @RI{-- 05 SALARY PIC 99999V99 USAGE COMP.} @RI{-- 05 ADJUST PIC S999V999 SIGN LEADING SEPARATE.} @RI{-- The COMP data is binary (32 bits), high-order byte first} @key(package) COBOL @key(renames) Interfaces.COBOL; @key(type) Salary_Type @key(is) @key(delta) 0.01 @key(digits) 7; @key(type) Adjustments_Type @key(is) @key(delta) 0.001 @key(digits) 6; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key(type) COBOL_Employee_Record_Type @key(is) @RI{-- External representation} @key(record) Name : COBOL.Alphanumeric(1..20); SSN : COBOL.Alphanumeric(1..9); Salary : COBOL.Byte_Array(1..4); Adjust : COBOL.Numeric(1..7); @RI{-- Sign and 6 digits} @key(end) @key(record)@Chg{Version=[3],New=[ @key[with] Convention => COBOL],Old=[; @key(pragma) Convention (COBOL, COBOL_Employee_Record_Type)]}; @key(package) COBOL_Employee_IO @key(is) @key(new) COBOL_Sequential_IO(COBOL_Employee_Record_Type); @key(use) COBOL_Employee_IO; COBOL_File : File_Type; @key(type) Ada_Employee_Record_Type @key(is) @RI{-- Internal representation} @key(record) Name : String(1..20); SSN : String(1..9); Salary : Salary_Type; Adjust : Adjustments_Type; @key(end) @key(record); COBOL_Record : COBOL_Employee_Record_Type; Ada_Record : Ada_Employee_Record_Type; @key(package) Salary_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Salary_Type); @key(use) Salary_Conversions; @key(package) Adjustments_Conversions @key(is) @key(new) COBOL.Decimal_Conversions(Adjustments_Type); @key(use) Adjustments_Conversions; @key(begin) Open (COBOL_File, Name => "Some_File"); @key(loop) Read (COBOL_File, COBOL_Record); Ada_Record.Name := To_Ada(COBOL_Record.Name); Ada_Record.SSN := To_Ada(COBOL_Record.SSN); Ada_Record.Salary := To_Decimal(COBOL_Record.Salary, COBOL.High_Order_First); Ada_Record.Adjust := To_Decimal(COBOL_Record.Adjust, COBOL.Leading_Separate); ... @RI{-- Process Ada_Record} @key(end) @key(loop); @key(exception) @key[when] End_Error => ... @key(end) Test_External_Formats; @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0066],ARef=[AI95-00071-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of Valid to match COBOL.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0067],ARef=[AI95-00072-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Specified the bounds of the results of To_Display, To_Packed, and To_Binary.]} @end{DiffWord95} @LabeledClause{Interfacing with Fortran} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{interface to Fortran} @Defn{Fortran interface} The facilities relevant to interfacing with the Fortran language are the package Interfaces.Fortran and support for @Chg{Version=[3],New=[specifying ],Old=[]}the @Chg{Version=[3],New=[],Old=[Import, Export and ]}Convention @Chg{Version=[3],New=[aspect],Old=[pragmas]} with @SynI{convention_}@nt{identifier} Fortran. The package Interfaces.Fortran defines Ada types whose representations are identical to the default representations of the Fortran intrinsic types Integer, Real, Double Precision, Complex, Logical, and Character in a supported Fortran implementation. These Ada types can therefore be used to pass objects between Ada and Fortran programs. @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Interfaces.Fortran has the following declaration: @begin{Example} @key[with] Ada.Numerics.Generic_Complex_Types; @RI{-- see @RefSecNum{Complex Types}} @key[pragma] Elaborate_All(Ada.Numerics.Generic_Complex_Types); @key[package] Interfaces.Fortran @key[is]@ChildUnit{Parent=[Interfaces],Child=[Fortran]} @key[pragma] Pure(Fortran); @key[type] @AdaTypeDefn{Fortran_Integer} @key[is] @key[range] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Real} @key[is] @key[digits] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Double_Precision} @key[is] @key[digits] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Logical} @key[is] @key[new] Boolean; @key[package] @AdaPackDefn{Single_Precision_Complex_Types} @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (Real); @key[type] @AdaTypeDefn{Complex} @key[is] @key[new] Single_Precision_Complex_Types.Complex; @key[subtype] @AdaSubtypeDefn{Name=[Imaginary],Of=[Imaginary]} @key[is] Single_Precision_Complex_Types.Imaginary; @AdaObjDefn{i} : Imaginary @key[renames] Single_Precision_Complex_Types.i; @AdaObjDefn{j} : Imaginary @key[renames] Single_Precision_Complex_Types.j; @key[type] @AdaTypeDefn{Character_Set} @key[is] @RI{implementation-defined character type}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[type] @AdaTypeDefn{Fortran_Character} @key[is] @key[array] (Positive @key[range] <>) @key[of] Character_Set@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack (Fortran_Character)]}; @key[function] @AdaSubDefn{To_Fortran} (Item : @key[in] Character) @key[return] Character_Set; @key[function] @AdaSubDefn{To_Ada} (Item : @key[in] Character_Set) @key[return] Character; @key(function) @AdaSubDefn{To_Fortran} (Item : @key(in) String) @key(return) Fortran_Character; @key(function) @AdaSubDefn{To_Ada} (Item : @key(in) Fortran_Character) @key(return) String; @key(procedure) @AdaSubDefn{To_Fortran} (Item : @key(in) String; Target : @key(out) Fortran_Character; Last : @key(out) Natural); @key(procedure) @AdaSubDefn{To_Ada} (Item : @key(in) Fortran_Character; Target : @key(out) String; Last : @key(out) Natural); @key[end] Interfaces.Fortran; @end{Example} @ChgImplDef{Version=[1],Kind=[Added],Text=[@Chg{New=[The types Fortran_Integer, Real, Double_Precision, and Character_Set in Interfaces.Fortran.],Old=[]}]} @begin{Ramification} The means by which the Complex type is provided in Interfaces.Fortran creates a dependence of Interfaces.Fortran on Numerics.Generic_Complex_Types (see @RefSecNum{Complex Types}). This dependence is intentional and unavoidable, if the Fortran-compatible Complex type is to be useful in Ada code without duplicating facilities defined elsewhere. @end{Ramification} The types Fortran_Integer, Real, Double_Precision, Logical, Complex, and Fortran_Character are Fortran-compatible. The To_Fortran and To_Ada functions map between the Ada type Character and the Fortran type Character_Set, and also between the Ada type String and the Fortran type Fortran_Character. The To_Fortran and To_Ada procedures have analogous effects to the string conversion subprograms found in Interfaces.COBOL. @end{StaticSem} @begin[ImplReq] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} An implementation shall support @Chg{Version=[3],New=[specifying aspect],Old=[@nt[pragma]]} Convention with a Fortran @i[convention]_@nt[identifier] for a Fortran-eligible type (see @RefSecNum(Interfacing Aspects)). @end[ImplReq] @begin{ImplPerm} An implementation may add additional declarations to the Fortran interface packages. For example, the Fortran interface package for an implementation of Fortran 77 (ANSI X3.9-1978) that defines types like Integer*@i{n}, Real*@i{n}, Logical*@i{n}, and Complex*@i{n} may contain the declarations of types named Integer_@!Star_@i{n}, Real_@!Star_@i{n}, Logical_@!Star_@i{n}, and Complex_@!Star_@i{n}. (This convention should not apply to Character*@i{n}, for which the Ada analog is the constrained array subtype Fortran_Character (1..@i{n}).) Similarly, the Fortran interface package for an implementation of Fortran 90 that provides multiple @i{kinds} of intrinsic types, e.g. Integer (Kind=@i{n}), Real (Kind=@i{n}), Logical (Kind=@i{n}), Complex (Kind=@i{n}), and Character (Kind=@i{n}), may contain the declarations of types with the recommended names Integer_Kind_@i{n}, Real_Kind_@i{n}, Logical_Kind_@i{n}, Complex_Kind_@i{n}, and Character_Kind_@i{n}. @begin[discussion] Implementations may add auxiliary declarations as needed to assist in the declarations of additional Fortran-compatible types. For example, if a double precision complex type is defined, then Numerics.@!Generic_@!Complex_@!Types may be instantiated for the double precision type. Similarly, if a wide character type is defined to match a Fortran 90 wide character type (accessible in Fortran 90 with the Kind modifier), then an auxiliary character set may be declared to serve as its component type. @end[discussion] @end{ImplPerm} @begin{ImplAdvice} @Leading@;An Ada implementation should support the following interface correspondences between Ada and Fortran: @begin[itemize] An Ada procedure corresponds to a Fortran subroutine. An Ada function corresponds to a Fortran function. An Ada parameter of an elementary, array, or record type T is passed as a T@-(F) argument to a Fortran procedure, where T@-(F) is the Fortran type corresponding to the Ada type T, and where the INTENT attribute of the corresponding dummy argument matches the Ada formal parameter mode; the Fortran implementation's parameter passing conventions are used. For elementary types, a local copy is used if necessary to ensure by-copy semantics. An Ada parameter of an access-to-subprogram type is passed as a reference to a Fortran procedure whose interface corresponds to the designated subprogram's specification. @end[itemize] @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If Fortran interfacing is supported, the interface correspondences between Ada and Fortran should be supported.]}]} @end{ImplAdvice} @begin[Notes] An object of a Fortran-compatible record type, declared in a library package or subprogram, can correspond to a Fortran common block; the type also corresponds to a Fortran @lquotes@;derived type@rquotes@;. @end[Notes] @begin{Examples} @Leading@Keepnext@i{Example of Interfaces.Fortran:} @begin{Example} @key[with] Interfaces.Fortran; @key[use] Interfaces.Fortran; @key[procedure] Ada_Application @key[is] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[type] Fortran_Matrix @key[is] @key[array] (Integer @key[range] <>, Integer @key[range] <>) @key[of] Double_Precision@Chg{Version=[3],New=[ @key[with] Convention => Fortran; ],Old=[; @key[pragma] Convention (Fortran, Fortran_Matrix);]} @RI{-- stored in Fortran's} @RI{-- column-major order} @key[procedure] Invert (Rank : @key[in] Fortran_Integer; X : @key[in] @key[out] Fortran_Matrix)@Chg{Version=[3],New=[ @key[with] Import => True, Convention => Fortran;],Old=[; @key[pragma] Import (Fortran, Invert); ]} @RI{-- a Fortran subroutine} Rank : @key[constant] Fortran_Integer := 100; My_Matrix : Fortran_Matrix (1 .. Rank, 1 .. Rank); @key[begin] ... My_Matrix := ...; ... Invert (Rank, My_Matrix); ... @key[end] Ada_Application; @end{Example} @end{Examples}����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/iso-rm.msm�����������������������������������������������������������0000755�0001752�0001001�00000015056�12273462240�017352� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the RM (ISO version)} @Comment{Global properties} @HideIndexEntries @HideAnnotations @ShowISO @Comment{Paragraphs are not numbered here} @Title{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @Title{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @Title{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]} @Title{Version=[3],Text=[ISO/IEC 8652:2012(E)]} @Comment{@Title{Version=[3],Text=[ISO/IEC 8652:DIS]}} @FilePrefix{8652} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @SubdivisionNames{Clause}@Comment{For Ada 95 and 2005, use "section" instead} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[]}@Comment{No prefix for all versions} @RTFFooterText{Version=[0],Text=[\'a9 ISO/IEC 1995 \endash All rights reserved]} @RTFFooterText{Version=[1],Text=[\'a9 ISO/IEC 2001 \endash All rights reserved]} @RTFFooterText{Version=[2],Text=[\'a9 ISO/IEC 2007 \endash All rights reserved]} @RTFFooterText{Version=[3],Text=[\'a9 ISO/IEC 2012 \endash All rights reserved]} @RTFFooter{UseDate=[F],UseClauseName=[F],UseISOFormat=[T]} @RTFPageSize{A4} @RTFFonts{Serif=[Times],SansSerif=[Helvetica]}@Comment{ISO requires the latter} @RTFVersionName{Version=[0],Text=[Original Text]} @RTFVersionName{Version=[1],Text=[Technical Corrigendum 1]} @RTFVersionName{Version=[2],Text=[Amendment 1]} @RTFVersionName{Version=[3],Text=[Ada 2012]} @Comment{HTML properties - generally, no HTML version is made of the ISO version, so these settings aren't important} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]} @HTMLNavBar{RefName=[8652-STDS.html],SrchName=[8652-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><SPAN Style="font-size:200%; color: rgb(0,0,153)"><B>Ada Reference Manual</B></SPAN> — <A HREF="8652-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="vertical-align: middle">Ada 2005 and 2012 Editions sponsored in part by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Con2.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Locales.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO requires skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO requires skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/langdef.mss����������������������������������������������������������0000755�0001752�0001001�00000005645�12066652506�017563� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(glossary, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledAddedInformativeAnnex{Version=[2],Name=[Language-Defined Entities]} @comment{$Source: e:\\cvsroot/ARM/Source/langdef.mss,v $} @comment{$Revision: 1.8 $} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgAdded{Version=[2],Text=[This annex lists the language-defined entities of the language. A list of language-defined library units can be found in @RefSec{Predefined Language Environment}.]} @end{Intro} @LabeledAddedClause{Version=[2],Name=[Language-Defined Packages]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} lists all language-defined packages.@Defn{Language-defined packages}]} @end{Intro} @PackageList @LabeledAddedClause{Version=[2],Name=[Language-Defined Types and Subtypes]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} lists all language-defined types and subtypes.@Defn{Language-defined types}@Defn{Language-defined subtypes}]} @end{Intro} @TypeList @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedClause{Version=[2],Name=[Language-Defined Subprograms]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} lists all language-defined subprograms.@Defn{Language-defined subprograms}]} @end{Intro} @SubprogramList @LabeledAddedClause{Version=[2],Name=[Language-Defined Exceptions]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} lists all language-defined exceptions.@Defn{Language-defined exceptions}]} @end{Intro} @ExceptionList @LabeledAddedClause{Version=[2],Name=[Language-Defined Objects]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00440-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} lists all language-defined constants, variables, named numbers, and enumeration literals.@Defn{Language-defined objects}@Defn{Language-defined constants}@Defn{Language-defined values}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Formally, named numbers and enumeration literals aren't objects, but it was thought to be too weird to say @lquotes@;Language-Defined Objects and Values@rquotes.]} @end{Honest} @end{Intro} @ObjectList �������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/library.mss����������������������������������������������������������0000755�0001752�0001001�00000000377�11776511201�017615� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(library, Root="ada.mss") @Comment{$Date: 2000/05/27 04:44:03 $} @comment{$Source: e:\\cvsroot/ARM/Source/library.mss,v $} @comment{$Revision: 1.2 $} @comment{$RLB: This is the library separator page. $} @UnnumberedSection{The Standard Libraries} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/numerics.mss���������������������������������������������������������0000755�0001752�0001001�00000647556�12066652506�020025� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/numerics.mss,v $ } @comment{ $Revision: 1.71 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(numerics, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledNormativeAnnex{Numerics} @begin{Intro} @Defn{numerics} The Numerics Annex specifies @begin{itemize} features for complex arithmetic, including complex I/O; a mode (@lquotes@;strict mode@rquotes@;), in which the predefined arithmetic operations of floating point and fixed point types and the functions and operations of various predefined packages have to provide guaranteed accuracy or conform to other numeric performance requirements, which the Numerics Annex also specifies; a mode (@lquotes@;relaxed mode@rquotes@;), in which no accuracy or other numeric performance requirements need be satisfied, as for implementations not conforming to the Numerics Annex; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00296-01]} models of floating point and fixed point arithmetic on which the accuracy requirements of strict mode are based;@Chg{Version=[2],New=[],Old=[ and]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00296-01]} the definitions of the model-oriented attributes of floating point types that apply in the strict mode@Chg{Version=[2],New=[; and],Old=[.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00296-01]}@ChgAdded{Version=[2], Text=[features for the manipulation of real and complex vectors and matrices.]} @end{itemize} @end{Intro} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If Fortran (respectively, C) is widely supported in the target environment, implementations supporting the Numerics Annex should provide the child package Interfaces.Fortran (respectively, Interfaces.C) specified in @RefSecNum{Interface to Other Languages} and should support a @i{convention_}@nt{identifier} of Fortran (respectively, C) @Chg{Version=[3],New=[for],Old=[in]} the @Chg{Version=[3],New=[Convention aspect],Old=[interfacing pragmas]} (see @RefSecNum{Interface to Other Languages}), thus allowing Ada programs to interface with programs written in that language. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[If Fortran (respectively, C) is supported in the target environment, then interfacing to Fortran (respectively, C) should be supported as specified in @RefSecNum{Interface to Other Languages}.]}]} @end{ImplAdvice} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Complex Arithmetic} @begin{Intro} Types and arithmetic operations for complex arithmetic are provided in Generic_Complex_Types, which is defined in @RefSecNum{Complex Types}. Implementation-defined approximations to the complex analogs of the mathematical functions known as the @lquotes@;elementary functions@rquotes@; are provided by the subprograms in Generic_@!Complex_@!Elementary_@!Functions, which is defined in @RefSecNum{Complex Elementary Functions}. Both of these library units are generic children of the predefined package Numerics (see @RefSecNum{The Numerics Packages}). Nongeneric equivalents of these generic packages for each of the predefined floating point types are also provided as children of Numerics. @ImplDef{The accuracy actually achieved by the complex elementary functions and by other complex arithmetic operations.} @begin{Discussion} Complex arithmetic is defined in the Numerics Annex, rather than in the core, because it is considered to be a specialized need of (some) numeric applications. @end{Discussion} @end{Intro} @LabeledSubClause{Complex Types} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Complex_Types has the following declaration: @begin{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @key{generic}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Types]} @key{type} Real @key{is} @key{digits} <>; @key{package} Ada.Numerics.Generic_Complex_Types @key{is} @Chg{New=[@key{pragma}],Old=[pragma]} Pure(Generic_Complex_Types); @key{type} @AdaTypeDefn{Complex} @key{is} @key{record} Re, Im : Real'Base; @key{end} @key{record}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key{type} @AdaTypeDefn{Imaginary} @key{is} @key{private};@Chg{Version=[2],New=[ @key{pragma} Preelaborable_Initialization(Imaginary);],Old=[]} @AdaObjDefn{i} : @key{constant} Imaginary; @AdaObjDefn{j} : @key{constant} Imaginary; @key{function} @AdaSubDefn{Re} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Im} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Im} (X : Imaginary) @key{return} Real'Base; @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in} @key{out} Complex; Re : @key{in} Real'Base); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in} @key{out} Complex; Im : @key{in} Real'Base); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{out} Imaginary; Im : @key{in} Real'Base); @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Im : Imaginary) @key{return} Complex; @key{function} @AdaSubDefn{Modulus} (X : Complex) @key{return} Real'Base; @key{function} "@key{abs}" (Right : Complex) @key{return} Real'Base @key{renames} Modulus; @key{function} @AdaSubDefn{Argument} (X : Complex) @key{return} Real'Base; @key{function} @AdaSubDefn{Argument} (X : Complex; Cycle : Real'Base) @key{return} Real'Base; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real'Base) @key{return} Complex; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument, Cycle : Real'Base) @key{return} Complex; @key{function} "+" (Right : Complex) @key{return} Complex; @key{function} "-" (Right : Complex) @key{return} Complex; @key{function} @AdaSubDefn{Conjugate} (X : Complex) @key{return} Complex; @key{function} "+" (Left, Right : Complex) @key{return} Complex; @key{function} "-" (Left, Right : Complex) @key{return} Complex; @key{function} "*" (Left, Right : Complex) @key{return} Complex; @key{function} "/" (Left, Right : Complex) @key{return} Complex; @key{function} "**" (Left : Complex; Right : Integer) @key{return} Complex; @key{function} "+" (Right : Imaginary) @key{return} Imaginary; @key{function} "-" (Right : Imaginary) @key{return} Imaginary; @key{function} @AdaSubDefn{Conjugate} (X : Imaginary) @key{return} Imaginary @key{renames} "-"; @key{function} "@key{abs}" (Right : Imaginary) @key{return} Real'Base; @key{function} "+" (Left, Right : Imaginary) @key{return} Imaginary; @key{function} "-" (Left, Right : Imaginary) @key{return} Imaginary; @key{function} "*" (Left, Right : Imaginary) @key{return} Real'Base; @key{function} "/" (Left, Right : Imaginary) @key{return} Real'Base; @key{function} "**" (Left : Imaginary; Right : Integer) @key{return} Complex; @key{function} "<" (Left, Right : Imaginary) @key{return} Boolean; @key{function} "<=" (Left, Right : Imaginary) @key{return} Boolean; @key{function} ">" (Left, Right : Imaginary) @key{return} Boolean; @key{function} ">=" (Left, Right : Imaginary) @key{return} Boolean; @key{function} "+" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "+" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "-" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "-" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "*" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "*" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "/" (Left : Complex; Right : Real'Base) @key{return} Complex; @key{function} "/" (Left : Real'Base; Right : Complex) @key{return} Complex; @key{function} "+" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "+" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "-" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "-" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "*" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "*" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "/" (Left : Complex; Right : Imaginary) @key{return} Complex; @key{function} "/" (Left : Imaginary; Right : Complex) @key{return} Complex; @key{function} "+" (Left : Imaginary; Right : Real'Base) @key{return} Complex; @key{function} "+" (Left : Real'Base; Right : Imaginary) @key{return} Complex; @key{function} "-" (Left : Imaginary; Right : Real'Base) @key{return} Complex; @key{function} "-" (Left : Real'Base; Right : Imaginary) @key{return} Complex; @key{function} "*" (Left : Imaginary; Right : Real'Base) @key{return} Imaginary; @key{function} "*" (Left : Real'Base; Right : Imaginary) @key{return} Imaginary; @key{function} "/" (Left : Imaginary; Right : Real'Base) @key{return} Imaginary; @key{function} "/" (Left : Real'Base; Right : Imaginary) @key{return} Imaginary; @key[private] @key{type} Imaginary @key{is} @key{new} Real'Base; i : @key{constant} Imaginary := 1.0; j : @key{constant} Imaginary := 1.0; @key{end} Ada.Numerics.Generic_Complex_Types; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Types]} The library package Numerics.Complex_Types @Chg{New=[is declared pure and ],Old=[]}defines the same types, constants, and subprograms as Numerics.Generic_Complex_Types, except that the predefined type Float is systematically substituted for Real'Base throughout. Nongeneric equivalents of Numerics.Generic_Complex_Types for each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Complex_@!Types, Numerics.@!Long_@!Complex_@!Types, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} @begin{Reason} The nongeneric equivalents all export the types Complex and Imaginary and the constants i and j (rather than uniquely named types and constants, such as Short_Complex, Long_Complex, etc.) to preserve their equivalence to actual instantiations of the generic package and to allow the programmer to change the precision of an application globally by changing a single context clause. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Redundant{Complex is a visible type with @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} components.} @begin{Reason} The @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} representation is far more common than the polar representation, in practice. The accuracy of the results of the complex arithmetic operations and of the complex elementary functions is dependent on the representation; thus, implementers need to know that representation. The type is visible so that complex @lquotes@;literals@rquotes@; can be written in aggregate notation, if desired. @end{Reason} @Redundant{Imaginary is a private type; its full type is derived from Real'Base.} @begin{Reason} @Leading@;The Imaginary type and the constants i and j are provided for two reasons: @begin{itemize} They allow complex @lquotes@;literals@rquotes@; to be written in the alternate form of @RI{a} + @RI{b}*i (or @RI{a} + @RI{b}*j), if desired. Of course, in some contexts the sum will need to be parenthesized. When an Ada binding to IEC 559:1989 that provides (signed) infinities as the result of operations that overflow becomes available, it will be important to allow arithmetic between pure-imaginary and complex operands without requiring the former to be represented as (or promoted to) complex values with a real component of zero. For example, the multiplication of @RI{a} + @RI{b}*i by @RI{d}*i should yield @en@RI{b}@Times @RI{d} + @RI{a}@Times @RI{d}*i, but if one cannot avoid representing the pure-imaginary value @RI{d}*i as the complex value 0.0 + @RI{d}*i, then a NaN ("Not-a-Number") could be produced as the result of multiplying @RI{a} by 0.0 (e.g., when @RI{a} is infinite); the NaN could later trigger an exception. Providing the Imaginary type and overloadings of the arithmetic operators for mixtures of Imaginary and Complex operands gives the programmer the same control over avoiding premature coercion of pure-imaginary values to complex as is already provided for pure-real values. @end{itemize} @end{Reason} @begin{Reason} @Leading@;The Imaginary type is private, rather than being visibly derived from Real'Base, for two reasons: @begin{itemize} to preclude implicit conversions of real literals to the Imaginary type (such implicit conversions would make many common arithmetic expressions ambiguous); and to suppress the implicit derivation of the multiplication, division, and absolute value operators with Imaginary operands and an Imaginary result (the result type would be incorrect). @end{itemize} @end{Reason} @begin{Reason} The base subtype Real'Base is used for the component type of Complex, the parent type of Imaginary, and the parameter and result types of some of the subprograms to maximize the chances of being able to pass meaningful values into the subprograms and receive meaningful results back. The generic formal parameter Real therefore plays only one role, that of providing the precision to be maintained in complex arithmetic calculations. Thus, the subprograms in Numerics.Generic_Complex_Types share with those in Numerics.Generic_Elementary_Functions, and indeed even with the predefined arithmetic operations (see @RefSecNum{Operators and Expression Evaluation}), the property of being free of range checks on input and output, i.e., of being able to exploit the base range of the relevant floating point type fully. As a result, the user loses the ability to impose application-oriented bounds on the range of values that the components of a complex variable can acquire; however, it can be argued that few, if any, applications have a naturally square domain (as opposed to a circular domain) anyway. @end{Reason} @Leading@;The arithmetic operations and the Re, Im, Modulus, Argument, and Conjugate functions have their usual mathematical meanings. When applied to a parameter of pure-imaginary type, the @lquotes@;imaginary-part@rquotes@; function Im yields the value of its parameter, as the corresponding real value. The remaining subprograms have the following meanings: @begin{Reason} The middle case can be understood by considering the parameter of pure-imaginary type to represent a complex value with a zero real part. @end{Reason} @begin{Itemize} The Set_Re and Set_Im procedures replace the designated component of a complex parameter with the given real value; applied to a parameter of pure-imaginary type, the Set_Im procedure replaces the value of that parameter with the imaginary value corresponding to the given real value. The Compose_From_Cartesian function constructs a complex value from the given real and imaginary components. If only one component is given, the other component is implicitly zero. The Compose_From_Polar function constructs a complex value from the given modulus (radius) and argument (angle). When the value of the parameter Modulus is positive (resp., negative), the result is the complex value represented by the point in the complex plane lying at a distance from the origin given by the absolute value of Modulus and forming an angle measured counterclockwise from the positive (resp., negative) real axis given by the value of the parameter Argument. @end(Itemize) When the Cycle parameter is specified, the result of the Argument function and the parameter Argument of the Compose_From_Polar function are measured in units such that a full cycle of revolution has the given value; otherwise, they are measured in radians. @Leading@;The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply the principal branch: @begin{Itemize} The result of the Modulus function is nonnegative. The result of the Argument function is in the quadrant containing the point in the complex plane represented by the parameter X. This may be any quadrant (I through IV); thus, the range of the Argument function is approximately @en@Pi to @Pi (@en@R[Cycle]/2.0 to @R[Cycle]/2.0, if the parameter Cycle is specified). When the point represented by the parameter X lies on the negative real axis, the result approximates @begin{InnerItemize} @Pi (resp., @en@Pi) when the sign of the imaginary component of X is positive (resp., negative), if Real'Signed_Zeros is True; @Pi, if Real'Signed_Zeros is False. @end{InnerItemize} Because a result lying on or near one of the axes may not be exactly representable, the approximation inherent in computing the result may place it in an adjacent quadrant, close to but on the wrong side of the axis. @end{Itemize} @end{StaticSem} @begin{RunTime} The exception Numerics.Argument_Error is raised by the Argument and Compose_From_Polar functions with specified cycle, signaling a parameter value outside the domain of the corresponding mathematical function, when the value of the parameter Cycle is zero or negative. @IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised by the division operator when the value of the right operand is zero, and by the exponentiation operator when the value of the left operand is zero and the value of the exponent is negative, provided that Real'Machine_Overflows is True; when Real'Machine_Overflows is False, the result is unspecified. @PDefn{unspecified} @Redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for Complex Arithmetic}).] @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit implementations of the complex arithmetic operations to deliver results with an infinite component (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the complex arithmetic operations to deliver results with infinite components (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error in the situations defined above, when traps are disabled. Finally, such a binding should also specify the behavior of the complex arithmetic operations, when sensible, given operands with infinite components. @end{Discussion} @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Complex_Types, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Real. @begin{ImplNote} Implementations of Numerics.Generic_Complex_Types written in Ada should therefore avoid declaring local variables of subtype Real; the subtype Real'Base should be used instead. @end{ImplNote} @Leading @Defn2{Term=[prescribed result], Sec=[for the evaluation of a complex arithmetic operation]} In the following cases, evaluation of a complex arithmetic operation shall yield the @i{prescribed result}, provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} The results of the Re, Im, and Compose_From_Cartesian functions are exact. The real (resp., imaginary) component of the result of a binary addition operator that yields a result of complex type is exact when either of its operands is of pure-imaginary (resp., real) type. @begin{Ramification} The result of the addition operator is exact when one of its operands is of real type and the other is of pure-imaginary type. In this particular case, the operator is analogous to the Compose_From_Cartesian function; it performs no arithmetic. @end{Ramification} The real (resp., imaginary) component of the result of a binary subtraction operator that yields a result of complex type is exact when its right operand is of pure-imaginary (resp., real) type. The real component of the result of the Conjugate function for the complex type is exact. When the point in the complex plane represented by the parameter X lies on the nonnegative real axis, the Argument function yields a result of zero. @begin{Discussion} Argument(X + i*Y) is analogous to @i{EF}.Arctan(Y, X), where @i{EF} is an appropriate instance of Numerics.Generic_Elementary_Functions, except when X and Y are both zero, in which case the former yields the value zero while the latter raises Numerics.Argument_Error. @end{Discussion} When the value of the parameter Modulus is zero, the Compose_From_Polar function yields a result of zero. When the value of the parameter Argument is equal to a multiple of the quarter cycle, the result of the Compose_From_Polar function with specified cycle lies on one of the axes. In this case, one of its components is zero, and the other has the magnitude of the parameter Modulus. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand. Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero, provided that the exponent is nonzero. When the left operand is of pure-imaginary type, one component of the result of the exponentiation operator is zero. @end{Itemize} When the result, or a result component, of any operator of Numerics.Generic_Complex_Types has a mathematical definition in terms of a single arithmetic or relational operation, that result or result component exhibits the accuracy of the corresponding operation of the type Real. Other accuracy requirements for the Modulus, Argument, and Compose_From_Polar functions, and accuracy requirements for the multiplication of a pair of complex operands or for division by a complex operand, all of which apply only in the strict mode, are given in @RefSecNum{Accuracy Requirements for Complex Arithmetic}. The sign of a zero result or zero result component yielded by a complex arithmetic operation or function is implementation defined when Real'Signed_Zeros is True. @ImplDef{The sign of a zero result (or a component thereof) from any operator or function in Numerics.Generic_Complex_Types, when Real'Signed_Zeros is True.} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0091]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Implementations may obtain the result of exponentiation of a complex or pure-imaginary operand by repeated complex multiplication, with arbitrary association of the factors and with a possible final complex reciprocation (when the exponent is negative). Implementations are also permitted to obtain the result of exponentiation of a complex operand, but not of a pure-imaginary operand, by converting the left operand to a polar representation; exponentiating the modulus by the given exponent; multiplying the argument by the given exponent@Chg{New=[],Old=[, when the exponent is positive, or dividing the argument by the absolute value of the given exponent, when the exponent is negative]}; and reconverting to a @Chg{Version=[2],New=[Cartesian],Old=[cartesian]} representation. Because of this implementation freedom, no accuracy requirement is imposed on complex exponentiation (except for the prescribed results given above, which apply regardless of the implementation method chosen). @end{ImplPerm} @begin{ImplAdvice} Because the usual mathematical meaning of multiplication of a complex operand and a real operand is that of the scaling of both components of the former by the latter, an implementation should not perform this operation by first promoting the real operand to complex type and then performing a full complex multiplication. In systems that, in the future, support an Ada binding to IEC 559:1989, the latter technique will not generate the required result when one of the components of the complex operand is infinite. (Explicit multiplication of the infinite component by the zero component obtained during promotion yields a NaN that propagates into the final result.) Analogous advice applies in the case of multiplication of a complex operand and a pure-imaginary operand, and in the case of division of a complex operand by a real or pure-imaginary operand. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Mixed real and complex operations (as well as pure-imaginary and complex operations) should not be performed by converting the real (resp. pure-imaginary) operand to complex.]}]} Likewise, because the usual mathematical meaning of addition of a complex operand and a real operand is that the imaginary operand remains unchanged, an implementation should not perform this operation by first promoting the real operand to complex type and then performing a full complex addition. In implementations in which the Signed_Zeros attribute of the component type is True (and which therefore conform to IEC 559:1989 in regard to the handling of the sign of zero in predefined arithmetic operations), the latter technique will not generate the required result when the imaginary component of the complex operand is a negatively signed zero. (Explicit addition of the negative zero to the zero obtained during promotion yields a positive zero.) Analogous advice applies in the case of addition of a complex operand and a pure-imaginary operand, and in the case of subtraction of a complex operand and a real or pure-imaginary operand. Implementations in which Real'Signed_Zeros is True should attempt to provide a rational treatment of the signs of zero results and result components. As one example, the result of the Argument function should have the sign of the imaginary component of the parameter X when the point represented by that parameter lies on the positive real axis; as another, the sign of the imaginary component of the Compose_@!From_@!Polar function should be the same as (resp., the opposite of) that of the Argument parameter when that parameter has a value of zero and the Modulus parameter has a nonnegative (resp., negative) value. @ChgImplAdvice{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[If Real'Signed_Zeros is @Chg{Version=[3],New=[True],Old=[true]} for Numerics.@!Generic_@!Complex_@!Types, a rational treatment of the signs of zero results and result components should be provided.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Complex_Types differs from Generic_Complex_Types as defined in ISO/IEC CD 13813 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child of the package defining the Argument_Error exception. The nongeneric equivalents export types and constants with the same names as those exported by the generic package, rather than with names unique to the package. Implementations are not allowed to impose an optional restriction that the generic actual parameter associated with Real be unconstrained. (In view of the ability to declare variables of subtype Real'Base in implementations of Numerics.Generic_Complex_Types, this flexibility is no longer needed.) The dependence of the Argument function on the sign of a zero parameter component is tied to the value of Real'Signed_Zeros. Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added a @nt{pragma} Preelaborable_Initialization to type Imaginary, so that it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Complex_Types are pure.]} @end{DiffWord95} @LabeledSubClause{Complex Elementary Functions} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Complex_Elementary_Functions has the following declaration: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @key[with] Ada.Numerics.Generic_Complex_Types; @key[generic]@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Elementary_@!Functions]} @key[with] @key[package] Complex_Types @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (<>); @key[use] Complex_Types; @key[package] Ada.Numerics.Generic_Complex_Elementary_Functions @key[is] @Chg{Version=[2],New=[@key{pragma}],Old=[pragma]} Pure(Generic_Complex_Elementary_Functions); @key[function] @AdaSubDefn{Sqrt} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Log} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Exp} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Exp} (X : Imaginary) @key[return] Complex; @key[function] "**" (Left : Complex; Right : Complex) @key[return] Complex; @key[function] "**" (Left : Complex; Right : Real'Base) @key[return] Complex; @key[function] "**" (Left : Real'Base; Right : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Sin} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cos} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Tan} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cot} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arcsin} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccos} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arctan} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccot} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Sinh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Cosh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Tanh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Coth} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arcsinh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccosh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arctanh} (X : Complex) @key[return] Complex; @key[function] @AdaSubDefn{Arccoth} (X : Complex) @key[return] Complex; @key[end] Ada.Numerics.Generic_Complex_Elementary_Functions; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Elementary_@!Functions]} The library package Numerics.Complex_Elementary_Functions @Chg{New=[is declared pure and ],Old=[]}defines the same subprograms as Numerics.@!Generic_@!Complex_@!Elementary_@!Functions, except that the predefined type Float is systematically substituted for Real'Base, and the Complex and Imaginary types exported by Numerics.@!Complex_@!Types are systematically substituted for Complex and Imaginary, throughout. Nongeneric equivalents of Numerics.@!Generic_@!Complex_@!Elementary_@!Functions corresponding to each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Complex_@!Elementary_@!Functions, Numerics.@!Long_@!Complex_@!Elementary_@!Functions, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} The overloading of the Exp function for the pure-imaginary type is provided to give the user an alternate way to compose a complex value from a given modulus and argument. In addition to Compose_@!From_@!Polar(Rho, Theta) (see @RefSecNum{Complex Types}), the programmer may write Rho * Exp(i * Theta). The imaginary (resp., real) component of the parameter X of the forward hyperbolic (resp., trigonometric) functions and of the Exp function (and the parameter X, itself, in the case of the overloading of the Exp function for the pure-imaginary type) represents an angle measured in radians, as does the imaginary (resp., real) component of the result of the Log and inverse hyperbolic (resp., trigonometric) functions. @Leading@;The functions have their usual mathematical meanings. However, the arbitrariness inherent in the placement of branch cuts, across which some of the complex elementary functions exhibit discontinuities, is eliminated by the following conventions: @begin{Itemize} The imaginary component of the result of the Sqrt and Log functions is discontinuous as the parameter X crosses the negative real axis. The result of the exponentiation operator when the left operand is of complex type is discontinuous as that operand crosses the negative real axis. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The @Chg{Version=[2],New=[],Old=[real (resp., ]}imaginary@Chg{Version=[2], New=[],Old=[)]} component of the result of the Arcsin@Chg{Version=[2], New=[,],Old=[ and]} Arccos@Chg{Version=[2],New=[],Old=[(resp.]}, @Chg{Version=[2],New=[and ],Old=[]}Arctanh@Chg{Version=[2], New=[],Old=[)]} functions is discontinuous as the parameter X crosses the real axis to the left of @en@;1.0 or the right of 1.0. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The real @Chg{Version=[2],New=[],Old=[(resp., imaginary) ]}component of the result of the Arctan @Chg{Version=[2],New=[and],Old=[(resp.,]} Arcsinh@Chg{Version=[2], New=[ functions],Old=[) function]} is discontinuous as the parameter X crosses the imaginary axis below @en@RI{i} or above @RI{i}. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]} The real component of the result of the Arccot function is discontinuous as the parameter X crosses the imaginary axis @Chg{Version=[2],New=[below], Old=[between]} @en@RI{i} @Chg{Version=[2],New=[or above],Old=[and]} @RI{i}. The imaginary component of the Arccosh function is discontinuous as the parameter X crosses the real axis to the left of 1.0. The imaginary component of the result of the Arccoth function is discontinuous as the parameter X crosses the real axis between @en@;1.0 and 1.0. @end{Itemize} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00185-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The branch cuts come from the fact that the functions in question are really multi-valued in the complex domain, and that we have to pick one @i{principal value} to be the result of the function. Evidently we have much freedom in choosing where the branch cuts lie. However, we are adhering to the following principles which seem to lead to the more @i{natural} definitions:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A branch cut should not intersect the real axis at a place where the corresponding real function is well-defined (in other words, the complex function should be an extension of the corresponding real function).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Because all the functions in question are analytic, to ensure power series validity for the principal value, the branch cuts should be invariant by complex conjugation.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For odd functions, to ensure that the principal value remains an odd function, the branch cuts should be invariant by reflection in the origin.]} @end{Itemize} @end{Discussion} @Leading@;@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00185-01]}The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply @Chg{Version=[2],New=[that ],Old=[]}the principal branch@Chg{Version=[2],New=[ is an analytic continuation of the corresponding real-valued function in Numerics.Generic_Elementary_Functions. (For Arctan and Arccot, the single-argument function in question is that obtained from the two-argument version by fixing the second argument to be its default value.)],Old=[:]} @begin{Itemize} The real component of the result of the Sqrt and Arccosh functions is nonnegative. The same convention applies to the imaginary component of the result of the Log function as applies to the result of the natural-cycle version of the Argument function of Numerics.Generic_Complex_Types (see @RefSecNum{Complex Types}). The range of the real (resp., imaginary) component of the result of the Arcsin and Arctan (resp., Arcsinh and Arctanh) functions is approximately @en@Pi/2.0 to @Pi/2.0. The real (resp., imaginary) component of the result of the Arccos and Arccot (resp., Arccoth) functions ranges from 0.0 to approximately @Pi. The range of the imaginary component of the result of the Arccosh function is approximately @en@Pi to @Pi. @end{Itemize} In addition, the exponentiation operator inherits the single-valuedness of the Log function. @end{StaticSem} @begin{RunTime} The exception Numerics.Argument_Error is raised by the exponentiation operator, signaling a parameter value outside the domain of the corresponding mathematical function, when the value of the left operand is zero and the real component of the exponent (or the exponent itself, when it is of real type) is zero. @Leading@IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised, signaling a pole of the mathematical function (analogous to dividing by zero), in the following cases, provided that Complex_Types.Real'Machine_Overflows is True: @begin{Itemize} by the Log, Cot, and Coth functions, when the value of the parameter X is zero; by the exponentiation operator, when the value of the left operand is zero and the real component of the exponent (or the exponent itself, when it is of real type) is negative; by the Arctan and Arccot functions, when the value of the parameter X is @PorM @RI{i}; by the Arctanh and Arccoth functions, when the value of the parameter X is @PorM 1.0. @end{Itemize} @redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for Complex Arithmetic}); this may occur for parameter values sufficiently @i{near} poles, and, in the case of some of the functions, for parameter values having components of sufficiently large magnitude.] @PDefn{unspecified} When Complex_Types.Real'Machine_Overflows is False, the result at poles is unspecified. @begin{Reason} The purpose of raising Constraint_Error (rather than Numerics.Argument_Error) at the poles of a function, when Float_Type'Machine_Overflows is True, is to provide continuous behavior as the actual parameters of the function approach the pole and finally reach it. @end{Reason} @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit implementations of the complex elementary functions to deliver results with an infinite component (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the complex elementary functions to deliver results with an infinite component (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error at poles, when traps are disabled. Finally, such a binding should also specify the behavior of the complex elementary functions, when sensible, given parameters with infinite components. @end{Discussion} @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Complex_Elementary_Functions, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Complex_Types.Real. @begin{ImplNote} Implementations of Numerics.Generic_Complex_Elementary_Functions written in Ada should therefore avoid declaring local variables of subtype Complex_Types.Real; the subtype Complex_Types.Real'Base should be used instead. @end{ImplNote} @Leading @Defn2{Term=[prescribed result], Sec=[for the evaluation of a complex elementary function]} In the following cases, evaluation of a complex elementary function shall yield the @i{prescribed result} (or a result having the prescribed component), provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} When the parameter X has the value zero, the Sqrt, Sin, Arcsin, Tan, Arctan, Sinh, Arcsinh, Tanh, and Arctanh functions yield a result of zero; the Exp, Cos, and Cosh functions yield a result of one; the Arccos and Arccot functions yield a real result; and the Arccoth function yields an imaginary result. When the parameter X has the value one, the Sqrt function yields a result of one; the Log, Arccos, and Arccosh functions yield a result of zero; and the Arcsin function yields a real result. When the parameter X has the value @en@;1.0, the Sqrt function yields the result @begin{InnerItemize} @RI{i} (resp., @en@RI{i}), when the sign of the imaginary component of X is positive (resp., negative), if Complex_Types.Real'Signed_Zeros is True; @RI{i}, if Complex_Types.Real'Signed_Zeros is False; @end{InnerItemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Chg{Version=[2],New=[When the parameter X has the value @en@;1.0, ], Old=[]}the Log function yields an imaginary result; and the Arcsin and Arccos functions yield a real result. When the parameter X has the value @PorM @RI{i}, the Log function yields an imaginary result. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand (as a complex value). Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero. @end{Itemize} @begin{Discussion} It is possible to give many other prescribed results restricting the result to the real or imaginary axis when the parameter X is appropriately restricted to easily testable portions of the domain. We follow the proposed ISO/IEC standard for Generic_Complex_Elementary_Functions (for Ada 83), CD 13813, in not doing so, however. @end{Discussion} Other accuracy requirements for the complex elementary functions, which apply only in the strict mode, are given in @RefSecNum{Accuracy Requirements for Complex Arithmetic}. The sign of a zero result or zero result component yielded by a complex elementary function is implementation defined when Complex_Types.Real'Signed_Zeros is True. @ImplDef{The sign of a zero result (or a component thereof) from any operator or function in Numerics.Generic_Complex_Elementary_Functions, when Complex_Types.Real'Signed_Zeros is True.} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package with the appropriate predefined nongeneric equivalent of Numerics.Generic_Complex_Types; if they are, then the latter shall have been obtained by actual instantiation of Numerics.Generic_Complex_Types. The exponentiation operator may be implemented in terms of the Exp and Log functions. Because this implementation yields poor accuracy in some parts of the domain, no accuracy requirement is imposed on complex exponentiation. @PDefn{unspecified} The implementation of the Exp function of a complex parameter X is allowed to raise the exception Constraint_Error, signaling overflow, when the real component of X exceeds an unspecified threshold that is approximately @Log(@R[Complex_Types.Real'Safe_Last]). This permission recognizes the impracticality of avoiding overflow in the marginal case that the exponential of the real component of X exceeds the safe range of Complex_Types.Real but both components of the final result do not. Similarly, the Sin and Cos (resp., Sinh and Cosh) functions are allowed to raise the exception Constraint_Error, signaling overflow, when the absolute value of the imaginary (resp., real) component of the parameter X exceeds an unspecified threshold that is approximately @Log(@R[Complex_Types.Real'Safe_Last]) + @Log(2.0). @PDefn{unspecified} This permission recognizes the impracticality of avoiding overflow in the marginal case that the hyperbolic sine or cosine of the imaginary (resp., real) component of X exceeds the safe range of Complex_Types.Real but both components of the final result do not. @end{ImplPerm} @begin{ImplAdvice} Implementations in which Complex_Types.Real'Signed_Zeros is True should attempt to provide a rational treatment of the signs of zero results and result components. For example, many of the complex elementary functions have components that are odd functions of one of the parameter components; in these cases, the result component should have the sign of the parameter component at the origin. Other complex elementary functions have zero components whose sign is opposite that of a parameter component at the origin, or is always positive or always negative. @ChgImplAdvice{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[If Complex_Types.Real'Signed_Zeros is @Chg{Version=[3],New=[True],Old=[true]} for Numerics.@!Generic_@!Complex_@!Elementary_@!Functions, a rational treatment of the signs of zero results and result components should be provided.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.@!Generic_@!Complex_@!Elementary_@!Functions differs from Generic_@!Complex_@!Elementary_@!Functions as defined in ISO/IEC CD 13814 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child unit of the package defining the Argument_Error exception. The proposed Generic_Complex_Elementary_Functions standard (for Ada 83) specified names for the nongeneric equivalents, if provided. Here, those nongeneric equivalents are required. The generic package imports an instance of Numerics.Generic_Complex_Types rather than a long list of individual types and operations exported by such an instance. The dependence of the imaginary component of the Sqrt and Log functions on the sign of a zero parameter component is tied to the value of Complex_Types.Real'Signed_Zeros. Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Complex_Elementary_Functions are pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00185-01]} @ChgAdded{Version=[2],Text=[Corrected various inconsistencies in the definition of the branch cuts.]} @end{DiffWord95} @LabeledSubClause{Complex Input-Output} @begin{Intro} The generic package Text_IO.Complex_IO defines procedures for the formatted input and output of complex values. The generic actual parameter in an instantiation of Text_IO.Complex_IO is an instance of Numerics.Generic_Complex_Types for some floating point subtype. Exceptional conditions are reported by raising the appropriate exception defined in Text_IO. @begin{ImplNote} An implementation of Text_IO.Complex_IO can be built around an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, where Complex_Types is the generic formal package parameter of Text_IO.Complex_IO. There is no need for an implementation of Text_IO.Complex_IO to parse real values. @end{ImplNote} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Text_IO.Complex_IO has the following declaration: @begin{Ramification} Because this is a child of Text_IO, the declarations of the visible part of Text_IO are directly visible within it. @end{Ramification} @begin{Example} @key[with] Ada.Numerics.Generic_Complex_Types; @key[generic]@ChildUnit{Parent=[Ada.Text_IO],Child=[Complex_IO]} @key[with] @key[package] Complex_Types @key[is] @key[new] Ada.Numerics.Generic_Complex_Types (<>); @key[package] Ada.Text_IO.Complex_IO @key[is] @key[use] Complex_Types; @AdaObjDefn{Default_Fore} : Field := 2; @AdaObjDefn{Default_Aft} : Field := Real'Digits - 1; @AdaObjDefn{Default_Exp} : Field := 3; @key[procedure] @AdaSubDefn{Get} (File : @key[in] File_Type; Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get} (Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put} (File : @key[in] File_Type; Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put} (Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @trailing@; @key[procedure] @AdaSubDefn{Get} (From : @key[in] String; Item : @key[out] Complex; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put} (To : @key[out] String; Item : @key[in] Complex; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Ada.Text_IO.Complex_IO; @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00328-01]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada],Child=[Complex_@!Text_IO]} The library package Complex_Text_IO defines the same subprograms as Text_IO.Complex_IO, except that the predefined type Float is systematically substituted for Real, and the type Numerics.Complex_Types.Complex is systematically substituted for Complex throughout. Nongeneric equivalents of Text_IO.Complex_IO corresponding to each of the other predefined floating point types are defined similarly, with the names Short_Complex_Text_IO, Long_Complex_Text_IO, etc.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics.]} @end{Reason} The semantics of the Get and Put procedures are as follows: @begin{DescribeCode} @begin{Example} @key[procedure] Get (File : @key[in] File_Type; Item : @key[out] Complex; Width : @key[in] Field := 0); @key[procedure] Get (Item : @key[out] Complex; Width : @key[in] Field := 0); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0092],ARef=[AI95-00029-01]} @Leading@;The input sequence is a pair of optionally signed real literals representing the real and imaginary components of a complex value@Chg{New=[. These components have the format defined for the corresponding Get procedure of an instance of Text_IO.Float_IO (see @RefSecNum{Input-Output for Real Types}) for the base subtype of Complex_Types.Real. The],Old=[; optionally, the]} pair of components may be separated by a comma @Chg{New=[],Old=[and/]}or surrounded by a pair of parentheses@Chg{New=[ or both],Old=[]}. Blanks are freely allowed before each of the components and before the parentheses and comma, if either is used. If the value of the parameter Width is zero, then @begin{Itemize} line and page terminators are also allowed in these places; the components shall be separated by at least one blank or line terminator if the comma is omitted; and reading stops when the right parenthesis has been read, if the input sequence includes a left parenthesis, or when the imaginary component has been read, otherwise. @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]}@Leading @Chg{New=[],Old=[@Noparanum@;]}If a nonzero value of Width is supplied, then @begin{Itemize} the components shall be separated by at least one blank if the comma is omitted; and exactly Width characters are read, or the characters (possibly none) up to a line terminator, whichever comes first (blanks are included in the count). @end{Itemize} @begin{Reason} The parenthesized and comma-separated form is the form produced by Put on output (see below), and also by list-directed output in Fortran. The other allowed forms match several common styles of edit-directed output in Fortran, allowing most preexisting Fortran data files containing complex data to be read easily. When such files contain complex values with no separation between the real and imaginary components, the user will have to read those components separately, using an instance of Text_IO.Float_IO. @end{Reason} Returns, in the parameter Item, the value of type Complex that corresponds to the input sequence. @Trailing@;The exception Text_IO.Data_Error is raised if the input sequence does not have the required syntax or if the components of the complex value obtained are not of the base subtype of Complex_Types.Real. @begin{Example} @key[procedure] Put (File : @key[in] File_Type; Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] Put (Item : @key[in] Complex; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item as a pair of decimal literals representing the real and imaginary components of the complex value, using the syntax of an aggregate. More specifically, @begin{itemize} outputs a left parenthesis; outputs the value of the real component of the parameter Item with the format defined by the corresponding Put procedure of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using the given values of Fore, Aft, and Exp; outputs a comma; outputs the value of the imaginary component of the parameter Item with the format defined by the corresponding Put procedure of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using the given values of Fore, Aft, and Exp; @Trailing@;outputs a right parenthesis. @end{itemize} @begin{Discussion} If the file has a bounded line length, a line terminator may be output implicitly before any element of the sequence itemized above. @end{Discussion} @begin{Discussion} The option of outputting the complex value as a pair of reals without additional punctuation is not provided, since it can be accomplished by outputting the real and imaginary components of the complex value separately. @end{Discussion} @begin{Example} @key[procedure] Get (From : @key[in] String; Item : @key[out] Complex; Last : @key[out] Positive); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Reads a complex value from the beginning of the given string, following the same rule as the Get procedure that reads a complex value from a file, but treating the end of the string as a @Chg{Version=[2],New=[file],Old=[line]} terminator. Returns, in the parameter Item, the value of type Complex that corresponds to the input sequence. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Text_IO.Data_Error is raised if the input sequence does not have the required syntax or if the components of the complex value obtained are not of the base subtype of Complex_Types.Real. @begin{Example} @key[procedure] Put (To : @key[out] String; Item : @key[in] Complex; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item to the given string as a pair of decimal literals representing the real and imaginary components of the complex value, using the syntax of an aggregate. More specifically, @begin{itemize} a left parenthesis, the real component, and a comma are left justified in the given string, with the real component having the format defined by the Put procedure (for output to a file) of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using a value of zero for Fore and the given values of Aft and Exp; the imaginary component and a right parenthesis are right justified in the given string, with the imaginary component having the format defined by the Put procedure (for output to a file) of an instance of Text_IO.Float_IO for the base subtype of Complex_Types.Real, using a value for Fore that completely fills the remainder of the string, together with the given values of Aft and Exp. @end{itemize} @begin{Reason} This rule is the one proposed in LSN-1051. Other rules were considered, including one that would have read @lquotes@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using a value for Fore such that the sequence of characters output exactly fills, or comes closest to filling, the string; in the latter case, the string is filled by inserting one extra blank immediately after the comma.@rquotes@; While this latter rule might be considered the closest analogue to the rule for output to a string in Text_IO.Float_IO, it requires a more difficult and inefficient implementation involving special cases when the integer part of one component is substantially longer than that of the other and the string is too short to allow both to be preceded by blanks. Unless such a special case applies, the latter rule might produce better columnar output if several such strings are ultimately output to a file, but very nearly the same output can be produced by outputting to the file directly, with the appropriate value of Fore; in any case, it might validly be assumed that output to a string is intended for further computation rather than for display, so that the precise formatting of the string to achieve a particular appearance is not the major concern. @end{Reason} The exception Text_IO.Layout_Error is raised if the given string is too short to hold the formatted output. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} Other exceptions declared (by renaming) in Text_IO may be raised by the preceding procedures in the appropriate circumstances, as for the corresponding procedures of Text_IO.Float_IO. @end{ImplPerm} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00328-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Nongeneric equivalents for Text_IO.Complex_IO are added, to be consistent with all other language-defined Numerics generic packages.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0092],ARef=[AI95-00029-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the syntax of values read by Complex_IO is the same as that read by Text_IO.Float_IO.]} @end{DiffWord95} @LabeledSubClause{The Package Wide_Text_IO.Complex_IO} @begin{StaticSem} @Defn{Ada.Wide_@!Text_IO.Complex_IO} @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Complex_IO]} Implementations shall also provide the generic library package Wide_Text_IO.Complex_IO. Its declaration is obtained from that of Text_IO.Complex_IO by systematically replacing Text_IO by Wide_Text_IO and String by Wide_String; the description of its behavior is obtained by additionally replacing references to particular characters (commas, parentheses, etc.) by those for the corresponding wide characters. @end{StaticSem} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Complex_IO]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{Ada.Wide_Wide_@!Text_IO.Complex_IO} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Complex_IO]} Implementations shall also provide the generic library package Wide_Wide_Text_IO.Complex_IO. Its declaration is obtained from that of Text_IO.Complex_IO by systematically replacing Text_IO by Wide_Wide_Text_IO and String by Wide_Wide_String; the description of its behavior is obtained by additionally replacing references to particular characters (commas, parentheses, etc.) by those for the corresponding wide wide characters.]} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Complex_IO is new. (At least it wasn't called Incredibly_Wide_Text_IO.Complex_IO; maybe next time.)]} @end{Extend95} @LabeledClause{Numeric Performance Requirements} @begin{ImplReq} @Defn{accuracy} @Defn{strict mode} Implementations shall provide a user-selectable mode in which the accuracy and other numeric performance requirements detailed in the following subclauses are observed. This mode, referred to as the @i{strict mode}, may or may not be the default mode; it directly affects the results of the predefined arithmetic operations of real types and the results of the subprograms in children of the Numerics package, and indirectly affects the operations in other language defined packages. @Defn{relaxed mode} Implementations shall also provide the opposing mode, which is known as the @i{relaxed mode}. @begin{Reason} On the assumption that the users of an implementation that does not support the Numerics Annex have no particular need for numerical performance, such an implementation has no obligation to meet any particular requirements in this area. On the other hand, users of an implementation that does support the Numerics Annex are provided with a way of ensuring that their programs achieve a known level of numerical performance and that the performance is portable to other such implementations. The relaxed mode is provided to allow implementers to offer an efficient but not fully accurate alternative in the case that the strict mode entails a time overhead that some users may find excessive. In some of its areas of impact, the relaxed mode may be fully equivalent to the strict mode. @end{Reason} @begin{ImplNote} The relaxed mode may, for example, be used to exploit the implementation of (some of) the elementary functions in hardware, when available. Such implementations often do not meet the accuracy requirements of the strict mode, or do not meet them over the specified range of parameter values, but compensate in other ways that may be important to the user, such as their extreme speed. @end{ImplNote} @begin{Ramification} For implementations supporting the Numerics Annex, the choice of mode has no effect on the selection of a representation for a real type or on the values of attributes of a real type. @end{Ramification} @end{ImplReq} @begin{ImplPerm} Either mode may be the default mode. @ImplDef{Whether the strict mode or the relaxed mode is the default.} The two modes need not actually be different. @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} The choice between strict and relaxed numeric performance was not available in Ada 83. @end{Extend83} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledSubClause{Model of Floating Point Arithmetic} @begin{Intro} In the strict mode, the predefined operations of a floating point type shall satisfy the accuracy requirements specified here and shall avoid or signal overflow in the situations described. This behavior is presented in terms of a model of floating point arithmetic that builds on the concept of the canonical form (see @RefSecNum{Attributes of Floating Point Types}). @end{Intro} @begin{StaticSem} Associated with each floating point type is an infinite set of model numbers. The model numbers of a type are used to define the accuracy requirements that have to be satisfied by certain predefined operations of the type; through certain attributes of the model numbers, they are also used to explain the meaning of a user-declared floating point type declaration. The model numbers of a derived type are those of the parent type; the model numbers of a subtype are those of its type. @Defn{model number} The @i{model numbers} of a floating point type T are zero and all the values expressible in the canonical form (for the type T), in which @i{mantissa} has T'Model_Mantissa digits and @i{exponent} has a value greater than or equal to T'Model_Emin. (These attributes are defined in @RefSecNum{Model-Oriented Attributes of Floating Point Types}.) @begin{Discussion} The model is capable of describing the behavior of most existing hardware that has a mantissa-exponent representation. As applied to a type T, it is parameterized by the values of T'Machine_Radix, T'Model_Mantissa, T'Model_Emin, T'Safe_First, and T'Safe_Last. The values of these attributes are determined by how, and how well, the hardware behaves. They in turn determine the set of model numbers and the safe range of the type, which figure in the accuracy and range (overflow avoidance) requirements. In hardware that is free of arithmetic anomalies, T'Model_Mantissa, T'Model_Emin, T'Safe_First, and T'Safe_Last will yield the same values as T'Machine_Mantissa, T'Machine_Emin, T'Base'First, and T'Base'Last, respectively, and the model numbers in the safe range of the type T will coincide with the machine numbers of the type T. In less perfect hardware, it is not possible for the model-oriented attributes to have these optimal values, since the hardware, by definition, and therefore the implementation, cannot conform to the stringencies of the resulting model; in this case, the values yielded by the model-oriented parameters have to be made more conservative (i.e., have to be penalized), with the result that the model numbers are more widely separated than the machine numbers, and the safe range is a subrange of the base range. The implementation will then be able to conform to the requirements of the weaker model defined by the sparser set of model numbers and the smaller safe range. @end{Discussion} @Defn{model interval} A @i(model interval) of a floating point type is any interval whose bounds are model numbers of the type. @Defn2{Term=[model interval], Sec=[associated with a value]} The @i{model interval} of a type T @i{associated with a value} @i{v} is the smallest model interval of T that includes @i{v}. (The model interval associated with a model number of a type consists of that number only.) @end{StaticSem} @begin{ImplReq} The accuracy requirements for the evaluation of certain predefined operations of floating point types are as follows. @begin{Discussion} This subclause does not cover the accuracy of an operation of a static expression; such operations have to be evaluated exactly (see @RefSecNum(Static Expressions and Static Subtypes)). It also does not cover the accuracy of the predefined attributes of a floating point subtype that yield a value of the type; such operations also yield exact results (see @RefSecNum(Operations of Floating Point Types) and @RefSecNum(Attributes of Floating Point Types)). @end{Discussion} @Defn{operand interval} An @i(operand interval) is the model interval, of the type specified for the operand of an operation, associated with the value of the operand. @Leading@;For any predefined arithmetic operation that yields a result of a floating point type T, the required bounds on the result are given by a model interval of T (called the @i(result interval)) defined in terms of the operand values as follows: @begin(Itemize) @Defn2{Term=[result interval], Sec=[for the evaluation of a predefined arithmetic operation]} The result interval is the smallest model interval of T that includes the minimum and the maximum of all the values obtained by applying the (exact) mathematical operation to values arbitrarily selected from the respective operand intervals. @end(Itemize) The result interval of an exponentiation is obtained by applying the above rule to the sequence of multiplications defined by the exponent, assuming arbitrary association of the factors, and to the final division in the case of a negative exponent. The result interval of a conversion of a numeric value to a floating point type T is the model interval of T associated with the operand value, except when the source expression is of a fixed point type with a @i(small) that is not a power of T'Machine_Radix or is a fixed point multiplication or division either of whose operands has a @i(small) that is not a power of T'Machine_Radix; in these cases, the result interval is implementation defined. @ImplDef{The result interval in certain cases of fixed-to-float conversion.} @IndexCheck{Overflow_Check} For any of the foregoing operations, the implementation shall deliver a value that belongs to the result interval when both bounds of the result interval are in the safe range of the result type T, as determined by the values of T'Safe_First and T'Safe_Last; otherwise, @begin(itemize) @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if T'Machine_Overflows is True, the implementation shall either deliver a value that belongs to the result interval or raise Constraint_Error; if T'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a floating point arithmetic operation in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end(itemize) For any predefined relation on operands of a floating point type T, the implementation may deliver any value (i.e., either True or False) obtained by applying the (exact) mathematical comparison to values arbitrarily chosen from the respective operand intervals. The result of a membership test is defined in terms of comparisons of the operand value with the lower and upper bounds of the given range or type mark (the usual rules apply to these comparisons). @end{ImplReq} @begin{ImplPerm} If the underlying floating point hardware implements division as multiplication by a reciprocal, the result interval for division (and exponentiation by a negative exponent) is implementation defined. @ImplDef{The result interval for division (or exponentiation by a negative exponent), when the floating point hardware implements division as multiplication by a reciprocal.} @end{ImplPerm} @begin{DiffWord83} The Ada 95 model numbers of a floating point type that are in the safe range of the type are comparable to the Ada 83 safe numbers of the type. There is no analog of the Ada 83 model numbers. The Ada 95 model numbers, when not restricted to the safe range, are an infinite set. @end{DiffWord83} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Giving the model numbers the hardware radix, instead of always a radix of two, allows (in conjunction with other changes) some borderline declared types to be represented with less precision than in Ada 83 (i.e., with single precision, whereas Ada 83 would have used double precision). Because the lower precision satisfies the requirements of the model (and did so in Ada 83 as well), this change is viewed as a desirable correction of an anomaly, rather than a worrisome inconsistency. (Of course, the wider representation chosen in Ada 83 also remains eligible for selection in Ada 95.) As an example of this phenomenon, assume that Float is represented in single precision and that a double precision type is also available. Also assume hexadecimal hardware with clean properties, for example certain IBM hardware. Then, @begin{Example} @key[type] T @key[is] @key[digits] Float'Digits @key[range] -Float'Last .. Float'Last; @end{Example} results in T being represented in double precision in Ada 83 and in single precision in Ada 95. The latter is intuitively correct; the former is counterintuitive. The reason why the double precision type is used in Ada 83 is that Float has model and safe numbers (in Ada 83) with 21 binary digits in their mantissas, as is required to model the hypothesized hexadecimal hardware using a binary radix; thus Float'Last, which is not a model number, is slightly outside the range of safe numbers of the single precision type, making that type ineligible for selection as the representation of T even though it provides adequate precision. In Ada 95, Float'Last (the same value as before) is a model number and is in the safe range of Float on the hypothesized hardware, making Float eligible for the representation of T. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Giving the model numbers the hardware radix allows for practical implementations on decimal hardware. @end{Extend83} @begin{DiffWord83} The wording of the model of floating point arithmetic has been simplified to a large extent. @end{DiffWord83} @LabeledSubClause{Model-Oriented Attributes of Floating Point Types} @begin{Intro} In implementations that support the Numerics Annex, the model-oriented attributes of floating point types shall yield the values defined here, in both the strict and the relaxed modes. These definitions add conditions to those in @RefSecNum{Attributes of Floating Point Types}. @end{Intro} @begin{StaticSem} @Leading@keepnext@;For every subtype S of a floating point type @i{T}: @begin{Description} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} S'@Attr{Model_Mantissa} @\Yields the number of digits in the mantissa of the canonical form of the model numbers of @i{T} (see @RefSecNum{Attributes of Floating Point Types}). The value of this attribute shall be greater than or equal to@Chg{Version=[2],New=[], Old=[ @Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + 1, where @RI{d} is the requested decimal precision of @i{T}. In addition, it shall be less than or equal to the value of @i{T}'Machine_Mantissa. This attribute yields a value of the type @i{universal_integer}.]} @begin{Display} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + @RI{g}]} @end{Display} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[where @RI{d} is the requested decimal precision of @i{T}, and @RI{g} is 0 if @i{T}'Machine_Radix is a positive power of 10 and 1 otherwise. In addition, @i{T}'Model_Mantissa shall be less than or equal to the value of @i{T}'Machine_Mantissa. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} S'Model_Epsilon, which is defined in terms of S'Model_Mantissa (see @RefSecNum{Attributes of Floating Point Types}), yields the absolute value of the difference between one and the next model number of the type @i{T} above one. It is equal to or larger than the absolute value of the difference between one and the next machine number of the type @i{T} above one. @end{Ramification} S'@Attr{Model_Emin} @\Yields the minimum exponent of the canonical form of the model numbers of @i{T} (see @RefSecNum{Attributes of Floating Point Types}). The value of this attribute shall be greater than or equal to the value of @i{T}'Machine_Emin. This attribute yields a value of the type @i{universal_integer}. @begin{Ramification} S'Model_Small, which is defined in terms of S'Model_Emin (see @RefSecNum{Attributes of Floating Point Types}), yields the smallest positive (nonzero) model number of the type @i{T}. @end{Ramification} S'@Attr{Safe_First} @\Yields the lower bound of the safe range of @i{T}. The value of this attribute shall be a model number of @i{T} and greater than or equal to the lower bound of the base range of @i{T}. In addition, if @i{T} is declared by a @nt{floating_point_definition} or is derived from such a type, and the @nt{floating_point_definition} includes a @nt{real_range_specification} specifying a lower bound of @RI{lb}, then the value of this attribute shall be less than or equal to @RI{lb}; otherwise, it shall be less than or equal to @en@;10.0 @+[4 @Times @RI{d}], where @RI{d} is the requested decimal precision of @i{T}. This attribute yields a value of the type @i{universal_real}. S'@Attr{Safe_Last} @\Yields the upper bound of the safe range of @i{T}. The value of this attribute shall be a model number of @i{T} and less than or equal to the upper bound of the base range of @i{T}. In addition, if @i{T} is declared by a @nt{floating_point_definition} or is derived from such a type, and the @nt{floating_point_definition} includes a @nt{real_range_specification} specifying an upper bound of @RI{ub}, then the value of this attribute shall be greater than or equal to @RI{ub}; otherwise, it shall be greater than or equal to 10.0 @+[4 @Times @RI{d}], where d is the requested decimal precision of @i{T}. This attribute yields a value of the type @i{universal_real}. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)}S'@Attr{Model} @\Denotes a function (of a parameter @i{X}) whose specification is given in @RefSecNum{Attributes of Floating Point Types}. If @i{X} is a model number of @i{T}, the function yields @i{X}; otherwise, it yields the value obtained by rounding or truncating @i{X} to either one of the adjacent model numbers of @i{T}. @IndexCheck{Overflow_Check}Constraint_Error is raised if the resulting model number is outside the safe range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True. @end{Description} @Leading@;Subject to the constraints given above, the values of S'Model_Mantissa and S'Safe_Last are to be maximized, and the values of S'Model_Emin and S'Safe_First minimized, by the implementation as follows: @begin{Itemize} First, S'Model_Mantissa is set to the largest value for which values of S'Model_Emin, S'Safe_First, and S'Safe_Last can be chosen so that the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes. Next, S'Model_Emin is set to the smallest value for which values of S'Safe_First and S'Safe_Last can be chosen so that the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes and the previously determined value of S'Model_Mantissa. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} Finally, S'Safe_First and S'@Chg{Version=[3],New=[Safe_Last],Old=[Safe_last]} are set (in either order) to the smallest and largest values, respectively, for which the implementation satisfies the strict-mode requirements of @RefSecNum{Model of Floating Point Arithmetic} in terms of the model numbers and safe range induced by these attributes and the previously determined values of S'Model_Mantissa and S'Model_Emin. @end{Itemize} @begin{Ramification} @Defn{IEEE floating point arithmetic} @Defn{IEC 559:1989} The following table shows appropriate attribute values for IEEE basic single and double precision types (ANSI/IEEE Std 754-1985, IEC 559:1989). Here, we use the names IEEE_Float_32 and IEEE_Float_64, the names that would typically be declared in package Interfaces, in an implementation that supports IEEE arithmetic. In such an implementation, the attributes would typically be the same for Standard.Float and Long_Float, respectively. @begin{Example} Attribute IEEE_Float_32 IEEE_Float_64 'Machine_Radix 2 2 'Machine_Mantissa 24 53 'Machine_Emin -125 -1021 'Machine_Emax 128 1024 'Denorm True True 'Machine_Rounds True True 'Machine_Overflows True/False True/False 'Signed_Zeros should be True should be True 'Model_Mantissa (same as 'Machine_Mantissa) (same as 'Machine_Mantissa) 'Model_Emin (same as 'Machine_Emin) (same as 'Machine_Emin) 'Model_Epsilon 2.0**(-23) 2.0**(-52) 'Model_Small 2.0**(-126) 2.0**(-1022) 'Safe_First -2.0**128*(1.0-2.0**(-24)) -2.0**1024*(1.0-2.0**(-53)) 'Safe_Last 2.0**128*(1.0-2.0**(-24)) 2.0**1024*(1.0-2.0**(-53)) 'Digits 6 15 'Base'Digits (same as 'Digits) (same as 'Digits) 'First (same as 'Safe_First) (same as 'Safe_First) 'Last (same as 'Safe_Last) (same as 'Safe_Last) 'Size 32 64 @end{Example} Note: 'Machine_Overflows can be True or False, depending on whether the Ada implementation raises Constraint_Error or delivers a signed infinity in overflow and zerodivide situations (and at poles of the elementary functions). @end{Ramification} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Corrected the definition of Model_Mantissa to match that given in @RefSecNum{Operations of Floating Point Types}.]} @end{DiffWord95} @LabeledSubClause{Model of Fixed Point Arithmetic} @begin{Intro} In the strict mode, the predefined arithmetic operations of a fixed point type shall satisfy the accuracy requirements specified here and shall avoid or signal overflow in the situations described. @end{Intro} @begin{ImplReq} The accuracy requirements for the predefined fixed point arithmetic operations and conversions, and the results of relations on fixed point operands, are given below. @begin{Discussion} This subclause does not cover the accuracy of an operation of a static expression; such operations have to be evaluated exactly (see @RefSecNum(Static Expressions and Static Subtypes)). @end{Discussion} The operands of the fixed point adding operators, absolute value, and comparisons have the same type. These operations are required to yield exact results, unless they overflow. Multiplications and divisions are allowed between operands of any two fixed point types; the result has to be (implicitly or explicitly) converted to some other numeric type. For purposes of defining the accuracy rules, the multiplication or division and the conversion are treated as a single operation whose accuracy depends on three types (those of the operands and the result). For decimal fixed point types, the attribute T'Round may be used to imply explicit conversion with rounding (see @RefSecNum(Operations of Fixed Point Types)). When the result type is a floating point type, the accuracy is as given in @RefSecNum(Model of Floating Point Arithmetic). @Defn{perfect result set} For some combinations of the operand and result types in the remaining cases, the result is required to belong to a small set of values called the @i(perfect result set); @Defn{close result set} for other combinations, it is required merely to belong to a generally larger and implementation-defined set of values called the @i(close result set). When the result type is a decimal fixed point type, the perfect result set contains a single value; thus, operations on decimal types are always fully specified. @ImplDef{The definition of @i{close result set}, which determines the accuracy of certain fixed point multiplications and divisions.} When one operand of a fixed-fixed multiplication or division is of type @i(universal_real), that operand is not implicitly converted in the usual sense, since the context does not determine a unique target type, but the accuracy of the result of the multiplication or division (i.e., whether the result has to belong to the perfect result set or merely the close result set) depends on the value of the operand of type @i(universal_real) and on the types of the other operand and of the result. @begin{Discussion} We need not consider here the multiplication or division of two such operands, since in that case either the operation is evaluated exactly (i.e., it is an operation of a static expression all of whose operators are of a root numeric type) or it is considered to be an operation of a floating point type. @end{Discussion} @Leading@;For a fixed point multiplication or division whose (exact) mathematical result is @RI{v}, and for the conversion of a value @RI{v} to a fixed point type, the perfect result set and close result set are defined as follows: @begin(itemize) @Leading@Keepnext@;If the result type is an ordinary fixed point type with a @i(small) of @RI{s}, @begin(InnerItemize) if @RI{v} is an integer multiple of @RI{s}, then the perfect result set contains only the value @RI{v}; otherwise, it contains the integer multiple of @RI{s} just below @RI{v} and the integer multiple of @RI{s} just above @RI{v}. @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integer multiples of @RI{s} containing the perfect result set as a subset. @Leading@Keepnext@;If the result type is a decimal type with a @i(small) of @RI{s}, @begin(InnerItemize) if @RI{v} is an integer multiple of @RI{s}, then the perfect result set contains only the value @RI{v}; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} otherwise, if truncation applies@Chg{Version=[3],New=[,],Old=[]} then it contains only the integer multiple of @RI{s} in the direction toward zero, whereas if rounding applies@Chg{Version=[3],New=[,],Old=[]} then it contains only the nearest integer multiple of @RI{s} (with ties broken by rounding away from zero). @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integer multiples of @RI{s} containing the perfect result set as a subset. @begin{Ramification} As a consequence of subsequent rules, this case does not arise when the operand types are also decimal types. @end{Ramification} @Leading@Keepnext@;If the result type is an integer type, @begin(InnerItemize) if @RI{v} is an integer, then the perfect result set contains only the value @RI{v}; otherwise, it contains the integer nearest to the value @RI{v} (if @RI{v} lies equally distant from two consecutive integers, the perfect result set contains the one that is further from zero). @end(InnerItemize) @NoPrefix@;The close result set is an implementation-defined set of consecutive integers containing the perfect result set as a subset. @end(itemize) The result of a fixed point multiplication or division shall belong either to the perfect result set or to the close result set, as described below, if overflow does not occur. In the following cases, if the result type is a fixed point type, let @RI{s} be its @i(small); otherwise, i.e. when the result type is an integer type, let @RI{s} be 1.0. @begin(itemize) For a multiplication or division neither of whose operands is of type @i(universal_real), let @RI{l} and @RI{r} be the @i(smalls) of the left and right operands. For a multiplication, if (@RI{l} @Times @RI{r}) / @RI{s} is an integer or the reciprocal of an integer (the @i(smalls) are said to be @lquotes@;compatible@rquotes@; in this case), the result shall belong to the perfect result set; otherwise, it belongs to the close result set. For a division, if @RI{l} / (@RI{r} @Times @RI{s}) is an integer or the reciprocal of an integer (i.e., the @i(smalls) are compatible), the result shall belong to the perfect result set; otherwise, it belongs to the close result set. @begin{Ramification} When the operand and result types are all decimal types, their @i(smalls) are necessarily compatible; the same is true when they are all ordinary fixed point types with binary @i(smalls). @end{Ramification} For a multiplication or division having one @i(universal_real) operand with a value of @RI{v}, note that it is always possible to factor @RI{v} as an integer multiple of a @lquotes@;compatible@rquotes@; @i(small), but the integer multiple may be @lquotes@;too big.@rquotes@; If there exists a factorization in which that multiple is less than some implementation-defined limit, the result shall belong to the perfect result set; otherwise, it belongs to the close result set. @ImplDef{Conditions on a @i{universal_real} operand of a fixed point multiplication or division for which the result shall be in the @i{perfect result set}.} @end(itemize) A multiplication P * Q of an operand of a fixed point type F by an operand of an integer type I, or vice-versa, and a division P / Q of an operand of a fixed point type F by an operand of an integer type I, are also allowed. In these cases, the result has a type of F; explicit conversion of the result is never required. The accuracy required in these cases is the same as that required for a multiplication F(P * Q) or a division F(P / Q) obtained by interpreting the operand of the integer type to have a fixed point type with a @i(small) of 1.0. The accuracy of the result of a conversion from an integer or fixed point type to a fixed point type, or from a fixed point type to an integer type, is the same as that of a fixed point multiplication of the source value by a fixed point operand having a @i(small) of 1.0 and a value of 1.0, as given by the foregoing rules. The result of a conversion from a floating point type to a fixed point type shall belong to the close result set. The result of a conversion of a @i(universal_real) operand to a fixed point type shall belong to the perfect result set. The possibility of overflow in the result of a predefined arithmetic operation or conversion yielding a result of a fixed point type T is analogous to that for floating point types, except for being related to the base range instead of the safe range. @IndexCheck{Overflow_Check} If all of the permitted results belong to the base range of T, then the implementation shall deliver one of the permitted results; otherwise, @begin(itemize) @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if T'Machine_Overflows is True, the implementation shall either deliver one of the permitted results or raise Constraint_Error; if T'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a fixed point arithmetic operation in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end(itemize) @end{ImplReq} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} Since the values of a fixed point type are now just the integer multiples of its @i{small}, the possibility of using extra bits available in the chosen representation for extra accuracy rather than for increasing the base range would appear to be removed, raising the possibility that some fixed point expressions will yield less accurate results than in Ada 83. However, this is partially offset by the ability of an implementation to choose a smaller default @i{small} than before. Of course, if it does so for a type T then T'Small will have a different value than it previously had. The accuracy requirements in the case of incompatible @i{smalls} are relaxed to foster wider support for nonbinary @i{smalls}. If this relaxation is exploited for a type that was previously supported, lower accuracy could result; however, there is no particular incentive to exploit the relaxation in such a case. @end{Inconsistent83} @begin{DiffWord83} @Leading@;The fixed point accuracy requirements are now expressed without reference to model or safe numbers, largely because the full generality of the former model was never exploited in the case of fixed point types (particularly in regard to operand perturbation). Although the new formulation in terms of perfect result sets and close result sets is still verbose, it can be seen to distill down to two cases: @begin{Itemize} a case where the result must be the exact result, if the exact result is representable, or, if not, then either one of the adjacent values of the type (in some subcases only one of those adjacent values is allowed); a case where the accuracy is not specified by the language. @end{Itemize} @end{DiffWord83} @LabeledSubClause{Accuracy Requirements for the Elementary Functions} @begin{Intro} In the strict mode, the performance of Numerics.Generic_Elementary_Functions shall be as specified here. @end{Intro} @begin{ImplReq} @Defn2{Term=[result interval], Sec=[for the evaluation of an elementary function]} @Defn2{Term=[maximum relative error], Sec=[for the evaluation of an elementary function]} When an exception is not raised, the result of evaluating a function in an instance @i{EF} of Numerics.Generic_Elementary_Functions belongs to a @i{result interval}, defined as the smallest model interval of @i{EF}.Float_Type that contains all the values of the form @RI{f} @Times (1.0 + @RI{d}), where @RI{f} is the exact value of the corresponding mathematical function at the given parameter values, @RI{d} is a real number, and @Abs[@RI{d}] is less than or equal to the function's @i{maximum relative error}. @IndexCheck{Overflow_Check} The function delivers a value that belongs to the result interval when both of its bounds belong to the safe range of @i{EF}.Float_Type; otherwise, @begin{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if @i{EF}.Float_Type'Machine_Overflows is True, the function either delivers a value that belongs to the result interval or raises Constraint_Error, signaling overflow; @Trailing@;if @i{EF}.Float_Type'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of an elementary function reference in overflow situations, when the Machine_Overflows attribute of the result type is False.} @end{Itemize} @Leading@;The maximum relative error exhibited by each function is as follows: @begin{Itemize} 2.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the Sqrt, Sin, and Cos functions; 4.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the Log, Exp, Tan, Cot, and inverse trigonometric functions; and 8.0 @Times @RI{EF}@R[.Float_Type'Model_Epsilon], in the case of the forward and inverse hyperbolic functions. @end{Itemize} The maximum relative error exhibited by the exponentiation operator, which depends on the values of the operands, is (4.0 + @Abs{@R[Right] @Times @Log(@R[Left])} / 32.0) @Times @RI{EF}@R[.Float_Type'Model_Epsilon]. The maximum relative error given above applies throughout the domain of the forward trigonometric functions when the Cycle parameter is specified. @Defn{angle threshold} When the Cycle parameter is omitted, the maximum relative error given above applies only when the absolute value of the angle parameter X is less than or equal to some implementation-defined @i{angle threshold}, which shall be at least @RI{EF}@R[.Float_@!Type'Machine_@!Radix] @+<@Floor(@RI{EF}@R[.Float_@!Type'Machine_@!Mantissa]/2)>. Beyond the angle threshold, the accuracy of the forward trigonometric functions is implementation defined. @ImplDef{The value of the @i{angle threshold}, within which certain elementary functions, complex arithmetic operations, and complex elementary functions yield results conforming to a maximum relative error bound.} @ImplDef{The accuracy of certain elementary functions for parameters beyond the angle threshold.} @begin{ImplNote} The angle threshold indirectly determines the amount of precision that the implementation has to maintain during argument reduction. @end{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The prescribed results specified in @RefSecNum{Elementary Functions} for certain functions at particular parameter values take precedence over the maximum relative error bounds; effectively, they narrow to a single value the result interval allowed by the maximum relative error bounds. Additional rules with a similar effect are given by @Chg{Version=[2],New=[],Old=[the ]}table @Chg{Version=[2],New=[G-1],Old=[below]} for the inverse trigonometric functions, at particular parameter values for which the mathematical result is possibly not a model number of @i{EF}.Float_Type (or is, indeed, even transcendental). In each table entry, the values of the parameters are such that the result lies on the axis between two quadrants; the corresponding accuracy rule, which takes precedence over the maximum relative error bounds, is that the result interval is the model interval of @i{EF}.Float_Type associated with the exact mathematical result given in the table. @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number (12) from original RM}>] @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} The last line of the table is meant to apply when @i{EF}.Float_Type'Signed_Zeros is False; the two lines just above it, when @i{EF}.Float_Type'Signed_Zeros is True and the parameter Y has a zero value with the indicated sign. @Table[Columns=<5>,Alignment=<AllCenter>,FirstColWidth=[2],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{@Chg{Version=[2],New=[Table G-1: ],Old=[]}Tightly Approximated Elementary Function Results}>, Headers=<@b{Function}@\@b{Value of X}@\@b{Value of Y}@\@b{Exact Result @*when Cycle @*Specified}@\@b{Exact Result @*when Cycle @*Omitted}>, Body=<Arcsin@\1.0@\n.a.@\Cycle/4.0@\@Pi/2.0 Arcsin@\@en@;1.0@\n.a.@\@en@R[Cycle]/4.0@\@en@Pi/2.0 Arccos@\0.0@\n.a.@\Cycle/4.0@\@Pi/2.0 Arccos@\@en@;1.0@\n.a.@\Cycle/2.0@\@Pi Arctan and Arccot@\0.0@\positive@\Cycle/4.0@\@Pi/2.0 Arctan and Arccot@\0.0@\negative@\@en@R[Cycle]/4.0@\@en@Pi/2.0 Arctan and Arccot@\negative@\+0.0@\Cycle/2.0@\@Pi Arctan and Arccot@\negative@\@en@;0.0@\@en@R[Cycle]/2.0@\@en@Pi@Last Arctan and Arccot@\negative@\0.0@\Cycle/2.0@\@Pi>] The amount by which the result of an inverse trigonometric function is allowed to spill over into a quadrant adjacent to the one corresponding to the principal branch, as given in @RefSecNum{Elementary Functions}, is limited. The rule is that the result belongs to the smallest model interval of @i{EF}.Float_Type that contains both boundaries of the quadrant corresponding to the principal branch. This rule also takes precedence over the maximum relative error bounds, effectively narrowing the result interval allowed by them. @Comment{For Ada 95 with Corr, table G-1 appears here} @Leading@;Finally, the following specifications also take precedence over the maximum relative error bounds: @begin{Itemize} The absolute value of the result of the Sin, Cos, and Tanh functions never exceeds one. The absolute value of the result of the Coth function is never less than one. The result of the Cosh function is never less than one. @end{Itemize} @end{ImplReq} @begin{ImplAdvice} The versions of the forward trigonometric functions without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter of 2.0*Numerics.Pi, since this will not provide the required accuracy in some portions of the domain. For the same reason, the version of Log without a Base parameter should not be implemented by calling the corresponding version with a Base parameter of Numerics.e. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For elementary functions, the forward trigonometric functions without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter. Log without a Base parameter should not be implemented by calling Log with a Base parameter.]}]} @end{ImplAdvice} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Elementary_Functions differs from Generic_Elementary_Functions as defined in ISO/IEC DIS 11430 (for Ada 83) in the following ways related to the accuracy specified for strict mode: @begin{Itemize} The maximum relative error bounds use the Model_Epsilon attribute instead of the Base'Epsilon attribute. The accuracy requirements are expressed in terms of result intervals that are model intervals. On the one hand, this facilitates the description of the required results in the presence of underflow; on the other hand, it slightly relaxes the requirements expressed in ISO/IEC DIS 11430. @end{Itemize} @end{DiffWord83} @LabeledSubClause{Performance Requirements for Random Number Generation} @begin{Intro} In the strict mode, the performance of Numerics.Float_Random and Numerics.Discrete_Random shall be as specified here. @end{Intro} @begin{ImplReq} Two different calls to the time-dependent Reset procedure shall reset the generator to different states, provided that the calls are separated in time by at least one second and not more than fifty years. The implementation's representations of generator states and its algorithms for generating random numbers shall yield a period of at least 2@+{31}@en@;2; much longer periods are desirable but not required. The implementations of Numerics.Float_Random.Random and Numerics.Discrete_Random.Random shall pass at least 85% of the individual trials in a suite of statistical tests. For Numerics.Float_Random, the tests are applied directly to the floating point values generated (i.e., they are not converted to integers first), while for Numerics.Discrete_Random they are applied to the generated values of various discrete types. Each test suite performs 6 different tests, with each test repeated 10 times, yielding a total of 60 individual trials. An individual trial is deemed to pass if the chi-square value (or other statistic) calculated for the observed counts or distribution falls within the range of values corresponding to the 2.5 and 97.5 percentage points for the relevant degrees of freedom (i.e., it shall be neither too high nor too low). For the purpose of determining the degrees of freedom, measurement categories are combined whenever the expected counts are fewer than 5. @begin{ImplNote} In the floating point random number test suite, the generator is reset to a time-dependent state at the beginning of the run. The test suite incorporates the following tests, adapted from D. E. Knuth, @i{The Art of Computer Programming, vol. 2: Seminumerical Algorithms.} In the descriptions below, the given number of degrees of freedom is the number before reduction due to any necessary combination of measurement categories with small expected counts; it is one less than the number of measurement categories. @begin{itemize} Proportional Distribution Test (a variant of the Equidistribution Test). The interval 0.0 .. 1.0 is partitioned into @RI{K} subintervals. @RI{K} is chosen randomly between 4 and 25 for each repetition of the test, along with the boundaries of the subintervals (subject to the constraint that at least 2 of the subintervals have a width of 0.001 or more). 5000 random floating point numbers are generated. The counts of random numbers falling into each subinterval are tallied and compared with the expected counts, which are proportional to the widths of the subintervals. The number of degrees of freedom for the chi-square test is @RI{K}@en@;1. Gap Test. The bounds of a range @RI{A} .. @RI{B}, with 0.0 @leq @RI{A} @Lt @RI{B} @leq 1.0, are chosen randomly for each repetition of the test, subject to the constraint that 0.2 @leq @RI{B}@en@RI{A} @leq 0.6. Random floating point numbers are generated until 5000 falling into the range @RI{A} .. @RI{B} have been encountered. Each of these 5000 is preceded by a @lquotes@;gap@rquotes@; (of length greater than or equal to 0) of consecutive random numbers not falling into the range @RI{A} .. @RI{B}. The counts of gaps of each length from 0 to 15, and of all lengths greater than 15 lumped together, are tallied and compared with the expected counts. Let @RI{P} = @RI{B}@en@RI{A}. The probability that a gap has a length of @RI{L} is (1@en@RI{P}) @+[@RI{L}] @Times @RI{P} for @RI{L} @leq 15, while the probability that a gap has a length of 16 or more is (1@en@RI{P}) @+[16]. The number of degrees of freedom for the chi-square test is 16. Permutation Test. 5000 tuples of 4 different random floating point numbers are generated. (An entire 4-tuple is discarded in the unlikely event that it contains any two exactly equal components.) The counts of each of the 4! = 24 possible relative orderings of the components of the 4-tuples are tallied and compared with the expected counts. Each of the possible relative orderings has an equal probability. The number of degrees of freedom for the chi-square test is 23. Increasing-Runs Test. Random floating point numbers are generated until 5000 increasing runs have been observed. An @lquotes@;increasing run@rquotes@; is a sequence of random numbers in strictly increasing order; it is followed by a random number that is strictly smaller than the preceding random number. (A run under construction is entirely discarded in the unlikely event that one random number is followed immediately by an exactly equal random number.) The decreasing random number that follows an increasing run is discarded and not included with the next increasing run. The counts of increasing runs of each length from 1 to 4, and of all lengths greater than 4 lumped together, are tallied and compared with the expected counts. The probability that an increasing run has a length of @RI{L} is 1/@RI{L}! @en 1/(@RI{L}+1)! for @RI{L} @leq 4, while the probability that an increasing run has a length of 5 or more is 1/5!. The number of degrees of freedom for the chi-square test is 4. Decreasing-Runs Test. The test is similar to the Increasing Runs Test, but with decreasing runs. Maximum-of-@RI{t} Test (with @RI{t} = 5). 5000 tuples of 5 random floating point numbers are generated. The maximum of the components of each 5-tuple is determined and raised to the 5th power. The uniformity of the resulting values over the range 0.0 .. 1.0 is tested as in the Proportional Distribution Test. @end{itemize} @end{ImplNote} @begin{ImplNote} In the discrete random number test suite, Numerics.Discrete_Random is instantiated as described below. The generator is reset to a time-dependent state after each instantiation. The test suite incorporates the following tests, adapted from D. E. Knuth (@i{op. cit.}) and other sources. The given number of degrees of freedom for the chi-square test is reduced by any necessary combination of measurement categories with small expected counts, as described above. @begin{Itemize} Equidistribution Test. In each repetition of the test, a number @RI{R} between 2 and 30 is chosen randomly, and Numerics.Discrete_Random is instantiated with an integer subtype whose range is 1 .. @RI{R}. 5000 integers are generated randomly from this range. The counts of occurrences of each integer in the range are tallied and compared with the expected counts, which have equal probabilities. The number of degrees of freedom for the chi-square test is @RI{R}@en@;1. Simplified Poker Test. Numerics.Discrete_Random is instantiated once with an enumeration subtype representing the 13 denominations (Two through Ten, Jack, Queen, King, and Ace) of an infinite deck of playing cards. 2000 @lquotes@;poker@rquotes@; hands (5-tuples of values of this subtype) are generated randomly. The counts of hands containing exactly @RI{K} different denominations (1 @leq @RI{K} @leq 5) are tallied and compared with the expected counts. The probability that a hand contains exactly @RI{K} different denominations is given by a formula in Knuth. The number of degrees of freedom for the chi-square test is 4. Coupon Collector's Test. Numerics.Discrete_Random is instantiated in each repetition of the test with an integer subtype whose range is 1 .. @RI{R}, where @RI{R} varies systematically from 2 to 11. Integers are generated randomly from this range until each value in the range has occurred, and the number @RI{K} of integers generated is recorded. This constitutes a @lquotes@;coupon collector's segment@rquotes@; of length @RI{K}. 2000 such segments are generated. The counts of segments of each length from @RI{R} to @RI{R}+29, and of all lengths greater than @RI{R}+29 lumped together, are tallied and compared with the expected counts. The probability that a segment has any given length is given by formulas in Knuth. The number of degrees of freedom for the chi-square test is 30. Craps Test (Lengths of Games). Numerics.Discrete_Random is instantiated once with an integer subtype whose range is 1 .. 6 (representing the six numbers on a die). 5000 craps games are played, and their lengths are recorded. (The length of a craps game is the number of rolls of the pair of dice required to produce a win or a loss. A game is won on the first roll if the dice show 7 or 11; it is lost if they show 2, 3, or 12. If the dice show some other sum on the first roll, it is called the @i{point}, and the game is won if and only if the point is rolled again before a 7 is rolled.) The counts of games of each length from 1 to 18, and of all lengths greater than 18 lumped together, are tallied and compared with the expected counts. For 2 @leq @RI{S} @leq 12, let @RI{D} @-{@RI{S}} be the probability that a roll of a pair of dice shows the sum @RI{S}, and let @RI{Q} @-[@RI{S}](@RI{L}) = @RI{D} @-[@RI{S}] @Times (1 @en (@RI{D} @-[@RI{S}] + @RI{D} @-[7])) @+[@RI{L}@en@;2] @Times (@RI{D} @-[@RI{S}] + @RI{D} @-[7]). Then, the probability that a game has a length of 1 is @RI{D} @-[7] + @RI{D} @-[11] + @RI{D} @-[2] + @RI{D} @-[3] + @RI{D} @-[12] and, for @RI{L} @Gt 1, the probability that a game has a length of @RI{L} is @RI{Q} @-[4](@RI{L}) + @RI{Q} @-[5](@RI{L}) + @RI{Q} @-[6](@RI{L}) + @RI{Q} @-[8](@RI{L}) + @RI{Q} @-[9](@RI{L}) + @RI{Q} @-[10](@RI{L}). The number of degrees of freedom for the chi-square test is 18. Craps Test (Lengths of Passes). This test is similar to the last, but enough craps games are played for 3000 losses to occur. A string of wins followed by a loss is called a @i{pass}, and its length is the number of wins preceding the loss. The counts of passes of each length from 0 to 7, and of all lengths greater than 7 lumped together, are tallied and compared with the expected counts. For @RI{L} @geq 0, the probability that a pass has a length of @RI{L} is @RI{W} @+[@RI{L}] @Times (1@en@RI{W}), where @RI{W}, the probability that a game ends in a win, is 244.0/495.0. The number of degrees of freedom for the chi-square test is 8. Collision Test. Numerics.Discrete_Random is instantiated once with an integer or enumeration type representing binary bits. 15 successive calls on the Random function are used to obtain the bits of a 15-bit binary integer between 0 and 32767. 3000 such integers are generated, and the number of collisions (integers previously generated) is counted and compared with the expected count. A chi-square test is not used to assess the number of collisions; rather, the limits on the number of collisions, corresponding to the 2.5 and 97.5 percentage points, are (from formulas in Knuth) 112 and 154. The test passes if and only if the number of collisions is in this range. @end{Itemize} @end{ImplNote} @end{ImplReq} @LabeledSubClause{Accuracy Requirements for Complex Arithmetic} @begin{Intro} In the strict mode, the performance of Numerics.Generic_@!Complex_Types and Numerics.Generic_@!Complex_@!Elementary_@!Functions shall be as specified here. @end{Intro} @begin{ImplReq} When an exception is not raised, the result of evaluating a real function of an instance @i{CT} of Numerics.Generic_Complex_Types (i.e., a function that yields a value of subtype @i{CT}.Real'Base or @i{CT}.Imaginary) belongs to a result interval defined as for a real elementary function (see @RefSecNum{Accuracy Requirements for the Elementary Functions}). @Defn2{Term=[result interval], Sec=[for a component of the result of evaluating a complex function]} When an exception is not raised, each component of the result of evaluating a complex function of such an instance, or of an instance of Numerics.Generic_Complex_Elementary_Functions obtained by instantiating the latter with @i{CT} (i.e., a function that yields a value of subtype @i{CT}.Complex), also belongs to a @i{result interval}. The result intervals for the components of the result are either defined by a @i{maximum relative error} bound or by a @i{maximum box error} bound. @Defn2{Term=[maximum relative error], Sec=[for a component of the result of evaluating a complex function]} When the result interval for the real (resp., imaginary) component is defined by maximum relative error, it is defined as for that of a real function, relative to the exact value of the real (resp., imaginary) part of the result of the corresponding mathematical function. @Defn2{Term=[maximum box error], Sec=[for a component of the result of evaluating a complex function]} When defined by maximum box error, the result interval for a component of the result is the smallest model interval of @i{CT}.Real that contains all the values of the corresponding part of @RI{f} @Times (1.0 + @RI{d}), where @RI{f} is the exact complex value of the corresponding mathematical function at the given parameter values, @RI{d} is complex, and @Abs{@RI{d}} is less than or equal to the given maximum box error. @IndexCheck{Overflow_Check} The function delivers a value that belongs to the result interval (or a value both of whose components belong to their respective result intervals) when both bounds of the result interval(s) belong to the safe range of @i{CT}.Real; otherwise, @begin{Discussion} The maximum relative error could be specified separately for each component, but we do not take advantage of that freedom here. @end{Discussion} @begin{Discussion} Note that @RI{f} @Times (1.0 + @RI{d}) defines a small circular region of the complex plane centered at @RI{f}, and the result intervals for the real and imaginary components of the result define a small rectangular box containing that circle. @end{Discussion} @begin{Reason} Box error is used when the computation of the result risks loss of significance in a component due to cancellation. @end{Reason} @begin{Ramification} The components of a complex function that exhibits bounded relative error in each component have to have the correct sign. In contrast, one of the components of a complex function that exhibits bounded box error may have the wrong sign, since the dimensions of the box containing the result are proportional to the modulus of the mathematical result and not to either component of the mathematical result individually. Thus, for example, the box containing the computed result of a complex function whose mathematical result has a large modulus but lies very close to the imaginary axis might well straddle that axis, allowing the real component of the computed result to have the wrong sign. In this case, the distance between the computed result and the mathematical result is, nevertheless, a small fraction of the modulus of the mathematical result. @end{Ramification} @begin{itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} if @i{CT}.Real'Machine_Overflows is True, the function either delivers a value that belongs to the result interval (or a value both of whose components belong to their respective result intervals) or raises Constraint_Error, signaling overflow; if @i{CT}.Real'Machine_Overflows is False, the result is implementation defined. @ImplDef{The result of a complex arithmetic operation or complex elementary function reference in overflow situations, when the Machine_Overflows attribute of the corresponding real type is False.} @end{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The error bounds for particular complex functions are tabulated @Chg{Version=[2],New=[in table G-2],Old=[below]}. In the table, the error bound is given as the coefficient of @i{CT}.Real'Model_Epsilon. @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number (7) from original RM}>] @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @Table[Columns=<4>,Alignment=<AllCenter>,FirstColWidth=[2],LastColWidth=[1], NoBreak=[T],Border=[T],SmallSize=[F], Caption=<@b{@Chg{Version=[2],New=[Table G-2: ],Old=[]}Error Bounds for Particular Complex Functions}>, Headers=<@b{Function or Operator}@\@b{Nature of @*Result}@\@b{Nature of @*Bound}@\@b{Error Bound}>, Body=<Modulus@\real@\max. rel. error@\3.0 Argument@\real@\max. rel. error@\4.0 Compose_From_Polar@\complex@\max. rel. error@\3.0 "*" (both operands complex)@\complex@\max. box error@\5.0 "/" (right operand complex)@\complex@\max. box error@\13.0 Sqrt@\complex@\max. rel. error@\6.0 Log@\complex@\max. box error@\13.0 Exp (complex parameter)@\complex@\max. rel. error@\7.0 Exp (imaginary parameter)@\complex@\max. rel. error@\2.0 Sin, Cos, Sinh, and Cosh@\complex@\max. rel. error@\11.0 Tan, Cot, Tanh, and Coth@\complex@\max. rel. error@\35.0 inverse trigonometric@\complex@\max. rel. error@\14.0@Last inverse hyperbolic@\complex@\max. rel. error@\14.0>] The maximum relative error given above applies throughout the domain of the Compose_From_Polar function when the Cycle parameter is specified. When the Cycle parameter is omitted, the maximum relative error applies only when the absolute value of the parameter Argument is less than or equal to the angle threshold (see @RefSecNum{Accuracy Requirements for the Elementary Functions}). For the Exp function, and for the forward hyperbolic (resp., trigonometric) functions, the maximum relative error given above likewise applies only when the absolute value of the imaginary (resp., real) component of the parameter X (or the absolute value of the parameter itself, in the case of the Exp function with a parameter of pure-imaginary type) is less than or equal to the angle threshold. For larger angles, the accuracy is implementation defined. @ImplDef{The accuracy of certain complex arithmetic operations and certain complex elementary functions for parameters (or components thereof) beyond the angle threshold.} @Comment{For Ada 95 with Corr, table G-2 appears here} @Leading@;The prescribed results specified in @RefSecNum{Complex Elementary Functions} for certain functions at particular parameter values take precedence over the error bounds; effectively, they narrow to a single value the result interval allowed by the error bounds for a component of the result. Additional rules with a similar effect are given below for certain inverse trigonometric and inverse hyperbolic functions, at particular parameter values for which a component of the mathematical result is transcendental. In each case, the accuracy rule, which takes precedence over the error bounds, is that the result interval for the stated result component is the model interval of @i{CT}.Real associated with the component's exact mathematical value. The cases in question are as follows: @begin{Itemize} When the parameter X has the value zero, the real (resp., imaginary) component of the result of the Arccot (resp., Arccoth) function is in the model interval of @i{CT}.Real associated with the value @Pi/2.0. When the parameter X has the value one, the real component of the result of the Arcsin function is in the model interval of @i{CT}.Real associated with the value @Pi/2.0. When the parameter X has the value @en@;1.0, the real component of the result of the Arcsin (resp., Arccos) function is in the model interval of @i{CT}.Real associated with the value @en@Pi/2.0 (resp., @Pi). @end{Itemize} @begin{Discussion} It is possible to give many other prescribed results in which a component of the parameter is restricted to a similar model interval when the parameter X is appropriately restricted to an easily testable portion of the domain. We follow the proposed ISO/IEC standard for Generic_Complex_Elementary_Functions (for Ada 83) in not doing so, however. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The amount by which a component of the result of an inverse trigonometric or inverse hyperbolic function is allowed to spill over into a quadrant adjacent to the one corresponding to the principal branch, as given in @RefSecNum{Complex Elementary Functions}, is limited. The rule is that the result belongs to the smallest model interval of @i{CT}.Real that contains both boundaries of the quadrant corresponding to the principal branch. This rule also takes precedence @Chg{Version=[2],New=[over],Old=[to]} the maximum error bounds, effectively narrowing the result interval allowed by them. Finally, the results allowed by the error bounds are narrowed by one further rule: The absolute value of each component of the result of the Exp function, for a pure-imaginary parameter, never exceeds one. @end{ImplReq} @begin{ImplAdvice} The version of the Compose_From_Polar function without a Cycle parameter should not be implemented by calling the corresponding version with a Cycle parameter of 2.0*Numerics.Pi, since this will not provide the required accuracy in some portions of the domain. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[For complex arithmetic, the Compose_From_Polar function without a Cycle parameter should not be implemented by calling Compose_From_Polar with a Cycle parameter.]}]} @end{ImplAdvice} @begin{DiffWord83} The semantics of Numerics.Generic_Complex_Types and Numerics.Generic_Complex_Elementary_Functions differs from Generic_Complex_Types and Generic_Complex_Elementary_Functions as defined in ISO/IEC CDs 13813 and 13814 (for Ada 83) in ways analogous to those identified for the elementary functions in @RefSecNum{Accuracy Requirements for the Elementary Functions}. In addition, we do not generally specify the signs of zero results (or result components), although those proposed standards do. @end{DiffWord83} @LabeledAddedClause{Version=[2],Name=[Vector and Matrix Manipulation]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Types and operations for the manipulation of real vectors and matrices are provided in Generic_Real_Arrays, which is defined in @RefSecNum[Real Vectors and Matrices]. Types and operations for the manipulation of complex vectors and matrices are provided in Generic_Complex_Arrays, which is defined in @RefSecNum[Complex Vectors and Matrices]. Both of these library units are generic children of the predefined package Numerics (see @RefSecNum[The Numerics Packages]). Nongeneric equivalents of these packages for each of the predefined floating point types are also provided as children of Numerics.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Vector and matrix manipulation is defined in the Numerics Annex, rather than in the core, because it is considered to be a specialized need of (some) numeric applications.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These packages provide facilities that are similar to and replace those found in ISO/IEC 13813:1998 @i{Information technology @em Programming languages @em Generic packages of real and complex type declarations and basic operations for Ada (including vector and matrix types)}. (The other facilities provided by that Standard were already provided in Ada 95.) In addition to the main facilities of that Standard, these packages also include subprograms for the solution of linear equations, matrix inversion, determinants, and the determination of the eigenvalues and eigenvectors of real symmetric matrices and Hermitian matrices.]} @end{Discussion} @end{Intro} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} This @Chg{Version=[3],New=[subclause],Old=[clause]} It just provides an introduction to the following subclauses.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Real Vectors and Matrices]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Numerics.Generic_Real_Arrays has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Real @key{is digits} <>; @key{package} Ada.Numerics.Generic_Real_Arrays @key{is}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_Real_Arrays]} @key{pragma} Pure(Generic_Real_Arrays);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Real_Vector} @key{is array} (Integer @key{range} <>) @key{of} Real'Base; @key{type} @AdaTypeDefn{Real_Matrix} @key{is array} (Integer @key{range} <>, Integer @key{range} <>) @key{of} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Real_Vector types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Real_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Left, Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Real_Vector) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Vector scaling operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Real_Vector) @key{return} Real_Vector; @key{function} "*" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector; @key{function} "/" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Other Real_Vector operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Vector} (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Subprograms for Real_Matrix types]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix arithmetic operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Transpose} (X : Real_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "*" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Real_Vector) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Real_Matrix) @key{return} Real_Vector; @key{function} "*" (Left : Real_Matrix; Right : Real_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix scaling operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "*" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix; @key{function} "/" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Real_Matrix inversion and related operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Solve} (A : Real_Matrix; X : Real_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Solve} (A, X : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Inverse} (A : Real_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Determinant} (A : Real_Matrix) @key{return} Real'Base;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Eigenvalues and vectors of a real symmetric matrix]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Eigenvalues} (A : Real_Matrix) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Eigensystem} (A : @key{in} Real_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Real_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Other Real_Matrix operations]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Matrix} (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Numerics.Generic_Real_Arrays;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Numerics],Child=[Real_@!Arrays]} The library package Numerics.Real_Arrays is declared pure and defines the same types and subprograms as Numerics.Generic_Real_Arrays, except that the predefined type Float is systematically substituted for Real'Base throughout. Nongeneric equivalents for each of the other predefined floating point types are defined similarly, with the names Numerics.Short_Real_Arrays, Numerics.Long_Real_Arrays, etc.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics, and to be consistent with other Numerics packages.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Two types are defined and exported by Numerics.Generic_Real_Arrays. The composite type Real_Vector is provided to represent a vector with components of type Real; it is defined as an unconstrained, one-dimensional array with an index of type Integer. The composite type Real_Matrix is provided to represent a matrix with components of type Real; it is defined as an unconstrained, two-dimensional array with indices of type Integer.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The effect of the various subprograms is as described below. In most cases the subprograms are described in terms of corresponding scalar operations of the type Real; any exception raised by those operations is propagated by the array operation. Moreover, the accuracy of the result for each individual component is as defined for the scalar operation unless stated otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[In the case of those operations which are defined to @i{involve an inner product}, Constraint_Error may be raised if an intermediate result is outside the range of Real'Base even though the mathematical final result would not be.@Defn2{Term=[involve an inner product],Sec=[real]}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Right : Real_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Right. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Real_Vector) @key{return} Real_Vector; @key{function} "-" (Left, Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Vector) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. This operation involves an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "@key{abs}" (Right : Real_Vector) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[This operation returns the L2-norm of Right (the square root of the inner product of the vector with itself).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Normalization of vectors is a frequent enough operation that it is useful to provide the norm as a basic operation. Furthermore, implementing the norm is not entirely straightforward, because the inner product might overflow while the final norm does not. An implementation cannot merely return Sqrt (X * X), it has to cope with a possible overflow of the inner product.]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While the definition is given in terms of an inner product, the norm doesn't @lquotes@;involve an inner product@rquotes@; in the technical sense. The reason is that it has accuracy requirements substantially different from those applicable to inner products; and that cancellations cannot occur, because all the terms are positive, so there is no possibility of intermediate overflow.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the scalar Left using the "*" operation of the type Real. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector; @key{function} "/" (Left : Real_Vector; Right : Real'Base) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and to the scalar Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a @i<unit vector>@Defn2{Term=[unit vector],Sec=[real vector]} with Order components and a lower bound of First. All components are set to 0.0 except for the Index component which is set to 1.0. Constraint_Error is raised if Index < First, Index > First + Order @en 1 or if First + Order @en 1 > Integer'Last.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Right. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Transpose (X : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the transpose of a matrix X. The first and second index ranges of the result are X'Range(2) and X'Range(1) respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Real_Matrix) @key{return} Real_Matrix; @key{function} "-" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Real_Vector) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the outer product of a (column) vector Left by a (row) vector Right using the operation "*" of the type Real for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Real_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the scalar Left using the "*" operation of the type Real. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix; @key{function} "/" (Left : Real_Matrix; Right : Real'Base) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation of the type Real to each component of Left and to the scalar Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A : Real_Matrix; X : Real_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a vector Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving a single set of linear equations. The index range of the result is A'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The text says that Y is such that @lquotes@;X is (nearly) equal to A * Y@rquotes rather than @lquotes@;X is equal to A * Y@rquotes because rounding errors may mean that there is no value of Y such that X is exactly equal to A * Y. On the other hand it does not mean that any old rough value will do. The algorithm given under @ImplAdviceTitle should be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The requirement to raise Constraint_Error if the matrix is ill-conditioned is really a reflection of what will happen if the matrix is ill-conditioned. See @ImplAdviceTitle. We do not make any attempt to define ill-conditioned formally.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These remarks apply to all versions of Solve and Inverse.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A, X : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving several sets of linear equations. The index ranges of the result are A'Range(2) and X'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length(1) are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Inverse (A : Real_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix B such that A * B is (nearly) equal to the unit matrix. The index ranges of the result are A'Range(2) and A'Range(1). Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Determinant (A : Real_Matrix) @key{return} Real'Base;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the determinant of the matrix A. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Eigenvalues(A : Real_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the eigenvalues of the symmetric matrix A as a vector sorted into order with the largest first. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index range of the result is A'Range(1). Argument_Error is raised if the matrix A is not symmetric.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Eigensystem(A : @key{in} Real_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Real_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0047-1]} @ChgAdded{Version=[2],Text=[This procedure computes both the eigenvalues and eigenvectors of the symmetric matrix A. The out parameter Values is the same as that obtained by calling the function Eigenvalues. The out parameter Vectors is a matrix whose columns are the eigenvectors of the matrix A. The order of the columns corresponds to the order of the eigenvalues. The eigenvectors are normalized and mutually orthogonal (they are orthonormal), including when there are repeated eigenvalues. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2)@Chg{Version=[3],New=[, or if Values'Range is not equal to A'Range(1), or if the],Old=[. The]} index ranges of the parameter Vectors are @Chg{Version=[3],New=[not equal to ],Old=[]}those of A. Argument_Error is raised if the matrix A is not symmetric.@Chg{Version=[3],New=[ Constraint_Error is also raised in implementation-defined circumstances if the algorithm used does not converge quickly enough.],Old=[]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[There is no requirement on the absolute direction of the returned eigenvectors. Thus they might be multiplied by -1. It is only the ratios of the components that matter. This is standard practice.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Matrix (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a square @i{unit matrix}@Defn2{Term=[unit matrix],Sec=[real matrix]} with Order**2 components and lower bounds of First_1 and First_2 (for the first and second index ranges respectively). All components are set to 0.0 except for the main diagonal, whose components are set to 1.0. Constraint_Error is raised if First_1 + Order @en 1 > Integer'Last or First_2 + Order @en 1 > Integer'Last.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem for type Real_Matrix.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For operations not involving an inner product, the accuracy requirements are those of the corresponding operations of the type Real in both the strict mode and the relaxed mode (see @RefSecNum{Numeric Performance Requirements}).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For operations involving an inner product, no requirements are specified in the relaxed mode. In the strict mode the modulus of the absolute error of the inner product @i<X>*@i<Y> shall not exceed @i<g>*@b<abs>(@i<X>)*@b<abs>(@i<Y>) where @i<g> is defined as]} @begin{Display} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i<g> = @i<X>'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa)]} @end{Display} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[For the L2-norm, no accuracy requirements are specified in the relaxed mode. In the strict mode the relative error on the norm shall not exceed @i<g> / 2.0 + 3.0 * Real'Model_Epsilon where @i<g> is defined as above.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is simply the combination of the error on the inner product with the error on Sqrt. A first order computation would lead to 2.0 * Real'Model_Epsilon above, but we are adding an extra Real'Model_Epsilon to account for higher order effects.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations shall document any techniques used to reduce cancellation errors such as extended precision arithmetic.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Any techniques used to reduce cancellation errors in Numerics.Generic_Real_Arrays shall be documented.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above accuracy requirement is met by the canonical implementation of the inner product by multiplication and addition using the corresponding operations of type Real'Base and performing the cumulative addition using ascending indices. Note however, that some hardware provides special operations for the computation of the inner product and although these may be fast they may not meet the accuracy requirement specified. See Accuracy and Stability of Numerical Algorithms By N J Higham (ISBN 0-89871-355-2), Section 3.1.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[Note moreover that the componentwise accuracy requirements are not met by subcubic methods for matrix multiplication such as that devised by Strassen. These methods, which are typically used for the fast multiplication of very large matrices (e.g. order more than a few thousands), have normwise accuracy properties. If it is desired to use such methods, then distinct subprograms should be provided (perhaps in a child package). See Section 22.2.2 in the above reference.]} @end{ImplNote} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[Implementations should implement the Solve and Inverse functions using established techniques such as LU decomposition with row interchanges followed by back and forward substitution. Implementations are recommended to refine the result by performing an iteration on the residuals; if this is done@Chg{Version=[3],New=[,],Old=[]} then it should be documented.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Solve and Inverse for Numerics.Generic_Real_Arrays should be implemented using established techniques such as LU decomposition and the result should be refined by an iteration on the residuals.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is not the intention that any special provision should be made to determine whether a matrix is ill-conditioned or not. The naturally occurring overflow (including division by zero) which will result from executing these functions with an ill-conditioned matrix and thus raise Constraint_Error is sufficient.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There isn't any advice for the implementation to document with this paragraph.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The test that a matrix is symmetric should be performed by using the equality operator to compare the relevant components.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The equality operator should be used to test that a matrix in Numerics.Generic_Real_Arrays is symmetric.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[An implementation should minimize the circumstances under which the algorithm used for Eigenvalues and Eigensystem fails to converge.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[An implementation should minimize the circumstances under which the algorithm used for Numerics.Generic_Real_Arrays.Eigenvalues and Numerics.Generic_Real_Arrays.Eigensystem fails to converge.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[J. H. Wilkinson is the acknowledged expert in this area. See for example Wilkinson, J. H., and Reinsch, C. , Linear Algebra , vol II of Handbook for Automatic Computation, Springer-Verlag, or Wilkinson, J. H., The Algebraic Eigenvalue Problem, Oxford University Press.]} @end{ImplNote} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Numerics.Generic_Real_Arrays and its nongeneric equivalents are new.]} @end{Extend95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected various accuracy and definition issues.]} @end{Diffword2005} @LabeledAddedSubClause{Version=[2],Name=[Complex Vectors and Matrices]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Numerics.Generic_Complex_Arrays has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Numerics.Generic_Real_Arrays, Ada.Numerics.Generic_Complex_Types; @key{generic} @key{with package} Real_Arrays @key{is new} Ada.Numerics.Generic_Real_Arrays (<>); @key{use} Real_Arrays; @key{with package} Complex_Types @key{is new} Ada.Numerics.Generic_Complex_Types (Real); @key{use} Complex_Types; @key{package} Ada.Numerics.Generic_Complex_Arrays @key{is}@ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Complex_@!Arrays]} @key{pragma} Pure(Generic_Complex_Arrays);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Complex_Vector} @key{is array} (Integer @key{range} <>) @key{of} Complex; @key{type} @AdaTypeDefn{Complex_Matrix} @key{is array} (Integer @key{range} <>, Integer @key{range} <>) @key{of} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Complex_Vector types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector selection, conversion and composition operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Re} (X : Complex_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Im} (X : Complex_Vector) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in out} Complex_Vector; Re : @key{in} Real_Vector); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in out} Complex_Vector; Im : @key{in} Real_Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modulus} (X : Complex_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Real_Vector @key{renames} Modulus; @key{function} @AdaSubDefn{Argument} (X : Complex_Vector) @key{return} Real_Vector; @key{function} @AdaSubDefn{Argument} (X : Complex_Vector; Cycle : Real'Base) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Vector; Cycle : Real'Base) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Conjugate} (X : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left, Right : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0047-1]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} @Chg{Version=[3],New=[Real'Base],Old=[Complex]};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Mixed Real_Vector and Complex_Vector arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "+" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Vector scaling operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Other Complex_Vector operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Vector} (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Subprograms for Complex_Matrix types}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix selection, conversion and composition operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Re} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Im} (X : Complex_Matrix) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Re} (X : @key{in out} Complex_Matrix; Re : @key{in} Real_Matrix); @key{procedure} @AdaSubDefn{Set_Im} (X : @key{in out} Complex_Matrix; Im : @key{in} Real_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re : Real_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Compose_From_Cartesian} (Re, Im : Real_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modulus} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Complex_Matrix) @key{return} Real_Matrix @key{renames} Modulus;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Argument} (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} @AdaSubDefn{Argument} (X : Complex_Matrix; Cycle : Real'Base) @key{return} Real_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Compose_From_Polar} (Modulus, Argument : Real_Matrix; Cycle : Real'Base) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Conjugate} (X : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Transpose} (X : Complex_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Complex_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Mixed Real_Matrix and Complex_Matrix arithmetic operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "+" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Real_Matrix; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Real_Vector) @key{return} Complex_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix scaling operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Complex; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "*" (Left : Real'Base; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Complex_Matrix inversion and related operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Solve} (A : Complex_Matrix; X : Complex_Vector) @key{return} Complex_Vector; @key{function} @AdaSubDefn{Solve} (A, X : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Inverse} (A : Complex_Matrix) @key{return} Complex_Matrix; @key{function} @AdaSubDefn{Determinant} (A : Complex_Matrix) @key{return} Complex;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Eigenvalues and vectors of a Hermitian matrix}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Eigenvalues}(A : Complex_Matrix) @key{return} Real_Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Eigensystem}(A : @key{in} Complex_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Complex_Matrix);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Other Complex_Matrix operations}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Unit_Matrix} (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Complex_Matrix;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Numerics.Generic_Complex_Arrays;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Numerics],Child=[Complex_@!Arrays]} The library package Numerics.Complex_Arrays is declared pure and defines the same types and subprograms as Numerics.Generic_Complex_Arrays, except that the predefined type Float is systematically substituted for Real'Base, and the Real_Vector and Real_Matrix types exported by Numerics.Real_Arrays are systematically substituted for Real_Vector and Real_Matrix, and the Complex type exported by Numerics.Complex_Types is systematically substituted for Complex, throughout. Nongeneric equivalents for each of the other predefined floating point types are defined similarly, with the names Numerics.Short_Complex_Arrays, Numerics.Long_Complex_Arrays, etc.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Two types are defined and exported by Numerics.Generic_Complex_Arrays. The composite type Complex_Vector is provided to represent a vector with components of type Complex; it is defined as an unconstrained one-dimensional array with an index of type Integer. The composite type Complex_Matrix is provided to represent a matrix with components of type Complex; it is defined as an unconstrained, two-dimensional array with indices of type Integer.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The effect of the various subprograms is as described below. In many cases they are described in terms of corresponding scalar operations in Numerics.Generic_Complex_Types. Any exception raised by those operations is propagated by the array subprogram. Moreover, any constraints on the parameters and the accuracy of the result for each individual component are as defined for the scalar operation.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[In the case of those operations which are defined to @i{involve an inner product}, Constraint_Error may be raised if an intermediate result has a component outside the range of Real'Base even though the final mathematical result would not.@Defn2{Term=[involve an inner product],Sec=[complex]}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[An inner product never involves implicit complex conjugation. If the product of a vector with the conjugate of another (or the same) vector is required, then this has to be stated explicitly by writing for example X * Conjugate(Y). This mimics the usual mathematical notation.]} @end{Discussion} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Re (X : Complex_Vector) @key{return} Real_Vector; @key{function} Im (X : Complex_Vector) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function returns a vector of the specified Cartesian components of X. The index range of the result is X'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Re (X : @key{in out} Complex_Vector; Re : @key{in} Real_Vector); @key{procedure} Set_Im (X : @key{in out} Complex_Vector; Im : @key{in} Real_Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each procedure replaces the specified (Cartesian) component of each of the components of X by the value of the matching component of Re or Im; the other (Cartesian) component of each of the components is unchanged. Constraint_Error is raised if X'Length is not equal to Re'Length or Im'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Cartesian (Re : Real_Vector) @key{return} Complex_Vector; @key{function} Compose_From_Cartesian (Re, Im : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a vector of Complex results (in Cartesian representation) formed from given vectors of Cartesian components; when only the real components are given, imaginary components of zero are assumed. The index range of the result is Re'Range. Constraint_Error is raised if Re'Length is not equal to Im'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Modulus (X : Complex_Vector) @key{return} Real_Vector; @key{function} "@key{abs}" (Right : Complex_Vector) @key{return} Real_Vector @key{renames} Modulus; @key{function} Argument (X : Complex_Vector) @key{return} Real_Vector; @key{function} Argument (X : Complex_Vector; Cycle : Real'Base) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function calculates and returns a vector of the specified polar components of X or Right using the corresponding function in numerics.@!generic_complex_types. The index range of the result is X'Range or Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Polar (Modulus, Argument : Real_Vector) @key{return} Complex_Vector; @key{function} Compose_From_Polar (Modulus, Argument : Real_Vector; Cycle : Real'Base) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a vector of Complex results (in Cartesian representation) formed from given vectors of polar components using the corresponding function in numerics.@!generic_complex_types on matching components of Modulus and Argument. The index range of the result is Modulus'Range. Constraint_Error is raised if Modulus'Length is not equal to Argument'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Right. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Conjugate (X : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the result of applying the appropriate function Conjugate in numerics.@!generic_complex_types to each component of X. The index range of the result is X'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left, Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. This operation involves an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0047-1]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "@key{abs}" (Right : Complex_Vector) @key{return} @Chg{Version=[3],New=[Real'Base],Old=[Complex]};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[This operation returns the Hermitian L2-norm of Right (the square root of the inner product of the vector with its conjugate).]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While the definition is given in terms of an inner product, the norm doesn't @lquotes@;involve an inner product@rquotes in the technical sense. The reason is that it has accuracy requirements substantially different from those applicable to inner products; and that cancellations cannot occur, because all the terms are positive, so there is no possibility of intermediate overflow.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "+" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "-" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index range of the result is Left'Range. Constraint_Error is raised if Left'Length is not equal to Right'Length.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the inner product of Left and Right. Constraint_Error is raised if Left'Length is not equal to Right'Length. These operations involve an inner product.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the complex number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Complex) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the vector Left and the complex number Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the real number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index range of the result is Right'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector; @key{function} "/" (Left : Complex_Vector; Right : Real'Base) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the vector Left and the real number Right. The index range of the result is Left'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Vector (Index : Integer; Order : Positive; First : Integer := 1) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a @i{unit vector}@Defn2{Term=[unit vector],Sec=[complex vector]} with Order components and a lower bound of First. All components are set to (0.0, 0.0) except for the Index component which is set to (1.0, 0.0). Constraint_Error is raised if Index < First, Index > First + Order @en 1, or if First + Order @en 1 > Integer'Last.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Re (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} Im (X : Complex_Matrix) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function returns a matrix of the specified Cartesian components of X. The index ranges of the result are those of X.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Re (X : @key{in out} Complex_Matrix; Re : @key{in} Real_Matrix); @key{procedure} Set_Im (X : @key{in out} Complex_Matrix; Im : @key{in} Real_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each procedure replaces the specified (Cartesian) component of each of the components of X by the value of the matching component of Re or Im; the other (Cartesian) component of each of the components is unchanged. Constraint_Error is raised if X'Length(1) is not equal to Re'Length(1) or Im'Length(1) or if X'Length(2) is not equal to Re'Length(2) or Im'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Cartesian (Re : Real_Matrix) @key{return} Complex_Matrix; @key{function} Compose_From_Cartesian (Re, Im : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a matrix of Complex results (in Cartesian representation) formed from given matrices of Cartesian components; when only the real components are given, imaginary components of zero are assumed. The index ranges of the result are those of Re. Constraint_Error is raised if Re'Length(1) is not equal to Im'Length(1) or Re'Length(2) is not equal to Im'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Modulus (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} "@key{abs}" (Right : Complex_Matrix) @key{return} Real_Matrix @key{renames} Modulus; @key{function} Argument (X : Complex_Matrix) @key{return} Real_Matrix; @key{function} Argument (X : Complex_Matrix; Cycle : Real'Base) @key{return} Real_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function calculates and returns a matrix of the specified polar components of X or Right using the corresponding function in numerics.@!generic_complex_types. The index ranges of the result are those of X or Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Compose_From_Polar (Modulus, Argument : Real_Matrix) @key{return} Complex_Matrix; @key{function} Compose_From_Polar (Modulus, Argument : Real_Matrix; Cycle : Real'Base) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each function constructs a matrix of Complex results (in Cartesian representation) formed from given matrices of polar components using the corresponding function in numerics.@!generic_complex_types on matching components of Modulus and Argument. The index ranges of the result are those of Modulus. Constraint_Error is raised if Modulus'Length(1) is not equal to Argument'Length(1) or Modulus'Length(2) is not equal to Argument'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Right. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Conjugate (X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the result of applying the appropriate function Conjugate in numerics.@!generic_complex_types to each component of X. The index ranges of the result are those of X.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Transpose (X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the transpose of a matrix X. The first and second index ranges of the result are X'Range(2) and X'Range(1) respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left, Right : Complex_Vector) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the outer product of a (column) vector Left by a (row) vector Right using the appropriate operation "*" in numerics.@!generic_complex_types for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Vector; Right : Complex_Matrix) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. This operation involves inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "+" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "+" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "-" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of Left and the matching component of Right. The index ranges of the result are those of Left. Constraint_Error is raised if Left'Length(1) is not equal to Right'Length(1) or Left'Length(2) is not equal to Right'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Complex_Matrix) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Matrix; Right : Real_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for matrix multiplication. The first and second index ranges of the result are Left'Range(1) and Right'Range(2) respectively. Constraint_Error is raised if Left'Length(2) is not equal to Right'Length(1). These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Vector) @key{return} Complex_Matrix; @key{function} "*" (Left : Complex_Vector; Right : Real_Vector) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the outer product of a (column) vector Left by a (row) vector Right using the appropriate operation "*" in numerics.@!generic_complex_types for computing the individual components. The first and second index ranges of the result are Left'Range and Right'Range respectively.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Vector; Right : Complex_Matrix) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Vector; Right : Real_Matrix) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for multiplication of a (row) vector Left by a matrix Right. The index range of the (row) vector result is Right'Range(2). Constraint_Error is raised if Left'Length is not equal to Right'Length(1). These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real_Matrix; Right : Complex_Vector) @key{return} Complex_Vector; @key{function} "*" (Left : Complex_Matrix; Right : Real_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation provides the standard mathematical operation for multiplication of a matrix Left by a (column) vector Right. The index range of the (column) vector result is Left'Range(1). Constraint_Error is raised if Left'Length(2) is not equal to Right'Length. These operations involve inner products.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex; Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the complex number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Complex) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the matrix Left and the complex number Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Real'Base; Right : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This operation returns the result of multiplying each component of Right by the real number Left using the appropriate operation "*" in numerics.@!generic_complex_types. The index ranges of the result are those of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "*" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix; @key{function} "/" (Left : Complex_Matrix; Right : Real'Base) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Each operation returns the result of applying the corresponding operation in numerics.@!generic_complex_types to each component of the matrix Left and the real number Right. The index ranges of the result are those of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A : Complex_Matrix; X : Complex_Vector) @key{return} Complex_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a vector Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving a single set of linear equations. The index range of the result is A'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The text says that Y is such that @lquotes@;X is (nearly) equal to A * Y@rquotes rather than @lquotes@;X is equal to A * Y@rquotes because rounding errors may mean that there is no value of Y such that X is exactly equal to A * Y. On the other hand it does not mean that any old rough value will do. The algorithm given under @ImplAdviceTitle should be followed.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The requirement to raise Constraint_Error if the matrix is ill-conditioned is really a reflection of what will happen if the matrix is ill-conditioned. See @ImplAdviceTitle. We do not make any attempt to define ill-conditioned formally.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These remarks apply to all versions of Solve and Inverse.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Solve (A, X : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix Y such that X is (nearly) equal to A * Y. This is the standard mathematical operation for solving several sets of linear equations. The index ranges of the result are A'Range(2) and X'Range(2). Constraint_Error is raised if A'Length(1), A'Length(2), and X'Length(1) are not equal. Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Inverse (A : Complex_Matrix) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a matrix B such that A * B is (nearly) equal to the unit matrix. The index ranges of the result are A'Range(2) and A'Range(1). Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). Constraint_Error is raised if the matrix A is ill-conditioned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Determinant (A : Complex_Matrix) @key{return} Complex;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the determinant of the matrix A. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Eigenvalues(A : Complex_Matrix) @key{return} Real_Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns the eigenvalues of the Hermitian matrix A as a vector sorted into order with the largest first. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2). The index range of the result is A'Range(1). Argument_Error is raised if the matrix A is not Hermitian.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A Hermitian matrix is one whose transpose is equal to its complex conjugate. The eigenvalues of a Hermitian matrix are always real. We only support this case because algorithms for solving the general case are inherently unstable.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Eigensystem(A : @key{in} Complex_Matrix; Values : @key{out} Real_Vector; Vectors : @key{out} Complex_Matrix);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0047-1]} @ChgAdded{Version=[2],Text=[This procedure computes both the eigenvalues and eigenvectors of the Hermitian matrix A. The out parameter Values is the same as that obtained by calling the function Eigenvalues. The out parameter Vectors is a matrix whose columns are the eigenvectors of the matrix A. The order of the columns corresponds to the order of the eigenvalues. The eigenvectors are mutually orthonormal, including when there are repeated eigenvalues. Constraint_Error is raised if A'Length(1) is not equal to A'Length(2)@Chg{Version=[3],New=[, or if Values'Range is not equal to A'Range(1), or if the],Old=[. The]} index ranges of the parameter Vectors are @Chg{Version=[3],New=[not equal to ],Old=[]}those of A. Argument_Error is raised if the matrix A is not Hermitian.@Chg{Version=[3],New=[ Constraint_Error is also raised in implementation-defined circumstances if the algorithm used does not converge quickly enough.],Old=[]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[There is no requirement on the absolute direction of the returned eigenvectors. Thus they might be multiplied by any complex number whose modulus is 1. It is only the ratios of the components that matter. This is standard practice.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Unit_Matrix (Order : Positive; First_1, First_2 : Integer := 1) @key{return} Complex_Matrix;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[This function returns a square @i{unit matrix}@Defn2{Term=[unit matrix],Sec=[complex matrix]} with Order**2 components and lower bounds of First_1 and First_2 (for the first and second index ranges respectively). All components are set to (0.0, 0.0) except for the main diagonal, whose components are set to (1.0, 0.0). Constraint_Error is raised if First_1 + Order @en 1 > Integer'Last or First_2 + Order @en 1 > Integer'Last.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The accuracy requirements for the subprograms Solve, Inverse, Determinant, Eigenvalues and Eigensystem for type Complex_Matrix.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[For operations not involving an inner product, the accuracy requirements are those of the corresponding operations of the type Real'Base and Complex in both the strict mode and the relaxed mode (see @RefSecNum{Numeric Performance Requirements}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[For operations involving an inner product, no requirements are specified in the relaxed mode. In the strict mode the modulus of the absolute error of the inner product @i{X}*@i{Y} shall not exceed @i{g}*@key{abs}(@i{X})*@key{abs}(@i{Y}) where @i{g} is defined as]} @begin{Display} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{g} = @i{X}'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa) for mixed complex and real operands]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@i{g} = sqrt(2.0) * @i{X}'Length * Real'Machine_Radix**(1 @en@; Real'Model_Mantissa) for two complex operands]} @end{Display} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00418-01]} @ChgAdded{Version=[2],Text=[For the L2-norm, no accuracy requirements are specified in the relaxed mode. In the strict mode the relative error on the norm shall not exceed @i<g> / 2.0 + 3.0 * Real'Model_Epsilon where @i<g> has the definition appropriate for two complex operands.]} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations shall document any techniques used to reduce cancellation errors such as extended precision arithmetic.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Any techniques used to reduce cancellation errors in Numerics.Generic_Complex_Arrays shall be documented.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above accuracy requirement is met by the canonical implementation of the inner product by multiplication and addition using the corresponding operations of type Complex and performing the cumulative addition using ascending indices. Note however, that some hardware provides special operations for the computation of the inner product and although these may be fast they may not meet the accuracy requirement specified. See Accuracy and Stability of Numerical Algorithms by N J Higham (ISBN 0-89871-355-2), Sections 3.1 and 3.6.]} @end{ImplNote} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Although many operations are defined in terms of operations from numerics.@!generic_complex_types, they need not be implemented by calling those operations provided that the effect is the same.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[Implementations should implement the Solve and Inverse functions using established techniques. Implementations are recommended to refine the result by performing an iteration on the residuals; if this is done@Chg{Version=[3],New=[,],Old=[]} then it should be documented.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Solve and Inverse for Numerics.Generic_Complex_Arrays should be implemented using established techniques and the result should be refined by an iteration on the residuals.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[It is not the intention that any special provision should be made to determine whether a matrix is ill-conditioned or not. The naturally occurring overflow (including division by zero) which will result from executing these functions with an ill-conditioned matrix and thus raise Constraint_Error is sufficient.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There isn't any advice for the implementation to document with this paragraph.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[The test that a matrix is Hermitian should use the equality operator to compare the real components and negation followed by equality to compare the imaginary components (see @RefSecNum{Model of Floating Point Arithmetic}).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The equality and negation operators should be used to test that a matrix is Hermitian.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[An implementation should minimize the circumstances under which the algorithm used for Eigenvalues and Eigensystem fails to converge.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[An implementation should minimize the circumstances under which the algorithm used for Numerics.Generic_Complex_Arrays.Eigenvalues and Numerics.Generic_Complex_Arrays.Eigensystem fails to converge.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[J. H. Wilkinson is the acknowledged expert in this area. See for example Wilkinson, J. H., and Reinsch, C. , Linear Algebra , vol II of Handbook for Automatic Computation, Springer-Verlag, or Wilkinson, J. H., The Algebraic Eigenvalue Problem, Oxford University Press.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[Implementations should not perform operations on mixed complex and real operands by first converting the real operand to complex. See @RefSecNum{Complex Types}.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Mixed real and complex operations should not be performed by converting the real operand to complex.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00296-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Numerics.Generic_Complex_Arrays and its nongeneric equivalents are new.@Comment{ It would be better if this was called "Ada.Numerics.Generic_Imitation_Arrays", 'cause that's the opposite of Real. :-) Just checking if anyone reads this stuff.}]} @end{Extend95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0047-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected various accuracy and definition issues.]} @end{Diffword2005} ��������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/obsolescent.mss������������������������������������������������������0000755�0001752�0001001�00000225345�12066652507�020505� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(obsolescent, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledNormativeAnnex{Obsolescent Features} @Comment{$Source: e:\\cvsroot/ARM/Source/obsolescent.mss,v $} @Comment{$Revision: 1.58 $} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00368-01]} @Redundant[@Defn{obsolescent feature} This Annex contains descriptions of features of the language whose functionality is largely redundant with other features defined by this International Standard. Use of these features is not recommended in newly written programs. @Chg{Version=[2],New=[Use of these features can be prevented by using pragma Restrictions (No_Obsolescent_Features), see @RefSecNum{Language-Defined Restrictions and Profiles}.], Old=[]}] @begin{Ramification} These features are still part of the language, and have to be implemented by conforming implementations. The primary reason for putting these descriptions here is to get redundant features out of the way of most readers. The designers of the next version of Ada@Chg{Version=[2],New=[], Old=[ after Ada 95]} will have to assess whether or not it makes sense to drop these features from the language. @end{Ramification} @end{Intro} @begin{DiffWord83} @Leading@;The following features have been removed from the language, rather than declared to be obsolescent: @begin{Itemize} The package Low_Level_IO (see @RefSecNum{Input-Output}). The Epsilon, Mantissa, Emax, Small, Large, Safe_Emax, Safe_Small, and Safe_Large attributes of floating point types (see @RefSecNum{Attributes of Floating Point Types}). @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00284-02]} @ChgDeleted{Version=[2],Text=[The pragma Interface (see @RefSecNum{Interfacing Aspects}).]} The pragmas System_Name, Storage_Unit, and Memory_Size (see @RefSecNum{The Package System}). The pragma Shared (see @RefSecNum{Shared Variable Control}). @end{Itemize} Implementations can continue to support the above features for upward compatibility. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00368-01]} @ChgAdded{Version=[2],Text=[A mention of the No_Obsolescent_Features restriction was added.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} Controlled has been removed from the language, rather than declared to be obsolescent. No existing implementation gives it any effect. An implementation could continue to support the pragma as an implementation-defined pragma for upward compatibility.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[3],New=[Renamings of Library Units], Old=[Renamings of Ada 83 Library Units]} @begin{StaticSem} The following @nt{library_unit_renaming_declaration}s exist: @begin{Example} @key[with] Ada.Unchecked_Conversion; @key[generic] @key[function] Unchecked_Conversion @key[renames] Ada.Unchecked_Conversion; @key[with] Ada.Unchecked_Deallocation; @key[generic] @key[procedure] Unchecked_Deallocation @key[renames] Ada.Unchecked_Deallocation; @key[with] Ada.Sequential_IO; @key[generic] @key[package] Sequential_IO @key[renames] Ada.Sequential_IO; @key[with] Ada.Direct_IO; @key[generic] @key[package] Direct_IO @key[renames] Ada.Direct_IO; @key[with] Ada.Text_IO; @key[package] Text_IO @key[renames] Ada.Text_IO; @key[with] Ada.IO_Exceptions; @key[package] IO_Exceptions @key[renames] Ada.IO_Exceptions; @key[with] Ada.Calendar; @key[package] Calendar @key[renames] Ada.Calendar; @key[with] System.Machine_Code; @key[package] Machine_Code @key[renames] System.Machine_Code; --@RI{ If supported.} @end{Example} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1]} @ChgAdded{Version=[3],Text=[These library units correspond to those declared in Ada 83, which did not have the child unit concept or the parent package Ada.]} @end{Discussion} @end{StaticSem} @begin{ImplReq} The implementation shall allow the user to replace these renamings. @end{ImplReq} @LabeledClause{Allowed Replacements of Characters} @begin{Syntax} @begin{SyntaxText} @Leading@;The following replacements are allowed for the vertical line, number sign, and quotation mark characters: @begin{Itemize} A vertical line character (|) can be replaced by an exclamation mark (!) where used as a delimiter. The number sign characters (#) of a @nt{based_literal} can be replaced by colons (:) provided that the replacement is done for both occurrences. @begin{Honest} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The intent is that such a replacement works in the Value@Chg{Version=[2],New=[,],Old=[ and]} Wide_Value@Chg{Version=[2],New=[, and Wide_Wide_Value],Old=[]} attributes, and in the Get procedures of Text_IO@Chg{Version=[2],New=[ (and Wide_Text_IO and Wide_Wide_Text_IO as well)],Old=[]}}, so that things like @lquotes@;16:.123:@rquotes@; is acceptable. @end{Honest} The quotation marks (") used as string brackets at both ends of a string literal can be replaced by percent signs (%) provided that the enclosed sequence of characters contains no quotation mark, and provided that both string brackets are replaced. Any percent sign within the sequence of characters shall then be doubled and each such doubled percent sign is interpreted as a single percent sign character value. @end{Itemize} These replacements do not change the meaning of the program. @begin{Reason} The original purpose of this feature was to support hardware (for example, teletype machines) that has long been obsolete. The feature is no longer necessary for that reason. Another use of the feature has been to replace the vertical line character (|) when using certain hardware that treats that character as a (non-English) letter. The feature is no longer necessary for that reason, either, since Ada 95 has full support for international character sets. Therefore, we believe this feature is no longer necessary. Users of equipment that still uses | to represent a letter will continue to do so. Perhaps by next the time Ada is revised, such equipment will no longer be in use. @Leading@;Note that it was never legal to use this feature as a convenient method of including double quotes in a string without doubling them @em the string literal: @begin{Example} %"This is quoted."% @end{Example} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} is not legal in Ada @Chg{Version=[3],New=[(and never was legal)],Old=[83, nor will it be in Ada 95]}. One has to write: @begin{Example} """This is quoted.""" @end{Example} @end{Reason} @end{SyntaxText} @end{Syntax} @LabeledClause{Reduced Accuracy Subtypes} @begin{Intro} A @nt<digits_constraint> may be used to define a floating point subtype with a new value for its requested decimal precision, as reflected by its Digits attribute. Similarly, a @nt<delta_constraint> may be used to define an ordinary fixed point subtype with a new value for its @i(delta), as reflected by its Delta attribute. @begin(Discussion) It might be more direct to make these attributes specifiable via an @nt<attribute_definition_clause>, and eliminate the syntax for these @ntf<_constraint>s. @end(Discussion) @end{Intro} @begin{Syntax} @Syn{lhs=<delta_constraint>, rhs="@key{delta} @SynI{static_}@Syn2{expression} [@Syn2{range_constraint}]"} @end{Syntax} @begin{Resolution} @PDefn2{Term=[expected type], Sec=(delta_constraint expression)} The @nt<expression> of a @nt<delta_constraint> is expected to be of any real type. @end{Resolution} @begin{Legality} The @nt<expression> of a @nt<delta_constraint> shall be static. For a @nt<subtype_indication> with a @nt<delta_constraint>, the @nt<subtype_mark> shall denote an ordinary fixed point subtype. @Defn{notwithstanding} For a @nt<subtype_indication> with a @nt<digits_constraint>, the @nt<subtype_mark> shall denote either a decimal fixed point subtype or a floating point subtype (notwithstanding the rule given in @RefSecNum(Fixed Point Types) that only allows a decimal fixed point subtype). @begin(Discussion) @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00114-01]} @ChgDeleted{Version=[2],Text=[We may need a better way to deal with obsolescent features with rules that contradict those of the nonobsolescent parts of the standard.]} @end(Discussion) @end{Legality} @begin{StaticSem} A @nt<subtype_indication> with a @nt<subtype_mark> that denotes an ordinary fixed point subtype and a @nt<delta_constraint> defines an ordinary fixed point subtype with a @i(delta) given by the value of the @nt<expression> of the @nt<delta_constraint>. If the @nt<delta_constraint> includes a @nt<range_@!constraint>, then the ordinary fixed point subtype is constrained by the @nt<range_@!constraint>. A @nt<subtype_indication> with a @nt<subtype_mark> that denotes a floating point subtype and a @nt<digits_constraint> defines a floating point subtype with a requested decimal precision (as reflected by its Digits attribute) given by the value of the @nt<expression> of the @nt<digits_constraint>. If the @nt<digits_constraint> includes a @nt<range_@!constraint>, then the floating point subtype is constrained by the @nt<range_@!constraint>. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[compatibility], Sec=(delta_constraint with an ordinary fixed point subtype)} A @nt<delta_constraint> is @i(compatible) with an ordinary fixed point subtype if the value of the @nt<expression> is no less than the @i(delta) of the subtype, and the @nt<range_constraint>, if any, is compatible with the subtype. @PDefn2{Term=[compatibility], Sec=(digits_constraint with a floating point subtype)} A @nt<digits_constraint> is @i(compatible) with a floating point subtype if the value of the @nt<expression> is no greater than the requested decimal precision of the subtype, and the @nt<range_constraint>, if any, is compatible with the subtype. @PDefn2{Term=[elaboration], Sec=(delta_constraint)} The elaboration of a @nt<delta_constraint> consists of the elaboration of the @nt<range_constraint>, if any. @begin{Reason} A numeric subtype is considered @lquotes@;constrained@rquotes@; only if a range constraint applies to it. The only effect of a @nt<digits_constraint> or a @nt<delta_constraint> without a @nt<range_constraint> is to specify the value of the corresponding Digits or Delta attribute in the new subtype. The set of values of the subtype is not @lquotes@;constrained@rquotes@; in any way by such @ntf<_constraint>s. @end{Reason} @end{RunTime} @begin{DiffWord83} In Ada 83, a @nt<delta_constraint> is called a fixed_point_constraint, and a @nt<digits_constraint> is called a floating_point_constraint. We have adopted other terms because @nt<digits_constraint>s apply primarily to decimal fixed point types now (they apply to floating point types only as an obsolescent feature). @end{DiffWord83} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{The Constrained Attribute} @begin{StaticSem} @Leading@;For every private subtype S, the following attribute is defined: @begin{Discussion} This includes generic formal private subtypes. @end{Discussion} @begin{Description} S'@attr{Constrained}@\Yields the value False if S denotes an unconstrained nonformal private subtype with discriminants; also yields the value False if S denotes a generic formal private subtype, and the associated actual subtype is either an unconstrained subtype with discriminants or an unconstrained array subtype; yields the value True otherwise. The value of this attribute is of the predefined subtype Boolean. @begin{Reason} Because Ada 95 has @nt{unknown_discriminant_part}s, the Constrained attribute of private subtypes is obsolete. This is fortunate, since its Ada 83 definition was confusing, as explained below. Because this attribute is obsolete, we do not bother to extend its definition to private extensions. The Constrained attribute of an object is @i(not) obsolete. Note well: S'Constrained matches the Ada 95 definition of @lquotes@;constrained@rquotes@; only for composite subtypes. For elementary subtypes, S'Constrained is always true, whether or not S is constrained. (The Constrained attribute of an object does not have this problem, as it is only defined for objects of a discriminated type.) So one should think of its designator as being 'Constrained_Or_Elementary. @end{Reason} @end{Description} @end{StaticSem} @LabeledClause{ASCII} @begin{StaticSem} @Leading@;The following declaration exists in the declaration of package Standard: @begin{example} @key[package] ASCII @key[is] --@RI{ Control characters:} @tabclear()@tabset(P47) NUL : @key[constant] Character := @RI{nul}; @\SOH : @key[constant] Character := @RI{soh}; STX : @key[constant] Character := @RI{stx}; @\ETX : @key[constant] Character := @RI{etx}; EOT : @key[constant] Character := @RI{eot}; @\ENQ : @key[constant] Character := @RI{enq}; ACK : @key[constant] Character := @RI{ack}; @\BEL : @key[constant] Character := @RI{bel}; BS : @key[constant] Character := @RI{bs}; @\HT : @key[constant] Character := @RI{ht}; LF : @key[constant] Character := @RI{lf}; @\VT : @key[constant] Character := @RI{vt}; FF : @key[constant] Character := @RI{ff}; @\CR : @key[constant] Character := @RI{cr}; SO : @key[constant] Character := @RI{so}; @\SI : @key[constant] Character := @RI{si}; DLE : @key[constant] Character := @RI{dle}; @\DC1 : @key[constant] Character := @RI{dc1}; DC2 : @key[constant] Character := @RI{dc2}; @\DC3 : @key[constant] Character := @RI{dc3}; DC4 : @key[constant] Character := @RI{dc4}; @\NAK : @key[constant] Character := @RI{nak}; SYN : @key[constant] Character := @RI{syn}; @\ETB : @key[constant] Character := @RI{etb}; CAN : @key[constant] Character := @RI{can}; @\EM : @key[constant] Character := @RI{em}; SUB : @key[constant] Character := @RI{sub}; @\ESC : @key[constant] Character := @RI{esc}; FS : @key[constant] Character := @RI{fs}; @\GS : @key[constant] Character := @RI{gs}; RS : @key[constant] Character := @RI{rs}; @\US : @key[constant] Character := @RI{us}; DEL : @key[constant] Character := @RI{del}; --@RI{ Other characters:} Exclam : @key[constant] Character:= '!';@\Quotation : @key[constant] Character:= '"'; Sharp : @key[constant] Character:= '#';@\Dollar : @key[constant] Character:= '$'; Percent : @key[constant] Character:= '%';@\Ampersand : @key[constant] Character:= '&'; Colon : @key[constant] Character:= ':';@\Semicolon : @key[constant] Character:= ';'; Query : @key[constant] Character:= '?';@\At_Sign : @key[constant] Character:= '@@'; L_Bracket: @key[constant] Character:= '[';@\Back_Slash: @key[constant] Character:= '\'; R_Bracket: @key[constant] Character:= ']';@\Circumflex: @key[constant] Character:= '^'; Underline: @key[constant] Character:= '_';@\Grave : @key[constant] Character:= '`'; L_Brace : @key[constant] Character:= '{';@\Bar : @key[constant] Character:= '|'; R_Brace : @key[constant] Character:= '}';@\Tilde : @key[constant] Character:= '~'; --@RI{ Lower case letters:} LC_A: @key[constant] Character:= 'a'; ... LC_Z: @key[constant] Character:= 'z'; @key[end] ASCII; @end{example} @end{StaticSem} @LabeledClause{Numeric_Error} @begin{StaticSem} @Leading@;The following declaration exists in the declaration of package Standard: @begin{Example} Numeric_Error : @key[exception] @key[renames] Constraint_Error; @end{Example} @begin{Discussion} This is true even though it is not shown in @RefSecNum{The Package Standard}. @end{Discussion} @begin{Reason} In Ada 83, it was unclear which situations should raise Numeric_Error, and which should raise Constraint_Error. The permissions of RM83-11.6 could often be used to allow the implementation to raise Constraint_Error in a situation where one would normally expect Numeric_Error. To avoid this confusion, all situations that raise Numeric_Error in Ada 83 are changed to raise Constraint_Error in Ada 95. Numeric_Error is changed to be a renaming of Constraint_Error to avoid most of the upward compatibilities associated with this change. In new code, Constraint_Error should be used instead of Numeric_Error. @end{Reason} @end{StaticSem} @LabeledClause{At Clauses} @begin{Syntax} @Syn{lhs=<at_clause>,rhs="@key{for} @Syn2{direct_name} @key{use} @key{at} @Syn2{expression};"} @end{Syntax} @begin{StaticSem} An @nt{at_clause} of the form @lquotes@;for @i{x} use at @i{y};@rquotes@; is equivalent to an @nt{attribute_definition_clause} of the form @lquotes@;for @i{x}'Address use @i{y};@rquotes@;. @begin{Reason} The preferred syntax for specifying the address of an entity is an @nt{attribute_definition_clause} specifying the Address attribute. Therefore, the special-purpose @nt{at_clause} syntax is now obsolete. The above equivalence implies, for example, that only one @nt{at_clause} is allowed for a given entity. Similarly, it is illegal to give both an @nt{at_clause} and an @nt{attribute_definition_clause} specifying the Address attribute. @end{Reason} @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} We now allow to define the address of an entity using an @nt{attribute_definition_clause}. This is because Ada 83's @nt{at_clause} is so hard to remember: programmers often tend to write @lquotes@;for X'Address use...;@rquotes@;. @end{Extend83} @begin{DiffWord83} Ada 83's @ntf{address_clause} is now called an @nt{at_clause} to avoid confusion with the new term @lquotes@;Address clause@rquotes@; (that is, an @nt{attribute_definition_clause} for the Address attribute). @end{DiffWord83} @LabeledSubClause{Interrupt Entries} @begin{Intro} @redundant[Implementations are permitted to allow the attachment of task entries to interrupts via the address clause. Such an entry is referred to as an @i{interrupt entry}. The address of the task entry corresponds to a hardware interrupt in an implementation-defined manner. (See Ada.Interrupts.Reference in @RefSecNum{The Package Interrupts}.)] @end{Intro} @begin{StaticSem} @Leading@;The following attribute is defined: @Leading@;For any task entry X: @begin{Description} @Defn{interrupt entry} X'@attr{Address} @\For a task entry whose address is specified (an @i{interrupt entry}), the value refers to the corresponding hardware interrupt. For such an entry, as for any other task entry, the meaning of this value is implementation defined. The value of this attribute is of the type of the subtype System.Address. @NoPrefix@;@PDefn2{Term=[specifiable], Sec=(of Address for entries)} Address may be specified for single entries via an @nt{attribute_definition_clause}. @begin{Reason} Because of the equivalence of @nt{at_clause}s and @nt{attribute_definition_clause}s, an interrupt entry may be specified via either notation. @end{Reason} @end{Description} @end{StaticSem} @begin{RunTime} @PDefn2{Term=[initialization], Sec=[of a task object]} As part of the initialization of a task object, the address clause for an interrupt entry is elaborated@Redundant[, which evaluates the @nt<expression> of the address clause]. A check is made that the address specified is associated with some interrupt to which a task entry may be attached. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If this check fails, Program_Error is raised. Otherwise, the interrupt entry is attached to the interrupt associated with the specified address. @PDefn2{Term=[finalization], Sec=[of a task object]} Upon finalization of the task object, the interrupt entry, if any, is detached from the corresponding interrupt and the default treatment is restored. While an interrupt entry is attached to an interrupt, the interrupt is reserved (see @RefSecNum{Interrupt Support}). An interrupt delivered to a task entry acts as a call to the entry issued by a hardware task whose priority is in the System.Interrupt_Priority range. It is implementation defined whether the call is performed as an ordinary entry call, a timed entry call, or a conditional entry call; which kind of call is performed can depend on the specific interrupt. @end{RunTime} @begin{Bounded} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to evaluate E'Caller (see @RefSecNum(The Package Task_Identification)) in an @nt{accept_statement} for an interrupt entry. The possible effects are the same as for calling Current_Task from an entry body. @end{Bounded} @begin{DocReq} The implementation shall document to which interrupts a task entry may be attached. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The interrupts to which a task entry may be attached.]}]} The implementation shall document whether the invocation of an interrupt entry has the effect of an ordinary entry call, conditional call, or a timed call, and whether the effect varies in the presence of pending interrupts. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The type of entry call invoked for an interrupt entry.]}]} @end{DocReq} @begin{ImplPerm} The support for this subclause is optional. Interrupts to which the implementation allows a task entry to be attached may be designated as reserved for the entire duration of program execution@Redundant[; that is, not just when they have an interrupt entry attached to them]. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} Interrupt entry calls may be implemented by having the hardware execute directly the appropriate @Chg{New=[@nt{accept_statement}],Old=[accept body]}. Alternatively, the implementation is allowed to provide an internal interrupt handler to simulate the effect of a normal task calling the entry. The implementation is allowed to impose restrictions on the specifications and bodies of tasks that have interrupt entries. It is implementation defined whether direct calls (from the program) to interrupt entries are allowed. If a @nt{select_statement} contains both a @nt{terminate_alternative} and an @nt{accept_alternative} for an interrupt entry, then an implementation is allowed to impose further requirements for the selection of the @nt{terminate_alternative} in addition to those given in @RefSecNum{Task Dependence - Termination of Tasks}. @end{ImplPerm} @begin{Notes} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} Queued interrupts correspond to ordinary entry calls. Interrupts that are lost if not immediately processed correspond to conditional entry calls. It is a consequence of the priority rules that an @Chg{New=[@nt{accept_statement}], Old=[accept body]} executed in response to an interrupt can be executed with the active priority at which the hardware generates the interrupt, taking precedence over lower priority tasks, without a scheduling action. Control information that is supplied upon an interrupt can be passed to an associated interrupt entry as one or more parameters of mode @key[in]. @end{Notes} @begin{Examples} @leading@keepnext@i{Example of an interrupt entry:} @begin{example} @key[task] Interrupt_Handler @key[is] @key[entry] Done; @key[for] Done'Address @key[use] Ada.Interrupts.Reference(Ada.Interrupts.Names.Device_Done); @key[end] Interrupt_Handler; @end{example} @end{Examples} @begin{DiffWord83} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} RM83-13.5.1 did not adequately address the problems @Chg{Version=[2],New=[associated],Old=[associate]} with interrupts. This feature is now obsolescent and is replaced by the Ada 95 interrupt model as specified in the Systems Programming Annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0077],ARef=[AI95-00111-01]} @Chg{Version=[2],New=[@b<Corrigendum:> The undefined term @i{accept body} was replaced by @nt{accept_statement}.], Old=[]} @end{DiffWord95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Mod Clauses} @begin{Syntax} @Syn{lhs=<mod_clause>,rhs="@key{at} @key{mod} @SynI{static_}@Syn2{expression};"} @end{Syntax} @begin{StaticSem} @leading@keepnext@;A @nt{record_representation_clause} of the form: @begin{example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @key[for] @RI{r} @key[use] @key[record] @key[at] @key[mod] @RI{a}@Chg{Version=[3],New=[;],Old=[]} ... @key[end] @key[record]; @end{example} @leading@keepnext@;is equivalent to: @begin{example} @key[for] @RI{r}'Alignment @key[use] @RI{a}; @key[for] @RI{r} @key[use] @key[record] ... @key[end] @key[record]; @end{example} @begin{Reason} The preferred syntax for specifying the alignment of an entity is an @nt{attribute_definition_clause} specifying the Alignment attribute. Therefore, the special-purpose @nt{mod_clause} syntax is now obsolete. The above equivalence implies, for example, that it is illegal to give both a @nt{mod_clause} and an @nt{attribute_definition_clause} specifying the Alignment attribute for the same type. @end{Reason} @end{StaticSem} @begin{DiffWord83} Ada 83's @ntf{alignment_clause} is now called a @nt{mod_clause} to avoid confusion with the new term @lquotes@;Alignment clause@rquotes@; (that is, an @nt{attribute_definition_clause} for the Alignment attribute). @end{DiffWord83} @LabeledClause{The Storage_Size Attribute} @begin{StaticSem} @Leading@;For any task subtype T, the following attribute is defined: @begin{Description} T'@attr{Storage_Size} @\Denotes an implementation-defined value of type @i{universal_integer} representing the number of storage elements reserved for a task of the subtype T. @begin{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} T'Storage_Size cannot be particularly meaningful in the presence of @Chg{Version=[3],New=[the specification of the aspect],Old=[a @nt{pragma}]} Storage_Size, especially when the expression is dynamic, or depends on a discriminant of the task, because the Storage_Size will be different for different objects of the type. Even without such a @Chg{Version=[3],New=[specification],Old=[@nt{pragma}]}, the Storage_Size can be different for different objects of the type, and in any case, the value is implementation defined. Hence, it is always implementation defined. @end{Honest} @NoPrefix@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00345-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @PDefn2{Term=[specifiable], Sec=(of Storage_Size for a task first subtype)} @NoPrefix@;Storage_Size may be specified for a task first subtype @Chg{Version=[2],New=[that is not an interface ],Old=[]}via an @nt{attribute_definition_clause}.@Chg{Version=[3],New=[ When the attribute is specified, the Storage_Size aspect is specified to be the value of the given @nt{expression}.],Old=[]} @end{Description} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[When this attribute is specified with an @nt{attribute_definition_clause}, the associated aspect is set to the @i<value> of the @nt{expression} given in the @nt{attribute_definition_clause}, rather than the @nt{expression} itself. This value is therefore the same for all objects of the type; in particular, it is not re-evaluated when objects are created. This is different than when the aspect is specified with an @nt{aspect_specification} (see @RefSecNum{Operational and Representation Attributes}).]} @end{Ramification} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00345-01]} @ChgAdded{Version=[2],Text=[We don't allow specifying Storage_Size on task interfaces. We don't need to mention class-wide task types, because these cannot be a first subtype.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Specific Suppression of Checks]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[Pragma Suppress can be used to suppress checks on specific entities.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The form of a specific Suppress @nt{pragma} is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @Chg{Version=[2], New=`@ @ @key{pragma} @prag{Suppress}(@Syn2{identifier}, [On =>] @Syn2{name});', Old=<>} @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[The @nt{identifier} shall be the name of a check (see @RefSecNum{Suppressing Checks}). The @nt{name} shall statically denote some entity.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[For a specific Suppress @nt{pragma} that is immediately within a @nt{package_specification}, the @nt{name} shall denote an entity (or several overloaded subprograms) declared immediately within the @nt{package_@!specification}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[A specific Suppress @nt{pragma} applies to the named check from the place of the @nt{pragma} to the end of the innermost enclosing declarative region, or, if the @nt{pragma} is given in a @nt{package_specification}, to the end of the scope of the named entity. The @nt{pragma} applies only to the named entity, or, for a subtype, on objects and values of its type. A specific Suppress @nt{pragma} suppresses the named check for any entities to which it applies (see @RefSecNum{Suppressing Checks}). Which checks are associated with a specific entity is not defined by this International Standard.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @begin{Discussion} @ChgAdded{Version=[2],Text=[The language doesn't specify exactly which entities control whether a check is performed. For example, in]} @begin{Example} @Chg{Version=[2],New=[@key{pragma} Suppress (Range_Check, On => A); A := B;],Old=[]} @end{Example} @ChgAdded{Version=[2],Text=[whether or not the range check is performed is not specified. The compiler may require that checks are suppressed on B or on the type of A in order to omit the range check.]} @end{Discussion} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation is allowed to place restrictions on specific Suppress @nt{pragma}s.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgAdded{Version=[2],Text=[An implementation may support a similar On parameter on @nt{pragma} Unsuppress (see @RefSecNum{Suppressing Checks}).]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00224-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. This feature was moved here because it is important for pragma Unsuppress that there be an unambiguous meaning for each checking pragma. For instance, in the example]} @begin{Example} @ChgAdded{Version=[2],Text=[@key{pragma} Suppress (Range_Check); @key{pragma} Unsuppress (Range_Check, On => A); A := B;]} @end{Example} @ChgAdded{Version=[2],Text=[the user needs to be able to depend on the range check being made on the assignment. But a compiler survey showed that the interpretation of this feature varied widely; trying to define this carefully was likely to cause a lot of user and implementer pain. Thus the feature was moved here, to emphasize that its use is not portable.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[The Class Attribute of Untagged Incomplete Types]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For the first subtype S of a type @i<T> declared by an @nt<incomplete_type_declaration> that is not tagged, the following attribute is defined:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @Chg{Version=[2],New=[S'@attr{Class} @\Denotes the first subtype of the incomplete class-wide type rooted at @i<T>. The completion of @i<T> shall declare a tagged type. Such an attribute reference shall occur in the same library unit as the @nt<incomplete_type_declaration>.],Old=[]} @end{Description} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgAdded{Version=[2],Text=[This must occur in the same unit to prevent children from imposing requirements on their ancestor library units for deferred incomplete types.]} @end{reason} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. This feature was moved here because the tagged incomplete type provides a better way to provide this capability (it doesn't put requirements on the completion based on uses that could be anywhere). Pity we didn't think of it in 1994.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Pragma Interface]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[In addition to an identifier, the reserved word @key{interface} is allowed as a pragma name, to provide compatibility with a prior edition of this International Standard.]} @end{SyntaxText} @end{Syntax} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00284-02]} @ChgAdded{Version=[2],Text=[All implementations need to at least recognize and ignore this pragma. A syntax error is not an acceptable implementation of this pragma.]} @end{ImplNote} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00326-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. This is necessary as @key{interface} is now a reserved word, which would prevent pragma Interface from being an implementation-defined pragma. We don't define any semantics for this pragma, as we expect that implementations will continue to use whatever they currently implement - requiring any changes would be counter-productive.]} @end{DiffWord95} @LabeledAddedClause{Version=[2],Name=[Dependence Restriction Identifiers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[The following restrictions involve dependence on specific language-defined units. The more general restriction No_Dependence (see @RefSecNum{Language-Defined Restrictions and Profiles}) should be used for this purpose.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following @Syni<restriction_>@nt<identifier>s exist:]} @begin{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Asynchronous_Control)}No_Asynchronous_Control @\Semantic dependence on the predefined package Asynchronous_Task_Control is not allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Conversion)}No_Unchecked_Conversion @\Semantic dependence on the predefined generic function Unchecked_Conversion is not allowed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Restrictions], Sec=(No_Unchecked_Deallocation)}No_Unchecked_Deallocation @\Semantic dependence on the predefined generic procedure Unchecked_Deallocation is not allowed.]} @end{Description} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. These restrictions are replaced by the more general No_Dependence (see @RefSecNum{Language-Defined Restrictions and Profiles}).]} @end{DiffWord95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedClause{Version=[2],Name=[Character and Wide_Character Conversion Functions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following declarations exist in the declaration of package Ada.Characters.Handling:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character (Item : @key{in} Wide_Character) @key{return} Boolean @key{renames} Conversions.Is_Character; @key{function} Is_String (Item : @key{in} Wide_String) @key{return} Boolean @key{renames} Conversions.Is_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Character (Item : @key{in} Wide_Character; Substitute : @key{in} Character := ' ') @key{return} Character @key{renames} Conversions.To_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_String (Item : @key{in} Wide_String; Substitute : @key{in} Character := ' ') @key{return} String @key{renames} Conversions.To_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Wide_Character (Item : @key{in} Character) @key{return} Wide_Character @key{renames} Conversions.To_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} To_Wide_String (Item : @key{in} String) @key{return} Wide_String @key{renames} Conversions.To_Wide_String;]} @end{Example} @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. These subprograms were moved to Characters.Conversions (see @RefSecNum{The Package Characters.Conversions}).]} @end{DiffWord95} @LabeledAddedClause{Version=[3],Name=[Aspect-related Pragmas]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Pragmas can be used as an alternative to aspect_specifications to specify certain aspects.]} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Many existing pragmas have been converted into aspects; the pragmas have moved here.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Inline]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Inline, which is a program unit pragma (see @RefSecNum{Pragmas and Program Units}), is as follows:@PDefn2{Term=[program unit pragma], Sec=(Inline)} @PDefn2{Term=[pragma, program unit], Sec=(Inline)}]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Inline> (@Syn2[name]{, @Syn2[name]});]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{pragma} shall apply to one or more callable entities or generic subprograms.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} Inline specifies that the Inline aspect (see @RefSecNum{Inline Expansion of Subprograms}) for each entity denoted by each @nt{name} given in the @nt{pragma} has the value True.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Note that inline expansion is desired no matter what @nt{name} is used in the call. This allows one to request inlining for only one of several overloaded subprograms as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] IO @key[is] @key[procedure] Put(X : @key[in] Integer); @key[procedure] Put(X : @key[in] String); @key[procedure] Put(X : @key[in] Character); @key[private] @key[procedure] Character_Put(X : @key[in] Character) @key[renames] Put; @key[pragma] Inline(Character_Put); @key[end] IO;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] IO; @key[use] IO; @key[procedure] Main @key[is] I : Integer; C : Character; @key[begin] ... Put(C); --@Examcom{ Inline expansion is desired.} Put(I); --@Examcom{ Inline expansion is NOT desired.} @key[end] Main;]} @end{Example} @end{Ramification} @end{StaticSem} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[An implementation may allow a @nt{pragma} Inline that has an argument which is a @nt{direct_name} denoting a @nt{subprogram_body} of the same @nt{declarative_part}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is allowed for Ada 83 compatibility. This is only a permission as this usage was considered obsolescent even for Ada 95.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We only need to allow this in @nt{declarative_part}s, because a @nt{body} is only allowed in another @nt{body}, and these all have @nt{declarative_part}s.]} @end{Discussion} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The name in a @nt{pragma} Inline may denote more than one entity in the case of overloading. Such a @nt{pragma} applies to all of the denoted entities.]} @end{Notes} @begin{Incompatible83} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00309-01],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 83} A pragma Inline cannot refer to a @nt{subprogram_body} outside of that body. The pragma can be given inside of the subprogram body. Ada 2005 adds an @ImplPermName to allow this usage for compatibility (and Ada 95 implementations also can use this permission), but implementations do not have to allow such @nt{pragma}s.]} @end{Incompatible83} @begin{Extend83} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 83} A @nt{pragma} Inline is allowed inside a @nt{subprogram_body} if there is no corresponding @nt{subprogram_declaration}. This is for uniformity with other program unit pragmas.]} @end{Extend83} @begin{Extend95} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00309-01],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Implementations are allowed to let @nt{Pragma} Inline apply to a @nt{subprogram_body}.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Inline was moved here from @RefSecNum{Inline Expansion of Subprograms}; aspect Inline lives there now.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubClause{Version=[3],Name=[Pragma No_Return]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} No_Return, which is a representation pragma (see @RefSecNum{Operational and Representation Aspects}), is as follows:@PDefn2{Term=[representation pragma], Sec=(No_Return)} @PDefn2{Term=[pragma, representation], Sec=(No_Return)}]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<No_Return> (@SynI[procedure_]@Syn2[local_name]{, @SynI[procedure_]@Syn2[local_name]});]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Each @SynI{procedure_}@nt{local_name} shall denote one or more procedures or generic procedures. @Redundant[The @SynI{procedure_}@nt{local_name} shall not denote a null procedure nor an instance of a generic unit.]]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} No_Return specifies that the No_Return aspect (see @RefSecNum{Nonreturning Procedures}) for each procedure denoted by each @nt{local_name} given in the @nt{pragma} has the value True.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma No_Return was moved here from @RefSecNum{Nonreturning Procedures}; aspect No_Return lives there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Pack]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Pack, which is a representation pragma (see @RefSecNum{Operational and Representation Aspects}), is as follows:@PDefn2{Term=[representation pragma], Sec=(Pack)} @PDefn2{Term=[pragma, representation], Sec=(Pack)}]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Pack> (@SynI[first_subtype_]@Syn2[local_name]);]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @SynI<first_subtype_>@nt{local_name} of a @nt{pragma} Pack shall denote a composite subtype.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@nt{Pragma} Pack specifies that the Pack aspect (see @RefSecNum{Packed Types}) for the type denoted by @SynI<first_subtype_>@nt{local_name} has the value True.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Pack was moved here from @RefSecNum{Packed Types}; aspect Pack lives there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Storage_Size]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Storage_Size is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Storage_Size> (@Syn2[expression]);]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Storage_Size is allowed only immediately within a @nt{task_definition}.]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{expression} of a @nt{pragma} Storage_Size is expected to be of any integer type.@PDefn2{Term=[expected type], Sec=(Storage_Size pragma argument)}]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Storage_Size sets the Storage_Size aspect (see @RefSecNum{Operational and Representation Attributes}) of the type defined by the immediately enclosing @nt{task_definition} to the value of the @nt{expression} of the @nt{pragma}.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Storage_Size was moved here from @RefSecNum{Operational and Representation Attributes}; aspect Storage_Size lives there now.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubClause{Version=[3],Name=[Interfacing Pragmas]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[@RootDefn{interfacing pragma} @PDefn2{Term=[interfacing pragma], Sec=(Import)} @PDefn2{Term=[pragma, interfacing], Sec=(Import)} @PDefn2{Term=[interfacing pragma], Sec=(Export)} @PDefn2{Term=[pragma, interfacing], Sec=(Export)} @PDefn2{Term=[interfacing pragma], Sec=(Convention)} @PDefn2{Term=[pragma, interfacing], Sec=(Convention)} @PDefn2{Term=[representation pragma], Sec=(Import)} @PDefn2{Term=[pragma, representation], Sec=(Import)} @PDefn2{Term=[representation pragma], Sec=(Export)} @PDefn2{Term=[pragma, representation], Sec=(Export)} @PDefn2{Term=[representation pragma], Sec=(Convention)} @PDefn2{Term=[pragma, representation], Sec=(Convention)} An @i{interfacing pragma} is a representation pragma that is one of the @nt{pragma}s Import, Export, or Convention. Their forms are as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=`@key{pragma} @prag(Import)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{external_name_string_}@Syn2{expression}]@* @ @ [, [Link_Name =>] @SynI{link_name_string_}@Syn2{expression}]);'}> @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=`@key{pragma} @prag(Export)(@* @ @ @ @ @ [Convention =>] @SynI{convention_}@Syn2{identifier}, [Entity =>] @Syn2{local_name}@* @ @ [, [External_Name =>] @SynI{external_name_string_}@Syn2{expression}]@* @ @ [, [Link_Name =>] @SynI{link_name_string_}@Syn2{expression}]);'}> @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=`@key{pragma} @prag(Convention)([Convention =>] @SynI{convention_}@Syn2{identifier},[Entity =>] @Syn2{local_name});'}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For @nt{pragma}s Import and Export, the argument for Link_Name shall not be given without the @i{pragma_@!argument_}@!@nt{identifier} unless the argument for External_Name is given.]} @end{SyntaxText} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=[expected type],Sec=(link name)} @PDefn2{Term=[expected type],Sec=(external name)} The expected type for an @SynI{external_name_string_}@nt{expression} and a @SynI{link_name_string_}@nt{expression} in an interfacing pragma is String.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @SynI{convention_}@nt{identifier} of an interfacing pragma shall be the name of a convention (see @RefSecNum{Interfacing Aspects}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Import shall be the completion of a declaration. @PDefn{Notwithstanding}Notwithstanding any rule to the contrary, a @nt{pragma} Import may serve as the completion of any kind of (explicit) declaration if supported by an implementation for that kind of declaration. If a completion is a @nt{pragma} Import, then it shall appear in the same @nt{declarative_part}, @nt{package_specification}, @nt{task_definition}, or @nt{protected_definition} as the declaration. For a library unit, it shall appear in the same @nt{compilation}, before any subsequent @nt{compilation_unit}s other than @nt{pragma}s. If the @nt{local_name} denotes more than one entity, then the @nt{pragma} Import is the completion of all of them.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @SynI{external_name_string_}@nt{expression} and @SynI{link_name_string_}@nt{expression} of a @nt{pragma} Import or Export shall be static.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{local_name} of each of these pragmas shall denote a declaration that may have the similarly named aspect specified.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[An interfacing pragma specifies various aspects of the entity denoted by the @nt{local_name} as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The Convention aspect (see @RefSecNum{Interfacing Aspects}) is @SynI{convention_}@nt{identifier}.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Import specifies that the Import aspect (see @RefSecNum{Interfacing Aspects}) is True.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Export specifies that the Export aspect (see @RefSecNum{Interfacing Aspects}) is True.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For both @nt{pragma} Import and Export, if an external name is given in the pragma, the External_Name aspect (see @RefSecNum{Interfacing Aspects}) is specified to be @SynI{external_name_string_}@nt{expression}. If a link name is given in the pragma, the Link_Name aspect (see @RefSecNum{Interfacing Aspects}) is specified to be the @SynI{link_name_string_}@nt{expression}.]} @end{Itemize} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragmas Import, Export, and Convention were moved here from @RefSecNum{Interfacing Aspects}; aspects Import, Export, Convention, Link_Name, and External_Name live there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Unchecked_Union]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Unchecked_Union, which is a representation pragma (see @RefSecNum{Operational and Representation Aspects}), is as follows:@PDefn2{Term=[representation pragma], Sec=(Unchecked_Union)} @PDefn2{Term=[pragma, representation], Sec=(Unchecked_Union)}]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Unchecked_Union> (@SynI[first_subtype_]@Syn2[local_name]);]}> @end{Syntax} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @SynI<first_subtype_>@nt{local_name} of a @nt{pragma} Unchecked_Union shall denote an unconstrained discriminated record subtype having a @nt{variant_part}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A @nt{pragma} Unchecked_Union specifies that the Unchecked_Union aspect (see @RefSecNum{Unchecked Union Types}) for the type denoted by @SynI<first_subtype_>@nt{local_name} has the value True.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Unchecked_Union was moved here from @RefSecNum{Unchecked Union Types}; aspect Unchecked_Union lives there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragmas Interrupt_Handler and Attach_Handler]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Interrupt_Handler is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Interrupt_Handler> (@SynI[handler_]@Syn2[name]);]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Attach_Handler is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Attach_Handler> (@SynI[handler_]@Syn2[name], @Syn2[expression]);]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For the Interrupt_Handler and Attach_Handler pragmas, the @SynI[handler_]@nt{name} shall resolve to denote a protected procedure with a parameterless profile.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For the Attach_Handler pragma, the expected type for the expression is Interrupts.Interrupt_Id (see @RefSecNum{The Package Interrupts}). @PDefn2{Term=[expected type], Sec=(Attach_Handler pragma second argument)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The Attach_Handler and Interrupt_Handler pragmas are only allowed immediately within the @nt{protected_definition} where the corresponding subprogram is declared. The corresponding @nt{protected_type_declaration} or @nt{single_protected_declaration} shall be a library-level declaration, and shall not be declared within a generic body. @PDefn{generic contract issue} In addition to the places where Legality Rules normally apply (see @RefSecNum{Generic Instantiation}), these rules also apply in the private part of an instance of a generic unit.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In the case of a @nt{protected_type_declaration}, an @nt{object_declaration} of an object of that type need not be at library level.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1]} @ChgAdded{Version=[3],Text=[We cannot allow these pragmas in a generic body, because legality rules are not checked for instance bodies, and these should not be allowed if the instance is not at the library level. The protected types can be declared in the private part if this is desired. Note that while the 'Access to use the handler would provide the check in the case of Interrupt_Handler, there is no other check for Attach_Handler. Since these pragmas are so similar, we want the rules to be the same.]} @end{Discussion} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For an implementation that supports Annex C, a pragma Interrupt_Handler specifies the Interrupt_Handler aspect (see @RefSecNum{Protected Procedure Handlers}) for the protected procedure @SynI<handler_>@nt{name} to have the value True. For an implementation that supports Annex C, a pragma Attach_Handler specifies the Attach_Handler aspect (see @RefSecNum{Protected Procedure Handlers}) for the protected procedure @SynI{handler_}@nt{name} to have the value of the given @nt{expression}@Redundant[ as evaluated at object creation time].]} @end{StaticSem} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added missing generic contract wording for the pragma Attach_Handler and Interrupt_Handler. This means that nested instances with these pragmas in the private part are now illegal. This is not likely to occur in practice.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragmas Interrupt_Handler and Attach_Handler were moved here from @RefSecNum{Protected Procedure Handlers}; aspects Interrupt_Handler and Attach_Handler live there now.]} @end{DiffWord2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubClause{Version=[3],Name=[Shared Variable Pragmas]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form for @nt{pragma}s Atomic, Volatile, Independent, Atomic_Components, and Volatile_Components, and Independent_Components is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Atomic> (@Syn2[local_name]);]}> @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Volatile> (@Syn2[local_name]);]}> @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Independent> (@SynI[component_]@Syn2[local_name]);]}> @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Atomic_Components> (@SynI[array_]@Syn2[local_name]);]}> @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Volatile_Components> (@SynI[array_]@Syn2[local_name]);]}> @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Independent_Components> (@Syn2[local_name]);]}> @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Pragmas Independent and Independent_Components are born obsolescent; they are defined to provide consistency with the existing shared variable pragmas. As with all obsolescent features, these pragmas are not optional; all Ada implementations need to implement them. Also note that these pragmas were defined as a @b<Correction>; as such, they are expected to be implemented as part of Ada 2005 implementations (and they would not be obsolescent there).]} @end{Discussion} @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{local_name} in an Atomic or Volatile pragma shall resolve to denote either an @nt{object_declaration}, a noninherited @nt{component_declaration}, or a @nt{full_type_declaration}. The @SynI{component_}@nt{local_name} in an Independent pragma shall resolve to denote a noninherited @nt{component_declaration}. The @SynI{array_}@nt{local_name} in an Atomic_Components or Volatile_Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type. The @nt{local_name} in an Independent_Components pragma shall resolve to denote the declaration of an array or record type or an array object of an anonymous type.]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[These @nt{pragma}s are representation pragmas (see @RefSecNum{Operational and Representation Aspects}). Each of these @nt{pragma}s specifies that the similarly named aspect (see @RefSecNum{Shared Variable Control}) of the type, object, or component denoted by its argument is True. @PDefn2{Term=[representation pragma], Sec=(Atomic)} @PDefn2{Term=[pragma, representation], Sec=(Atomic)} @PDefn2{Term=[representation pragma], Sec=(Volatile)} @PDefn2{Term=[pragma, representation], Sec=(Volatile)} @PDefn2{Term=[representation pragma], Sec=(Atomic_Components)} @PDefn2{Term=[pragma, representation], Sec=(Atomic_Components)} @PDefn2{Term=[representation pragma], Sec=(Volatile_Components)} @PDefn2{Term=[pragma, representation], Sec=(Volatile_Components)} @PDefn2{Term=[representation pragma], Sec=(Independent)} @PDefn2{Term=[pragma, representation], Sec=(Independent)} @PDefn2{Term=[representation pragma], Sec=(Independent_Components)} @PDefn2{Term=[pragma, representation], Sec=(Independent_Components)}]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{local_name} of each of these @nt{pragma}s shall denote a declaration that may have the similarly named aspect specified.]} @end{Legality} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. These pragmas were moved here from @RefSecNum{Shared Variable Control}; various aspects live there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma CPU]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[This pragma is born obsolescent; it is defined to provide consistency with existing real-time pragmas. As with all obsolescent features, this pragma is not optional; all Ada implementations need to implement it.]} @end{Discussion} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} CPU is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<CPU> (@Syn2[expression]);]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} of a @nt{pragma} CPU is System.Multiprocessors.CPU_Range.@PDefn2{Term=[expected type], Sec=(CPU pragma argument)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A CPU pragma is allowed only immediately within a @nt{task_definition}, or the @nt{declarative_part} of a @nt{subprogram_body}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For a CPU pragma that appears in the @nt{declarative_part} of a @nt{subprogram_body}, the @nt{expression} shall be static.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For an implementation that supports Annex D, a @nt{pragma} CPU specifies the value of the CPU aspect (see @RefSecNum{Multiprocessor Implementation}). If the @nt{pragma} appears in a @nt{task_definition}, the @nt{expression} is associated with the aspect for the task type or @nt{single_task_declaration} that contains the @nt{pragma}; otherwise, the @nt{expression} is associated with the aspect for the subprogram that contains the @nt{pragma}.]} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Pragma CPU is new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Dispatching_Domain]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[This pragma is born obsolescent; it is defined to provide consistency with existing real-time pragmas. As with all obsolescent features, this pragma is not optional; all Ada implementations need to implement it.]} @end{Discussion} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Dispatching_Domain is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Dispatching_Domain> (@nt{expression});]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} is System.Multiprocessors.Dispatching_Domains.Dispatching_Domain. @PDefn2{Term=[expected type], Sec=(Dispatching_Domains pragma argument)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[A Dispatching_Domain pragma is allowed only immediately within a @nt{task_definition}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[For an implementation that supports Annex D, a pragma Dispatching_Domain specifies the value of the Dispatching_Domain aspect (see @RefSecNum{Multiprocessor Dispatching Domains}). The @nt{expression} is associated with the aspect for the task type or @nt{single_task_declaration} that contains the pragma.]} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Pragma Dispatching_Domain is new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[Pragmas Priority and Interrupt_Priority]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Priority is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Priority> (@nt{expression});]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Interrupt_Priority is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Interrupt_Priority> [(@nt{expression})];]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The expected type for the @nt{expression} in a Priority or Interrupt_Priority pragma is Integer.@PDefn2{Term=[expected type], Sec=(Priority pragma argument)} @PDefn2{Term=[expected type], Sec=(Interrupt_Priority pragma argument)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A Priority pragma is allowed only immediately within a @nt{task_definition}, a @nt{protected_definition}, or the @nt{declarative_part} of a @nt{subprogram_body}. An Interrupt_Priority pragma is allowed only immediately within a @nt{task_definition} or a @nt{protected_definition}.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For a Priority pragma that appears in the @nt{declarative_part} of a @nt{subprogram_body}, the @nt{expression} shall be static, and its value shall be in the range of System.Priority.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For an implementation that supports Annex D, a @nt{pragma} Priority specifies the value of the Priority aspect (see @RefSecNum{Task Priorities}) and a @nt{pragma} Interrupt_Priority specifies the value of the Interrupt_Priority aspect as follows:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{pragma} appears in a @nt{task_definition}, the @nt{expression} is associated with the aspect for the task type or @nt{single_task_declaration} that contains the @nt{pragma};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{pragma} appears in a @nt{protected_definition}, the @nt{expression} is associated with the aspect for the protected type or @nt{single_protected_declaration} that contains the @nt{pragma};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the @nt{pragma} appears in the @nt{declarative_part} of a @nt{subprogram_body}, the @nt{expression} is associated with the aspect for the subprogram that contains the @nt{pragma}.]} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If there is no @nt{expression} in an Interrupt_Priority pragma, the Interrupt_Priority aspect has the value Interrupt_Priority'Last.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragmas Interrupt_Priority and Priority were moved here from @RefSecNum{Task Priorities}; aspects Interrupt_Priority and Priority live there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Relative_Deadline]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Relative_Deadline is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Relative_Deadline> (@SynI{relative_deadline_}@nt{expression});]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The expected type for a @SynI{relative_deadline_}@nt{expression} is Real_Time.Time_Span.@PDefn2{Term=[expected type], Sec=(Relative_Deadline pragma argument)}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A Relative_Deadline pragma is allowed only immediately within a @nt{task_definition} or the @nt{declarative_part} of a @nt{subprogram_body}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For an implementation that supports Annex D, a @nt{pragma} Relative_Deadline specifies the value of the Relative_Deadline aspect (see @RefSecNum{Earliest Deadline First Dispatching}). If the @nt{pragma} appears in a @nt{task_definition}, the @nt{expression} is associated with the aspect for the task type or @nt{single_task_declaration} that contains the @nt{pragma}; otherwise, the @nt{expression} is associated with the aspect for the subprogram that contains the @nt{pragma}.]} @end{StaticSem} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Relative_Deadline was moved here from @RefSecNum{Earliest Deadline First Dispatching}; aspect Relative_Deadline lives there now.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[3],Name=[Pragma Asynchronous]} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The form of a @nt{pragma} Asynchronous, which is a representation pragma (see @RefSecNum{Operational and Representation Aspects}), is as follows:@PDefn2{Term=[representation pragma], Sec=(Asynchronous)} @PDefn2{Term=[pragma, representation], Sec=(Asynchronous)}]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[3],@ChgAdded{Version=[3], Text=[@key{pragma} @prag<Asynchronous> (@Syn2[local_name]);]}> @end{Syntax} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[For an implementation that supports Annex E, a pragma Asynchronous specifies that the Asynchronous aspect (see @RefSecNum{Asynchronous Remote Calls}) for the procedure or type denoted by @nt{local_name} has the value True.]} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{local_name} of a pragma Asynchronous shall denote a declaration that may have aspect Asynchronous specified.]} @end{Legality} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause is new. Pragma Asynchronous was moved here from @RefSecNum{Asynchronous Remote Calls}; aspect Asynchronous lives there now.]} @end{DiffWord2005} �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pragmas.mss����������������������������������������������������������0000755�0001752�0001001�00000000723�12066652506�017605� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(pragmas, Root="ada.mss") @Comment{$Date: 2000/08/12 00:40:17 $} @LabeledInformativeAnnex{Language-Defined Pragmas} @comment{$Source: e:\\cvsroot/ARM/Source/pragmas.mss,v $} @comment{$Revision: 1.14 $} @begin{Intro} @Defn{pragma} This Annex summarizes the definitions given elsewhere of the language-defined pragmas. @PragmaList @end{Intro} @begin{DiffWord83} Pragmas List, Page, and Optimize are now officially defined in @RefSec{Pragmas}. @end{DiffWord83}���������������������������������������������org.adaic.arm_form/source_2012/pre.mss��������������������������������������������������������������0000755�0001752�0001001�00000056230�11776511201�016736� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(predef, Root="ada.mss") @Comment{$Date: 2012/03/20 06:13:59 $} @LabeledNormativeAnnex{Predefined Language Environment} @comment{$Source: e:\\cvsroot/ARM/Source/pre.mss,v $} @comment{$Revision: 1.50 $} @comment{$RLB: Eliminated includes. $} @begin{Intro} @Leading@keepnext @redundant[@Defn{Language-Defined Library Units} @Defn{predefined environment} This Annex contains the specifications of library units that shall be provided by every implementation. There are three root library units: Ada, Interfaces, and System; other library units are children of these:] @Leading@Keepnext @ChgRef{Version=(1),Kind=(Revised),Ref=(8652/0047),ARef=(AI95-00081-01)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00424-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0049-1],ARef=[AI05-0069-1],ARef=[AI05-0111-3],ARef=[AI05-0136-1],ARef=[AI05-0137-1],ARef=[AI05-0166-1],ARef=[AI05-0168-1]} @ @*@ @;@comment{paragraph number here, paragraph numbers seem to intrude on the RHS column, misaligning it. Thus we have two lines, as small as possible.} @begin{Display} @TabClear{}@TabSet{L2, L4, L6, L8, L10, L12, L14, L16} @begin{TwoCol} @Noparanum@redundant[@shrink<Standard @em @RefSecNum{The Package Standard} @\Ada @em @RefSecNum{The Package Ada} @Chg{Version=[2],New=(@\@\Assertions @em @RefSecNum{Pragmas Assert and Assertion_Policy} ), Old=()}@\@\Asynchronous_Task_Control @em @RefSecNum{Asynchronous Task Control} @\@\Calendar @em @RefSecNum{Delay Statements, Duration, and Time} @Chg{Version=[2],New=(@\@\@\Arithmetic @em @RefSecNum{Formatting, Time Zones, and other operations for Time} @\@\@\Formatting @em @RefSecNum{Formatting, Time Zones, and other operations for Time} @\@\@\Time_Zones @em @RefSecNum{Formatting, Time Zones, and other operations for Time} ), Old=()}@\@\Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} @Chg{Version=[2],New=(@\@\@\Conversions @em @RefSecNum{The Package Characters.Conversions} ), Old=()}@\@\@\Handling @em @RefSecNum{The Package Characters.Handling} @\@\@\Latin_1 @em @RefSecNum{The Package Characters.Latin_1} @\@\Command_Line @em @RefSecNum{The Package Command_Line} @Chg{Version=[2],New=(@\@\Complex_Text_IO @em @RefSecNum{Complex Input-Output} @\@\Containers @em @RefSecNum{The Package Containers} @Chg{Version=[3],New=(@\@\@\Bounded_Doubly_Linked_Lists @\@\@\@\@\@\@em @RefSecNum{The Generic Package Containers.Bounded_Doubly_Linked_Lists} @\@\@\Bounded_Hashed_Maps @em @RefSecNum{The Generic Package Containers.Bounded_Hashed_Maps} @\@\@\Bounded_Hashed_Sets @em @RefSecNum{The Generic Package Containers.Bounded_Hashed_Sets} @\@\@\Bounded_Multiway_Trees @em @RefSecNum{The Generic Package Containers.Bounded_Multiway_Trees} @\@\@\Bounded_Ordered_Maps @em @RefSecNum{The Generic Package Containers.Bounded_Ordered_Maps} @\@\@\Bounded_Ordered_Sets @em @RefSecNum{The Generic Package Containers.Bounded_Ordered_Sets} @\@\@\Bounded_Priority_Queues @em @RefSecNum{The Generic Package Containers.Bounded_Priority_Queues} @\@\@\Bounded_Synchronized_Queues @\@\@\@\@\@\ @em @RefSecNum{The Generic Package Containers.Bounded_Synchronized_Queues} @\@\@\Bounded_Vectors @em @RefSecNum{The Generic Package Containers.Bounded_Vectors} ), Old=()}@\@\@\Doubly_Linked_Lists @em @RefSecNum{The Generic Package Containers.Doubly_Linked_Lists} @\@\@\Generic_Array_Sort @em @RefSecNum{Array Sorting} @\@\@\Generic_Constrained_Array_Sort @\@\@\@\@\@\@em @RefSecNum{Array Sorting} @Chg{Version=[3],New=(@\@\@\Generic_Sort @em @RefSecNum{Array Sorting} ), Old=()}@\@\@\Hashed_Maps @em @RefSecNum{The Generic Package Containers.Hashed_Maps} @\@\@\Hashed_Sets @em @RefSecNum{The Generic Package Containers.Hashed_Sets} @\@\@\Indefinite_Doubly_Linked_Lists @\@\@\@\@\@\@em @RefSecNum{The Generic Package Containers.Indefinite_Doubly_Linked_Lists} @\@\@\Indefinite_Hashed_Maps @em @RefSecNum{The Generic Package Containers.Indefinite_Hashed_Maps} @\@\@\Indefinite_Hashed_Sets @em @RefSecNum{The Generic Package Containers.Indefinite_Hashed_Sets} @Chg{Version=[3],New=(@\@\@\Indefinite_Holders @em @RefSecNum{The Generic Package Containers.Indefinite_Holders} @\@\@\Indefinite_Multiway_Trees @em @RefSecNum{The Generic Package Containers.Indefinite_Multiway_Trees} ), Old=()}@\@\@\Indefinite_Ordered_Maps @em @RefSecNum{The Generic Package Containers.Indefinite_Ordered_Maps} @\@\@\Indefinite_Ordered_Sets @em @RefSecNum{The Generic Package Containers.Indefinite_Ordered_Sets} @\@\@\Indefinite_Vectors @em @RefSecNum{The Generic Package Containers.Indefinite_Vectors}), Old=()}>@NewColumnVer{Version=[3]}@Noparanum@shrink<@Chg{Version=[2], New=[@Chg{Version=[3],New=[Standard (@i{...continued}) @\Ada (@i{...continued}) @\@\Containers (@i{...continued}) @\@\@\Multiway_Trees @em @RefSecNum{The Generic Package Containers.Multiway_Trees} ], Old=()}@\@\@\Ordered_Maps @em @RefSecNum{The Generic Package Containers.Ordered_Maps} @\@\@\Ordered_Sets @em @RefSecNum{The Generic Package Containers.Ordered_Sets} @Chg{Version=[3],New=(@\@\@\Synchronized_Queue_Interfaces @\@\@\@\@\@\@em @RefSecNum{The Generic Package Containers.Synchronized_Queue_Interfaces} @\@\@\Unbounded_Priority_Queues @\@\@\@\@\@\@em @RefSecNum{The Generic Package Containers.Unbounded_Priority_Queues} @\@\@\Unbounded_Synchronized_Queues @\@\@\@\@\@\@em @RefSecNum{The Generic Package Containers.Unbounded_Synchronized_Queues} ), Old=()}@\@\@\Vectors @em @RefSecNum{The Generic Package Containers.Vectors} ], Old=()}>@NewColumnVer{Version=[2]}@Noparanum@shrink<@Chg{Version=[2], New=[@Chg{Version=[3],New=[],Old=[Standard (@i{...continued}) @\Ada (@i{...continued}) ]}],Old=[]}@\@\Decimal @em @RefSecNum{The Package Decimal} @\@\Direct_IO @em @RefSecNum{The Generic Package Direct_IO} @Chg{Version=[2],New=(@\@\Directories @em @RefSecNum{The Package Directories} @Chg{Version=[3],New=(@\@\@\Hierarchical_File_Names @em @RefSecNum{The Package Directories.Hierarchical_File_Names} ), Old=()}@\@\@\Information @em @RefSecNum{The Package Directories} @\@\Dispatching @em @RefSecNum{The Task Dispatching Model} @\@\@\EDF @em @RefSecNum{Earliest Deadline First Dispatching} @Chg{Version=[3],New=[@\@\@\Non_Preemptive @em @RefSecNum{Non-Preemptive Dispatching} ], Old=[]}@\@\@\Round_Robin @em @RefSecNum{Round Robin Dispatching} ), Old=()}@\@\Dynamic_Priorities @em @RefSecNum{Dynamic Priorities for Tasks} @Chg{Version=[2],New=(@\@\Environment_Variables @em @RefSecNum{The Package Environment_Variables} ), Old=()}@\@\Exceptions @em @RefSecNum{The Package Exceptions} @Chg{Version=[2],New=(@\@\Execution_Time @em @RefSecNum{Execution Time} @\@\@\Group_Budgets @em @RefSecNum{Group Execution Time Budgets} @Chg{Version=[3],New=(@\@\@\Interrupts @em @RefSecNum{Execution Time of Interrupt Handlers} ), Old=()}@\@\@\Timers @em @RefSecNum{Execution Time Timers} ), Old=()}@\@\Finalization @em @RefSecNum{Assignment and Finalization} @Chg{New=(@\@\Float_Text_IO @em @RefSecNum{Input-Output for Real Types} @\@\Float_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @Chg{Version=[2],New=(@\@\Float_Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} ), Old=()}@\@\Integer_Text_IO @em @RefSecNum{Input-Output for Integer Types} @\@\Integer_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @Chg{Version=[2],New=(@\@\Integer_Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} ), Old=()}), Old=()}@\@\Interrupts @em @RefSecNum{The Package Interrupts} @\@\@\Names @em @RefSecNum{The Package Interrupts} @\@\IO_Exceptions @em @RefSecNum{Exceptions in Input-Output} @Chg{Version=[3],New=(@\@\Iterator_Interfaces @em @RefSecNum{User-Defined Iterator Types} @\@\Locales @em @RefSecNum{The Package Locales} ), Old=()}>@NewColumnVer{Version=[3]}@Noparanum@shrink<@Chg{Version=[3], New=[Standard (@i{...continued}) @\Ada (@i{...continued}) ],Old=[]}@\@\Numerics @em @RefSecNum{The Numerics Packages} @Chg{Version=[2],New=(@\@\@\Complex_Arrays @em @RefSecNum{Complex Vectors and Matrices} ), Old=()}@\@\@\Complex_Elementary_Functions @em @RefSecNum{Complex Elementary Functions} @\@\@\Complex_Types @em @RefSecNum{Complex Types} @\@\@\Discrete_Random @em @RefSecNum{Random Number Generation} @\@\@\Elementary_Functions @em @RefSecNum{Elementary Functions} @\@\@\Float_Random @em @RefSecNum{Random Number Generation} @Chg{Version=[2],New=(@\@\@\Generic_Complex_Arrays @em @RefSecNum{Complex Vectors and Matrices} ), Old=()}@\@\@\Generic_Complex_Elementary_Functions @\@\@\@\@\@\@em @RefSecNum{Complex Elementary Functions} @\@\@\Generic_Complex_Types @em @RefSecNum{Complex Types} @\@\@\Generic_Elementary_Functions @em @RefSecNum{Elementary Functions} @Chg{Version=[2],New=(@\@\@\Generic_Real_Arrays @em @RefSecNum{Real Vectors and Matrices} @\@\@\Real_Arrays @em @RefSecNum{Real Vectors and Matrices} ), Old=()}@\@\Real_Time @em @RefSecNum{Monotonic Time} @Chg{Version=[2],New=(@\@\@\Timing_Events @em @RefSecNum{Timing Events} ), Old=()}@\@\Sequential_IO @em @RefSecNum{The Generic Package Sequential_IO} @\@\Storage_IO @em @RefSecNum{The Generic Package Storage_IO} @\@\Streams @em @RefSecNum{The Package Streams} @\@\@\Stream_IO @em @RefSecNum{The Package Streams.Stream_IO} >@NewColumnVer{Version=[0]}@NewColumnVer{Version=[1]}@NewColumnVer{Version=[2]}@Noparanum@shrink<@Chg{Version=[3], New=[],Old=[Standard (@i{...continued}) @\Ada (@i{...continued}) ]}@\@\Strings @em @RefSecNum{The Package Strings} @\@\@\Bounded @em @RefSecNum{Bounded-Length String Handling} @Chg{Version=[3],New=(@\@\@\@\Equal_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} @Chg{Version=[3],New=(@\@\@\@\Hash_Case_Insensitive @em @RefSecNum{String Hashing} @\@\@\@\Less_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}), Old=()}@\@\@\Fixed @em @RefSecNum{Fixed-Length String Handling} @Chg{Version=[3],New=(@\@\@\@\Equal_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} @Chg{Version=[3],New=(@\@\@\@\Hash_Case_Insensitive @em @RefSecNum{String Hashing} @\@\@\@\Less_Case_Insensitive @em @RefSecNum{String Comparison} @\@\@\Equal_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}), Old=()}@\@\@\Hash @em @RefSecNum{String Hashing} @Chg{Version=[3],New=(@\@\@\Hash_Case_Insensitive @em @RefSecNum{String Hashing} @\@\@\Less_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}@\@\@\Maps @em @RefSecNum{The Package Strings.Maps} @\@\@\@\Constants @em @RefSecNum{String-Handling Sets and Mappings} @\@\@\Unbounded @em @RefSecNum{Unbounded-Length String Handling} @Chg{Version=[3],New=(@\@\@\@\Equal_Case_Insensitive @em @RefSecNum{String Comparison} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Hash @em @RefSecNum{String Hashing} @Chg{Version=[3],New=(@\@\@\@\Hash_Case_Insensitive @em @RefSecNum{String Hashing} @\@\@\@\Less_Case_Insensitive @em @RefSecNum{String Comparison} @\@\@\UTF_Encoding @em @RefSecNum{String Encoding} @\@\@\@\Conversions @em @RefSecNum{String Encoding} @\@\@\@\Strings @em @RefSecNum{String Encoding} @\@\@\@\Wide_Strings @em @RefSecNum{String Encoding} @\@\@\@\Wide_Wide_Strings @em @RefSecNum{String Encoding} ), Old=()}), Old=()}>@NewColumnVer{Version=[3]}@Noparanum@shrink<@Chg{Version=[3], New=[Standard (@i{...continued}) @\Ada (@i{...continued}) @\@\Strings (@i{...continued}) ],Old=[]}@\@\@\Wide_Bounded @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_String Handling} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Hash_Case_Insensitive @em @RefSecNum{Wide_String Handling} ), Old=()}), Old=()}@Chg{Version=[3],New=(@\@\@\Wide_Equal_Case_Insensitive @em @RefSecNum{Wide_String Handling} ), Old=()}@\@\@\Wide_Fixed @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_String Handling} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Hash_Case_Insensitive @em @RefSecNum{Wide_String Handling} ), Old=()}@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\Wide_Hash_Case_Insensitive @em @RefSecNum{Wide_String Handling} ), Old=()}), Old=()}@\@\@\Wide_Maps @em @RefSecNum{Wide_String Handling} @\@\@\@\Wide_Constants @em @RefSecNum{Wide_String Handling} @\@\@\Wide_Unbounded @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_String Handling} ), Old=()}@Chg{Version=[2],New=(@\@\@\@\Wide_Hash @em @RefSecNum{Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Hash_Case_Insensitive @em @RefSecNum{Wide_String Handling} ), Old=()}@\@\@\Wide_Wide_Bounded @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old=()}@\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Hash_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Equal_Case_Insensitive @\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old={}}@\@\@\Wide_Wide_Fixed @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old=()}@\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Hash_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old=[]}@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\Wide_Wide_Hash_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old=()}@\@\@\Wide_Wide_Maps @em @RefSecNum{Wide_Wide_String Handling} @\@\@\@\Wide_Wide_Constants @em @RefSecNum{Wide_Wide_String Handling} @\@\@\Wide_Wide_Unbounded @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Equal_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} ), Old=()}@\@\@\@\Wide_Wide_Hash @em @RefSecNum{Wide_Wide_String Handling} @Chg{Version=[3],New=(@\@\@\@\Wide_Wide_Hash_Case_Insensitive @\@\@\@\@\@\@\@em @RefSecNum{Wide_Wide_String Handling} @\@\Synchronous_Barriers @em @RefSecNum{Synchronous Barriers} ), Old=[]}), Old=()}@\@\Synchronous_Task_Control @em @RefSecNum{Synchronous Task Control} @Chg{Version=[3],New=[@\@\@\EDF @em @RefSecNum{Synchronous Task Control} ], Old=[]}>@NewColumnVer{Version=[3]}@Noparanum@shrink<@Chg{Version=[3], New=[Standard (@i{...continued}) @\Ada (@i{...continued}) ],Old=[]}@\@\Tags @em @RefSecNum{Tagged Types and Type Extensions} @Chg{Version=[2],New=(@\@\@\Generic_Dispatching_Constructor @em @RefSecNum{Tagged Types and Type Extensions} ), Old=()}@\@\Task_Attributes @em @RefSecNum{The Package Task_Attributes} @\@\Task_Identification @em @RefSecNum{The Package Task_Identification} @Chg{Version=[2],New=(@\@\Task_Termination @em @RefSecNum{The Package Task_Termination}), Old=()}> @NewColumnVer{Version=[2]}@Noparanum@shrink<@Chg{Version=[2], New=[@Chg{Version=[3],New=[],Old=[Standard (@i{...continued}) @\Ada (@i{...continued}) ]}], Old=()}@\@\Text_IO @em @RefSecNum{The Package Text_IO} @Chg{Version=[2],New=(@\@\@\Bounded_IO @em @RefSecNum{Input-Output for Bounded Strings} ),Old=()}@\@\@\Complex_IO @em @RefSecNum{Complex Input-Output} @\@\@\Editing @em @RefSecNum{The Package Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Text_IO.Text_Streams} @Chg{Version=[2],New=(@\@\@\Unbounded_IO @em @RefSecNum{Input-Output for Unbounded Strings} ), Old=()}@\@\Unchecked_Conversion @em @RefSecNum{Unchecked Type Conversions} @Chg{Version=[3],New=(@\@\Unchecked_Deallocate_Subpool @em @RefSecNum{Subpool Reclamation} ), Old=()}@\@\Unchecked_Deallocation @em @RefSecNum{Unchecked Storage Deallocation} @Chg{Version=[2],New=(@\@\Wide_Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} @Chg{Version=[3],New=(@\@\@\Handling @em @RefSecNum{The Package Wide_Characters.Handling} ),Old=()}),Old=()}@\@\Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Complex_IO @em @RefSecNum{The Package Wide_Text_IO.Complex_IO} @\@\@\Editing @em @RefSecNum{The Package Wide_Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Wide_Text_IO.Text_Streams} @Chg{Version=[2],New=(@\@\@\Wide_Bounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Wide_Unbounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\Wide_Wide_Characters @em @RefSecNum{The Packages Characters, Wide_Characters, and Wide_Wide_Characters} @Chg{Version=[3],New=(@\@\@\Handling @em @RefSecNum{The Package Wide_Wide_Characters.Handling} ),Old=()}@\@\Wide_Wide_Text_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Complex_IO @em @RefSecNum{The Package Wide_Wide_Text_IO.Complex_IO} @\@\@\Editing @em @RefSecNum{The Package Wide_Wide_Text_IO.Editing} @\@\@\Text_Streams @em @RefSecNum{The Package Wide_Wide_Text_IO.Text_Streams} @\@\@\Wide_Wide_Bounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output} @\@\@\Wide_Wide_Unbounded_IO @em @RefSecNum{Wide Text Input-Output and Wide Wide Text Input-Output}), Old=()}> @NewColumnVer{Version=[3]}@Noparanum@shrink<@\Interfaces @em @RefSecNum{The Package Interfaces} @\@\C @em @RefSecNum{Interfacing with C and C++} @\@\@\Pointers @em @RefSecNum{The Generic Package Interfaces.C.Pointers} @\@\@\Strings @em @RefSecNum{The Package Interfaces.C.Strings} @\@\COBOL @em @RefSecNum{Interfacing with COBOL} @\@\Fortran @em @RefSecNum{Interfacing with Fortran}> @Noparanum@shrink<@\System @em @RefSecNum{The Package System} @\@\Address_To_Access_Conversions @em @RefSecNum{The Package System.Address_To_Access_Conversions} @\@\Machine_Code @em @RefSecNum{Machine Code Insertions} @Chg{Version=[3],New=(@\@\Multiprocessors @em @RefSecNum{Multiprocessor Implementation} @\@\@\Dispatching_Domains @em @RefSecNum{Multiprocessor Dispatching Domains} ),Old=()}@\@\RPC @em @RefSecNum{Partition Communication Subsystem} @\@\Storage_Elements @em @RefSecNum{The Package System.Storage_Elements} @\@\Storage_Pools @em @RefSecNum{Storage Management}@Chg{Version=[3],New=( @\@\@\Subpools @em @RefSecNum{Storage Subpools}), Old=()}>] @end{TwoCol} @end{Display} @begin{Discussion} In running text, we generally leave out the @lquotes@;Ada.@rquotes@; when referring to a child of Ada. @end{Discussion} @begin{Reason} We had no strict rule for which of Ada, Interfaces, or System should be the parent of a given library unit. However, we have tried to place as many things as possible under Ada, except that interfacing is a separate category, and we have tried to place library units whose use is highly nonportable under System. @end{Reason} @end{Intro} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The implementation shall ensure that each language@Chg{Version=[2],New=[-],Old=[]}defined subprogram is reentrant@Chg{Version=[2],New=[@Defn{reentrant}],Old=[]}@ChgNote{Suggested by Gary Dismukes} in the sense that concurrent calls on the same subprogram perform as specified, so long as all parameters that could be passed by reference denote nonoverlapping objects. @begin{Ramification} For example, simultaneous calls to Text_IO.Put will work properly, so long as they are going to two different files. On the other hand, simultaneous output to the same file constitutes erroneous use of shared variables. @end{Ramification} @begin{Honest} Here, @lquotes@;language defined subprogram@rquotes@; means a language defined library subprogram, a subprogram declared in the visible part of a language defined library package, an instance of a language defined generic library subprogram, or a subprogram declared in the visible part of an instance of a language defined generic library package. @end{Honest} @begin{Ramification} The rule implies that any data local to the private part or body of the package has to be somehow protected against simultaneous access. @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0048-1]} @ChgAdded{Version=[3],Text=[If a descendant of a language-defined tagged type is declared, the implementation shall ensure that each inherited language-defined subprogram behaves as described in this International Standard. In particular, overriding a language-defined subprogram shall not alter the effect of any inherited language-defined subprogram.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This means that internally the implementation must not do redispatching unless it is required by the Standard. So when we say that some subprogram Bar is equivalent to Foo, overriding Foo for a derived type doesn't change the semantics of Bar, and in particular it means that Bar may no longer be equivalent to Foo. The word @ldquote@;equivalent@rdquote is always a bit of a lie anyway.]} @end{Reason} @end{ImplReq} @begin{ImplPerm} The implementation may restrict the replacement of language-defined compilation units. The implementation may restrict children of language-defined library units (other than Standard). @begin{Ramification} For example, the implementation may say, @lquotes@;you cannot compile a library unit called System@rquotes@; or @lquotes@;you cannot compile a child of package System@rquotes@; or @lquotes@;if you compile a library unit called System, it has to be a package, and it has to contain at least the following declarations: ...@rquotes@;. @end{Ramification} @end{ImplPerm} @begin{DiffWord83} Many of Ada 83's language-defined library units are now children of Ada or System. For upward compatibility, these are renamed as root library units (see @RefSecNum{Renamings of Library Units}). The order and lettering of the annexes has been changed. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0047],ARef=[AI95-00081-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Units missing from the list of predefined units were added.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00424-01]} @ChgAdded{Version=[2],Text=[Added new units to the list of predefined units.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0048-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to ban redispatching unless it is explicitly required, in order to safeguard portability when overriding language-defined routines.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0060-1],ARef=[AI05-0206-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a permission to omit pragma Remote_Types from language-defined units if Annex E is not supported. This was later removed, as a better method of supporting the reason is now available. Note that this requires all implementations to provide minimal support for the Remote_Types categorization even if Annex E is not supported; being unable to compile language-defined units is not allowed.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0049-1],ARef=[AI05-0069-1],ARef=[AI05-0111-3],ARef=[AI05-0136-1],ARef=[AI05-0137-1],ARef=[AI05-0166-1],ARef=[AI05-0168-1]} @ChgAdded{Version=[3],Text=[Added various new units to the list of predefined units.]} @end{DiffWord2005} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_ada.mss����������������������������������������������������������0000755�0001752�0001001�00000003465�12066652506�017554� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_ada.mss,v $ } @comment{ $Revision: 1.16 $ $Date: 00/03/08 Created by RLB to avoid Includes } @Part(predefstandard, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledClause{The Package Ada} @begin{StaticSem} @Leading@keepnext@;The following language-defined library package exists: @begin{Example} @RootLibUnit{Ada}@key[package] Ada @key[is] @key[pragma] Pure(Ada); @key[end] Ada; @end{Example} Ada serves as the parent of most of the other language-defined library units; its declaration is empty (except for the @nt{pragma} Pure). @end{StaticSem} @begin{Legality} In the standard mode, it is illegal to compile a child of package Ada. @begin{Reason} The intention is that mentioning, say, Ada.Text_IO in a @nt{with_clause} is guaranteed (at least in the standard mode) to refer to the standard version of Ada.Text_IO. The user can compile a root library unit Text_IO that has no relation to the standard version of Text_IO. @end{Reason} @begin{Ramification} Note that Ada can have non-language-defined grandchildren, assuming the implementation allows it. Also, packages System and Interfaces can have children, assuming the implementation allows it. @end{Ramification} @begin{ImplNote} An implementation will typically support a nonstandard mode in which compiling the language defined library units is allowed. Whether or not this mode is made available to users is up to the implementer. An implementation could theoretically have private children of Ada, since that would be semantically neutral. However, a programmer cannot compile such a library unit. @end{ImplNote} @end{Legality} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{extensions to Ada 83} This @Chg{Version=[3],New=[subclause],Old=[clause]} is new to Ada 95. @end{Extend83} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_chars.mss��������������������������������������������������������0000755�0001752�0001001�00000222506�12066652507�020127� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_chars.mss,v $ } @comment{ $Revision: 1.48 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(predefchars, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledClause{Character Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0243-1],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} presents the packages related to character processing: an empty @Chg{Version=[3],New=[declared ],Old=[]}pure package Characters and child packages Characters.Handling and Characters.Latin_1. The package Characters.Handling provides classification and conversion functions for Character data, and some simple functions for dealing with Wide_Character @Chg{Version=[2],New=[and Wide_Wide_Character ], Old=[]}data. The child package Characters.Latin_1 declares a set of constants initialized to values of type Character. @end{Intro} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{extensions to Ada 83} This @Chg{Version=[3],New=[subclause],Old=[clause]} is new to Ada 95. @end{Extend83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included Wide_Wide_Character in this description; the individual changes are documented as extensions as needed.]} @end{Diffword95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledRevisedSubClause{Version=[2],New=[The Packages Characters, Wide_Characters, and Wide_Wide_Characters],Old=[The Package Characters]} @begin{StaticSem} @leading@keepnext@;The library package Characters has the following declaration: @begin{example} @ChildUnit{Parent=[Ada],Child=[Characters]}@key(package) Ada.Characters @key[is] @key[pragma] Pure(Characters); @key(end) Ada.Characters; @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Wide_Characters has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Wide_Characters]}@key(package) Ada.Wide_Characters @key[is] @key[pragma] Pure(Wide_Characters); @key[end] Ada.Wide_Characters;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Wide_Wide_Characters has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada],Child=[Wide_Wide_Characters]}@key(package) Ada.Wide_Wide_Characters @key[is] @key[pragma] Pure(Wide_Wide_Characters); @key[end] Ada.Wide_Wide_Characters;]} @end{example} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0185-1]} @ChgAdded{Version=[2],Text=[If an implementation chooses to provide implementation-defined operations on Wide_Character or Wide_String (such as @Chg{Version=[3],New=[],Old=[case mapping, classification, ]}collating and sorting, etc.) it should do so by providing child units of Wide_Characters. Similarly if it chooses to provide implementation-defined operations on Wide_Wide_Character or Wide_Wide_String it should do so by providing child units of Wide_Wide_Characters.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Implementation-defined operations on Wide_Character, Wide_String, Wide_Wide_Character, and Wide_Wide_String should be child units of Wide_Characters or Wide_Wide_Characters.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The packages Wide_Characters and Wide_Wide_Characters are new.]} @end{Extend95} @LabeledSubClause{The Package Characters.Handling} @begin{StaticSem} @leading@keepnext@;The library package Characters.Handling has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01],ARef=[AI95-00395-01]} @Chg{Version=[2],New=[@key[with] Ada.Characters.Conversions; ],Old=[]}@key[package] Ada.Characters.Handling @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Handling]} @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Handling); @keepnext--@RI{Character classification functions} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0185-1]} @key[function] @AdaSubDefn{Is_Control} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Graphic} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Letter} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Lower} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Upper} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Basic} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Digit} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Decimal_Digit} (Item : @key[in] Character) @key[return] Boolean @key[renames] Is_Digit; @key[function] @AdaSubDefn{Is_Hexadecimal_Digit} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Alphanumeric} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Special} (Item : @key[in] Character) @key[return] Boolean;@Chg{Version=[3],New=[ @key[function] @AdaSubDefn{Is_Line_Terminator} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Mark} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Other_Format} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Punctuation_Connector} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Space} (Item : @key[in] Character) @key[return] Boolean;],Old=[]} @keepnext--@RI{Conversion functions for Character and String} @key[function] @AdaSubDefn{To_Lower} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Upper} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Basic} (Item : @key[in] Character) @key[return] Character; @key[function] @AdaSubDefn{To_Lower} (Item : @key[in] String) @key[return] String; @key[function] @AdaSubDefn{To_Upper} (Item : @key[in] String) @key[return] String; @key[function] @AdaSubDefn{To_Basic} (Item : @key[in] String) @key[return] String; @keepnext--@RI{Classifications of and conversions between Character and ISO 646} @key[subtype] @AdaSubtypeDefn{Name=[ISO_646],Of=[Character]} @key[is] Character @key[range] Character'Val(0) .. Character'Val(127); @key[function] @AdaSubDefn{Is_ISO_646} (Item : @key[in] Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_ISO_646} (Item : @key[in] String) @key[return] Boolean; @key[function] @AdaSubDefn{To_ISO_646} (Item : @key[in] Character; Substitute : @key[in] ISO_646 := ' ') @key[return] ISO_646; @key[function] @AdaSubDefn{To_ISO_646} (Item : @key[in] String; Substitute : @key[in] ISO_646 := ' ') @key[return] String; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @Keepnext--@RI{@Chg{Version=[2],New=[ The functions Is_Character, Is_String, To_Character, To_String, To_Wide_Character,],Old=[Classifications of and conversions between Wide_Character and Character.]}}@Chg{Version=[2],New=[ --@RI{ and To_Wide_String are obsolescent; see @RefSecnum{Character and Wide_Character Conversion Functions}.}],Old=[]} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@roman{@Shrink{@i<Paragraphs 14 through 18 were deleted.>}}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_String) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Character;]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] String) @key[return] Wide_String;]} @key[end] Ada.Characters.Handling; @end{Example} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The @nt{with_clause} for Ada.Characters.Conversions is needed for the definition of the obsolescent functions (see @RefSecnum{Character and Wide_Character Conversion Functions}). It would be odd to put this clause into @RefSecnum{Character and Wide_Character Conversion Functions} as it was not present in Ada 95, and @nt{with_clause}s are semantically neutral to clients anyway.]} @end{Discussion} In the description below for each function that returns a Boolean result, the effect is described in terms of the conditions under which the value True is returned. If these conditions are not met, then the function returns False. Each of the following classification functions has a formal Character parameter, Item, and returns a Boolean result. @begin{description} @Defn2{term=[control character], sec=[a category of Character]}Is_Control @\True if Item is a control character. A @i{control character} is a character whose position is in one of the ranges 0..31 or 127..159. @Defn2{term=[graphic character], sec=[a category of Character]}Is_Graphic @\True if Item is a graphic character. A @i[graphic character] is a character whose position is in one of the ranges 32..126 or 160..255. @Defn2{term=[letter], sec=[a category of Character]}Is_Letter @\True if Item is a letter. A @i[letter] is a character that is in one of the ranges 'A'..'Z' or 'a'..'z', or whose position is in one of the ranges 192..214, 216..246, or 248..255. @Defn2{term=[lower-case letter], sec=[a category of Character]}Is_Lower @\True if Item is a lower-case letter. A @i[lower-case letter] is a character that is in the range 'a'..'z', or whose position is in one of the ranges 223..246 or 248..255. @Defn2{term=[upper-case letter], sec=[a category of Character]}Is_Upper@\True if Item is an upper-case letter. An @i[upper-case letter] is a character that is in the range 'A'..'Z' or whose position is in one of the ranges 192..214 or 216.. 222. @Defn2{term=[basic letter], sec=[a category of Character]}Is_Basic @\True if Item is a basic letter. A @i[basic letter] is a character that is in one of the ranges 'A'..'Z' and 'a'..'z', or that is one of the following: '@latin1(198)', '@latin1(230)', '@latin1(208)', '@latin1(240)', '@latin1(222)', '@latin1(254)', or '@latin1(223)'. @comment[These characters are at the positions 198 and 230, 208 and 240, 222 and 254, and 223.] @Defn2{term=[decimal digit], sec=[a category of Character]}Is_Digit @\True if Item is a decimal digit. A @i[decimal digit] is a character in the range '0'..'9'. Is_Decimal_Digit @\A renaming of Is_Digit. @Defn2{term=[hexadecimal digit], sec=[a category of Character]}Is_Hexadecimal_Digit @\True if Item is a hexadecimal digit. A @i[hexadecimal digit] is a character that is either a decimal digit or that is in one of the ranges 'A' .. 'F' or 'a' .. 'f'. @Defn2{term=[alphanumeric character], sec=[a category of Character]}Is_Alphanumeric @\True if Item is an alphanumeric character. An @i[alphanumeric character] is a character that is either a letter or a decimal digit. @Defn2{term=[special graphic character], sec=[a category of Character]}Is_Special @\True if Item is a special graphic character. A @i[special graphic character] is a graphic character that is not alphanumeric. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[Is_Line_Terminator@\True if Item is a character with position 10 .. 13 (Line_Feed, Line_Tabulation, Form_Feed, Carriage_Return) or 133 (Next_Line).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[Is_Mark@\Never True (no value of type Character has categories Mark, Non-Spacing or Mark, Spacing Combining).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[Is_Other_Format@\True if Item is a character with position 173 (Soft_Hyphen).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[Is_Punctuation_Connector@\True if Item is a character with position 95 ('_', known as Low_Line or Underscore).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[Is_Space@\True if Item is a character with position 32 (' ') or 160 (No_Break_Space).]} @end{description} Each of the names To_Lower, To_Upper, and To_Basic refers to two functions: one that converts from Character to Character, and the other that converts from String to String. The result of each Character-to-Character function is described below, in terms of the conversion applied to Item, its formal Character parameter. The result of each String-to-String conversion is obtained by applying to each element of the function's String parameter the corresponding Character-to-Character conversion; the result is the null String if the value of the formal parameter is the null String. The lower bound of the result String is 1. @begin{description} To_Lower@\Returns the corresponding lower-case value for Item if Is_Upper(Item), and returns Item otherwise. To_Upper@\Returns the corresponding upper-case value for Item if Is_Lower(Item) and Item has an upper-case form, and returns Item otherwise. The lower case letters '@latin1(223)' and '@latin1(255)' @comment{These are at positions 223 and 255} do not have upper case forms. To_Basic@\Returns the letter corresponding to Item but with no diacritical mark, if Item is a letter but not a basic letter; returns Item otherwise. @end{Description} The following set of functions test for membership in the ISO 646 character range, or convert between ISO 646 and Character. @begin{description} Is_ISO_646@\The function whose formal parameter, Item, is of type Character returns True if Item is in the subtype ISO_646. Is_ISO_646@\The function whose formal parameter, Item, is of type String returns True if Is_ISO_646(Item(I)) is True for each I in Item'Range. To_ISO_646@\The function whose first formal parameter, Item, is of type Character returns Item if Is_ISO_646(Item), and returns the Substitute ISO_646 character otherwise. To_ISO_646@\The function whose first formal parameter, Item, is of type String returns the String whose Range is 1..Item'Length and each of whose elements is given by To_ISO_646 of the corresponding element in Item. @end{description} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@roman{@Shrink{@i<Paragraphs 42 through 49 were deleted.>}}]}@Comment{This message should be deleted if the paragraphs are ever renumbered. This includes the following ImplAdv paragraph.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[The following set of functions test Wide_Character values for membership in Character, or convert between corresponding characters of Wide_Character and Character.]} @begin{description} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Is_Character@\Returns True if Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Is_String@\Returns True if Is_Character(Item(I)) is True for each I in Item'Range.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Character@\Returns the Character corresponding to Item if Is_Character(Item), and returns the Substitute Character otherwise.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_String@\Returns the String whose range is 1..Item'Length and each of whose elements is given by To_Character of the corresponding element in Item.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Wide_Character@\Returns the Wide_Character X such that Character'Pos(Item) = Wide_Character'Pos(X).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[To_Wide_String@\Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item.]} @end{description} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00285-01]} @ChgDeleted{Version=[2],Text=[If an implementation provides a localized definition of Character or Wide_Character, then the effects of the subprograms in Characters.Handling should reflect the localizations. See also @RefSecNum(Character Types).]} @ChgNote{No @ChgImplAdvice here, because we'd have to insert and delete the item in the same version.} @end{ImplAdvice} @begin{Notes} A basic letter is a letter without a diacritical mark. @Leading@;Except for the hexadecimal digits, basic letters, and ISO_646 characters, the categories identified in the classification functions form a strict hierarchy: @begin{Display} @TabClear{}@Comment{We use "Leading" below to make this list closely packed} @TabSet{4, 8, 12, 16} @Leading@em Control characters @Leading@em Graphic characters @Leading@\@em Alphanumeric characters @Leading@\@\@em Letters @Leading@\@\@\@em Upper-case letters @Leading@\@\@\@em Lower-case letters @Leading@\@\@em Decimal digits @Leading@\@em Special graphic characters @end{Display} @begin{Ramification} Thus each Character value is either a control character or a graphic character but not both; each graphic character is either an alphanumeric or special graphic but not both; each alphanumeric is either a letter or decimal digit but not both; each letter is either upper case or lower case but not both.@end{ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0114-1]} @ChgAdded{Version=[3],Text=[There are certain characters which are defined to be lower case letters by ISO 10646 and are therefore allowed in identifiers, but are not considered lower case letters by Ada.Characters.Handling.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is to maintain runtime compatibility with the Ada 95 definitions of these functions. We don't list the exact characters involved because they're likely to change in future character set standards; the list for ISO 10646:2011 can be found in @AILink{AI=[AI05-0114-1],Text=[AI05-0114-1]}.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[No version of Characters.Handling is intended to do portable (Ada-version independent) manipulation of Ada identifiers. The classification given by Wide_Characters.Handling will be correct for the current implementation for Ada 2012 identifiers, but it might not be correct for a different implementation or version of Ada.]} @end{Ramification} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Characters.Handling is now Pure, so it can be used in pure units.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Added additional classification routines so that Characters.Handling has all of the routines available in Wide_Characters.Handling. If Characters.Handling is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} that is the same as one of the new functions is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The conversion functions are made obsolescent; a more complete set is available in Characters.Conversions @em see @RefSecNum{The Package Characters.Conversions}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[We no longer talk about localized character sets; these are a @Chg{Version=[3],New=[nonstandard],Old=[non-standard]} mode, which is none of our business.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0114-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a note to clarify that these functions don't have any relationship to the characters allowed in identifiers.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledSubClause{The Package Characters.Latin_1} @begin{Intro} The package Characters.Latin_1 declares constants for characters in ISO 8859-1. @begin{reason} The constants for the ISO 646 characters could have been declared as renamings of objects declared in package ASCII, as opposed to explicit constants. The main reason for explicit constants was for consistency of style with the upper-half constants, and to avoid emphasizing the package ASCII.@end{reason} @end{Intro} @begin{StaticSem} @leading@keepnext@;The library package Characters.Latin_1 has the following declaration: @begin{Example} @key[package] Ada.Characters.Latin_1 @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Latin_1]} @key[pragma] Pure(Latin_1); @keepnext--@RI{ Control characters:}@PDefn2{term=[control character], sec=[a category of Character]} @AdaObjDefn{NUL} : @key[constant] Character := Character'Val(0); @AdaObjDefn{SOH} : @key[constant] Character := Character'Val(1); @AdaObjDefn{STX} : @key[constant] Character := Character'Val(2); @AdaObjDefn{ETX} : @key[constant] Character := Character'Val(3); @AdaObjDefn{EOT} : @key[constant] Character := Character'Val(4); @AdaObjDefn{ENQ} : @key[constant] Character := Character'Val(5); @AdaObjDefn{ACK} : @key[constant] Character := Character'Val(6); @AdaObjDefn{BEL} : @key[constant] Character := Character'Val(7); @AdaObjDefn{BS} : @key[constant] Character := Character'Val(8); @AdaObjDefn{HT} : @key[constant] Character := Character'Val(9); @AdaObjDefn{LF} : @key[constant] Character := Character'Val(10); @AdaObjDefn{VT} : @key[constant] Character := Character'Val(11); @AdaObjDefn{FF} : @key[constant] Character := Character'Val(12); @AdaObjDefn{CR} : @key[constant] Character := Character'Val(13); @AdaObjDefn{SO} : @key[constant] Character := Character'Val(14); @AdaObjDefn{SI} : @key[constant] Character := Character'Val(15); @AdaObjDefn{DLE} : @key[constant] Character := Character'Val(16); @AdaObjDefn{DC1} : @key[constant] Character := Character'Val(17); @AdaObjDefn{DC2} : @key[constant] Character := Character'Val(18); @AdaObjDefn{DC3} : @key[constant] Character := Character'Val(19); @AdaObjDefn{DC4} : @key[constant] Character := Character'Val(20); @AdaObjDefn{NAK} : @key[constant] Character := Character'Val(21); @AdaObjDefn{SYN} : @key[constant] Character := Character'Val(22); @AdaObjDefn{ETB} : @key[constant] Character := Character'Val(23); @AdaObjDefn{CAN} : @key[constant] Character := Character'Val(24); @AdaObjDefn{EM} : @key[constant] Character := Character'Val(25); @AdaObjDefn{SUB} : @key[constant] Character := Character'Val(26); @AdaObjDefn{ESC} : @key[constant] Character := Character'Val(27); @AdaObjDefn{FS} : @key[constant] Character := Character'Val(28); @AdaObjDefn{GS} : @key[constant] Character := Character'Val(29); @AdaObjDefn{RS} : @key[constant] Character := Character'Val(30); @AdaObjDefn{US} : @key[constant] Character := Character'Val(31); @keepnext--@RI{ ISO 646 graphic characters:} @AdaObjDefn{Space} : @key[constant] Character := ' '; --@RI{ Character'Val(32)} @AdaObjDefn{Exclamation} : @key[constant] Character := '!'; --@RI{ Character'Val(33)} @AdaObjDefn{Quotation} : @key[constant] Character := '"'; --@RI{ Character'Val(34)} @AdaObjDefn{Number_Sign} : @key[constant] Character := '#'; --@RI{ Character'Val(35)} @AdaObjDefn{Dollar_Sign} : @key[constant] Character := '$'; --@RI{ Character'Val(36)} @AdaObjDefn{Percent_Sign} : @key[constant] Character := '%'; --@RI{ Character'Val(37)} @AdaObjDefn{Ampersand} : @key[constant] Character := '&'; --@RI{ Character'Val(38)} @AdaObjDefn{Apostrophe} : @key[constant] Character := '''; --@RI{ Character'Val(39)} @AdaObjDefn{Left_Parenthesis} : @key[constant] Character := '('; --@RI{ Character'Val(40)} @AdaObjDefn{Right_Parenthesis} : @key[constant] Character := ')'; --@RI{ Character'Val(41)} @AdaObjDefn{Asterisk} : @key[constant] Character := '*'; --@RI{ Character'Val(42)} @AdaObjDefn{Plus_Sign} : @key[constant] Character := '+'; --@RI{ Character'Val(43)} @AdaObjDefn{Comma} : @key[constant] Character := ','; --@RI{ Character'Val(44)} @AdaObjDefn{Hyphen} : @key[constant] Character := '-'; --@RI{ Character'Val(45)} @AdaObjDefn{Minus_Sign} : Character @key[renames] Hyphen; @AdaObjDefn{Full_Stop} : @key[constant] Character := '.'; --@RI{ Character'Val(46)} @AdaObjDefn{Solidus} : @key[constant] Character := '/'; --@RI{ Character'Val(47)} @keepnext --@RI{ Decimal digits '0' though '9' are at positions 48 through 57} @AdaObjDefn{Colon} : @key[constant] Character := ':'; --@RI{ Character'Val(58)} @AdaObjDefn{Semicolon} : @key[constant] Character := ';'; --@RI{ Character'Val(59)} @AdaObjDefn{Less_Than_Sign} : @key[constant] Character := '<'; --@RI{ Character'Val(60)} @AdaObjDefn{Equals_Sign} : @key[constant] Character := '='; --@RI{ Character'Val(61)} @AdaObjDefn{Greater_Than_Sign} : @key[constant] Character := '>'; --@RI{ Character'Val(62)} @AdaObjDefn{Question} : @key[constant] Character := '?'; --@RI{ Character'Val(63)} @AdaObjDefn{Commercial_At} : @key[constant] Character := '@@'; --@RI{ Character'Val(64)} @keepnext --@RI{ Letters 'A' through 'Z' are at positions 65 through 90} @AdaObjDefn{Left_Square_Bracket} : @key[constant] Character := '['; --@RI{ Character'Val(91)} @AdaObjDefn{Reverse_Solidus} : @key[constant] Character := '\'; --@RI{ Character'Val(92)} @AdaObjDefn{Right_Square_Bracket} : @key[constant] Character := ']'; --@RI{ Character'Val(93)} @AdaObjDefn{Circumflex} : @key[constant] Character := '^'; --@RI{ Character'Val(94)} @AdaObjDefn{Low_Line} : @key[constant] Character := '_'; --@RI{ Character'Val(95)} @AdaObjDefn{Grave} : @key[constant] Character := '`'; --@RI{ Character'Val(96)} @AdaObjDefn{LC_A} : @key[constant] Character := 'a'; --@RI{ Character'Val(97)} @AdaObjDefn{LC_B} : @key[constant] Character := 'b'; --@RI{ Character'Val(98)} @AdaObjDefn{LC_C} : @key[constant] Character := 'c'; --@RI{ Character'Val(99)} @AdaObjDefn{LC_D} : @key[constant] Character := 'd'; --@RI{ Character'Val(100)} @AdaObjDefn{LC_E} : @key[constant] Character := 'e'; --@RI{ Character'Val(101)} @AdaObjDefn{LC_F} : @key[constant] Character := 'f'; --@RI{ Character'Val(102)} @AdaObjDefn{LC_G} : @key[constant] Character := 'g'; --@RI{ Character'Val(103)} @AdaObjDefn{LC_H} : @key[constant] Character := 'h'; --@RI{ Character'Val(104)} @AdaObjDefn{LC_I} : @key[constant] Character := 'i'; --@RI{ Character'Val(105)} @AdaObjDefn{LC_J} : @key[constant] Character := 'j'; --@RI{ Character'Val(106)} @AdaObjDefn{LC_K} : @key[constant] Character := 'k'; --@RI{ Character'Val(107)} @AdaObjDefn{LC_L} : @key[constant] Character := 'l'; --@RI{ Character'Val(108)} @AdaObjDefn{LC_M} : @key[constant] Character := 'm'; --@RI{ Character'Val(109)} @AdaObjDefn{LC_N} : @key[constant] Character := 'n'; --@RI{ Character'Val(110)} @AdaObjDefn{LC_O} : @key[constant] Character := 'o'; --@RI{ Character'Val(111)} @AdaObjDefn{LC_P} : @key[constant] Character := 'p'; --@RI{ Character'Val(112)} @AdaObjDefn{LC_Q} : @key[constant] Character := 'q'; --@RI{ Character'Val(113)} @AdaObjDefn{LC_R} : @key[constant] Character := 'r'; --@RI{ Character'Val(114)} @AdaObjDefn{LC_S} : @key[constant] Character := 's'; --@RI{ Character'Val(115)} @AdaObjDefn{LC_T} : @key[constant] Character := 't'; --@RI{ Character'Val(116)} @AdaObjDefn{LC_U} : @key[constant] Character := 'u'; --@RI{ Character'Val(117)} @AdaObjDefn{LC_V} : @key[constant] Character := 'v'; --@RI{ Character'Val(118)} @AdaObjDefn{LC_W} : @key[constant] Character := 'w'; --@RI{ Character'Val(119)} @AdaObjDefn{LC_X} : @key[constant] Character := 'x'; --@RI{ Character'Val(120)} @AdaObjDefn{LC_Y} : @key[constant] Character := 'y'; --@RI{ Character'Val(121)} @AdaObjDefn{LC_Z} : @key[constant] Character := 'z'; --@RI{ Character'Val(122)} @AdaObjDefn{Left_Curly_Bracket} : @key[constant] Character := '{'; --@RI{ Character'Val(123)} @AdaObjDefn{Vertical_Line} : @key[constant] Character := '|'; --@RI{ Character'Val(124)} @AdaObjDefn{Right_Curly_Bracket} : @key[constant] Character := '}'; --@RI{ Character'Val(125)} @AdaObjDefn{Tilde} : @key[constant] Character := '~'; --@RI{ Character'Val(126)} @AdaObjDefn{DEL} : @key[constant] Character := Character'Val(127); @keepnext--@RI{ ISO 6429 control characters:}@PDefn2{term=[control character], sec=[a category of Character]} @AdaObjDefn{IS4} : Character @key[renames] FS; @AdaObjDefn{IS3} : Character @key[renames] GS; @AdaObjDefn{IS2} : Character @key[renames] RS; @AdaObjDefn{IS1} : Character @key[renames] US; @AdaObjDefn{Reserved_128} : @key[constant] Character := Character'Val(128); @AdaObjDefn{Reserved_129} : @key[constant] Character := Character'Val(129); @AdaObjDefn{BPH} : @key[constant] Character := Character'Val(130); @AdaObjDefn{NBH} : @key[constant] Character := Character'Val(131); @AdaObjDefn{Reserved_132} : @key[constant] Character := Character'Val(132); @AdaObjDefn{NEL} : @key[constant] Character := Character'Val(133); @AdaObjDefn{SSA} : @key[constant] Character := Character'Val(134); @AdaObjDefn{ESA} : @key[constant] Character := Character'Val(135); @AdaObjDefn{HTS} : @key[constant] Character := Character'Val(136); @AdaObjDefn{HTJ} : @key[constant] Character := Character'Val(137); @AdaObjDefn{VTS} : @key[constant] Character := Character'Val(138); @AdaObjDefn{PLD} : @key[constant] Character := Character'Val(139); @AdaObjDefn{PLU} : @key[constant] Character := Character'Val(140); @AdaObjDefn{RI} : @key[constant] Character := Character'Val(141); @AdaObjDefn{SS2} : @key[constant] Character := Character'Val(142); @AdaObjDefn{SS3} : @key[constant] Character := Character'Val(143); @AdaObjDefn{DCS} : @key[constant] Character := Character'Val(144); @AdaObjDefn{PU1} : @key[constant] Character := Character'Val(145); @AdaObjDefn{PU2} : @key[constant] Character := Character'Val(146); @AdaObjDefn{STS} : @key[constant] Character := Character'Val(147); @AdaObjDefn{CCH} : @key[constant] Character := Character'Val(148); @AdaObjDefn{MW} : @key[constant] Character := Character'Val(149); @AdaObjDefn{SPA} : @key[constant] Character := Character'Val(150); @AdaObjDefn{EPA} : @key[constant] Character := Character'Val(151); @AdaObjDefn{SOS} : @key[constant] Character := Character'Val(152); @AdaObjDefn{Reserved_153} : @key[constant] Character := Character'Val(153); @AdaObjDefn{SCI} : @key[constant] Character := Character'Val(154); @AdaObjDefn{CSI} : @key[constant] Character := Character'Val(155); @AdaObjDefn{ST} : @key[constant] Character := Character'Val(156); @AdaObjDefn{OSC} : @key[constant] Character := Character'Val(157); @AdaObjDefn{PM} : @key[constant] Character := Character'Val(158); @AdaObjDefn{APC} : @key[constant] Character := Character'Val(159); @keepnext--@RI{ Other graphic characters:} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0181-1]} --@RI{ Character positions 160 (16#A0#) .. 175 (16#AF#):} @AdaObjDefn{No_Break_Space} : @key[constant] Character := ' '; --@RI{Character'Val(160)} @AdaObjDefn{NBSP} : Character @key[renames] No_Break_Space; @AdaObjDefn{Inverted_Exclamation} : @key[constant] Character := '@latin1(161)'; --@RI{Character'Val(161)} @AdaObjDefn{Cent_Sign} : @key[constant] Character := '@latin1(162)'; --@RI{Character'Val(162)} @AdaObjDefn{Pound_Sign} : @key[constant] Character := '@latin1(163)'; --@RI{Character'Val(163)} @AdaObjDefn{Currency_Sign} : @key[constant] Character := '@latin1(164)'; --@RI{Character'Val(164)} @AdaObjDefn{Yen_Sign} : @key[constant] Character := '@latin1(165)'; --@RI{Character'Val(165)} @AdaObjDefn{Broken_Bar} : @key[constant] Character := '@latin1(166)'; --@RI{Character'Val(166)} @AdaObjDefn{Section_Sign} : @key[constant] Character := '@latin1(167)'; --@RI{Character'Val(167)} @AdaObjDefn{Diaeresis} : @key[constant] Character := '@latin1(168)'; --@RI{Character'Val(168)} @AdaObjDefn{Copyright_Sign} : @key[constant] Character := '@latin1(169)'; --@RI{Character'Val(169)} @AdaObjDefn{Feminine_Ordinal_Indicator} : @key[constant] Character := '@latin1(170)'; --@RI{Character'Val(170)} @AdaObjDefn{Left_Angle_Quotation} : @key[constant] Character := '@latin1(171)'; --@RI{Character'Val(171)} @AdaObjDefn{Not_Sign} : @key[constant] Character := '@latin1(172)'; --@RI{Character'Val(172)} @AdaObjDefn{Soft_Hyphen} : @key[constant] Character := @Chg{Version=[3],New=[Character'Val(173);],Old=['@latin1(173)'; --@RI{Character'Val(173)}]} @AdaObjDefn{Registered_Trade_Mark_Sign} : @key[constant] Character := '@latin1(174)'; --@RI{Character'Val(174)} @AdaObjDefn{Macron} : @key[constant] Character := '@latin1(175)'; --@RI{Character'Val(175)} --@RI{ Character positions 176 (16#B0#) .. 191 (16#BF#):} @AdaObjDefn{Degree_Sign} : @key[constant] Character := '@latin1(176)'; --@RI{Character'Val(176)} @AdaObjDefn{Ring_Above} : Character @key[renames] Degree_Sign; @AdaObjDefn{Plus_Minus_Sign} : @key[constant] Character := '@latin1(177)'; --@RI{Character'Val(177)} @AdaObjDefn{Superscript_Two} : @key[constant] Character := '@latin1(178)'; --@RI{Character'Val(178)} @AdaObjDefn{Superscript_Three} : @key[constant] Character := '@latin1(179)'; --@RI{Character'Val(179)} @AdaObjDefn{Acute} : @key[constant] Character := '@latin1(180)'; --@RI{Character'Val(180)} @AdaObjDefn{Micro_Sign} : @key[constant] Character := '@latin1(181)'; --@RI{Character'Val(181)} @AdaObjDefn{Pilcrow_Sign} : @key[constant] Character := '@latin1(182)'; --@RI{Character'Val(182)} @AdaObjDefn{Paragraph_Sign} : Character @key[renames] Pilcrow_Sign; @AdaObjDefn{Middle_Dot} : @key[constant] Character := '@latin1(183)'; --@RI{Character'Val(183)} @AdaObjDefn{Cedilla} : @key[constant] Character := '@latin1(184)'; --@RI{Character'Val(184)} @AdaObjDefn{Superscript_One} : @key[constant] Character := '@latin1(185)'; --@RI{Character'Val(185)} @AdaObjDefn{Masculine_Ordinal_Indicator}: @key[constant] Character := '@latin1(186)'; --@RI{Character'Val(186)} @AdaObjDefn{Right_Angle_Quotation} : @key[constant] Character := '@latin1(187)'; --@RI{Character'Val(187)} @AdaObjDefn{Fraction_One_Quarter} : @key[constant] Character := '@latin1(188)'; --@RI{Character'Val(188)} @AdaObjDefn{Fraction_One_Half} : @key[constant] Character := '@latin1(189)'; --@RI{Character'Val(189)} @AdaObjDefn{Fraction_Three_Quarters} : @key[constant] Character := '@latin1(190)'; --@RI{Character'Val(190)} @AdaObjDefn{Inverted_Question} : @key[constant] Character := '@latin1(191)'; --@RI{Character'Val(191)} --@RI{ Character positions 192 (16#C0#) .. 207 (16#CF#):} @AdaObjDefn{UC_A_Grave} : @key[constant] Character := '@latin1(192)'; --@RI{Character'Val(192)} @AdaObjDefn{UC_A_Acute} : @key[constant] Character := '@latin1(193)'; --@RI{Character'Val(193)} @AdaObjDefn{UC_A_Circumflex} : @key[constant] Character := '@latin1(194)'; --@RI{Character'Val(194)} @AdaObjDefn{UC_A_Tilde} : @key[constant] Character := '@latin1(195)'; --@RI{Character'Val(195)} @AdaObjDefn{UC_A_Diaeresis} : @key[constant] Character := '@latin1(196)'; --@RI{Character'Val(196)} @AdaObjDefn{UC_A_Ring} : @key[constant] Character := '@latin1(197)'; --@RI{Character'Val(197)} @AdaObjDefn{UC_AE_Diphthong} : @key[constant] Character := '@latin1(198)'; --@RI{Character'Val(198)} @AdaObjDefn{UC_C_Cedilla} : @key[constant] Character := '@latin1(199)'; --@RI{Character'Val(199)} @AdaObjDefn{UC_E_Grave} : @key[constant] Character := '@latin1(200)'; --@RI{Character'Val(200)} @AdaObjDefn{UC_E_Acute} : @key[constant] Character := '@latin1(201)'; --@RI{Character'Val(201)} @AdaObjDefn{UC_E_Circumflex} : @key[constant] Character := '@latin1(202)'; --@RI{Character'Val(202)} @AdaObjDefn{UC_E_Diaeresis} : @key[constant] Character := '@latin1(203)'; --@RI{Character'Val(203)} @AdaObjDefn{UC_I_Grave} : @key[constant] Character := '@latin1(204)'; --@RI{Character'Val(204)} @AdaObjDefn{UC_I_Acute} : @key[constant] Character := '@latin1(205)'; --@RI{Character'Val(205)} @AdaObjDefn{UC_I_Circumflex} : @key[constant] Character := '@latin1(206)'; --@RI{Character'Val(206)} @AdaObjDefn{UC_I_Diaeresis} : @key[constant] Character := '@latin1(207)'; --@RI{Character'Val(207)} --@RI{ Character positions 208 (16#D0#) .. 223 (16#DF#):} @AdaObjDefn{UC_Icelandic_Eth} : @key[constant] Character := '@latin1(208)'; --@RI{Character'Val(208)} @AdaObjDefn{UC_N_Tilde} : @key[constant] Character := '@latin1(209)'; --@RI{Character'Val(209)} @AdaObjDefn{UC_O_Grave} : @key[constant] Character := '@latin1(210)'; --@RI{Character'Val(210)} @AdaObjDefn{UC_O_Acute} : @key[constant] Character := '@latin1(211)'; --@RI{Character'Val(211)} @AdaObjDefn{UC_O_Circumflex} : @key[constant] Character := '@latin1(212)'; --@RI{Character'Val(212)} @AdaObjDefn{UC_O_Tilde} : @key[constant] Character := '@latin1(213)'; --@RI{Character'Val(213)} @AdaObjDefn{UC_O_Diaeresis} : @key[constant] Character := '@latin1(214)'; --@RI{Character'Val(214)} @AdaObjDefn{Multiplication_Sign} : @key[constant] Character := '@latin1(215)'; --@RI{Character'Val(215)} @AdaObjDefn{UC_O_Oblique_Stroke} : @key[constant] Character := '@latin1(216)'; --@RI{Character'Val(216)} @AdaObjDefn{UC_U_Grave} : @key[constant] Character := '@latin1(217)'; --@RI{Character'Val(217)} @AdaObjDefn{UC_U_Acute} : @key[constant] Character := '@latin1(218)'; --@RI{Character'Val(218)} @AdaObjDefn{UC_U_Circumflex} : @key[constant] Character := '@latin1(219)'; --@RI{Character'Val(219)} @AdaObjDefn{UC_U_Diaeresis} : @key[constant] Character := '@latin1(220)'; --@RI{Character'Val(220)} @AdaObjDefn{UC_Y_Acute} : @key[constant] Character := '@latin1(221)'; --@RI{Character'Val(221)} @AdaObjDefn{UC_Icelandic_Thorn} : @key[constant] Character := '@latin1(222)'; --@RI{Character'Val(222)} @AdaObjDefn{LC_German_Sharp_S} : @key[constant] Character := '@latin1(223)'; --@RI{Character'Val(223)} --@RI{ Character positions 224 (16#E0#) .. 239 (16#EF#):} @AdaObjDefn{LC_A_Grave} : @key[constant] Character := '@latin1(224)'; --@RI{Character'Val(224)} @AdaObjDefn{LC_A_Acute} : @key[constant] Character := '@latin1(225)'; --@RI{Character'Val(225)} @AdaObjDefn{LC_A_Circumflex} : @key[constant] Character := '@latin1(226)'; --@RI{Character'Val(226)} @AdaObjDefn{LC_A_Tilde} : @key[constant] Character := '@latin1(227)'; --@RI{Character'Val(227)} @AdaObjDefn{LC_A_Diaeresis} : @key[constant] Character := '@latin1(228)'; --@RI{Character'Val(228)} @AdaObjDefn{LC_A_Ring} : @key[constant] Character := '@latin1(229)'; --@RI{Character'Val(229)} @AdaObjDefn{LC_AE_Diphthong} : @key[constant] Character := '@latin1(230)'; --@RI{Character'Val(230)} @AdaObjDefn{LC_C_Cedilla} : @key[constant] Character := '@latin1(231)'; --@RI{Character'Val(231)} @AdaObjDefn{LC_E_Grave} : @key[constant] Character := '@latin1(232)'; --@RI{Character'Val(232)} @AdaObjDefn{LC_E_Acute} : @key[constant] Character := '@latin1(233)'; --@RI{Character'Val(233)} @AdaObjDefn{LC_E_Circumflex} : @key[constant] Character := '@latin1(234)'; --@RI{Character'Val(234)} @AdaObjDefn{LC_E_Diaeresis} : @key[constant] Character := '@latin1(235)'; --@RI{Character'Val(235)} @AdaObjDefn{LC_I_Grave} : @key[constant] Character := '@latin1(236)'; --@RI{Character'Val(236)} @AdaObjDefn{LC_I_Acute} : @key[constant] Character := '@latin1(237)'; --@RI{Character'Val(237)} @AdaObjDefn{LC_I_Circumflex} : @key[constant] Character := '@latin1(238)'; --@RI{Character'Val(238)} @AdaObjDefn{LC_I_Diaeresis} : @key[constant] Character := '@latin1(239)'; --@RI{Character'Val(239)} --@RI{ Character positions 240 (16#F0#) .. 255 (16#FF#):} @AdaObjDefn{LC_Icelandic_Eth} : @key[constant] Character := '@latin1(240)'; --@RI{Character'Val(240)} @AdaObjDefn{LC_N_Tilde} : @key[constant] Character := '@latin1(241)'; --@RI{Character'Val(241)} @AdaObjDefn{LC_O_Grave} : @key[constant] Character := '@latin1(242)'; --@RI{Character'Val(242)} @AdaObjDefn{LC_O_Acute} : @key[constant] Character := '@latin1(243)'; --@RI{Character'Val(243)} @AdaObjDefn{LC_O_Circumflex} : @key[constant] Character := '@latin1(244)'; --@RI{Character'Val(244)} @AdaObjDefn{LC_O_Tilde} : @key[constant] Character := '@latin1(245)'; --@RI{Character'Val(245)} @AdaObjDefn{LC_O_Diaeresis} : @key[constant] Character := '@latin1(246)'; --@RI{Character'Val(246)} @AdaObjDefn{Division_Sign} : @key[constant] Character := '@latin1(247)'; --@RI{Character'Val(247)} @AdaObjDefn{LC_O_Oblique_Stroke} : @key[constant] Character := '@latin1(248)'; --@RI{Character'Val(248)} @AdaObjDefn{LC_U_Grave} : @key[constant] Character := '@latin1(249)'; --@RI{Character'Val(249)} @AdaObjDefn{LC_U_Acute} : @key[constant] Character := '@latin1(250)'; --@RI{Character'Val(250)} @AdaObjDefn{LC_U_Circumflex} : @key[constant] Character := '@latin1(251)'; --@RI{Character'Val(251)} @AdaObjDefn{LC_U_Diaeresis} : @key[constant] Character := '@latin1(252)'; --@RI{Character'Val(252)} @AdaObjDefn{LC_Y_Acute} : @key[constant] Character := '@latin1(253)'; --@RI{Character'Val(253)} @AdaObjDefn{LC_Icelandic_Thorn} : @key[constant] Character := '@latin1(254)'; --@RI{Character'Val(254)} @AdaObjDefn{LC_Y_Diaeresis} : @key[constant] Character := '@latin1(255)'; --@RI{Character'Val(255)} @key[end] Ada.Characters.Latin_1; @end{Example} @end{StaticSem} @begin{ImplPerm} An implementation may provide additional packages as children of Ada.Characters, to declare names for the symbols of the local character set or other character sets. @end{ImplPerm} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0181-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Soft_Hyphen is not a graphic character, and thus a character literal for it is illegal. So we have to use the position value. This makes no semantic change to users of the constant.]} @end{DiffWord2005} @RMNewPage@LabeledAddedSubClause{Version=[2],Name=[The Package Characters.Conversions]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The library package Characters.Conversions has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[package] Ada.Characters.Conversions @key[is]@ChildUnit{Parent=[Ada.Characters],Child=[Conversions]} @key[pragma] Pure(Conversions);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_String) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Character} (Item : @key[in] Wide_Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_String} (Item : @key[in] Wide_Wide_String) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Wide_Character} (Item : @key[in] Wide_Wide_Character) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Wide_String} (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Character; @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] String) @key[return] Wide_String; @key[function] @AdaSubDefn{To_Wide_Wide_Character} (Item : @key[in] Character) @key[return] Wide_Wide_Character; @key[function] @AdaSubDefn{To_Wide_Wide_String} (Item : @key[in] String) @key[return] Wide_Wide_String; @key[function] @AdaSubDefn{To_Wide_Wide_Character} (Item : @key[in] Wide_Character) @key[return] Wide_Wide_Character; @key[function] @AdaSubDefn{To_Wide_Wide_String} (Item : @key[in] Wide_String) @key[return] Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] @AdaSubDefn{To_Character} (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] @AdaSubDefn{To_String} (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] @AdaSubDefn{To_Wide_Character} (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_Character; @key[function] @AdaSubDefn{To_Wide_String} (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[end] Ada.Characters.Conversions;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The functions in package Characters.Conversions test Wide_Wide_Character or Wide_Character values for membership in Wide_Character or Character, or convert between corresponding characters of Wide_Wide_Character, Wide_Character, and Character.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Character (Item : @key[in] Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Character (Item : @key[in] Wide_Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Wide_Character'Pos(Item) <= Character'Pos(Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Wide_Character (Item : @key[in] Wide_Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Wide_Wide_Character'Pos(Item) <= Wide_Character'Pos(Wide_Character'Last).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_String (Item : @key[in] Wide_String) @key[return] Boolean; @key[function] Is_String (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Is_Character(Item(I)) is True for each I in Item'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] Is_Wide_String (Item : @key[in] Wide_Wide_String) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if Is_Wide_Character(Item(I)) is True for each I in Item'Range.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Character (Item : @key[in] Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character; @key[function] To_Character (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Character := ' ') @key[return] Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Character corresponding to Item if Is_Character(Item), and returns the Substitute Character otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Character (Item : @key[in] Character) @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Character X such that Character'Pos(Item) = Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Character (Item : @key[in] Wide_Wide_Character; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Character corresponding to Item if Is_Wide_Character(Item), and returns the Substitute Wide_Character otherwise.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Wide_Character (Item : @key[in] Character) @key[return] Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_Character X such that Character'Pos(Item) = Wide_Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_Wide_Character (Item : @key[in] Wide_Character) @key[return] Wide_Wide_Character;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_Character X such that Wide_Character'Pos(Item) = Wide_Wide_Character'Pos (X).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_String (Item : @key[in] Wide_String; Substitute : @key[in] Character := ' ') @key[return] String; @key[function] To_String (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Character := ' ') @key[return] String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the String whose range is 1..Item'Length and each of whose elements is given by To_Character of the corresponding element in Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_String (Item : @key[in] String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[function] To_Wide_String (Item : @key[in] Wide_Wide_String; Substitute : @key[in] Wide_Character := ' ') @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Character of the corresponding element in Item with the given Substitute Wide_Character.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key[function] To_Wide_Wide_String (Item : @key[in] String) @key[return] Wide_Wide_String; @key[function] To_Wide_Wide_String (Item : @key[in] Wide_String) @key[return] Wide_Wide_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the Wide_Wide_String whose range is 1..Item'Length and each of whose elements is given by To_Wide_Wide_Character of the corresponding element in Item.]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Characters.Conversions is new, replacing functions previously found in Characters.Handling.]} @end{Extend95} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledAddedSubClause{Version=[3],Name=[The Package Wide_Characters.Handling]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[The package Wide_Characters.Handling provides operations for classifying Wide_Characters and case folding for Wide_Characters.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[The library package Wide_Characters.Handling has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[@key[package] Ada.Wide_Characters.Handling @key[is]@ChildUnit{Parent=[Ada.Wide_Characters],Child=[Handling]} @key[pragma] Pure(Handling);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Character_Set_Version} @key[return] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Control} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Letter} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Lower} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Upper} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Digit} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Decimal_Digit} (Item : Wide_Character) @key[return] Boolean @key[renames] Is_Digit;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Hexadecimal_Digit} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Alphanumeric} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Special} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Line_Terminator} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Mark} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Other_Format} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Punctuation_Connector} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Space} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Graphic} (Item : Wide_Character) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{To_Lower} (Item : Wide_Character) @key[return] Wide_Character; @key[function] @AdaSubDefn{To_Upper} (Item : Wide_Character) @key[return] Wide_Character;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{To_Lower} (Item : Wide_String) @key[return] Wide_String; @key[function] @AdaSubDefn{To_Upper} (Item : Wide_String) @key[return] Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Wide_Characters.Handling;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[The subprograms defined in Wide_Characters.Handling are locale independent.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Character_Set_Version @key[return] String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns an implementation-defined identifier that identifies the version of the character set standard that is used for categorizing characters by the implementation.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Control (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{other_control}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Letter (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{letter_uppercase}, @ntf{letter_lowercase}, @ntf{letter_titlecase}, @ntf{letter_modifier}, @ntf{letter_other}, or @ntf{number_letter}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Keepnext=[T],Text=[@key[function] Is_Lower (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{letter_lowercase}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Upper (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{letter_uppercase}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Digit (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{number_decimal}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Hexadecimal_Digit (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{number_decimal}, or is in the range 'A' .. 'F' or 'a' .. 'f'; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Alphanumeric (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{letter_uppercase}, @ntf{letter_lowercase}, @ntf{letter_titlecase}, @ntf{letter_modifier}, @ntf{letter_other}, @ntf{number_letter}, or @ntf{number_decimal}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Special (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{graphic_character}, but not categorized as @ntf{letter_uppercase}, @ntf{letter_lowercase}, @ntf{letter_titlecase}, @ntf{letter_modifier}, @ntf{letter_other}, @ntf{number_letter}, or @ntf{number_decimal}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Line_Terminator (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{separator_line} or @ntf{separator_paragraph}, or if Item is a conventional line terminator character (Line_Feed, Line_Tabulation, Form_Feed, Carriage_Return, Next_Line); otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Mark (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{mark_non_spacing} or @ntf{mark_spacing_combining}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Other_Format (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{other_format}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Punctuation_Connector (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{punctuation_connector}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Space (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{separator_space}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Is_Graphic (Item : Wide_Character) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the Wide_Character designated by Item is categorized as @ntf{graphic_character}; otherwise returns False.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] To_Lower (Item : Wide_Character) @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1],ARef=[AI05-0266-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the Simple Lowercase Mapping as defined by documents referenced in the note in Clause 1 of ISO/IEC 10646:2011 of the Wide_Character designated by Item. If the Simple Lowercase Mapping does not exist for the Wide_Character designated by Item, then the value of Item is returned.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The case mappings come from Unicode as ISO/IEC 10646:2011 does not include case mappings (but rather references the Unicode ones as above).]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] To_Lower (Item : Wide_String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of applying the To_Lower conversion to each Wide_Character element of the Wide_String designated by Item. The result is the null Wide_String if the value of the formal parameter is the null Wide_String. The lower bound of the result Wide_String is 1.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] To_Upper (Item : Wide_Character) @key[return] Wide_Character;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1],ARef=[AI05-0266-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the Simple Uppercase Mapping as defined by documents referenced in the note in Clause 1 of ISO/IEC 10646:2011 of the Wide_Character designated by Item. If the Simple Uppercase Mapping does not exist for the Wide_Character designated by Item, then the value of Item is returned.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] To_Upper (Item : Wide_String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of applying the To_Upper conversion to each Wide_Character element of the Wide_String designated by Item. The result is the null Wide_String if the value of the formal parameter is the null Wide_String. The lower bound of the result Wide_String is 1.]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[The string returned by Character_Set_Version should include either @ldquote@;10646:@rdquote or @ldquote@;Unicode@rdquote@;.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The string returned by Wide_Characters.Handling.Character_Set_Version should include either @ldquote@;10646:@rdquote or @ldquote@;Unicode@rdquote@;.]}]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=<The intent is that the returned string include the year for 10646 (as in "10646:2011"), and the version number for Unicode (as in "Unicode 6.0"). We don't try to specify that further so we don't need to decide how to represent Corrigenda for 10646, nor which of these is preferred. (Giving a Unicode version is more accurate, as the case folding and mapping rules always come from a Unicode version [10646 just tells one to look at Unicode to get those], and the character classifications ought to be the same for equivalent versions, but we don't want to talk about non-ISO standards in an ISO standard.)>} @end{Discussion} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[The results returned by these functions may depend on which particular version of the 10646 standard is supported by the implementation (see @RefSecNum{Character Set}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[The case insensitive equality comparison routines provided in @RefSec{String Comparison} are also available for wide strings (see @RefSecNum{Wide_String Handling}).]} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1],ARef=[AI05-0266-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package Wide_Characters.Handling is new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[The Package Wide_Wide_Characters.Handling]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[The package Wide_Wide_Characters.Handling @ChildUnit{Parent=[Ada.Wide_Wide_Characters],Child=[Handling]}has the same contents as Wide_Characters.Handling except that each occurrence of Wide_Character is replaced by Wide_Wide_Character, and each occurrence of Wide_String is replaced by Wide_Wide_String.]} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0185-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package Wide_Wide_Characters.Handling is new.]} @end{Extend2005} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_cmdln.mss��������������������������������������������������������0000755�0001752�0001001�00000012014�12066652507�020113� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_cmdln.mss,v $ } @comment{ $Revision: 1.29 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(predefcmdln, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledClause{The Package Command_Line} @begin{Intro} The package Command_Line allows a program to obtain the values of its arguments and to set the exit status code to be returned on normal termination. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The meaning of Argument_Count, Argument, and Command_Name@Chg{Version=[2],New=[ for package Command_Line. The bounds of type Command_Line.Exit_Status],Old=[]}.]} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Ada.Command_Line has the following declaration: @begin{Example} @key[package] Ada.Command_Line @key[is]@ChildUnit{Parent=[Ada],Child=[Command_Line]} @key[pragma] Preelaborate(Command_Line); @key[function] @AdaSubDefn{Argument_Count} @key[return] Natural; @key[function] @AdaSubDefn{Argument} (Number : @key[in] Positive) @key[return] String; @key[function] @AdaSubDefn{Command_Name} @key[return] String; @key[type] @AdaTypeDefn{Exit_Status} @key[is] @RI{implementation-defined integer type}; @AdaObjDefn{Success} : @key[constant] Exit_Status; @AdaObjDefn{Failure} : @key[constant] Exit_Status; @key[procedure] @AdaSubDefn{Set_Exit_Status} (Code : @key[in] Exit_Status); @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Command_Line; @comment{Blank line} @end{example} @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Argument_Count @key[return] Natural; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If the external execution environment supports passing arguments to a program, then Argument_Count returns the number of arguments passed to the program invoking the function. Otherwise@Chg{Version=[3],New=[,],Old=[]} it returns 0. The meaning of @lquotes@;number of arguments@rquotes@; is implementation defined. @begin{Example}@Keepnext @key[function] Argument (Number : @key[in] Positive) @key[return] String; @end{Example} @Trailing@;If the external execution environment supports passing arguments to a program, then Argument returns an implementation-defined value corresponding to the argument at relative position Number. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If Number is outside the range 1..Argument_Count, then Constraint_Error is propagated. @begin{Ramification} If the external execution environment does not support passing arguments to a program, then Argument(N) for any N will raise Constraint_Error, since Argument_Count is 0.@end{ramification} @begin{Example}@Keepnext @key[function] Command_Name @key[return] String; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If the external execution environment supports passing arguments to a program, then Command_Name returns an implementation-defined value corresponding to the name of the command invoking the program; otherwise@Chg{Version=[3],New=[,],Old=[]} Command_Name returns the null string. @Comment{This is missing; leading the following paragraph glued to "Command_Name"} @begin{Example}@Keepnext @ChgRef{Version=[1],Kind=[Added]} @Chg{New=[@key[type] Exit_Status @key[is] @RI{implementation-defined integer type};],Old=[]} @end{Example} @Trailing@; The type Exit_Status represents the range of exit status values supported by the external execution environment. The constants Success and Failure correspond to success and failure, respectively. @begin{Example}@Keepnext @key[procedure] Set_Exit_Status (Code : @key[in] Exit_Status); @end{Example} If the external execution environment supports returning an exit status from a program, then Set_Exit_Status sets Code as the status. Normal termination of a program returns as the exit status the value most recently set by Set_Exit_Status, or, if no such value has been set, then the value Success. If a program terminates abnormally, the status set by Set_Exit_Status is ignored, and an implementation-defined exit status value is set. @ChgNote{An incorrect index entry; presentation AI-00005} @Chg{New=[],Old=[@PDefn{unspecified}]} If the external execution environment does not support returning an exit value from a program, then Set_Exit_Status does nothing. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} An alternative declaration is allowed for package Command_Line if different functionality is appropriate for the external execution environment. @end{ImplPerm} @begin{Notes} Argument_Count, Argument, and Command_Name correspond to the C language's argc, argv[n] (for n>0) and argv[0], respectively. @begin{Honest} The correspondence of Argument_Count to argc is not direct @em argc would be one more than Argument_Count, since the argc count includes the command name, whereas Argument_Count does not. @end{Honest} @end{Notes} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{extensions to Ada 83} This @Chg{Version=[3],New=[subclause],Old=[clause]} is new in Ada 95. @end{Extend83}��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_con2.mss���������������������������������������������������������0000755�0001752�0001001�00000707374�12066652506�017702� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� @Part(precontainers-2, Root="ada.mss") @comment{ $Source: e:\\cvsroot/ARM/Source/pre_con2.mss,v $ } @comment{ $Revision: 1.24 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Multiway_Trees]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Multiway_Trees provides private types Tree and Cursor, and a set of operations for each type. A multiway tree container is well-suited to represent nested structures.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[This tree just provides a basic structure, and make no promises about balancing or other automatic organization. In this sense, it is different than the indexed (Map, Set) forms. Rather, it provides a building block on which to construct more complex and more specialized tree containers.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[A multiway tree container object manages a tree of internal @i<nodes>, each of which contains an element and pointers to the parent, first child, last child, next (successor) sibling, and previous (predecessor) sibling internal nodes.@Defn2{Term=[node],Sec=[of a tree]} A cursor designates a particular node within a tree (and by extension the element contained in that node, if any). A cursor keeps designating the same node (and element) as long as the node is part of the container, even if the node is moved within the container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[A @i<subtree> is a particular node (which @i<roots the subtree>) and all of its child nodes (including all of the children of the child nodes, recursively). @Defn2{Term=[subtree],Sec=[of a tree]}@Defn{roots the subtree}@Defn2{Term=[subtree],Sec=[node which roots]} There is a special node, the @i<root>, which is always present and has neither an associated element value nor any parent node. The root node provides a place to add nodes to an otherwise empty tree and represents the base of the tree.@Defn2{Term=[root],Sec=[of a tree]}@Defn2{Term=[root node],Sec=[of a tree]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[A node that has no children is called a @i<leaf node>.@Defn2{Term=[leaf node],Sec=[of a tree]} The @i<ancestors> of a node are the node itself, its parent node, the parent of the parent node, and so on until a node with no parent is reached.@Defn2{Term=[ancestor],Sec=[of a tree node]} Similarly, the @i<descendants> of a node are the node itself, its child nodes, the children of each child node, and so on.@Defn2{Term=[descendant],Sec=[of a tree node]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The nodes of a subtree can be visited in several different orders. For a @i<depth-first order>, after visiting a node, the nodes of its child list are each visited in depth-first order, with each child node visited in natural order (first child to last child).@Defn{depth-first order}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For the depth-first order, when each child node is visited, the child list of the child node is visited before the next sibling of the child node is visited.]} @end{Ramification} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Multiway_Trees has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@key{with} Ada.Iterator_Interfaces; @key{generic} @key{type} Element_Type @key{is private}; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Multiway_Trees @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Multiway_Trees]} @key{pragma} Preelaborate(Multiway_Trees); @key{pragma} Remote_Types(Multiway_Trees);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{type} @AdaTypeDefn{Tree} @key{is tagged private} @key{with} Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type; @key{pragma} Preelaborable_Initialization(Tree);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{Empty_Tree} : @key{constant} Tree;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{package} @AdaPackDefn{Tree_Iterator_Interfaces} @key{is new} Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Equal_Subtree} (Left_Position : Cursor; Right_Position: Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} "=" (Left, Right : Tree) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Tree) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Node_Count} (Container : Tree) @key{return} Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Subtree_Node_Count} (Position : Cursor) @key{return} Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Depth} (Position : Cursor) @key{return} Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Root} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Leaf} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Root} (Container : Tree) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Tree);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Tree; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Tree; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Constant_Reference_Type} (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Tree; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Tree; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Assign} (Target : @key{in out} Tree; Source : @key{in} Tree);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Copy} (Source : Tree) @key{return} Tree;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Tree; Source : @key{in out} Tree);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Delete_Leaf} (Container : @key{in out} Tree; Position : @key{in out} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Delete_Subtree} (Container : @key{in out} Tree; Position : @key{in out} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} Tree; I, J : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Find} (Container : Tree; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Find_In_Subtree} (Position : Cursor; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Ancestor_Find} (Position : Cursor; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Tree; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Tree; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Iterate_Subtree} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Iterate} (Container : @key{in} Tree) @key{return} Tree_Iterator_Interfaces.Forward_Iterator'Class;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Iterate_Subtree} (Position : @key{in} Cursor) @key{return} Tree_Iterator_Interfaces.Forward_Iterator'Class;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Child_Count} (Parent : Cursor) @key{return} Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Child_Depth} (Parent, Child : Cursor) @key{return} Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Insert_Child} (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Insert_Child} (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Insert_Child} (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Prepend_Child} (Container : @key{in out} Tree; Parent : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Append_Child} (Container : @key{in out} Tree; Parent : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Delete_Children} (Container : @key{in out} Tree; Parent : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Copy_Subtree} (Target : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Splice_Subtree} (Target : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in out} Tree; Position : @key{in out} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Splice_Subtree} (Container: @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Splice_Children} (Target : @key{in out} Tree; Target_Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in out} Tree; Source_Parent : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Splice_Children} (Container : @key{in out} Tree; Target_Parent : @key{in} Cursor; Before : @key{in} Cursor; Source_Parent : @key{in} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Parent} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{First_Child} (Parent : Cursor) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{First_Child_Element} (Parent : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Last_Child} (Parent : Cursor) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Last_Child_Element} (Parent : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Next_Sibling} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Previous_Sibling} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Next_Sibling} (Position : @key{in out} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Previous_Sibling} (Position : @key{in out} Cursor);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Iterate_Children} (Parent : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate_Children} (Parent : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Iterate_Children} (Container : @key[in] Tree; Parent : @key[in] Cursor) @key[return] Tree_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private} ... -- @Examcom[not specified by the language] @key[end] Ada.Containers.Multiway_Trees;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the functions Find, Reverse_Find, Equal_Subtree, and "=" on tree values return an unspecified value. The exact arguments and number of calls of this generic formal function by the functions Find, Reverse_Find, Equal_Subtree, and "=" on tree values are unspecified.@PDefn{unspecified}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The type Tree is used to represent trees. The type Tree needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Empty_Tree represents the empty Tree object. It contains only the root node (Node_Count (Empty_Tree) returns 1). If an object of type Tree is not otherwise initialized, it is initialized to the same value as Empty_Tree.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Tree'Write for a Tree object @i<T> writes Node_Count(@i<T>) - 1 elements of the tree to the stream. It also may write additional information about the tree.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Tree'Read reads the representation of a tree from the stream, and assigns to @i<Item> a tree with the same elements and structure as was written by Tree'Write.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Streaming more elements than the container holds is wrong. For implementation implications of this rule, see the Implementation Note in @RefSecNum{The Generic Package Containers.Vectors}.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for "tampering with cursors" of a container because they depend on the set of elements of the container remaining constant, and others check for "tampering with elements" of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a tree]} A subprogram is said to @i{tamper with cursors} of a tree object @i<T> if:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it inserts or deletes elements of @i<T>, that is, it calls the Clear, Delete_Leaf, Insert_Child, Delete_Children, Delete_Subtree, or Copy_Subtree procedures with @i<T> as a parameter; or]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[it reorders the elements of @i<T>, that is, it calls the Splice_Subtree or Splice_Children procedures with @i<T> as a parameter; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it finalizes @i<T>; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it calls Assign with @i<T> as the Target parameter; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[We don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with cursors.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it calls the Move procedure with @i<T> as a parameter.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Swap copies elements rather than reordering them, so it doesn't tamper with cursors.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a tree]} A subprogram is said to @i{tamper with elements} of a tree object @i<T> if:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it tampers with cursors of @i<T>; or]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[it replaces one or more elements of @i<T>, that is, it calls the Replace_Element or Swap procedures with @i<T> as a parameter.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Assign is defined in terms of Clear and Replace_Element, so we don't need to mention it explicitly. Similarly, we don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with the element.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a tree]} @Defn2{Term=[tampering],Sec=[prohibited for a tree]} When tampering with cursors is @i<prohibited> for a particular tree object @i<T>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the cursors of @i<T>, leaving @i<T> unmodified. Similarly, when tampering with elements is @i<prohibited> for a particular tree object @i<T>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the elements of @i<T> @Redundant[(or tamper with the cursors of @i<T>)], leaving @i<T> unmodified.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we mention it only from completeness in the second sentence.]} @end{TheProof} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise. @Redundant[In particular, Has_Element returns False if the cursor designates a root node or equals No_Element.]]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[This function might not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Equal_Subtree (Left_Position : Cursor; Right_Position: Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Left_Position or Right_Position equals No_Element, propagates Constraint_Error. If the number of child nodes of the element designated by Left_Position is different from the number of child nodes of the element designated by Right_Position, the function returns False. If Left_Position designates a root node and Right_Position does not, the function returns False. If Right_Position designates a root node and Left_Position does not, the function returns False. Unless both cursors designate a root node, the elements are compared using the generic formal equality operator. If the result of the element comparison is False, the function returns False. Otherwise, it calls Equal_Subtree on a cursor designating each child element of the element designated by Left_Position and a cursor designating the corresponding child element of the element designated by Right_Position. If any such call returns False, the function returns False; otherwise, it returns True. Any exception raised during the evaluation of element equality is propagated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Left_Position and Right_Position do not need to be from the same tree.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Similarly, a global rule (see the introduction of @RefSecNum{Predefined Language Environment}) says that language-defined routines are not affected by overriding of other language-defined routines. This means that no reasonable program can tell how many times Equal_Subtree is called, and thus an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality or Equal_Subtree additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Tree) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Left and Right denote the same tree object, then the function returns True. Otherwise, it calls Equal_Subtree with cursors designating the root nodes of Left and Right; the result is returned. Any exception raised during the evaluation of Equal_Subtree is propagated.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Similar considerations apply here as apply to Equal_Subtree. The actual number of calls performed is unspecified.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Node_Count (Container : Tree) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Node_Count returns the number of nodes in Container.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Since all tree objects have a root node, this can never return a value of 0. Node_Count (Some_Tree) should always equal Subtree_Node_Count (Root (Some_Tree)).]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Subtree_Node_Count (Position : Cursor) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position is No_Element, Subtree_Node_Count returns 0; otherwise, Subtree_Node_Count returns the number of nodes in the subtree that is rooted by Position.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Tree) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Node_Count (Container) = 1.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[An empty tree contains just the root node.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Depth (Position : Cursor) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, Depth returns 0; otherwise, Depth returns the number of ancestor nodes of the node designated by Position (including the node itself).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Depth (Root (Some_Tree)) = 1.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Is_Root (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Is_Root returns True if the Position designates the root node of some tree; and returns False otherwise.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Is_Leaf (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Is_Leaf returns True if Position designates a node that does not have any child nodes; and returns False otherwise.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Is_Leaf returns False if passed No_Element, since No_Element does not designate a node. Is_Leaf can be passed a cursor that designates the root node; Is_Leaf will return True if passed the root node of an empty tree.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Root (Container : Tree) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Root returns a cursor that designates the root node of Container.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There is always a root node, even in an empty container, so this function never returns No_Element.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Tree);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Removes all the elements from Container.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The root node is not removed; all trees have a root node.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position designates the root node of a tree, then Program_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The root node does not contain an element, so that value cannot be read or written.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Tree; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container (including if it designates the root node), then Program_Error is propagated. Otherwise, Replace_Element assigns the value New_Item to the element designated by Position.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position designates the root node of a tree, then Program_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. Tampering with the elements of the tree that contains the element designated by Position is prohibited during the execution of the call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Tree; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0264-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container (including if it designates the root node), then Program_Error is propagated. Otherwise, Update_Element calls Process.@key{all} with the element designated by Position as the argument. Tampering with the elements of Container is prohibited during the execution of the call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{type} Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The types Constant_Reference_Type and Reference_Type need finalization.@PDefn2{Term=<needs finalization>,Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type or Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Reference_Type (and Constant_Reference_Type) will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Tree; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a tree given a cursor.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Tree; Position : @key[in] Cursor) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a tree given a cursor.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Assign (Target : @key{in out} Tree; Source : @key{in} Tree);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. Otherwise, the elements of Source are copied to Target as for an @nt{assignment_statement} assigning Source to Target.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each element in Target has a parent element that corresponds to the parent element of the Source element, and has child elements that correspond to the child elements of the Source element.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the bounded tree container. For an unbounded tree, @exam{Assign(A, B)} and @exam{A := B} behave identically. For a bounded tree, := will raise an exception if the container capacities are different, while Assign will not raise an exception if there is enough room in the target.]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Copy (Source : Tree) @key{return} Tree;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a tree with the same structure as Source and whose elements are initialized from the corresponding elements of Source.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Tree; Source : @key{in out} Tree);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, then the operation has no effect. Otherwise, Move first calls Clear (Target). Then, the nodes other than the root node in Source are moved to Target (in the same positions). After Move completes, Node_Count (Target) is the number of nodes originally in Source, and Node_Count (Source) is 1.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Delete_Leaf (Container : @key{in out} Tree; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container (including if it designates the root node), then Program_Error is propagated. If the element designated by position has any child elements, then Constraint_Error is propagated. Otherwise, Delete_Leaf removes (from Container) the element designated by Position. Finally, Position is set to No_Element.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The check on Position checks that the cursor does not belong to some other Container. This check implies that a reference to the container is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The root node cannot be deleted.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Delete_Subtree (Container : @key{in out} Tree; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0264-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container (including if it designates the root node), then Program_Error is propagated. Otherwise, Delete_Subtree removes (from Container) the subtree designated by Position (that is, all descendants of the node designated by Position including the node itself), and Position is set to No_Element.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The root node cannot be deleted. To delete the entire contents of the tree, call Clear(Container).]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} Tree; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If either I or J equals No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container (including if either designates the root node), then Program_Error is propagated. Otherwise, Swap exchanges the values of the elements designated by I and J.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[After a call to Swap, I designates the element value previously designated by J, and J designates the element value previously designated by I. The position of the elements do not change; for instance, the parent node and the first child node of I are unchanged by the operation.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The root nodes do not contain element values, so they cannot be swapped.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Find (Container : Tree; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the root node. The search traverses the tree in a depth-first order. If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Find_In_Subtree (Position : Cursor; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Find_In_Subtree searches the subtree rooted by Position for an element equal to Item (using the generic formal equality operator). The search starts at the element designated by Position. The search traverses the subtree in a depth-first order. If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Find_In_Subtree does not check any siblings of the element designated by Position. The root node does not contain an element, and therefore it can never be returned, but it can be explicitly passed to Position.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Ancestor_Find (Position : Cursor; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Ancestor_Find searches for an element equal to Item (using the generic formal equality operator). The search starts at the node designated by Position, and checks each ancestor proceeding toward the root of the subtree. If no equal element is found, then Ancestor_Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[No_Element is returned if Position is the root node.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Contains (Container : Tree; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Find (Container, Item) /= No_Element.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Tree; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each element in Container, starting with the root node and proceeding in a depth-first order. Tampering with the cursors of Container is prohibited during the execution of a call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Process is not called with the root node, which does not have an associated element.]} @end{Ramification} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The purpose of the tamper with cursors check is to prevent erroneous execution from the Position parameter of Process.@key{all} becoming invalid. This check takes place when the operations that tamper with the cursors of the container are called. The check cannot be made later (say in the body of Iterate), because that could cause the Position cursor to be invalid and potentially cause execution to become erroneous @em defeating the purpose of the check.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[See Iterate for vectors (@RefSecNum{The Generic Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Iterate_Subtree (Position : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Iterate_Subtree calls Process.@key{all} with a cursor that designates each element in the subtree rooted by the node designated by Position, starting with the node designated by Position and proceeding in a depth-first order. Tampering with the cursors of the tree that contains the element designated by Position is prohibited during the execution of a call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Position can be passed a cursor designating the root node; in that case, Process is not called with the root node, which does not have an associated element.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Iterate (Container : @key{in} Tree) @key{return} Tree_Iterator_Interfaces.Forward_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns an iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the root node and proceeding in a depth-first order. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Exits are allowed from the loops created using the iterator objects. In particular, to stop the iteration at a particular cursor, just add]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[exit when] Cur = Stop;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[in the body of the loop (assuming that @exam{Cur} is the loop parameter and @exam{Stop} is the cursor that you want to stop at).]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Iterate_Subtree (Position : @key{in} Cursor) @key{return} Tree_Iterator_Interfaces.Forward_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Iterate_Subtree returns an iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each element in the subtree rooted by the node designated by Position, starting with the node designated by Position and proceeding in a depth-first order. If Position equals No_Element, then Constraint_Error is propagated. Tampering with the cursors of the container that contains the node designated by Position is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Child_Count (Parent : Cursor) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Child_Count returns the number of child nodes of the node designated by Parent.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Child_Depth (Parent, Child : Cursor) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Child or Parent is equal to No_Element, then Constraint_Error is propagated. Otherwise, Child_Depth returns the number of ancestor nodes of Child (including Child itself), up to but not including Parent; Program_Error is propagated if Parent is not an ancestor of Child.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Program_Error is propagated if Parent and Child are nodes in different containers.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Child_Depth (Root (Some_Tree), Child) + 1 = Depth (Child) as the root is not counted.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Insert_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes containing copies of New_Item and inserts them as children of Parent. If Parent already has child nodes, then the new nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the new nodes are inserted after the last existing child node of Parent. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Insert_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0257-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes containing copies of New_Item and inserts them as children of Parent. If Parent already has child nodes, then the new nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the new nodes are inserted after the last existing child node of Parent. Position designates the first newly-inserted node, or if Count equals 0, then Position is assigned the value of Before. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Insert_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0257-1],ARef=[AI05-0262-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. Otherwise, Insert_Child allocates Count nodes, the elements contained in the new nodes are initialized by default (see @RefSecNum{Object Declarations}), and the new nodes are inserted as children of Parent. If Parent already has child nodes, then the new nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the new nodes are inserted after the last existing child node of Parent. Position designates the first newly-inserted node, or if Count equals 0, then Position is assigned the value of Before. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Prepend_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Insert_Child (Container, Parent, First_Child (Container, Parent), New_Item, Count).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Append_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Insert_Child (Container, Parent, No_Element, New_Item, Count).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Delete_Children (Container : @key{in out} Tree; Parent : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, Program_Error is propagated. Otherwise, Delete_Children removes (from Container) all of the descendants of Parent other than Parent itself.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This routine deletes all of the child subtrees of Parent at once. Use Delete_Subtree to delete an individual subtree.]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Copy_Subtree (Target : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Target, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Target, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. If Source designates a root node, then Constraint_Error is propagated. If Source is equal to No_Element, then the operation has no effect. Otherwise, the subtree rooted by Source (which can be from any tree; it does not have to be a subtree of Target) is copied (new nodes are allocated to create a new subtree with the same structure as the Source subtree, with each element initialized from the corresponding element of the Source subtree) and inserted into Target as a child of Parent. If Parent already has child nodes, then the new nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the new nodes are inserted after the last existing child node of Parent. The parent of the newly created subtree is set to Parent, and the overall count of Target is incremented by Subtree_Node_Count (Source). Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We only need one routine here, as the source object is not modified, so we can use the same routine for both copying within and between containers.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not allow copying a subtree that includes a root node, as that would require inserting a node with no value in the middle of the target tree. To copy an entire tree to another tree object, use Copy.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Splice_Subtree (Target : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in out} Tree; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Target, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Target, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. If Position equals No_Element, Constraint_Error is propagated. If Position does not designate a node in Source or designates a root node, then Program_Error is propagated. If Source denotes the same object as Target, then: if Position equals Before there is no effect; if Position designates an ancestor of Parent (including Parent itself), Constraint_Error is propagated; otherwise, the subtree rooted by the element designated by Position is moved to be a child of Parent. If Parent already has child nodes, then the moved nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved nodes are inserted after the last existing child node of Parent. In each of these cases, Position and the count of Target are unchanged, and the parent of the element designated by Position is set to Parent.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We can't allow moving the subtree of Position to a proper descendant node of the subtree, as the descendant node will be part of the subtree being moved. The result would be a circularly linked tree, or one with inaccessible nodes. Thus we have to check Position against Parent, even though such a check is @i<O>(Depth(Source)).]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Otherwise (if Source does not denote the same object as Target), the subtree designated by Position is removed from Source and moved to Target. The subtree is inserted as a child of Parent. If Parent already has child nodes, then the moved nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved nodes are inserted after the last existing child node of Parent. In each of these cases, the count of Target is incremented by Subtree_Node_Count (Position), and the count of Source is decremented by Subtree_Node_Count (Position), Position is updated to represent an element in Target.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If Source is the same as Target, and Position = Before, or Next_Sibling(Position) = Before, Splice_Subtree has no effect, as the subtree does not have to move to meet the postcondition.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not allow splicing a subtree that includes a root node, as that would require inserting a node with no value in the middle of the target tree. Splice the children of the root node instead.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For this reason there is no operation to splice an entire tree, as that would necessarily involve splicing a root node.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Splice_Subtree (Container: @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. If Position equals No_Element, Constraint_Error is propagated. If Position does not designate a node in Container or designates a root node, then Program_Error is propagated. If Position equals Before, there is no effect. If Position designates an ancestor of Parent (including Parent itself), Constraint_Error is propagated. Otherwise, the subtree rooted by the element designated by Position is moved to be a child of Parent. If Parent already has child nodes, then the moved nodes are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved nodes are inserted after the last existing child node of Parent. The parent of the element designated by Position is set to Parent.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We can't allow moving the subtree of Position to a proper descendant node of the subtree, as the descendant node will be part of the subtree being moved.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Splice_Children (Target : @key{in out} Tree; Target_Parent : @key{in} Cursor; Before : @key{in} Cursor; Source : @key{in out} Tree; Source_Parent : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target_Parent equals No_Element, then Constraint_Error is propagated. If Target_Parent does not designate a node in Target, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate an element in Target, then Program_Error is propagated. If Source_Parent equals No_Element, then Constraint_Error is propagated. If Source_Parent does not designate a node in Source, then Program_Error is propagated. If Before is not equal to No_Element, and Target_Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[If Source denotes the same object as Target, then:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[if Target_Parent equals Source_Parent there is no effect; else]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[if Source_Parent is an ancestor of Target_Parent other than Target_Parent itself, then Constraint_Error is propagated; else]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[the child elements (and the further descendants) of Source_Parent are moved to be child elements of Target_Parent. If Target_Parent already has child elements, then the moved elements are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved elements are inserted after the last existing child node of Target_Parent. The parent of each moved child element is set to Target_Parent.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We can't allow moving the children of Source_Parent to a proper descendant node, as the descendant node will be part of one of the subtrees being moved.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Otherwise (if Source does not denote the same object as Target), the child elements (and the further descendants) of Source_Parent are removed from Source and moved to Target. The child elements are inserted as children of Target_Parent. If Target_Parent already has child elements, then the moved elements are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved elements are inserted after the last existing child node of Target_Parent. In each of these cases, the overall count of Target is incremented by Subtree_Node_Count (Source_Parent)-1, and the overall count of Source is decremented by Subtree_Node_Count (Source_Parent)-1.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The node designated by Source_Parent is not moved, thus we never need to update Source_Parent.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Move (Target, Source) could be written Splice_Children (Target, Target.Root, No_Element, Source, Source.Root);]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Splice_Children (Container : @key{in out} Tree; Target_Parent : @key{in} Cursor; Before : @key{in} Cursor; Source_Parent : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1],ARef=[AI05-0264-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target_Parent equals No_Element, then Constraint_Error is propagated. If Target_Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and does not designate an element in Container, then Program_Error is propagated. If Source_Parent equals No_Element, then Constraint_Error is propagated. If Source_Parent does not designate a node in Container, then Program_Error is propagated. If Before is not equal to No_Element, and Target_Parent does not designate the parent node of the node designated by Before, then Constraint_Error is propagated. If Target_Parent equals Source_Parent there is no effect. If Source_Parent is an ancestor of Target_Parent other than Target_Parent itself, then Constraint_Error is propagated. Otherwise, the child elements (and the further descendants) of Source_Parent are moved to be child elements of Target_Parent. If Target_Parent already has child elements, then the moved elements are inserted prior to the node designated by Before, or, if Before equals No_Element, the moved elements are inserted after the last existing child node of Target_Parent. The parent of each moved child element is set to Target_Parent.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Parent (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position is equal to No_Element or designates a root node, No_Element is returned. Otherwise, a cursor designating the parent node of the node designated by Position is returned.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} First_Child (Parent : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent is equal to No_Element, then Constraint_Error is propagated. Otherwise, First_Child returns a cursor designating the first child node of the node designated by Parent; if there is no such node, No_Element is returned.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} First_Child_Element (Parent : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Element (First_Child (Parent)).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Last_Child (Parent : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent is equal to No_Element, then Constraint_Error is propagated. Otherwise, Last_Child returns a cursor designating the last child node of the node designated by Parent; if there is no such node, No_Element is returned.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Last_Child_Element (Parent : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Element (Last_Child (Parent)).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Next_Sibling (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element or designates the last child node of its parent, then Next_Sibling returns the value No_Element. Otherwise, it returns a cursor that designates the successor (with the same parent) of the node designated by Position.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Previous_Sibling (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Position equals No_Element or designates the first child node of its parent, then Previous_Sibling returns the value No_Element. Otherwise, it returns a cursor that designates the predecessor (with the same parent) of the node designated by Position.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Next_Sibling (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Position := Next_Sibling (Position);]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Previous_Sibling (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Position := Previous_Sibling (Position);]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Iterate_Children (Parent : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Iterate_Children calls Process.@key{all} with a cursor that designates each child node of Parent, starting with the first child node and moving the cursor as per the Next_Sibling function.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[Tampering with the cursors of the tree containing Parent is prohibited during the execution of a call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate_Children (Parent : @key{in} Cursor; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Parent equals No_Element, then Constraint_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Reverse_Iterate_Children calls Process.@key{all} with a cursor that designates each child node of Parent, starting with the last child node and moving the cursor as per the Previous_Sibling function.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[Tampering with the cursors of the tree containing Parent is prohibited during the execution of a call on Process.@key{all}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Iterate_Children (Container : @key[in] Tree; Parent : @key[in] Cursor) @key[return] Tree_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate_Children returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each child node of Parent. If Parent equals No_Element, then Constraint_Error is propagated. If Parent does not designate a node in Container, then Program_Error is propagated. Otherwise, when used as a forward iterator, the nodes are designated starting with the first child node and moving the cursor as per the function Next_Sibling; when used as a reverse iterator, the nodes are designated starting with the last child node and moving the cursor as per the function Previous_Sibling. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of this package, to tamper with elements of any Tree parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the Tree either prior to, or subsequent to, some or all of the modifications to the Tree.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram declared in the visible part of Containers.Multiway_Trees when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[A Cursor value is @i<invalid> if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a tree]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The tree that contains the element it designates has been finalized;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The tree that contains the element it designates has been used as the Source or Target of a call to Move;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The tree that contains the element it designates has been used as the Target of a call to Assign or the target of an @nt{assignment_statement};]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The element it designates has been removed from the tree that previously contained the element.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We talk about which tree the element was removed from in order to handle splicing nodes from one tree to another. The node still exists, but any cursors that designate it in the original tree are now invalid. This bullet covers removals caused by calls to Clear, Delete_Leaf, Delete_Subtree, Delete_Children, Splice_Children, and Splice_Subtree.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The result of "=" or Has_Element is unspecified if it is called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Multiway_Trees is called with an invalid cursor parameter.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element (or the root node). For instance, cursor values survive the insertion and deletion of other nodes.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the tree associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[No storage associated with a multiway tree object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The execution of an @nt{assignment_statement} for a tree shall have the effect of copying the elements from the source tree object to the target tree object and changing the node count of the target object to that of the source object.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[An assignment of a Tree is a @lquotes@;deep@rquotes copy; that is the elements are copied as well the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed. (Note that this implementation would require care, see @RefSecNum{The Generic Package Containers.Vectors} for more.)]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[Containers.Multiway_Trees should be implemented similarly to a multiway tree. In particular, if @i{N} is the overall number of nodes for a particular tree, then the worst-case time complexity of Element, Parent, First_Child, Last_Child, Next_Sibling, Previous_Sibling, Insert_Child with Count=1, and Delete should be @i{O}(log @i{N}).]} @ChgImplAdvice{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[The worst-case time complexity of the Element, Parent, First_Child, Last_Child, Next_Sibling, Previous_Sibling, Insert_Child with Count=1, and Delete operations of Containers.Multiway_Trees should be @i{O}(log @i<N>).]}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i<N>) time to access elements, that program could be unusable when the trees are large. We allow @i{O}(log @i<N>) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[Containers.Multiway_Trees.Move should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[If an exception is propagated from a tree operation, no storage should be lost, nor any elements removed from a tree unless specified by the operation.]} @ChgImplAdvice{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[If an exception is propagated from a tree operation, no storage should be lost, nor any elements removed from a tree unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0257-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Multiway_Trees is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Vectors]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Vectors provides a private type Vector and a set of operations. It provides the same operations as the package Containers.Vectors (see @RefSecNum{The Generic Package Containers.Vectors}), with the difference that the generic formal Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Vectors@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Vectors]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.Vectors except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedures with the profiles:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[F],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[are omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These procedures are omitted because there is no way to create a default-initialized object of an indefinite type. Note that Insert_Space can be used instead of this routine in most cases. Omitting the routine completely allows any problems to be diagnosed by the compiler when converting from a definite to indefinite vector.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Vectors is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Doubly_Linked_Lists]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Doubly_Linked_Lists provides private types List and Cursor, and a set of operations for each type. It provides the same operations as the package Containers.Doubly_Linked_Lists (see @RefSecNum{The Generic Package Containers.Doubly_Linked_Lists}), with the difference that the generic formal Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.@!Indefinite_@!Doubly_@!Linked_@!Lists@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Doubly_Linked_Lists]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.@!Doubly_@!Linked_@!Lists except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing definite container. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Doubly_Linked_Lists is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Hashed_Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Hashed_Maps provides a map with the same operations as the package Containers.Hashed_Maps (see @RefSecNum{The Generic Package Containers.Hashed_Maps}), with the difference that the generic formal types Key_Type and Element_Type are indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Hashed_Maps@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Hashed_Maps]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.Hashed_Maps except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Key_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Hashed_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Ordered_Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Ordered_Maps provides a map with the same operations as the package Containers.Ordered_Maps (see @RefSecNum{The Generic Package Containers.Ordered_Maps}), with the difference that the generic formal types Key_Type and Element_Type are indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Ordered_Maps@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Ordered_Maps]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.Ordered_Maps except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Key_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Ordered_Maps is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Hashed_Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Hashed_Sets provides a set with the same operations as the package Containers.Hashed_Sets (see @RefSecNum{The Generic Package Containers.Hashed_Sets}), with the difference that the generic formal type Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Hashed_Sets@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Hashed_Sets]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.Hashed_Sets except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_@!Element_@!Preserving_Key may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Hashed_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Indefinite_Ordered_Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Indefinite_Ordered_Sets provides a set with the same operations as the package Containers.Ordered_Sets (see @RefSecNum{The Generic Package Containers.Ordered_Sets}), with the difference that the generic formal type Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Ordered_Sets@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Ordered_Sets]} has the same contents @Chg{Version=[3],New=[and semantics ],Old=[]}as Containers.Ordered_Sets except:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The actual Element parameter of access subprogram Process of Update_@!Element_@!Preserving_Key may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Indefinite_Ordered_Sets is new.]} @end{Extend95} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Indefinite_Multiway_Trees]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Indefinite_Multiway_Trees provides a multiway tree with the same operations as the package Containers.Multiway_Trees (see @RefSecNum{The Generic Package Containers.Multiway_Trees}), with the difference that the generic formal Element_Type is indefinite.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Indefinite_Multiway_Trees@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Multiway_Trees]} has the same contents and semantics as Containers.Multiway_Trees except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The generic formal Element_Type is indefinite.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Keepnext=[T],Type=[Leading],Text=[The procedure with the profile:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Keepnext=[T],Type=[Leading],Text=[@key{procedure} Insert_Child (Container : @key{in out} Tree; Parent : @key{in} Cursor; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[is omitted.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This procedure is omitted because there is no way to create a default-initialized object of an indefinite type. We considered having this routine insert an empty element similar to the empty elements of a vector, but rejected this possibility because the semantics are fairly complex and very different from the existing case. That would make it more error-prone to convert a container from a definite type to an indefinite type; by omitting the routine completely, any problems will be diagnosed by the compiler.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The actual Element parameter of access subprogram Process of Update_Element may be constrained even if Element_Type is unconstrained.]} @end{Itemize} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Indefinite_Multiway_Trees is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Indefinite_Holders]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Indefinite_Holders provides a private type Holder and a set of operations for that type. A holder container holds a single element of an indefinite type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[A holder container allows the declaration of an object that can be used like an uninitialized variable or component of an indefinite type.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[A holder container may be @i{empty}. An empty holder does not contain an element.@Defn{empty holder}]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Indefinite_Holders has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],Aref=[AI05-0069-1],Aref=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@key[generic] @key[type] Element_Type (<>) @key[is private]; @key[with function] "=" (Left, Right : Element_Type) @key[return] Boolean @key[is] <>; @key[package] Ada.Containers.Indefinite_Holders @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Indefinite_Holders]} @key[pragma] Preelaborate(Indefinite_Holders); @key[pragma] Remote_Types(Indefinite_Holders);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Holder} @key[is tagged private]; @key[pragma] Preelaborable_Initialization (Holder);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{Empty_Holder} : @key[constant] Holder;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] "=" (Left, Right : Holder) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{To_Holder} (New_Item : Element_Type) @key[return] Holder;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Is_Empty} (Container : Holder) @key[return] Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Clear} (Container : @key[in out] Holder);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Element} (Container : Holder) @key[return] Element_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Replace_Element} (Container : @key[in out] Holder; New_Item : @key[in] Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Query_Element} (Container : @key[in] Holder; Process : @key[not null access procedure] (Element : @key[in] Element_Type));]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Update_Element} (Container : @key[in out] Holder; Process : @key[not null access procedure] (Element : @key[in out] Element_Type));]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Constant_Reference_Type} (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Holder) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Holder) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign} (Target : @key[in out] Holder; Source : @key[in] Holder);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Holder) @key[return] Holder;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Move} (Target : @key[in out] Holder; Source : @key[in out] Holder);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ ... -- @Examcom[not specified by the language]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Indefinite_Holders;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the function "=" on holder values returns an unspecified value. The exact arguments and number of calls of this generic formal function by the function "=" on holder values are unspecified.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by any of the functions defined to use "=" cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other "bad" behavior. And it can call "=" in whatever manner makes sense. But note that only the results of the function "=" is unspecified; other subprograms are not allowed to break if "=" is bad.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[The type Holder is used to represent holder containers. The type Holder needs finalization@PDefn2{Term=<needs finalization>, Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[Empty_Holder represents an empty holder object. If an object of type Holder is not otherwise initialized, it is initialized to the same value as Empty_Holder.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @ldquote@;tampering with the element@rdquote of a container because they depend on the element of the container not being replaced.]]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a holder]} A subprogram is said to @i{tamper with the element} of a holder object @i<H> if:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It clears the element contained by @i<H>, that is, it calls the Clear procedure with @i<H> as a parameter;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It replaces the element contained by @i<H>, that is, it calls the Replace_Element procedure with @i<H> as a parameter;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It calls the Move procedure with @i<H> as a parameter;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It finalizes @i<H>.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a holder]} @Defn2{Term=[tampering],Sec=[prohibited for a holder]} When tampering with the element is @i<prohibited> for a particular holder object @i<H>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the element of @i<H>, leaving @i<H> unmodified.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Holder) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Left and Right denote the same holder object, then the function returns True. Otherwise, it compares the element contained in Left to the element contained in Right using the generic formal equality operator, returning the result of that operation. Any exception raised during the evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality @key[function] is unspecified, so an implementation need not call the equality function if the correct answer can be determined without doing so.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] To_Holder (New_Item : Element_Type) @key[return] Holder;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a nonempty holder containing an element initialized to New_Item.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Is_Empty (Container : Holder) @key[return] Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Container is empty, and False if it contains an element.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Clear (Container : @key[in out] Holder);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Removes the element from Container. Container is empty after a successful Clear operation.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Element (Container : Holder) @key[return] Element_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Container is empty, Constraint_Error is propagated. Otherwise, returns the element stored in Container.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Replace_Element (Container : @key[in out] Holder; New_Item : @key[in] Element_Type);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Replace_Element assigns the value New_Item into Container, replacing any preexisting content of Container. Container is not empty after a successful call to Replace_Element.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Query_Element (Container : @key[in] Holder; Process : @key[not null access procedure] (Element : @key[in] Element_Type));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Container is empty, Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key[all] with the contained element as the argument. Tampering with the element of Container is prohibited during the execution of the call on Process.@key[all]. Any exception raised by Process.@key[all] is propagated.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[The @ldquote@;tamper with the element@rdquote check is intended to prevent the Element parameter of Process from being replaced or deleted outside of Process. The check prevents data loss (if Element_Type is passed by copy) or erroneous execution (if Element_Type is an unconstrained type).]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Update_Element (Container : @key[in out] Holder; Process : @key[not null access procedure] (Element : @key[in out] Element_Type));]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Container is empty, Constraint_Error is propagated. Otherwise, Update_Element calls Process.@key[all] with the contained element as the argument. Tampering with the element of Container is prohibited during the execution of the call on Process.@key[all]. Any exception raised by Process.@key[all] is propagated.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The Element parameter of Process.@key[all] may be constrained even if Element_Type is unconstrained.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The types Constant_Reference_Type and Reference_Type need finalization.@PDefn2{Term=<needs finalization>,Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type or Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Reference_Type (and Constant_Reference_Type) will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Holder) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Implicit_Dereference aspect) provides a convenient way to gain read access to the contained element of a holder container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Container is empty, Constraint_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the contained element. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Holder) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Implicit_Dereference aspects) provides a convenient way to gain read and write access to the contained element of a holder container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Container is empty, Constraint_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the contained element. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Assign (Target : @key[in out] Holder; Source : @key[in] Holder);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. If Source is empty, Clear (Target) is called. Otherwise, Replace_Element (Target, Element (Source)) is called.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the other containers. For a holder, @exam{Assign(A, B)} and @exam{A := B} behave effectively the same. (Assign Clears the Target, while := finalizes the Target, but these should have similar effects.)]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Copy (Source : Holder) @key[return] Holder;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Source is empty, returns an empty holder container; otherwise, returns To_Holder (Element (Source)).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Move (Target : @key[in out] Holder; Source : @key[in out] Holder);]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, then the operation has no effect. Otherwise, the element contained by Source (if any) is removed from Source and inserted into Target, replacing any preexisting content. Source is empty after a successful call to Move.]} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0022-1],ARef=[AI05-0069-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of this package, to tamper with the element of any Holder parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the Holder either prior to, or subsequent to, some or all of the modifications to the Holder.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0027-1],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram declared in the visible part of Containers.Indefinite_Holders when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the holder container associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[No storage associated with a holder object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The execution of an @nt{assignment_statement} for a holder container shall have the effect of copying the element (if any) from the source holder object to the target holder object.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],Text=[An assignment of a holder container is a @ldquote@;deep@rdquote copy; that is the element is copied as well as any data structures. We say @ldquote@;effect of@rdquote in order to allow the implementation to avoid copying the element immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed. (Note that this implementation would require care, see @RefSecNum{The Generic Package Containers.Vectors} for more.)]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Move should not copy the element, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Containers.Indefinite_Holders.Move should not copy the element, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source holder to the Target holder.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[If an exception is propagated from a holder operation, no storage should be lost, nor should the element be removed from a holder container unless specified by the operation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[If an exception is propagated from a holder operation, no storage should be lost, nor should the element be removed from a holder container unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0069-1],ARef=[AI05-0084-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Indefinite_Holders is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Vectors]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Vectors provides a private type Vector and a set of operations. It provides the same operations as the package Containers.Vectors (see @RefSecNum{The Generic Package Containers.Vectors}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Vectors has the same contents and semantics as Containers.Vectors except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Vector is declared with a discriminant that specifies the capacity:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key{type} Vector (Capacity : Count_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Vector needs finalization if and only if type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Vector cannot depend on package Ada.Finalization unless the element type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In function Copy, if the Capacity parameter is equal to or greater than the length of Source, the vector capacity exactly equals the value of the Capacity parameter.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The description of Reserve_Capacity is replaced with:]} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If the specified Capacity is larger than the capacity of Container, then Reserve_Capacity propagates Capacity_Error. Otherwise, the operation has no effect.]} @end{Indent} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded vector object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded vector object @i<V> is finalized, if tampering with cursors is prohibited for @i<V> other than due to an assignment from another vector, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Vectors and each instance of Containers.Bounded_Vectors, if the two instances meet the following conditions, then the output generated by the Vector'Output or Vector'Write subprograms of either instance shall be readable by the Vector'Input or Vector'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters); and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the preceding two conditions also hold for the Index_Type parameters of the instances.]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Bounded vector objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded vector objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded vectors.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Vectors is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Doubly_Linked_Lists]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Doubly_Linked_Lists provides a private type List and a set of operations. It provides the same operations as the package Containers.Doubly_Linked_Lists (see @RefSecNum{The Generic Package Containers.Doubly_Linked_Lists}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Doubly_Linked_Lists has the same contents and semantics as Containers.Doubly_Linked_Lists except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type List is declared with a discriminant that specifies the capacity (maximum number of elements) as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key{type} List (Capacity : Count_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type List needs finalization if and only if type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type List cannot depend on package Ada.Finalization unless the element type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The allocation of internal storage includes a check that the capacity is not exceeded, and Capacity_Error is raised if this check fails.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In procedure Assign, if Source length is greater than Target capacity, then Capacity_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The function Copy is replaced with:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Copy} (Source : List; Capacity : Count_Type := 0) @key[return] List;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[If Capacity is 0, then the list capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the list capacity equals the value of the Capacity parameter; otherwise, the operation propagates Capacity_Error.]} @end{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In the three-parameter procedure Splice whose Source has type List, if the sum of the length of Target and the length of Source is greater than the capacity of Target, then Splice propagates Capacity_Error.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In the four-parameter procedure Splice, if the length of Target equals the capacity of Target, then Splice propagates Capacity_Error.]} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded list object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded list object @i<L> is finalized, if tampering with cursors is prohibited for @i<L> other than due to an assignment from another list, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Doubly_Linked_Lists and each instance of Containers.Bounded_Doubly_Linked_Lists, if the two instances meet the following conditions, then the output generated by the List'Output or List'Write subprograms of either instance shall be readable by the List'Input or List'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters).]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Bounded list objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded list objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded lists.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Doubly_Linked_Lists is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Hashed_Maps]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Hashed_Maps provides a private type Map and a set of operations. It provides the same operations as the package Containers.Hashed_Maps (see @RefSecNum{The Generic Package Containers.Hashed_Maps}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Hashed_Maps has the same contents and semantics as Containers.Hashed_Maps except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Map is declared with discriminants that specify both the capacity (number of elements) and modulus (number of distinct hash values) of the hash table as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[type] Map (Capacity : Count_Type; Modulus : Hash_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Map needs finalization if and only if type Key_Type or type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Map cannot depend on package Ada.Finalization unless the element or key type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The description of Reserve_Capacity is replaced with:]} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If the specified Capacity is larger than the capacity of Container, then Reserve_Capacity propagates Capacity_Error. Otherwise, the operation has no effect.]} @end{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[An additional operation is added immediately following Reserve_Capacity:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Default_Modulus} (Capacity : Count_Type) @key[return] Hash_Type;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Default_Modulus returns an implementation-defined value for the number of distinct hash values to be used for the given capacity (maximum number of elements).]} @end{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The function Copy is replaced with:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Map; Capacity : Count_Type := 0; Modulus : Hash_Type := 0) @key[return] Map;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Returns a map with key/element pairs initialized from the values in Source. If Capacity is 0, then the map capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the map capacity is the value of the Capacity parameter; otherwise, the operation propagates Capacity_Error. If the Modulus argument is 0, then the map modulus is the value returned by a call to Default_Modulus with the map capacity as its argument; otherwise, the map modulus is the value of the Modulus parameter.]} @end{Indent} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded map object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded map object @i<M> is finalized, if tampering with cursors is prohibited for @i<M> other than due to an assignment from another map, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Hashed_Maps and each instance of Containers.Bounded_Hashed_Maps, if the two instances meet the following conditions, then the output generated by the Map'Output or Map'Write subprograms of either instance shall be readable by the Map'Input or Map'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters); and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the preceding two conditions also hold for the Key_Type parameters of the instances.]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Bounded hashed map objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded hashed map objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded hashed maps.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Hashed_Maps is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Ordered_Maps]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Ordered_Maps provides a private type Map and a set of operations. It provides the same operations as the package Containers.Ordered_Maps (see @RefSecNum{The Generic Package Containers.Ordered_Maps}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Ordered_Maps has the same contents and semantics as Containers.Ordered_Maps except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Map is declared with a discriminant that specifies the capacity (maximum number of elements) as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[type] Map (Capacity : Count_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Map needs finalization if and only if type Key_Type or type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Map cannot depend on package Ada.Finalization unless the element type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The allocation of a new node includes a check that the capacity is not exceeded, and Capacity_Error is raised if this check fails.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In procedure Assign, if Source length is greater than Target capacity, then Capacity_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The function Copy is replaced with:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Map; Capacity : Count_Type := 0) @key[return] Map;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Returns a map with key/element pairs initialized from the values in Source. If Capacity is 0, then the map capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the map capacity is the specified value; otherwise, the operation propagates Capacity_Error.]} @end{Indent} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded map object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded map object @i<M> is finalized, if tampering with cursors is prohibited for @i<M> other than due to an assignment from another map, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Ordered_Maps and each instance of Containers.Bounded_Ordered_Maps, if the two instances meet the following conditions, then the output generated by the Map'Output or Map'Write subprograms of either instance shall be readable by the Map'Input or Map'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters); and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the preceding two conditions also hold for the Key_Type parameters of the instances.]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Bounded ordered map objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded ordered map objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded ordered maps.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Ordered_Maps is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Hashed_Sets]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Hashed_Sets provides a private type Set and a set of operations. It provides the same operations as the package Containers.Hashed_Sets (see @RefSecNum{The Generic Package Containers.Hashed_Sets}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Hashed_Sets has the same contents and semantics as Containers.Hashed_Sets except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Set is declared with discriminants that specify both the capacity (number of elements) and modulus (number of distinct hash values) of the hash table as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[type] Set (Capacity : Count_Type; Modulus : Hash_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Set needs finalization if and only if type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Set cannot depend on package Ada.Finalization unless the element or key type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The description of Reserve_Capacity is replaced with:]} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[If the specified Capacity is larger than the capacity of Container, then Reserve_Capacity propagates Capacity_Error. Otherwise, the operation has no effect.]} @end{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[An additional operation is added immediately following Reserve_Capacity:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Default_Modulus} (Capacity : Count_Type) @key[return] Hash_Type;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Default_Modulus returns an implementation-defined value for the number of distinct hash values to be used for the given capacity (maximum number of elements).]} @end{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The function Copy is replaced with:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Set; Capacity : Count_Type := 0; Modulus : Hash_Type := 0) @key[return] Set;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Returns a set whose elements are initialized from the values in Source. If Capacity is 0, then the set capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the set capacity is the value of the Capacity parameter; otherwise, the operation propagates Capacity_Error. If the Modulus argument is 0, then the set modulus is the value returned by a call to Default_Modulus with the set capacity as its argument; otherwise, the set modulus is the value of the Modulus parameter.]} @end{Indent} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded set object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded set object @i<S> is finalized, if tampering with cursors is prohibited for @i<S> other than due to an assignment from another set, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Hashed_Sets and each instance of Containers.Bounded_Hashed_Sets, if the two instances meet the following conditions, then the output generated by the Set'Output or Set'Write subprograms of either instance shall be readable by the Set'Input or Set'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters).]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Bounded hashed set objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded hashed set objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded hashed sets.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Hashed_Sets is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Ordered_Sets]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Ordered_Sets provides a private type Set and a set of operations. It provides the same operations as the package Containers.Ordered_Sets (see @RefSecNum{The Generic Package Containers.Ordered_Sets}), with the difference that the maximum storage is bounded.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Ordered_Sets has the same contents and semantics as Containers.Ordered_Sets except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Set is declared with a discriminant that specifies the capacity (maximum number of elements) as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key{type} Set (Capacity : Count_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Set needs finalization if and only if type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Set cannot depend on package Ada.Finalization unless the element type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If Insert (or Include) adds an element, a check is made that the capacity is not exceeded, and Capacity_Error is raised if this check fails.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In procedure Assign, if Source length is greater than Target capacity, then Capacity_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The function Copy is replaced with:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Set; Capacity : Count_Type := 0) @key[return] Set;]} @end{Example} @begin{Indent} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[Returns a set whose elements are initialized from the values in Source. If Capacity is 0, then the set capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the set capacity is the specified value; otherwise, the operation propagates Capacity_Error.]} @end{Indent} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded set object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded set object @i<S> is finalized, if tampering with cursors is prohibited for @i<S> other than due to an assignment from another set, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Ordered_Sets and each instance of Containers.Bounded_Ordered_Sets, if the two instances meet the following conditions, then the output generated by the Set'Output or Set'Write subprograms of either instance shall be readable by the Set'Input or Set'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters).]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Bounded ordered set objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded ordered set objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded ordered sets.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0160-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Ordered_Sets is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Multiway_Trees]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Multiway_Trees provides a private type Tree and a set of operations. It provides the same operations as the package Containers.Multiway_Trees (see @RefSecNum{The Generic Package Containers.Multiway_Trees}), with the difference that the maximum storage is bounded.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The declaration of the generic library package Containers.Bounded_Multiway_Trees has the same contents and semantics as Containers.Multiway_Trees except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The @nt{pragma} Preelaborate is replaced with @nt{pragma} Pure.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[The type Tree is declared with a discriminant that specifies the capacity (maximum number of elements) as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key{type} Tree (Capacity : Count_Type) @key[is tagged private];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The type Tree needs finalization if and only if type Element_Type needs finalization.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The type Tree cannot depend on package Ada.Finalization unless the element type depends on that package. The objects returned from the Iterator and Reference functions probably do depend on package Ada.Finalization. Restricted environments may need to avoid use of those functions and their associated types.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The allocation of internal storage includes a check that the capacity is not exceeded, and Capacity_Error is raised if this check fails.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In procedure Assign, if Source length is greater than Target capacity, then Capacity_Error is propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Function Copy is declared as follows:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[ @key{function} Copy (Source : Tree; Capacity : Count_Type := 0) @key{return} List;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Noprefix=[T],Text=[If Capacity is 0, then the tree capacity is the count of Source; if Capacity is equal to or greater than Source.Count, the tree capacity equals the value of the Capacity parameter; otherwise, the operation propagates Capacity_Error.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[In the five-parameter procedure Splice_Subtree, if Source is not the same object as Target, and if the sum of Target.Count and Subtree_Node_Count (Position) is greater than Target.Capacity, then Splice_Subtree propagates Capacity_Error.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[In the five-parameter procedure Splice_Children, if Source is not the same object as Target, and if the sum of Target.Count and Subtree_Node_Count (Source_Parent)-1 is greater than Target.Capacity, then Splice_Children propagates Capacity_Error.]} @end{Itemize} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to assign from a bounded tree object while tampering with elements @Redundant[or cursors] of that object is prohibited. Either Program_Error is raised by the assignment, execution proceeds with the target object prohibiting tampering with elements @Redundant[or cursors], or execution proceeds normally.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we only really need to talk about tampering with elements here; we mention cursors for clarity.]} @end{TheProof} @end{Bounded} @begin{Erron} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[When a bounded tree object @i<T> is finalized, if tampering with cursors is prohibited for @i<T> other than due to an assignment from another tree, then execution is erroneous. @PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is a tampering event, but since the implementation is not allowed to use Ada.Finalization, it is not possible in a pure Ada implementation to detect this error. (There is no Finalize routine that will be called that could make the check.) Since the check probably cannot be made, the bad effects that could occur (such as an iterator going into an infinite loop or accessing a nonexistent element) cannot be prevented and we have to allow anything. We do allow re-assigning an object that only prohibits tampering because it was copied from another object as that cannot cause any negative effects.]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For each instance of Containers.Multiway_Trees and each instance of Containers.Bounded_Multiway_Trees, if the two instances meet the following conditions, then the output generated by the Tree'Output or Tree'Write subprograms of either instance shall be readable by the Tree'Input or Tree'Read of the other instance, respectively:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[the Element_Type parameters of the two instances are statically matching subtypes of the same type; and]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[the output generated by Element_Type'Output or Element_Type'Write is readable by Element_Type'Input or Element_Type'Read, respectively (where Element_Type denotes the type of the two actual Element_Type parameters).]} @end{Itemize} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[Bounded tree objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded tree objects should be implemented without implicit pointers or dynamic allocation.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[The implementation advice for procedure Move to minimize copying does not apply.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The implementation advice for procedure Move to minimize copying does not apply to bounded trees.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0136-1],ARef=[AI05-0184-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Multiway_Trees is new.]} @end{Extend2005} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubclause{Version=[2],Name=[Array Sorting]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1]} @ChgAdded{Version=[2],Text=[The language-defined generic procedures Containers.@!Generic_@!Array_Sort@Chg{Version=[3],New=[,],Old=[ and]} Containers.@!Generic_@!Constrained_@!Array_Sort@Chg{Version=[3],New=[, and Containers.@!Generic_Sort],Old=[]} provide sorting on arbitrary array types.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library procedure Containers.Generic_Array_Sort has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Index_Type @key{is} (<>); @key{type} Element_Type @key{is private}; @key{type} Array_Type @key{is array} (Index_Type @key{range} <>) @key{of} Element_Type; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{procedure} Ada.Containers.Generic_Array_Sort (Container : @key{in out} Array_Type);@SubChildUnit{Parent=[Ada.Containers],Child=[Generic_Array_Sort]} @key{pragma} Pure(Ada.Containers.Generic_Array_Sort);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Array_Sort is unspecified. @Chg{Version=[3],New=[The number of],Old=[How many]} times Generic_Array_Sort calls "<" is unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies swapping the elements, usually including an intermediate copy. This of course means that the elements will be copied. Since the elements are nonlimited, this usually will not be a problem. Note that there is Implementation Advice below that the implementation should use a sort that minimizes copying of elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The sort is not required to be stable (and the fast algorithm required will not be stable). If a stable sort is needed, the user can include the original location of the element as an extra "sort key". We considered requiring the implementation to do that, but it is mostly extra overhead -- usually there is something already in the element that provides the needed stability.]} @end{Ramification} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library procedure Containers.@!Generic_@!Constrained_@!Array_Sort has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{generic} @key{type} Index_Type @key{is} (<>); @key{type} Element_Type @key{is private}; @key{type} Array_Type @key{is array} (Index_Type) @key{of} Element_Type; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{procedure} Ada.Containers.Generic_Constrained_Array_Sort@SubChildUnit{Parent=[Ada.Containers],Child=[Generic_Constrained_Array_Sort]} (Container : @key{in out} Array_Type); @key{pragma} Pure(Ada.Containers.Generic_Constrained_Array_Sort);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Constrained_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Constrained_Array_Sort is unspecified. @Chg{Version=[3],New=[The number of],Old=[How many]} times Generic_Constrained_Array_Sort calls "<" is unspecified.@PDefn{unspecified}]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library procedure Containers.@!Generic_@!Sort has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key{generic} @key{type} Index_Type @key{is} (<>); @key{with function} Before (Left, Right : Index_Type) @key{return} Boolean; @key{with procedure} Swap (Left, Right : Index_Type); @key{procedure} Ada.Containers.Generic_Sort@SubChildUnit{Parent=[Ada.Containers],Child=[Generic_Sort]} (First, Last : Index_Type'Base); @key{pragma} Pure(Ada.Containers.Generic_Sort);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Reorders the elements of an indexable structure, over the range First .. Last, such that the elements are sorted in the ordering determined by the generic formal function Before; Before should return True if Left is to be sorted before Right. The generic formal Before compares the elements having the given indices, and the generic formal Swap exchanges the values of the indicated elements. Any exception raised during evaluation of Before or Swap is propagated.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The actual function for the generic formal function Before of Generic_Sort is expected to return the same value each time it is called with index values that identify a particular pair of element values. It should define a strict weak ordering relationship (see @RefSecNum{Containers}); it should not modify the elements. The actual function for the generic formal Swap should exchange the values of the indicated elements. If the actual for either Before or Swap behaves in some other manner, the behavior of Generic_Sort is unspecified. The number of times the Generic_Sort calls Before or Swap is unspecified.@PDefn{unspecified}]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[ The worst-case time complexity of a call on an instance of Containers.Generic_Array_Sort or Containers.Generic_Constrained_Array_Sort should be @i{O}(@i<N>**2) or better, and the average time complexity should be better than @i{O}(@i<N>**2), where @i<N> is the length of the Container parameter.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should have an average time complexity better than @i{O}(@i{N}**2) and worst case no worse than @i{O}(@i{N}**2).]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a sorting algorithm better than @i{O}(@i<N>**2), such as Quicksort. No bubble sorts allowed!]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[ Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should minimize copying of elements.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort should minimize copying of elements.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean @lquotes@;absolutely minimize@rquotes@; here; we're not intending to require a single copy for each element. Rather, we want to suggest that the sorting algorithm chosen is one that does not copy items unnecessarily. Bubble sort would not meet this advice, for instance.]} @end{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[ The worst-case time complexity of a call on an instance of Containers.Generic_Sort should be @i{O}(@i<N>**2) or better, and the average time complexity should be better than @i{O}(@i<N>**2), where @i<N> is the difference between the Last and First parameters plus 1.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Containers.Generic_Sort should have an average time complexity better than @i{O}(@i{N}**2) and worst case no worse than @i{O}(@i{N}**2).]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Containers.Generic_Sort should minimize calls to the generic formal Swap.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Containers.Generic_Sort should minimize calls to the generic formal Swap.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic procedures Containers.Generic_Array_Sort and Containers.Generic_Constrained_Array_Sort are new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic procedure Containers.Generic_Sort is new.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Redefined "<" actuals to require a strict weak ordering; the old definition allowed indeterminant comparisons that would not have worked in a sort.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Synchronized_Queue_Interfaces]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Synchronized_Queue_Interfaces provides interface type Queue, and a set of operations for that type. Interface Queue specifies a first-in, first-out queue.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Synchronized_Queue_Interfaces has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[type] Element_Type @key[is private]; @key[package] Ada.Containers.Synchronized_Queue_Interfaces @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Synchronized_Queue_Interfaces]} @key[pragma] Pure(Synchronized_Queue_Interfaces);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Queue} @key[is synchronized interface];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Enqueue} (Container : @key[in out] Queue; New_Item : @key[in] Element_Type) @key[is abstract] @key[with] Synchronization => By_Entry;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Dequeue} (Container : @key[in out] Queue; Element : @key[out] Element_Type) @key[is abstract] @key[with] Synchronization => By_Entry;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Current_Use} (Container : Queue) @key[return] Count_Type @key[is abstract]; @key[function] @AdaSubDefn{Peak_Use} (Container : Queue) @key[return] Count_Type @key[is abstract];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Synchronized_Queue_Interfaces;]} @end{Example} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Enqueue (Container : @key[in out] Queue; New_Item : @key[in] Element_Type) @key[is abstract];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0262-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[A queue type that implements this interface is allowed to have a bounded @i<capacity>@Defn2{Term=[capacity],Sec=[of a queue]}. If the queue object has a bounded capacity, and the number of existing elements equals the capacity, then Enqueue blocks until storage becomes available; otherwise, Enqueue does not block. In any case, it then copies New_Item onto the queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Dequeue (Container : @key[in out] Queue; Element : @key[out] Element_Type) @key[is abstract];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If the queue is empty, then Dequeue blocks until an item becomes available. In any case, it then assigns the element at the head of the queue to Element, and removes it from the queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Current_Use (Container : Queue) @key[return] Count_Type @key[is abstract];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the number of elements currently in the queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Peak_Use (Container : Queue) @key[return] Count_Type @key[is abstract];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the maximum number of elements that have been in the queue at any one time.]} @end{DescribeCode} @end{StaticSem} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[Unlike other language-defined containers, there are no queues whose element types are indefinite. Elements of an indefinite type can be handled by defining the element of the queue to be a holder container (see @RefSecNum{The Generic Package Containers.Indefinite_Holders}) of the indefinite type, or to be an explicit access type that designates the indefinite type.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[There are no indefinite queues, as a useful definition for Dequeue is not possible. Dequeue cannot be a function, as Ada does not have entries that are functions (thus conditional and timed calls would not be possible). Moreover, protected functions do not allow modifying the queue object (thus it doesn't work even if we decided we didn't care about conditional and timed calls). If Dequeue is an entry, then the dequeued object would have to be an @key[out] parameter and that would require the queue client to guess the tag and constraints of the value that will be dequeued (otherwise Constraint_Error would be raised), and that is rarely going to be possible.]} @end{Reason} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Synchronized_Queue_Interfaces is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Unbounded_Synchronized_Queues]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Unbounded_Synchronized_Queues provides type Queue, which implements the interface type Containers.Synchronized_Queue_Interfaces.Queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System; @key[with] Ada.Containers.Synchronized_Queue_Interfaces; @key[generic] @key[with package] Queue_Interfaces @key[is new] Ada.Containers.Synchronized_Queue_Interfaces (<>); Default_Ceiling : System.Any_Priority := System.Priority'Last; @key[package] Ada.Containers.Unbounded_Synchronized_Queues @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Unbounded_Synchronized_Queues]} @key[pragma] Preelaborate(Unbounded_Synchronized_Queues);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Implementation @key[is] ... -- @Examcom[not specified by the language] @key[end] Implementation;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[protected type] @AdaTypeDefn{Queue} (Ceiling : System.Any_Priority := Default_Ceiling) @key[with] Priority => Ceiling @key[is] @key[new] Queue_Interfaces.Queue @key[with]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[entry] @AdaSubDefn{Enqueue} (New_Item : @key[in] Queue_Interfaces.Element_Type); @key[overriding] @key[entry] @AdaSubDefn{Dequeue} (Element : @key[out] Queue_Interfaces.Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] @AdaSubDefn{Current_Use} @key[return] Count_Type; @key[overriding] @key[function] @AdaSubDefn{Peak_Use} @key[return] Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[private] ... -- @Examcom[not specified by the language] @key[end] Queue;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ ... -- @Examcom[not specified by the language]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Unbounded_Synchronized_Queues;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The type Queue is used to represent task-safe queues.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The capacity for instances of type Queue is unbounded.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Enqueue never blocks; if more storage is needed for a new element, it is allocated dynamically. We don't need to explicitly specify that Queue needs finalization, because it is visibly protected.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Nested package Implementation can be used to declare the types needed to implement the protected type Queue. This nested package is necessary as types cannot be declared in the private part of a protected type, and the types have to be declared within the generic unit in order to depend on the types imported with package Queue_Interfaces. Clients should never depend on the contents of nested package Implementation.]} @end{Discussion} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Unbounded_Synchronized_Queues is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Synchronized_Queues]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Synchronized_Queues provides type Queue, which implements the interface type Containers.Synchronized_Queue_Interfaces.Queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System; @key[with] Ada.Containers.Synchronized_Queue_Interfaces; @key[generic] @key[with package] Queue_Interfaces @key[is new] Ada.Containers.Synchronized_Queue_Interfaces (<>); Default_Capacity : Count_Type; Default_Ceiling : System.Any_Priority := System.Priority'Last; @key[package] Ada.Containers.Bounded_Synchronized_Queues @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Bounded_Synchronized_Queues]} @key[pragma] Preelaborate(Bounded_Synchronized_Queues);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Implementation @key[is] ... -- @Examcom[not specified by the language] @key[end] Implementation;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[protected type] @AdaTypeDefn{Queue} (Capacity : Count_Type := Default_Capacity; Ceiling : System.Any_Priority := Default_Ceiling) @key[with] Priority => Ceiling @key[is] @key[new] Queue_Interfaces.Queue @key[with]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[entry] @AdaSubDefn{Enqueue} (New_Item : @key[in] Queue_Interfaces.Element_Type); @key[overriding] @key[entry] @AdaSubDefn{Dequeue} (Element : @key[out] Queue_Interfaces.Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] @AdaSubDefn{Current_Use} @key[return] Count_Type; @key[overriding] @key[function] @AdaSubDefn{Peak_Use} @key[return] Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[private] ... -- @Examcom[not specified by the language] @key[end] Queue;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ ... -- @Examcom[not specified by the language]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Bounded_Synchronized_Queues;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Keepnext=[T],Type=[Leading],Text=[The semantics are the same as for Unbounded_Synchronized_Queues, except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The capacity for instances of type Queue is bounded and specified by the discriminant Capacity.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Since this type has a bounded capacity, Enqueue might block if the queue is full.]} @end{Ramification} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Bounded queue objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded queue objects should be implemented without implicit pointers or dynamic allocation.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Synchronized_Queues is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Unbounded_Priority_Queues]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Unbounded_Priority_Queues provides type Queue, which implements the interface type Containers.Synchronized_Queue_Interfaces.Queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System; @key[with] Ada.Containers.Synchronized_Queue_Interfaces; @key[generic] @key[with package] Queue_Interfaces @key[is new] Ada.Containers.Synchronized_Queue_Interfaces (<>); @key[type] Queue_Priority @key[is private]; @key[with] @key[function] Get_Priority (Element : Queue_Interfaces.Element_Type) @key[return] Queue_Priority @key[is] <>; @key[with] @key[function] Before (Left, Right : Queue_Priority) @key[return] Boolean @key[is] <>; Default_Ceiling : System.Any_Priority := System.Priority'Last; @key[package] Ada.Containers.Unbounded_Priority_Queues @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Unbounded_Priority_Queues]} @key[pragma] Preelaborate(Unbounded_Priority_Queues);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Implementation @key[is] ... -- @Examcom[not specified by the language] @key[end] Implementation;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[protected type] @AdaTypeDefn{Queue} (Ceiling : System.Any_Priority := Default_Ceiling) @key[with] Priority => Ceiling @key[is] @key[new] Queue_Interfaces.Queue @key[with]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[entry] @AdaSubDefn{Enqueue} (New_Item : @key[in] Queue_Interfaces.Element_Type); @key[overriding] @key[entry] @AdaSubDefn{Dequeue} (Element : @key[out] Queue_Interfaces.Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[ @key[not overriding] @key[procedure] @AdaSubDefn{Dequeue_Only_High_Priority} (At_Least : @key[in] Queue_Priority; Element : @key[in out] Queue_Interfaces.Element_Type; Success : @key[out] Boolean);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] @AdaSubDefn{Current_Use} @key[return] Count_Type; @key[overriding] @key[function] @AdaSubDefn{Peak_Use} @key[return] Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[private] ... -- @Examcom[not specified by the language] @key[end] Queue;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ ... -- @Examcom[not specified by the language]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Unbounded_Priority_Queues;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The type Queue is used to represent task-safe priority queues.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The capacity for instances of type Queue is unbounded.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Two elements @i<E1> and @i<E2> are equivalent if Before(Get_Priority(@i<E1>), Get_Priority(@i<E2>)) and Before(Get_Priority(@i<E2>), Get_Priority(@i<E1>)) both return False.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[The actual functions for Get_Priority and Before are expected to return the same value each time they are called with the same actuals, and should not modify their actuals. Before should define a strict weak ordering relationship (see @RefSecNum{Containers}). If the actual functions behave in some other manner, the behavior of Unbounded_Priority_Queues is unspecified.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Enqueue inserts an item according to the order specified by the Before function on the result of Get_Priority on the elements; Before should return True if Left is to be inserted before Right. If the queue already contains elements equivalent to New_Item, then it is inserted after the existing equivalent elements.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Enqueue never blocks; if more storage is needed for a new element, it is allocated dynamically. We don't need to explicitly specify that Queue needs finalization, because it is visibly protected.]} @end{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[For a call on Dequeue_Only_High_Priority, if the head of the nonempty queue is @i<E>, and the function Before(At_Least, Get_Priority(@i<E>)) returns False, then @i<E> is assigned to Element and then removed from the queue, and Success is set to True; otherwise, Success is set to False and Element is unchanged.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[Unlike Dequeue, Dequeue_Only_High_Priority is not blocking; it always returns immediately.]} @end{Ramification} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[The use of Before is "backwards" so that it acts like ">=" (it is defined similarly to ">"); thus we dequeue only when it is False.]} @end{Reason} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Unbounded_Priority_Queues is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[The Generic Package Containers.Bounded_Priority_Queues]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[The language-defined generic package Containers.Bounded_Priority_Queues provides type Queue, which implements the interface type Containers.Synchronized_Queue_Interfaces.Queue.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] System; @key[with] Ada.Containers.Synchronized_Queue_Interfaces; @key[generic] @key[with package] Queue_Interfaces @key[is new] Ada.Containers.Synchronized_Queue_Interfaces (<>); @key[type] Queue_Priority @key[is private]; @key[with function] Get_Priority (Element : Queue_Interfaces.Element_Type) @key[return] Queue_Priority @key[is] <>; @key[with function] Before (Left, Right : Queue_Priority) @key[return] Boolean @key[is] <>; Default_Capacity : Count_Type; Default_Ceiling : System.Any_Priority := System.Priority'Last; @key[package] Ada.Containers.Bounded_Priority_Queues @key[is]@ChildUnit{Parent=[Ada.Containers],Child=[Bounded_Priority_Queues]} @key[pragma] Preelaborate(Bounded_Priority_Queues);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Implementation @key[is] ... -- @Examcom[not specified by the language] @key[end] Implementation;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[protected type] @AdaTypeDefn{Queue} (Capacity : Count_Type := Default_Capacity; Ceiling : System.Any_Priority := Default_Ceiling) @key[with] Priority => Ceiling @key[is] @key[new] Queue_Interfaces.Queue @key[with]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[entry] @AdaSubDefn{Enqueue} (New_Item : @key[in] Queue_Interfaces.Element_Type); @key[overriding] @key[entry] @AdaSubDefn{Dequeue} (Element : @key[out] Queue_Interfaces.Element_Type);]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[ @key[not overriding] @key[procedure] @AdaSubDefn{Dequeue_Only_High_Priority} (At_Least : @key[in] Queue_Priority; Element : @key[in out] Queue_Interfaces.Element_Type; Success : @key[out] Boolean);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[overriding] @key[function] @AdaSubDefn{Current_Use} @key[return] Count_Type; @key[overriding] @key[function] @AdaSubDefn{Peak_Use} @key[return] Count_Type;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[private] ... -- @Examcom[not specified by the language] @key[end] Queue;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{private}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ ... -- @Examcom[not specified by the language]]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Containers.Bounded_Priority_Queues;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Keepnext=[T],Type=[Leading],Text=[The semantics are the same as for Unbounded_Priority_Queues, except:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The capacity for instances of type Queue is bounded and specified by the discriminant Capacity.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Since this type has a bounded capacity, Enqueue might block if the queue is full.]} @end{Ramification} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Bounded priority queue objects should be implemented without implicit pointers or dynamic allocation.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[Bounded priority queue objects should be implemented without implicit pointers or dynamic allocation.]}]} @end{ImplAdvice} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0159-1],ARef=[AI05-0251-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The generic package Containers.Bounded_Priority_Queues is new.]} @end{Extend2005} @LabeledAddedSubclause{Version=[3],Name=[Example of Container Use]} @begin{Examples} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[The following example is an implementation of Dijkstra's shortest path algorithm in a directed graph with positive distances. The graph is represented by a map from nodes to sets of edges.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Ada.Containers.Vectors; @key[with] Ada.Containers.Doubly_Linked_Lists; @key[use] Ada.Containers; @key[generic] @key[type] Node @key[is range] <>; @key[package] Shortest_Paths @key[is] @key[type] Distance @key[is new] Float @key[range] 0.0 .. Float'Last; @key[type] Edge @key[is record] To, From : Node; Length : Distance; @key[end record];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Node_Maps @key[is new] Vectors (Node, Node); -- @Examcom{The algorithm builds a map to indicate the node used to reach a given} -- @Examcom{node in the shortest distance.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Adjacency_Lists @key[is new] Doubly_Linked_Lists (Edge); @key[use] Adjacency_Lists;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Graphs @key[is new] Vectors (Node, Adjacency_Lists.List);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[package] Paths @key[is new] Doubly_Linked_Lists (Node);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] Shortest_Path (G : Graphs.Vector; Source : Node; Target : Node) @key[return] Paths.List @key[with] Pre => G (Source) /= Adjacency_Lists.Empty_List;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Shortest_Paths;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package body] Shortest_Paths @key[is] @key[function] Shortest_Path (G : Graphs.Vector; Source : Node; Target : Node) @key[return] Paths.List @key[is] @key[use] Adjacency_Lists, Node_Maps, Paths, Graphs; Reached : @key[array] (Node) @key[of] Boolean := (@key[others] => False); -- @ExamCom{The set of nodes whose shortest distance to the source is known.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[ Reached_From : @key[array] (Node) @key[of] Node; So_Far : @key[array] (Node) @key[of] Distance := (@key[others] => Distance'Last); The_Path : Paths.List := Paths.Empty_List; Nearest_Distance : Distance; Next : Node; @key[begin] So_Far(Source) := 0.0;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[while not] Reached(Target) @key[loop] Nearest_Distance := Distance'Last;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Find closest node not reached yet, by iterating over all nodes.} -- @Examcom{A more efficient algorithm uses a priority queue for this step.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ Next := Source; @key[for] N @key[in] Node'First .. Node'Last @key[loop] @key[if not] Reached(N) @key[and then] So_Far(N) < Nearest_Distance @key[then] Next := N; Nearest_Distance := So_Far(N); @key[end if]; @key[end loop];]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[ @key[if] Nearest_Distance = Distance'Last @key[then] -- @Examcom{No next node found, graph is not connected} @key[return] Paths.Empty_List;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[else] Reached(Next) := True; @key[end if];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @ExamCom{Update minimum distance to newly reachable nodes.}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[ @key[for] E @key[of] G (Next) @key[loop] @key[if not] Reached(E.To) @key[then] Nearest_Distance := E.Length + So_Far(Next);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[if] Nearest_Distance < So_Far(E.To) @key[then] Reached_From(E.To) := Next; So_Far(E.To) := Nearest_Distance; @key[end if]; @key[end if]; @key[end loop]; @key[end loop];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @ExamCom{Rebuild path from target to source.}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[declare] N : Node := Target; @key[begin] @key[while] N /= Source @key[loop] N := Reached_From(N); Prepend (The_Path, N); @key[end loop]; @key[end];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[return] The_Path; @key[end]; @key[end] Shortest_Paths;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[Note that the effect of the Constant_Indexing aspect (on type Vector) and the Implicit_Dereference aspect (on type Reference_Type) is that]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[G (Next)]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[is a convenient short hand for]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[G.Constant_Reference (Next).Element.@key[all]]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[Similarly, the effect of the loop:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[for] E @key[of] G (Next) @key[loop] @key[if not] Reached(E.To) @key[then] ... @key[end if]; @key[end loop];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[is the same as:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[for] C @key[in] G (Next).Iterate @key[loop] @key[declare] E : Edge @key[renames] G (Next)(C).@key[all]; @key[begin] @key[if not] Reached(E.To) @key[then] ... @key[end if]; @key[end]; @key[end loop];]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Leading],Keepnext=[T],Text=[which is the same as:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[declare] L : Adjacency_Lists.List @key[renames] G (Next); C : Adjacency_Lists.Cursor := L.First; @key[begin] @key[while] Has_Element (C) @key[loop] @key[declare] E : Edge @key[renames] L(C).@key[all]; @key[begin] @key[if not] Reached(E.To) @key[then] ... @key[end if]; @key[end]; C := L.Next (C); @key[end loop]; @key[end];]} @end{Example} @end{Examples} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[This example of container use is new.]} @end{DiffWord2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_containers.mss���������������������������������������������������0000755�0001752�0001001�00001534040�12066652506�021173� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_containers.mss,v $ } @comment{ $Revision: 1.95 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(precontainers, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @RMNewPage @LabeledAddedClause{Version=[2],Name=[Containers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This clause presents the specifications of the package Containers and several child packages, which provide facilities for storing collections of elements.]} @ChgToGlossary{Version=[3],Kind=[Added],Term=<Container>, Text=<@ChgAdded{Version=[3],Text=[A container is an object that contain other objects all of the same type, which could be class-wide. Several predefined container types are provided by the children of package Ada.Containers (see @RefSecNum{The Package Containers}).]}>} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A variety of sequence and associative containers are provided. Each container includes a @i{cursor} type. A cursor is a reference to an element within a container. Many operations on cursors are common to all of the containers. A cursor referencing an element in a container is considered to be overlapping with the container object itself.@PDefn2{Term=[cursor],Sec=[for a container]} @Defn2{Term=[container],Sec=[cursor]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The last sentence is intended to clarify that operations that just use a cursor are on the same footing as operations that use a container in terms of the reentrancy rules of Annex A.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Within this clause we provide Implementation Advice for the desired average or worst case time complexity of certain operations on a container. This advice is expressed using the Landau symbol @i{O}(X). Presuming f is some function of a length parameter N and t(N) is the time the operation takes (on average or worst case, as specified) for the length N, a complexity of @i{O}(f(N)) means that there exists a finite A such that for any N, t(N)/f(N) < A. @Defn{Landau symbol @i{O}(X)}@Defn{@i{O}(f(N))}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Of course, an implementation can do better than a specified @i{O}(f(N)): for example, @i{O}(1) meets the requirements for @i{O}(log N).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This concept seems to have as many names as there are authors. We used @lquotes@;Landau symbol@rquotes because that's what our reference does. But we'd also seen this referred as big-O notation@Defn{big-O notation} (sometimes written as @i<big-oh>), and as Bachmann notation. Whatever the name, it always has the above definition.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the advice suggests that the complexity should be less than @i{O}(f(N)), then for any arbitrarily small positive real D, there should exist a positive integer M such that for all N > M, t(N)/f(N) < D.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[When a formal function is used to provide an ordering for a container, it is generally required to define a strict weak ordering. A function "<" defines a @i<strict weak ordering>@Defn{strict weak ordering} if it is irreflexive, asymmetric, transitive, and in addition, if @i<x> < @i<y> for any values @i<x> and @i<y>, then for all other values @i<z>, (@i<x> < @i<z>) or (@i<z> < @i<y>).]} @end{Intro} @begin{Metarules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} provides a number of useful containers for Ada. Only the most useful containers are provided. Ones that are relatively easy to code, redundant, or rarely used are omitted from this set, even if they are generally included in containers libraries.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The containers packages are modeled on the Standard Template Library (STL), an algorithms and data structure library popularized by Alexander Stepanov, and included in the C++ standard library. The structure and terminology differ from the STL where that better maps to common Ada usage. For instance, what the STL calls @lquotes@;iterators@rquotes@; are called @lquotes@;cursors@rquotes@; here.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following major nonlimited containers are provided:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[(Expandable) Vectors of any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Doubly-linked Lists of any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Hashed Maps keyed by any nonlimited hashable type, and containing any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Ordered Maps keyed by any nonlimited ordered type, and containing any nonlimited type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0136-1]} @ChgAdded{Version=[2],Text=[Hashed Sets of any nonlimited hashable type;@Chg{Version=[3],New=[],Old=[ and]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0136-1]} @ChgAdded{Version=[2],Text=[Ordered Sets of any nonlimited ordered type@Chg{Version=[3],New=[;],Old=[.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0136-1]} @ChgAdded{Version=[3],Text=[Multiway Trees of any nonlimited type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0069-1]} @ChgAdded{Version=[3],Text=[Holders of any (indefinite) nonlimited type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Synchronized queues of any definite nonlimited type; and]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0159-1]} @ChgAdded{Version=[3],Text=[Priority queues of any definite nonlimited type.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1]} @ChgAdded{Version=[2],Text=[Separate versions for definite and indefinite element types are provided, as those for definite types can be implemented more efficiently.@Chg{Version=[3],New=[ Similarly, a separate bounded version is provided in order to give more predictable memory usage.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Each container includes a cursor, which is a reference to an element within a container. Cursors generally remain valid as long as the container exists and the element referenced is not deleted. Many operations on cursors are common to all of the containers. This makes it possible to write generic algorithms that work on any kind of container.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The containers packages are structured so that additional packages can be added in the future. Indeed, we hope that these packages provide the basis for a more extensive secondary standard for containers.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If containers with similar functionality (but different performance characteristics) are provided (by the implementation or by a secondary standard), we suggest that a prefix be used to identify the class of the functionality: "Ada.Containers.Bounded_Sets" (for a set with a maximum number of elements); "Ada.Containers.Protected_Maps" (for a map which can be accessed by multiple tasks at one time); "Ada.Containers.Persistent_Vectors" (for a persistent vector which continues to exist between executions of a program) and so on.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Note that the language already includes several requirements that are important to the use of containers. These include:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Library packages must be reentrant @en multiple tasks can use the packages as long as they operate on separate containers. Thus, it is only necessary for a user to protect a container if a single container needs to be used by multiple tasks.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Language-defined types must stream "properly". That means that the stream attributes can be used to implement persistence of containers when necessary, and containers can be passed between partitions of a program.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Equality of language-defined types must compose @lquotes@;properly@rquotes@;. This means that the version of "=" directly used by users is the same one that will be used in generics and in predefined equality operators of types with components of the containers and/or cursors. This prevents the abstraction from breaking unexpectedly.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0048-1]} @ChgAdded{Version=[3],Text=[Redispatching is not allowed (unless it is required). That means that overriding a container operation will not change the behavior of any other predefined container operation. This provides a stable base for extensions.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If a container's element type is controlled, the point at which the element is finalized will depend on the implementation of the container. We do not specify precisely where this will happen (it will happen no later than the finalization of the container, of course) in order to give implementation's flexibility to cache, block, or split the nodes of the container. In particular, Delete does not necessarily finalize the element; the implementation may (or may not) hold the space for reuse.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not likely to be a hardship, as the element type has to be nonlimited. Types used to manage scarce resources generally need to be limited. Otherwise, the amount of resources needed is hard to control, as the language allows a lot of variation in the number or order of adjusts/finalizations. For common uses of nonlimited controlled types such as managing storage, the types already have to manage arbitrary copies.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The use of controlled types also brings up the possibility of failure of finalization (and thus deallocation) of an element. This is a @ldquote@;serious bug@rdquote@;, as AI95-179 puts it, so we don't try to specify what happens in that case. The implementation should propagate the exception.]} @end{Metarules} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is expected that exceptions propagated from these operations do not damage containers. That is, if Storage_Error is propagated because of an allocation failure, or Constraint_Error is propagated by the assignment of elements, the container can continue to be used without further exceptions. The intent is that it should be possible to recover from errors without losing data. We don't try to state this formally in most cases, because it is hard to define precisely what is and is not allowed behavior.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When this clause says that the behavior of something is unspecified@PDefn{unspecified}, we really mean that any result of executing Ada code short of erroneous execution is allowed. We do not mean that memory not belonging to the parameters of the operation can be trashed. When we mean to allow erroneous behavior, we specifically say that execution is erroneous. All this means if the containers are written in Ada is that checks should not be suppressed or removed assuming some behavior of other code, and that the implementation should take care to avoid creating internal dangling accesses by assuming behavior from generic formals that can't be guaranteed. We don't try to say this normatively because it would be fairly complex, and implementers are unlikely to increase their support costs by fielding implementations that are unstable if given buggy hash functions, et al.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} This @Chg{Version=[3],New=[subclause],Old=[clause]} is new. It just provides an introduction to the following subclauses.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a definition of strict weak ordering.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[The Package Containers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The package Containers is the root of the containers subsystem.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Containers has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Containers @key{is}@ChildUnit{Parent=[Ada],Child=[Containers]} @key{pragma} Pure(Containers);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Hash_Type} @key{is mod} @i<implementation-defined>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Count_Type} @key{is range} 0 .. @i<implementation-defined>;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @AdaExcDefn{Capacity_Error} : @key[exception];]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Hash_Type represents the range of the result of a hash function. Count_Type represents the (potential or actual) number of elements of a container.]} @ChgImpldef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The value of Containers.Hash_Type'Modulus. The value of Containers.Count_Type'Last.]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Capacity_Error is raised when the capacity of a container is exceeded.]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Hash_Type'Modulus should be at least 2**32. Count_Type'Last should be at least 2**31@en@;1.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Hash_Type'Modulus should be at least 2**32. Containers.Count_Type'Last should be at least 2**31@en@;1.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is not a requirement so that these types can be declared properly on machines with native sizes that are not 32 bits. For instance, a 24-bit target could use 2**24 for Hash_Type'Modulus.]} @end{Discussion} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Containers is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Exception Capacity_Error is added to Containers. If Containers is referenced in a @nt{use_clause}, and an entity with the name Capacity_Error is defined in a package that is also referenced in a @nt{use_clause}, the entity Capacity_Error may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Vectors]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Vectors provides private types Vector and Cursor, and a set of operations for each type. A vector container allows insertion and deletion at any position, but it is specifically optimized for insertion and deletion at the high end (the end with the higher index) of the container. A vector container also provides random access to its elements.@Defn{vector container} @Defn2{Term=[container],Sec=[vector]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Pdefn2{Term=[length], Sec=(of a vector container)} @Pdefn2{Term=[capacity], Sec=(of a vector)} A vector container behaves conceptually as an array that expands as necessary as items are inserted. The @i{length} of a vector is the number of elements that the vector contains. The @i{capacity} of a vector is the maximum number of elements that can be inserted into the vector prior to it being automatically expanded.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Elements in a vector container can be referred to by an index value of a generic formal type. The first element of a vector always has its index value equal to the lower bound of the formal type.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Pdefn2{Term=[empty element], Sec=(of a vector)} A vector container may contain @i{empty elements}. Empty elements do not have a specified value.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ Vectors are not intended to be sparse (that is, there are elements at all defined positions). Users are expected to use other containers (like a Map) when they need sparse structures (there is a Note to this effect at the end of this subclause).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ The internal array is a conceptual model of a vector. There is no requirement for an implementation to be a single contiguous array.]} @end{Implnote} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Vectors has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Index_Type @key{is range} <>; @key{type} Element_Type @key{is private}; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Vectors @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Vectors]} @key{pragma} Preelaborate(Vectors);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Vectors);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{subtype} @AdaSubtypeDefn{Name=[Extended_Index],Of=[Index_Type'Base]} @key{is} Index_Type'Base @key{range} Index_Type'First-1 .. Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1; @AdaObjDefn{No_Index} : @key{constant} Extended_Index := Extended_Index'First;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Vector} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Vector} : @key{constant} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{Vector_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Vector} (Length : Count_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Vector} (New_Item : Element_Type; Length : Count_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left, Right : Vector) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left : Vector; Right : Element_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left : Element_Type; Right : Vector) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "&" (Left, Right : Element_Type) @key{return} Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Vector) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Vector; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Vector) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Length} (Container : @key{in out} Vector; Length : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Cursor} (Container : Vector; Index : Extended_Index) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Index} (Position : Cursor) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Vector; Index : Index_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Vector; Index : @key{in} Index_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Vector; Position : @key{in} Cursor; New_item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Container : @key{in} Vector; Index : @key{in} Index_Type; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Vector; Index : @key{in} Index_Type; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Vector; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Vector; Index : @key[in] Index_Type) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Vector; Index : @key[in] Index_Type) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Vector; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Vector; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Assign} (Target : @key{in out} Vector; Source : @key{in} Vector);]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Copy} (Source : Vector; Capacity : Count_Type := 0) @key[return] Vector;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector; Position : @key{out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert_Space} (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert_Space} (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Vector; Index : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Vector; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Elements} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} Vector; I, J : @key{in} Index_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} Vector; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Index} (Container : Vector) @key{return} Index_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Vector) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Vector) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Index} (Container : Vector) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Vector) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Vector) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find_Index} (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'First) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find_Index} (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'Last) @key{return} Extended_Index;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find} (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Vector; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Vector; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Vector; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Vector) @key[return] Vector_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Vector; Start : @key[in] Cursor) @key[return] Vector_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean is <>; @key{package} @AdaPackDefn{Generic_Sorting} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Sorted} (Container : Vector) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Sort} (Container : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Merge} (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Sorting;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Vectors;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the functions defined to use it return an unspecified value. The exact arguments and number of calls of this generic formal function by the functions defined to use it are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;functions defined to use it@rquotes are Find, Find_Index, Reverse_Find, Reverse_Find_Index, and "=" for Vectors. This list is a bit too long to give explicitly.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by any of the functions defined to use "=" cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the results of the functions defined to use "=" are unspecified; other subprograms are not allowed to break if "=" is bad.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Vector is used to represent vectors. The type Vector needs finalization@PDefn2{Term=<needs finalization>, Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Vector represents the empty vector object. It has a length of 0. If an object of type Vector is not otherwise initialized, it is initialized to the same value as Empty_Vector.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Vector'Write for a Vector object @i<V> writes Length(@i<V>) elements of the vector to the stream. It also may write additional information about the vector.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Vector'Read reads the representation of a vector from the stream, and assigns to @i<Item> a vector with the same length and elements as was written by Vector'Write.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The Standard requires streaming of all language-defined nonlimited types (including containers) to "work" (see @RefSecNum{Stream-Oriented Attributes}). In addition, we do not want all of the elements that make up the capacity of the vector streamed, as those beyond the length of the container have undefined contents (and might cause bad things when read back in). This will require a custom stream attribute implementation; the language-defined default implementation will not work (even for a bounded form, as that would most likely stream the entire capacity of the vector). There is a separate requirement that the unbounded and Bounded form use the same streaming representation for the same element type, see @RefSecNum{The Generic Package Containers.Bounded_Vectors}.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Index represents a position that does not correspond to any element. The subtype Extended_Index includes the indices covered by Index_Type plus the value No_Index and, if it exists, the successor to the Index_Type'Last.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We require the existence of Index_Type'First @en 1, so that No_Index and Last_Index of an empty vector is well-defined. We don't require the existence of Index_Type'Last + 1, as it is only used as the position of insertions (and needs to be allowed only when inserting an empty vector).]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[If an operation attempts to modify the vector such that the position of the last element would be greater than Index_Type'Last, then the operation propagates Constraint_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We don't want to require an implementation to go to heroic efforts to handle index values larger than the base type of the index subtype.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a vector]} A subprogram is said to @i{tamper with cursors} of a vector object @i<V> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<V>, that is, it calls the Insert, Insert_Space, Clear, Delete, or Set_Length procedures with @i<V> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<V>; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[it calls the Assign procedure with @i<V> as the Target parameter; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[We don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<V> as a parameter.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Swap, Sort, and Merge copy elements rather than reordering them, so they don't tamper with cursors.]} @end{Discussion} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a vector]} A subprogram is said to @i{tamper with elements} of a vector object @i<V> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<V>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<V>, that is, it calls the Replace_Element, Reverse_Elements, or Swap procedures or the Sort or Merge procedures of an instance of Generic_Sorting with @i<V> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a vector]} @Defn2{Term=[tampering],Sec=[prohibited for a vector]} When tampering with cursors is @i<prohibited> for a particular vector object @i<V>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the cursors of @i<V>, leaving @i<V> unmodified. Similarly, when tampering with elements is @i<prohibited> for a particular vector object @i<V>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the elements of @i<V> @Redundant[(or tamper with the cursors of @i<V>)], leaving @i<V> unmodified.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we mention it only from completeness in the second sentence.]} @end{TheProof} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[This function might not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same vector object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, it compares each element in Left to the corresponding element in Right using the generic formal equality operator. If any such comparison returns False, the function returns False; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Vector (Length : Count_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector with a length of Length, filled with empty elements.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Vector (New_Item : Element_Type; Length : Count_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector with a length of Length, filled with elements initialized to the value New_Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left, Right : Vector) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the elements of Left followed by the elements of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left : Vector; Right : Element_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the elements of Left followed by the element Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left : Element_Type; Right : Vector) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the element Left followed by the elements of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "&" (Left, Right : Element_Type) @key{return} Vector;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a vector comprising the element Left followed by the element Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Vector) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Vector; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[If the capacity of Container is already greater than or equal to Capacity, then Reserve_Capacity has no effect. Otherwise, ],Old=[]}Reserve_Capacity allocates @Chg{Version=[3],New=[additional storage as necessary to ensure],Old=[new internal data structures such]} that the length of the resulting vector can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then@Chg{Version=[3],New=[, as necessary, moves],Old=[ copies the]} elements into the new @Chg{Version=[3],New=[storage],Old=[data structures]} and deallocates @Chg{Version=[3],New=[any storage no longer needed],Old=[the old data structures]}. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Expanding the internal array can be done by allocating a new, longer array, copying the elements, and deallocating the original array. This may raise Storage_Error, or cause an exception from a controlled subprogram. We require that a failed Reserve_Capacity does not lose any elements if an exception occurs, but we do not require a specific order of evaluations or copying.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine is used to preallocate the internal array to the specified capacity such that future Inserts do not require memory allocation overhead. Therefore, the implementation should allocate the needed memory to make that true at this point, even though the visible semantics could be preserved by waiting until the memory is needed. This doesn't apply to the indefinite element container, because elements will have to be allocated individually.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation does not have to contract the internal array if the capacity is reduced, as any capacity greater than or equal to the specified capacity is allowed.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Vector) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set_Length (Container : @key{in out} Vector; Length : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length is larger than the capacity of Container, Set_Length calls Reserve_Capacity (Container, Length), then sets the length of the Container to Length. If Length is greater than the original length of Container, empty elements are added to Container; otherwise@Chg{Version=[3],New=[,],Old=[]} elements are removed from Container.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[No elements are moved by this operation; any new empty elements are added at the end. This follows from the rules that a cursor continues to designate the same element unless the routine is defined to make the cursor ambiguous or invalid; this operation does not do that.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container. The capacity of Container does not change.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Cursor (Container : Vector; Index : Extended_Index) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then No_Element is returned. Otherwise, a cursor designating the element at position Index in Container is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Index (Position : Cursor) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element, No_Index is returned. Otherwise, the index (within its containing vector) of the element designated by Position is returned.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies that the index is determinable from a bare cursor alone. The basic model is that a vector cursor is implemented as a record containing an access to the vector container and an index value. This does constrain implementations, but it also allows all of the cursor operations to be defined in terms of the corresponding index operation (which should be primary for a vector).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Container : Vector; Index : Index_Type) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Element returns the element at position Index.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Vector; Index : @key{in} Index_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Replace_Element assigns the value New_Item to the element at position Index. Any exception raised during the assignment is propagated. The element at position Index is not an empty element after successful call to Replace_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Vector; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Replace_Element assigns New_Item to the element designated by Position. Any exception raised during the assignment is propagated. The element at Position is not an empty element after successful call to Replace_Element.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[Replace_Element@Chg{Version=[3],New=[,],Old=[ and]} Update_Element@Chg{Version=[3],New=[, and Reference],Old=[]} are the only ways that an element can change from empty to nonempty. Also see the note following Update_Element.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Container : @key{in} Vector; Index : @key{in} Index_Type; Process : @key{not null access} @key{procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element at position Index as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with the elements@rquotes@; check is intended to prevent the Element parameter of Process from being @Chg{Version=[3],New=[replaced],Old=[modified]} or deleted outside of Process. The check prevents data loss (if Element_Type is passed by copy) or erroneous execution (if Element_Type is an unconstrained type in an indefinite container).]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access} @key{procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of @Chg{Version=[3],New=[the vector that contains the element designated by Position is prohibited during the execution of the call on Process.@key{all}],Old=[Container]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Vector; Index : @key{in} Index_Type; Process : @key{not null access} @key{procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Update_Element calls Process.@key{all} with the element at position Index as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The element at position Index is not an empty element after successful completion of this operation.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since reading an empty element is a bounded error, attempting to use this procedure to replace empty elements may fail. Use Replace_Element to do that reliably.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Vector; Position : @key{in} Cursor; Process : @key{not null access} @key{procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Update_Element calls Process.@key{all} with the element designated by Position as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The element designated by Position is not an empty element after successful completion of this operation.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The types Constant_Reference_Type and Reference_Type need finalization.@PDefn2{Term=<needs finalization>, Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type or Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Reference_Type (and Constant_Reference_Type) will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Vector; Index : @key[in] Index_Type) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a vector given an index value.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element at position Index. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Vector; Index : @key[in] Index_Type) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a vector given an index value.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the element at position Index. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The element at position Index is not an empty element after successful completion of this operation.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Vector; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a vector given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Vector; Position : @key[in] Cursor) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a vector given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The element designated by Position is not an empty element after successful completion of this operation.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Assign (Target : @key{in out} Vector; Source : @key{in} Vector);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. If the length of Source is greater than the capacity of Target, Reserve_Capacity (Target, Length (Source)) is called. The elements of Source are then copied to Target as for an @nt{assignment_statement} assigning Source to Target (this includes setting the length of Target to be that of Source).]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the bounded vector container. For an unbounded vector, @exam{Assign(A, B)} and @exam{A := B} behave identically. For a bounded vector, := will raise an exception if the container capacities are different, while Assign will not raise an exception if there is enough room in the target.]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Copy (Source : Vector; Capacity : Count_Type := 0) @key[return] Vector;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a vector whose elements are initialized from the corresponding elements of Source. If Capacity is 0, then the vector capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the vector capacity is at least the specified value. Otherwise, the operation propagates Capacity_Error.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then @Chg{Version=[3],New=[the operation],Old=[Move]} has no effect. Otherwise, Move first calls @Chg{Version=[3],New=[Reserve_Capacity (Target, Length (Source)) and then ],Old=[]}Clear (Target); then, each element from Source is removed from Source and inserted into Target in the original order. The length of Source is 0 after a successful call to Move.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The idea is that the internal array is removed from Source and moved to Target. (See the @ImplAdviceName for Move). If Capacity (Target) /= 0, the previous internal array may need to be deallocated. We don't mention this explicitly, because it is covered by the "no memory loss" @ImplReqName@;.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Length(New_Item) is 0, then Insert does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Length (New_Item); if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last@Chg{Version=[3],New=[,],Old=[]} then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert slides the elements in the range Before .. Last_Index (Container) up by Length(New_Item) positions, and then copies the elements of New_Item to the positions starting at Before. Any exception raised during the copying is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Moving the elements does not necessarily involve copying. Similarly, since Reserve_Capacity does not require the copying of elements, it does not need to be explicitly called (the implementation can combine the operations if it wishes to).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, if Length(New_Item) is 0, then Insert does nothing. If Before is No_Element, then the call is equivalent to Insert (Container, Last_Index (Container) + 1, New_Item); otherwise@Chg{Version=[3],New=[,],Old=[]} the call is equivalent to Insert (Container, To_Index (Before), New_Item);]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Before checks that the cursor does not belong to some other Container. This check implies that a reference to the container is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Vector; Position : @key{out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert (Container, @i<T>, New_Item) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The messy wording is needed because Before is invalidated by Insert, and we don't want Position to be invalid after this call. An implementation probably only needs to copy Before to Position.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Before, To_Vector (New_Item, Count), Position);]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0257-1]} @ChgAdded{Version=[3],Text=[If Count equals 0, Position will designate the element designated by Before, rather than a newly inserted element. Otherwise, Position will designate the first newly inserted element.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, then Insert does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Count; if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last@Chg{Version=[3],New=[,],Old=[]} then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert slides the elements in the range Before .. Last_Index (Container) up by Count positions, and then inserts elements that are initialized by default (see @RefSecNum{Object Declarations}) in the positions starting at Before.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert (Container, @i<T>, Count) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine exists mainly to ease conversion between Vector and List containers. Unlike Insert_Space, this routine default initializes the elements it inserts, which can be more expensive for some element types.]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} Vector; New_Item : @key{in} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First_Index (Container), New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First_Index (Container), New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} Vector; New_Item : @key{in} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} Vector; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert_Space (Container : @key{in out} Vector; Before : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If Before is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, then Insert_Space does nothing. Otherwise, it computes the new length @i<NL> as the sum of the current length and Count; if the value of Last appropriate for length @i<NL> would be greater than Index_Type'Last@Chg{Version=[3],New=[,],Old=[]} then Constraint_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the current vector capacity is less than @i<NL>, Reserve_Capacity (Container, @i<NL>) is called to increase the vector capacity. Then Insert_Space slides the elements in the range Before .. Last_Index (Container) up by Count positions, and then inserts empty elements in the positions starting at Before.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert_Space (Container : @key{in out} Vector; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. If Before equals No_Element, then let @i<T> be Last_Index (Container) + 1; otherwise, let @i<T> be To_Index (Before). Insert_Space (Container, @i<T>, Count) is called, and then Position is set to To_Cursor (Container, @i<T>).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Vector; Index : @key{in} Extended_Index; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Index is not in the range First_Index (Container) .. Last_Index (Container) + 1, then Constraint_Error is propagated. If Count is 0, Delete has no effect. Otherwise@Chg{Version=[3],New=[,],Old=[]} Delete slides the elements (if any) starting at position Index + Count down to Index. Any exception raised during element assignment is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Index + Count >= Last_Index(Container), this effectively truncates the vector (setting Last_Index to Index @en 1 and consequently sets Length to Index @en Index_Type'First).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Vector; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete (Container, To_Index (Position), Count) is called, and then Position is set to No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Delete (Container, First_Index (Container), Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Vector; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) <= Count@Chg{Version=[3],New=[,],Old=[]} then Delete_Last is equivalent to Clear (Container). Otherwise@Chg{Version=[3],New=[,],Old=[]} it is equivalent to Delete (Container, Index_Type'Val(Index_Type'Pos(Last_Index (Container)) @en Count + 1), Count).]} @begin{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Elements (Container : @key{in out} @Chg{Version=[3],New=[Vector],Old=[List]});]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container in reverse order.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This can copy the elements of the vector @em all cursors referencing the vector are ambiguous afterwards and may designate different elements afterwards.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} Vector; I, J : @key{in} Index_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is not in the range First_Index (Container) .. Last_Index (Container), then Constraint_Error is propagated. Otherwise, Swap exchanges the values of the elements at positions I and J.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} Vector; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap exchanges the values of the elements designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[After a call to Swap, I designates the element value previously designated by J, and J designates the element value previously designated by I. The cursors do not become ambiguous from this operation.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Index (Container : Vector) @key{return} Index_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the value Index_Type'First.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We'd rather call this @lquotes@;First@rquotes@;, but then calling most routines in here with First (Some_Vect) would be ambiguous.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Vector) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, First returns No_Element. Otherwise, it returns a cursor that designates the first element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Vector) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Container, First_Index (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Index (Container : Vector) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last_Index returns No_Index. Otherwise, it returns the position of the last element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Vector) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last returns No_Element. Otherwise, it returns a cursor that designates the last element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Vector) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Container, Last_Index (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the last element of the container, then Next returns the value No_Element. Otherwise, it returns a cursor that designates the element with index To_Index (Position) + 1 in the same vector as Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the first element of the container, then Previous returns the value No_Element. Otherwise, it returns a cursor that designates the element with index To_Index (Position) @en 1 in the same vector as Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find_Index (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'First) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at position Index and proceeds towards Last_Index (Container). If no equal element is found, then Find_Index returns No_Index. Otherwise, it returns the index of the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the first element if Position equals No_Element, and at the element designated by Position otherwise. It proceeds towards the last element of Container. If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find_Index (Container : Vector; Item : Element_Type; Index : Index_Type := Index_Type'Last) @key{return} Extended_Index;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at position Index or, if Index is greater than Last_Index (Container), at position Last_Index (Container). It proceeds towards First_Index (Container). If no equal element is found, then Reverse_Find_Index returns No_Index. Otherwise, it returns the index of the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find (Container : Vector; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Reverse_Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the last element if Position equals No_Element, and at the element designated by Position otherwise. It proceeds towards the first element of Container. If no equal element is found, then Reverse_Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Vector; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Has_Element (Find (Container, Item)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@Chg{Version=[3],New=[],Old=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[],Old=[Returns True if Position designates an element, and returns False otherwise.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]}]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 225 and 226 were moved above.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Vector; Process : @key{not null access} @key{procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Invokes Process.@key{all} with a cursor that designates each element in Container, in index order. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the cursors of Container@Chg{Version=[3],New=[ is prohibited during the execution of a call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The purpose of the @lquotes@;tamper with the cursors@rquotes@; check is to prevent erroneous execution from the Position parameter of Process.@key{all} becoming invalid. This check takes place when the operations that tamper with the cursors of the container are called. The check cannot be made later (say in the body of Iterate), because that could cause the Position cursor to be invalid and potentially cause execution to become erroneous -- defeating the purpose of the check.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ There is no check needed if an attempt is made to insert or delete nothing (that is, Count = 0 or Length(Item) = 0).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check is easy to implement: each container needs a counter. The counter is incremented when Iterate is called, and decremented when Iterate completes. If the counter is nonzero when an operation that inserts or deletes is called, Finalize is called, or one of the other operations in the list occurs, Program_Error is raised.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Vector; Process : @key{not null access} @key{procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the elements in Container as per @Chg{Version=[3],New=[procedure ],Old=[]}Iterate, except that elements are traversed in reverse index order.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Vector) @key[return] Vector_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the first node and moving the cursor as per the Next function when used as a forward iterator, and starting with the last node and moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Vector; Start : @key[in] Cursor) @key[return] Vector_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Otherwise, Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the node designated by Start and moving the cursor as per the Next function when used as a forward iterator, or moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Exits are allowed from the loops created using the iterator objects. In particular, to stop the iteration at a particular cursor, just add]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[exit when] Cur = Stop;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[in the body of the loop (assuming that @exam{Cur} is the loop parameter and @exam{Stop} is the cursor that you want to stop at).]} @end{Discussion} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. @Chg{Version=[3],New=[The number of],Old=[How many]} times the subprograms of Generic_Sorting call "<" is unspecified.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Sorted (Container : Vector) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if the elements are sorted smallest first as determined by the generic formal "<" operator; otherwise, Is_Sorted returns False. Any exception raised during evaluation of "<" is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Sort (Container : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies swapping the elements, usually including an intermediate copy. This means that the elements will usually be copied. (As with Swap, if the implementation can do this some other way, it is allowed to.) Since the elements are nonlimited, this usually will not be a problem. Note that there is @ImplAdviceName below that the implementation should use a sort that minimizes copying of elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The sort is not required to be stable (and the fast algorithm required will not be stable). If a stable sort is needed, the user can include the original location of the element as an extra "sort key". We considered requiring the implementation to do that, but it is mostly extra overhead -- usually there is something already in the element that provides the needed stability.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Merge (Target : @key{in out} Vector; Source : @key{in out} Vector);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[If Source is empty, then Merge does nothing. If Source and Target are the same nonempty container object, then Program_Error is propagated. Otherwise, ],Old=[]}Merge removes elements from Source and inserts them into Target; afterwards, Target contains the union of the elements that were initially in Source and Target; Source is left empty. If Target and Source are initially sorted smallest first, then Target is ordered smallest first as determined by the generic formal "<" operator; otherwise, the order of elements in Target is unspecified. Any exception raised during evaluation of "<" is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is a bounded error if either of the vectors is unsorted, see below. The bounded error can be recovered by sorting Target after the merge call, or the vectors can be pretested with Is_Sorted.]} @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Merge operation will usually require copying almost all of the elements. One implementation strategy would be to extend Target to the appropriate length, then copying elements from the back of the vectors working towards the front. An alternative approach would be to allocate a new internal data array of the appropriate length, copy the elements into it in an appropriate order, and then replacing the data array in Target with the temporary.]} @end{ImplNote} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Reading the value of an empty element by calling Element, Query_Element, Update_Element,@Chg{Version=[3],New=[ Constant_Reference, Reference,],Old=[]} Swap, Is_Sorted, Sort, Merge, "=", Find, or Reverse_Find is a bounded error. The implementation may treat the element as having any normal value (see @RefSecNum{Data Validity}) of the element type, or raise Constraint_Error or Program_Error before modifying the vector.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For instance, a default initialized element could be returned. Or some previous value of an element. But returning random junk is not allowed if the type has default initial value(s).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Assignment and streaming of empty elements are @b<not> bounded errors. This is consistent with regular composite types, for which assignment and streaming of uninitialized components do not cause a bounded error, but reading the uninitialized component does cause a bounded error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There are other operations which are defined in terms of the operations listed above.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Calling Merge in an instance of Generic_Sorting with either Source or Target not ordered smallest first using the provided generic formal "<" operator is a bounded error. Either Program_Error is raised after Target is updated as described for Merge, or the operation works as defined.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0022-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of this package, to tamper with elements of any Vector parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the Vector either prior to, or subsequent to, some or all of the modifications to the Vector.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[It is a bounded error to call any subprogram declared in the visible part of Containers.Vectors when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[ambiguous cursor],Sec=[of a vector]} @Defn2{Term=[cursor],Sec=[ambiguous]} A Cursor value is @i{ambiguous} if any of the following have occurred since it was created:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Insert, Insert_Space, or Delete has been called on the vector that contains the element the cursor designates with an index value (or a cursor designating an element at such an index value) less than or equal to the index value of the element designated by the cursor; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The vector that contains the element it designates has been passed to the Sort or Merge procedures of an instance of Generic_Sorting, or to the Reverse_Elements procedure.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram other than "=" or Has_Element declared in Containers.Vectors with an ambiguous (but not invalid, see below) cursor parameter. Possible results are:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor may be treated as if it were No_Element;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor may designate some element in the vector (but not necessarily the element that it originally designated);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Constraint_Error may be raised; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Program_Error may be raised.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Cursors are made ambiguous if an Insert or Delete occurs that moves the elements in the internal array including the designated ones. After such an operation, the cursor probably still designates an element (although it might not after a deletion), but it is a @i<different> element. That violates the definition of cursor @em it designates a particular element.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For "=" or Has_Element, the cursor works normally (it would not be No_Element). We don't want to trigger an exception simply for comparing a bad cursor.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases or ensure that cursors survive such operations, in many cases the overhead necessary to make the check (or ensure cursors continue to designate the same element) is substantial in time or space.]} @end{Reason} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i{invalid} if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a vector]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The vector that contains the element it designates has been finalized;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[The vector that contains the element it designates has been used as the Target of a call to Assign, or as the target of an @nt{assignment_statement};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Redundant[The vector that contains the element it designates has been used as the Source or Target of a call to Move;] or]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Move has been reworded in terms of Assign and Clear, which are covered by other bullets, so this text is redundant.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0160-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The element it designates has been deleted@Chg{Version=[3],New=[ or removed from the vector that previously contained the element],Old=[]}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[An element can be removed via calls to Set_Length, Clear, and Merge; and indirectly via calls to Assign and Move.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if it is called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Vectors is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution), Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above (combined with the bounded error cases) is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the appending of new elements.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the vector associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a vector object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a vector shall have the effect of copying the elements from the source vector object to the target vector object@Chg{Version=[3],New=[ and changing the length of the target object to that of the source object],Old=[]}.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[An assignment of a Vector is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.@Chg{Version=[3],New=[ (Note that such an implementation would be require care, as Query_Element and Constant_Reference both could be used to access an element which later needs to be reallocated while the parameter or reference still exists, potentially leaving the parameter or reference pointing at the wrong element.)],Old=[]}]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Vectors should be implemented similarly to an array. In particular, if the length of a vector is @i{N}, then]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Element should be @i{O}(log @i{N});]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element for Containers.Vector should be @i{O}(log @i{N}).]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Append with Count=1 when @i{N} is less than the capacity of the vector should be @i{O}(log @i{N}); and]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Append with Count = 1 when @i{N} is less than the capacity for Containers.Vector should be @i{O}(log @i{N}).]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the worst-case time complexity of Prepend with Count=1 and Delete_First with Count=1 should be @i{O}(@i{N} log @i{N}).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Prepend with Count = 1 and Delete_First with Count=1 for Containers.Vectors should be @i{O}(@i{N} log @i{N}).]}]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i{N}) time to access elements, that program could be unusable when the vectors are large. We allow @i{O}(log @i{N}) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Vectors.Generic_Sorting should be @i{O}(@i{N}**2), and the average time complexity should be better than @i{O}(@i{N}**2).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Vectors.Generic_Sorting should be @i{O}(@i{N}**2), and the average time complexity should be better than @i{O}(@i{N}**2).]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a better than @i{O}(@i{N}**2) sorting algorithm, such as Quicksort. No bubble sorts allowed!]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Vectors.Generic_Sorting.Sort and Containers.Vectors.Generic_Sorting.Merge should minimize copying of elements.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Vectors.Generic_Sorting.Sort and Containers.Vectors.Generic_Sorting.Merge should minimize copying of elements.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean @lquotes@;absolutely minimize@rquotes here; we're not intending to require a single copy for each element. Rather, we want to suggest that the sorting algorithm chosen is one that does not copy items unnecessarily. Bubble sort would not meet this advice, for instance.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Vectors.Move should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source vector to the Target vector.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a vector operation, no storage should be lost, nor any elements removed from a vector unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a vector operation, no storage should be lost, nor any elements removed from a vector unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[All elements of a vector occupy locations in the internal array. If a sparse container is required, a Hashed_Map should be used rather than a vector.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Index_Type'Base'First = Index_Type'First an instance of Ada.Containers.Vectors will raise Constraint_Error. A value below Index_Type'First is required so that an empty vector has a meaningful value of Last_Index.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This property is the main reason why only integer types (as opposed to any discrete type) are allowed as the index type of a vector. An enumeration or modular type would require a subtype in order to meet this requirement.]} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Containers.Vectors is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Vectors. If an instance of Containers.Vectors is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Vectors is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator, reference, and indexing support to make vector containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Generalized the definition of Reserve_Capacity and Move. Specified which elements are read/written by stream attributes.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0022-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover tampering by generic actual subprograms.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover access to finalized vector containers.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Redefined "<" actuals to require a strict weak ordering; the old definition allowed indeterminant comparisons that would not have worked in a container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the definition of invalid cursors to cover missing (and new) cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined when a container prohibits tampering in order to more clearly define where the check is made and the exception raised.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2], Name=[The Generic Package Containers.Doubly_Linked_Lists]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic package Containers.Doubly_Linked_Lists provides private types List and Cursor, and a set of operations for each type. A list container is optimized for insertion and deletion at any position. @Defn{list container}@Defn2{Term=[container],Sec=[list]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[node],Sec=[of a list]}A doubly-linked list container object manages a linked list of internal @i{nodes}, each of which contains an element and pointers to the next (successor) and previous (predecessor) internal nodes. A cursor designates a particular node within a list (and by extension the element contained in that node). A cursor keeps designating the same node (and element) as long as the node is part of the container, even if the node is moved in the container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The @i{length} of a list is the number of elements it contains.@Defn2{Term=[length],Sec=(of a list container)}]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Doubly_Linked_Lists has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Element_Type @key{is private}; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Doubly_Linked_Lists @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Doubly_@!Linked_@!Lists]} @key{pragma} Preelaborate(Doubly_Linked_Lists);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Doubly_Linked_Lists);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{List} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_List} : @key{constant} List;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{List_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : List) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} List; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} List; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] List; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] List; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key{procedure} @AdaSubDefn{Assign} (Target : @key{in out} List; Source : @key{in} List);]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Copy} (Source : List) @key[return] List;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} List; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Prepend} (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Append} (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} List; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Elements} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap} (Container : @key{in out} List; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Swap_Links} (Container : @key{in out} List; I, J : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Splice} (Container: @key{in out} List; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : List) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : List) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : List) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : List) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Reverse_Find} (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : List; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] List) @key[return] List_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] List; Start : @key[in] Cursor) @key[return] List_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean is <>; @key{package} @AdaPackDefn{Generic_Sorting} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Sorted} (Container : List) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Sort} (Container : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Merge} (Target : @key{in out} List; Source : @key{in out} List);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Sorting;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Doubly_Linked_Lists;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the functions Find, Reverse_Find, and "=" on list values return an unspecified value. The exact arguments and number of calls of this generic formal function by the functions Find, Reverse_Find, and "=" on list values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by the listed functions cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the results of Find, Reverse_Find, and List "=" are unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type List is used to represent lists. The type List needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_List represents the empty List object. It has a length of 0. If an object of type List is not otherwise initialized, it is initialized to the same value as Empty_List.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[List'Write for a List object @i<L> writes Length(@i<L>) elements of the list to the stream. It also may write additional information about the list.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[List'Read reads the representation of a list from the stream, and assigns to @i<Item> a list with the same length and elements as was written by List'Write.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Streaming more elements than the container length is wrong. For implementation implications of this rule, see the Implementation Note in @RefSecNum{The Generic Package Containers.Vectors}.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of this generic package have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a list]} A subprogram is said to @i{tamper with cursors} of a list object @i<L> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<L>, that is, it calls the Insert, Clear, Delete, or Delete_Last procedures with @i<L> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it reorders the elements of @i<L>, that is, it calls the Splice, Swap_Links, or Reverse_Elements procedures or the Sort or Merge procedures of an instance of Generic_Sorting with @i<L> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<L>; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[it calls the Assign procedure with @i<L> as the Target parameter; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[We don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<L> as a parameter.]} @end{Itemize} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Swap copies elements rather than reordering them, so it doesn't tamper with cursors.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a list]} A subprogram is said to @i{tamper with elements} of a list object @i<L> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<L>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<L>, that is, it calls the Replace_Element or Swap procedures with @i<L> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a list]} @Defn2{Term=[tampering],Sec=[prohibited for a list]} When tampering with cursors is @i<prohibited> for a particular list object @i<L>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the cursors of @i<L>, leaving @i<L> unmodified. Similarly, when tampering with elements is @i<prohibited> for a particular list object @i<L>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the elements of @i<L> @Redundant[(or tamper with the cursors of @i<L>)], leaving @i<L> unmodified.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we mention it only from completeness in the second sentence.]} @end{TheProof} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[This function might not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same list object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, it compares each element in Left to the corresponding element in Right using the generic formal equality operator. If any such comparison returns False, the function returns False; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : List) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} List; Position : @b{in} Cursor; New_Item : @b{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Replace_Element assigns the value New_Item to the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of @Chg{Version=[3],New=[the list that contains the element designated by Position is prohibited during the execution of the call on Process.@key{all}],Old=[Container]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} List; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Update_Element calls Process.@key{all} with the element designated by Position as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The types Constant_Reference_Type and Reference_Type need finalization.@PDefn2{Term=<needs finalization>, Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type or Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Reference_Type (and Constant_Reference_Type) will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] List; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a list given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] List; Position : @key[in] Cursor) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a list given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Assign (Target : @key{in out} List; Source : @key{in} List);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. Otherwise, the elements of Source are copied to Target as for an @nt{assignment_statement} assigning Source to Target.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the bounded list container. For an unbounded list, @exam{Assign(A, B)} and @exam{A := B} behave identically. For a bounded list, := will raise an exception if the container capacities are different, while Assign will not raise an exception if there is enough room in the target.]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Copy (Source : List) @key[return] List;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a list whose elements match the elements of Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} List; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then @Chg{Version=[3],New=[the operation],Old=[Move]} has no effect. Otherwise, @Chg{Version=[3],New=[the operation is equivalent to Assign (Target, Source) followed by Clear (Source)],Old=[Move first calls Clear (Target). Then, the nodes in Source are moved to Target (in the original order). The length of Target is set to the length of Source, and the length of Source is set to 0]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert inserts Count copies of New_Item prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last node (if any). Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Before checks that the cursor does not belong to some other Container. This check implies that a reference to the container is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0257-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert allocates Count copies of New_Item, and inserts them prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last element (if any). Position designates the first newly-inserted element@Chg{Version=[3],New=[, or if Count equals 0, then Position is assigned the value of Before],Old=[]}. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} List; Before : @key{in} Cursor; Position : @key{out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0257-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Otherwise, Insert inserts Count new elements prior to the element designated by Before. If Before equals No_Element, the new elements are inserted after the last node (if any). The new elements are initialized by default (see @RefSecNum{Object Declarations}). @Chg{Version=[3],New=[Position designates the first newly-inserted element, or if Count equals 0, then Position is assigned the value of Before],Old=[]}. Any exception raised during allocation of internal storage is propagated, and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Prepend (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, First (Container), New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Append (Container : @key{in out} List; New_Item : @key{in} Element_Type; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Insert (Container, No_Element, New_Item, Count).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} List; Position : @key{in out} Cursor; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Delete removes (from Container) Count elements starting at the element designated by Position (or all of the elements starting at Position if there are fewer than Count elements starting at Position). Finally, Position is set to No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[If Length (Container) <= Count, then Delete_First is equivalent to Clear (Container). Otherwise, it removes the first Count nodes from Container],Old=[Equivelent to Delete (Container, First (Container), Count)]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} List; Count : @key{in} Count_Type := 1);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) <= Count@Chg{Version=[3],New=[,],Old=[]} then Delete_Last is equivalent to Clear (Container). Otherwise@Chg{Version=[3],New=[,],Old=[]} it removes the last Count nodes from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Elements (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the elements of Container in reverse order.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike the similar routine for a vector, elements should not be copied; rather, the nodes should be exchanged. Cursors are expected to reference the same elements afterwards.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap (Container : @key{in out} List; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap exchanges the values of the elements designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[After a call to Swap, I designates the element value previously designated by J, and J designates the element value previously designated by I. The cursors do not become ambiguous from this operation.]} @end{Ramification} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to actually copy the elements if it can do the swap some other way. But it is allowed to copy the elements if needed.]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Swap_Links (Container : @key{in out} List; I, J : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If either I or J is No_Element, then Constraint_Error is propagated. If either I or J do not designate an element in Container, then Program_Error is propagated. Otherwise, Swap_Links exchanges the nodes designated by I and J.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike Swap, this exchanges the nodes, not the elements. No copying is performed. I and J designate the same elements after this call as they did before it. This operation can provide better performance than Swap if the element size is large.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Before is not No_Element, and does not designate an element in Target, then Program_Error is propagated. Otherwise, if Source denotes the same object as Target, the operation has no effect. Otherwise, Splice reorders elements such that they are removed from Source and moved to Target, immediately prior to Before. If Before equals No_Element, the nodes of Source are spliced after the last node of Target. The length of Target is incremented by the number of nodes in Source, and the length of Source is set to 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Target : @key{in out} List; Before : @key{in} Cursor; Source : @key{in out} List; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element@Chg{Version=[3],New=[,],Old=[]} then Constraint_Error is propagated. If Before does not equal No_Element, and does not designate an element in Target, then Program_Error is propagated. If Position does not equal No_Element, and does not designate a node in Source, then Program_Error is propagated. If Source denotes the same object as Target, then there is no effect if Position equals Before, else the element designated by Position is moved immediately prior to Before, or, if Before equals No_Element, after the last element. In both cases, Position and the length of Target are unchanged. Otherwise@Chg{Version=[3],New=[,],Old=[]} the element designated by Position is removed from Source and moved to Target, immediately prior to Before, or, if Before equals No_Element, after the last element of Target. The length of Target is incremented, the length of Source is decremented, and Position is updated to represent an element in Target.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Source is the same as Target, and Position = Before, or Next(Position) = Before, Splice has no effect, as the element does not have to move to meet the postcondition.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Splice (Container: @key{in out} List; Before : @key{in} Cursor; Position : @key{in} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is No_Element@Chg{Version=[3],New=[,],Old=[]} then Constraint_Error is propagated. If Before does not equal No_Element, and does not designate an element in Container, then Program_Error is propagated. If Position does not equal No_Element, and does not designate a node in Container, then Program_Error is propagated. If Position equals Before there is no effect. Otherwise, the element designated by Position is moved immediately prior to Before, or, if Before equals No_Element, after the last element. The length of Container is unchanged.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : List) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, First returns the value No_Element. Otherwise@Chg{Version=[3],New=[,],Old=[]} it returns a cursor that designates the first node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : List) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : List) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Last returns the value No_Element. Otherwise@Chg{Version=[3],New=[,],Old=[]} it returns a cursor that designates the last node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : List) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the last element of the container, then Next returns the value No_Element. Otherwise, it returns a cursor that designates the successor of the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element or designates the first element of the container, then Previous returns the value No_Element. Otherwise, it returns a cursor that designates the predecessor of the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the element designated by Position, or at the first element if Position equals No_Element. It proceeds towards Last (Container). If no equal element is found, then Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Reverse_Find (Container : List; Item : Element_Type; Position : Cursor := No_Element) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position is not No_Element, and does not designate an element in Container, then Program_Error is propagated. Find searches the elements of Container for an element equal to Item (using the generic formal equality operator). The search starts at the element designated by Position, or at the last element if Position equals No_Element. It proceeds towards First (Container). If no equal element is found, then Reverse_Find returns No_Element. Otherwise, it returns a cursor designating the first equal element encountered.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : List; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Find (Container, Item) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@Chg{Version=[3],New=[],Old=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[],Old=[Returns True if Position designates an element, and returns False otherwise.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]}]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 139 and 140 were moved above.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each node in Container, starting with the first node and moving the cursor as per the Next function. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the cursors of Container@Chg{Version=[3],New=[ is prohibited during the execution of a call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The purpose of the tamper with cursors check is to prevent erroneous execution from the Position parameter of Process.@key{all} becoming invalid. This check takes place when the operations that tamper with the cursors of the container are called. The check cannot be made later (say in the body of Iterate), because that could cause the Position cursor to be invalid and potentially cause execution to become erroneous -- defeating the purpose of the check.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Generic Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} List; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the nodes in Container as per @Chg{Version=[3],New=[procedure ],Old=[]}Iterate, except that elements are traversed in reverse order, starting with the last node and moving the cursor as per the Previous function.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] List) @key[return] List_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the first node and moving the cursor as per the Next function when used as a forward iterator, and starting with the last node and moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] List; Start : @key[in] Cursor) @key[return] List_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0262-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Otherwise, Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the node designated by Start and moving the cursor as per the Next function when used as a forward iterator, or moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Exits are allowed from the loops created using the iterator objects. In particular, to stop the iteration at a particular cursor, just add]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[exit when] Cur = Stop;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[in the body of the loop (assuming that @exam{Cur} is the loop parameter and @exam{Stop} is the cursor that you want to stop at).]} @end{Discussion} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. @Chg{Version=[3],New=[The number of],Old=[How many]} times the subprograms of Generic_Sorting call "<" is unspecified.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Sorted (Container : List) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if the elements are sorted smallest first as determined by the generic formal "<" operator; otherwise, Is_Sorted returns False. Any exception raised during evaluation of "<" is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Sort (Container : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reorders the nodes of Container such that the elements are sorted smallest first as determined by the generic formal "<" operator provided. The sort is stable. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike array sorts, we do require stable sorts here. That's because algorithms in the merge sort family (as described by Knuth) can be both fast and stable. Such sorts use the extra memory as offered by the links to provide better performance.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that list sorts never copy elements; it is the nodes, not the elements, that are reordered.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Merge (Target : @key{in out} List; Source : @key{in out} List);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[If Source is empty, then Merge does nothing. If Source and Target are the same nonempty container object, then Program_Error is propagated. Otherwise, ],Old=[]}Merge removes elements from Source and inserts them into Target; afterwards, Target contains the union of the elements that were initially in Source and Target; Source is left empty. If Target and Source are initially sorted smallest first, then Target is ordered smallest first as determined by the generic formal "<" operator; otherwise, the order of elements in Target is unspecified. Any exception raised during evaluation of "<" is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is a bounded error if either of the lists is unsorted, see below. The bounded error can be recovered by sorting Target after the merge call, or the lists can be pretested with Is_Sorted.]} @end{Ramification} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} Calling Merge in an instance of Generic_Sorting with either Source or Target not ordered smallest first using the provided generic formal "<" operator is a bounded error. Either Program_Error is raised after Target is updated as described for Merge, or the operation works as defined.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0022-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of this package, to tamper with elements of any List parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the List either prior to, or subsequent to, some or all of the modifications to the List.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram declared in the visible part of Containers.Doubly_Linked_Lists when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[A Cursor value is @i<invalid> if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a list container]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list that contains the element it designates has been finalized;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[The list that contains the element it designates has been used as the Target of a call to Assign, or as the target of an @nt{assignment_statement};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Redundant[The list that contains the element it designates has been used as the Source or Target of a call to Move;] or]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Move has been reworded in terms of Assign and Clear, which are covered by other bullets, so this text is redundant.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0160-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The element it designates has been @Chg{Version=[3],New=[removed from the list that previously contained the element],Old=[deleted]}.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[The cursor modified by the four parameter Splice is not invalid, even though the element it designates has been removed from the source list, because that cursor has been modified to designate that element in the target list @en the cursor no longer designates an element in the source list.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[This can happen directly via calls to Delete, Delete_Last, Clear, Splice with a Source parameter, and Merge; and indirectly via calls to Delete_First, Assign, and Move.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if it is called with an invalid cursor parameter. Execution is erroneous if any other subprogram declared in Containers.Doubly_Linked_Lists is called with an invalid cursor parameter. @PDefn{unspecified}@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other nodes.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the list associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a doubly-linked List object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a list shall have the effect of copying the elements from the source list object to the target list object@Chg{Version=[3],New=[ and changing the length of the target object to that of the source object],Old=[]}.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[An assignment of a List is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.@Chg{Version=[3],New=[ (Note that this implementation would require care, see @RefSecNum{The Generic Package Containers.Vectors} for more.)],Old=[]}]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Containers.Doubly_Linked_Lists should be implemented similarly to a linked list. In particular, if @i<N> is the length of a list, then the worst-case time complexity of Element, Insert with Count=1, and Delete with Count=1 should be @i{O}(log @i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element, Insert with Count=1, and Delete with Count=1 for Containers.Doubly_Linked_Lists should be @i{O}(log @i<N>).]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i<N>) time to access elements, that program could be unusable when the lists are large. We allow @i{O}(log @i<N>) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The worst-case time complexity of a call on procedure Sort of an instance of Containers.Doubly_Linked_Lists.Generic_Sorting should be @i{O}(@i<N>**2), and the average time complexity should be better than @i{O}(@i<N>**2).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A call on procedure Sort of an instance of Containers.Doubly_Linked_Lists.Generic_Sorting should have an average time complexity better than @i{O}(@i{N}**2) and worst case no worse than @i{O}(@i{N}**2).]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In other words, we're requiring the use of a better than @i{O}(@i{N}**2) sorting algorithm, such as Quicksort. No bubble sorts allowed!]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Containers.Doubly_Linked_Lists.Move should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a list operation, no storage should be lost, nor any elements removed from a list unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a list operation, no storage should be lost, nor any elements removed from a list unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Sorting a list never copies elements, and is a stable sort (equal elements remain in the original order). This is different than sorting an array or vector, which may need to copy elements, and is probably not a stable sort.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Doubly_Linked_Lists is new.]} @end{Extend95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0248-1],ARef=[AI05-0257-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> The Insert versions that return a Position parameter are now defined to return Position = Before if Count = 0. This was unspecified for Ada 2005; so this will only be inconsistent if an implementation did something else and a program depended on that something else @em this should be very rare.]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Doubly_Linked_Lists. If an instance of Containers.Doubly_Linked_Lists is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Doubly_Linked_Lists is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator, reference, and indexing support to make list containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Generalized the definition of Move. Specified which elements are read/written by stream attributes.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0022-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover tampering by generic actual subprograms.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover access to finalized list containers.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Redefined "<" actuals to require a strict weak ordering; the old definition allowed indeterminant comparisons that would not have worked in a container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the definition of invalid cursors to cover missing (and new) cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0257-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added missing wording to describe the Position after Inserting 0 elements.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined when a container prohibits tampering in order to more clearly define where the check is made and the exception raised.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[Maps]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic packages Containers.Hashed_Maps and Containers.Ordered_Maps provide private types Map and Cursor, and a set of operations for each type. A map container allows an arbitrary type to be used as a key to find the element associated with that key. A hashed map uses a hash function to organize the keys, while an ordered map orders the keys per a specified relation. @Defn{map container}@Defn2{Term=[container],Sec=[map]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[section]} describes the declarations that are common to both kinds of maps. See @RefSecNum{The Generic Package Containers.Hashed_Maps} for a description of the semantics specific to Containers.Hashed_Maps and @RefSecNum{The Generic Package Containers.Ordered_Maps} for a description of the semantics specific to Containers.Ordered_Maps.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the function "=" on map values returns an unspecified value. The exact arguments and number of calls of this generic formal function by the function "=" on map values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by "=" for Map objects cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the result of "=" for Map objects is unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Map is used to represent maps. The type Map needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[node],Sec=[of a map]}A map contains pairs of keys and elements, called @i{nodes}. Map cursors designate nodes, but also can be thought of as designating an element (the element contained in the node) for consistency with the other containers. There exists an equivalence relation on keys, whose definition is different for hashed maps and ordered maps. A map never contains two or more nodes with equivalent keys. The @i{length} of a map is the number of nodes it contains.@Defn2{Term=[length],Sec=[of a map]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of a map]} @Defn2{Term=[last node],Sec=[of a map]} @Defn2{Term=[successor node],Sec=[of a map]}Each nonempty map has two particular nodes called the @i{first node} and the @i{last node} (which may be the same). Each node except for the last node has a @i{successor node}. If there are no other intervening operations, starting with the first node and repeatedly going to the successor node will visit each node in the map exactly once until the last node is reached. The exact definition of these terms is different for hashed maps and ordered maps.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of these generic packages have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[tamper with cursors],Sec=[of a map]} A subprogram is said to @i{tamper with cursors} of a map object @i<M> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i<M>, that is, it calls the Insert, Include, Clear, Delete, or Exclude procedures with @i<M> as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<M>; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[it calls the Assign procedure with @i<M> as the Target parameter; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<M> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls one of the operations defined to tamper with the cursors of @i<M>.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Replace only modifies a key and element rather than rehashing, so it does not tamper with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ @Defn2{Term=[tamper with elements],Sec=[of a map]} A subprogram is said to @i{tamper with elements} of a map object @i<M> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<M>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it replaces one or more elements of @i<M>, that is, it calls the Replace or Replace_Element procedures with @i<M> as a parameter.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_Element does not cause a problem.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a map]} @Defn2{Term=[tampering],Sec=[prohibited for a map]} When tampering with cursors is @i<prohibited> for a particular map object @i<M>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the cursors of @i<M>, leaving @i<M> unmodified. Similarly, when tampering with elements is @i<prohibited> for a particular map object @i<M>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the elements of @i<M> @Redundant[(or tamper with the cursors of @i<M>)], leaving @i<M> unmodified.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we mention it only from completeness in the second sentence.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Map represents the empty Map object. It has a length of 0. If an object of type Map is not otherwise initialized, it is initialized to the same value as Empty_Map.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no node. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Map'Write for a Map object @i<M> writes Length(@i<M>) elements of the map to the stream. It also may write additional information about the map.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Map'Read reads the representation of a map from the stream, and assigns to @i<Item> a map with the same length and elements as was written by Map'Write.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Streaming more elements than the container length is wrong. For implementation implications of this rule, see the Implementation Note in @RefSecNum{The Generic Package Containers.Vectors}.]} @end{Ramification} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[This function might not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[If Left and Right denote the same map object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each key @i<K> in Left, the function returns False if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[a key equivalent to @i<K> is not present in Right; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the element associated with @i<K> in Left is not equal to the element associated with @i<K> in Right (using the generic formal equality operator for elements).]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the function has not returned a result after checking all of the keys, it returns True. Any exception raised during evaluation of key equivalence or element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Map) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of nodes in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Map) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the nodes from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Key (Position : Cursor) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Key returns the key component of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element component of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Replace_Element assigns New_Item to the element of the node designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the key and element from the node designated by Position as the arguments. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of @Chg{Version=[3],New=[the map that contains the element designated by Position is prohibited during the execution of the call on Process.@key{all}],Old=[Container]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise@Chg{Version=[3],New=[,],Old=[]} Update_Element calls Process.@key{all} with the key and element from the node designated by Position as the arguments. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The types Constant_Reference_Type and Reference_Type need finalization.@PDefn2{Term=<needs finalization>, Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type or Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Reference_Type (and Constant_Reference_Type) will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Map; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a map given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Map; Position : @key[in] Cursor) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a map given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Map; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a map given a key value.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Equivalent to Constant_Reference (Container, Find (Container, Key)).]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference (Container : @key[aliased in out] Map; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Variable_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read and write access to an individual element of a map given a key value.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Equivalent to Reference (Container, Find (Container, Key)).]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Assign (Target : @key{in out} Map; Source : @key{in} Map);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. Otherwise, the key/element pairs of Source are copied to Target as for an @nt{assignment_statement} assigning Source to Target.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the bounded map containers. For an unbounded map, @exam{Assign(A, B)} and @exam{A := B} behave identically. For a bounded map, := will raise an exception if the container capacities are different, while Assign will not raise an exception if there is enough room in the target.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Map; Source : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then @Chg{Version=[3],New=[the operation],Old=[Move]} has no effect. Otherwise, @Chg{Version=[3],New=[the operation is equivalent to Assign (Target, Source) followed by Clear (Source)],Old=[Move first calls Clear (Target). Then, each node from Source is removed from Source and inserted into Target. The length of Source is 0 after a successful call to Move]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert checks if a node with a key equivalent to Key is already present in Container. If a match is found, Inserted is set to False and Position designates the element with the matching key. Otherwise, Insert allocates a new node, initializes it to Key and New_Item, and adds it to Container; Inserted is set to True and Position designates the newly-inserted node. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts Key into Container as per the five-parameter Insert, with the difference that an element initialized by default (see @RefSecNum{Object Declarations}) is inserted.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts Key and New_Item into Container as per the five-parameter Insert, with the difference that if a node with a key equivalent to Key is already in the map, then Constraint_Error is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} Inserted : Boolean; C : Cursor; @key{begin} Insert (Container, Key, New_Item, C, Inserted); @key{if not} Inserted @key{then} @key{raise} Constraint_Error; @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but doesn't require the hassle of @key{out} parameters.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Include (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Include inserts Key and New_Item into Container as per the five-parameter Insert, with the difference that if a node with a key equivalent to Key is already in the map, then this operation assigns Key and New_Item to the matching node. Any exception raised during assignment is propagated.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} C : Cursor := Find (Container, Key); @key{begin} @key{if} C = No_Element @key{then} Insert (Container, Key, New_Item); @key{else} Replace (Container, Key, New_Item); @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but this avoids doing the search twice.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Replace checks if a node with a key equivalent to Key is present in Container. If a match is found, Replace assigns Key and New_Item to the matching node; otherwise, Constraint_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We update the key as well as the element, as the key might include additional information that does not participate in equivalence. If only the element needs to be updated, use Replace_Element (Find (Container, Key), New_Element).]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Exclude checks if a node with a key equivalent to Key is present in Container. If a match is found, Exclude removes the node from the map.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Exclude should work on an empty map; nothing happens in that case.]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Delete checks if a node with a key equivalent to Key is present in Container. If a match is found, Delete removes the node from the map; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete removes the node designated by Position from the map. Position is set to No_Element on return.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Position checks that the cursor does not belong to some other map. This check implies that a reference to the map is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first node in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the successor of the node designated by Position. If Position designates the last node, then No_Element is returned. If Position equals No_Element, then No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) equals 0, then Find returns No_Element. Otherwise, Find checks if a node with a key equivalent to Key is present in Container. If a match is found, a cursor designating the matching node is returned; otherwise, No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Find (Container, Key)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Map; Key : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Find (Container, Key) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@Chg{Version=[3],New=[],Old=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[],Old=[Returns True if Position designates an element, and returns False otherwise.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]}]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 72 and 73 were moved above.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each node in Container, starting with the first node and moving the cursor according to the successor relation. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the cursors of Container@Chg{Version=[3],New=[ is prohibited during the execution of a call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with cursors@rquotes@; check takes place when the operations that insert or delete elements, and so on, are called.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Generic Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0022-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of a map package, to tamper with elements of any map parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the map either prior to, or subsequent to, some or all of the modifications to the map.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram declared in the visible part of a map package when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i{invalid} if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a map]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The map that contains the node it designates has been finalized;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[The map that contains the node it designates has been used as the Target of a call to Assign, or as the target of an @nt{assignment_statement};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The map that contains the node it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0160-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The node it designates has been @Chg{Version=[3],New=[removed],Old=[deleted]} from the map@Chg{Version=[3],New=[ that previously contained the node],Old=[]}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[This can happen directly via calls to Clear, Exclude, and Delete.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if these functions are called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Hashed_Maps or Containers.Ordered_Maps is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other nodes.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the map associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a Map object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a map shall have the effect of copying the elements from the source map object to the target map object@Chg{Version=[3],New=[ and changing the length of the target object to that of the source object],Old=[]}.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[An assignment of a Map is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.@Chg{Version=[3],New=[ (Note that this implementation would require care, see @RefSecNum{The Generic Package Containers.Vectors} for more.)],Old=[]}]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Move for a map should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a map operation, no storage should be lost, nor any elements removed from a map unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a map operation, no storage should be lost, nor any elements removed from a map unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This description of maps is new; the extensions are documented with the specific packages.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added reference support to make map containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Added procedure Assign; the extension and incompatibility is documented with the specific packages.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Generalized the definition of Move. Specified which elements are read/written by stream attributes.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0022-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover tampering by generic actual subprograms.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover access to finalized map containers.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the definition of invalid cursors to cover missing (and new) cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined when a container prohibits tampering in order to more clearly define where the check is made and the exception raised.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Hashed_Maps]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Hashed_Maps has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Key_Type @key{is private}; @key{type} Element_Type @key{is private}; @key{with function} Hash (Key : Key_Type) @key{return} Hash_Type; @key{with function} Equivalent_Keys (Left, Right : Key_Type) @key{return} Boolean; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @Chg{Version=[3],New=[@b<is>],Old=[is]} <>; @key{package} Ada.Containers.Hashed_Maps @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Hashed_Maps]} @key{pragma} Preelaborate(Hashed_Maps);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Hashed_Maps);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Map} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Map} : @key{constant} Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{Map_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Map; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Map; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Map; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Map; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Map; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign} (Target : @key[in out] Map; Source : @key[in] Map);]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Map; Capacity : Count_Type := 0) @key[return] Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Map; Source : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Map; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Map) @key[return] Map_Iterator_Interfaces.Forward_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Hashed_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[An object of type Map contains an expandable hash table, which is used to provide direct access to nodes. The @i<capacity> of an object of type Map is the maximum number of nodes that can be inserted into the hash table prior to it being automatically expanded.@Defn2{Term=[capacity],Sec=[of a hashed map]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The expected implementation for a Map uses a hash table which is grown when it is too small, with linked lists hanging off of each bucket. Note that in that implementation a cursor needs a back pointer to the Map object to implement iteration; that could either be in the nodes, or in the cursor object. To provide an average @i{O}(1) access time, capacity would typically equal the number of buckets in such an implementation, so that the average bucket linked list length would be no more than 1.0.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no defined relationship between elements in a hashed map. Typically, iteration will return elements in the order that they are hashed in.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term={equivalent key},Sec={of a hashed map}} Two keys @i<K1> and @i<K2> are defined to be @i<equivalent> if Equivalent_Keys (@i<K1>, @i<K2>) returns True.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Hash is expected to return the same value each time it is called with a particular key value. For any two equivalent key values, the actual for Hash is expected to return the same value. If the actual for Hash behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against Hash raising an exception, or returning random numbers, or any other @lquotes@;bad@rquotes behavior. It's not practical to do so, and a broken Hash function makes the container unusable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation can call Hash whenever it is needed; we don't want to specify how often that happens. The result must remain the same (this is logically a pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Equivalent_Keys on Key_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define an equivalence relationship, that is, be reflexive, symmetric, and transitive. If the actual for Equivalent_Keys behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Equivalent_Keys, and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[As with Hash, the implementation is not required to protect against Equivalent_Keys raising an exception or returning random results. Similarly, the implementation can call this operation whenever it is needed. The result must remain the same (this is a logically pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of a key stored in a node of a map is changed other than by an operation in this package such that at least one of Hash or Equivalent_Keys give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against changes to key values other than via the operations declared in the Hashed_Maps package.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[To see how this could happen, imagine an instance of Hashed_Maps where the key type is an access-to-variable type and Hash returns a value derived from the components of the designated object. Then, any operation that has a key value could modify those components and change the hash value:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Key (Map).Some_Component := New_Value;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is really a design error on the part of the user of the map; it shouldn't be possible to modify keys stored in a map. But we can't prevent this error anymore than we can prevent someone passing as Hash a random number generator.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of a hashed map]} @Defn2{Term=[last node],Sec=[of a hashed map]} @Defn2{Term=[successor node],Sec=[of a hashed map]}Which nodes are the first node and the last node of a map, and which node is the successor of a given node, are unspecified, other than the general semantics described in @RefSecNum{Maps}.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Typically the first node will be the first node in the first bucket, the last node will be the last node in the last bucket, and the successor will be obtained by following the collision list, and going to the next bucket at the end of each bucket.]} @end{ImplNote} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Map) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Map; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Reserve_Capacity allocates a new hash table such that the length of the resulting map can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then rehashes the nodes in Container onto the new hash table. It replaces the old hash table with the new hash table, and then deallocates the old hash table. Any exception raised during allocation is propagated and Container is not modified.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors of Container.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This routine is used to preallocate the internal hash table to the specified capacity such that future Inserts do not require expansion of the hash table. Therefore, the implementation should allocate the needed memory to make that true at this point, even though the visible semantics could be preserved by waiting until enough elements are inserted.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[While Reserve_Capacity can be used to reduce the capacity of a map, we do not specify whether an implementation actually supports reduction of the capacity. Since the actual capacity can be anything greater than or equal to @Chg{Version=[3],New=[Capacity],Old=[Count]}, an implementation never has to reduce the capacity.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Reserve_Capacity tampers with the cursors, as rehashing probably will change the order that elements are stored in the map.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Maps}, Clear does not affect the capacity of Container.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Assign (Target : @key[in out] Map; Source : @key[in] Map);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Maps}, if the length of Source is greater than the capacity of Target, Reserve_Capacity (Target, Length (Source)) is called before assigning any elements.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Copy (Source : Map; Capacity : Count_Type := 0) @key[return] Map;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a map whose keys and elements are initialized from the keys and elements of Source. If Capacity is 0, then the map capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the map capacity is at least the specified value. Otherwise, the operation propagates Capacity_Error.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Map; Source : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The intended implementation is that the internal hash table of Target is first deallocated; then the internal hash table is removed from Source and moved to Target.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Maps}, if Length (Container) equals Capacity (Container), then Insert first calls Reserve_Capacity to increase the capacity of Container to some larger value.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Insert should only compare keys that hash to the same bucket in the hash table.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We specify when Reserve_Capacity is called to bound the overhead of capacity expansion operations (which are potentially expensive). Moreover, expansion can be predicted by comparing Capacity(Map) to Length(Map). Since we don't specify by how much the hash table is expanded, this only can be used to predict the next expansion, not later ones.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Exclude should only compare keys that hash to the same bucket in the hash table.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Delete should only compare keys that hash to the same bucket in the hash table. The node containing the element may be deallocated now, or it may be saved and reused later.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In a typical implementation, this will be the first node in the lowest numbered hash bucket that contains a node.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In a typical implementation, this will return the next node in a bucket; if Position is the last node in a bucket, this will return the first node in the next nonempty bucket.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A typical implementation will need to a keep a pointer at the map container in the cursor in order to implement this function.]} @end{ImplNote} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[In:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Find should only compare keys that hash to the same bucket in the hash table.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Key (Left), Key (Right)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Key (Left), Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Keys (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Keys (Left, Key (Right)).]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Map) @key[return] Map_Iterator_Interfaces.Forward_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns an iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the first node and moving the cursor according to the successor relation. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a map, the average time complexity of the subprograms Element, Insert, Include, Replace, Delete, Exclude and Find that take a key parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms that take a cursor parameter should be @i{O}(1). The average time complexity of Reserve_Capacity should be @i{O}(@i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The average time complexity of Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter for Containers.Hashed_Maps should be @i{O}(log @i<N>). The average time complexity of the subprograms of Containers.Hashed_Maps that take a cursor parameter should be @i{O}(1). The average time complexity of Containers.Hashed_Maps.Reserve_Capacity should be @i{O}(@i<N>).]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation for which Find is @i{O}(@i<N>), that program could be unusable when the maps are large. We allow @i{O}(log @i<N>) access because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Hashed_Maps is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Hashed_Maps. If an instance of Containers.Hashed_Maps is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Hashed_Maps is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator and indexing support to make hashed map containers more convenient to use.]} @end{Extend2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @end{Diffword2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Ordered_Maps]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Ordered_Maps has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Key_Type @key{is private}; @key{type} Element_Type @key{is private}; @key{with function} "<" (Left, Right : Key_Type) @key{return} Boolean @key{is} <>; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Ordered_Maps @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Ordered_Maps]} @key{pragma} Preelaborate(Ordered_Maps);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Ordered_Maps);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Map} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Variable_Indexing => Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Map} : @key{constant} Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{Map_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Map) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Map) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in} Element_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element} (Container : @key{in out} Map; Position : @key{in} Cursor; Process : @key{not null access procedure} (Key : @key{in} Key_Type; Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Map; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Map; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Map; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference} (Container : @key[aliased in out] Map; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign} (Target : @key[in out] Map; Source : @key[in] Map);]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Map) @key[return] Map;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Map; Source : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Map; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Map; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Map);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Map) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Key} (Container : Map) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Map) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Map) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Key} (Container : Map) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Map; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Map; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Map; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Map) @key[return] Map_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Map; Start : @key[in] Cursor) @key[return] Map_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Ordered_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term={equivalent key},Sec={of an ordered map}} Two keys @i<K1> and @i<K2> are @i<equivalent> if both @i<K1> < @i<K2> and @i<K2> < @i<K1> return False, using the generic formal "<" operator for keys. Function Equivalent_Keys returns True if Left and Right are equivalent, and False otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" on Key_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}. If the actual for "<" behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call "<" and how many times they call it, is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against "<" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. It's not practical to do so, and a broken "<" function makes the container unusable.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation can call "<" whenever it is needed; we don't want to specify how often that happens. The result must remain the same (this is a logically pure function), or the behavior is unspecified.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of a key stored in a map is changed other than by an operation in this package such that at least one of "<" or "=" give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation is not required to protect against changes to key values other than via the operations declared in the Ordered_Maps package.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[To see how this could happen, imagine an instance of Ordered_Maps package where the key type is an access-to-variable type and "<" returns a value derived from comparing the components of the designated objects. Then, any operation that has a key value (even if the key value is constant) could modify those components and change the result of "<":]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Key (Map).Some_Component := New_Value;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is really a design error on the part of the user of the map; it shouldn't be possible to modify keys stored in a map such that "<" changes. But we can't prevent this error anymore than we can prevent someone passing as "<" a routine that produces random answers.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first node],Sec=[of an ordered map]} @Defn2{Term=[last node],Sec=[of an ordered map]} @Defn2{Term=[successor node],Sec=[of an ordered map]}@Chg{Version=[3],New=[ @Defn2{Term=[predecessor node],Sec=[of an ordered map]}],Old=[]} The @Chg{Version=[3],New=[@i<first node>],Old=[first node]} of a nonempty map is the one whose key is less than the key of all the other nodes in the map. The @Chg{Version=[3],New=[@i<last node>],Old=[last node]} of a nonempty map is the one whose key is greater than the key of all the other elements in the map. The @Chg{Version=[3],New=[@i<successor>],Old=[successor]} of a node is the node with the smallest key that is larger than the key of the given node. The @Chg{Version=[3],New=[@i<predecessor>],Old=[predecessor]} of a node is the node with the largest key that is smaller than the key of the given node. All comparisons are done using the generic formal "<" operator for keys.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Copy (Source : Map) @key[return] Map;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a map whose keys and elements are initialized from the corresponding keys and elements of Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_First has no effect. Otherwise@Chg{Version=[3],New=[,],Old=[]} the node designated by First (Container) is removed from Container. Delete_First tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Map);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_Last has no effect. Otherwise@Chg{Version=[3],New=[,],Old=[]} the node designated by Last (Container) is removed from Container. Delete_Last tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Map) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Key (Container : Map) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Map) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the last node in Container. If Container is empty, returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Map) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Key (Container : Map) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Previous returns No_Element. Otherwise@Chg{Version=[3],New=[,],Old=[]} Previous returns a cursor designating the @Chg{Version=[3],New=[predecessor ],Old=[]}node @Chg{Version=[3],New=[of],Old=[that precedes]} the one designated by Position. If Position designates the first element, then Previous returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Floor (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Floor searches for the last node whose key is not greater than Key, using the generic formal "<" operator for keys. If such a node is found, a cursor that designates it is returned. Otherwise@Chg{Version=[3],New=[,],Old=[]} No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Ceiling (Container : Map; Key : Key_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ceiling searches for the first node whose key is not less than Key, using the generic formal "<" operator for keys. If such a node is found, a cursor that designates it is returned. Otherwise@Chg{Version=[3],New=[,],Old=[]} No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Left) < Key (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Right) < Key (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Left) < Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Cursor; Right : Key_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Right < Key (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Left < Key (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Key_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Right) < Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Map; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the nodes in Container as per @Chg{Version=[3],New=[procedure ],Old=[]}Iterate, with the difference that the nodes are traversed in predecessor order, starting with the last node.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Map) @key[return] Map_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the first node and moving the cursor according to the successor relation when used as a forward iterator, and starting with the last node and moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Map; Start : @key[in] Cursor) @key[return] Map_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Otherwise, Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each node in Container, starting with the node designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Exits are allowed from the loops created using the iterator objects. In particular, to stop the iteration at a particular cursor, just add]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[exit when] Cur = Stop;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[in the body of the loop (assuming that @exam{Cur} is the loop parameter and @exam{Stop} is the cursor that you want to stop at).]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a map, then the worst-case time complexity of the Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms that take a cursor parameter should be @i{O}(1).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of Element, Insert, Include, Replace, Delete, Exclude and Find operations that take a key parameter for Containers.Ordered_Maps should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms of Containers.Ordered_Maps that take a cursor parameter should be @i{O}(1).]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A balanced (red-black) tree for keys has @i{O}(log @i<N>) worst-case performance. Note that a @i{O}(@i<N>) worst-case implementation (like a list) would be wrong.]} @end{ImplNote} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We do not mean to overly constrain implementation strategies here. However, it is important for portability that the performance of large containers has roughly the same factors on different implementations. If a program is moved to an implementation that takes @i{O}(@i<N>) to find elements, that program could be unusable when the maps are large. We allow the extra log @i<N> factors because the proportionality constant and caching effects are likely to be larger than the log factor, and we don't want to discourage innovative implementations.]} @end{Reason} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Ordered_Maps is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Ordered_Maps. If an instance of Containers.Ordered_Maps is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Ordered_Maps is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator and indexing support to make ordered map containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Redefined "<" actuals to require a strict weak ordering; the old definition allowed indeterminant comparisons that would not have worked in a container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[Sets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The language-defined generic packages Containers.Hashed_Sets and Containers.Ordered_Sets provide private types Set and Cursor, and a set of operations for each type. A set container allows elements of an arbitrary type to be stored without duplication. A hashed set uses a hash function to organize elements, while an ordered set orders its element per a specified relation.@Defn{set container} @Defn2{Term=[container],Sec=[set]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[section]} describes the declarations that are common to both kinds of sets. See @RefSecNum{The Generic Package Containers.Hashed_Sets} for a description of the semantics specific to Containers.Hashed_Sets and @RefSecNum{The Generic Package Containers.Ordered_Sets} for a description of the semantics specific to Containers.Ordered_Sets.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "=" on Element_Type values is expected to define a reflexive and symmetric relationship and return the same result value each time it is called with a particular pair of values. If it behaves in some other manner, the function "=" on set values returns an unspecified value. The exact arguments and number of calls of this generic formal function by the function "=" on set values are unspecified.@PDefn{unspecified}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the actual function for "=" is not symmetric and consistent, the result returned by the "=" for Set objects cannot be predicted. The implementation is not required to protect against "=" raising an exception, or returning random results, or any other @lquotes@;bad@rquotes behavior. And it can call "=" in whatever manner makes sense. But note that only the result of "=" for Set objects is unspecified; other subprograms are not allowed to break if "=" is bad (they aren't expected to use "=").]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The type Set is used to represent sets. The type Set needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A set contains elements. Set cursors designate elements. There exists an equivalence relation on elements, whose definition is different for hashed sets and ordered sets. A set never contains two or more equivalent elements. The @i{length} of a set is the number of elements it contains.@Defn2{Term={length},Sec={of a set}}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of a set]} @Defn2{Term=[last element],Sec=[of a set]} @Defn2{Term=[successor element],Sec=[of a set]} Each nonempty set has two particular elements called the @i{first element} and the @i{last element} (which may be the same). Each element except for the last element has a @i{successor element}. If there are no other intervening operations, starting with the first element and repeatedly going to the successor element will visit each element in the set exactly once until the last element is reached. The exact definition of these terms is different for hashed sets and ordered sets.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Redundant[Some operations of these generic packages have access-to-subprogram parameters. To ensure such operations are well-defined, they guard against certain actions by the designated subprogram. In particular, some operations check for @lquotes@;tampering with cursors@rquotes of a container because they depend on the set of elements of the container remaining constant, and others check for @lquotes@;tampering with elements@rquotes of a container because they depend on elements of the container not being replaced.]]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with cursors],Sec=[of a set]} A subprogram is said to @i{tamper with cursors} of a set object @i{S} if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it inserts or deletes elements of @i{S}, that is, it calls the Insert, Include, Clear, Delete, Exclude, or Replace_Element procedures with @i{S} as a parameter; or]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Operations which are defined to be equivalent to a call on one of these operations also are included. Similarly, operations which call one of these as part of their definition are included.]} @end{Honest} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We have to include Replace_Element here because it might delete and reinsert the element if it moves in the set. That could change the order of iteration, which is what this check is designed to prevent. Replace is also included, as it is defined in terms of Replace_Element.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it finalizes @i<S>; or]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[it calls the Assign procedure with @i<S> as the Target parameter; or]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We don't need to explicitly mention @nt{assignment_statement}, because that finalizes the target object as part of the operation, and finalization of an object is already defined as tampering with cursors.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls the Move procedure with @i<S> as a parameter; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it calls one of the operations defined to tamper with cursors of @i<S>.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn2{Term=[tamper with elements],Sec=[of a set]} A subprogram is said to @i{tamper with elements} of a set object @i<S> if:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[it tampers with cursors of @i<S>.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Complete replacement of an element can cause its memory to be deallocated while another operation is holding onto a reference to it. That can't be allowed. However, a simple modification of (part of) an element is not a problem, so Update_@!Element_@!Preserving_@!Key does not cause a problem.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't need to list Replace and Replace_Element here because they are covered by @lquotes@;tamper with cursors@rquotes. For Set, @lquotes@;tamper with cursors@rquotes@; and @lquotes@;tamper with elements@rquotes are the same. We leave both terms so that the rules for routines like Iterate and Query_Element are consistent across all containers.]} @end{Reason} @end{Itemize} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[prohibited],Sec=[tampering with a set]} @Defn2{Term=[tampering],Sec=[prohibited for a set]} When tampering with cursors is @i<prohibited> for a particular set object @i<S>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the cursors of @i<S>, leaving @i<S> unmodified. Similarly, when tampering with elements is @i<prohibited> for a particular set object @i<S>, Program_Error is propagated by a call of any language-defined subprogram that is defined to tamper with the elements of @i<S> @Redundant[(or tamper with the cursors of @i<S>)], leaving @i<S> unmodified.]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Tampering with elements includes tampering with cursors, so we mention it only from completeness in the second sentence.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Empty_Set represents the empty Set object. It has a length of 0. If an object of type Set is not otherwise initialized, it is initialized to the same value as Empty_Set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No_Element represents a cursor that designates no element. If an object of type Cursor is not otherwise initialized, it is initialized to the same value as No_Element.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The predefined "=" operator for type Cursor returns True if both cursors are No_Element, or designate the same element in the same container.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A cursor will probably be implemented in terms of one or more access values, and the effects of streaming access values is unspecified. Rather than letting the user stream junk by accident, we mandate that streaming of cursors raise Program_Error by default. The attributes can always be specified if there is a need to support streaming.]} @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Set'Write for a Set object @i<S> writes Length(@i<S>) elements of the set to the stream. It also may write additional information about the set.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Set'Read reads the representation of a set from the stream, and assigns to @i<Item> a set with the same length and elements as was written by Set'Write.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Streaming more elements than the container length is wrong. For implementation implications of this rule, see the Implementation Note in @RefSecNum{The Generic Package Containers.Vectors}.]} @end{Ramification} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if Position designates an element, and returns False otherwise.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[This function might not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]} @end{Honest} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same set object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each element @i<E> in Left, the function returns False if an element equal to @i<E> (using the generic formal equality operator) is not present in Right. If the function has not returned a result after checking all of the elements, it returns True. Any exception raised during evaluation of element equality is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This wording describes the canonical semantics. However, the order and number of calls on the formal equality function is unspecified for all of the operations that use it in this package, so an implementation can call it as many or as few times as it needs to get the correct answer. Specifically, there is no requirement to call the formal equality additional times once the answer has been determined.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Sets (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Left and Right denote the same set object, then the function returns True. If Left and Right have different lengths, then the function returns False. Otherwise, for each element @i<E> in Left, the function returns False if an element equivalent to @i<E> is not present in Right. If the function has not returned a result after checking all of the elements, it returns True. Any exception raised during evaluation of element equivalence is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} To_Set (New_Item : Element_Type) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set containing the single element New_Item.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Length (Container : Set) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the number of elements in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Empty (Container : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Length (Container) = 0.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Removes all the elements from Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Element (Position : Cursor) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Element returns the element designated by Position.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace_Element (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. If an element equivalent to New_Item is already present in Container at a position other than Position, Program_Error is propagated. Otherwise, Replace_Element assigns New_Item to the element designated by Position. Any exception raised by the assignment is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The final assignment may require that the node of the element be moved in the Set's data structures. That could mean that implementing this operation exactly as worded above could require the overhead of searching twice. Implementations are encouraged to avoid this extra overhead when possible, by prechecking if the old element is equivalent to the new one, by inserting a placeholder node while checking for an equivalent element, and similar optimizations.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The cursor still designates the same element after this operation; only the value of that element has changed. Cursors cannot include information about the relative position of an element in a Set (as they must survive insertions and deletions of other elements), so this should not pose an implementation hardship.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Query_Element (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0021-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. Otherwise, Query_Element calls Process.@key{all} with the element designated by Position as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of @Chg{Version=[3],New=[the set that contains the element designated by Position is prohibited during the execution of the call on Process.@key{all}],Old=[Container]}. Any exception raised by Process.@key{all} is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The type Constant_Reference_Type needs finalization.@PDefn2{Term=<needs finalization>, Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Constant_Reference_Type propagates Program_Error.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[It is expected that Constant_Reference_Type will be a controlled type, for which finalization will have some action to terminate the tampering check for the associated container. If the object is created by default, however, there is no associated container. Since this is useless, and supporting this case would take extra work, we define it to raise an exception.]} @end{Reason} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Set; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Constant_Indexing and Implicit_Dereference aspects) provides a convenient way to gain read access to an individual element of a set given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Constant_Reference returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Constant_Reference exists and has not been finalized.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{procedure} Assign (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Target denotes the same object as Source, the operation has no effect. Otherwise, the elements of Source are copied to Target as for an @nt{assignment_statement} assigning Source to Target.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This routine exists for compatibility with the bounded set containers. For an unbounded set, @exam{Assign(A, B)} and @exam{A := B} behave identically. For a bounded set, := will raise an exception if the container capacities are different, while Assign will not raise an exception if there is enough room in the target.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Move (Target : @key{in out} Set; Source : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then @Chg{Version=[3],New=[the operation],Old=[Move]} has no effect. Otherwise, @Chg{Version=[3],New=[the operation is equivalent to Assign (Target, Source) followed by Clear (Source)],Old=[Move first clears Target. Then, each element from Source is removed from Source and inserted into Target. The length of Source is 0 after a successful call to Move]}.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert checks if an element equivalent to New_Item is already present in Container. If a match is found, Inserted is set to False and Position designates the matching element. Otherwise, Insert adds New_Item to Container; Inserted is set to True and Position designates the newly-inserted element. Any exception raised during allocation is propagated and Container is not modified.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Insert inserts New_Item into Container as per the four-parameter Insert, with the difference that if an element equivalent to New_Item is already in the set, then Constraint_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[This is equivalent to:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{declare} Inserted : Boolean; C : Cursor; @key{begin} Insert (Container, New_Item, C, Inserted); @key{if not} Inserted @key{then} @key{raise} Constraint_Error; @key{end if}; @key{end};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[but doesn't require the hassle of @key{out} parameters.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Include (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Include inserts New_Item into Container as per the four-parameter Insert, with the difference that if an element equivalent to New_Item is already in the set, then it is replaced. Any exception raised during assignment is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Replace checks if an element equivalent to New_Item is already in the set. If a match is found, that element is replaced with New_Item; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Exclude (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Exclude checks if an element equivalent to Item is present in Container. If a match is found, Exclude removes the element from the set.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Delete checks if an element equivalent to Item is present in Container. If a match is found, Delete removes the element from the set; otherwise, Constraint_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Constraint_Error is propagated. If Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Delete removes the element designated by Position from the set. Position is set to No_Element on return.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The check on Position checks that the cursor does not belong to some other set. This check implies that a reference to the set is included in the cursor value. This wording is not meant to require detection of dangling cursors; such cursors are defined to be invalid, which means that execution is erroneous, and any result is allowed (including not raising an exception).]} @end{Ramification} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Union (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Union inserts into Target the elements of Source that are not equivalent to some element already in Target.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the objects are the same, the result is the same as the original object. The implementation needs to take care so that aliasing effects do not make the result trash; Union (S, S); must work.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Union (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising all of the elements of Left, and the elements of Right that are not equivalent to some element of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Intersection (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[Intersection],Old=[Union]} deletes from Target the elements of Target that are not equivalent to some element of Source.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the objects are the same, the result is the same as the original object. The implementation needs to take care so that aliasing effects do not make the result trash; Intersection (S, S); must work.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Intersection (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising all the elements of Left that are equivalent to the some element of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Difference (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Difference clears Target. Otherwise, it deletes from Target the elements that are equivalent to some element of Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Difference (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising the elements of Left that are not equivalent to some element of Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Symmetric_Difference (Target : @key{in out} Set; Source : @key{in} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Target denotes the same object as Source, then Symmetric_Difference clears Target. Otherwise, it deletes from Target the elements that are equivalent to some element of Source, and inserts into Target the elements of Source that are not equivalent to some element of Target.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Symmetric_Difference (Left, Right : Set) @key{return} Set;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a set comprising the elements of Left that are not equivalent to some element of Right, and the elements of Right that are not equivalent to some element of Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Overlap (Left, Right : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If an element of Left is equivalent to some element of Right, then Overlap returns True. Otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is commutative. If Overlap returns False, the two sets are disjoint.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Is_Subset (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If an element of Subset is not equivalent to some element of Of_Set, then Is_Subset returns False. Otherwise@Chg{Version=[3],New=[,],Old=[]} it returns True.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is not commutative, so we use parameter names that make it clear in named notation which set is which.]} @end{Discussion} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Next (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the successor of the element designated by Position. If Position designates the last element, then No_Element is returned. If Position equals No_Element, then No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Next (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Next (Position).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0004-1]} @ChgDeleted{Version=[3],Type=[Trailing],Text=[@Chg{Version=[2],New=[Equivalent to Find (Container, Item) /= No_Element.],Old=[]}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Find (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) equals 0, then Find returns No_Element. Otherwise, Find checks if an element equivalent to Item is present in Container. If a match is found, a cursor designating the matching element is returned; otherwise, No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Contains (Container : Set; Item : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0004-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Find (Container, Item) /= No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@Chg{Version=[3],New=[],Old=[@key{function} Has_Element (Position : Cursor) @key{return} Boolean;]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[],Old=[Returns True if Position designates an element, and returns False otherwise.]}]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[This function may not detect cursors that designate deleted elements; such cursors are invalid (see below) and the result of calling Has_Element with an invalid cursor is unspecified (but not erroneous).]}]} @end{Honest} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 83 and 84 were moved above.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Iterate (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterate calls Process.@key{all} with a cursor that designates each element in Container, starting with the first element and moving the cursor according to the successor relation. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the cursors of Container@Chg{Version=[3],New=[ is prohibited during the execution of a call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @lquotes@;tamper with cursors@rquotes@; check takes place when the operations that insert or delete elements, and so on are called.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See Iterate for vectors (@RefSecNum{The Generic Package Containers.Vectors}) for a suggested implementation of the check.]} @end{ImplNote} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Both Containers.Hashed_Set and Containers.Ordered_Set declare a nested generic package Generic_Keys, which provides operations that allow set manipulation in terms of a key (typically, a portion of an element) instead of a complete element. The formal function Key of Generic_Keys extracts a key value from an element. It is expected to return the same value each time it is called with a particular element. The behavior of Generic_Keys is unspecified if Key behaves in some other manner.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[A key is expected to unambiguously determine a single equivalence class for elements. The behavior of Generic_Keys is unspecified if the formal parameters of this package behave in some other manner.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Key (Position : Cursor) @key{return} Key_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Key (Element (Position)).]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The subprograms in package Generic_Keys named Contains, Find, Element, Delete, and Exclude, are equivalent to the corresponding subprograms in the parent package, with the difference that the Key parameter is used to locate an element in the set.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Replace (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Replace_Element (Container, Find (Container, Key), New_Item).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Update_Element_Preserving_Key (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0265-1]} @ChgAdded{Version=[2],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Update_@!Element_@!Preserving_Key uses Key to save the key value @i<K> of the element designated by Position. Update_@!Element_@!Preserving_Key then calls Process.@key{all} with that element as the argument. @Chg{Version=[3],New=[Tampering],Old=[Program_Error is propagated if Process.@key{all} tampers]} with the elements of Container@Chg{Version=[3],New=[ is prohibited during the execution of the call on Process.@key{all}],Old=[]}. Any exception raised by Process.@key{all} is propagated. After Process.@key{all} returns, Update_@!Element_@!Preserving_Key checks if @i<K> determines the same equivalence class as that for the new element; if not, the element is removed from the set and Program_Error is propagated.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The key check ensures that the invariants of the set are preserved by the modification. The @lquotes@;tampers with the elements@rquotes@; check prevents data loss (if Element_Type is by-copy) or erroneous execution (if element type is unconstrained and indefinite).]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Element_Type is unconstrained and definite, then the actual Element parameter of Process.@key{all} shall be unconstrained.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that the elements cannot be directly allocated from the heap; it must be possible to change the discriminants of the element in place.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[type] Reference_Type (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[The type Reference_Type needs finalization.@PDefn2{Term=<needs finalization>, Sec=<language-defined type>}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[The default initialization of an object of type Reference_Type propagates Program_Error.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference_Preserving_Key (Container : @key[aliased in out] Set; Position : @key[in] Cursor) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Implicit_Dereference aspect) provides a convenient way to gain read and write access to an individual element of a set given a cursor.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[If Position equals No_Element, then Constraint_Error is propagated; if Position does not designate an element in Container, then Program_Error is propagated. Otherwise, Reference_Preserving_Key uses Key to save the key value @i<K>; then returns an object whose discriminant is an access value that designates the element designated by Position. Tampering with the elements of Container is prohibited while the object returned by Reference_Preserving_Key exists and has not been finalized. When the object returned by Reference_Preserving_Key is finalized, a check is made if @i<K> determines the same equivalence class as that for the new element; if not, the element is removed from the set and Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Constant_Reference (Container : @key[aliased in] Set; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Implicit_Dereference aspect) provides a convenient way to gain read access to an individual element of a set given a key value.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Equivalent to Constant_Reference (Container, Find (Container, Key)).]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Reference_Preserving_Key (Container : @key[aliased in out] Set; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[This function (combined with the Implicit_Dereference aspect) provides a convenient way to gain read and write access to an individual element of a set given a key value.]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Equivalent to Reference_Preserving_Key (Container, Find (Container, Key)).]} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0022-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error for the actual function associated with a generic formal subprogram, when called as part of an operation of a set package, to tamper with elements of any set parameter of the operation. Either Program_Error is raised, or the operation works as defined on the value of the set either prior to, or subsequent to, some or all of the modifications to the set.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call any subprogram declared in the visible part of a set package when the associated container has been finalized. If the operation takes Container as an @key[in out] parameter, then it raises Constraint_Error or Program_Error. Otherwise, the operation either proceeds as it would for an empty container, or it raises Constraint_Error or Program_Error.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Leading],Text=[ A Cursor value is @i<invalid> if any of the following have occurred since it was created:@Defn2{Term=[invalid cursor],Sec=[of a set]} @PDefn2{Term=[cursor],Sec=[invalid]}]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The set that contains the element it designates has been finalized;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[The set that contains the element it designates has been used as the Target of a call to Assign, or as the target of an @nt{assignment_statement};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The set that contains the element it designates has been used as the Source or Target of a call to Move; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0160-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The element it designates has been @Chg{Version=[3],New=[removed],Old=[deleted]} from the set@Chg{Version=[3],New=[ that previously contained the element],Old=[]}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[This can happen directly via calls to Clear, Exclude, Delete, and Update_Element_Preserving_Key, and indirectly via calls to procedures Intersection, Difference, and Symmetric_Difference.]} @end{Ramification} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The result of "=" or Has_Element is unspecified if these functions are called with an invalid cursor parameter.@PDefn{unspecified} Execution is erroneous if any other subprogram declared in Containers.Hashed_Sets or Containers.Ordered_Sets is called with an invalid cursor parameter.@PDefn2{Term=(erroneous execution),Sec=(cause)}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The list above is intended to be exhaustive. In other cases, a cursor value continues to designate its original element. For instance, cursor values survive the insertion and deletion of other elements.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While it is possible to check for these cases, in many cases the overhead necessary to make the check is substantial in time or space. Implementations are encouraged to check for as many of these cases as possible and raise Program_Error if detected.]} @end{Discussion} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[Execution is erroneous if the set associated with the result of a call to Reference or Constant_Reference is finalized before the result object returned by the call to Reference or Constant_Reference is finalized.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Each object of Reference_Type and Constant_Reference_Type probably contains some reference to the originating container. If that container is prematurely finalized (which is only possible via Unchecked_Deallocation, as accessibility checks prevent passing a container to Reference that will not live as long as the result), the finalization of the object of Reference_Type will try to access a nonexistent object. This is a normal case of a dangling pointer created by Unchecked_Deallocation; we have to explicitly mention it here as the pointer in question is not visible in the specification of the type. (This is the same reason we have to say this for invalid cursors.)]} @end{Reason} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[No storage associated with a Set object shall be lost upon assignment or scope exit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The execution of an @nt{assignment_statement} for a set shall have the effect of copying the elements from the source set object to the target set object@Chg{Version=[3],New=[ and changing the length of the target object to that of the source object],Old=[]}.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[An assignment of a Set is a @lquotes@;deep@rquotes copy; that is the elements are copied as well as the data structures. We say @lquotes@;effect of@rquotes in order to allow the implementation to avoid copying elements immediately if it wishes. For instance, an implementation that avoided copying until one of the containers is modified would be allowed.@Chg{Version=[3],New=[ (Note that this implementation would require care, see @RefSecNum{The Generic Package Containers.Vectors} for more.)],Old=[]}]} @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Move should not copy elements, and should minimize copying of internal data structures.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Move for sets should not copy elements, and should minimize copying of internal data structures.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Usually that can be accomplished simply by moving the pointer(s) to the internal data structures from the Source container to the Target container.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If an exception is propagated from a set operation, no storage should be lost, nor any elements removed from a set unless specified by the operation.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an exception is propagated from a set operation, no storage should be lost, nor any elements removed from a set unless specified by the operation.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is important so that programs can recover from errors. But we don't want to require heroic efforts, so we just require documentation of cases where this can't be accomplished.]} @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[This description of sets is new; the extensions are documented with the specific packages.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added reference support to make set containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Added procedure Assign; the extension and incompatibility is documented with the specific packages.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[Generalized the definition of Move. Specified which elements are read/written by stream attributes.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0022-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover tampering by generic actual subprograms.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0027-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a @BoundedName to cover access to finalized set containers.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0160-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Revised the definition of invalid cursors to cover missing (and new) cases.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0265-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Defined when a container prohibits tampering in order to more clearly define where the check is made and the exception raised.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Hashed_Sets]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Hashed_Sets has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Element_Type @key{is private}; @key{with function} Hash (Element : Element_Type) @key{return} Hash_Type; @key{with function} Equivalent_Elements (Left, Right : Element_Type) @key{return} Boolean; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Hashed_Sets @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Hashed_Sets]} @key{pragma} Preelaborate(Hashed_Sets);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Hashed_Sets);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Set} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Set} : @key{constant} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{Set_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Sets} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Set} (New_Item : Element_Type) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Capacity} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reserve_Capacity} (Container : @key{in out} Set; Capacity : @key{in} Count_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Set; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign} (Target : @key[in out] Set; Source : @key[in] Set);]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Set; Capacity : Count_Type := 0) @key[return] Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Set; Source : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Union} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Union} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{or}" (Left, Right : Set) @key{return} Set @key{renames} Union;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Intersection} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Intersection} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{and}" (Left, Right : Set) @key{return} Set @key{renames} Intersection;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "-" (Left, Right : Set) @key{return} Set @key{renames} Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Symmetric_Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Symmetric_Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{xor}" (Left, Right : Set) @key{return} Set @key{renames} Symmetric_Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Overlap} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Subset} (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Set) @key[return] Set_Iterator_Interfaces.Forward_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{type} Key_Type (<>) @key{is private}; @key{with function} Key (Element : Element_Type) @key{return} Key_Type; @key{with function} Hash (Key : Key_Type) @key{return} Hash_Type; @key{with function} Equivalent_Keys (Left, Right : Key_Type) @key{return} Boolean; @key{package} @AdaPackDefn{Generic_Keys} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Set; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element_Preserving_Key} (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference_Preserving_Key} (Container : @key[aliased in out] Set; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Set; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference_Preserving_Key} (Container : @key[aliased in out] Set; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Keys;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Hashed_Sets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[capacity],Sec=[of a hashed set]} An object of type Set contains an expandable hash table, which is used to provide direct access to elements. The @i<capacity> of an object of type Set is the maximum number of elements that can be inserted into the hash table prior to it being automatically expanded.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[equivalent element],Sec=[of a hashed set]} Two elements @i<E1> and @i<E2> are defined to be @i<equivalent> if Equivalent_Elements (@i<E1>, @i<E2>) returns True.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Hash is expected to return the same value each time it is called with a particular element value. For any two equivalent elements, the actual for Hash is expected to return the same value. If the actual for Hash behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function Equivalent_Elements is expected to return the same value each time it is called with a particular pair of Element values. It should define an equivalence relationship, that is, be reflexive, symmetric, and transitive. If the actual for Equivalent_Elements behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Equivalent_Elements, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[If the actual function for the generic formal function "=" returns True for any pair of nonequivalent elements, then the behavior of the container function "=" is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of an element stored in a set is changed other than by an operation in this package such that at least one of Hash or Equivalent_Elements give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See @RefSec{The Generic Package Containers.Hashed_Maps} for a suggested implementation, and for justification of the restrictions regarding Hash and Equivalent_Elements. Note that sets only need to store elements, not key/element pairs.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of a hashed set]} @Defn2{Term=[last element],Sec=[of a hashed set]} @Defn2{Term=[successor element],Sec=[of a hashed set]} Which elements are the first element and the last element of a set, and which element is the successor of a given element, are unspecified, other than the general semantics described in @RefSecNum{Sets}.@PDefn{unspecified}]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Capacity (Container : Set) @key{return} Count_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the capacity of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reserve_Capacity (Container : @key{in out} Set; Capacity : @key{in} Count_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Reserve_Capacity allocates a new hash table such that the length of the resulting set can become at least the value Capacity without requiring an additional call to Reserve_Capacity, and is large enough to hold the current length of Container. Reserve_Capacity then rehashes the elements in Container onto the new hash table. It replaces the old hash table with the new hash table, and then deallocates the old hash table. Any exception raised during allocation is propagated and Container is not modified.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors of Container.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Reserve_Capacity tampers with the cursors, as rehashing probably will change the relationships of the elements in Container.]} @end{Reason} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Sets}, Clear does not affect the capacity of Container.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[procedure] Assign (Target : @key[in out] Set; Source : @key[in] Set);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Sets}, if the length of Source is greater than the capacity of Target, Reserve_Capacity (Target, Length (Source)) is called before assigning any elements.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Copy (Source : Set; Capacity : Count_Type := 0) @key[return] Set;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a set whose elements are initialized from the elements of Source. If Capacity is 0, then the set capacity is the length of Source; if Capacity is equal to or greater than the length of Source, the set capacity is at least the specified value. Otherwise, the operation propagates Capacity_Error.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Insert (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[In addition to the semantics described in @RefSecNum{Sets}, if Length (Container) equals Capacity (Container), then Insert first calls Reserve_Capacity to increase the capacity of Container to some larger value.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Length (Container) = 0, then First returns No_Element. Otherwise, First returns a cursor that designates the first hashed element in Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Element (Left), Element (Right)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Element (Left), Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Equivalent_Elements (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Equivalent_Elements (Left, Element (Right)).]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Set) @key[return] Set_Iterator_Interfaces.Forward_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns an iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each element in Container, starting with the first element and moving the cursor according to the successor relation. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any element @i{E}, the actual function for the generic formal function Generic_Keys.Hash is expected to be such that Hash (@i{E}) = Generic_Keys.Hash (Key (@i{E})). If the actuals for Key or Generic_Keys.Hash behave in some other manner, the behavior of Generic_Keys is unspecified. Which subprograms of Generic_Keys call Generic_Keys.Hash, and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any two elements @i{E1} and @i{E2}, the boolean values Equivalent_Elements (@i{E1}, @i{E2}) and Equivalent_Keys (Key (@i{E1}), Key (@i{E2})) are expected to be equal. If the actuals for Key or Equivalent_Keys behave in some other manner, the behavior of Generic_Keys is unspecified. Which subprograms of Generic_Keys call Equivalent_Keys, and how many times they call it, is unspecified.@PDefn{unspecified}]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a set, the average time complexity of the subprograms Insert, Include, Replace, Delete, Exclude and Find that take an element parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms that take a cursor parameter should be @i{O}(1). The average time complexity of Reserve_Capacity should be @i{O}(@i<N>).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The average time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations of Containers.Hashed_Sets that take an element parameter should be @i{O}(log @i<N>). The average time complexity of the subprograms of Containers.Hashed_Sets that take a cursor parameter should be @i{O}(1). The average time complexity of Containers.@!Hashed_Sets.@!Reserve_Capacity should be @i{O}(@i<N>).]}]} @end{ImplAdvice} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[See @RefSec{The Generic Package Containers.Hashed_Maps} for implementation notes regarding some of the operations of this package.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Hashed_Sets is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Hashed_Sets. If an instance of Containers.Hashed_Sets is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Hashed_Sets is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator and indexing support to make hashed set containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to require the formal function be such that equal elements are also equivalent.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @end{DiffWord2005} @LabeledAddedSubclause{Version=[2],Name=[The Generic Package Containers.Ordered_Sets]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Containers.Ordered_Sets has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0084-1],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[@key[with] Ada.Iterator_Interfaces; ],Old=[]}@key{generic} @key{type} Element_Type @key{is private}; @key{with function} "<" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{with function} "=" (Left, Right : Element_Type) @key{return} Boolean @key{is} <>; @key{package} Ada.Containers.Ordered_Sets @key{is}@ChildUnit{Parent=[Ada.Containers],Child=[Ordered_Sets]} @key{pragma} Preelaborate(Ordered_Sets);@Chg{Version=[3],New=[ @key{pragma} Remote_Types(Ordered_Sets);],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Elements} (Left, Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Set} @key{is tagged private}@Chg{Version=[3],New=[ @key[with] Constant_Indexing => Constant_Reference, Default_Iterator => Iterate, Iterator_Element => Element_Type],Old=[]}; @key{pragma} Preelaborable_Initialization(Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Cursor} @key{is private}; @key{pragma} Preelaborable_Initialization(Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Empty_Set} : @key{constant} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{No_Element} : @key{constant} Cursor;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[package] @AdaPackDefn{Set_Iterator_Interfaces} @key[is new] Ada.Iterator_Interfaces (Cursor, Has_Element);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "=" (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Sets} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{To_Set} (New_Item : Element_Type) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Length} (Container : Set) @key{return} Count_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Empty} (Container : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Position : Cursor) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace_Element} (Container : @key{in out} Set; Position : @key{in} Cursor; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Query_Element} (Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] Constant_Reference_Type (Element : @key[not null access constant] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Set; Position : @key[in] Cursor) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign} (Target : @key[in out] Set; Source : @key[in] Set);]} @ChgRef{Version=[3],Kind=[Added],Aref=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Copy} (Source : Set) @key[return] Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Move} (Target : @key{in out} Set; Source : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type; Position : @key{out} Cursor; Inserted : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Insert} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Include} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_First} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Last} (Container : @key{in out} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Union} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Union} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{or}" (Left, Right : Set) @key{return} Set @key{renames} Union;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Intersection} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Intersection} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{and}" (Left, Right : Set) @key{return} Set @key{renames} Intersection;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "-" (Left, Right : Set) @key{return} Set @key{renames} Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Symmetric_Difference} (Target : @key{in out} Set; Source : @key{in} Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Symmetric_Difference} (Left, Right : Set) @key{return} Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "@key{xor}" (Left, Right : Set) @key{return} Set @key{renames} Symmetric_Difference;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Overlap} (Left, Right : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Is_Subset} (Subset : Set; Of_Set : Set) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{First_Element} (Container : Set) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last} (Container : Set) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Last_Element} (Container : Set) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Next} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Next} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Previous} (Position : Cursor) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Previous} (Position : @key{in out} Cursor);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Set; Item : Element_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Item : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[ @key{function} @AdaSubDefn{Has_Element} (Position : Cursor) @key{return} Boolean;]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} ">" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Reverse_Iterate} (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Set) @key[return] Set_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[ @key[function] Iterate (Container : @key[in] Set; Start : @key[in] Cursor) @key[return] Set_Iterator_Interfaces.Reversible_Iterator'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{generic} @key{type} Key_Type (<>) @key{is private}; @key{with function} Key (Element : Element_Type) @key{return} Key_Type; @key{with function} "<" (Left, Right : Key_Type) @key{return} Boolean @key{is} <>; @key{package} @AdaPackDefn{Generic_Keys} @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Equivalent_Keys} (Left, Right : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Key} (Position : Cursor) @key{return} Key_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Element} (Container : Set; Key : Key_Type) @key{return} Element_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replace} (Container : @key{in out} Set; Key : @key{in} Key_Type; New_Item : @key{in} Element_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Exclude} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete} (Container : @key{in out} Set; Key : @key{in} Key_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Find} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Floor} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Ceiling} (Container : Set; Key : Key_Type) @key{return} Cursor;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Contains} (Container : Set; Key : Key_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Update_Element_Preserving_Key} (Container : @key{in out} Set; Position : @key{in} Cursor; Process : @key{not null access procedure} (Element : @key{in out} Element_Type));]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Reference_Type} (Element : @key[not null access] Element_Type) @key[is private] @key[with] Implicit_Dereference => Element;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference_Preserving_Key} (Container : @key[aliased in out] Set; Position : @key[in] Cursor) @key[return] Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Constant_Reference} (Container : @key[aliased in] Set; Key : @key[in] Key_Type) @key[return] Constant_Reference_Type;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Reference_Preserving_Key} (Container : @key[aliased in out] Set; Key : @key[in] Key_Type) @key[return] Reference_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{end} Generic_Keys;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... -- @RI[not specified by the language]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Containers.Ordered_Sets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Two elements @i<E1> and @i<E2> are @i<equivalent> if both @i<E1> < @i<E2> and @i<E2> < @i<E1> return False, using the generic formal "<" operator for elements.@Defn2{Term=[equivalent element],Sec=[of an ordered set]} Function Equivalent_Elements returns True if Left and Right are equivalent, and False otherwise.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0044-1]} @ChgAdded{Version=[2],Text=[The actual function for the generic formal function "<" on Element_Type values is expected to return the same value each time it is called with a particular pair of key values. It should define a strict @Chg{Version=[3],New=[weak ],Old=[]}ordering relationship@Chg{Version=[3], New=[ (see @RefSecNum{Containers})],Old=[, that is, be irreflexive, asymmetric, and transitive]}. If the actual for "<" behaves in some other manner, the behavior of this package is unspecified. Which subprograms of this package call "<" and how many times they call it, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[If the actual function for the generic formal function "=" returns True for any pair of nonequivalent elements, then the behavior of the container function "=" is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If the value of an element stored in a set is changed other than by an operation in this package such that at least one of "<" or "=" give different results, the behavior of this package is unspecified.@PDefn{unspecified}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[See @RefSec{The Generic Package Containers.Ordered_Maps} for a suggested implementation, and for justification of the restrictions regarding "<" and "=". Note that sets only need to store elements, not key/element pairs.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[first element],Sec=[of an ordered set]} @Defn2{Term=[last element],Sec=[of an ordered set]} @Defn2{Term=[successor element],Sec=[of an ordered set]}@Chg{Version=[3],New=[ @Defn2{Term=[predecessor element],Sec=[of an ordered set]}],Old=[]} The @Chg{Version=[3],New=[@i<first element>],Old=[first element]} of a nonempty set is the one which is less than all the other elements in the set. The @Chg{Version=[3],New=[@i<last element>],Old=[last element]} of a nonempty set is the one which is greater than all the other elements in the set. The @Chg{Version=[3],New=[@i<successor>],Old=[successor]} of an element is the smallest element that is larger than the given element. The @Chg{Version=[3],New=[@i<predecessor>],Old=[predecessor]} of an element is the largest element that is smaller than the given element. All comparisons are done using the generic formal "<" operator for elements.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Copy (Source : Set) @key[return] Set;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns a set whose elements are initialized from the corresponding elements of Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_First (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_First has no effect. Otherwise@Chg{Version=[3],New=[,],Old=[]} the element designated by First (Container) is removed from Container. Delete_First tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Delete_Last (Container : @key{in out} Set);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Container is empty, Delete_Last has no effect. Otherwise@Chg{Version=[3],New=[,],Old=[]} the element designated by Last (Container) is removed from Container. Delete_Last tampers with the cursors of Container.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} First_Element (Container : Set) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (First (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last (Container : Set) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a cursor that designates the last element in Container. If Container is empty, returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Last_Element (Container : Set) @key{return} Element_Type;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Last (Container)).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Previous (Position : Cursor) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If Position equals No_Element, then Previous returns No_Element. Otherwise@Chg{Version=[3],New=[,],Old=[]} Previous returns a cursor designating the @Chg{Version=[3],New=[predecessor ],Old=[]}element @Chg{Version=[3],New=[of],Old=[that precedes]} the one designated by Position. If Position designates the first element, then Previous returns No_Element.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Previous (Position : @key{in out} Cursor);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Position := Previous (Position).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Floor (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Floor searches for the last element which is not greater than Item. If such an element is found, a cursor that designates it is returned. Otherwise@Chg{Version=[3],New=[,],Old=[]} No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Ceiling (Container : Set; Item : Element_Type) @key{return} Cursor;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ceiling searches for the first element which is not less than Item. If such an element is found, a cursor that designates it is returned. Otherwise@Chg{Version=[3],New=[,],Old=[]} No_Element is returned.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Left) < Element (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left, Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Right) < Element (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Left) < Right.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Cursor; Right : Element_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Right < Element (Left).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} "<" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Left < Element (Right).]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} ">" (Left : Element_Type; Right : Cursor) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Element (Right) < Left.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Reverse_Iterate (Container : @key{in} Set; Process : @key{not null access procedure} (Position : @key{in} Cursor));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0212-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Iterates over the elements in Container as per @Chg{Version=[3],New=[procedure ],Old=[]}Iterate, with the difference that the elements are traversed in predecessor order, starting with the last element.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Set) @key[return] Set_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0212-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each element in Container, starting with the first element and moving the cursor according to the successor relation when used as a forward iterator, and starting with the last element and moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key[function] Iterate (Container : @key[in] Set; Start : @key[in] Cursor) @key[return] Set_Iterator_Interfaces.Reversible_Iterator'Class;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1],ARef=[AI05-0265-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Otherwise, Iterate returns a reversible iterator object (see @RefSecNum{User-Defined Iterator Types}) that will generate a value for a loop parameter (see @RefSecNum{Generalized Loop Iteration}) designating each element in Container, starting with the element designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @nt{sequence_of_statements} of the @nt{loop_statement} whose @nt{iterator_specification} denotes this object). The iterator object needs finalization.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Exits are allowed from the loops created using the iterator objects. In particular, to stop the iteration at a particular cursor, just add]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[exit when] Cur = Stop;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[in the body of the loop (assuming that @exam{Cur} is the loop parameter and @exam{Stop} is the cursor that you want to stop at).]} @end{Discussion} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[For any two elements @i<E1> and @i<E2>, the boolean values (@i<E1> < @i<E2>) and (Key(@i<E1>) < Key(@i<E2>)) are expected to be equal. If the actuals for Key or Generic_Keys."<" behave in some other manner, the behavior of this package is unspecified. Which subprograms of this package call Key and Generic_Keys."<", and how many times the functions are called, is unspecified.@PDefn{unspecified}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[In addition to the semantics described in @RefSecNum{Sets}, the subprograms in package Generic_Keys named Floor and Ceiling, are equivalent to the corresponding subprograms in the parent package, with the difference that the Key subprogram parameter is compared to elements in the container using the Key and "<" generic formal functions. The function named Equivalent_Keys in package Generic_Keys returns True if both Left < Right and Right < Left return False using the generic formal "<" operator, and returns True otherwise.]} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[If @i<N> is the length of a set, then the worst-case time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations that take an element parameter should be @i{O}((log @i<N>)**2) or better. The worst-case time complexity of the subprograms that take a cursor parameter should be @i{O}(1).]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The worst-case time complexity of the Insert, Include, Replace, Delete, Exclude and Find operations of Containers.Ordered_Sets that take an element parameter should be @i{O}((log @i<N>)**2). The worst-case time complexity of the subprograms of Containers.Ordered_Sets that take a cursor parameter should be @i{O}(1).]}]} @end{ImplAdvice} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[See @RefSec{The Generic Package Containers.Ordered_Maps} for implementation notes regarding some of the operations of this package.]} @end{ImplNote} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The generic package Containers.Ordered_Sets is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}Subprograms Assign and Copy are added to Containers.Ordered_Sets. If an instance of Containers.Ordered_Sets is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Containers.Ordered_Sets is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0212-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Added iterator and indexing support to make ordered set containers more convenient to use.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to require the formal function be such that equal elements are also equivalent.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0044-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Redefined "<" actuals to require a strict weak ordering; the old definition allowed indeterminant comparisons that would not have worked in a container.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0084-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a pragma Remote_Types so that containers can be used in distributed programs.]} @end{DiffWord2005} ������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_dirs.mss���������������������������������������������������������0000755�0001752�0001001�00000227616�12066652506�017776� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_dirs.mss,v $ } @comment{ $Revision: 1.49 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(predefdirs, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledAddedClause{Version=[2],Name=[The Package Directories]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The package Directories provides operations for manipulating files and directories, and their names.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The notes for this @Chg{Version=[3],New=[subclause],Old=[clause]} contain the expected interpretations of some of the operations on various target systems. @lquotes@;Unix@rquotes@; refers to the UNIX@latin1(174) operating system, and in most cases also covers Unix-like systems such as Linux and POSIX. @lquotes@;Windows@latin1(174)@rquotes@; refers to the Microsoft@latin1(174) Windows@latin1(174) 2000 operating system and usually also covers most other versions that use the Win32 API.]} @end{Discussion} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Directories has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.IO_Exceptions; @key{with} Ada.Calendar; @key{package} Ada.Directories @key{is}@ChildUnit{Parent=[Ada],Child=[Directories]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Directory and file operations:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Current_Directory} @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Directory} (Directory : in String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Create_Directory} (New_Directory : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Directory} (Directory : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Create_Path} (New_Directory : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_Tree} (Directory : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Delete_File} (Name : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Rename} (Old_Name, New_Name : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Copy_File} (Source_Name, Target_Name : @key{in} String; Form : @key{in} String := "");]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[File and directory name operations:]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Full_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Simple_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Containing_Directory} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Extension} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Base_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Compose} (Containing_Directory : @key{in} String := ""; Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[ @Key{type} @AdaTypeDefn{Name_Case_Kind} @key{is} (Unknown, Case_Sensitive, Case_Insensitive, Case_Preserving);]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Name_Case_Equivalence} (Name : @key{in} String) @key{return} Name_Case_Kind;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{File and directory queries:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{File_Kind} @key{is} (Directory, Ordinary_File, Special_File);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{File_Size} @key{is range} 0 .. @RI{implementation-defined};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Exists} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Kind} (Name : @key{in} String) @key{return} File_Kind;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Size} (Name : @key{in} String) @key{return} File_Size;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modification_Time} (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Directory searching:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Directory_Entry_Type} @key{is limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Filter_Type} @key{is array} (File_Kind) @key{of} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Search_Type} @key{is limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Start_Search} (Search : @key{in out} Search_Type; Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{End_Search} (Search : @key{in out} Search_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{More_Entries} (Search : @key{in} Search_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Next_Entry} (Search : @key{in out} Search_Type; Directory_Entry : @key{out} Directory_Entry_Type);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Search ( Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True); Process : @key{not null access procedure} ( Directory_Entry : @key{in} Directory_Entry_Type));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI{Operations on Directory Entries:}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Simple_Name} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Full_Name} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Kind} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Kind;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Size} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Size;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Modification_Time} (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Status_Error} : @key{exception renames} Ada.IO_Exceptions.Status_Error; @AdaExcDefn{Name_Error} : @key{exception renames} Ada.IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key{exception renames} Ada.IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key{exception renames} Ada.IO_Exceptions.Device_Error;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[@key{private} @Chg{Version=[3],New=[... ],Old=[]}-- @RI{@Chg{Version=[3],New=[not],Old=[Not]} specified by the language@Chg{Version=[3],New=[],Old=[.]}} @key{end} Ada.Directories;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[External files may be classified as directories, special files, or ordinary files. A @i<directory> is an external file that is a container for files on the target system. A @i<special file> is an external file that cannot be created or read by a predefined Ada input-output package. External files that are not special files or directories are called @i<ordinary files>. @Defn{directory} @Defn{special file} @Defn{ordinary file}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A directory is an external file, although it may not have a name on some targets. A directory is not a special file, as it can be created and read by Directories.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Devices and soft links are examples of special files on Windows@latin1(174) and Unix.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Even if an implementation provides a package to create and read soft links, such links are still special files.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[A @i<file name> is a string identifying an external file. Similarly, a @i<directory name> is a string identifying a directory. The interpretation of file names and directory names is implementation-defined. @Defn{directory name} @Defn{file name}]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The interpretation of file names and directory names.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The @i<full name> of an external file is a full specification of the name of the file. If the external environment allows alternative specifications of the name (for example, abbreviations), the full name should not use such alternatives. A full name typically will include the names of all of the directories that contain the item. The @i<simple name> of an external file is the name of the item, not including any containing directory names. Unless otherwise specified, a file name or directory name parameter in a call to a predefined Ada input-output subprogram can be a full name, a simple name, or any other form of name supported by the implementation. @Defn2{Term=[full name],Sec=[of a file]} @Defn2{Term=[simple name],Sec=[of a file]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The full name on Unix is a complete path to the root. For Windows@latin1(174), the full name includes a complete path, as well as a disk name ("C:") or network share name. For both systems, the simple name is the part of the name following the last '/' (or '\' for Windows@latin1(174)). For example, in the name "/usr/randy/ada-directories.ads", "ada-directories.ads" is the simple name.]} @end{Discussion} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[It is possible for a file or directory name to be neither a full name nor a simple name. For instance, the Unix name "../parent/myfile" is neither a full name nor a simple name.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[The @i<default directory> is the directory that is used if a directory or file name is not a full name (that is, when the name does not fully identify all of the containing directories). @Defn{default directory}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The default directory is the one maintained by the familiar @lquotes@;cd@rquotes@; command on Unix and Windows@latin1(174). Note that Windows@latin1(174) maintains separate default directories for each disk drive; implementations should use the natural implementation.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[A @i<directory entry> is a single item in a directory, identifying a single external file (including directories and special files). @Defn{directory entry}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[For each function that returns a string, the lower bound of the returned value is 1.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading], Text=[The following file and directory operations are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Current_Directory @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full directory name for the current default directory. The name returned shall be suitable for a future call to Set_Directory. The exception Use_Error is propagated if a default directory is not supported by the external environment.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Set_Directory (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Sets the current default directory. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the external environment does not support making Directory (in the absence of Name_Error) a default directory.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Create_Directory (New_Directory : @key{in} String; Form : @key{in} String := "");]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Creates a directory with name New_Directory. The Form parameter can be used to give system-dependent characteristics of the directory; the interpretation of the Form parameter is implementation-defined. A null string for Form specifies the use of the default options of the implementation of the new directory. The exception Name_Error is propagated if the string given as New_Directory does not allow the identification of a directory. The exception Use_Error is propagated if the external environment does not support the creation of a directory with the given name (in the absence of Name_Error) and form.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_Directory (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0231-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing empty directory with name Directory. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the @Chg{Version=[3],New=[directory is not empty or the ],Old=[]}external environment does not support the deletion of the directory @Chg{Version=[3],New=[],Old=[(or some portion of its contents) ]}with the given name (in the absence of Name_Error).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Create_Path (New_Directory : @key{in} String; Form : @key{in} String := "");]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0271-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Creates zero or more directories with name New_Directory. Each nonexistent directory named by New_Directory is created.@Redundant[ For example, on a typical Unix system, Create_Path ("/usr/me/my"); would create directory "me" in directory "usr", then create directory "my" in directory "me".] The Form parameter can be used to give system-dependent characteristics of the directory; the interpretation of the Form parameter is implementation-defined. A null string for Form specifies the use of the default options of the implementation of the new directory. The exception Name_Error is propagated if the string given as New_Directory does not allow the identification of any directory. The exception Use_Error is propagated if the external environment does not support the creation of any directories with the given name (in the absence of Name_Error) and form.@Chg{Version=[3],New=[ If Use_Error is propagated, it is unspecified whether a portion of the directory path is created.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_Tree (Directory : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing directory with name Directory. The directory and all of its contents (possibly including other directories) are deleted. The exception Name_Error is propagated if the string given as Directory does not identify an existing directory. The exception Use_Error is propagated if the external environment does not support the deletion of the directory or some portion of its contents with the given name (in the absence of Name_Error). If Use_Error is propagated, it is unspecified whether a portion of the contents of the directory is deleted.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Delete_File (Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Deletes an existing ordinary or special file with name Name. The exception Name_Error is propagated if the string given as Name does not identify an existing ordinary or special external file. The exception Use_Error is propagated if the external environment does not support the deletion of the file with the given name (in the absence of Name_Error).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Rename (Old_Name, New_Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0231-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Renames an existing external file (including directories) with name Old_Name to New_Name. The exception Name_Error is propagated if the string given as Old_Name does not identify an existing external file@Chg{Version=[3],New=[ or if the string given as New_Name does not allow the identification of an external file],Old=[]}. The exception Use_Error is propagated if the external environment does not support the renaming of the file with the given name (in the absence of Name_Error). In particular, Use_Error is propagated if a file or directory already exists with name New_Name.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This operation is expected to work within a single directory, and implementers are encouraged to support it across directories on a single device. Copying files from one device to another is discouraged (that's what Copy_File is for). However, there is no requirement to detect file copying by the target system. If the target system has an API that gives that for @lquotes@;free@rquotes, it can be used. For Windows@latin1(174), for instance, MoveFile can be used to implement Rename.]} @end{ImplNote} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Copy_File (Source_Name, Target_Name : @key{in} String; Form : @key{in} String@Chg{Version=[3],New=[ := ""],Old=[]});]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0271-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Copies the contents of the existing external file with name Source_Name to an external file with name Target_Name. The resulting external file is a duplicate of the source external file. The Form parameter can be used to give system-dependent characteristics of the resulting external file; the interpretation of the Form parameter is implementation-defined. Exception Name_Error is propagated if the string given as Source_Name does not identify an existing external ordinary or special file, or if the string given as Target_Name does not allow the identification of an external file. The exception Use_Error is propagated if the external environment does not support creating the file with the name given by Target_Name and form given by Form, or copying of the file with the name given by Source_Name (in the absence of Name_Error).@Chg{Version=[3],New=[ If Use_Error is propagated, it is unspecified whether a portion of the file is copied.],Old=[]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Name_Error is always raised if Source_Name identifies a directory. It is up to the implementation whether special files can be copied, or if Use_Error will be raised.]} @end{Ramification} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following file and directory name operations are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Full_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full name corresponding to the file name specified by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Full name means that no abbreviations are used in the returned name, and that it is a full specification of the name. Thus, for Unix and Windows@latin1(174), the result should be a full path that does not contain any "." or ".." directories. Typically, the default directory is used to fill in any missing information.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Simple_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the simple name portion of the file name specified by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Containing_Directory (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the name of the containing directory of the external file (including directories) identified by Name. (If more than one directory can contain Name, the directory name returned is implementation-defined.) The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file. The exception Use_Error is propagated if the external file does not have a containing directory.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is purely a string manipulation function. If Name is not given as a full name, the containing directory probably won't be one, either. For example, if Containing_Directory ("..\AARM\RM-A-8") is called on Windows@latin1(174), the result should be "..\AARM". If there is no path at all on the name, the result should be "." (which represents the current directory). Use Full_Name on the result of Containing_Directory if the full name is needed.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Extension (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the extension name corresponding to Name. The extension name is a portion of a simple name (not including any separator characters), typically used to identify the file class. If the external environment does not have extension names, then the null string is returned. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Unix and Windows@latin1(174), the extension is the portion of the simple name following the rightmost period. For example, in the simple name "RM-A-8.html", the extension is "html".]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Base_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the base name corresponding to Name. The base name is the remainder of a simple name after removing any extension and extension separators. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Unix and Windows@latin1(174), the base name is the portion of the simple name preceding the rightmost period (except for the special directory names "." and "..", whose Base_Name is "." and ".."). For example, in the simple name "RM-A-8.html", the base name is "RM-A-8".]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Compose (Containing_Directory : @key{in} String := ""; Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the name of the external file with the specified Containing_Directory, Name, and Extension. If Extension is the null string, then Name is interpreted as a simple name; otherwise@Chg{Version=[3],New=[,],Old=[]} Name is interpreted as a base name. The exception Name_Error is propagated if the string given as Containing_Directory is not null and does not allow the identification of a directory, or if the string given as Extension is not null and is not a possible extension, or if the string given as Name is not a possible simple name (if Extension is null) or base name (if Extension is nonnull).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The above definition implies that if the Extension is null, for Unix and Windows@latin1(174) no '.' is added to Name.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If Name is null, Name_Error should be raised, as nothing is not a possible simple name or base name.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Generally, Compose(Containing_Directory(F), Base_Name(F),Extension(F)) = F. However, this is not true on Unix or Windows@latin1(174) for file names that end with a '.'; Compose(Base_Name("Fooey."),Extension("Fooey.")) = "Fooey". This is not a problem for Windows@latin1(174), as the names have the same meaning with or without the '.', but these are different names for Unix. Thus, care needs to be taken on Unix; if Extension is null, Base_Name should be avoided. (That's not usually a problem with file names generated by a program.)]} @end{Discussion} @begin{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key{function} Name_Case_Equivalence (Name : @key{in} String) @key{return} Name_Case_Kind;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0049-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Returns the file name equivalence rule for the directory containing Name. Raises Name_Error if Name is not a full name. Returns Case_Sensitive if file names that differ only in the case of letters are considered different names. If file names that differ only in the case of letters are considered the same name, then Case_Preserving is returned if names have the case of the file name used when a file is created; and Case_Insensitive is returned otherwise. Returns Unknown if the file name equivalence is not known.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Unix, Linux, and their relatives are Case_Sensitive systems. Microsoft@latin1(174) Windows@latin1(174) is a Case_Preserving system (unless the rarely used POSIX mode is used). Ancient systems like CP/M and early MS-DOS were Case_Insensitive systems (file names were always in UPPER CASE). Unknown is provided in case it is impossible to tell (such as could be the case for network files).]} @end{ImplNote} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following file and directory queries and types are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} File_Kind @key{is} (Directory, Ordinary_File, Special_File);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type File_Kind represents the kind of file represented by an external file or directory.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} File_Size @key{is range} 0 .. @RI<implementation-defined>;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type File_Size represents the size of an external file.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The maximum value for a file size in Directories.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Exists (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if an external file represented by Name exists, and False otherwise. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Kind (Name : @key{in} String) @key{return} File_Kind;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the kind of external file represented by Name. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Size (Name : @key{in} String) @key{return} File_Size;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the size of the external file represented by Name. The size of an external file is the number of stream elements contained in the file. If the external file is not an ordinary file, the result is implementation-defined. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file. The exception Constraint_Error is propagated if the file size is not a value of type File_Size.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The result for Directories.Size for a directory or special file],Old=[]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[We allow raising Constraint_Error, so that an implementation for a system with 64-bit file sizes does not need to support full numerics on 64-bit integers just to implement this package. Of course, if 64-bit integers are available on such a system, they should be used when defining type File_Size.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Modification_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the time that the external file represented by Name was most recently modified. If the external file is not an ordinary file, the result is implementation-defined. The exception Name_Error is propagated if the string given as Name does not allow the identification of an existing external file. The exception Use_Error is propagated if the external environment does not support reading the modification time of the file with the name given by Name (in the absence of Name_Error).]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The result for Directories.Modification_Time for a directory or special file.], Old=[]}]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following directory searching operations and types are provided:]} @begin{DescribeCode} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Directory_Entry_Type @key{is limited private};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Directory_Entry_Type represents a single item in a directory. These items can only be created by the Get_Next_Entry procedure in this package. Information about the item can be obtained from the functions declared in this package. A default-initialized object of this type is invalid; objects returned from Get_Next_Entry are valid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Filter_Type @key{is array} (File_Kind) @key{of} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Filter_Type specifies which directory entries are provided from a search operation. If the Directory component is True, directory entries representing directories are provided. If the Ordinary_File component is True, directory entries representing ordinary files are provided. If the Special_File component is True, directory entries representing special files are provided.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{type} Search_Type @key{is limited private};]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[The type Search_Type contains the state of a directory search. A default-initialized Search_Type object has no entries available (function More_Entries returns False). Type Search_Type needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Start_Search (Search : @key{in out} Search_Type; Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Starts a search in the directory named by Directory for entries matching Pattern@Chg{Version=[3],New=[ and Filter],Old=[]}. Pattern represents a pattern for matching file names. If Pattern is @Chg{Version=[3],New=[the ],Old=[]}null@Chg{Version=[3],New=[ string],Old=[]}, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. After a successful call on Start_Search, the object Search may have entries available, but it may have no entries available if no files or directories match Pattern and Filter. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error). When Start_Search propagates Name_Error or Use_Error, the object Search will have no entries available.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The interpretation of a nonnull search pattern in Directories.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} End_Search (Search : @key{in out} Search_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Ends the search represented by Search. After a successful call on End_Search, the object Search will have no entries available.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The only way that a call to End_Search could be unsuccessful if Device_Error (see @RefSecNum{Exceptions in Input-Output}) is raised because of an underlying failure (or bug).]} @end{Ramification} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} More_Entries (Search : @key{in} Search_Type) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns True if more entries are available to be returned by a call to Get_Next_Entry for the specified search object, and False otherwise.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Get_Next_Entry (Search : @key{in out} Search_Type; Directory_Entry : @key{out} Directory_Entry_Type);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the next Directory_Entry for the search described by Search that matches the pattern and filter. If no further matches are available, Status_Error is raised. It is implementation-defined as to whether the results returned by this @Chg{Version=[3],New=[subprogram],Old=[routine]} are altered if the contents of the directory are altered while the Search object is valid (for example, by another program). The exception Use_Error is propagated if the external environment does not support continued searching of the directory represented by Search.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The results of a Directories search if the contents of the directory are altered while a search is in progress.],Old=[]}]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{procedure} Search ( Directory : @key{in} String; Pattern : @key{in} String; Filter : @key{in} Filter_Type := (@key{others} => True); Process : @key{not null access procedure} ( Directory_Entry : @key{in} Directory_Entry_Type));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Searches in the directory named by Directory for entries matching Pattern@Chg{Version=[3],New=[ and Filter],Old=[]}. The subprogram designated by Process is called with each matching entry in turn. Pattern represents a pattern for matching file names. If Pattern is @Chg{Version=[3],New=[the ],Old=[]}null@Chg{Version=[3],New=[ string],Old=[]}, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error).]} @Comment{The implementation-defined case is handled above.} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@lquotes@;In turn@rquotes means that the calls to the subprogram designated by Process are not made in parallel; they can be made in any order but must be in sequence.]} @end{Discussion} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Simple_Name (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the simple external name of the external file (including directories) represented by Directory_Entry. The format of the name returned is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Full_Name (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the full external name of the external file (including directories) represented by Directory_Entry. The format of the name returned is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Kind (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Kind;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the kind of external file represented by Directory_Entry. The exception Status_Error is propagated if Directory_Entry is invalid.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Size (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} File_Size;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the size of the external file represented by Directory_Entry. The size of an external file is the number of stream elements contained in the file. If the external file represented by Directory_Entry is not an ordinary file, the result is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid. The exception Constraint_Error is propagated if the file size is not a value of type File_Size.]} @begin{Example}@ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Modification_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the time that the external file represented by Directory_Entry was most recently modified. If the external file represented by Directory_Entry is not an ordinary file, the result is implementation-defined. The exception Status_Error is propagated if Directory_Entry is invalid. The exception Use_Error is propagated if the external environment does not support reading the modification time of the file represented by Directory_Entry.]} @end{DescribeCode} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[For Copy_File, if Source_Name identifies an existing external ordinary file created by a predefined Ada input-output package, and Target_Name and Form can be used in the Create operation of that input-output package with mode Out_File without raising an exception, then Copy_File shall not propagate Use_Error.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This means that Copy_File will copy any file that the Ada programmer could copy (by writing some possibly complicated Ada code).]} @end{Discussion} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If other information about a file (such as the owner or creation date) is available in a directory entry, the implementation should provide functions in a child package Directories.Information to retrieve it.@ChildUnit{Parent=[Ada.Directories],Child=[Information]}]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Package Directories.Information should be provided to retrieve other information about a file.]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Windows@latin1(174), Directories.Information should contain at least the following routines:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Directories.Information @key{is} -- @RI[System-specific directory information.] -- @RI[Version for the Microsoft@latin1(174) Windows@latin1(174) operating system.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Creation_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Read_Only (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Needs_Archiving (Name : @key{in} String) @key{return} Boolean; -- @RI[This generally means that the file needs to be backed up.] -- @RI[The flag is only cleared by backup programs.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Compressed (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Encrypted (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Hidden (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_System (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Offline (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Temporary (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Sparse (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Not_Indexed (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Creation_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Read_Only (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Needs_Archiving (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean; -- @RI[This generally means that the file needs to be backed up.] -- @RI[The flag is only cleared by backup programs.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Compressed (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Encrypted (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Hidden (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_System (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Offline (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Temporary (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Sparse (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Not_Indexed (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Additional implementation-defined subprograms allowed here.] @key{end} Ada.Directories.Information;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Unix-like systems (Unix, POSIX, Linux, etc.), Directories.Information should contain at least the following routines:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Directories.Information @key{is} -- @RI[System-specific directory information.] -- @RI[Unix and similar systems version.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Status_Change_Time (Name : @key{in} String) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Permission @key{is} (Others_Execute, Others_Write, Others_Read, Group_Execute, Group_Write, Group_Read, Owner_Execute, Owner_Write, Owner_Read, Set_Group_ID, Set_User_ID);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} Permission_Set_Type @key{is array} (Permission) @key{of} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Permission_Set (Name : @key{in} String) @key{return} Permission_Set_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Owner (Name : @key{in} String) @key{return} String; -- @RI[Returns the image of the User_Id. If a definition of User_Id] -- @RI[is available, an implementation-defined version of Owner] -- @RI[returning User_Id should also be defined.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[ @key{function} Group (Name : @key{in} String) @key{return} String; -- @RI[Returns the image of the @Chg{Version=[3],New=[Group_Id],Old=[User_Id]}. If a definition of Group_Id] -- @RI[is available, an implementation-defined version of Group] -- @RI[returning Group_Id should also be defined.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Block_Special_File (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character_Special_File (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_FIFO (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Symbolic_Link (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Socket (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Access_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Last_Status_Change_Time (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Ada.Calendar.Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Permission_Set (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Permission_Set_Type;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Owner (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String; -- @RI[See Owner above.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Group (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} String; -- @RI[See Group above.]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Block_Special_File (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Character_Special_File (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_FIFO (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Symbolic_Link (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} Is_Socket (Directory_Entry : @key{in} Directory_Entry_Type) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @RI[Additional implementation-defined subprograms allowed here.] @key{end} Ada.Directories.Information;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We give these definitions to give guidance so that every implementation for a given target is not unnecessarily different. Implementers are encouraged to make packages for other targets as similar to these as possible.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0231-1]} @ChgAdded{Version=[2],Text=[Start_Search and Search should raise @Chg{Version=[3],New=[Name_Error],Old=[Use_Error]} if Pattern is malformed, but not if it could represent a file in the directory but does not actually do so.]} @ChgImplAdvice{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[Directories.Start_Search and Directories.Search should raise @Chg{Version=[3],New=[Name_Error],Old=[Use_Error]} for malformed patterns.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Rename should be supported at least when both New_Name and Old_Name are simple names and New_Name does not identify an existing external file.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Directories.Rename should be supported at least when both New_Name and Old_Name are simple names and New_Name does not identify an existing external file.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@Lquotes@;Supported@rquotes@; includes raising an exception if either name is malformed, the file to rename doesn't exist, insufficient permission for the operation exists, or similar problems. But this advice requires implementations to document what they do, and tells implementers that simply raising Use_Error isn't acceptable.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The operations Containing_Directory, Full_Name, Simple_Name, Base_Name, Extension, and Compose operate on file names, not external files. The files identified by these operations do not need to exist. Name_Error is raised only if the file name is malformed and cannot possibly identify a file. Of these operations, only the result of Full_Name depends on the current default directory; the result of the others depends only on their parameters.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Using access types, values of Search_Type and Directory_Entry_Type can be saved and queried later. However, another task or application can modify or delete the file represented by a Directory_Entry_Type value or the directory represented by a Search_Type value; such a value can only give the information valid at the time it is created. Therefore, long-term storage of these values is not recommended.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target system does not support directories inside of directories, then Kind will never return Directory and Containing_Directory will always raise Use_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the target system does not support creation or deletion of directories, then Create_Directory, Create_Path, Delete_Directory, and Delete_Tree will always propagate Use_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To move a file or directory to a different location, use Rename. Most target systems will allow renaming of files from one directory to another. If the target file or directory might already exist, it should be deleted first.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[While Rename is only guaranteed to work for name changes within a single directory, its unlikely that implementers would purposely prevent functionality present in the underlying system from working. To move a file totally portably, it's necessary to handle failure of the Rename and fall back to Copy_File and Delete:]} @begin{Example} @ChgAdded{Version=[2],Text=[@key[begin] Rename (Source, Target); @key[exception] @key[when] Use_Error => Copy_File (Source, Target); Delete (Source); @key[end];]} @end{Example} @end{Discussion} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Ada.Directories is new.]} @end{Extend95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0231-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction>: Clarified when and which exceptions are raised for Start_Search, Search, Delete_Directory, and Rename. If an implementation followed the original incorrect wording, it might raise Use_Error instead of Name_Error for Start_Search and Search, Name_Error instead of Use_Error for Rename, and might have deleted a nonempty directory instead of raising Use_Error for Delete_Directory. The first two cases are very unlikely to matter in practice, and it unlikely that an implementation would have followed the latter implementation strategy, as it would be more work and would make Delete_Directory identical to Delete_Tree (which is obvious nonsense).]} @end{Inconsistent2005} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} A new enumeration type Name_Case_Kind and a new function Name_Case_Equivalence is added to Directories. If Directories is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of one of the new entities is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0271-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> We now explicitly say that the behavior of Create_Path and Copy_File is unspecified when Use_Error is raised. Nothing has changed here, as the behavior was (implicitly) unspecified in the 2007 Amendment.]} @end{Diffword2005} @LabeledAddedSubClause{Version=[3],Name=[The Package Directories.Hierarchical_File_Names]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[The library package Directories.Hierarchical_File_Names is an optional package providing operations for file name construction and decomposition for targets with hierarchical file naming.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[If provided, the library package Directories.Hierarchical_File_Names has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{package} Ada.Directories.Hierarchical_File_Names @key{is}@ChildUnit{Parent=[Ada.Directories],Child=[Hierarchical_File_Names]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Simple_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Root_Directory_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Parent_Directory_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Current_Directory_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Full_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Is_Relative_Name} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Simple_Name} (Name : @key{in} String) @key{return} String @key{renames} Ada.Directories.Simple_Name;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Containing_Directory} (Name : @key{in} String) @key{return} String @key{renames} Ada.Directories.Containing_Directory;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Initial_Directory} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Relative_Name} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Compose} (Directory : @key{in} String := ""; Relative_Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{end} Ada.Directories.Hierarchical_File_Names;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[In addition to the operations provided in package Directories.Hierarchical_File_Names, the operations in package Directories can be used with hierarchical file names. In particular, functions Full_Name, Base_Name, and Extension provide additional capabilities for hierarchical file names.]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Simple_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns True if Name is a simple name, and returns False otherwise.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Root_Directory_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns True if Name is syntactically a root (a directory that cannot be decomposed further), and returns False otherwise.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For Unix and Unix-like systems, "/" is the root. For Windows, "C:\" and "\\Computer\Share" are roots.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Parent_Directory_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns True if Name can be used to indicate symbolically the parent directory of any directory, and returns False otherwise.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Is_Parent_Directory_Name returns True if and only if Name is ".." for both Unix and Windows.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Current_Directory_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns True if Name can be used to indicate symbolically the directory itself for any directory, and returns False otherwise.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Is_Current_Directory_Name returns True if and only if Name is "." for both Unix and Windows.]} @end{ImplNote} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Full_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns True if the leftmost directory part of Name is a root, and returns False otherwise.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Is_Relative_Name (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Returns True if Name allows the identification of an external file (including directories and special files) but is not a full name, and returns False otherwise.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Relative names include simple names as a special case. This function returns False if the syntax of the name is incorrect.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Initial_Directory (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Returns the leftmost directory part in Name. @Redundant[That is, it returns a root directory name (for a full name), or one of a parent directory name, a current directory name, or a simple name (for a relative name).] The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files).]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Relative_Name (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns the entire file name except the Initial_Directory portion. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file (including directories and special files), or if Name has a single part (this includes if any of Is_Simple_Name, Is_Root_Directory_Name, Is_Parent_Directory_Name, or Is_Current_Directory_Name are True).]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The result might be a simple name.]} @end{Ramification} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{function} Compose (Directory : @key{in} String := ""; Relative_Name : @key{in} String; Extension : @key{in} String := "") @key{return} String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Returns the name of the external file with the specified Directory, Relative_Name, and Extension. The exception Name_Error is propagated if the string given as Directory is not the null string and does not allow the identification of a directory, or if Is_Relative_Name (Relative_Name) is False, or if the string given as Extension is not the null string and is not a possible extension, or if Extension is not the null string and Simple_Name (Relative_Name) is not a base name.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The result of Compose is a full name if Is_Full_Name (Directory) is True; result is a relative name otherwise.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Name_Error is raised by Compose if Directory is not the null string, and both Is_Full_Name and Is_Relative_Name return False.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[A common security problem is to include a parent directory name in the middle of a file name; this is often used to navigate outside of an intended root directory. We considered attempting to prevent that case by having Compose detect it and raise an exception. But the extra rules necessary were more confusing than helpful.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We can say more about the details of these operations by adopting the notation of a subscript to specify how many path fragments a particular result has. Then, we can abbreviate "Full Name" as "Full" and "Relative Name" as "Rel". In this notation, Unix file name "a/b" is a Rel(2), "../c/d" is a Rel(3), and "/a/b" is a Full(2). Rel(1) is equivalent to a simple name; thus we don't have to describe that separately.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[In this notation,]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For N>1, Containing_Directory(Rel(N)) = Leftmost Rel(N-1), Containing_Directory(Full(N)) = Leftmost Full(N-1), Else if N = 1, raise Name_Error.]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Similarly,]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For N>1, Relative_Name(Rel(N)) = Rightmost Rel(N-1), Relative_Name(Full(N)) = Rightmost Full(N-1), Else if N = 1, raise Name_Error.]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Leading],Text=[Finally, for Compose (ignoring the extension here):]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Compose (Directory => Full(N), Relative_Name => Rel(M)) => Full(N+M) Compose (Directory => Rel(N), Relative_Name => Rel(M)) => Rel(N+M) Name_Error if Relative_Name is a Full(M).]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[We didn't try to write wording to reflect these details of these functions.]} @end{Discussion} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[Directories.Hierarchical_File_Names should be provided for systems with hierarchical file naming, and should not be provided on other systems.]} @ChgImplAdvice{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[Directories.Hierarchical_File_Names should be provided for systems with hierarchical file naming, and should not be provided on other systems.]}]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This package should be provided when targeting Microsoft@latin1(174) Windows@latin1(174), Unix, Linux, and most Unix-like systems.]} @end{ImplNote} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[These operations operate on file names, not external files. The files identified by these operations do not need to exist. Name_Error is raised only as specified or if the file name is malformed and cannot possibly identify a file. The result of these operations depends only on their parameters.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[Containing_Directory raises Use_Error if Name does not have a containing directory, including when any of Is_Simple_Name, Is_Root_Directory_Name, Is_Parent_Directory_Name, or Is_Current_Directory_Name are True.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[In particular, the default directory is not used to find the containing directory either when Is_Parent_Directory_Name or Is_Current_Directory_Name is True. As noted above, these functions operate purely on the syntax of the file names and do not attempt to interpret them. If interpretation is needed, Directories.Full_Name can be to expand any shorthands used before calling Containing_Directory.]} @end{Ramification} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0049-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Package Ada.Directories.Hierarchical_File_Names is new.]} @end{Extend2005} ������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_environ.mss������������������������������������������������������0000755�0001752�0001001�00000027306�11776511201�020500� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_environ.mss,v $ } @comment{ $Revision: 1.13 $ $Date: 2012/03/20 06:13:59 $ $Author: randy $ } @Part(predefenviron, Root="ada.mss") @Comment{$Date: 2012/03/20 06:13:59 $} @LabeledAddedClause{Version=[2],Name=[The Package Environment_Variables]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@Defn{environment variable} The package Environment_Variables allows a program to read or modify environment variables. Environment variables are name-value pairs, where both the name and value are strings. The definition of what constitutes an @i{environment variable}, and the meaning of the name and value, are implementation defined.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[The definition and meaning of an environment variable.],Old=[]}]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Environment_Variables has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Environment_Variables @key{is}@ChildUnit{Parent=[Ada],Child=[Environment_Variables]} @key{pragma} Preelaborate(Environment_Variables);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Value} (Name : @key{in} String) @key{return} String;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0285-1]} @ChgAdded{Version=[3],Text=[ @key{function} @AdaSubDefn{Value} (Name : @key{in} String; Default : @key{in} String) @key{return} String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Exists} (Name : @key{in} String) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set} (Name : @key{in} String; Value : @key{in} String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Clear} (Name : @key{in} String); @key{procedure} @AdaSubDefn{Clear};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Iterate}@Chg{Version=[3],New=[],Old=[ (]} @Chg{Version=[3],New=[(],Old=[ ]}Process : @key{not null access procedure} (Name, Value : @key{in} String));]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@key{end} Ada.Environment_Variables;]} @end{Example} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Value (Name : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Value returns the value of the environment variable with the given name. If no environment variable with the given name exists, then Constraint_Error is propagated. If the execution environment does not support environment variables, then Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],KeepNext=[T],Text=[@key{function} Value (Name : @key{in} String; Default : @key{in} String) @key{return} String;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0285-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If the external execution environment supports environment variables and an environment variable with the given name currently exists, then Value returns its value; otherwise, it returns Default.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Exists (Name : @key{in} String) @key{return} Boolean;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables and an environment variable with the given name currently exists, then Exists returns True; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Set (Name : @key{in} String; Value : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the external execution environment supports environment variables, then Set first clears any existing environment variable with the given name, and then defines a single new environment variable with the given name and value. Otherwise@Chg{Version=[3],New=[,],Old=[]} Program_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If implementation-defined circumstances prohibit the definition of an environment variable with the given name and value, then Constraint_Error is propagated.]} @ChgImplDef{Version=[2],Kind=[AddedNormal], Text=[@Chg{Version=[2],New=[The circumstances where an environment variable cannot be defined.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[It is implementation defined whether there exist values for which the call Set(Name, Value) has the same effect as Clear (Name).]} @ChgImplDef{Version=[2],Kind=[AddedNormal], Text=[@Chg{Version=[2],New=[Environment names for which Set has the effect of Clear.],Old=[]}]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear (Name : @key{in} String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Clear deletes all existing environment @Chg{Version=[3],New=[variables],Old=[variable]} with the given name. Otherwise@Chg{Version=[3],New=[,],Old=[]} Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Clear;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[If the external execution environment supports environment variables, then Clear deletes all existing environment variables. Otherwise@Chg{Version=[3],New=[,],Old=[]} Program_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} @ChgAdded{Version=[2],Text=[@key{procedure} Iterate@Chg{Version=[3],New=[],Old=[ (]} @Chg{Version=[3],New=[(],Old=[ ]}Process : @key{not null access procedure} (Name, Value : @key{in} String));]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the external execution environment supports environment variables, then Iterate calls the subprogram designated by Process for each existing environment variable, passing the name and value of that environment variable. Otherwise@Chg{Version=[3],New=[,],Old=[]} Program_Error is propagated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If several environment variables exist that have the same name, Process is called once for each such variable.]} @end{DescribeCode} @end{StaticSem} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call Value if more than one environment variable exists with the given name; the possible outcomes are that:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[one of the values is returned, and that same value is returned in subsequent calls in the absence of changes to the environment; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Program_Error is propagated.]} @end{Itemize} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} Making calls to the procedures Set or Clear concurrently with calls to any subprogram of package Environment_Variables, or to any instantiation of Iterate, results in erroneous execution.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Making calls to the procedures Set or Clear in the actual subprogram corresponding to the Process parameter of Iterate results in erroneous execution.]} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[An implementation shall document how the operations of this package behave if environment variables are changed by external mechanisms (for instance, calling operating system services).]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The behavior of package Environment_Variables when environment variables are changed by external mechanisms.]}]} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[An implementation running on a system that does not support environment variables is permitted to define the operations of package Environment_Variables with the semantics corresponding to the case where the external execution environment does support environment variables. In this case, it shall provide a mechanism to initialize a nonempty set of environment variables prior to the execution of a partition.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[If the execution environment supports subprocesses, the currently defined environment variables should be used to initialize the environment variables of a subprocess.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the execution environment supports subprocesses, the current environment variables should be used to initialize the environment variables of a subprocess.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Changes to the environment variables made outside the control of this package should be reflected immediately in the effect of the operations of this package. Changes to the environment variables made using this package should be reflected immediately in the external execution environment. This package should not perform any buffering of the environment variables.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Changes to the environment variables made outside the control of Environment_Variables should be reflected immediately.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00370-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Environment_Variables is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0285-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} A new overloaded function Value is added to Environment_Variables. If Environment_Variables is referenced in a @nt{use_clause}, and an entity @i<E> with the name Value is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_io.mss�����������������������������������������������������������0000755�0001752�0001001�00000534755�12066652506�017451� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(predefio, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @Comment{$Source: e:\\cvsroot/ARM/Source/pre_io.mss,v $} @Comment{$Revision: 1.67 $} @LabeledClause{Input-Output} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Redundant[@Defn{input}@Defn{output} Input-output is provided through language-defined packages, each of which is a child of the root package Ada. The generic packages Sequential_IO and Direct_IO define input-output operations applicable to files containing elements of a given type. The generic package Storage_IO supports reading from and writing to an in-memory buffer. Additional operations for text input-output are supplied in the packages Text_IO@Chg{Version=[2],New=[,],Old=[ and]} Wide_Text_IO@Chg{Version=[2],New=[, and Wide_Wide_Text_IO],Old=[]}. Heterogeneous input-output is provided through the child packages Streams.@!Stream_IO and Text_IO.@!Text_@!Streams (see also @RefSecNum{Streams}). The package IO_Exceptions defines the exceptions needed by the predefined input-output packages.] @end{Intro} @begin{Inconsistent83} @Defn{inconsistencies with Ada 83} The introduction of Append_File as a new element of the enumeration type File_Mode in Sequential_IO and Text_IO, and the introduction of several new declarations in Text_IO, may result in name clashes in the presence of @key[use] clauses. @end{Inconsistent83} @begin{Extend83} @Defn{extensions to Ada 83} Text_IO enhancements (Get_Immediate, Look_Ahead, Standard_Error, Modular_IO, Decimal_IO), Wide_Text_IO, and the stream input-output facilities are new in Ada 95. @end{Extend83} @begin{DiffWord83} RM83-14.6, "Low Level Input-Output," is removed. This has no semantic effect, since the package was entirely implementation defined, nobody actually implemented it, and if they did, they can always provide it as a vendor-supplied package. @end{DiffWord83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO in this description.]} @end{Diffword95} @LabeledClause{External Files and File Objects} @begin{StaticSem} @Defn{external file} @Defn2{Term=[name], Sec=(of an external file)} @Defn2{Term=[form], Sec=(of an external file)} Values input from the external environment of the program, or output to the external environment, are considered to occupy @i{external files}. An external file can be anything external to the program that can produce a value to be read or receive a value to be written. An external file is identified by a string (the @i{name}). A second string (the @i{form}) gives further system-dependent characteristics that may be associated with the file, such as the physical organization or access rights. The conventions governing the interpretation of such strings shall be documented. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn2{Term=[file], Sec=(as file object)} Input and output operations are expressed as operations on objects of some @i{file type}, rather than directly in terms of the external files. In the remainder of this @Chg{Version=[3],New=[clause],Old=[section]}, the term @i{file} is always used to refer to a file object; the term @i{external file} is used otherwise. Input-output for sequential files of values of a single element type is defined by means of the generic package Sequential_IO. In order to define sequential input-output for a given element type, an instantiation of this generic unit, with the given type as actual parameter, has to be declared. The resulting package contains the declaration of a file type (called File_Type) for files of such elements, as well as the operations applicable to these files, such as the Open, Read, and Write procedures. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Input-output for direct access files is likewise defined by a generic package called Direct_IO. Input-output in human-readable form is defined by the (nongeneric) packages Text_IO for Character and String data, @Chg{Version=[2],New=[],Old=[and ]}Wide_Text_IO for Wide_Character and Wide_String data@Chg{Version=[2],New=[, and Wide_Wide_Text_IO for Wide_Wide_Character and Wide_Wide_String data],Old=[]}. Input-output for files containing streams of elements representing values of possibly different types is defined by means of the (nongeneric) package Streams.Stream_IO. Before input or output operations can be performed on a file, the file first has to be associated with an external file. While such an association is in effect, the file is said to be @i{open}, and otherwise the file is said to be @i{closed}. The language does not define what happens to external files after the completion of the main program and all the library tasks (in particular, if corresponding files have not been closed). @Defn2{Term=[access types], Sec=(input-output unspecified)} @Defn2{Term=[input-output], Sec=(unspecified for access types)} @PDefn{unspecified} The effect of input-output for access types is unspecified. @Leading@Keepnext@Defn2{Term=[current mode], Sec=(of an open file)} An open file has a @i{current mode}, which is a value of one of the following enumeration types: @begin{DescribeCode} @begin{Example} @key[type] File_Mode @key[is] (In_File, Inout_File, Out_File); --@RI{ for Direct_IO} @end{Example} These values correspond respectively to the cases where only reading, both reading and writing, or only writing are to be performed. @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @key[type] File_Mode @key[is] (In_File, Out_File, Append_File); --@RI{ for Sequential_IO, Text_IO, Wide_Text_IO, @Chg{Version=[2],New=[Wide_Wide_Text_IO, ], Old=[]}and Stream_IO} @end{Example} These values correspond respectively to the cases where only reading, only writing, or only appending are to be performed. @Trailing@;The mode of a file can be changed. @end{DescribeCode} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Several file management operations are common to Sequential_IO, Direct_IO, Text_IO, @Chg{Version=[2],New=[],Old=[and ]}Wide_Text_IO@Chg{Version=[2], New=[, and Wide_Wide_Text_IO],Old=[]}. These operations are described in subclause @RefSecNum{File Management} for sequential and direct files. Any additional effects concerning text input-output are described in subclause @RefSecNum{Text File Management}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The exceptions that can be propagated by the execution of an input-output subprogram are defined in the package IO_Exceptions; the situations in which they can be propagated are described following the description of the subprogram (and in @Chg{Version=[3],New=[subclause],Old=[clause]} @RefSecNum{Exceptions in Input-Output}). @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} The exceptions Storage_Error and Program_Error may be propagated. (Program_Error can only be propagated due to errors made by the caller of the subprogram.) Finally, exceptions can be propagated in certain implementation-defined situations. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Any implementation-defined characteristics of the input-output packages.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The last sentence here is referring to the documentation requirements in @RefSec{Exceptions in Input-Output}, and the documentation summary item is provided there.]} @end{Discussion} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} Each instantiation of the generic packages Sequential_IO and Direct_IO declares a different type File_Type. In the case of Text_IO, Wide_Text_IO, @Chg{Version=[2],New=[Wide_Wide_Text_IO, ],Old=[]}and Streams.Stream_IO, the corresponding type File_Type is unique. A bidirectional device can often be modeled as two sequential files associated with the device, one of mode In_File, and one of mode Out_File. An implementation may restrict the number of files that may be associated with a given external file. @end{Notes} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO in this description.]} @end{Diffword95} @RMNewPageVer{Version=[1]}@Comment{Break here so printed Ada 95 w/ corrigendum RM looks better.} @LabeledClause{Sequential and Direct Files} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} @Defn{sequential file} @Defn{direct file}@Chg{Version=[2],New=[@Defn{stream file}],Old=[]} Two kinds of access to external files are defined in this subclause: @i{sequential access} and @i{direct access}. The corresponding file types and the associated operations are provided by the generic packages Sequential_IO and Direct_IO. A file object to be used for sequential access is called a @i{sequential file}, and one to be used for direct access is called a @i{direct file}. Access to @Chg{Version=[2],New=[@i{stream file}s],Old=[stream files]} is described in @RefSecNum(The Package Streams.Stream_IO). @Defn{sequential access} For sequential access, the file is viewed as a sequence of values that are transferred in the order of their appearance (as produced by the program or by the external environment). When the file is opened with mode In_File or Out_File, transfer starts respectively from or to the beginning of the file. When the file is opened with mode Append_File, transfer to the file starts after the last element of the file. @begin{Discussion} Adding stream I/O necessitates a review of the terminology. In Ada 83, `sequential' implies both the access method (purely sequential @em that is, no indexing or positional access) and homogeneity. Direct access includes purely sequential access and indexed access, as well as homogeneity. In Ada 95, streams allow purely sequential access but also positional access to an individual element, and are heterogeneous. We considered generalizing the notion of `sequential file' to include both Sequential_IO and Stream_IO files, but since streams allow positional access it seems misleading to call them sequential files. Or, looked at differently, if the criterion for calling something a sequential file is whether it permits (versus requires) purely sequential access, then one could just as soon regard a Direct_IO file as a sequential file. It seems better to regard `sequential file' as meaning `only permitting purely sequential access'; hence we have decided to supplement `sequential access' and `direct access' with a third category, informally called `access to streams'. (We decided against the term `stream access' because of possible confusion with the Stream_Access type declared in one of the stream packages.)@end{discussion} @Defn{direct access} @Defn2{Term=[index], Sec=(of an element of an open direct file)} @Defn2{Term=[current size], Sec=(of an external file)} For direct access, the file is viewed as a set of elements occupying consecutive positions in linear order; a value can be transferred to or from an element of the file at any selected position. The position of an element is specified by its @i{index}, which is a number, greater than zero, of the implementation-defined integer type Count. The first element, if any, has index one; the index of the last element, if any, is called the @i{current size}; the current size is zero if there are no elements. The current size is a property of the external file. @Defn2{Term=[current index], Sec=(of an open direct file)} An open direct file has a @i{current index}, which is the index that will be used by the next read or write operation. When a direct file is opened, the current index is set to one. The current index of a direct file is a property of a file object, not of an external file. @end{StaticSem} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Text=[Italicized @lquotes@;stream file@rquotes@; to clarify that this is another kind of file.]} @end{DiffWord95} @LabeledSubClause{The Generic Package Sequential_IO} @begin{StaticSem} @Leading@;The generic library package Sequential_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[generic] @key[type] Element_Type(<>) @key[is] @key[private]; @key[package] Ada.Sequential_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Sequential_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Out_File, Append_File); @RI{-- File management} @key[procedure] @AdaSubDefn{Create}(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Out_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete}(File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write} (File : @key[in] File_Type; Item : @key[in] Element_Type); @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @keepnext --@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Sequential_IO; @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}) in every instantiation of Sequential_IO.]} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The new enumeration element Append_File may introduce upward incompatibilities. It is possible that a program based on the assumption that File_Mode'Last = Out_File will be illegal (e.g., case statement choice coverage) or execute with a different effect in Ada 95. @end{Incompatible83} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[File_Type cannot be implemented as a (directly) controlled type, as Ada.Sequential_IO can be instantiated at any nesting depth. File_Type could have a component of a controlled type, as long as that type is declared in some other (nongeneric) package.],Old=[]}]}@ChgNote{AI-344 allows controlled types to be declared at any nesting depth, so this note is obsolete.} @end{ImplNote} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] File_Type in an instance of Sequential_IO is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @LabeledSubClause{File Management} @begin{StaticSem} The procedures and functions described in this subclause provide for the control of external files; their declarations are repeated in each of the packages for sequential, direct, text, and stream input-output. For text input-output, the procedures Create, Open, and Reset have additional effects described in subclause @RefSecNum{Text File Management}. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Create(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := @RI{default_mode}; Name : @key[in] String := ""; Form : @key[in] String := ""); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} Establishes a new external file, with the given name and form, and associates this external file with the given file. The given file is left open. The current mode of the given file is set to the given access mode. The default access mode is the mode Out_File for sequential@Chg{Version=[2],New=[, stream,],Old=[]} and text input-output; it is the mode Inout_File for direct input-output. For direct access, the size of the created file is implementation defined. A null string for Name specifies an external file that is not accessible after the completion of the main program (a temporary file). A null string for Form specifies the use of the default options of the implementation for the external file. @Trailing@;The exception Status_Error is propagated if the given file is already open. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file. The exception Use_Error is propagated if, for the specified mode, the external environment does not support creation of an external file with the given name (in the absence of Name_Error) and form. @begin{Example}@Keepnext @key[procedure] Open(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @end{Example} Associates the given file with an existing external file having the given name and form, and sets the current mode of the given file to the given mode. The given file is left open. @Trailing@;The exception Status_Error is propagated if the given file is already open. The exception Name_Error is propagated if the string given as Name does not allow the identification of an external file; in particular, this exception is propagated if no external file with the given name exists. The exception Use_Error is propagated if, for the specified mode, the external environment does not support opening for an external file with the given name (in the absence of Name_Error) and form. @begin{Example}@Keepnext @key[procedure] Close(File : @key[in] @key[out] File_Type); @end{Example} Severs the association between the given file and its associated external file. The given file is left closed. In addition, for sequential files, if the file being closed has mode Out_File or Append_File, then the last element written since the most recent open or reset is the last element that can be read from the file. If no elements have been written and the file mode is Out_File, then the closed file is empty. If no elements have been written and the file mode is Append_File, then the closed file is unchanged. @Trailing@;The exception Status_Error is propagated if the given file is not open. @begin{Example}@Keepnext @key[procedure] Delete(File : @key[in] @key[out] File_Type); @end{Example} Deletes the external file associated with the given file. The given file is closed, and the external file ceases to exist. @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Use_Error is propagated if deletion of the external file is not supported by the external environment. @begin{Example}@Keepnext @key[procedure] Reset(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] Reset(File : @key[in] @key[out] File_Type); @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00085-01]} Resets the given file so that reading from its elements can be restarted from the beginning of the @Chg{Version=[2],New=[external ],Old=[]}file (for modes In_File and Inout_File), and so that writing to its elements can be restarted at the beginning of the @Chg{Version=[2],New=[external ],Old=[]}file (for modes Out_File and Inout_File) or after the last element of the @Chg{Version=[2],New=[external ],Old=[]}file (for mode Append_File). In particular, for direct access this means that the current index is set to one. If a Mode parameter is supplied, the current mode of the given file is set to the given mode. In addition, for sequential files, if the given file has mode Out_File or Append_File when Reset is called, the last element written since the most recent open or reset is the last element that can be read from the @Chg{Version=[2],New=[external ],Old=[]}file. If no elements have been written and the file mode is Out_File, the reset file is empty. If no elements have been written and the file mode is Append_File, then the reset file is unchanged. @Trailing@;The exception Status_Error is propagated if the file is not open. The exception Use_Error is propagated if the external environment does not support resetting for the external file and, also, if the external environment does not support resetting to the specified mode for the external file. @begin{Example}@Keepnext @key[function] Mode(File : @key[in] File_Type) @key[return] File_Mode; @end{Example} Returns the current mode of the given file. @Trailing@;The exception Status_Error is propagated if the file is not open. @begin{Example}@Keepnext @key[function] Name(File : @key[in] File_Type) @key[return] String; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00248-01]} Returns a string which uniquely identifies the external file currently associated with the given file (and may thus be used in an Open operation).@Chg{Version=[2],New=[],Old=[ If an external environment allows alternative specifications of the name (for example, abbreviations), the string returned by the function should correspond to a full specification of the name.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[Retrieving the full path can be accomplished by passing the result of Name to Directories.Full_Name (see @RefSecNum{The Package Directories}). It is important to drop the requirement on Name, as the only way to accomplish this requirement given that the current directory can be changed with package Directories is to store the full path when the file is opened. That's expensive, and it's better for users that need the full path to explicitly request it.]} @end{Discussion} @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Use_Error is propagated if the associated external file is a temporary file that cannot be opened by any name. @begin{Example}@Keepnext @key[function] Form(File : @key[in] File_Type) @key[return] String; @end{Example} Returns the form string for the external file currently associated with the given file. If an external environment allows alternative specifications of the form (for example, abbreviations using default options), the string returned by the function should correspond to a full specification (that is, it should indicate explicitly all options selected, including default options). @Trailing@;The exception Status_Error is propagated if the given file is not open. @begin{Example}@Keepnext @key[function] Is_Open(File : @key[in] File_Type) @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Returns True if the file is open (that is, if it is associated with an external file)@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. @end{DescribeCode} @end{StaticSem} @begin{ImplPerm} An implementation may propagate Name_Error or Use_Error if an attempt is made to use an I/O feature that cannot be supported by the implementation due to limitations in the external environment. Any such restriction should be documented. @end{ImplPerm} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[Clarified that Reset affects and depends on the external file.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00248-01]} @ChgAdded{Version=[2],Text=[Removed the requirement for Name to return a full path; this is now accomplished by Directories.Full_Name(Name(File)) (see @RefSecNum{The Package Directories}). This is not documented as an inconsistency, because there is no requirement for implementations to change @em the Ada 95 behavior is still allowed, it just is no longer required.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Text=[Added text to specify the default mode for a stream file.]} @end{DiffWord95} @LabeledSubClause{Sequential Input-Output Operations} @begin{StaticSem} The operations available for sequential input and output are described in this subclause. The exception Status_Error is propagated if any of these operations is attempted for a file that is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type); @end{Example} Operates on a file of mode In_File. Reads an element from the given file, and returns the value of this element in the Item parameter. @begin{Discussion} We considered basing Sequential_IO.Read on Element_Type'Read from an implicit stream associated with the sequential file. However, Element_Type'Read is a type-related attribute, whereas Sequential_IO should take advantage of the particular constraints of the actual subtype corresponding to Element_Type to minimize the size of the external file. Furthermore, forcing the implementation of Sequential_IO to be based on Element_Type'Read would create an upward incompatibility since existing data files written by an Ada 83 program using Sequential_IO might not be readable by the identical program built with an Ada 95 implementation of Sequential_IO. An Ada 95 implementation might still use an implementation-defined attribute analogous to 'Read to implement the procedure Read, but that attribute will likely have to be subtype-specific rather than type-related, and it need not be user-specifiable. Such an attribute will presumably be needed to implement the generic package Storage_IO (see @RefSecNum{The Generic Package Storage_IO}). @end{Discussion} @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if no more elements can be read from the given file. The exception Data_Error can be propagated if the element read cannot be interpreted as a value of the subtype Element_Type (see @RefSec{Exceptions in Input-Output}). @begin{Discussion} Data_Error need not be propagated if the check is too complex. See @RefSec{Exceptions in Input-Output}. @end{Discussion} @begin{Example}@Keepnext @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type); @end{Example} Operates on a file of mode Out_File or Append_File. Writes the value of Item to the given file. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. The exception Use_Error is propagated if the capacity of the external file is exceeded. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Operates on a file of mode In_File. Returns True if no more elements can be read from the given file; otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. The exception Mode_Error is propagated if the mode is not In_File. @end{DescribeCode} @end{StaticSem} @LabeledSubClause{The Generic Package Direct_IO} @begin{StaticSem} @Leading@;The generic library package Direct_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[generic] @key[type] Element_Type @key[is] @key[private]; @key[package] Ada.Direct_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Direct_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Inout_File, Out_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; --@RI{ File management} @key[procedure] @AdaSubDefn{Create}(File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Inout_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete}(File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type; From : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Read} (File : @key[in] File_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write}(File : @key[in] File_Type; Item : @key[in] Element_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Write}(File : @key[in] File_Type; Item : @key[in] Element_Type); @key[procedure] @AdaSubDefn{Set_Index}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Index}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Size} (File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @keepnext --@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Direct_IO; @end{Example} @begin{Reason} The Element_Type formal of Direct_IO does not have an @nt{unknown_discriminant_part} (unlike Sequential_IO) so that the implementation can make use of the ability to declare uninitialized variables of the type. @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}) in every instantiation of Direct_IO.]} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[File_Type cannot be implemented as a (directly) controlled type, as Ada.Direct_IO can be instantiated at any nesting depth. File_Type could have a component of a controlled type, as long as that type is declared in some other (nongeneric) package.],Old=[]}]} @end{ImplNote} @end{StaticSem} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] File_Type in an instance of Direct_IO is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @LabeledSubClause{Direct Input-Output Operations} @begin{StaticSem} The operations available for direct input and output are described in this subclause. The exception Status_Error is propagated if any of these operations is attempted for a file that is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type; From : @key[in] Positive_Count); @key[procedure] Read(File : @key[in] File_Type; Item : @key[out] Element_Type); @end{Example} Operates on a file of mode In_File or Inout_File. In the case of the first form, sets the current index of the given file to the index value given by the parameter From. Then (for both forms) returns, in the parameter Item, the value of the element whose position in the given file is specified by the current index of the file; finally, increases the current index by one. @Trailing@;The exception Mode_Error is propagated if the mode of the given file is Out_File. The exception End_Error is propagated if the index to be used exceeds the size of the external file. The exception Data_Error can be propagated if the element read cannot be interpreted as a value of the subtype Element_Type (see @RefSecNum{Exceptions in Input-Output}). @begin{Example}@Keepnext @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type; To : @key[in] Positive_Count); @key[procedure] Write(File : @key[in] File_Type; Item : @key[in] Element_Type); @end{Example} Operates on a file of mode Inout_File or Out_File. In the case of the first form, sets the index of the given file to the index value given by the parameter To. Then (for both forms) gives the value of the parameter Item to the element whose position in the given file is specified by the current index of the file; finally, increases the current index by one. @Trailing@;The exception Mode_Error is propagated if the mode of the given file is In_File. The exception Use_Error is propagated if the capacity of the external file is exceeded. @begin{Example}@Keepnext @key[procedure] Set_Index(File : @key[in] File_Type; To : @key[in] Positive_Count); @end{Example} @Trailing@;Operates on a file of any mode. Sets the current index of the given file to the given index value (which may exceed the current size of the file). @begin{Example}@Keepnext @key[function] Index(File : @key[in] File_Type) @key[return] Positive_Count; @end{Example} @Trailing@;Operates on a file of any mode. Returns the current index of the given file. @begin{Example}@Keepnext @key[function] Size(File : @key[in] File_Type) @key[return] Count; @end{Example} @Trailing@;Operates on a file of any mode. Returns the current size of the external file that is associated with the given file. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Operates on a file of mode In_File or Inout_File. Returns True if the current index exceeds the size of the external file; otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. The exception Mode_Error is propagated if the mode of the given file is Out_File. @end{DescribeCode} @end{StaticSem} @begin{Notes} Append_File mode is not supported for the generic package Direct_IO. @end{Notes} @LabeledClause{The Generic Package Storage_IO} @begin{Intro} The generic package Storage_IO provides for reading from and writing to an in-memory buffer. This generic package supports the construction of user-defined input-output packages. @begin{Reason} This package exists to allow the portable construction of user-defined direct-access-oriented input-output packages. The Write procedure writes a value of type Element_Type into a Storage_Array of size Buffer_Size, flattening out any implicit levels of indirection used in the representation of the type. The Read procedure reads a value of type Element_Type from the buffer, reconstructing any implicit levels of indirection used in the representation of the type. It also properly initializes any type tags that appear within the value, presuming that the buffer was written by a different program and that tag values for the@lquotes@;same@rquotes@; type might vary from one executable to another. @end{Reason} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Storage_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[with] System.Storage_Elements; @key[generic] @key[type] Element_Type @key[is] @key[private]; @key[package] Ada.Storage_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Storage_IO]} @key[pragma] Preelaborate(Storage_IO); @AdaObjDefn{Buffer_Size} : @key(constant) System.Storage_Elements.Storage_Count := @RI(implementation-defined); @key(subtype) @AdaSubtypeDefn{Name=[Buffer_Type],Of=[Storage_Array]} @key(is) System.Storage_Elements.Storage_Array(1..Buffer_Size); --@RI{ Input and output operations} @key[procedure] @AdaSubDefn{Read} (Buffer : @key[in] Buffer_Type; Item : @key[out] Element_Type); @key[procedure] @AdaSubDefn{Write}(Buffer : @key[out] Buffer_Type; Item : @key[in] Element_Type); @keepnext --@RI{ Exceptions} @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @key[end] Ada.Storage_IO; @end{Example} In each instance, the constant Buffer_Size has a value that is the size (in storage elements) of the buffer required to represent the content of an object of subtype Element_Type, including any implicit levels of indirection used by the implementation. The Read and Write procedures of Storage_IO correspond to the Read and Write procedures of Direct_IO (see @RefSecNum{The Generic Package Direct_IO}), but with the content of the Item parameter being read from or written into the specified Buffer, rather than an external file. @begin{Reason} @Leading@;As with Direct_IO, the Element_Type formal of Storage_IO does not have an @nt{unknown_discriminant_part} so that there is a well-defined upper bound on the size of the buffer needed to hold the content of an object of the formal subtype (i.e. Buffer_Size). If there are no implicit levels of indirection, Buffer_Size will typically equal: @begin{Example} (Element_Type'Size + System.Storage_Unit - 1) / System.Storage_Unit @end{Example} @end{Reason} @ImplDef{The value of Buffer_Size in Storage_IO.} @end{StaticSem} @begin{Notes} A buffer used for Storage_IO holds only one element at a time; an external file used for Direct_IO holds a sequence of elements. @end{Notes} @begin{Extend83} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 83} Storage_IO is new in Ada 95.]} @end{Extend83} @LabeledClause{Text Input-Output} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} describes the package Text_IO, which provides facilities for input and output in human-readable form. Each file is read or written sequentially, as a sequence of characters grouped into lines, and as a sequence of lines grouped into pages. The specification of the package is given below in subclause @RefSecNum{The Package Text_IO}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The facilities for file management given above, in subclauses @RefSecNum{File Management} and @RefSecNum{Sequential Input-Output Operations}, are available for text input-output. In place of Read and Write, however, there are procedures Get and Put that input values of suitable types from text files, and output values to them. These values are provided to the Put procedures, and returned by the Get procedures, in a parameter Item. Several overloaded procedures of these names exist, for different types of Item. These Get procedures analyze the input sequences of characters based on lexical elements (see @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Lexical Elements}) and return the corresponding values; the Put procedures output the given values as appropriate lexical elements. Procedures Get and Put are also available that input and output individual characters treated as character values rather than as lexical elements. Related to character input are procedures to look ahead at the next character without reading it, and to read a character @lquotes@;immediately@rquotes@; without waiting for an end-of-line to signal availability. In addition to the procedures Get and Put for numeric and enumeration types of Item that operate on text files, analogous procedures are provided that read from and write to a parameter of type String. These procedures perform the same analysis and composition of character sequences as their counterparts which have a file parameter. For all Get and Put procedures that operate on text files, and for many other subprograms, there are forms with and without a file parameter. Each such Get procedure operates on an input file, and each such Put procedure operates on an output file. If no file is specified, a default input file or a default output file is used. @Defn{standard input file} @Defn{standard output file} At the beginning of program execution the default input and output files are the so-called standard input file and standard output file. These files are open, have respectively the current modes In_File and Out_File, and are associated with two implementation-defined external files. Procedures are provided to change the current default input file and the current default output file. @ChgNote{The following was poorly formatted.} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[@Chg{Version=[2],New=[The ], Old=[]}external files @Chg{Version=[2],New=[associated with the],Old=[for]} standard input, standard output, and standard error@Chg{Version=[2],New=[ files.],Old=[]}]} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0113],ARef=[AI95-00087-01]} @ChgAdded{Version=[1],Text=[The default input file and default output file are not the names of distinct file objects, but rather the @i<role> played by one or more (other) file object(s). Thus, they generally will be implemented as accesses to another file object. An implementation that implements them by copying them is incorrect.]} @end{ImplNote} @Defn{standard error file} At the beginning of program execution a default file for program-dependent error-related text output is the so-called standard error file. This file is open, has the current mode Out_File, and is associated with an implementation-defined external file. A procedure is provided to change the current default error file. @Defn{line terminator} @Defn{page terminator} @Defn{file terminator} From a logical point of view, a text file is a sequence of pages, a page is a sequence of lines, and a line is a sequence of characters; the end of a line is marked by a @i{line terminator}; the end of a page is marked by the combination of a line terminator immediately followed by a @i{page terminator}; and the end of a file is marked by the combination of a line terminator immediately followed by a page terminator and then a @i{file terminator}. Terminators are generated during output; either by calls of procedures provided expressly for that purpose; or implicitly as part of other operations, for example, when a bounded line length, a bounded page length, or both, have been specified for a file. The actual nature of terminators is not defined by the language and hence depends on the implementation. Although terminators are recognized or generated by certain of the procedures that follow, they are not necessarily implemented as characters or as sequences of characters. Whether they are characters (and if so which ones) in any particular implementation need not concern a user who neither explicitly outputs nor explicitly inputs control characters. The effect of input (Get) or output (Put) of control characters (other than horizontal tabulation) is not specified by the language. @PDefn{unspecified} @Defn{column number} @Defn{current column number} @Defn{current line number} @Defn{current page number} The characters of a line are numbered, starting from one; the number of a character is called its @i{column number}. For a line terminator, a column number is also defined: it is one more than the number of characters in the line. The lines of a page, and the pages of a file, are similarly numbered. The current column number is the column number of the next character or line terminator to be transferred. The current line number is the number of the current line. The current page number is the number of the current page. These numbers are values of the subtype Positive_Count of the type Count (by convention, the value zero of the type Count is used to indicate special conditions). @begin{Example} @Trailing@key[type] Count @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] Positive_Count @key[is] Count @key[range] 1 .. Count'Last; @end{Example} @Defn{maximum line length} @Defn{maximum page length} For an output file or an append file, a @i{maximum line length} can be specified and a @i{maximum page length} can be specified. If a value to be output cannot fit on the current line, for a specified maximum line length, then a new line is automatically started before the value is output; if, further, this new line cannot fit on the current page, for a specified maximum page length, then a new page is automatically started before the value is output. Functions are provided to determine the maximum line length and the maximum page length. When a file is opened with mode Out_File or Append_File, both values are zero: by convention, this means that the line lengths and page lengths are unbounded. (Consequently, output consists of a single line if the subprograms for explicit control of line and page structure are not used.) The constant Unbounded is provided for this purpose. @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} Append_File is new in Ada 95. @end{Extend83} @LabeledSubClause{The Package Text_IO} @begin{StaticSem} @Leading@;The library package Text_IO has the following declaration: @begin{Example} @key[with] Ada.IO_Exceptions; @key[package] Ada.Text_IO @key[is]@ChildUnit{Parent=[Ada],Child=[Text_IO]} @key[type] @AdaTypeDefn{File_Type} @key[is] @key[limited] @key[private]; @key[type] @AdaTypeDefn{File_Mode} @key[is] (In_File, Out_File, Append_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; @AdaObjDefn{Unbounded} : @key[constant] Count := 0; --@RI{ line and page length} @key[subtype] @AdaSubtypeDefn{Name=[Field],Of=[Integer]} @key[is] Integer @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Number_Base],Of=[Integer]} @key[is] Integer @key[range] 2 .. 16; @key[type] @AdaTypeDefn{Type_Set} @key[is] (Lower_Case, Upper_Case); --@RI{ File Management} @key[procedure] @AdaSubDefn{Create} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode := Out_File; Name : @key[in] String := ""; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Open} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode; Name : @key[in] String; Form : @key[in] String := ""); @key[procedure] @AdaSubDefn{Close} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Delete} (File : @key[in] @key[out] File_Type); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type; Mode : @key[in] File_Mode); @key[procedure] @AdaSubDefn{Reset} (File : @key[in] @key[out] File_Type); @key[function] @AdaSubDefn{Mode} (File : @key[in] File_Type) @key[return] File_Mode; @key[function] @AdaSubDefn{Name} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Form} (File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Is_Open}(File : @key[in] File_Type) @key[return] Boolean; --@RI{ Control of default input and output files} @key[procedure] @AdaSubDefn{Set_Input} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Set_Output}(File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Set_Error} (File : @key[in] File_Type); @key[function] @AdaSubDefn{Standard_Input} @key[return] File_Type; @key[function] @AdaSubDefn{Standard_Output} @key[return] File_Type; @key[function] @AdaSubDefn{Standard_Error} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Input} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Output} @key[return] File_Type; @key[function] @AdaSubDefn{Current_Error} @key[return] File_Type; @key[type] @AdaTypeDefn{File_Access} @key[is] @key[access] @key[constant] File_Type; @key[function] @AdaSubDefn{Standard_Input} @key[return] File_Access; @key[function] @AdaSubDefn{Standard_Output} @key[return] File_Access; @key[function] @AdaSubDefn{Standard_Error} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Input} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Output} @key[return] File_Access; @key[function] @AdaSubDefn{Current_Error} @key[return] File_Access; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]} --@RI{Buffer control} @key[procedure] @AdaSubDefn{Flush} (File : @key[in] @Chg{New=[],Old=[@key[out] ]}File_Type); @key[procedure] @AdaSubDefn{Flush}; --@RI{ Specification of line and page lengths} @key[procedure] @AdaSubDefn{Set_Line_Length}(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Line_Length}(To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Page_Length}(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] @AdaSubDefn{Set_Page_Length}(To : @key[in] Count); @key[function] @AdaSubDefn{Line_Length}(File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{Line_Length} @key[return] Count; @key[function] @AdaSubDefn{Page_Length}(File : @key[in] File_Type) @key[return] Count; @key[function] @AdaSubDefn{Page_Length} @key[return] Count; --@RI{ Column, Line, and Page Control} @key[procedure] @AdaSubDefn{New_Line} (File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{New_Line} (Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{Skip_Line} (File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] @AdaSubDefn{Skip_Line} (Spacing : @key[in] Positive_Count := 1); @key[function] @AdaSubDefn{End_Of_Line}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_Line} @key[return] Boolean; @key[procedure] @AdaSubDefn{New_Page} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{New_Page}; @key[procedure] @AdaSubDefn{Skip_Page} (File : @key[in] File_Type); @key[procedure] @AdaSubDefn{Skip_Page}; @key[function] @AdaSubDefn{End_Of_Page}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_Page} @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_File}(File : @key[in] File_Type) @key[return] Boolean; @key[function] @AdaSubDefn{End_Of_File} @key[return] Boolean; @key[procedure] @AdaSubDefn{Set_Col} (File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Col} (To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Line}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] @AdaSubDefn{Set_Line}(To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Col} (File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Col} @key[return] Positive_Count; @key[function] @AdaSubDefn{Line}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Line} @key[return] Positive_Count; @key[function] @AdaSubDefn{Page}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Page} @key[return] Positive_Count; --@RI{ Character Input-Output} @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Character); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Character); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Character); @key[procedure] @AdaSubDefn{Look_Ahead} (File : @key[in] File_Type; Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] @AdaSubDefn{Look_Ahead} (Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] @AdaSubDefn{Get_Immediate}(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get_Immediate}(Item : @key[out] Character); @key[procedure] @AdaSubDefn{Get_Immediate}(File : @key[in] File_Type; Item : @key[out] Character; Available : @key[out] Boolean); @key[procedure] @AdaSubDefn{Get_Immediate}(Item : @key[out] Character; Available : @key[out] Boolean); --@RI{ String Input-Output} @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] String); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] String); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] String); @key[procedure] @AdaSubDefn{Get_Line}(File : @key[in] File_Type; Item : @key[out] String; Last : @key[out] Natural); @key[procedure] @AdaSubDefn{Get_Line}(Item : @key[out] String; Last : @key[out] Natural); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Get_Line}(File : @key[in] File_Type) @key[return] String; @key[function] @AdaSubDefn{Get_Line} @key[return] String;]} @key[procedure] @AdaSubDefn{Put_Line}(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] @AdaSubDefn{Put_Line}(Item : @key[in] String); --@RI{ Generic packages for Input-Output of Integer Types} @key[generic] @key[type] Num @key[is] @key[range] <>; @key[package] @AdaPackDefn{Integer_IO} @key[is] @AdaObjDefn{Default_Width} : Field := Num'Width; @AdaObjDefn{Default_Base} : Number_Base := 10; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @key[end] Integer_IO; @key[generic] @key[type] Num @key[is] @key[mod] <>; @key[package] @AdaPackDefn{Modular_IO} @key[is] @AdaObjDefn{Default_Width} : Field := Num'Width; @AdaObjDefn{Default_Base} : Number_Base := 10; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @key[end] Modular_IO; --@RI{ Generic packages for Input-Output of Real Types} @key[generic] @key[type] Num @key[is] @key[digits] <>; @key[package] @AdaPackDefn{Float_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := 2; @AdaObjDefn{Default_Aft} : Field := Num'Digits-1; @AdaObjDefn{Default_Exp} : Field := 3; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Float_IO; @key[generic] @key[type] Num @key[is] @key[delta] <>; @key[package] @AdaPackDefn{Fixed_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := Num'Fore; @AdaObjDefn{Default_Aft} : Field := Num'Aft; @AdaObjDefn{Default_Exp} : Field := 0; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Fixed_IO; @key[generic] @key[type] Num @key[is] @key[delta] <> @key[digits] <>; @key[package] @AdaPackDefn{Decimal_IO} @key[is] @AdaObjDefn{Default_Fore} : Field := Num'Fore; @AdaObjDefn{Default_Aft} : Field := Num'Aft; @AdaObjDefn{Default_Exp} : Field := 0; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @key[end] Decimal_IO; --@RI{ Generic package for Input-Output of Enumeration Types} @key[generic] @key[type] Enum @key[is] (<>); @key[package] @AdaPackDefn{Enumeration_IO} @key[is] @AdaObjDefn{Default_Width} : Field := 0; @AdaObjDefn{Default_Setting} : Type_Set := Upper_Case; @key[procedure] @AdaSubDefn{Get}(File : @key[in] File_Type; Item : @key[out] Enum); @key[procedure] @AdaSubDefn{Get}(Item : @key[out] Enum); @key[procedure] @AdaSubDefn{Put}(File : @key[in] File_Type; Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @key[procedure] @AdaSubDefn{Put}(Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @key[procedure] @AdaSubDefn{Get}(From : @key[in] String; Item : @key[out] Enum; Last : @key[out] Positive); @key[procedure] @AdaSubDefn{Put}(To : @key[out] String; Item : @key[in] Enum; Set : @key[in] Type_Set := Default_Setting); @key[end] Enumeration_IO; @keepnext@;--@RI{ Exceptions} @AdaExcDefn{Status_Error} : @key[exception] @key[renames] IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key[exception] @key[renames] IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key[exception] @key[renames] IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key[exception] @key[renames] IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key[exception] @key[renames] IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key[exception] @key[renames] IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key[exception] @key[renames] IO_Exceptions.Data_Error; @AdaExcDefn{Layout_Error} : @key[exception] @key[renames] IO_Exceptions.Layout_Error; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Text_IO; @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Append_File is a new element of enumeration type File_Mode. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} Get_Immediate, Look_Ahead, the subprograms for dealing with standard error, the type File_Access and its associated subprograms, and the generic packages Modular_IO and Decimal_IO are new in Ada 95. @end{Extend83} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] Text_IO.File_Type is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The Text_IO.Get_Line functions are new; they are described in @RefSec{Input-Output of Characters and Strings}.]} @end{DiffWord95} @LabeledSubClause{Text File Management} @begin{StaticSem} @Leading@;The only allowed file modes for text files are the modes In_File, Out_File, and Append_File. The subprograms given in subclause @RefSecNum{File Management} for the control of external files, and the function End_Of_File given in subclause @RefSecNum{Sequential Input-Output Operations} for sequential input-output, are also available for text files. There is also a version of End_Of_File that refers to the current default input file. For text files, the procedures have the following additional effects: @begin{Itemize} For the procedures Create and Open: After a file with mode Out_File or Append_File is opened, the page length and line length are unbounded (both have the conventional value zero). After a file (of any mode) is opened, the current column, current line, and current page numbers are set to one. If the mode is Append_File, it is implementation defined whether a page terminator will separate preexisting text in the file from the new text to be written. @begin{Reason} For a file with mode Append_File, although it may seem more sensible for Open to set the current column, line, and page number based on the number of pages in the file, the number of lines on the last page, and the number of columns in the last line, we rejected this approach because of implementation costs; it would require the implementation to scan the file before doing the append, or to do processing that would be equivalent in effect. For similar reasons, there is no requirement to erase the last page terminator of the file, nor to insert an explicit page terminator in the case when the final page terminator of a file is represented implicitly by the implementation. @end{Reason} For the procedure Close: If the file has the current mode Out_File or Append_File, has the effect of calling New_Page, unless the current page is already terminated; then outputs a file terminator. For the procedure Reset: If the file has the current mode Out_File or Append_File, has the effect of calling New_Page, unless the current page is already terminated; then outputs a file terminator. The current column, line, and page numbers are set to one, and the line and page lengths to Unbounded. If the new mode is Append_File, it is implementation defined whether a page terminator will separate preexisting text in the file from the new text to be written. @begin{Reason} The behavior of Reset should be similar to closing a file and reopening it with the given mode@end{reason} @end{Itemize} The exception Mode_Error is propagated by the procedure Reset upon an attempt to change the mode of a file that is the current default input file, the current default output file, or the current default error file. @end{StaticSem} @begin{Notes} @Leading@;An implementation can define the Form parameter of Create and Open to control effects including the following: @begin{itemize} the interpretation of line and column numbers for an interactive file, and the interpretation of text formats in a file created by a foreign program. @end{itemize} @end{Notes} @LabeledSubClause{Default Input, Output, and Error Files} @begin{StaticSem} The following subprograms provide for the control of the particular default files that are used when a file parameter is omitted from a Get, Put, or other operation of text input-output described below, or when application-dependent error-related text is to be output. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Input(File : @key[in] File_Type); @end{Example} Operates on a file of mode In_File. Sets the current default input file to File. @Trailing@;The exception Status_Error is propagated if the given file is not open. The exception Mode_Error is propagated if the mode of the given file is not In_File. @begin{Example}@Keepnext @key[procedure] Set_Output(File : @key[in] File_Type); @key[procedure] Set_Error (File : @key[in] File_Type); @end{Example} @Trailing@;Each operates on a file of mode Out_File or Append_File. Set_Output sets the current default output file to File. Set_Error sets the current default error file to File. The exception Status_Error is propagated if the given file is not open. The exception Mode_Error is propagated if the mode of the given file is not Out_File or Append_File. @begin{Example}@Keepnext @key[function] Standard_Input @key[return] File_Type; @key[function] Standard_Input @key[return] File_Access; @end{Example} @Trailing@;Returns the standard input file (see @RefSecNum{Text Input-Output}), or an access value designating the standard input file, respectively. @begin{Example}@Keepnext @key[function] Standard_Output @key[return] File_Type; @key[function] Standard_Output @key[return] File_Access; @end{Example} @Trailing@;Returns the standard output file (see @RefSecNum{Text Input-Output}) or an access value designating the standard output file, respectively. @begin{Example}@Keepnext @key[function] Standard_Error @key[return] File_Type; @key[function] Standard_Error @key[return] File_Access; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0052],ARef=[AI95-00194-01]} @Trailing@;Returns the standard error file (see @RefSecNum{Text Input-Output}), or an access value designating the standard @Chg{New=[error],Old=[output]} file, respectively. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} @Trailing@;The Form strings implicitly associated with the opening of Standard_Input, Standard_Output, and Standard_Error at the start of program execution are implementation defined. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Current_Input @key[return] File_Type; @key[function] Current_Input @key[return] File_Access; @end{Example} @Trailing@;Returns the current default input file, or an access value designating the current default input file, respectively. @begin{Example}@Keepnext @key[function] Current_Output @key[return] File_Type; @key[function] Current_Output @key[return] File_Access; @end{Example} @Trailing@;Returns the current default output file, or an access value designating the current default output file, respectively. @begin{Example}@Keepnext @key[function] Current_Error @key[return] File_Type; @key[function] Current_Error @key[return] File_Access; @end{Example} @Trailing@;Returns the current default error file, or an access value designating the current default error file, respectively. @begin{Example}@ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]}@Keepnext @key[procedure] Flush (File : @key[in] @Chg{New=[],Old=[@key[out] ]}File_Type); @key[procedure] Flush; @end{Example} The effect of Flush is the same as the corresponding subprogram in Streams.Stream_IO (see @RefSecNum[The Package Streams.Stream_IO]). If File is not explicitly specified, Current_Output is used. @end{DescribeCode} @end{StaticSem} @begin{Erron} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0053],ARef=[AI95-00063-01]} @PDefn2{Term=(erroneous execution),Sec=(cause)} The execution of a program is erroneous if it @Chg{New=[invokes an operation on], Old=[attempts to use]} a current default input, default output, or default error file@Chg{New=[, and if the corresponding file object is closed or],Old=[ that]} no longer exists. @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgAdded{Version=[1],Text=[Closing a default file, then setting the default file to another open file before accessing it is not erroneous.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgDeleted{Version=[1],Text=[If the Close operation is applied to a file object that is also serving as the default input, default output, or default error file, then subsequent operations on such a default file are erroneous.]} @end{Erron} @begin{Notes} The standard input, standard output, and standard error files cannot be opened, closed, reset, or deleted, because the parameter File of the corresponding procedures has the mode @key[in] @key[out]. The standard input, standard output, and standard error files are different file objects, but not necessarily different external files. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0052],ARef=[AI95-00194-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected Standard_Error so it refers to the correct file.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0053],ARef=[AI95-00063-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that execution is erroneous only when a closed default file is accessed.]} @end{DiffWord95} @LabeledSubClause{Specification of Line and Page Lengths} @begin{StaticSem} The subprograms described in this subclause are concerned with the line and page structure of a file of mode Out_File or Append_File. They operate either on the file given as the first parameter, or, in the absence of such a file parameter, on the current default output file. They provide for output of text with a specified maximum line length or page length. In these cases, line and page terminators are output implicitly and automatically when needed. When line and page lengths are unbounded (that is, when they have the conventional value zero), as in the case of a newly opened file, new lines and new pages are only started when explicitly called for. In all cases, the exception Status_Error is propagated if the file to be used is not open; the exception Mode_Error is propagated if the mode of the file is not Out_File or Append_File. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Line_Length(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] Set_Line_Length(To : @key[in] Count); @end{Example} Sets the maximum line length of the specified output or append file to the number of characters specified by To. The value zero for To specifies an unbounded line length. @begin{Ramification} The setting does not affect the lengths of lines in the existing file, rather it only influences subsequent output operations.@end{ramification} @Trailing@;The exception Use_Error is propagated if the specified line length is inappropriate for the associated external file. @begin{Example}@Keepnext @key[procedure] Set_Page_Length(File : @key[in] File_Type; To : @key[in] Count); @key[procedure] Set_Page_Length(To : @key[in] Count); @end{Example} Sets the maximum page length of the specified output or append file to the number of lines specified by To. The value zero for To specifies an unbounded page length. @Trailing@;The exception Use_Error is propagated if the specified page length is inappropriate for the associated external file. @begin{Example}@Keepnext @key[function] Line_Length(File : @key[in] File_Type) @key[return] Count; @key[function] Line_Length @key[return] Count; @end{Example} @Trailing@;Returns the maximum line length currently set for the specified output or append file, or zero if the line length is unbounded. @begin{Example}@Keepnext @key[function] Page_Length(File : @key[in] File_Type) @key[return] Count; @key[function] Page_Length @key[return] Count; @end{Example} Returns the maximum page length currently set for the specified output or append file, or zero if the page length is unbounded. @end{DescribeCode} @end{StaticSem} @LabeledSubClause{Operations on Columns, Lines, and Pages} @begin{StaticSem} The subprograms described in this subclause provide for explicit control of line and page structure; they operate either on the file given as the first parameter, or, in the absence of such a file parameter, on the appropriate (input or output) current default file. The exception Status_Error is propagated by any of these subprograms if the file to be used is not open. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] New_Line(File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] New_Line(Spacing : @key[in] Positive_Count := 1); @end{Example} Operates on a file of mode Out_File or Append_File. For a Spacing of one: Outputs a line terminator and sets the current column number to one. Then increments the current line number by one, except in the case that the current line number is already greater than or equal to the maximum page length, for a bounded page length; in that case a page terminator is output, the current page number is incremented by one, and the current line number is set to one. For a Spacing greater than one, the above actions are performed Spacing times. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. @begin{Example}@Keepnext @key[procedure] Skip_Line(File : @key[in] File_Type; Spacing : @key[in] Positive_Count := 1); @key[procedure] Skip_Line(Spacing : @key[in] Positive_Count := 1); @end{Example} Operates on a file of mode In_File. For a Spacing of one: Reads and discards all characters until a line terminator has been read, and then sets the current column number to one. If the line terminator is not immediately followed by a page terminator, the current line number is incremented by one. Otherwise, if the line terminator is immediately followed by a page terminator, then the page terminator is skipped, the current page number is incremented by one, and the current line number is set to one. For a Spacing greater than one, the above actions are performed Spacing times. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if an attempt is made to read a file terminator. @begin{Example}@Keepnext @key[function] End_Of_Line(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_Line @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Operates on a file of mode In_File. Returns True if a line terminator or a file terminator is next; otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @begin{Example}@Keepnext @key[procedure] New_Page(File : @key[in] File_Type); @key[procedure] New_Page; @end{Example} Operates on a file of mode Out_File or Append_File. Outputs a line terminator if the current line is not terminated, or if the current page is empty (that is, if the current column and line numbers are both equal to one). Then outputs a page terminator, which terminates the current page. Adds one to the current page number and sets the current column and line numbers to one. @Trailing@;The exception Mode_Error is propagated if the mode is not Out_File or Append_File. @begin{Example}@Keepnext @key[procedure] Skip_Page(File : @key[in] File_Type); @key[procedure] Skip_Page; @end{Example} Operates on a file of mode In_File. Reads and discards all characters and line terminators until a page terminator has been read. Then adds one to the current page number, and sets the current column and line numbers to one. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. The exception End_Error is propagated if an attempt is made to read a file terminator. @begin{Example}@Keepnext @key[function] End_Of_Page(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_Page @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Operates on a file of mode In_File. Returns True if the combination of a line terminator and a page terminator is next, or if a file terminator is next; otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @begin{Example}@Keepnext @key[function] End_Of_File(File : @key[in] File_Type) @key[return] Boolean; @key[function] End_Of_File @key[return] Boolean; @end{Example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Operates on a file of mode In_File. Returns True if a file terminator is next, or if the combination of a line, a page, and a file terminator is next; otherwise@Chg{Version=[3],New=[,],Old=[]} returns False. @Trailing@;The exception Mode_Error is propagated if the mode is not In_File. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} The following subprograms provide for the control of the current position of reading or writing in a file. In all cases, the default file is the current output file. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Set_Col(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] Set_Col(To : @key[in] Positive_Count); @end{Example} @Leading@;If the file mode is Out_File or Append_File: @begin{itemize} If the value specified by To is greater than the current column number, outputs spaces, adding one to the current column number after each space, until the current column number equals the specified value. If the value specified by To is equal to the current column number, there is no effect. If the value specified by To is less than the current column number, has the effect of calling New_Line (with a spacing of one), then outputs (To @en 1) spaces, and sets the current column number to the specified value. The exception Layout_Error is propagated if the value specified by To exceeds Line_Length when the line length is bounded (that is, when it does not have the conventional value zero). @end{itemize} @Leading@;If the file mode is In_File: @begin{itemize} Reads (and discards) individual characters, line terminators, and page terminators, until the next character to be read has a column number that equals the value specified by To; there is no effect if the current column number already equals this value. Each transfer of a character or terminator maintains the current column, line, and page numbers in the same way as a Get procedure (see @RefSecNum{Get and Put Procedures}). (Short lines will be skipped until a line is reached that has a character at the specified column position.) @Trailing@;The exception End_Error is propagated if an attempt is made to read a file terminator. @end{itemize} @begin{Example}@Keepnext @key[procedure] Set_Line(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[procedure] Set_Line(To : @key[in] Positive_Count); @end{Example} @Leading@;If the file mode is Out_File or Append_File: @begin{itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0038-1]} If the value specified by To is greater than the current line number, has the effect of repeatedly calling New_Line (with a spacing of one), until the current line number equals the specified value. If the value specified by To is equal to the current line number, there is no effect. If the value specified by To is less than the current line number, has the effect of calling New_Page followed@Chg{Version=[3],New=[, if To is greater than 1,],Old=[]} by a call of New_Line with a spacing equal to (To @en 1). The exception Layout_Error is propagated if the value specified by To exceeds Page_Length when the page length is bounded (that is, when it does not have the conventional value zero). @end{itemize} @Leading@;If the mode is In_File: @begin{itemize} Has the effect of repeatedly calling Skip_Line (with a spacing of one), until the current line number equals the value specified by To; there is no effect if the current line number already equals this value. (Short pages will be skipped until a page is reached that has a line at the specified line position.) @Trailing@;The exception End_Error is propagated if an attempt is made to read a file terminator. @end{itemize} @begin{Example}@Keepnext @key[function] Col(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Col @key[return] Positive_Count; @end{Example} Returns the current column number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @begin{Example}@Keepnext @key[function] Line(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Line @key[return] Positive_Count; @end{Example} Returns the current line number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @begin{Example}@Keepnext @key[function] Page(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] Page @key[return] Positive_Count; @end{Example} Returns the current page number. @Trailing@;The exception Layout_Error is propagated if this number exceeds Count'Last. @end{DescribeCode} The column number, line number, or page number are allowed to exceed Count'Last (as a consequence of the input or output of sufficiently many characters, lines, or pages). These events do not cause any exception to be propagated. However, a call of Col, Line, or Page propagates the exception Layout_Error if the corresponding number exceeds Count'Last. @end{StaticSem} @begin{Notes} A page terminator is always skipped whenever the preceding line terminator is skipped. An implementation may represent the combination of these terminators by a single character, provided that it is properly recognized on input. @end{Notes} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0038-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Fixed a glitch in Set_Line such that we could have called New_Line(0), which would have to raise Constraint_Error. It's now defined to work. The bug occurred in Ada 95 and Ada 2005. It's very unlikely that any real programs depend on this exception being raised.]} @end{Inconsistent2005} @LabeledSubClause{Get and Put Procedures} @begin{StaticSem} The procedures Get and Put for items of the type Character, String, numeric types, and enumeration types are described in subsequent subclauses. Features of these procedures that are common to most of these types are described in this subclause. The Get and Put procedures for items of type Character and String deal with individual character values; the Get and Put procedures for numeric and enumeration types treat the items as lexical elements. All procedures Get and Put have forms with a file parameter, written first. Where this parameter is omitted, the appropriate (input or output) current default file is understood to be specified. Each procedure Get operates on a file of mode In_File. Each procedure Put operates on a file of mode Out_File or Append_File. All procedures Get and Put maintain the current column, line, and page numbers of the specified file: the effect of each of these procedures upon these numbers is the result of the effects of individual transfers of characters and of individual output or skipping of terminators. Each transfer of a character adds one to the current column number. Each output of a line terminator sets the current column number to one and adds one to the current line number. Each output of a page terminator sets the current column and line numbers to one and adds one to the current page number. For input, each skipping of a line terminator sets the current column number to one and adds one to the current line number; each skipping of a page terminator sets the current column and line numbers to one and adds one to the current page number. Similar considerations apply to the procedures Get_Line, Put_Line, and Set_Col. Several Get and Put procedures, for numeric and enumeration types, have @i{format} parameters which specify field lengths; these parameters are of the nonnegative subtype Field of the type Integer. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00223-01]} @Defn2{Term=[blank], Sec=(in text input for enumeration and numeric types)} Input-output of enumeration values uses the syntax of the corresponding lexical elements. Any Get procedure for an enumeration type begins by skipping any leading blanks, or line or page terminators. @Chg{Version=[2], New=[A],Old=[Get procedures for numeric or enumeration types start by skipping leading blanks, where a]} @i{blank} is defined as a space or a horizontal tabulation character. Next, characters are input only so long as the sequence input is an initial sequence of an identifier or of a character literal (in particular, input ceases when a line terminator is encountered). The character or line terminator that causes input to cease remains available for subsequent input. For a numeric type, the Get procedures have a format parameter called Width. If the value given for this parameter is zero, the Get procedure proceeds in the same manner as for enumeration types, but using the syntax of numeric literals instead of that of enumeration literals. If a nonzero value is given, then exactly Width characters are input, or the characters up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. The syntax used for numeric literals is an extended syntax that allows a leading sign (but no intervening blanks, or line or page terminators) and that also allows (for real types) an integer literal as well as forms that have digits only before the point or only after the point. Any Put procedure, for an item of a numeric or an enumeration type, outputs the value of the item as a numeric literal, identifier, or character literal, as appropriate. This is preceded by leading spaces if required by the format parameters Width or Fore (as described in later subclauses), and then a minus sign for a negative value; for an enumeration type, the spaces follow instead of leading. The format given for a Put procedure is overridden if it is insufficiently wide, by using the minimum needed width. Two further cases arise for Put procedures for numeric and enumeration types, if the line length of the specified output file is bounded (that is, if it does not have the conventional value zero). If the number of characters to be output does not exceed the maximum line length, but is such that they cannot fit on the current line, starting from the current column, then (in effect) New_Line is called (with a spacing of one) before output of the item. Otherwise, if the number of characters exceeds the maximum line length, then the exception Layout_Error is propagated and nothing is output. The exception Status_Error is propagated by any of the procedures Get, Get_Line, Put, and Put_Line if the file to be used is not open. The exception Mode_Error is propagated by the procedures Get and Get_Line if the mode of the file to be used is not In_File; and by the procedures Put and Put_Line, if the mode is not Out_File or Append_File. The exception End_Error is propagated by a Get procedure if an attempt is made to skip a file terminator. The exception Data_Error is propagated by a Get procedure if the sequence finally input is not a lexical element corresponding to the type, in particular if no characters were input; for this test, leading blanks are ignored; for an item of a numeric type, when a sign is input, this rule applies to the succeeding numeric literal. The exception Layout_Error is propagated by a Put procedure that outputs to a parameter of type String, if the length of the actual string is insufficient for the output of the item. @end{StaticSem} @begin{Examples} In the examples, here and in subclauses @RefSecNum{Input-Output for Integer Types} and @RefSecNum{Input-Output for Real Types}, the string quotes and the lower case letter b are not transferred: they are shown only to reveal the layout and spaces. @begin{Example} N : Integer; ... Get(N); @tabclear()@tabset(P4, P22, P38) @RI[-- @\Characters at input @\Sequence input @\Value of N] @Comment{Blank line.} @RI[-- @\bb@en@|12535b @\@en@|12535 @\@en@|12535] @RI[-- @\bb12_535e1b @\12_535e1 @\125350] @RI[-- @\bb12_535e; @\12_535e @\(none) Data_Error raised] @end{Example} @begin{WideAbove} @Leading@;Example of overridden width parameter: @end{WideAbove} @begin{Example} Put(Item => -23, Width => 2); --@RI{ "@en@|23"} @end{Example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00223-01]} @ChgAdded{Version=[2],Text=[Removed conflicting text describing the skipping of blanks for a Get procedure.]} @end{DiffWord95} @LabeledSubClause{Input-Output of Characters and Strings} @begin{StaticSem} @Leading@Keepnext@;For an item of type Character the following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] Get(Item : @key[out] Character); @end{Example} After skipping any line terminators and any page terminators, reads the next character from the specified input file and returns the value of this character in the out parameter Item. @Trailing@;The exception End_Error is propagated if an attempt is made to skip a file terminator. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Character); @key[procedure] Put(Item : @key[in] Character); @end{Example} @Trailing@;If the line length of the specified output file is bounded (that is, does not have the conventional value zero), and the current column number exceeds it, has the effect of calling New_Line with a spacing of one. Then, or otherwise, outputs the given character to the file. @begin{Example}@Keepnext @key[procedure] Look_Ahead (File : @key[in] File_Type; Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @key[procedure] Look_Ahead (Item : @key[out] Character; End_Of_Line : @key[out] Boolean); @end{Example} @Trailing@ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0038-1],ARef=[AI05-0264-1]}@Chg{Version=[3], New=[Status_Error is propagated if the file is not open. ],Old=[]}Mode_Error is propagated if the mode of the file is not In_File. Sets End_Of_Line to True if at end of line, including if at end of page or at end of file; in each of these cases the value of Item is not specified. @PDefn{unspecified} Otherwise@Chg{Version=[3],New=[,],Old=[]} End_Of_Line is set to False and Item is set to @Chg{New=[],Old=[the ]}the next character (without consuming it) from the file. @begin{Example}@Keepnext @key[procedure] Get_Immediate(File : @key[in] File_Type; Item : @key[out] Character); @key[procedure] Get_Immediate(Item : @key[out] Character); @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0038-1]}Reads the next character, either control or graphic, from the specified File or the default input file. @Chg{Version=[3],New=[Status_Error is propagated if the file is not open. ],Old=[]}Mode_Error is propagated if the mode of the file is not In_File. End_Error is propagated if at the end of the file. The current column, line and page numbers for the file are not affected. @begin{Example}@Keepnext @key[procedure] Get_Immediate(File : @key[in] File_Type; Item : @key[out] Character; Available : @key[out] Boolean); @key[procedure] Get_Immediate(Item : @key[out] Character; Available : @key[out] Boolean); @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0038-1]}If a character, either control or graphic, is available from the specified File or the default input file, then the character is read; Available is True and Item contains the value of this character. If a character is not available, then Available is False and the value of Item is not specified. @PDefn{unspecified} @Chg{Version=[3],New=[Status_Error is propagated if the file is not open. ],Old=[]}Mode_Error is propagated if the mode of the file is not In_File. End_Error is propagated if at the end of the file. The current column, line and page numbers for the file are not affected. @end{DescribeCode} @Comment{The following paragraph was originally in a DescribeCode section; but that clearly was not intended; I've fixed it. (This changes the indentation of the paragraph in the old version too, but the change is harmless.) RLB-21-08-2000} @Leading@; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} For an item of type String the following @Chg{Version=[2],New=[subprograms], Old=[procedures]} are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] String); @key[procedure] Get(Item : @key[out] String); @end{Example} @Trailing@;Determines the length of the given string and attempts that number of Get operations for successive characters of the string (in particular, no operation is performed if the string is null). @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] Put(Item : @key[in] String); @end{Example} @Trailing@;Determines the length of the given string and attempts that number of Put operations for successive characters of the string (in particular, no operation is performed if the string is null). @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Keepnext=[T],Text=[@key{function} Get_Line(File : @key{in} File_Type) @key{return} String; @key{function} Get_Line @b<return> String;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns a result string constructed by reading successive characters from the specified input file, and assigning them to successive characters of the result string. The result string has a lower bound of 1 and an upper bound of the number of characters read. Reading stops when the end of the line is met; Skip_Line is then (in effect) called with a spacing of 1.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Constraint_Error is raised if the length of the line exceeds Positive'Last; in this case, the line number and page number are unchanged, and the column number is unspecified but no less than it was before the call.@PDefn{unspecified} The exception End_Error is propagated if an attempt is made to skip a file terminator.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Precisely what is left in the file is unspecified if Constraint_Error is raised because the line doesn't fit in a String; it should be consistent with column number. This allows implementers to use whatever buffering scheme makes sense. But the line terminator is not skipped in this case.]} @end{Ramification} @begin{Example}@Keepnext @key[procedure] Get_Line(File : @key[in] File_Type; Item : @key[out] String; Last : @key[out] Natural); @key[procedure] Get_Line(Item : @key[out] String; Last : @key[out] Natural); @end{Example} Reads successive characters from the specified input file and assigns them to successive characters of the specified string. Reading stops if the end of the string is met. Reading also stops if the end of the line is met before meeting the end of the string; in this case Skip_Line is (in effect) called with a spacing of 1. @PDefn{unspecified} The values of characters not assigned are not specified. @Trailing@;If characters are read, returns in Last the index value such that Item(Last) is the last character assigned (the index of the first character assigned is Item'First). If no characters are read, returns in Last an index value that is one less than Item'First. The exception End_Error is propagated if an attempt is made to skip a file terminator. @begin{Example}@Keepnext @key[procedure] Put_Line(File : @key[in] File_Type; Item : @key[in] String); @key[procedure] Put_Line(Item : @key[in] String); @end{Example} Calls the procedure Put for the given string, and then the procedure New_Line with a spacing of one. @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} The Get_Immediate procedures should be implemented with unbuffered input. For a device such as a keyboard, input should be @lquotes@;available@rquotes@; if a key has already been typed, whereas for a disk file, input should always be available except at end of file. For a file associated with a keyboard-like device, any line-editing features of the underlying operating system should be disabled during the execution of Get_Immediate. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Get_Immediate should be implemented with unbuffered input; input should be available immediately; line-editing should be disabled.]}]} @end{ImplAdvice} @begin{Notes} Get_Immediate can be used to read a single key from the keyboard @lquotes@;immediately@rquotes@;; that is, without waiting for an end of line. In a call of Get_Immediate without the parameter Available, the caller will wait until a character is available. In a literal string parameter of Put, the enclosing string bracket characters are not output. Each doubled string bracket character in the enclosed string is output as a single string bracket character, as a consequence of the rule for string literals (see @RefSecNum{String Literals}). A string read by Get or written by Put can extend over several lines. An implementation is allowed to assume that certain external files do not contain page terminators, in which case Get_Line and Skip_Line can return as soon as a line terminator is read. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} The Get_Line functions are @Chg{Version=[3],New=[],Old=[newly ]}added to Ada.Text_IO. If Ada.Text_IO is referenced in a @nt{use_clause}, and a function Get_Line is defined in a package that is also referenced in a @nt{use_clause}, the user-defined Get_Line may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Text_IO.Get_Line functions are new.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0038-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added missing wording about raising Status_Error to Look_Ahead and Get_Immediate.]} @end{DiffWord2005} @LabeledSubClause{Input-Output for Integer Types} @begin{StaticSem} The following procedures are defined in the generic packages Integer_IO and Modular_IO, which have to be instantiated for the appropriate signed integer or modular type respectively (indicated by Num in the specifications). @Leading@;Values are output as decimal or based literals, without low line characters or exponent, and, for Integer_IO, preceded by a minus sign if negative. The format (which includes any leading spaces and minus sign) can be specified by an optional field width parameter. Values of widths of fields in output formats are of the nonnegative integer subtype Field. Values of bases are of the integer subtype Number_Base. @begin{Example} @Trailing@key[subtype] Number_Base @key[is] Integer @key[range] 2 .. 16; @end{Example} @Leading@;The default field width and base to be used by output procedures are defined by the following variables that are declared in the generic packages Integer_IO and Modular_IO: @begin{Example} @Trailing@;Default_Width : Field := Num'Width; Default_Base : Number_Base := 10; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] Get(Item : @key[out] Num; Width : @key[in] Field := 0); @end{Example} If the value of the parameter Width is zero, skips any leading blanks, line terminators, or page terminators, then reads a plus sign if present or (for a signed type only) a minus sign if present, then reads the longest possible sequence of characters matching the syntax of a numeric literal without a point. If a nonzero value of Width is supplied, then exactly Width characters are input, or the characters (possibly none) up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0038-1]} @Trailing@;The exception Data_Error is propagated if the sequence of characters read does not form a legal integer literal or if the value obtained is not of the subtype Num@Chg{Version=[3],New=[],Old=[ (for Integer_IO) or is not in the base range of Num (for Modular_IO)]}. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Num; Width : @key[in] Field := Default_Width; Base : @key[in] Number_Base := Default_Base); @end{Example} Outputs the value of the parameter Item as an integer literal, with no low lines, no exponent, and no leading zeros (but a single zero for the value zero), and a preceding minus sign for a negative value. If the resulting sequence of characters to be output has fewer than Width characters, then leading spaces are first output to make up the difference. @Trailing@;Uses the syntax for decimal literal if the parameter Base has the value ten (either explicitly or through Default_Base); otherwise, uses the syntax for based literal, with any letters in upper case. @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @end{Example} Reads an integer value from the beginning of the given string, following the same rules as the Get procedure that reads an integer value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Num; Base : @key[in] Number_Base := Default_Base); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using the length of the given string as the value for Width. @end{DescribeCode} @Leading@;Integer_Text_IO is a library package that is a nongeneric equivalent to Text_IO.Integer_IO for the predefined type Integer: @begin{Example} @key[with] Ada.Text_IO;@ChildUnit{Parent=[Ada],Child=[Integer_@!Text_IO]} @key[package] Ada.Integer_Text_IO @key[is] @key[new] Ada.Text_IO.Integer_IO(Integer); @end{Example} For each predefined signed integer type, a nongeneric equivalent to Text_IO.Integer_IO is provided, with names such as Ada.Long_Integer_Text_IO. @end{StaticSem} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0038-1]} @ChgDeleted{Version=[3],Text=[For Modular_IO, execution of Get propagates Data_Error if the sequence of characters read forms an integer literal outside the range 0..Num'Last.]} @end{Notes} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 24 and 25 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered. This includes the next paragraph.} @end{NotIso} @begin{Examples} @begin{Example} @ChgRef{Version=[1], Kind=[DeletedNoDelMsg]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @ChgRef{Version=[3], Kind=[Revised],ARef=[AI05-0298-1]} @Chg{Version=[3],New=[@key[subtype] Byte_Int @key[is] Integer @key[range] -127 .. 127; ],Old=[]}@key[package] Int_IO @key[is] @key[new] Integer_IO(@Chg{Version=[3],New=[Byte_Int],Old=[Small_Int]}); @key[use] Int_IO; --@RI{ default format used at instantiation,} --@RI{ Default_Width = 4, Default_Base = 10} Put(126); --@RI{ "b126"} Put(-126, 7); --@RI{ "bbb@en@|126"} Put(126, Width => 13, Base => 2); --@RI{ "bbb2#1111110#"} @end{Example} @end{Examples} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0038-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005}@b<Correction:> Changed wording to make Integer_IO and Modular_IO raise Data_Error in the same way when the bounds of the subtype are exceeded. There is no value to different behavior, and all surveyed compilers already treat integer and modular values the same way. This could only cause a problem if a program was compiled with some unsurveyed compiler, and the Ada 95-defined behavior is expected for Modular_IO. But note that such code is not portable anyway, as most widely used compilers behave consistently with the new wording, so it is unlikely that such code exists.]} @end{Inconsistent2005} @LabeledSubClause{Input-Output for Real Types} @begin{StaticSem} The following procedures are defined in the generic packages Float_IO, Fixed_IO, and Decimal_IO, which have to be instantiated for the appropriate floating point, ordinary fixed point, or decimal fixed point type respectively (indicated by Num in the specifications). @Leading@;Values are output as decimal literals without low line characters. The format of each value output consists of a Fore field, a decimal point, an Aft field, and (if a nonzero Exp parameter is supplied) the letter E and an Exp field. The two possible formats thus correspond to: @begin{Example} Fore . Aft @end{Example} @Leading@;and to: @begin{Example} Fore . Aft E Exp @end{Example} without any spaces between these fields. The Fore field may include leading spaces, and a minus sign for negative values. The Aft field includes only decimal digits (possibly with trailing zeros). The Exp field includes the sign (plus or minus) and the exponent (possibly with leading zeros). @Leading@;For floating point types, the default lengths of these fields are defined by the following variables that are declared in the generic package Float_IO: @begin{Example} @Trailing@;Default_Fore : Field := 2; Default_Aft : Field := Num'Digits-1; Default_Exp : Field := 3; @end{Example} @Leading@;For ordinary or decimal fixed point types, the default lengths of these fields are defined by the following variables that are declared in the generic packages Fixed_IO and Decimal_IO, respectively: @begin{Example} @Trailing@;Default_Fore : Field := Num'Fore; Default_Aft : Field := Num'Aft; Default_Exp : Field := 0; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Num; Width : @key[in] Field := 0); @key[procedure] Get(Item : @key[out] Num; Width : @key[in] Field := 0); @end{Example} @Leading@;If the value of the parameter Width is zero, skips any leading blanks, line terminators, or page terminators, then reads the longest possible sequence of characters matching the syntax of any of the following (see @RefSecNum(Numeric Literals)): @begin[itemize] [+|@en]@nt[numeric_literal] [+|@en]@nt[numeral].[@nt[exponent]] [+|@en].@nt[numeral][@nt[exponent]] [+|@en]@nt[base]#@nt[based_numeral].#[@nt[exponent]] [+|@en]@nt[base]#.@nt[based_numeral]#[@nt[exponent]] @end{Itemize} If a nonzero value of Width is supplied, then exactly Width characters are input, or the characters (possibly none) up to a line terminator, whichever comes first; any skipped leading blanks are included in the count. Returns in the parameter Item the value of type Num that corresponds to the sequence input, preserving the sign (positive if none has been specified) of a zero value if Num is a floating point type and Num'Signed_Zeros is True. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Num; Fore : @key[in] Field := Default_Fore; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} Outputs the value of the parameter Item as a decimal literal with the format defined by Fore, Aft and Exp. If the value is negative, or if Num is a floating point type where Num'Signed_Zeros is True and the value is a negatively signed zero, then a minus sign is included in the integer part. If Exp has the value zero, then the integer part to be output has as many digits as are needed to represent the integer part of the value of Item, overriding Fore if necessary, or consists of the digit zero if the value of Item has no integer part. If Exp has a value greater than zero, then the integer part to be output has a single digit, which is nonzero except for the value 0.0 of Item. In both cases, however, if the integer part to be output has fewer than Fore characters, including any minus sign, then leading spaces are first output to make up the difference. The number of digits of the fractional part is given by Aft, or is one if Aft equals zero. The value is rounded; a value of exactly one half in the last place is rounded away from zero. @Trailing@;If Exp has the value zero, there is no exponent part. If Exp has a value greater than zero, then the exponent part to be output has as many digits as are needed to represent the exponent part of the value of Item (for which a single digit integer part is used), and includes an initial sign (plus or minus). If the exponent part to be output has fewer than Exp characters, including the sign, then leading zeros precede the digits, to make up the difference. For the value 0.0 of Item, the exponent has the value zero. @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Num; Last : @key[out] Positive); @end{Example} Reads a real value from the beginning of the given string, following the same rule as the Get procedure that reads a real value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Num that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the value obtained is not of the subtype Num. @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Num; Aft : @key[in] Field := Default_Aft; Exp : @key[in] Field := Default_Exp); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using a value for Fore such that the sequence of characters output exactly fills the string, including any leading spaces. @end{DescribeCode} @Leading@;Float_Text_IO is a library package that is a nongeneric equivalent to Text_IO.Float_IO for the predefined type Float: @begin{Example} @key[with] Ada.Text_IO;@ChildUnit{Parent=[Ada],Child=[Float_@!Text_IO]} @key[package] Ada.Float_Text_IO @key[is] @key[new] Ada.Text_IO.Float_IO(Float); @end{Example} For each predefined floating point type, a nongeneric equivalent to Text_IO.Float_IO is provided, with names such as Ada.Long_Float_Text_IO. @end{StaticSem} @begin{ImplPerm} An implementation may extend Get @Redundant[and Put] for floating point types to support special values such as infinities and NaNs. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} See also the similar permission for the @Chg{Version=[3],New=[Wide_Wide_Value, ],Old=[]} Wide_Value@Chg{Version=[3],New=[, and Value attributes],Old=[attribute]} in @RefSecNum{Scalar Types}. @end{Discussion} The implementation of Put need not produce an output value with greater accuracy than is supported for the base subtype. The additional accuracy, if any, of the value produced by Put when the number of requested digits in the integer and fractional parts exceeds the required accuracy is implementation defined. @begin{Discussion} The required accuracy is thus Num'Base'Digits digits if Num is a floating point subtype. For a fixed point subtype the required accuracy is a function of the subtype's Fore, Aft, and Delta attributes. @end{Discussion} @ImplDef{The accuracy of the value produced by Put.} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{Notes} For an item with a positive value, if output to a string exactly fills the string without leading spaces, then output of the corresponding negative value will propagate Layout_Error. The rules for the Value attribute (see @RefSecNum(Scalar Types)) and the rules for Get are based on the same set of formats. @end{Notes} @begin{Examples} @begin{Example} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[package] Real_IO @key[is] @key[new] Float_IO(Real); @key[use] Real_IO; --@RI{ default format used at instantiation, Default_Exp = 3} X : Real := -123.4567; --@RI{ digits 8 (see @RefSecNum{Floating Point Types})} @tabclear()@tabset(P50) Put(X); @RI[-- default format] @\@RI["@en@|1.2345670E+02"] Put(X, Fore => 5, Aft => 3, Exp => 2); @\@RI[-- "bbb@en@|1.235E+2"] Put(X, 5, 3, 0); @\@RI[-- "b@en@|123.457"] @end{Example} @end{Examples} @LabeledSubClause{Input-Output for Enumeration Types} @begin{StaticSem} The following procedures are defined in the generic package Enumeration_IO, which has to be instantiated for the appropriate enumeration type (indicated by Enum in the specification). Values are output using either upper or lower case letters for identifiers. This is specified by the parameter Set, which is of the enumeration type Type_Set. @begin{Example} @Trailing@key[type] Type_Set @key[is] (Lower_Case, Upper_Case); @end{Example} @Leading@;The format (which includes any trailing spaces) can be specified by an optional field width parameter. The default field width and letter case are defined by the following variables that are declared in the generic package Enumeration_IO: @begin{Example} @Trailing@;Default_Width : Field := 0; Default_Setting : Type_Set := Upper_Case; @end{Example} @Leading@Keepnext@;The following procedures are provided: @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Get(File : @key[in] File_Type; Item : @key[out] Enum); @key[procedure] Get(Item : @key[out] Enum); @end{Example} After skipping any leading blanks, line terminators, or page terminators, reads an identifier according to the syntax of this lexical element (lower and upper case being considered equivalent), or a character literal according to the syntax of this lexical element (including the apostrophes). Returns, in the parameter Item, the value of type Enum that corresponds to the sequence input. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the identifier or character literal does not correspond to a value of the subtype Enum. @begin{Example}@Keepnext @key[procedure] Put(File : @key[in] File_Type; Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @comment{Blank Line} @key[procedure] Put(Item : @key[in] Enum; Width : @key[in] Field := Default_Width; Set : @key[in] Type_Set := Default_Setting); @end{Example} @Trailing@;Outputs the value of the parameter Item as an enumeration literal (either an identifier or a character literal). The optional parameter Set indicates whether lower case or upper case is used for identifiers; it has no effect for character literals. If the sequence of characters produced has fewer than Width characters, then trailing spaces are finally output to make up the difference. If Enum is a character type, the sequence of characters produced is as for Enum'Image(Item), as modified by the Width and Set parameters. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} For a character type, the literal might be a @Chg{Version=[3],New=[Wide_Wide_Character, ],Old=[]}Wide_Character@Chg{Version=[3],New=[,],Old=[]} or a control character. Whatever Image does for these things is appropriate here, too. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0036-1]} @ChgAdded{Version=[3],Text=[The @ldquote@;characters produced@rdquote@; defines the @ldquote@;characters to be output@rdquote in the sense of @RefSecNum{Get and Put Procedures}, so a result that cannot fit on any bounded line will raise Layout_Error.]} @end{Discussion} @begin{Example}@Keepnext @key[procedure] Get(From : @key[in] String; Item : @key[out] Enum; Last : @key[out] Positive); @end{Example} Reads an enumeration value from the beginning of the given string, following the same rule as the Get procedure that reads an enumeration value from a file, but treating the end of the string as a file terminator. Returns, in the parameter Item, the value of type Enum that corresponds to the sequence input. Returns in Last the index value such that From(Last) is the last character read. @Trailing@;The exception Data_Error is propagated if the sequence input does not have the required syntax, or if the identifier or character literal does not correspond to a value of the subtype Enum. @begin{Honest} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} For a character type, it is permissible for the implementation to make Get do the inverse of what Put does, in the case of wide@Chg{Version=[3],New=[ and wide_wide],Old=[]} @nt{character_literal}s and control characters. @end{Honest} @begin{Example}@Keepnext @key[procedure] Put(To : @key[out] String; Item : @key[in] Enum; Set : @key[in] Type_Set := Default_Setting); @end{Example} @Trailing@;Outputs the value of the parameter Item to the given string, following the same rule as for output to a file, using the length of the given string as the value for Width. @end{DescribeCode} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0054],ARef=[AI95-00007-01]} Although the specification of the generic package Enumeration_IO would allow instantiation for an @Chg{New=[integer],Old=[float]} type, this is not the intended purpose of this generic package, and the effect of such instantiations is not defined by the language. @end{StaticSem} @begin{Notes} There is a difference between Put defined for characters, and for enumeration values. Thus @begin{Example} Ada.Text_IO.Put('A'); --@RI{ outputs the character A} @key[package] Char_IO @key[is] @key[new] Ada.Text_IO.Enumeration_IO(Character); Char_IO.Put('A'); --@RI{ outputs the character 'A', between apostrophes} @end{Example} The type Boolean is an enumeration type, hence Enumeration_IO can be instantiated for this type. @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0054],ARef=[AI95-00007-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to say Enumeration_IO can be instantiated with an integer type, not a float type.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Input-Output for Bounded Strings]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[The package Text_IO.Bounded_IO provides input-output in human-readable form for Bounded_Strings.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library package Text_IO.Bounded_IO has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Strings.Bounded; @key{generic} @key{with package} Bounded @key{is} @key{new} Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key{package} Ada.Text_IO.Bounded_IO @key{is}@ChildUnit{Parent=[Ada.Text_IO],Child=[Bounded_IO]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (Item : @key{in} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} (File : @key{in} File_Type) @key{return} Bounded.Bounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} @key{return} Bounded.Bounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (File : @key{in} File_Type; Item : @key{out} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (Item : @key{out} Bounded.Bounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Text_IO.Bounded_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an item of type Bounded_String, the following subprograms are provided:]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (File, Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (File : @key{in} File_Type; Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (File, Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (Item : @key{in} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (Bounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line (File : @key{in} File_Type) @key{return} Bounded.Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Returns Bounded.To_Bounded_String(Text_IO.Get_Line(File));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line @key{return} Bounded.Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Returns Bounded.To_Bounded_String(Text_IO.Get_Line);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (File : @key{in} File_Type; Item : @key{out} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line (File);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (Item : @key{out} Bounded.Bounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line;]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Text_IO.Bounded_IO is new.]} @end{Extend95} @LabeledAddedSubClause{Version=[2],Name=[Input-Output for Unbounded Strings]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The package Text_IO.Unbounded_IO provides input-output in human-readable form for Unbounded_Strings.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library package Text_IO.Unbounded_IO has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Strings.Unbounded; @key{package} Ada.Text_IO.Unbounded_IO @key{is}@ChildUnit{Parent=[Ada.Text_IO],Child=[Unbounded_IO]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put} (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Put_Line} (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} (File : @key{in} File_Type) @key{return} Strings.Unbounded.Unbounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Get_Line} @key{return} Strings.Unbounded.Unbounded_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (File : @key{in} File_Type; Item : @key{out} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Get_Line} (Item : @key{out} Strings.Unbounded.Unbounded_String);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{end} Ada.Text_IO.Unbounded_IO;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For an item of type Unbounded_String, the following subprograms are provided:]} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (File, Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put (Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (File : @key{in} File_Type; Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (File, Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Put_Line (Item : @key{in} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Text_IO.Put_Line (Strings.Unbounded.To_String(Item));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line (File : @key{in} File_Type) @key{return} Strings.Unbounded.Unbounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Returns Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line(File));]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{function} Get_Line @key{return} Strings.Unbounded.Unbounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Returns Strings.Unbounded.To_Unbounded_String(Text_IO.Get_Line);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (File : @key{in} File_Type; Item : @key{out} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line (File);]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key{procedure} Get_Line (Item : @key{out} Strings.Unbounded.Unbounded_String);]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Equivalent to Item := Get_Line;]} @end{DescribeCode} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Text_IO.Unbounded_IO is new.]} @end{Extend95} @LabeledRevisedClause{Version=[1],New=[Wide Text Input-Output and Wide Wide Text Input-Output],Old=[Wide Text Input-Output]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The @Chg{Version=[2],New=[packages],Old=[package]} Wide_Text_IO @Chg{Version=[2],New=[and Wide_Wide_Text_IO provide],Old=[provides]} facilities for input and output in human-readable form. Each file is read or written sequentially, as a sequence of wide characters @Chg{Version=[2],New=[(or wide wide characters) ],Old=[]}grouped into lines, and as a sequence of lines grouped into pages. @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @ChildUnit{Parent=[Ada],Child=[Wide_@!Text_IO]} The specification of package Wide_Text_IO is the same as that for Text_IO, except that in each Get, Look_Ahead, Get_Immediate, Get_Line, Put, and Put_Line @Chg{Version=[2],New=[subprogram],Old=[procedure]}, any occurrence of Character is replaced by Wide_Character, and any occurrence of String is replaced by Wide_String.@Chg{Version=[2],New=[ @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_@!Text_IO]} Nongeneric equivalents of Wide_Text_IO.Integer_IO and Wide_Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Text_IO, Ada.Long_@!Integer_@!Wide_Text_IO, Ada.Float_@!Wide_Text_IO, Ada.Long_@!Float_@!Wide_Text_IO.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @Chg{Version=[2],New=[ @ChildUnit{Parent=[Ada],Child=[Wide_Wide_@!Text_IO]} The specification of package Wide_Wide_Text_IO is the same as that for Text_IO, except that in each Get, Look_Ahead, Get_Immediate, Get_Line, Put, and Put_Line subprogram, any occurrence of Character is replaced by Wide_Wide_Character, and any occurrence of String is replaced by Wide_Wide_String. @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_Wide_@!Text_IO]} Nongeneric equivalents of Wide_Wide_Text_IO.Integer_IO and Wide_Wide_@!Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Wide_@!Text_IO, Ada.Long_@!Integer_@!Wide_Wide_@!Text_IO, Ada.Float_@!Wide_Wide_@!Text_IO, Ada.Long_@!Float_@!Wide_Wide_@!Text_IO.], Old=[ @ChildUnit{Parent=[Ada],Child=[Integer_@!Wide_@!Text_IO]} @ChildUnit{Parent=[Ada],Child=[Float_@!Wide_@!Text_IO]} Nongeneric equivalents of Wide_Text_IO.Integer_IO and Wide_Text_IO.@!Float_IO are provided (as for Text_IO) for each predefined numeric type, with names such as Ada.Integer_@!Wide_Text_IO, Ada.Long_@!Integer_@!Wide_Text_IO, Ada.Float_@!Wide_Text_IO, Ada.Long_@!Float_@!Wide_Text_IO.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00428-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0004-1],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Bounded_IO]} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Bounded_IO]} The specification of package Wide_Text_IO.Wide_@!Bounded_IO is the same as that for Text_IO.Bounded_IO, except that any occurrence of Bounded_String is replaced by @Chg{Version=[3],New=[Bounded_@!Wide_@!String],Old=[Wide_@!Bounded_@!String]}, and any occurrence of package Bounded is replaced by Wide_Bounded. The specification of package @Chg{Version=[3],New=[Wide_Wide_@!Text_IO.Wide_Wide_@!Bounded_IO], Old=[Wide_Wide_@!Text_IO.Wide_@!Bounded_IO]} is the same as that for Text_IO.@!Bounded_IO, except that any occurrence of Bounded_@!String is replaced by @Chg{Version=[3],New=[Bounded_@!Wide_Wide_@!String], Old=[Wide_Wide_@!Bounded_@!String]}, and any occurrence of package Bounded is replaced by Wide_Wide_@!Bounded.]} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[@ldquote@;package Bounded@rdquote refers to both the package Ada.Strings.Bounded and the formal package parameter named Bounded.]} @end{Honest} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0092-1]} @ChgAdded{Version=[2],Text=[ @ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Unbounded_IO]} @ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Unbounded_IO]} The specification of package Wide_Text_IO.@!Wide_Unbounded_IO is the same as that for Text_IO.@!Unbounded_IO, except that any occurrence of Unbounded_@!String is replaced by @Chg{Version=[3],New=[Unbounded_@!Wide_@!String],Old=[Wide_@!Unbounded_@!String]}, and any occurrence of package Unbounded is replaced by Wide_@!Unbounded. The specification of package Wide_Wide_Text_IO.Wide_Wide_@!Unbounded_IO is the same as that for Text_IO.Unbounded_IO, except that any occurrence of Unbounded_String is replaced by @Chg{Version=[3],New=[Unbounded_@!Wide_Wide_@!String], Old=[Wide_Wide_@!Unbounded_@!String]}, and any occurrence of package Unbounded is replaced by Wide_Wide_@!Unbounded.]} @end{StaticSem} @begin{Extend83} @Defn{extensions to Ada 83} Support for Wide_Character and Wide_String I/O is new in Ada 95. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO is new. Be glad it wasn't called Double_Wide_Text_IO (for use in trailer parks) or Really_Wide_Text_IO.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Packages Wide_Text_IO.Wide_Unbounded_IO and Wide_Wide_Text_IO.Wide_Wide_Unbounded_IO are also new.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00428-01]} @ChgAdded{Version=[2],Text=[Packages Wide_Text_IO.Wide_Bounded_IO and Wide_Wide_Text_IO.Wide_Wide_Bounded_IO are new as well.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0092-1]} @ChgAdded{Version=[3],Text=[@B<Correction>: Corrected the names of various entities in the above description. Since the previously named entities don't exist and the intent is obvious, this is just considered a presentation change.]} @end{DiffWord2005} @LabeledClause{Stream Input-Output} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} The packages Streams.Stream_IO, Text_IO.Text_Streams, @Chg{Version=[2], New=[],Old=[and ]}Wide_Text_IO.Text_Streams@Chg{Version=[2],New=[, and Wide_Wide_Text_IO.Text_Streams],Old=[]} provide stream-oriented operations on files. @end{Intro} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included package Wide_Wide_Text_IO.Text_Streams in this description.]} @end{Diffword95} @LabeledSubClause{The Package Streams.Stream_IO} @begin{Intro} @Defn{heterogeneous input-output} @Redundant[The subprograms in the child package Streams.Stream_IO provide control over stream files. Access to a stream file is either sequential, via a call on Read or Write to transfer an array of stream elements, or positional (if supported by the implementation for the given file), by specifying a relative index for an element. Since a stream file can be converted to a Stream_Access value, calling stream-oriented attribute subprograms of different element types with the same Stream_Access value provides heterogeneous input-output.] See @RefSecNum{Streams} for a general discussion of streams. @end{Intro} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The elements of a stream file are stream elements. If positioning is supported for the specified external file, a current index and current size are maintained for the file as described in @RefSecNum(Sequential and Direct Files). If positioning is not supported, a current index is not maintained, and the current size is implementation defined.@Defn2{Term=(Current index), Sec=(of an open stream file)}@Defn2{Term=(Current size),Sec=(of a stream file)}]} @ChgImpldef{Version=[1],Kind=[Added],Text=[@ChgAdded{Version=[1], Text=[Current size for a stream file for which positioning is not supported.]}]} @Leading@;The library package Streams.Stream_IO has the following declaration: @begin(example) @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0283-1]} @key(with) Ada.IO_Exceptions;@ChildUnit{Parent=[Ada.Streams],Child=[Stream_@!IO]} @key(package) Ada.Streams.Stream_IO @key(is)@Chg{Version=[3],New=[ @key(pragma) Preelaborate(Stream_IO);],Old=[]} @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Root_Stream_Type'Class; @key(type) @AdaTypeDefn{File_Type} @key(is) @key(limited) @key(private;) @key(type) @AdaTypeDefn{File_Mode} @key(is) (In_File, Out_File, Append_File); @key[type] @AdaTypeDefn{Count} @key[is] @key[range] 0 .. @RI[implementation-defined]; @key[subtype] @AdaSubtypeDefn{Name=[Positive_Count],Of=[Count]} @key[is] Count @key[range] 1 .. Count'Last; -- @RI(Index into file, in stream elements.) @key(procedure) @AdaSubDefn{Create} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode := Out_File; Name : @key(in) String := ""; Form : @key(in) String := ""); @key(procedure) @AdaSubDefn{Open} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode; Name : @key(in) String; Form : @key(in) String := ""); @key(procedure) @AdaSubDefn{Close} (File : @key(in) @key(out) File_Type); @key(procedure) @AdaSubDefn{Delete} (File : @key(in) @key(out) File_Type); @key(procedure) @AdaSubDefn{Reset} (File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode); @key(procedure) @AdaSubDefn{Reset} (File : @key(in) @key(out) File_Type); @key(function) @AdaSubDefn{Mode} (File : @key(in) File_Type) @key(return) File_Mode; @key(function) @AdaSubDefn{Name} (File : @key(in) File_Type) @key(return) String; @key(function) @AdaSubDefn{Form} (File : @key(in) File_Type) @key(return) String; @key(function) @AdaSubDefn{Is_Open} (File : @key(in) File_Type) @key(return) Boolean; @key(function) @AdaSubDefn{End_Of_File} (File : @key(in) File_Type) @key(return) Boolean; @key(function) @AdaSubDefn{Stream} (File : @key(in) File_Type) @key(return) Stream_Access; -- @RI(Return stream access for use with T'Input and T'Output) @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Read array of stream elements from file) @key(procedure) @AdaSubDefn{Read} (File : @key(in) File_Type; Item : @key(out) Stream_Element_Array; Last : @key(out) Stream_Element_Offset; From : @key(in) Positive_Count); @key(procedure) @AdaSubDefn{Read} (File : @key(in) File_Type; Item : @key(out) Stream_Element_Array; Last : @key(out) Stream_Element_Offset); @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Write array of stream elements into file) @key(procedure) @AdaSubDefn{Write} (File : @key(in) File_Type; Item : @key(in) Stream_Element_Array; To : @key(in) Positive_Count); @key(procedure) @AdaSubDefn{Write} (File : @key(in) File_Type; Item : @key(in) Stream_Element_Array); @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] -- @RI(Operations on position within file) @key[procedure] @AdaSubDefn{Set_Index}(File : @key[in] File_Type; To : @key[in] Positive_Count); @key[function] @AdaSubDefn{Index}(File : @key[in] File_Type) @key[return] Positive_Count; @key[function] @AdaSubDefn{Size} (File : @key[in] File_Type) @key[return] Count; @key(procedure) @AdaSubDefn{Set_Mode}(File : @key(in) @key(out) File_Type; Mode : @key(in) File_Mode); @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0051],ARef=[AI95-00057-01]} @key(procedure) @AdaSubDefn{Flush}(File : @key(in) @Chg{New=[],Old=[@key(out) ]}File_Type); -- @RI(exceptions) @AdaExcDefn{Status_Error} : @key(exception) @key(renames) IO_Exceptions.Status_Error; @AdaExcDefn{Mode_Error} : @key(exception) @key(renames) IO_Exceptions.Mode_Error; @AdaExcDefn{Name_Error} : @key(exception) @key(renames) IO_Exceptions.Name_Error; @AdaExcDefn{Use_Error} : @key(exception) @key(renames) IO_Exceptions.Use_Error; @AdaExcDefn{Device_Error} : @key(exception) @key(renames) IO_Exceptions.Device_Error; @AdaExcDefn{End_Error} : @key(exception) @key(renames) IO_Exceptions.End_Error; @AdaExcDefn{Data_Error} : @key(exception) @key(renames) IO_Exceptions.Data_Error; @key[private] ... -- @RI{not specified by the language} @key(end) Ada.Streams.Stream_IO; @end(example) @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type File_Type needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00283-01]} The subprograms @Chg{Version=[2],New=[given in subclause @RefSecNum(File Management) for the control of external files (],Old=[]}Create, Open, Close, Delete, Reset, Mode, Name, Form,@Chg{Version=[2],New=[ and],Old=[]} Is_Open@Chg{Version=[2],New=[) are available for stream files], Old=[, and End_of_File have the same effect as the corresponding subprograms in Sequential_IO (see @RefSecNum(File Management))]}. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00283-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The End_Of_File function:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Propagates Mode_Error if the mode of the file is not In_File;]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If positioning is supported for the given external file, the function returns True if the current index exceeds the size of the external file; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False;]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If positioning is not supported for the given external file, the function returns True if no more elements can be read from the given file; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @end{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00085-01]} @ChgAdded{Version=[1],Text=[The Set_Mode procedure @Chg{Version=[2],New=[sets],Old=[changes]} the mode of the file. If the new mode is Append_File, the file is positioned to its end; otherwise, the position in the file is unchanged.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The Flush procedure synchronizes the external file with the internal file (by flushing any internal buffers) without closing the file or changing the position. Mode_Error is propagated if the mode of the file is In_File.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0056],ARef=[AI95-00001-01]} The Stream function returns a Stream_Access result from a File_Type object, thus allowing the stream-oriented attributes Read, Write, Input, and Output to be used on the same file for multiple types. @Chg{New=[Stream propagates Status_Error if File is not open.],Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} The procedures Read and Write are equivalent to the corresponding operations in the package Streams. Read propagates Mode_Error if the mode of File is not In_File. Write propagates Mode_Error if the mode of File is not Out_File or Append_File. The Read procedure with a Positive_Count parameter starts reading at the specified index. The Write procedure with a Positive_Count parameter starts writing at the specified index.@Chg{Version=[2],New=[ For a file that supports positioning, Read without a Positive_Count parameter starts reading at the current index, and Write without a Positive_Count parameter starts writing at the current index.],Old=[]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[The Size function returns the current size of the file.]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0055],ARef=[AI95-00026-01]} The Index function returns the current @Chg{New=[],Old=[file ]}index@Chg{New=[], Old=[, as a count (in stream elements) from the beginning of the file. The position of the first element in the file is 1]}. @begin{Ramification} @ChgRef{Version=[1],Kind=[Deleted]} @ChgNote{This ramification is now part of the official wording.} @ChgDeleted{Version=[1],Text=[The notion of Index for Stream_IO is analogous to that of Index in Direct_IO, except that the former is measured in Stream_Element units, whereas the latter is in terms of Element_Type values.]} @end{Ramification} The Set_Index procedure sets the current index to the specified value. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Type=[Leading],Text=[If positioning is supported for the external file, the current index is maintained as follows:]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Open and Create, if the Mode parameter is Append_File, the current index is set to the current size of the file plus one; otherwise, the current index is set to one.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Reset, if the Mode parameter is Append_File, or no Mode parameter is given and the current mode is Append_File, the current index is set to the current size of the file plus one; otherwise, the current index is set to one.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Set_Mode, if the new mode is Append_File, the current index is set to current size plus one; otherwise, the current index is unchanged.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Read and Write without a Positive_Count parameter, the current index is incremented by the number of stream elements read or written.]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgAdded{Version=[1],Text=[For Read and Write with a Positive_Count parameter, the value of the current index is set to the value of the Positive_Count parameter plus the number of stream elements read or written.]} @end{Itemize} If positioning is not supported for the given file, then a call of Index or Set_Index propagates Use_Error. Similarly, a call of Read or Write with a Positive_Count parameter propagates Use_Error. @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[It is permissible for an implementation to implement mode Append_File using the Unix append mode (the O_APPEND bit). Such an implementation does not support positioning when the mode is Append_File, and therefore the operations listed above must raise Use_Error. This is acceptable as there is no requirement that any particular file support positioning; therefore it is acceptable that a file support positioning when opened with mode Out_File, and the same file not support positioning when opened with mode Append_File. But it is not acceptable for a file to support positioning (by allowing the above operations), but to do something other than the defined semantics (that is, always write at the end, even when explicitly commanded to write somewhere else).]} @end{ImplNote} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 34 through 36 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Size function returns the current size of the file, in stream elements.]} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Set_Mode procedure changes the mode of the file. If the new mode is Append_File, the file is positioned to its end; otherwise, the position in the file is unchanged.]} @ChgRef{Version=[1],Kind=[DeletedNoDelMsg],Ref=[8652/0055],ARef=[AI95-00026-01]} @ChgDeleted{Version=[1],Text=[The Flush procedure synchronizes the external file with the internal file (by flushing any internal buffers) without closing the file or changing the position. Mode_Error is propagated if the mode of the file is In_File.]} @end{StaticSem} @begin{Erron} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0056],ARef=[AI95-00001-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the File_Type object passed to the Stream function is later closed or finalized, and the stream-oriented attributes are subsequently called (explicitly or implicitly) on the Stream_Access value returned by Stream, execution is erroneous. This rule applies even if the File_Type object was opened again after it had been closed.]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[These rules are analogous to the rule for the result of the Current_Input, Current_Output, and Current_Error functions. These rules make it possible to represent a value of (some descendant of) Root_Stream_Type which represents a file as an access value, with a null value corresponding to a closed file.]} @end{Reason} @end{Erron} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00283-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @b[Amendment Correction:] The description of the subprograms for managing files was corrected so that they do not require truncation of the external file @em a stream file is not a sequential file. An Ada 95 program that expects truncation of the stream file @Chg{Version=[3],New=[might],Old=[may]} not work under Ada 2005. Note that the Ada 95 standard was ambiguous on this point (the normative wording seemed to require truncation, but didn't explain where; the AARM notes seemed to expect behavior like Direct_IO), and implementations varied widely. Therefore, as a practical matter, code that depends on stream truncation @Chg{Version=[3],New=[might],Old=[may]} not work even in Ada 95; deleting the file before opening it provides truncation that works in both Ada 95 and Ada 2005.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @B[Amendment Correction:] Stream_IO.File_Type is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and File_Type does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in File_Type, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0051],ARef=[AI95-00057-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter mode of Flush; otherwise it could not be used on Standard_Output.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0055],ARef=[AI95-00026-01],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Added wording to describe the effects of the various operations on the current index. The Amendment adds an explanation of the use of current index for Read and Write.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0056],ARef=[AI95-00001-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Stream can raise Status_Error, and clarified that using a Stream_Access whose file has been closed is erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00085-01]} @ChgAdded{Version=[2],Text=[Clarified that Set_Mode can be called with the current mode.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0283-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Package Ada.Streams.Stream_IO is now preelaborated, allowing it to be used in more contexts (including in distributed systems). Note that is @i<not> a remote types package; File_Type objects cannot be passed between partitions.]} @end{Extend2005} @LabeledSubClause{The Package Text_IO.Text_Streams} @begin{Intro} The package Text_IO.Text_Streams provides a function for treating a text file as a stream. @end{Intro} @begin{StaticSem} @Leading@;The library package Text_IO.Text_Streams has the following declaration: @begin{example} @key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class; @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Text_IO.Text_Streams; @end{example} The Stream function has the same effect as the corresponding function in Streams.Stream_IO. @end{StaticSem} @begin[Notes] The ability to obtain a stream for a text file allows Current_Input, Current_Output, and Current_Error to be processed with the functionality of streams, including the mixing of text and binary input-output, and the mixing of binary input-output for different types. Performing operations on the stream associated with a text file does not affect the column, line, or page counts. @end[Notes] @LabeledSubClause{The Package Wide_Text_IO.Text_Streams} @begin{Intro} The package Wide_Text_IO.Text_Streams provides a function for treating a wide text file as a stream. @end{Intro} @begin{StaticSem} @Leading@;The library package Wide_Text_IO.Text_Streams has the following declaration: @begin{example} @key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Wide_@!Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Wide_Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class; @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Wide_Text_IO.Text_Streams; @end{example} The Stream function has the same effect as the corresponding function in Streams.Stream_IO. @end{StaticSem} @LabeledAddedSubClause{Version=[2],Name=[The Package Wide_Wide_Text_IO.Text_Streams]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The package Wide_Wide_Text_IO.Text_Streams provides a function for treating a wide wide text file as a stream.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Leading@;The library package Wide_Wide_Text_IO.Text_Streams has the following declaration:]} @begin{example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key[with] Ada.Streams;@ChildUnit{Parent=[Ada.Wide_Wide_@!Text_IO],Child=[Text_@!Streams]} @key[package] Ada.Wide_Wide_Text_IO.Text_Streams @key[is] @key[type] @AdaTypeDefn{Stream_Access} @key[is] @key[access] @key[all] Streams.Root_Stream_Type'Class;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Stream} (File : @key[in] File_Type) @key[return] Stream_Access; @key[end] Ada.Wide_Wide_Text_IO.Text_Streams;]} @end{example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[The Stream function has the same effect as the corresponding function in Streams.Stream_IO.]} @end{StaticSem} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Wide_Wide_Text_IO.Text_Streams is new.]} @end{Extend95} @LabeledClause{Exceptions in Input-Output} @begin{Intro} The package IO_Exceptions defines the exceptions needed by the predefined input-output packages. @end{Intro} @begin{StaticSem} @Leading@;The library package IO_Exceptions has the following declaration: @begin{Example} @key[package] Ada.IO_Exceptions @key[is]@ChildUnit{Parent=[Ada],Child=[IO_Exceptions]} @key[pragma] Pure(IO_Exceptions); @AdaExcDefn{Status_Error} : @key[exception]; @AdaExcDefn{Mode_Error} : @key[exception]; @AdaExcDefn{Name_Error} : @key[exception]; @AdaExcDefn{Use_Error} : @key[exception]; @AdaExcDefn{Device_Error} : @key[exception]; @AdaExcDefn{End_Error} : @key[exception]; @AdaExcDefn{Data_Error} : @key[exception]; @AdaExcDefn{Layout_Error} : @key[exception]; @key[end] Ada.IO_Exceptions; @end{Example} If more than one error condition exists, the corresponding exception that appears earliest in the following list is the one that is propagated. The exception Status_Error is propagated by an attempt to operate upon a file that is not open, and by an attempt to open a file that is already open. The exception Mode_Error is propagated by an attempt to read from, or test for the end of, a file whose current mode is Out_File or Append_File, and also by an attempt to write to a file whose current mode is In_File. In the case of Text_IO, the exception Mode_Error is also propagated by specifying a file whose current mode is Out_File or Append_File in a call of Set_Input, Skip_Line, End_Of_Line, Skip_Page, or End_Of_Page; and by specifying a file whose current mode is In_File in a call of Set_Output, Set_Line_Length, Set_Page_Length, Line_Length, Page_Length, New_Line, or New_Page. The exception Name_Error is propagated by a call of Create or Open if the string given for the parameter Name does not allow the identification of an external file. For example, this exception is propagated if the string is improper, or, alternatively, if either none or more than one external file corresponds to the string. The exception Use_Error is propagated if an operation is attempted that is not possible for reasons that depend on characteristics of the external file. For example, this exception is propagated by the procedure Create, among other circumstances, if the given mode is Out_File but the form specifies an input only device, if the parameter Form specifies invalid access rights, or if an external file with the given name already exists and overwriting is not allowed. The exception Device_Error is propagated if an input-output operation cannot be completed because of a malfunction of the underlying system. The exception End_Error is propagated by an attempt to skip (read past) the end of a file. The exception Data_Error can be propagated by the procedure Read (or by the Read attribute) if the element read cannot be interpreted as a value of the required subtype. This exception is also propagated by a procedure Get (defined in the package Text_IO) if the input character sequence fails to satisfy the required syntax, or if the value input does not belong to the range of the required subtype. The exception Layout_Error is propagated (in text input-output) by Col, Line, or Page if the value returned exceeds Count'Last. The exception Layout_Error is also propagated on output by an attempt to set column or line numbers in excess of specified maximum line or page lengths, respectively (excluding the unbounded cases). It is also propagated by an attempt to Put too many characters to a string. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[These exceptions are also propagated by various other language-defined packages and operations, see the definition of those entities for other reasons that these exceptions are propagated.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is based in Ada 95. Later versions of Ada (starting with Technical Corrigendum 1) have added a number of additional places and reasons that cause these exceptions. In particular, TC1 says that stream attributes need to raise End_Error in some circumstances; Amendment 1 adds Ada.Directories and a number of new places and reasons that Name_Error and Use_Error are raised. There are more. We don't want to try to update this text (or even this note!) for every possible reason and place that might raise one of these exceptions, so we add this blanket statement.]} @end{Reason} @end{StaticSem} @begin{DocReq} The implementation shall document the conditions under which Name_Error, Use_Error and Device_Error are propagated. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The conditions under which Io_Exceptions.Name_Error, Io_Exceptions.Use_Error, and Io_Exceptions.Device_Error are propagated.]}]} @end{DocReq} @begin{ImplPerm} If the associated check is too complex, an implementation need not propagate Data_Error as part of a procedure Read (or the Read attribute) if the value read cannot be interpreted as a value of the required subtype. @begin{Ramification} An example where the implementation may choose not to perform the check is an enumeration type with a representation clause with @lquotes@;holes@rquotes@; in the range of internal codes.@end{ramification} @end{ImplPerm} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)}@Redundant[If the element read by the procedure Read (or by the Read attribute) cannot be interpreted as a value of the required subtype, but this is not detected and Data_Error is not propagated, then the resulting value can be abnormal, and subsequent references to the value can lead to erroneous execution, as explained in @RefSecNum{Data Validity}. @PDefn{normal state of an object} @PDefn{abnormal state of an object}] @end{Erron} @LabeledClause{File Sharing} @begin{RunTime} @PDefn{unspecified} @Leading@;It is not specified by the language whether the same external file can be associated with more than one file object. If such sharing is supported by the implementation, the following effects are defined: @begin{itemize} Operations on one text file object do not affect the column, line, and page numbers of any other file object. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0057],ARef=[AI95-00050-01]} @ChgDeleted{Version=[1],Text=[Standard_Input and Standard_Output are associated with distinct external files, so operations on one of these files cannot affect operations on the other file. In particular, reading from Standard_Input does not affect the current page, line, and column numbers for Standard_Output, nor does writing to Standard_Output affect the current page, line, and column numbers for Standard_Input.]} For direct and stream files, the current index is a property of each file object; an operation on one file object does not affect the current index of any other file object. For direct and stream files, the current size of the file is a property of the external file. @end{itemize} All other effects are identical. @end{RunTime} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0057],ARef=[AI95-00050-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Removed the incorrect statement that the external files associated with the standard input, standard output, and standard error files are distinct.]} @end{DiffWord95} �������������������org.adaic.arm_form/source_2012/pre_locales.mss������������������������������������������������������0000755�0001752�0001001�00000011116�11776511201�020432� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_locales.mss,v $ } @comment{ $Revision: 1.6 $ $Date: 2011/11/01 05:34:04 $ $Author: randy $ } @Part(predefenviron, Root="ada.mss") @Comment{$Date: 2011/11/01 05:34:04 $} @LabeledAddedClause{Version=[3],Name=[The Package Locales]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[A @i{locale}@Defn{locale} identifies a geopolitical place or region and its associated language, which can be used to determine other internationalization-related characteristics.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library package Locales has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{package} Ada.Locales @key{is}@ChildUnit{Parent=[Ada],Child=[Locales]} @key{pragma} Preelaborate(Locales); @key{pragma} Remote_Types(Locales);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Language_Code} @key[is array] (1 .. 3) @key[of] Character @key[range] 'a' .. 'z'; @key[type] @AdaTypeDefn{Country_Code} @key[is array] (1 .. 2) @key[of] Character @key[range] 'A' .. 'Z';]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{Language_Unknown} : @key[constant] Language_Code := "und"; @AdaObjDefn{Country_Unknown} : @key[constant] Country_Code := "ZZ";]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Language} @key[return] Language_Code; @key[function] @AdaSubDefn{Country} @key[return] Country_Code;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Locales;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2],ARef=[AI05-0233-1]} @ChgAdded{Version=[3],Text=[The @i{active locale}@Defn{active locale}@Defn2{Term=[locale],Sec=[active]} is the locale associated with the partition of the current task.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0233-1]} @ChgAdded{Version=[3],Text=[Some environments define both a system locale and the locale of the current user. For such environments, the active locale is that of current user if any; otherwise (as in a partition running on a server without a user), the system locale should be used.]} @end{ImplNote} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2]} @ChgAdded{Version=[3],Text=[Language_Code is a lower-case string representation of an ISO 639-3 alpha-3 code that identifies a language.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Some common language codes are: "eng" @en English; "fra" @en French; "deu" @en German; "zho" @en Chinese. These are the same codes as used by POSIX systems. We considered including constants for the most common languages, but that was rejected as the likely source of continual arguments about the constant names and which languages are important enough to include.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2]} @ChgAdded{Version=[3],Text=[Country_Code is an upper-case string representation of an ISO 3166-1 alpha-2 code that identifies a country.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Some common country codes are: "CA" @en Canada; "FR" @en France; "DE" @en Germany; "IT" @en Italy; "ES" @en Spain; "GB" @en United Kingdom; "US" @en United States. These are the same codes as used by POSIX systems. We didn't include any country constants for the same reasons that we didn't include any language constants.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Function Language returns the code of the language associated with the active locale. If the Language_Code associated with the active locale cannot be determined from the environment, then Language returns Language_Unknown.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2],ARef=[AI05-0248-1]} @ChgAdded{Version=[3],Text=[Function Country returns the code of the country associated with the active locale. If the Country_Code associated with the active locale cannot be determined from the environment, then Country returns Country_Unknown.]} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0127-2],ARef=[AI05-0233-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Package Locales is new.]} @end{Extend2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_math.mss���������������������������������������������������������0000755�0001752�0001001�00000124006�11776511201�017744� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_math.mss,v $ } @comment{ $Revision: 1.43 $ $Date: 2012/02/19 01:58:37 $ $Author: randy $ } @Part(predefmath, Root="ada.mss") @Comment{$Date: 2012/02/19 01:58:37 $} @LabeledClause{The Numerics Packages} @begin{Intro} The library package Numerics is the parent of several child units that provide facilities for mathematical computation. One child, the generic package Generic_Elementary_Functions, is defined in @RefSecNum{Elementary Functions}, together with nongeneric equivalents; two others, the package Float_Random and the generic package Discrete_Random, are defined in @RefSecNum{Random Number Generation}. Additional (optional) children are defined in @RefSec{Numerics}. @end{Intro} @begin{StaticSem} @ChgRef{Version=[1], Kind=[Deleted]} @ChgDeleted[Version=[1],Text=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00388-01]} @key[package] Ada.Numerics @key[is]@ChildUnit{Parent=[Ada],Child=[Numerics]} @key[pragma] Pure(Numerics); @AdaExcDefn{Argument_Error} : @key[exception]; @AdaObjDefn{Pi} : @key[constant] := 3.14159_26535_89793_23846_26433_83279_50288_41971_69399_37511;@Chg{Version=[2],New=[ @pi : @key[constant] := Pi;],Old=[]} @AdaObjDefn{e} : @key[constant] := 2.71828_18284_59045_23536_02874_71352_66249_77572_47093_69996; @key[end] Ada.Numerics; @end{Example} The Argument_Error exception is raised by a subprogram in a child unit of Numerics to signal that one or more of the actual subprogram parameters are outside the domain of the corresponding mathematical function. @end{StaticSem} @begin{ImplPerm} The implementation may specify the values of Pi and e to a larger number of significant digits. @begin{Reason} 51 digits seem more than adequate for all present computers; converted to binary, the values given above are accurate to more than 160 bits. Nevertheless, the permission allows implementations to accommodate unforeseen hardware advances. @end{Reason} @end{ImplPerm} @begin{Extend83} @Defn{extensions to Ada 83} Numerics and its children were not predefined in Ada 83. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00388-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The alternative declaration of @pi is new.]} @end{Extend95} @LabeledSubClause{Elementary Functions} @begin{Intro} Implementation-defined approximations to the mathematical functions known as the @lquotes@;elementary functions@rquotes@; are provided by the subprograms in Numerics.@!Generic_@!Elementary_@!Functions. Nongeneric equivalents of this generic package for each of the predefined floating point types are also provided as children of Numerics. @ImplDef{The accuracy actually achieved by the elementary functions.} @end{Intro} @begin{StaticSem} @Leading@;The generic library package Numerics.Generic_Elementary_Functions has the following declaration: @begin{Example} @key{generic} @key{type} Float_Type @key{is} @key{digits} <>; @ChildUnit{Parent=[Ada.Numerics],Child=[Generic_@!Elementary_@!Functions]} @key{package} Ada.Numerics.Generic_Elementary_Functions @key{is} @key[pragma] Pure(Generic_Elementary_Functions); @key{function} @AdaSubDefn{Sqrt} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Log} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Log} (X, Base : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Exp} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} "**" (Left, Right : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sin} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sin} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cos} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cos} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tan} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tan} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cot} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cot} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsin} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsin} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccos} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccos} (X, Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctan} (Y : Float_Type'Base; X : Float_Type'Base := 1.0) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctan} (Y : Float_Type'Base; X : Float_Type'Base := 1.0; Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccot} (X : Float_Type'Base; Y : Float_Type'Base := 1.0) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccot} (X : Float_Type'Base; Y : Float_Type'Base := 1.0; Cycle : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Sinh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Cosh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Tanh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Coth} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arcsinh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccosh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arctanh} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{function} @AdaSubDefn{Arccoth} (X : Float_Type'Base) @key{return} Float_Type'Base; @key{end} Ada.Numerics.Generic_Elementary_Functions; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChildUnit{Parent=[Ada.Numerics],Child=[Elementary_@!Functions]} The library package Numerics.Elementary_Functions @Chg{New=[is declared pure and ],Old=[]}defines the same subprograms as Numerics.@!Generic_@!Elementary_@!Functions, except that the predefined type Float is systematically substituted for Float_Type'Base throughout. Nongeneric equivalents of Numerics.@!Generic_@!Elementary_@!Functions for each of the other predefined floating point types are defined similarly, with the names Numerics.@!Short_@!Elementary_@!Functions, Numerics.@!Long_@!Elementary_@!Functions, etc. @begin{Reason} The nongeneric equivalents are provided to allow the programmer to construct simple mathematical applications without being required to understand and use generics. @end{Reason} The functions have their usual mathematical meanings. When the Base parameter is specified, the Log function computes the logarithm to the given base; otherwise, it computes the natural logarithm. When the Cycle parameter is specified, the parameter X of the forward trigonometric functions (Sin, Cos, Tan, and Cot) and the results of the inverse trigonometric functions (Arcsin, Arccos, Arctan, and Arccot) are measured in units such that a full cycle of revolution has the given value; otherwise, they are measured in radians. @Leading@;The computed results of the mathematically multivalued functions are rendered single-valued by the following conventions, which are meant to imply the principal branch: @begin{Itemize} The results of the Sqrt and Arccosh functions and that of the exponentiation operator are nonnegative. The result of the Arcsin function is in the quadrant containing the point (1.0, @i[x]), where @i[x] is the value of the parameter X. This quadrant is I or IV; thus, the range of the Arcsin function is approximately @en@Pi/2.0 to @Pi/2.0 (@en@R[Cycle]/4.0 to @R[Cycle]/4.0, if the parameter Cycle is specified). The result of the Arccos function is in the quadrant containing the point (@i{x}, 1.0), where @i[x] is the value of the parameter X. This quadrant is I or II; thus, the Arccos function ranges from 0.0 to approximately @Pi (@R[Cycle]/2.0, if the parameter Cycle is specified). The results of the Arctan and Arccot functions are in the quadrant containing the point (@i[x], @i[y]), where @i[x] and @i[y] are the values of the parameters X and Y, respectively. This may be any quadrant (I through IV) when the parameter X (resp., Y) of Arctan (resp., Arccot) is specified, but it is restricted to quadrants I and IV (resp., I and II) when that parameter is omitted. Thus, the range when that parameter is specified is approximately @en@Pi to @Pi (@en@R[Cycle]/2.0 to @R[Cycle]/2.0, if the parameter Cycle is specified); when omitted, the range of Arctan (resp., Arccot) is that of Arcsin (resp., Arccos), as given above. When the point (@i[x], @i[y]) lies on the negative x-axis, the result approximates @begin{Itemize} @Pi (resp., @en@Pi) when the sign of the parameter Y is positive (resp., negative), if Float_Type'Signed_Zeros is True; @Pi, if Float_Type'Signed_Zeros is False. @end{Itemize} @end{Itemize} (In the case of the inverse trigonometric functions, in which a result lying on or near one of the axes may not be exactly representable, the approximation inherent in computing the result may place it in an adjacent quadrant, close to but on the wrong side of the axis.) @end{StaticSem} @begin{RunTime} @Leading@;The exception Numerics.Argument_Error is raised, signaling a parameter value outside the domain of the corresponding mathematical function, in the following cases: @begin{Itemize} by any forward or inverse trigonometric function with specified cycle, when the value of the parameter Cycle is zero or negative; by the Log function with specified base, when the value of the parameter Base is zero, one, or negative; by the Sqrt and Log functions, when the value of the parameter X is negative; by the exponentiation operator, when the value of the left operand is negative or when both operands have the value zero; by the Arcsin, Arccos, and Arctanh functions, when the absolute value of the parameter X exceeds one; by the Arctan and Arccot functions, when the parameters X and Y both have the value zero; by the Arccosh function, when the value of the parameter X is less than one; and by the Arccoth function, when the absolute value of the parameter X is less than one. @end{Itemize} @Leading@IndexCheck{Division_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} The exception Constraint_Error is raised, signaling a pole of the mathematical function (analogous to dividing by zero), in the following cases, provided that Float_Type'Machine_Overflows is True: @begin{Itemize} by the Log, Cot, and Coth functions, when the value of the parameter X is zero; by the exponentiation operator, when the value of the left operand is zero and the value of the exponent is negative; by the Tan function with specified cycle, when the value of the parameter X is an odd multiple of the quarter cycle; by the Cot function with specified cycle, when the value of the parameter X is zero or a multiple of the half cycle; and by the Arctanh and Arccoth functions, when the absolute value of the parameter X is one. @end{Itemize} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} @redundant[Constraint_Error can also be raised when a finite result overflows (see @RefSecNum{Accuracy Requirements for the Elementary Functions}); this may occur for parameter values sufficiently @i{near} poles, and, in the case of some of the functions, for parameter values with sufficiently large magnitudes.]@PDefn{unspecified} When Float_Type'Machine_Overflows is False, the result at poles is unspecified. @begin{Reason} The purpose of raising Constraint_Error (rather than Numerics.Argument_Error) at the poles of a function, when Float_Type'Machine_Overflows is True, is to provide continuous behavior as the actual parameters of the function approach the pole and finally reach it. @end{Reason} @begin{Discussion} It is anticipated that an Ada binding to IEC 559:1989 will be developed in the future. As part of such a binding, the Machine_Overflows attribute of a conformant floating point type will be specified to yield False, which will permit both the predefined arithmetic operations and implementations of the elementary functions to deliver signed infinities (and set the overflow flag defined by the binding) instead of raising Constraint_Error in overflow situations, when traps are disabled. Similarly, it is appropriate for the elementary functions to deliver signed infinities (and set the zero-divide flag defined by the binding) instead of raising Constraint_Error at poles, when traps are disabled. Finally, such a binding should also specify the behavior of the elementary functions, when sensible, given parameters with infinite values. @end{Discussion} When one parameter of a function with multiple parameters represents a pole and another is outside the function's domain, the latter takes precedence (i.e., Numerics.Argument_Error is raised). @end{RunTime} @begin{ImplReq} In the implementation of Numerics.Generic_Elementary_Functions, the range of intermediate values allowed during the calculation of a final result shall not be affected by any range constraint of the subtype Float_Type. @begin{ImplNote} Implementations of Numerics.Generic_Elementary_Functions written in Ada should therefore avoid declaring local variables of subtype Float_Type; the subtype Float_Type'Base should be used instead. @end{ImplNote} @Leading@Defn2{Term=[prescribed result], Sec=[for the evaluation of an elementary function]} In the following cases, evaluation of an elementary function shall yield the @i{prescribed result}, provided that the preceding rules do not call for an exception to be raised: @begin{Itemize} When the parameter X has the value zero, the Sqrt, Sin, Arcsin, Tan, Sinh, Arcsinh, Tanh, and Arctanh functions yield a result of zero, and the Exp, Cos, and Cosh functions yield a result of one. When the parameter X has the value one, the Sqrt function yields a result of one, and the Log, Arccos, and Arccosh functions yield a result of zero. When the parameter Y has the value zero and the parameter X has a positive value, the Arctan and Arccot functions yield a result of zero. The results of the Sin, Cos, Tan, and Cot functions with specified cycle are exact when the mathematical result is zero; those of the first two are also exact when the mathematical result is @PorM 1.0. Exponentiation by a zero exponent yields the value one. Exponentiation by a unit exponent yields the value of the left operand. Exponentiation of the value one yields the value one. Exponentiation of the value zero yields the value zero. @end{Itemize} Other accuracy requirements for the elementary functions, which apply only in implementations conforming to the Numerics Annex, and then only in the @lquotes@;strict@rquotes@; mode defined there (see @RefSecNum{Numeric Performance Requirements}), are given in @RefSecNum{Accuracy Requirements for the Elementary Functions}. @Leading@;When Float_Type'Signed_Zeros is True, the sign of a zero result shall be as follows: @begin{itemize} A prescribed zero result delivered @i{at the origin} by one of the odd functions (Sin, Arcsin, Sinh, Arcsinh, Tan, Arctan or Arccot as a function of Y when X is fixed and positive, Tanh, and Arctanh) has the sign of the parameter X (Y, in the case of Arctan or Arccot). A prescribed zero result delivered by one of the odd functions @i{away from the origin}, or by some other elementary function, has an implementation-defined sign. @ImplDef{The sign of a zero result from some of the operators or functions in Numerics.Generic_Elementary_Functions, when Float_Type'Signed_Zeros is True.} @redundant[A zero result that is not a prescribed result (i.e., one that results from rounding or underflow) has the correct mathematical sign.] @begin{Reason} This is a consequence of the rules specified in IEC 559:1989 as they apply to underflow situations with traps disabled. @end{Reason} @end{itemize} @end{ImplReq} @begin{ImplPerm} The nongeneric equivalent packages may, but need not, be actual instantiations of the generic package for the appropriate predefined type. @end{ImplPerm} @begin{DiffWord83} @Leading@;The semantics of Numerics.Generic_Elementary_Functions differs from Generic_Elementary_Functions as defined in ISO/IEC DIS 11430 (for Ada 83) in the following ways: @begin{itemize} The generic package is a child unit of the package defining the Argument_Error exception. DIS 11430 specified names for the nongeneric equivalents, if provided. Here, those nongeneric equivalents are required. Implementations are not allowed to impose an optional restriction that the generic actual parameter associated with Float_Type be unconstrained. (In view of the ability to declare variables of subtype Float_Type'Base in implementations of Numerics.Generic_Elementary_Functions, this flexibility is no longer needed.) The sign of a prescribed zero result at the origin of the odd functions is specified, when Float_Type'Signed_Zeros is True. This conforms with recommendations of Kahan and other numerical analysts. The dependence of Arctan and Arccot on the sign of a parameter value of zero is tied to the value of Float_Type'Signed_Zeros. Sqrt is prescribed to yield a result of one when its parameter has the value one. This guarantee makes it easier to achieve certain prescribed results of the complex elementary functions (see @RefSec{Complex Elementary Functions}). Conformance to accuracy requirements is conditional. @end{itemize} @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0020],ARef=[AI95-00126-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Explicitly stated that the nongeneric equivalents of Generic_Elementary_Functions are pure.]} @end{DiffWord95} @LabeledSubClause{Random Number Generation} @begin{Intro} @redundant[Facilities for the generation of pseudo-random floating point numbers are provided in the package Numerics.Float_Random; the generic package Numerics.Discrete_Random provides similar facilities for the generation of pseudo-random integers and pseudo-random values of enumeration types. @Defn{random number} For brevity, pseudo-random values of any of these types are called @i{random numbers}. Some of the facilities provided are basic to all applications of random numbers. These include a limited private type each of whose objects serves as the generator of a (possibly distinct) sequence of random numbers; a function to obtain the @lquotes@;next@rquotes@; random number from a given sequence of random numbers (that is, from its generator); and subprograms to initialize or reinitialize a given generator to a time-dependent state or a state denoted by a single integer. Other facilities are provided specifically for advanced applications. These include subprograms to save and restore the state of a given generator; a private type whose objects can be used to hold the saved state of a generator; and subprograms to obtain a string representation of a given generator state, or, given such a string representation, the corresponding state.] @begin{Discussion} These facilities support a variety of requirements ranging from repeatable sequences (for debugging) to unique sequences in each execution of a program. @end{Discussion} @end{Intro} @begin{StaticSem} @Leading@;The library package Numerics.Float_Random has the following declaration: @begin{Example} @key[package] Ada.Numerics.Float_Random @key[is]@ChildUnit{Parent=[Ada.Numerics],Child=[Float_@!Random]} -- @RI{Basic facilities} @key[type] @AdaTypeDefn{Generator} @key[is] @key[limited] @key[private]; @key[subtype] @AdaSubtypeDefn{Name=[Uniformly_Distributed],Of=[Float]} @key[is] Float @key[range] 0.0 .. 1.0; @key[function] @AdaSubDefn{Random} (Gen : Generator) @key[return] Uniformly_Distributed; @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator); -- @RI{Advanced facilities} @key[type] @AdaTypeDefn{State} @key[is] @key[private]; @key[procedure] @AdaSubDefn{Save} (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; From_State : @key[in] State); @AdaObjDefn{Max_Image_Width} : @key[constant] := @RI{implementation-defined integer value}; @key[function] @AdaSubDefn{Image} (Of_State : State) @key[return] String; @key[function] @AdaSubDefn{Value} (Coded_State : String) @key[return] State; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Numerics.Float_Random; @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Generator needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} The generic library package Numerics.Discrete_Random has the following declaration: @begin{Example} @ChildUnit{Parent=[Ada.Numerics],Child=[Discrete_@!Random]} @key[generic] @key[type] Result_Subtype @key[is] (<>); @key[package] Ada.Numerics.Discrete_Random @key[is] -- @RI{Basic facilities} @key[type] @AdaTypeDefn{Generator} @key[is] @key[limited] @key[private]; @key[function] @AdaSubDefn{Random} (Gen : Generator) @key[return] Result_Subtype; @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator); -- @RI{Advanced facilities} @key[type] @AdaTypeDefn{State} @key[is] @key[private]; @key[procedure] @AdaSubDefn{Save} (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] @AdaSubDefn{Reset} (Gen : @key[in] Generator; From_State : @key[in] State); @AdaObjDefn{Max_Image_Width} : @key[constant] := @RI{implementation-defined integer value}; @key[function] @AdaSubDefn{Image} (Of_State : State) @key[return] String; @key[function] @AdaSubDefn{Value} (Coded_State : String) @key[return] State; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Numerics.Discrete_Random; @end{Example} @ImplDef{The value of Numerics.Float_Random.Max_Image_Width.} @ImplDef{The value of Numerics.Discrete_Random.Max_Image_Width.} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0097],ARef=[AI95-00115-01]} @Leading@; The following is a possible implementation of the private part of @Chg{New=[Numerics.Float_Random], Old=[each package]} (assuming the presence of @lquotes@;@key[with] Ada.Finalization;@rquotes@; as a context clause): @begin{example} @key[type] State @key[is] ...; @key[type] Access_State @key[is] @key[access] State; @key[type] Generator @key[is] @key[new] Finalization.Limited_Controlled @key[with] @key[record] S : Access_State := @key[new] State'(...); @key[end] @key[record]; @key[procedure] Finalize (G : @key[in] @key[out] Generator); @end{Example} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00344-01]} @ChgAdded{Version=[1],Text=[@Chg{Version=[2],New=[], Old=[Unfortunately, ]}Numerics.Discrete_Random.Generator @Chg{Version=[2],New=[also can],Old=[cannot]} be implemented this way@Chg{Version=[2],New=[],Old=[, as Numerics.Discrete_Random can be instantiated at any nesting depth. However, Generator could have a component of a controlled type, as long as that type is declared in some other (nongeneric) package. One possible solution would be to implement Numerics.@!Discrete_@!Random in terms of Numerics.@!Float_@!Random, using a component of Numerics.@!Float_@!Random.Generator to implement Numerics.@!Float_@!Random.@!Generator]}.]} Clearly some level of indirection is required in the implementation of a Generator, since the parameter mode is @key(in) for all operations on a Generator. For this reason, Numerics.Float_Random and Numerics.Discrete_Random cannot be declared pure. @end{ImplNote} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Generator needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}) in every instantiation of Numerics.Discrete_Random.]} An object of the limited private type Generator is associated with a sequence of random numbers. Each generator has a hidden (internal) state, which the operations on generators use to determine the position in the associated sequence. @PDefn{unspecified} All generators are implicitly initialized to an unspecified state that does not vary from one program execution to another; they may also be explicitly initialized, or reinitialized, to a time-dependent state, to a previously saved state, or to a state uniquely denoted by an integer value. @begin{Discussion} The repeatability provided by the implicit initialization may be exploited for testing or debugging purposes. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0280-1]} An object of the private type State can be used to hold the internal state of a generator. Such objects are only needed if the application is designed to save and restore generator states or to examine or manufacture them.@Chg{Version=[3],New=[ The implicit initial value of type State corresponds to the implicit initial value of all generators.],Old=[]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0280-1]} @ChgAdded{Version=[3],Text=[All generators are implicitly initialized to the same unchanging value, and using Reset on a default initialized object of type State will produce a generator with that same value.]} @end{Discussion} @Trailing@;The operations on generators affect the state and therefore the future values of the associated sequence. The semantics of the operations on generators and states are defined below. @begin{DescribeCode} @begin{Example} @key[function] Random (Gen : Generator) @key[return] Uniformly_Distributed; @key[function] Random (Gen : Generator) @key[return] Result_Subtype; @end{Example} @Trailing@;Obtains the @lquotes@;next@rquotes@; random number from the given generator, relative to its current state, according to an implementation-defined algorithm. The result of the function in Numerics.Float_Random is delivered as a value of the subtype Uniformly_Distributed, which is a subtype of the predefined type Float having a range of 0.0 .. 1.0. The result of the function in an instantiation of Numerics.Discrete_Random is delivered as a value of the generic formal subtype Result_Subtype. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2],Text=[The algorithms for random number generation.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The algorithm is the subject of a @DocReqName@;, so we don't separately summarize this implementation-defined item.]} @end{Discussion} @begin{Reason} The requirement for a level of indirection in accessing the internal state of a generator arises from the desire to make Random a function, rather than a procedure. @end{Reason} @begin{Example} @key[procedure] Reset (Gen : @key[in] Generator; Initiator : @key[in] Integer); @key[procedure] Reset (Gen : @key[in] Generator); @end{Example} @Trailing@PDefn{unspecified} Sets the state of the specified generator to one that is an unspecified function of the value of the parameter Initiator (or to a time-dependent state, if only a generator parameter is specified). @Defn2{Term=[Time-dependent Reset procedure],Sec=(of the random number generator)} The latter form of the procedure is known as the @i{time-dependent Reset procedure}. @begin{ImplNote} The time-dependent Reset procedure can be implemented by mapping the current time and date as determined by the system clock into a state, but other implementations are possible. For example, a white-noise generator or a radioactive source can be used to generate time-dependent states. @end{ImplNote} @begin{Example} @key[procedure] Save (Gen : @key[in] Generator; To_State : @key[out] State); @key[procedure] Reset (Gen : @key[in] Generator; From_State : @key[in] State); @end{Example} @Trailing@;Save obtains the current state of a generator. Reset gives a generator the specified state. A generator that is reset to a state previously obtained by invoking Save is restored to the state it had when Save was invoked. @begin{Example} @key[function] Image (Of_State : State) @key[return] String; @key[function] Value (Coded_State : String) @key[return] State; @end{Example} Image provides a representation of a state coded (in an implementation-defined way) as a string whose length is bounded by the value of Max_Image_Width. Value is the inverse of Image: Value(Image(S)) = S for each state S that can be obtained from a generator by invoking Save. @ImplDef{The string representation of a random number generator's state.} @end{DescribeCode} @end{StaticSem} @begin{RunTime} @IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Instantiation of Numerics.Discrete_Random with a subtype having a null range raises Constraint_Error. @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0050],ARef=[AI95-00089]} @ChgDeleted{Version=[1],Text=[@IndexCheck{Range_Check} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} Invoking Value with a string that is not the image of any generator state raises Constraint_Error.]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0050],ARef=[AI95-00089]} @ChgAdded{Version=[1],Text=[It is a bounded error to invoke Value with a string that is not the image of any generator state. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If the error is detected, Constraint_Error or Program_Error is raised. Otherwise, a call to Reset with the resulting state will produce a generator such that calls to Random with this generator will produce a sequence of values of the appropriate subtype, but which might not be random in character. That is, the sequence of values might not fulfill the implementation requirements of this subclause.]} @end{Bounded} @begin{ImplReq} A sufficiently long sequence of random numbers obtained by successive calls to Random is approximately uniformly distributed over the range of the result subtype. The Random function in an instantiation of Numerics.Discrete_Random is guaranteed to yield each value in its result subtype in a finite number of calls, provided that the number of such values does not exceed 2 @+[15]. Other performance requirements for the random number generator, which apply only in implementations conforming to the Numerics Annex, and then only in the @lquotes@;strict@rquotes@; mode defined there (see @RefSecNum{Numeric Performance Requirements}), are given in @RefSecNum{Performance Requirements for Random Number Generation}. @end{ImplReq} @begin{DocReq} No one algorithm for random number generation is best for all applications. To enable the user to determine the suitability of the random number generators for the intended application, the implementation shall describe the algorithm used and shall give its period, if known exactly, or a lower bound on the period, if the exact period is unknown. Periods that are so long that the periodicity is unobservable in practice can be described in such terms, without giving a numerical bound. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The algorithm used for random number generation, including a description of its period.]}]} The implementation also shall document the minimum time interval between calls to the time-dependent Reset procedure that are guaranteed to initiate different sequences, and it shall document the nature of the strings that Value will accept without raising Constraint_Error. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2],Text=[The minimum time interval between calls to the time-dependent Reset procedure that are guaranteed to initiate different random number sequences.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[The minimum time interval between calls to the time-dependent Reset procedure that is guaranteed to initiate different random number sequences.]}]} @end{DocReq} @begin{ImplAdvice} Any storage associated with an object of type Generator should be reclaimed on exit from the scope of the object. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2],Text=[Any storage associated with an object of type Generator of the random number packages should be reclaimed on exit from the scope of the object.]}]} @begin{Ramification} A level of indirection is implicit in the semantics of the operations, given that they all take parameters of mode @key(in). This implies that the full type of Generator probably should be a controlled type, with appropriate finalization to reclaim any heap-allocated storage. @end{Ramification} If the generator period is sufficiently long in relation to the number of distinct initiator values, then each possible value of Initiator passed to Reset should initiate a sequence of random numbers that does not, in a practical sense, overlap the sequence initiated by any other value. If this is not possible, then the mapping between initiator values and generator states should be a rapidly varying function of the initiator value. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[Each value of Initiator passed to Reset for the random number packages should initiate a distinct sequence of random numbers, or, if that is not possible, be at least a rapidly varying function of the initiator value.]}]} @end{ImplAdvice} @begin{Notes} If two or more tasks are to share the same generator, then the tasks have to synchronize their access to the generator as for any shared variable (see @RefSecNum(Shared Variables)). Within a given implementation, a repeatable random number sequence can be obtained by relying on the implicit initialization of generators or by explicitly initializing a generator with a repeatable initiator value. Different sequences of random numbers can be obtained from a given generator in different program executions by explicitly initializing the generator to a time-dependent state. A given implementation of the Random function in Numerics.Float_Random may or may not be capable of delivering the values 0.0 or 1.0. Portable applications should assume that these values, or values sufficiently close to them to behave indistinguishably from them, can occur. If a sequence of random integers from some fixed range is needed, the application should use the Random function in an appropriate instantiation of Numerics.Discrete_Random, rather than transforming the result of the Random function in Numerics.Float_Random. However, some applications with unusual requirements, such as for a sequence of random integers each drawn from a different range, will find it more convenient to transform the result of the floating point Random function. For @R[M] @geq 1, the expression @begin{Example} Integer(Float(M) * Random(G)) mod M @end{Example} @NoPrefix@;transforms the result of Random(G) to an integer uniformly distributed over the range 0 .. @R[M]@en@;1; it is valid even if Random delivers 0.0 or 1.0. Each value of the result range is possible, provided that M is not too large. Exponentially distributed (floating point) random numbers with mean and standard deviation 1.0 can be obtained by the transformation @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} -Log(Random(G) + Float'Model_Small)@Chg{Version=[2],New=[],Old=[)]} @end{Example} @NoPrefix@;where Log comes from Numerics.Elementary_Functions (see @RefSecNum{Elementary Functions}); in this expression, the addition of Float'Model_Small avoids the exception that would be raised were Log to be given the value zero, without affecting the result (in most implementations) when Random returns a nonzero value. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of a program that plays a simulated dice game:} @begin{Example}@Trailing @key[with] Ada.Numerics.Discrete_Random; @key[procedure] Dice_Game @key[is]@Softpage @key[subtype] Die @key[is] Integer @key[range] 1 .. 6; @key[subtype] Dice @key[is] Integer @key[range] 2*Die'First .. 2*Die'Last; @key[package] Random_Die @key[is] @key[new] Ada.Numerics.Discrete_Random (Die); @key[use] Random_Die; G : Generator; D : Dice;@Softpage @key[begin]@Softpage Reset (G); -- @RI{Start the generator in a unique state in each run} @key[loop] -- @RI{Roll a pair of dice; sum and process the results} D := Random(G) + Random(G); ... @key[end] @key[loop];@Softpage @key[end] Dice_Game; @end{Example} @Leading@Keepnext@i{Example of a program that simulates coin tosses:} @begin{Example}@Trailing @key[with] Ada.Numerics.Discrete_Random; @key[procedure] Flip_A_Coin @key[is]@Softpage @key[type] Coin @key[is] (Heads, Tails); @key[package] Random_Coin @key[is] @key[new] Ada.Numerics.Discrete_Random (Coin); @key[use] Random_Coin; G : Generator;@Softpage @key[begin]@Softpage Reset (G); -- @RI{Start the generator in a unique state in each run} @key[loop] -- @RI{Toss a coin and process the result} @key[case] Random(G) @key[is] @key[when] Heads => ... @key[when] Tails => ... @key[end] @key[case]; ... @key[end] @key[loop];@Softpage @key[end] Flip_A_Coin; @end{Example} @Leading@Keepnext@i{Example of a parallel simulation of a physical system, with a separate generator of event probabilities in each task:} @begin{Example} @key[with] Ada.Numerics.Float_Random; @key[procedure] Parallel_Simulation @key[is]@Softpage @key[use] Ada.Numerics.Float_Random; @key[task] @key[type] Worker @key[is] @key[entry] Initialize_Generator (Initiator : @key[in] Integer); ... @key[end] Worker; W : @key[array] (1 .. 10) @key[of] Worker;@Softpage @key[task] @key[body] Worker @key[is] G : Generator; Probability_Of_Event : Uniformly_Distributed; @key[begin]@Softpage @key[accept] Initialize_Generator (Initiator : @key[in] Integer) @key[do] Reset (G, Initiator); @key[end] Initialize_Generator; @key[loop] ... Probability_Of_Event := Random(G); ... @key[end] @key[loop]; @key[end] Worker;@Softpage @key[begin]@Softpage -- @RI{Initialize the generators in the Worker tasks to different states} @key[for] I @key[in] W'Range @key[loop] W(I).Initialize_Generator (I); @key[end] @key[loop]; ... -- @RI{Wait for the Worker tasks to terminate}@Softpage @key[end] Parallel_Simulation; @end{Example} @end{Examples} @begin{Notes} @i{Notes on the last example:} Although each Worker task initializes its generator to a different state, those states will be the same in every execution of the program. The generator states can be initialized uniquely in each program execution by instantiating Ada.Numerics.Discrete_Random for the type Integer in the main procedure, resetting the generator obtained from that instance to a time-dependent state, and then using random integers obtained from that generator to initialize the generators in each Worker task. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Type Generator in Numerics.Float_Random and in an instance of Numerics.Discrete_Random is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and Generator does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as another Ada compiler may have a controlled part in Generator, and thus would be illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0050],ARef=[AI95-00089-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Made the passing of an incorrect Image of a generator a bounded error, as it @Chg{Version=[3],New=[might],Old=[may]} not be practical to check for problems (if a generator consists of several related values).]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0280-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Specified the implicit initial value for (sub)type State. This was unspecified in Ada 95 and Ada 2005, so a program depending on some other initial value is very unlikely and certainly was not portable. An implementation can use default expressions, aspect Default_Value, or aspect Default_Component_Value to keep the representation of the type unchanged while meeting this new requirement.]} @end{DiffWord2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_standard.mss�����������������������������������������������������0000755�0001752�0001001�00000061515�12066652507�020630� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_standard.mss,v $ } @comment{ $Revision: 1.42 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(predefstandard, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{The Package Standard} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} outlines the specification of the package Standard containing all predefined identifiers in the language. @PDefn{unspecified} The corresponding package body is not specified by the language. The operators that are predefined for the types declared in the package Standard are given in comments since they are implicitly declared. @Defn2{Term=[italics],Sec=(pseudo-names of anonymous types)} Italics are used for pseudo-names of anonymous types (such as @i{root_real}) and for undefined information (such as @i{implementation-defined}). @begin{Ramification} All of the predefined operators are of convention Intrinsic. @end{Ramification} @end{Intro} @begin{StaticSem} @Leading@;The library package Standard has the following declaration: @ImplDef{The names and characteristics of the numeric subtypes declared in the visible part of package Standard.} @begin{Example} @RootLibUnit{Standard}@key[package] Standard @key[is] @key[pragma] Pure(Standard); @key[type] @AdaTypeDefn{Boolean} @key[is] (False, True); @Keepnext --@RI{ The predefined relational operators for this type are as follows:} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "<" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] ">" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean; @Keepnext --@RI{ The predefined logical operators and the predefined logical} --@RI{ negation operator are as follows:} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "@key[and]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; -- @key[function] "@key[or]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; -- @key[function] "@key[xor]" (Left, Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0028],ARef=[AI95-00145-01]} -- @key[function] "@key[not]" (Right : Boolean@Chg{New=['Base],Old=[]}) @key[return] Boolean@Chg{New=['Base],Old=[]}; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} --@RI{ The integer type root_integer @Chg{Version=[2],New=[and the],Old=[is predefined.]}} --@RI{ @Chg{Version=[2],New=[],Old=[The ]}corresponding universal type @Chg{Version=[2],New=[],Old=[is ]}universal_integer@Chg{Version=[2],New=[ are predefined],Old=[]}.} @key[type] @AdaTypeDefn{Integer} @key[is] @key{range} @RI{implementation-defined}; @key[subtype] @AdaSubtypeDefn{Name=[Natural],Of=[Integer]} @key[is] Integer @key[range] 0 .. Integer'Last; @key[subtype] @AdaSubtypeDefn{Name=[Positive],Of=[Integer]} @key[is] Integer @key[range] 1 .. Integer'Last; @Keepnext --@RI{ The predefined operators for type Integer are as follows:} -- @key[function] "=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "<" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] ">" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Integer'Base) @key[return] Boolean; -- @key[function] "+" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "-" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[abs]" (Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "+" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "-" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "*" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "/" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[rem]" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "@key[mod]" (Left, Right : Integer'Base) @key[return] Integer'Base; -- @key[function] "**" (Left : Integer'Base; Right : Natural) -- @key[return] Integer'Base; --@RI{ The specification of each operator for the type} --@RI{ root_integer, or for any additional predefined integer} --@RI{ type, is obtained by replacing Integer by the name of the type} --@RI{ in the specification of the corresponding operator of the type} --@RI{ Integer. The right operand of the exponentiation operator} --@RI{ remains as subtype Natural.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} --@RI{ The floating point type root_real @Chg{Version=[2],New=[and the],Old=[is predefined.]}} --@RI{ @Chg{Version=[2],New=[],Old=[The ]}corresponding universal type @Chg{Version=[2],New=[],Old=[is ]}universal_real@Chg{Version=[2],New=[ are predefined],Old=[]}.} @key[type] @AdaTypeDefn{Float} @key[is] @key{digits} @RI{implementation-defined}; @Keepnext --@RI{ The predefined operators for this type are as follows:} -- @key[function] "=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "/=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "<" (Left, Right : Float) @key[return] Boolean; -- @key[function] "<=" (Left, Right : Float) @key[return] Boolean; -- @key[function] ">" (Left, Right : Float) @key[return] Boolean; -- @key[function] ">=" (Left, Right : Float) @key[return] Boolean; -- @key[function] "+" (Right : Float) @key[return] Float; -- @key[function] "-" (Right : Float) @key[return] Float; -- @key[function] "@key[abs]" (Right : Float) @key[return] Float; -- @key[function] "+" (Left, Right : Float) @key[return] Float; -- @key[function] "-" (Left, Right : Float) @key[return] Float; -- @key[function] "*" (Left, Right : Float) @key[return] Float; -- @key[function] "/" (Left, Right : Float) @key[return] Float; -- @key[function] "**" (Left : Float; Right : Integer'Base) @key[return] Float; --@RI{ The specification of each operator for the type root_real, or for} --@RI{ any additional predefined floating point type, is obtained by} --@RI{ replacing Float by the name of the type in the specification of the} --@RI{ corresponding operator of the type Float.} @Keepnext --@RI{ In addition, the following operators are predefined for the root} --@RI{ numeric types:} @key[function] "*" (Left : @RI{root_integer}; Right : @RI{root_real}) @key[return] @RI{root_real}; @key[function] "*" (Left : @RI{root_real}; Right : @RI{root_integer}) @key[return] @RI{root_real}; @key[function] "/" (Left : @RI{root_real}; Right : @RI{root_integer}) @key[return] @RI{root_real}; --@RI{ The type universal_fixed is predefined.} --@RI{ The only multiplying operators defined between} --@RI{ fixed point types are} @key[function] "*" (Left : @RI[universal_fixed]; Right : @RI[universal_fixed]) @key[return] @RI[universal_fixed]; @key[function] "/" (Left : @RI[universal_fixed]; Right : @RI[universal_fixed]) @key[return] @RI[universal_fixed]; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[ --@RI{ The type universal_access is predefined.} --@RI{ The following equality operators are predefined:}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[ @key[function] "=" (Left, Right: @RI[universal_access]) @key[return] Boolean; @key[function] "/=" (Left, Right: @RI[universal_access]) @key[return] Boolean;]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00415-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0181-1],ARef=[AI05-0248-1]} @tabclear()@tabset(P7, P14, P21, P28, P37, P44, P51, P58, P64) @comment{blank line} --@RI{ The declaration of type Character is based on the standard ISO 8859-1 character set.} @comment{blank line} --@RI{ There are no character literals corresponding to the positions for control characters.} --@RI{ They are indicated in italics in this definition. See @refsecnum[Character Types].} @comment[blank line] @key[type] @AdaTypeDefn{Character} @key[is] (@RI[nul],@\@RI[soh],@\@RI[stx],@\@RI[etx],@\@RI[eot],@\@RI[enq],@\@RI[ack],@\@RI[bel],@\--@RI{0 (16#00#) .. 7 (16#07#)} @RI[bs],@\@RI[ht],@\@RI[lf],@\@RI[vt],@\@RI[ff],@\@RI[cr],@\@RI[so],@\@RI[si],@\--@RI{8 (16#08#) .. 15 (16#0F#)} @comment{blank line} @RI[dle],@\@RI[dc1],@\@RI[dc2],@\@RI[dc3],@\@RI[dc4],@\@RI[nak],@\@RI[syn],@\@RI[etb],@\--@RI{16 (16#10#) .. 23 (16#17#)} @RI[can],@\@RI[em],@\@RI[sub],@\@RI[esc],@\@RI[fs],@\@RI[gs],@\@RI[rs],@\@RI[us],@\--@RI{24 (16#18#) .. 31 (16#1F#)} @comment{blank line} ' ',@\'!',@\'"',@\'#',@\'$',@\'%',@\'&',@\''',@\--@RI{32 (16#20#) .. 39 (16#27#)} '(',@\')',@\'*',@\'+',@\',',@\'-',@\'.',@\'/',@\--@RI{40 (16#28#) .. 47 (16#2F#)} @comment{blank line} '0',@\'1',@\'2',@\'3',@\'4',@\'5',@\'6',@\'7',@\--@RI{48 (16#30#) .. 55 (16#37#)} '8',@\'9',@\':',@\';',@\'<',@\'=',@\'>',@\'?',@\--@RI{56 (16#38#) .. 63 (16#3F#)} @comment{blank line} '@@',@\'A',@\'B',@\'C',@\'D',@\'E',@\'F',@\'G',@\--@RI{64 (16#40#) .. 71 (16#47#)} 'H',@\'I',@\'J',@\'K',@\'L',@\'M',@\'N',@\'O',@\--@RI{72 (16#48#) .. 79 (16#4F#)} @comment{blank line} 'P',@\'Q',@\'R',@\'S',@\'T',@\'U',@\'V',@\'W',@\--@RI{80 (16#50#) .. 87 (16#57#)} 'X',@\'Y',@\'Z',@\'[',@\'\',@\']',@\'^',@\'_',@\--@RI{88 (16#58#) .. 95 (16#5F#)} @comment{blank line} '`',@\'a',@\'b',@\'c',@\'d',@\'e',@\'f',@\'g',@\--@RI{96 (16#60#) .. 103 (16#67#)} 'h',@\'i',@\'j',@\'k',@\'l',@\'m',@\'n',@\'o',@\--@RI{104 (16#68#) .. 111 (16#6F#)} @comment{blank line} 'p',@\'q',@\'r',@\'s',@\'t',@\'u',@\'v',@\'w',@\--@RI{112 (16#70#) .. 119 (16#77#)} 'x',@\'y',@\'z',@\'{',@\'|',@\'}',@\'~',@\@RI[del],@\--@RI{120 (16#78#) .. 127 (16#7F#)} @Comment{Blank line} @RI[reserved_128],@\@RI[reserved_129],@\@RI[bph],@\@RI[nbh],@\@\@\--@RI{128 (16#80#) .. 131 (16#83#)} @RI[reserved_132],@\@RI[nel],@\@RI[ssa],@\@RI[esa],@\@\@\@\--@RI{132 (16#84#) .. 135 (16#87#)} @RI[hts],@\@RI[htj],@\@RI[vts],@\@RI[pld],@\@RI[plu],@\@RI[ri],@\@RI[ss2],@\@RI[ss3],@\--@RI{136 (16#88#) .. 143 (16#8F#)} @comment{blank line} @RI[dcs],@\@RI[pu1],@\@RI[pu2],@\@RI[sts],@\@RI[cch],@\@RI[mw],@\@RI[spa],@\@RI[epa],@\--@RI{144 (16#90#) .. 151 (16#97#)} @RI[sos],@\@RI[reserved_153],@\@RI[sci],@\@RI[csi],@\@\@\@\--@RI{152 (16#98#) .. 155 (16#9B#)} @RI[st],@\@RI[osc],@\@RI[pm],@\@RI[apc],@\@\@\@\@\--@RI{156 (16#9C#) .. 159 (16#9F#)} @comment{blank line} ' ',@\'@latin1(161)',@\'@latin1(162)',@\'@latin1(163)',@\'@latin1(164)',@\'@latin1(165)',@\'@latin1(166)',@\'@latin1(167)',@\--@RI{160 (16#A0#) .. 167 (16#A7#)} '@latin1(168)',@\'@latin1(169)',@\'@latin1(170)',@\'@latin1(171)',@Chg{Version=[3],New=[@\@\@\@\@\--@RI{168 (16#A8#) .. 171 (16#AB#)} @latin1(172)',@\@RI[soft_hyphen],@\'@latin1(174)',@\'@latin1(175)',@\@\@\@\--@RI{172 (16#AC#) .. 175 (16#AF#)}],Old=[@\'@latin1(172)',@\'@latin1(173)',@\'@latin1(174)',@\'@latin1(175)',@\--@RI{168 (16#A8#) .. 175 (16#AF#)}]} @comment{blank line} '@latin1(176)',@\'@latin1(177)',@\'@latin1(178)',@\'@latin1(179)',@\'@latin1(180)',@\'@latin1(181)',@\'@latin1(182)',@\'@latin1(183)',@\--@RI{176 (16#B0#) .. 183 (16#B7#)} '@latin1(184)',@\'@latin1(185)',@\'@latin1(186)',@\'@latin1(187)',@\'@latin1(188)',@\'@latin1(189)',@\'@latin1(190)',@\'@latin1(191)',@\--@RI{184 (16#B8#) .. 191 (16#BF#)} @comment{blank line} '@latin1(192)',@\'@latin1(193)',@\'@latin1(194)',@\'@latin1(195)',@\'@latin1(196)',@\'@latin1(197)',@\'@latin1(198)',@\'@latin1(199)',@\--@RI{192 (16#C0#) .. 199 (16#C7#)} '@latin1(200)',@\'@latin1(201)',@\'@latin1(202)',@\'@latin1(203)',@\'@latin1(204)',@\'@latin1(205)',@\'@latin1(206)',@\'@latin1(207)',@\--@RI{200 (16#C8#) .. 207 (16#CF#)} @comment{blank line} '@latin1(208)',@\'@latin1(209)',@\'@latin1(210)',@\'@latin1(211)',@\'@latin1(212)',@\'@latin1(213)',@\'@latin1(214)',@\'@latin1(215)',@\--@RI{208 (16#D0#) .. 215 (16#D7#)} '@latin1(216)',@\'@latin1(217)',@\'@latin1(218)',@\'@latin1(219)',@\'@latin1(220)',@\'@latin1(221)',@\'@latin1(222)',@\'@latin1(223)',@\--@RI{216 (16#D8#) .. 223 (16#DF#)} @comment{blank line} '@latin1(224)',@\'@latin1(225)',@\'@latin1(226)',@\'@latin1(227)',@\'@latin1(228)',@\'@latin1(229)',@\'@latin1(230)',@\'@latin1(231)',@\--@RI{224 (16#E0#) .. 231 (16#E7#)} '@latin1(232)',@\'@latin1(233)',@\'@latin1(234)',@\'@latin1(235)',@\'@latin1(236)',@\'@latin1(237)',@\'@latin1(238)',@\'@latin1(239)',@\--@RI{232 (16#E8#) .. 239 (16#EF#)} @comment{blank line} '@latin1(240)',@\'@latin1(241)',@\'@latin1(242)',@\'@latin1(243)',@\'@latin1(244)',@\'@latin1(245)',@\'@latin1(246)',@\'@latin1(247)',@\--@RI{240 (16#F0#) .. 247 (16#F7#)} '@latin1(248)',@\'@latin1(249)',@\'@latin1(250)',@\'@latin1(251)',@\'@latin1(252)',@\'@latin1(253)',@\'@latin1(254)',@\'@latin1(255)'@Chg{Version=[2],New=[);],Old=[,@\]}--@RI{248 (16#F8#) .. 255 (16#FF#)} --@RI{ The predefined operators for the type Character are the same as for} --@RI{ any enumeration type.} @Softpage@; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]}@Comment{Odd missing paragraph number here} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0266-1]} @Chg{Version=[2],New=[],Old=[@noparanum@;]} --@RI{ The declaration of type Wide_Character is based on the standard @Chg{Version=[2],New=[ISO/IEC],Old=[ISO]} 10646@Chg{Version=[2],New=[:@Chg{Version=[3],New=[2011],Old=[2003]}],Old=[]} BMP character@Chg{Version=[2],New=[],Old=[ set.]}} --@RI{ @Chg{Version=[2],New=[set. ],Old=[]}The first 256 positions have the same contents as type Character. See @refsecnum[Character types].} @comment[blank line] @key[type] @AdaTypeDefn{Wide_Character} @key[is] (@RI[nul], @RI[soh] ... @RI[@Chg{Version=[2],New=[Hex_0000FFFE],Old=[FFFE]}], @RI[@Chg{Version=[2],New=[Hex_0000FFFF],Old=[FFFF]}]); @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0266-1]} @ChgAdded{Version=[2],Text=[ --@RI[ The declaration of type Wide_Wide_Character is based on the full] --@RI[ ISO/IEC 10646:@Chg{Version=[3],New=[2011],Old=[2003]} character set. The first 65536 positions have the] --@RI[ same contents as type Wide_Character. See @refsecnum[Character types].] @comment[blank line] @key[type] @AdaTypeDefn{Wide_Wide_Character} @key[is] (@RI[nul], @RI[soh] ... @RI[Hex_7FFFFFFE], @RI[Hex_7FFFFFFF]); @key[for] Wide_Wide_Character'Size @key[use] 32;]} @ChgRef{Version=[2],Kind=[Added]}@Comment{Odd missing paragraph number here} @Chg{Version=[2],New=[],Old=[@noparanum@;]} @key[package] @AdaPackDefn{ASCII} @key[is] ... @key[end] ASCII; --@RI{Obsolescent; see @RefSecNum[ASCII]} @Defn2{Term=[ASCII], Sec=(package physically nested within the declaration of Standard)} @comment[blank line] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} --@RI{ Predefined string types:} @comment[blank line] @key[type] @AdaTypeDefn{String} @key[is] @key[array](Positive @key[range] <>) @key[of] Character@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(String)]}; @Keepnext --@RI{ The predefined operators for this type are as follows:} -- @key[function] "=" (Left, Right: String) @key[return] Boolean; -- @key[function] "/=" (Left, Right: String) @key[return] Boolean;@Softpage -- @key[function] "<" (Left, Right: String) @key[return] Boolean; -- @key[function] "<=" (Left, Right: String) @key[return] Boolean; -- @key[function] ">" (Left, Right: String) @key[return] Boolean; -- @key[function] ">=" (Left, Right: String) @key[return] Boolean; -- @key[function] "&" (Left: String; Right: String) @key[return] String; -- @key[function] "&" (Left: Character; Right: String) @key[return] String; -- @key[function] "&" (Left: String; Right: Character) @key[return] String; -- @key[function] "&" (Left: Character; Right: Character) @key[return] String; @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @key[type] @AdaTypeDefn{Wide_String} @key[is] @key[array](Positive @key[range] <>) @key[of] Wide_Character@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack(Wide_String)]}; --@RI{ The predefined operators for this type correspond to those for String.} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[ @key[type] @AdaTypeDefn{Wide_Wide_String} @key[is array] (Positive @key[range] <>) @key[of] Wide_Wide_Character@Chg{Version=[3],New=[ @key[with] Pack],Old=[; @key[pragma] Pack (Wide_Wide_String)]};]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[ --@RI[ The predefined operators for this type correspond to those for String.]]} @key[type] @AdaTypeDefn{Duration} @key[is] @key[delta] @RI{implementation-defined} @key[range] @RI{implementation-defined}; --@RI{ The predefined operators for the type Duration are the same as for} --@RI{ any fixed point type.} @Keepnext --@RI{ The predefined exceptions:} @AdaExcDefn{Constraint_Error}: @key[exception]; @AdaExcDefn{Program_Error} : @key[exception]; @AdaExcDefn{Storage_Error} : @key[exception]; @AdaExcDefn{Tasking_Error} : @key[exception]; @key[end] Standard; @end{Example} Standard has no private part. @begin{Reason} This is important for portability. All library packages are children of Standard, and if Standard had a private part then it would be visible to all of them. @end{reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} In each of the types Character@Chg{Version=[2],New=[,],Old=[ and]} Wide_Character@Chg{Version=[2],New=[, and Wide_Wide_Character],Old=[]}, the character literals for the space character (position 32) and the non-breaking space character (position 160) correspond to different values. Unless indicated otherwise, each occurrence of the character literal ' ' in this International Standard refers to the space character. Similarly, the character literals for hyphen (position 45) and soft hyphen (position 173) correspond to different values. Unless indicated otherwise, each occurrence of the character literal '@en@;' in this International Standard refers to the hyphen character. @end{StaticSem} @begin{RunTime} @PDefn2{Term=[elaboration], Sec=(package_body of Standard)} Elaboration of the body of Standard has no effect. @begin{Discussion} Note that the language does not define where this body appears in the environment @nt{declarative_part} @em see @RefSec{Program Structure and Compilation Issues}. @end{Discussion} @end{RunTime} @begin{ImplPerm} An implementation may provide additional predefined integer types and additional predefined floating point types. Not all of these types need have names. @begin{Honest} An implementation may add representation items to package Standard, for example to specify the internal codes of type Boolean, or the Small of type Duration. @end{Honest} @end{ImplPerm} @begin{ImplAdvice} If an implementation provides additional named predefined integer types, then the names should end with @lquotes@;Integer@rquotes@; as in @lquotes@;Long_Integer@rquotes@;. If an implementation provides additional named predefined floating point types, then the names should end with @lquotes@;Float@rquotes@; as in @lquotes@;Long_Float@rquotes@;. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an implementation provides additional named predefined integer types, then the names should end with @lquotes@;Integer@rquotes@;. If an implementation provides additional named predefined floating point types, then the names should end with @lquotes@;Float@rquotes@;.]}]} @end{ImplAdvice} @begin{Notes} Certain aspects of the predefined entities cannot be completely described in the language itself. For example, although the enumeration type Boolean can be written showing the two enumeration literals False and True, the short-circuit control forms cannot be expressed in the language. As explained in @RefSec{Declarative Region} and @RefSec{The Compilation Process}, the declarative region of the package Standard encloses every library unit and consequently the main subprogram; the declaration of every library unit is assumed to occur within this declarative region. @nt{Library_item}s are assumed to be ordered in such a way that there are no forward semantic dependences. However, as explained in @RefSec{Visibility}, the only library units that are visible within a given compilation unit are the library units named by all @nt{with_clause}s that apply to the given unit, and moreover, within the declarative region of a given library unit, that library unit itself. If all @nt{block_statement}s of a program are named, then the name of each program unit can always be written as an expanded name starting with Standard (unless Standard is itself hidden). The name of a library unit cannot be a homograph of a name (such as Integer) that is already declared in Standard. The exception Standard.Numeric_Error is defined in @RefSecNum{Numeric_Error}. @begin{Discussion} The declaration of Natural needs to appear between the declaration of Integer and the (implicit) declaration of the "**" operator for Integer, because a formal parameter of "**" is of subtype Natural. This would be impossible in normal code, because the implicit declarations for a type occur immediately after the type declaration, with no possibility of intervening explicit declarations. But we're in Standard, and Standard is somewhat magic anyway. Using Natural as the subtype of the formal of "**" seems natural; it would be silly to have a textual rule about Constraint_Error being raised when there is a perfectly good subtype that means just that. Furthermore, by not using Integer for that formal, it helps remind the reader that the exponent remains Natural even when the left operand is replaced with the derivative of Integer. It doesn't logically imply that, but it's still useful as a reminder. In any case, declaring these general-purpose subtypes of Integer close to Integer seems more readable than declaring them much later. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} Package Standard is declared to be pure. @begin{discussion} The introduction of the types Wide_Character and Wide_String is not an Ada 95 extension to Ada 83, since ISO WG9 has approved these as an authorized extension of the original Ada 83 standard that is part of that standard. @end{discussion} @end{Extend83} @begin{DiffWord83} Numeric_Error is made obsolescent. The declarations of Natural and Positive are moved to just after the declaration of Integer, so that "**" can refer to Natural without a forward reference. There's no real need to move Positive, too @em it just came along for the ride. @end{DiffWord83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Types Wide_Wide_Character and Wide_Wide_String are new.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The inconsistencies associated with these types are documented in @RefSecNum{Character Types} and @RefSecNum{String Types}.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00230-01]} @ChgAdded{Version=[2],Text=[Type @i<universal_access> and the equality operations for it are new.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0028],ARef=[AI95-00145-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the parameter type for the Boolean operators declared in Standard..]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0181-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Since soft_hyphen (position 173) is defined to be nongraphic, gave it a name.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The inconsistencies associated with this change are documented in @RefSecNum{Scalar Types}.]} @end{Discussion} @end{DiffWord2005} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/pre_strings.mss������������������������������������������������������0000755�0001752�0001001�00000541550�12066652507�020523� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/pre_strings.mss,v $ } @comment{ $Revision: 1.79 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(predefstrings, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @RMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{String Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} presents the specifications of the package Strings and several child packages, which provide facilities for dealing with string data. Fixed-length, bounded-length, and unbounded-length strings are supported, for @Chg{Version=[2],New=[],Old=[both]} String@Chg{Version=[2],New=[,],Old=[ and]} Wide_String@Chg{Version=[2],New=[, and Wide_Wide_String],Old=[]}. The string-handling subprograms include searches for pattern strings and for characters in program-specified sets, translation (via a character-to-character mapping), and transformation (replacing, inserting, overwriting, and deleting of substrings). @end{Intro} @begin{Extend83} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Defn{extensions to Ada 83} This @Chg{Version=[3],New=[subclause],Old=[clause]} is new to Ada 95. @end{Extend83} @begin{Diffword95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Included Wide_Wide_String in this description; the individual changes are documented as extensions as needed.]} @end{Diffword95} @LabeledSubClause{The Package Strings} @begin{Intro} The package Strings provides declarations common to the string handling packages. @end{Intro} @begin{StaticSem} @Leading@;The library package Strings has the following declaration: @begin{example} @ChildUnit{Parent=[Ada],Child=[Strings]}@key[package] Ada.Strings @key[is] @key[pragma] Pure(Strings); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @AdaObjDefn{Space} : @key[constant] Character := ' '; @AdaObjDefn{Wide_Space} : @key[constant] Wide_Character := ' ';@Chg{Version=[2],New=[ @AdaObjDefn{Wide_Wide_Space} : @key[constant] Wide_Wide_Character := ' ';],Old=[]} @AdaExcDefn{Length_Error}, @AdaExcDefn{Pattern_Error}, @AdaExcDefn{Index_Error}, @AdaExcDefn{Translation_Error} : @key[exception]; @key[type] @AdaTypeDefn{Alignment} @key[is] (Left, Right, Center); @key[type] @AdaTypeDefn{Truncation} @key[is] (Left, Right, Error); @key[type] @AdaTypeDefn{Membership} @key[is] (Inside, Outside); @key[type] @AdaTypeDefn{Direction} @key[is] (Forward, Backward); @key[type] @AdaTypeDefn{Trim_End} @key[is] (Left, Right, Both); @key[end] Ada.Strings; @end{example} @end{StaticSem} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Constant Wide_Wide_Space is @Chg{Version=[3],New=[],Old=[newly ]}added to Ada.Strings. If Ada.Strings is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Wide_Wide_Space is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @RMNewPageVer{Version=[1]}@Comment{Insert page break so printed Ada 95 w/ Corr RM looks better.} @LabeledSubClause{The Package Strings.Maps} @begin{Intro} The package Strings.Maps defines the types, operations, and other entities needed for character sets and character-to-character mappings. @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Maps has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada.Strings],Child=[Maps]}@key[package] Ada.Strings.Maps @key[is] @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Maps); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@Examcom{ Representation for a set of character values:} @key[type] @AdaTypeDefn{Character_Set} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Character_Set);],Old=[]} @AdaObjDefn{Null_Set} : @key[constant] Character_Set; @key[type] @AdaTypeDefn{Character_Range} @key[is] @Key[record] Low : Character; High : Character; @key[end] @key[record]; -- @Examcom[Represents Character range Low..High] @key[type] @AdaTypeDefn{Character_Ranges} @key[is] @key[array] (Positive @key[range] <>) @key[of] Character_Range; @key[function] @AdaSubDefn{To_Set} (Ranges : @key[in] Character_Ranges)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Set} (Span : @key[in] Character_Range)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Ranges} (Set : @key[in] Character_Set) @key[return] Character_Ranges; @key[function] "=" (Left, Right : @key[in] Character_Set) @key[return] Boolean; @key[function] "@key[not]" (Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[and]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[or]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "@key[xor]" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] "-" (Left, Right : @key[in] Character_Set) @key[return] Character_Set; @key[function] @AdaSubDefn{Is_In} (Element : @key[in] Character; Set : @key[in] Character_Set) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Subset} (Elements : @key[in] Character_Set; Set : @key[in] Character_Set) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Character_Set; Right : @key[in] Character_Set) @key[return] Boolean @key[renames] Is_Subset; --@Examcom{ Alternative representation for a set of character values:} @key[subtype] @AdaSubtypeDefn{Name=[Character_Sequence],Of=[String]} @key[is] String; @key[function] @AdaSubDefn{To_Set} (Sequence : @key[in] Character_Sequence)@key[return] Character_Set; @key[function] @AdaSubDefn{To_Set} (Singleton : @key[in] Character) @key[return] Character_Set; @key[function] @AdaSubDefn{To_Sequence} (Set : @key[in] Character_Set) @key[return] Character_Sequence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@Examcom{ Representation for a character to character mapping:} @key[type] @AdaTypeDefn{Character_Mapping} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Character_Mapping);],Old=[]} @key[function] @AdaSubDefn{Value} (Map : @key[in] Character_Mapping; Element : @key[in] Character) @key[return] Character; @AdaObjDefn{Identity} : @key[constant] Character_Mapping; @key[function] @AdaSubDefn{To_Mapping} (From, To : @key[in] Character_Sequence) @key[return] Character_Mapping; @key[function] @AdaSubDefn{To_Domain} (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @key[function] @AdaSubDefn{To_Range} (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @key{type} @AdaTypeDefn{Character_Mapping_Function} @key{is} @key{access} @key{function} (From : @key{in} Character) @key{return} Character; @key[private] ... -- @Examcom{not specified by the language} @key[end] Ada.Strings.Maps; @end{example} An object of type Character_Set represents a set of characters. Null_Set represents the set containing no characters. An object Obj of type Character_Range represents the set of characters in the range Obj.Low .. Obj.High. An object Obj of type Character_Ranges represents the union of the sets corresponding to Obj(I) for I in Obj'Range. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] To_Set (Ranges : @key[in] Character_Ranges) @key[return] Character_Set; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If Ranges'Length=0 then Null_Set is returned; otherwise@Chg{Version=[3],New=[,],Old=[]} the returned value represents the set corresponding to Ranges. @begin{Example}@Keepnext @key[function] To_Set (Span : @key[in] Character_Range) @key[return] Character_Set; @end{Example} The returned value represents the set containing each character in Span. @begin{Example}@Keepnext @key[function] To_Ranges (Set : @key[in] Character_Set) @key[return] Character_Ranges; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If Set = Null_Set@Chg{Version=[3],New=[,],Old=[]} then an empty Character_Ranges array is returned; otherwise@Chg{Version=[3],New=[,],Old=[]} the shortest array of contiguous ranges of Character values in Set, in increasing order of Low, is returned. @begin{Example}@Keepnext @key[function] "=" (Left, Right : @key[in] Character_Set) @key[return] Boolean; @end{Example} @Trailing@;The function "=" returns True if Left and Right represent identical sets, and False otherwise. @end{DescribeCode} @Trailing@;Each of the logical operators "@key[not]", "@key[and]", "@key[or]", and "@key[xor]" returns a Character_Set value that represents the set obtained by applying the corresponding operation to the set(s) represented by the parameter(s) of the operator. "@en"(Left, Right) is equivalent to "and"(Left, "not"(Right)). @begin{reason} The set minus operator is provided for efficiency.@end{reason} @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Is_In (Element : @key[in] Character; Set : @key[in] Character_Set); @key[return] Boolean; @end{Example} @Trailing@;Is_In returns True if Element is in Set, and False otherwise. @begin{Example}@Keepnext @key[function] Is_Subset (Elements : @key[in] Character_Set; Set : @key[in] Character_Set) @key[return] Boolean; @end{Example} @Trailing@;Is_Subset returns True if Elements is a subset of Set, and False otherwise. @begin{Example}@Keepnext @key[subtype] Character_Sequence @key[is] String; @end{Example} @Trailing@;The Character_Sequence subtype is used to portray a set of character values and also to identify the domain and range of a character mapping. @begin{reason} Although a named subtype is redundant @em the predefined type String could have been used for the parameter to To_Set and To_Mapping below @em the use of a differently named subtype identifies the intended purpose of the parameter. @end{reason} @begin{Example}@Keepnext @key[function] To_Set (Sequence : @key[in] Character_Sequence) @key[return] Character_Set;@* @key[function] To_Set (Singleton : @key[in] Character) @key[return] Character_Set; @end{Example} @Trailing@;Sequence portrays the set of character values that it explicitly contains (ignoring duplicates). Singleton portrays the set comprising a single Character. Each of the To_Set functions returns a Character_Set value that represents the set portrayed by Sequence or Singleton. @begin{Example}@Keepnext @key[function] To_Sequence (Set : @key[in] Character_Set) @key[return] Character_Sequence; @end{Example} @Trailing@;The function To_Sequence returns a Character_Sequence value containing each of the characters in the set represented by Set, in ascending order with no duplicates. @begin{Example}@Keepnext @key[type] Character_Mapping @key[is] @key[private]; @end{Example} @Trailing@;An object of type Character_Mapping represents a Character-to-Character mapping. @begin{Example}@Keepnext @key[function] Value (Map : @key[in] Character_Mapping; Element : @key[in] Character) @key[return] Character; @end{Example} @Trailing@;The function Value returns the Character value to which Element maps with respect to the mapping represented by Map. @end{DescribeCode} @Defn2{Term=[match], Sec=(a character to a pattern character)} A character C @i{matches} a pattern character P with respect to a given Character_Mapping value Map if Value(Map, C) = P. @Defn2{Term=[match], Sec=(a string to a pattern string)} A string S @i{matches} a pattern string P with respect to a given Character_Mapping if their lengths are the same and if each character in S matches its corresponding character in the pattern string P. @begin{Discussion} In an earlier version of the string handling packages, the definition of matching was symmetrical, namely C matches P if Value(Map,C) = Value(Map,P). However, applying the mapping to the pattern was confusing according to some reviewers. Furthermore, if the symmetrical version is needed, it can be achieved by applying the mapping to the pattern (via translation) prior to passing it as a parameter. @end{Discussion} String handling subprograms that deal with character mappings have parameters whose type is Character_Mapping. @begin{DescribeCode} @begin{Example}@Keepnext Identity : @key[constant] Character_Mapping; @end{Example} @Trailing@;Identity maps each Character to itself. @begin{Example}@Keepnext @key[function] To_Mapping (From, To : @key[in] Character_Sequence) @key[return] Character_Mapping; @end{Example} @Trailing@;To_Mapping produces a Character_Mapping such that each element of From maps to the corresponding element of To, and each other character maps to itself. If From'Length /= To'Length, or if some character is repeated in From, then Translation_Error is propagated. @begin{Example}@Keepnext @key[function] To_Domain (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @end{Example} @Trailing@;To_Domain returns the shortest Character_Sequence value D such that each character not in D maps to itself, and such that the characters in D are in ascending order. The lower bound of D is 1. @begin{Example}@Keepnext @key[function] To_Range (Map : @key[in] Character_Mapping) @key[return] Character_Sequence; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0048],ARef=[AI95-00151-01]} @Trailing@;To_Range returns the Character_Sequence value R, @Chg{New=[],Old=[with lower bound 1 and upper bound Map'Length,]} such that if D = To_Domain(Map)@Chg{New=[, then R has the same bounds as D, and],Old=[ then]} D(I) maps to R(I) for each I in D'Range. @end{DescribeCode} An object F of type Character_Mapping_Function maps a Character value C to the Character value F.@key{all}(C), which is said to @i{match} C with respect to mapping function F. @Defn2[term=<match>,sec=<a character to a pattern character, with respect to a character mapping function>] @end{StaticSem} @begin{Notes} Character_Mapping and Character_Mapping_Function are used both for character equivalence mappings in the search subprograms (such as for case insensitivity) and as transformational mappings in the Translate subprograms. To_Domain(Identity) and To_Range(Identity) each returns the null string. @begin{Reason} Package Strings.Maps is not pure, since it declares an access-to-subprogram type. @end{Reason} @end{Notes} @begin{Examples} To_Mapping("ABCD", "ZZAB") returns a Character_Mapping that maps 'A' and 'B' to 'Z', 'C' to 'A', 'D' to 'B', and each other Character to itself. @end{Examples} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to types Character_Set and Character_Mapping, so that they can be used to declare default-initialized objects in preelaborated units.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Strings.Maps is now Pure, so it can be used in pure units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0048],ARef=[AI95-00151-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of the range of the result of To_Range, since the Ada 95 definition makes no sense.]} @end{DiffWord95} @LabeledSubClause{Fixed-Length String Handling} @begin{Intro} The language-defined package Strings.Fixed provides string-handling subprograms for fixed-length strings; that is, for values of type Standard.String. Several of these subprograms are procedures that modify the contents of a String that is passed as an @key[out] or an @key[in] @key[out] parameter; each has additional parameters to control the effect when the logical length of the result differs from the parameter's length. For each function that returns a String, the lower bound of the returned value is 1. @begin{Discussion} @Chgref{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Most operations that @Chg{Version=[2],New=[yield],Old=[yields]} a String are provided both as a function and as a procedure. The functional form is possibly a more aesthetic style but may introduce overhead due to extra copying or dynamic memory usage in some implementations. Thus a procedural form, with an @key[in] @key[out] parameter so that all copying is done `in place', is also supplied.@end{discussion} The basic model embodied in the package is that a fixed-length string comprises significant characters and possibly padding (with space characters) on either or both ends. When a shorter string is copied to a longer string, padding is inserted, and when a longer string is copied to a shorter one, padding is stripped. The Move procedure in Strings.Fixed, which takes a String as an @key[out] parameter, allows the programmer to control these effects. Similar control is provided by the string transformation procedures. @end{Intro} @begin{StaticSem} @Leading@keepnext @Leading@;The library package Strings.Fixed has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Fixed]}@key[package] Ada.Strings.Fixed @key[is] @key[pragma] Preelaborate(Fixed); --@Examcom{ "Copy" procedure for strings of possibly different lengths} @key[procedure] @AdaSubDefn{Move} (Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@Examcom{ Search subprograms} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural);]} @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@;--@Examcom{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping) @key[return] String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@;--@Examcom{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Insert} (Source : @key[in] String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Right); @key[function] @AdaSubDefn{Delete} (Source : @key[in] String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] String; From : @key[in] Positive; Through : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); --@Examcom{String selector subprograms} @key[function] @AdaSubDefn{Trim} (Source : @key[in] String; Side : @key[in] Trim_End) @key[return] String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] String; Side : @key[in] Trim_End; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Trim} (Source : @key[in] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set; Justify : @key[in] Alignment := Strings.Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Head} (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Tail} (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @keepnext@;--@Examcom{String constructor functions} @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] String; @key[end] Ada.Strings.Fixed; @end{example} The effects of the above subprograms are as follows. @begin{DescribeCode} @begin{Example}@Keepnext @key[procedure] Move (Source : @key[in] String; Target : @key[out] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} The Move procedure copies characters from Source to Target. If Source has the same length as Target, then the effect is to assign Source to Target. If Source is shorter than Target@Chg{Version=[3],New=[,],Old=[]} then: @begin{itemize} If Justify=Left, then Source is copied into the first Source'Length characters of Target. If Justify=Right, then Source is copied into the last Source'Length characters of Target. If Justify=Center, then Source is copied into the middle Source'Length characters of Target. In this case, if the difference in length between Target and Source is odd, then the extra Pad character is on the right. Pad is copied to each Target character not otherwise assigned. @end{itemize} If Source is longer than Target, then the effect is based on Drop. @begin{itemize} If Drop=Left, then the rightmost Target'Length characters of Source are copied into Target. If Drop=Right, then the leftmost Target'Length characters of Source are copied into Target. @Leading@;If Drop=Error, then the effect depends on the value of the Justify parameter and also on whether any characters in Source other than Pad would fail to be copied: @begin{inneritemize} If Justify=Left, and if each of the rightmost Source'Length-Target'Length characters in Source is Pad, then the leftmost Target'Length characters of Source are copied to Target. If Justify=Right, and if each of the leftmost Source'Length-Target'Length characters in Source is Pad, then the rightmost Target'Length characters of Source are copied to Target. @Trailing@;Otherwise, Length_Error is propagated. @end{inneritemize} @end{itemize} @begin{ramification} The Move procedure will work even if Source and Target overlap.@end{ramification} @begin{reason} The order of parameters (Source before Target) corresponds to the order in COBOL's MOVE verb.@end{reason} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0056-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Each Index function searches, starting from From, for a slice of Source, with length Pattern'Length, that matches Pattern with respect to Mapping; the parameter Going indicates the direction of the lookup. @Chg{Version=[3],New=[If Source is the null string, Index returns 0; otherwise, if],Old=[If]} From is not in Source'Range, then Index_Error is propagated. If Going = Forward, then Index returns the smallest index I which is greater than or equal to From such that the slice of Source starting at I matches Pattern. If Going = Backward, then Index returns the largest index I such that the slice of Source starting at I matches Pattern and has an upper bound less than or equal to From. If there is no such slice, then 0 is returned. If Pattern is the null string, then Pattern_Error is propagated.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no default parameter for From; the default value would need to depend on other parameters (the bounds of Source and the direction Going). It is better to use overloaded functions rather than a special value to represent the default.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[There is no default value for the Mapping parameter that is a Character_Mapping_Function; if there were, a call would be ambiguous since there is also a default for the Mapping parameter that is a Character_Mapping.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0056-1]} @ChgAdded{Version=[3],Text=[The language does not define when the Pattern_Error check is made. (That's because many common searching implementations require a nonempty pattern) That means that the result for a call like @f{Index ("", "")} could be 0 or could raise Pattern_Error. Similarly, in the call @f{Index ("", "", From => 2)}, the language does not define whether Pattern_Error or Index_Error is raised.]} @end{Discussion} @begin{Example}@Keepnext @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Index (Source : @key[in] String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} @Comment{@ChgDeleted{Version=[2],Type=[Trailing],Text=[]}@Comment{Fake to hold conditional format.}Can't have both.} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Fake to hold conditional format.} @Chg{Version=[2],New=[If Going = Forward, returns], Old=[Each Index function searches for a slice of Source, with length Pattern'Length, that matches Pattern with respect to Mapping; the parameter Going indicates the direction of the lookup. If Going = Forward, then Index returns the smallest index I such that the slice of Source starting at I matches Pattern. If Going = Backward, then Index returns the largest index I such that the slice of Source starting at I matches Pattern. If there is no such slice, then 0 is returned. If Pattern is the null string then Pattern_Error is propagated.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Index (Source, Pattern, Source'First, Forward, Mapping);]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[otherwise@Chg{Version=[3],New=[,],Old=[]} returns]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Trailing],Text=[ Index (Source, Pattern, Source'Last, Backward, Mapping);]} @end{Example} @begin{discussion} @ChgRef{Version=[2],Kind=[Deleted]}@ChgNote{Moved up} @ChgAdded{Version=[2],Text=[There is no default value for the Mapping parameter that is a Character_Mapping_Function; if there were, a call would be ambiguous since there is also a default for the Mapping parameter that is a Character_Mapping.]} @end{discussion} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0056-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Index searches for the first or last occurrence of any of a set of characters (when Test=Inside), or any of the complement of a set of characters (when Test=Outside). @Chg{Version=[3],New=[If Source is the null string, Index returns 0; otherwise, if],Old=[If]} From is not in Source'Range, then Index_Error is propagated. Otherwise, it returns the smallest index I >= From (if Going=Forward) or the largest index I <= From (if Going=Backward) such that Source(I) satisfies the Test condition with respect to Set; it returns 0 if there is no such Character in Source.]} @begin{Example}@Keepnext @key[function] Index (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @end{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} @Comment{@ChgDeleted{Version=[2],Type=[Trailing],Text=[]}@Comment{Fake to hold conditional format.}Can't have both.} @ChgAdded{Version=[2],Type=[Leading],Text=[]}@Comment{Fake to hold conditional format.} @Chg{Version=[2],New=[If Going = Forward, returns], Old=[Index searches for the first or last occurrence of any of a set of characters (when Test=Inside), or any of the complement of a set of characters (when Test=Outside). It returns the smallest index I (if Going=Forward) or the largest index I (if Going=Backward) such that Source(I) satisfies the Test condition with respect to Set; it returns 0 if there is no such Character in Source.]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[ Index (Source, Set, Source'First, Test, Forward);]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[otherwise@Chg{Version=[3],New=[,],Old=[]} returns]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Trailing],Text=[ Index (Source, Set, Source'Last, Test, Backward);]} @end{Example} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key[function] Index_Non_Blank (Source : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns Index (Source, Maps.To_Set(Space), From, Outside, Going);]} @begin{Example}@Keepnext @key[function] Index_Non_Blank (Source : @key[in] String; Going : @key[in] Direction := Forward) @key[return] Natural; @end{Example} @Trailing@;Returns Index(Source, Maps.To_Set(Space), Outside, Going) @begin{Example}@Keepnext @key[function] Count (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;@* @key[function] Count (Source : @key[in] String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @end{Example} @Trailing@;Returns the maximum number of nonoverlapping slices of Source that match Pattern with respect to Mapping. If Pattern is the null string then Pattern_Error is propagated. @begin{reason} We say `maximum number' because it is possible to slice a source string in different ways yielding different numbers of matches. For example if Source is "ABABABA" and Pattern is "ABA", then Count yields 2, although there is a partitioning of Source that yields just 1 match, for the middle slice. Saying `maximum number' is equivalent to saying that the pattern match starts either at the low index or the high index position. @end{reason} @begin{Example}@Keepnext @key[function] Count (Source : @key[in] String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @end{Example} @Trailing@;Returns the number of occurrences in Source of characters that are in Set. @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key[procedure] Find_Token (Source : @key[in] String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural);]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[If Source is not the null string and From is not in Source'Range, then Index_Error is raised. Otherwise, First is set to the index of the first character in Source(From .. Source'Last) that satisfies the Test condition. Last is set to the largest index such that all characters in Source(First .. Last) satisfy the Test condition. If no characters in Source(From .. Source'Last) satisfy the Test condition, First is set to From, and Last is set to 0.]} @begin{Example}@Keepnext @key[procedure] Find_Token (Source : @key[in] String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0031-1]} @Trailing@;@Chg{Version=[3],New=[Equivalent to Find_Token (Source, Set, Source'First, Test, First, Last).],Old=[Find_Token returns in First and Last the indices of the beginning and end of the first slice of Source all of whose elements satisfy the Test condition, and such that the elements (if any) immediately before and after the slice do not satisfy the Test condition. If no such slice exists, then the value returned for Last is zero, and the value returned for First is Source'First@Chg{New=[; however, if Source'First is not in Positive then Constraint_Error @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} is raised],Old=[]}.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[If Source'First is not in Positive, which can only happen for an empty string, this will raise Constraint_Error.]} @end{Ramification} @begin{Example}@Keepnext @key[function] Translate (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping) @key[return] String;@* @key[function] Translate (Source : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] String; @end{Example} @Trailing@;Returns the string S whose length is Source'Length and such that S(I) is the character to which Mapping maps the corresponding element of Source, for I in 1..Source'Length. @begin{Example}@Keepnext @key[procedure] Translate (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping);@* @key[procedure] Translate (Source : @key[in] @key[out] String; Mapping : @key[in] Maps.Character_Mapping_Function); @end{Example} @Trailing@;Equivalent to Source := Translate(Source, Mapping). @begin{Example}@Keepnext @key[function] Replace_Slice (Source : @key[in] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @Chg{New=[@Leading],Old=[@Trailing]}If Low > Source'Last+1, or High < Source'First@en@;1, then Index_Error is propagated. Otherwise@Chg{New=[:],Old=[, if High >= Low then the returned string comprises Source(Source'First..Low@en@;1) & By & Source(High+1..Source'Last), and if High < Low then the returned string is Insert(Source, Before=>Low, New_Item=>By).]} @begin{Itemize} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[1],Text=[If High >= Low, then the returned string comprises Source(Source'First..Low@en@;1) & By & Source(High+1..Source'Last), but with lower bound 1.@Trailing]} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[1],Text=[If High < Low, then the returned string is Insert(Source, Before=>Low, New_Item=>By).]} @end{Itemize} @begin{Example}@Keepnext @key[procedure] Replace_Slice (Source : @key[in] @key[out] String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Replace_Slice(Source, Low, High, By), Source, Drop, Justify, Pad). @begin{Example}@Keepnext @key[function] Insert (Source : @key[in] String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Propagates Index_Error if Before is not in Source'First .. Source'Last+1; otherwise@Chg{Version=[3],New=[,],Old=[]} returns Source(Source'First..Before@en@;1) & New_Item & Source(Before..Source'Last), but with lower bound 1. @begin{Example}@Keepnext @key[procedure] Insert (Source : @key[in] @key[out] String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @end{Example} @Trailing@;Equivalent to Move(Insert(Source, Before, New_Item), Source, Drop). @begin{Example}@Keepnext @key[function] Overwrite (Source : @key[in] String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] String; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Propagates Index_Error if Position is not in Source'First .. Source'Last+1; otherwise@Chg{Version=[3],New=[,],Old=[]} returns the string obtained from Source by consecutively replacing characters starting at Position with corresponding characters from New_Item. If the end of Source is reached before the characters in New_Item are exhausted, the remaining characters from New_Item are appended to the string. @begin{Example}@Keepnext @key[procedure] Overwrite (Source : @key[in] @key[out] String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Right); @end{Example} @Trailing@;Equivalent to Move(Overwrite(Source, Position, New_Item), Source, Drop). @begin{Example}@Keepnext @key[function] Delete (Source : @key[in] String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @Trailing@;If From <= Through, the returned string is Replace_Slice(Source, From, Through, "")@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is Source@Chg{New=[ with lower bound 1],Old=[]}. @begin{Example}@Keepnext @key[procedure] Delete (Source : @key[in] @key[out] String; From : @key[in] Positive; Through : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Delete(Source, From, Through), Source, Justify => Justify, Pad => Pad). @begin{Example}@Keepnext @key[function] Trim (Source : @key[in] String; Side : @key[in] Trim_End) @key[return] String; @end{Example} @Trailing@;Returns the string obtained by removing from Source all leading Space characters (if Side = Left), all trailing Space characters (if Side = Right), or all leading and trailing Space characters (if Side = Both). @begin{Example}@Keepnext @key[procedure] Trim (Source : @key[in] @key[out] String; Side : @key[in] Trim_End; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Trim(Source, Side), Source, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Trim (Source : @key[in] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] String; @end{Example} @Trailing@;Returns the string obtained by removing from Source all leading characters in Left and all trailing characters in Right. @begin{Example}@Keepnext @key[procedure] Trim (Source : @key[in] @key[out] String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set; Justify : @key[in] Alignment := Strings.Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Trim(Source, Left, Right), Source, Justify => Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Head (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Returns a string of length Count. If Count <= Source'Length, the string comprises the first Count characters of Source. Otherwise@Chg{Version=[3],New=[,],Old=[]} its contents are Source concatenated with Count@en@;Source'Length Pad characters. @begin{Example}@Keepnext @key[procedure] Head (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Head(Source, Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] Tail (Source : @key[in] String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] String; @end{Example} @Trailing@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} Returns a string of length Count. If Count <= Source'Length, the string comprises the last Count characters of Source. Otherwise@Chg{Version=[3],New=[,],Old=[]} its contents are Count-Source'Length Pad characters concatenated with Source. @begin{Example}@Keepnext @key[procedure] Tail (Source : @key[in] @key[out] String; Count : @key[in] Natural; Justify : @key[in] Alignment := Left; Pad : @key[in] Character := Space); @end{Example} @Trailing@;Equivalent to Move(Tail(Source, Count, Pad), Source, Drop=>Error, Justify=>Justify, Pad=>Pad). @begin{Example}@Keepnext @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] String;@* @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} These functions replicate a character or string a specified number of times. The first function returns a string whose length is Left and each of whose elements is Right. The second function returns a string whose length is Left*Right'Length and whose value is the null string if Left = 0 and @Chg{New=[otherwise ],Old=[]}is (Left@en@;1)*Right & Right @Chg{New=[with lower bound 1],Old=[otherwise]}. @end{DescribeCode} @end{StaticSem} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} In the Index and Count functions taking Pattern and Mapping parameters, the actual String parameter passed to Pattern should comprise characters occurring as target characters of the mapping. Otherwise@Chg{Version=[3],New=[,],Old=[]} the pattern will not match. In the Insert subprograms, inserting at the end of a string is obtained by passing Source'Last+1 as the Before parameter. @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Character_Mapping_Function is passed to any of the string handling subprograms, Constraint_Error is propagated. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Overloaded versions of Index and Index_Non_Blank are @Chg{Version=[3],New=[],Old=[newly ]}added to Strings.Fixed. If Strings.Fixed is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Index or Index_Non_Blank is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Find_Token may raise Constraint_Error if Source'First is not in Positive (which is only possible for a null string).]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that Replace_Slice, Delete, and "*" always return a string with lower bound 1.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} An overloaded version of Find_Token is added to Strings.Fixed. If Strings.Fixed is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Find_Token is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0056-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified that Index never raises Index_Error if the source string is null.]} @end{DiffWord2005} @LabeledSubClause{Bounded-Length String Handling} @begin{Intro} The language-defined package Strings.Bounded provides a generic package each of whose instances yields a private type Bounded_String and a set of operations. An object of a particular Bounded_String type represents a String whose low bound is 1 and whose length can vary conceptually between 0 and a maximum size established at the generic instantiation. The subprograms for fixed-length string handling are either overloaded directly for Bounded_String, or are modified as needed to reflect the variability in length. Additionally, since the Bounded_String type is private, appropriate constructor and selector operations are provided. @begin{reason} Strings.Bounded declares an inner generic package, versus itself being directly a generic child of Strings, in order to retain compatibility with a version of the string-handling packages that is generic with respect to the character and string types.@end{reason} @begin{reason} The bound of a bounded-length string is specified as a parameter to a generic, versus as the value for a discriminant, because of the inappropriateness of assignment and equality of discriminated types for the copying and comparison of bounded strings.@end{reason} @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The library package Strings.Bounded has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Bounded]}@key[package] Ada.Strings.Bounded @key[is] @key[pragma] Preelaborate(Bounded); @key[generic] Max : Positive; --@Examcom{ Maximum length of a Bounded_String} @key[package] @AdaPackDefn{Generic_Bounded_Length} @key[is] @AdaObjDefn{Max_Length} : @key[constant] Positive := Max; @key[type] @AdaTypeDefn{Bounded_String} @key[is] @key[private]; @AdaObjDefn{Null_Bounded_String} : @key[constant] Bounded_String; @key[subtype] @AdaSubtypeDefn{Name=[Length_Range],Of=[Natural]} @key[is] Natural @key[range] 0 .. Max_Length; @key[function] @AdaSubDefn{Length} (Source : @key[in] Bounded_String) @key[return] Length_Range; --@Examcom{ Conversion, Concatenation, and Selection functions} @key[function] @AdaSubDefn{To_Bounded_String} (Source : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{To_String} (Source : @key[in] Bounded_String) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Set_Bounded_String} (Target : @key[out] Bounded_String; Source : @key[in] String; Drop : @key[in] Truncation := Error);]} @key[function] @AdaSubDefn{Append} (Left, Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Bounded_String; Right : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] String; Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Bounded_String; Right : @key[in] Character; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Append} (Left : @key[in] Character; Right : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] Bounded_String; Drop : @key[in] Truncation := Error); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Bounded_String; New_Item : @key[in] Character; Drop : @key[in] Truncation := Error); @key[function] "&" (Left, Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Bounded_String; Right : @key[in] Character) @key[return] Bounded_String; @key[function] "&" (Left : @key[in] Character; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] @AdaSubDefn{Element} (Source : @key[in] Bounded_String; Index : @key[in] Positive) @key[return] Character; @key[procedure] @AdaSubDefn{Replace_Element} (Source : @key[in] @key[out] Bounded_String; Index : @key[in] Positive; By : @key[in] Character); @key[function] @AdaSubDefn{Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Bounded_Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Bounded_String;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Bounded_Slice} (Source : @key[in] Bounded_String; Target : @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @key[function] "=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">=" (Left, Right : @key[in] Bounded_String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] Bounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] String; Right : @key[in] Bounded_String) @key[return] Boolean; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} --@Examcom{ Search @Chg{Version=[2],New=[subprograms],Old=[functions]}} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Bounded_String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Bounded_String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural);]} @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Bounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@; --@Examcom{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] Bounded_String; Mapping : @key[in] Maps.Character_Mapping) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Bounded_String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] Bounded_String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Bounded_String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@; --@Examcom{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Insert} (Source : @key[in] Bounded_String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] Bounded_String; Before : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] Bounded_String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] Bounded_String; Position : @key[in] Positive; New_Item : @key[in] String; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Delete} (Source : @key[in] Bounded_String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] Bounded_String; From : @key[in] Positive; Through : @key[in] Natural); --@Examcom{String selector subprograms} @key[function] @AdaSubDefn{Trim} (Source : @key[in] Bounded_String; Side : @key[in] Trim_End) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Bounded_String; Side : @key[in] Trim_End); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Bounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Bounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set); @key[function] @AdaSubDefn{Head} (Source : @key[in] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error); @key[function] @AdaSubDefn{Tail} (Source : @key[in] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] Bounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space; Drop : @key[in] Truncation := Error); --@Examcom{String constructor subprograms} @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] Bounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] Bounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Bounded_String) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] Character; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[function] @AdaSubDefn{Replicate} (Count : @key[in] Natural; Item : @key[in] Bounded_String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @key[private] ... -- @Examcom{not specified by the language} @key[end] Generic_Bounded_Length; @key[end] Ada.Strings.Bounded; @end{example} @begin{ImplNote} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0097],ARef=[AI95-00115-01]} @ChgRef{Version=[2],Kind=[DeletedAdded],ARef=[AI95-00344-01]} @ChgDeleted{Version=[2],Text=[@Chg{Version=[1],New=[Bounded_String cannot be implemented as a (directly) controlled type, as Ada.Strings.Bounded.Generic_Bounded_Length can be instantiated at any nesting depth. Bounded_String could have a component of a controlled type, as long as that type is declared in some other (nongeneric) package (including directly in Ada.Strings.Bounded).],Old=[]}]} @ChgNote{AI-344 allows controlled types to be declared at any nesting depth, so this note is obsolete.} @end{ImplNote} Null_Bounded_String represents the null string. If an object of type Bounded_String is not otherwise initialized, it will be initialized to the same value as Null_Bounded_String. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Length (Source : @key[in] Bounded_String) @key[return] Length_Range; @end{Example} @Trailing@;The Length function returns the length of the string represented by Source. @begin{Example}@Keepnext @key[function] To_Bounded_String (Source : @key[in] String; Drop : @key[in] Truncation := Error) @key[return] Bounded_String; @end{Example} @Leading@ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} If Source'Length <= Max_Length@Chg{Version=[3],New=[,],Old=[]} then this function returns a Bounded_String that represents Source. Otherwise@Chg{Version=[3],New=[,],Old=[]} the effect depends on the value of Drop: @begin{itemize} If Drop=Left, then the result is a Bounded_String that represents the string comprising the rightmost Max_Length characters of Source. If Drop=Right, then the result is a Bounded_String that represents the string comprising the leftmost Max_Length characters of Source. @Trailing@;If Drop=Error, then Strings.Length_Error is propagated. @end{itemize} @begin{Example}@Keepnext @key[function] To_String (Source : @key[in] Bounded_String) @key[return] String; @end{Example} @Trailing@;To_String returns the String value with lower bound 1 represented by Source. If B is a Bounded_String, then B = To_Bounded_String(To_String(B)). @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[procedure] Set_Bounded_String (Target : @key[out] Bounded_String; Source : @key[in] String; Drop : @key[in] Truncation := Error);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Target := To_Bounded_String (Source, Drop);]} @end{DescribeCode} Each of the Append functions returns a Bounded_String obtained by concatenating the string or character given or represented by one of the parameters, with the string or character given or represented by the other parameter, and applying To_Bounded_String to the concatenation result string, with Drop as provided to the Append function. Each of the procedures Append(Source, New_Item, Drop) has the same effect as the corresponding assignment Source := Append(Source, New_Item, Drop). Each of the "&" functions has the same effect as the corresponding Append function, with Error as the Drop parameter. @begin{DescribeCode} @begin{Example}@Keepnext @key[function] Element (Source : @key[in] Bounded_String; Index : @key[in] Positive) @key[return] Character; @end{Example} @Trailing@;Returns the character at position Index in the string represented by Source; propagates Index_Error if Index > Length(Source). @begin{Example}@Keepnext @key[procedure] Replace_Element (Source : @key[in] @key[out] Bounded_String; Index : @key[in] Positive; By : @key[in] Character); @end{Example} @Trailing@;Updates Source such that the character at position Index in the string represented by Source is By; propagates Index_Error if Index > Length(Source). @begin{Example}@Keepnext @key[function] Slice (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @end{Example} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgRef{Version=[1],Kind=[Revised],ARef=[AI95-00238-01]} @Trailing@;Returns the slice at positions Low through High in the string represented by Source; propagates Index_Error if Low > Length(Source)+1@Chg{New=[ or High > Length(Source)],Old=[]}.@Chg{Version=[2], New=[ The bounds of the returned string are Low and High.],Old=[]}. @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[function] Bounded_Slice (Source : @key[in] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Bounded_String;]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns the slice at positions Low through High in the string represented by Source as a bounded string; propagates Index_Error if Low > Length(Source)+1 or High > Length(Source).]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],KeepNext=[T],Text=[@key[procedure] Bounded_Slice (Source : @key[in] Bounded_String; Target : @key[out] Bounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @end{Example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Equivalent to Target := Bounded_Slice (Source, Low, High);]} @end{DescribeCode} Each of the functions "=", "<", ">", "<=", and ">=" returns the same result as the corresponding String operation applied to the String values given or represented by the two parameters. Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token) has the same effect as the corresponding subprogram in Strings.Fixed applied to the string represented by the Bounded_String parameter. Each of the Translate subprograms, when applied to a Bounded_String, has an analogous effect to the corresponding subprogram in Strings.Fixed. For the Translate function, the translation is applied to the string represented by the Bounded_String parameter, and the result is converted (via To_Bounded_String) to a Bounded_String. For the Translate procedure, the string represented by the Bounded_String parameter after the translation is given by the Translate function for fixed-length strings applied to the string represented by the original value of the parameter. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0049],ARef=[AI95-00128-01]} Each of the transformation subprograms (Replace_Slice, Insert, Overwrite, Delete), selector subprograms (Trim, Head, Tail), and constructor functions ("*") has an effect based on its corresponding subprogram in Strings.Fixed, and Replicate is based on Fixed."*". @Chg{New=[In the case of a function], Old=[For each of these subprograms]}, the corresponding fixed-length string subprogram is applied to the string represented by the Bounded_String parameter. To_Bounded_String is applied the result string, with Drop (or Error in the case of Generic_Bounded_Length."*") determining the effect when the string length exceeds Max_Length. @Chg{New=[In the case of a procedure, the corresponding function in Strings.@!Bounded.@!Generic_@!Bounded_@!Length is applied, with the result assigned into the Source parameter.],Old=[]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The "/=" operations between Bounded_String and String, and between String and Bounded_String, are automatically defined based on the @Chg{Version=[2], New=[corresponding],Old=[corrsponding]} "=" operations. @end{Ramification} @end{StaticSem} @begin{ImplAdvice} Bounded string objects should not be implemented by implicit pointers and dynamic allocation. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Bounded string objects should not be implemented by implicit pointers and dynamic allocation.]}]} @begin{ImplNote} @Leading@;The following is a possible implementation of the private part of the package: @begin{example} @key[type] Bounded_String_Internals (Length : Length_Range := 0) @key[is] @key[record] Data : String(1..Length); @key[end] @key[record]; @key[type] Bounded_String @key[is] @key[record] Data : Bounded_String_Internals; --@Examcom{ Unconstrained} @key[end] @key[record]; Null_Bounded_String : @key[constant] Bounded_String := (Data => (Length => 0, Data => (1..0 => ' '))); @end{example} @end{ImplNote} @end{ImplAdvice} @begin{Inconsistent95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00238-01]} @ChgAdded{Version=[2],Text=[@Defn{inconsistencies with Ada 95} @B[Amendment Correction:] The bounds of the string returned from Slice are now defined. This is technically an inconsistency; if a program depended on some other lower bound for the string returned from Slice, it could fail when compiled with Ada 2005. Such code is not portable even between Ada 95 implementations, so it should be very rare.]} @end{Inconsistent95} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Procedure Set_Bounded_String, two Bounded_Slice subprograms, and overloaded versions of Index and Index_Non_Blank are @Chg{Version=[3],New=[],Old=[newly ]}added to Strings.Bounded.Generic_Bounded_Length. If an instance of Generic_Bounded_Length is referenced in a @nt{use_clause}, and an entity @i<E> with the @nt{defining_identifier} as a new entity in Generic_Bounded_Length is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the conditions for which Slice raises Index_Error.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0049],ARef=[AI95-00128-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of transformation, selector, and constructor subprograms by describing the effects of procedures and functions separately.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} An overloaded version of Find_Token is added to Strings.Bounded.Generic_Bounded_Length. If an instance of Generic_Bounded_Length is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Find_Token is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @LabeledSubClause{Unbounded-Length String Handling} @begin{Intro} The language-defined package Strings.Unbounded provides a private type Unbounded_String and a set of operations. An object of type Unbounded_String represents a String whose low bound is 1 and whose length can vary conceptually between 0 and Natural'Last. The subprograms for fixed-length string handling are either overloaded directly for Unbounded_String, or are modified as needed to reflect the flexibility in length. Since the Unbounded_String type is private, relevant constructor and selector operations are provided. @begin{reason} The transformation operations for fixed- and bounded-length strings that are not necessarily length preserving are supplied for Unbounded_String as procedures as well as functions. This allows an implementation to do an initial allocation for an unbounded string and to avoid further allocations as long as the length does not exceed the allocated length. @end{reason} @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Unbounded has the following declaration: @begin{example} @key[with] Ada.Strings.Maps; @ChildUnit{Parent=[Ada.Strings],Child=[Unbounded]}@key[package] Ada.Strings.Unbounded @key[is] @key[pragma] Preelaborate(Unbounded); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} @key[type] @AdaTypeDefn{Unbounded_String} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Unbounded_String);],Old=[]} @AdaObjDefn{Null_Unbounded_String} : @key[constant] Unbounded_String; @key[function] @AdaSubDefn{Length} (Source : @key[in] Unbounded_String) @key[return] Natural; @key[type] @AdaTypeDefn{String_Access} @key[is] @key[access] @key[all] String; @key[procedure] @AdaSubDefn{Free} (X : @key[in] @key[out] String_Access); --@Examcom{ Conversion, Concatenation, and Selection functions} @key[function] @AdaSubDefn{To_Unbounded_String} (Source : @key[in] String) @key[return] Unbounded_String; @key[function] @AdaSubDefn{To_Unbounded_String} (Length : @key[in] Natural) @key[return] Unbounded_String; @key[function] @AdaSubDefn{To_String} (Source : @key[in] Unbounded_String) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Set_Unbounded_String} (Target : @key[out] Unbounded_String; Source : @key[in] String);]} @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] Unbounded_String); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] String); @key[procedure] @AdaSubDefn{Append} (Source : @key[in out] Unbounded_String; New_Item : @key[in] Character); @key[function] "&" (Left, Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Unbounded_String; Right : @key[in] Character) @key[return] Unbounded_String; @key[function] "&" (Left : @key[in] Character; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[function] @AdaSubDefn{Element} (Source : @key[in] Unbounded_String; Index : @key[in] Positive) @key[return] Character; @key[procedure] @AdaSubDefn{Replace_Element} (Source : @key[in] @key[out] Unbounded_String; Index : @key[in] Positive; By : @key[in] Character); @key[function] @AdaSubDefn{Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] String; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Unbounded_Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural) @key[return] Unbounded_String;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[procedure] @AdaSubDefn{Unbounded_Slice} (Source : @key[in] Unbounded_String; Target : @key[out] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural);]} @key[function] "=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] "<=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">=" (Left, Right : @key[in] Unbounded_String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] Unbounded_String; Right : @key[in] String) @key[return] Boolean; @key[function] ">=" (Left : @key[in] String; Right : @key[in] Unbounded_String) @key[return] Boolean; --@Examcom{ Search subprograms} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural;]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; From : @key[in] Positive; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Going : @key[in] Direction := Forward; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership := Inside; Going : @key[in] Direction := Forward) @key[return] Natural; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[ @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Unbounded_String; From : @key[in] Positive; Going : @key[in] Direction := Forward) @key[return] Natural;]} @key[function] @AdaSubDefn{Index_Non_Blank} (Source : @key[in] Unbounded_String; Going : @key[in] Direction := Forward) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping := Maps.Identity) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Pattern : @key[in] String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Natural; @key[function] @AdaSubDefn{Count} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set) @key[return] Natural; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; From : @key[in] Positive; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural);]} @key[procedure] @AdaSubDefn{Find_Token} (Source : @key[in] Unbounded_String; Set : @key[in] Maps.Character_Set; Test : @key[in] Membership; First : @key[out] Positive; Last : @key[out] Natural); @Keepnext@;--@Examcom{ String translation subprograms} @key[function] @AdaSubDefn{Translate} (Source : @key[in] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping); @key[function] @AdaSubDefn{Translate} (Source : @key[in] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping_Function) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Translate} (Source : @key[in] @key[out] Unbounded_String; Mapping : @key[in] Maps.Character_Mapping_Function); @Keepnext@;--@Examcom{ String transformation subprograms} @key[function] @AdaSubDefn{Replace_Slice} (Source : @key[in] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Replace_Slice} (Source : @key[in] @key[out] Unbounded_String; Low : @key[in] Positive; High : @key[in] Natural; By : @key[in] String); @key[function] @AdaSubDefn{Insert} (Source : @key[in] Unbounded_String; Before : @key[in] Positive; New_Item : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Insert} (Source : @key[in] @key[out] Unbounded_String; Before : @key[in] Positive; New_Item : @key[in] String); @key[function] @AdaSubDefn{Overwrite} (Source : @key[in] Unbounded_String; Position : @key[in] Positive; New_Item : @key[in] String) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Overwrite} (Source : @key[in] @key[out] Unbounded_String; Position : @key[in] Positive; New_Item : @key[in] String); @key[function] @AdaSubDefn{Delete} (Source : @key[in] Unbounded_String; From : @key[in] Positive; Through : @key[in] Natural) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Delete} (Source : @key[in] @key[out] Unbounded_String; From : @key[in] Positive; Through : @key[in] Natural); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Unbounded_String; Side : @key[in] Trim_End) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Unbounded_String; Side : @key[in] Trim_End); @key[function] @AdaSubDefn{Trim} (Source : @key[in] Unbounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Trim} (Source : @key[in] @key[out] Unbounded_String; Left : @key[in] Maps.Character_Set; Right : @key[in] Maps.Character_Set); @key[function] @AdaSubDefn{Head} (Source : @key[in] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Head} (Source : @key[in] @key[out] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space); @key[function] @AdaSubDefn{Tail} (Source : @key[in] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space) @key[return] Unbounded_String; @key[procedure] @AdaSubDefn{Tail} (Source : @key[in] @key[out] Unbounded_String; Count : @key[in] Natural; Pad : @key[in] Character := Space); @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Character) @key[return] Unbounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] String) @key[return] Unbounded_String; @key[function] "*" (Left : @key[in] Natural; Right : @key[in] Unbounded_String) @key[return] Unbounded_String; @key[private] ... -- @Examcom{not specified by the language} @key[end] Ada.Strings.Unbounded; @end{example} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[The type Unbounded_String needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} Null_Unbounded_String represents the null String. If an object of type Unbounded_String is not otherwise initialized, it will be initialized to the same value as Null_Unbounded_String. The function Length returns the length of the String represented by Source. The type String_Access provides a (nonprivate) access type for explicit processing of unbounded-length strings. The procedure Free performs an unchecked deallocation of an object of type String_Access. The function To_Unbounded_String(Source : in String) returns an Unbounded_String that represents Source. The function To_Unbounded_String(Length : in Natural) returns an Unbounded_String that represents an uninitialized String whose length is Length. @Leading@;The function To_String returns the String with lower bound 1 represented by Source. To_String and To_Unbounded_String are related as follows: @begin{itemize} If S is a String, then To_String(To_Unbounded_String(S)) = S. If U is an Unbounded_String, then To_Unbounded_String(To_String(U)) = U. @end{itemize} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[The procedure Set_Unbounded_String sets Target to an Unbounded_String that represents Source.]} For each of the Append procedures, the resulting string represented by the Source parameter is given by the concatenation of the original value of Source and the value of New_Item. Each of the "&" functions returns an Unbounded_String obtained by concatenating the string or character given or represented by one of the parameters, with the string or character given or represented by the other parameter, and applying To_Unbounded_String to the concatenation result string. The Element, Replace_Element, and Slice subprograms have the same effect as the corresponding bounded-length string subprograms. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[The function Unbounded_Slice returns the slice at positions Low through High in the string represented by Source as an Unbounded_String. The procedure Unbounded_Slice sets Target to the Unbounded_String representing the slice at positions Low through High in the string represented by Source. Both @Chg{Version=[3],New=[subprograms],Old=[routines]} propagate Index_Error if Low > Length(Source)+1 or High > Length(Source).]} Each of the functions "=", "<", ">", "<=", and ">=" returns the same result as the corresponding String operation applied to the String values given or represented by Left and Right. Each of the search subprograms (Index, Index_Non_Blank, Count, Find_Token) has the same effect as the corresponding subprogram in Strings.Fixed applied to the string represented by the Unbounded_String parameter. The Translate function has an analogous effect to the corresponding subprogram in Strings.Fixed. The translation is applied to the string represented by the Unbounded_String parameter, and the result is converted (via To_Unbounded_String) to an Unbounded_String. Each of the transformation functions (Replace_Slice, Insert, Overwrite, Delete), selector functions (Trim, Head, Tail), and constructor functions ("*") is likewise analogous to its corresponding subprogram in Strings.Fixed. For each of the subprograms, the corresponding fixed-length string subprogram is applied to the string represented by the Unbounded_String parameter, and To_Unbounded_String is applied the result string. For each of the procedures Translate, Replace_Slice, Insert, Overwrite, Delete, Trim, Head, and Tail, the resulting string represented by the Source parameter is given by the corresponding function for fixed-length strings applied to the string represented by Source's original value. @end{StaticSem} @begin{ImplReq} No storage associated with an Unbounded_String object shall be lost upon assignment or scope exit. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00301-01]} A sample implementation of the private part of the package and several of the subprograms appears in the @Chg{Version=[2], New=[Ada 95 ],Old=[]}Rationale. @end{ImplNote} @end{ImplReq} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Type Unbounded_String is defined to need finalization. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and Unbounded_String does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as most Ada compilers have a controlled part in Unbounded_String, and thus would be illegal.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[Procedure Set_Unbounded_String, two Unbounded_Slice subprograms, and overloaded versions of Index and Index_Non_Blank are @Chg{Version=[3],New=[],Old=[newly ]}added to Strings.Unbounded. If Strings.Unbounded is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity in Strings.Unbounded is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added a @nt{pragma} Preelaborable_Initialization to type Unbounded_String, so that it can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0031-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} An overloaded version of Find_Token is added to Strings.Unbounded. If Strings.Unbounded is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Find_Token is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @LabeledSubClause{String-Handling Sets and Mappings} @begin{Intro} The language-defined package Strings.Maps.Constants declares Character_Set and Character_Mapping constants corresponding to classification and conversion functions in package Characters.Handling. @begin{discussion} The Constants package is a child of Strings.Maps since it needs visibility of the private part of Strings.Maps in order to initialize the constants in a preelaborable way (i.e. via aggregates versus function calls). @end{discussion} @end{Intro} @begin{StaticSem} @Leading@;The library package Strings.Maps.Constants has the following declaration: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @ChildUnit{Parent=[Ada.Strings.Maps],Child=[Constants]}@key[package] Ada.Strings.Maps.Constants @key[is] @key[pragma] @Chg{Version=[2],New=[Pure],Old=[Preelaborate]}(Constants); @AdaObjDefn{Control_Set} : @key[constant] Character_Set; @AdaObjDefn{Graphic_Set} : @key[constant] Character_Set; @AdaObjDefn{Letter_Set} : @key[constant] Character_Set; @AdaObjDefn{Lower_Set} : @key[constant] Character_Set; @AdaObjDefn{Upper_Set} : @key[constant] Character_Set; @AdaObjDefn{Basic_Set} : @key[constant] Character_Set; @AdaObjDefn{Decimal_Digit_Set} : @key[constant] Character_Set; @AdaObjDefn{Hexadecimal_Digit_Set} : @key[constant] Character_Set; @AdaObjDefn{Alphanumeric_Set} : @key[constant] Character_Set; @AdaObjDefn{Special_Set} : @key[constant] Character_Set; @AdaObjDefn{ISO_646_Set} : @key[constant] Character_Set; @AdaObjDefn{Lower_Case_Map} : @key[constant] Character_Mapping; --@Examcom{Maps to lower case for letters, else identity} @AdaObjDefn{Upper_Case_Map} : @key[constant] Character_Mapping; --@Examcom{Maps to upper case for letters, else identity} @AdaObjDefn{Basic_Map} : @key[constant] Character_Mapping; --@Examcom{Maps to basic letter for letters, else identity} @key[private] ... -- @Examcom{not specified by the language} @key[end] Ada.Strings.Maps.Constants; @end{example} Each of these constants represents a correspondingly named set of characters or character mapping in Characters.Handling (see @refsecnum(The Package Characters.Handling)). @end{StaticSem} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0114-1]} @ChgAdded{Version=[3],Text=[There are certain characters which are defined to be lower case letters by ISO 10646 and are therefore allowed in identifiers, but are not considered lower case letters by Ada.Strings.Maps.Constants.]} @begin{Reason} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This is to maintain runtime compatibility with the Ada 95 definitions of these constants; existing correct programs could break if the definitions were changed in a way the programs did not anticipate.]} @end{Reason} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Strings.Maps.Constants is now Pure, so it can be used in pure units.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0114-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added a note to clarify that these constants don't have any relationship to the characters allowed in identifiers.]} @end{DiffWord2005} @LabeledSubClause{Wide_String Handling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0286-1]} Facilities for handling strings of Wide_Character elements are found in the packages Strings.@!Wide_Maps, Strings.@!Wide_Fixed, Strings.@!Wide_@!Bounded, Strings.@!Wide_@!Unbounded, and Strings.@!Wide_Maps.@!Wide_@!Constants@Chg{Version=[2],New=[, and in the @Chg{Version=[3],New=[library ],Old=[]}functions Strings.@!Wide_Hash, Strings.@!Wide_Fixed.@!Wide_Hash, Strings.@!Wide_Bounded.@!Wide_Hash,@Chg{Version=[3],New=[],Old=[ and]} Strings.@!Wide_Unbounded.@!Wide_Hash@Chg{Version=[3],New=[, Strings.@!Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_@!Fixed.Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_@!Bounded.Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_@!Unbounded.Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_@!Equal_@!Case_@!Insensitive, Strings.@!Wide_@!Fixed.Wide_@!Equal_@!Case_@!Insensitive, Strings.@!Wide_@!Bounded.Wide_@!Equal_@!Case_@!Insensitive, and Strings.@!Wide_@!Unbounded.Wide_@!Equal_@!Case_@!Insensitive],Old=[]}],Old=[]}. They provide the same string-handling operations as the corresponding packages@Chg{Version=[2],New=[ and functions],Old=[]} for strings of Character elements. @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Fixed]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Bounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Unbounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Fixed],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Bounded],Child=[Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Unbounded],Child=[Wide_@!Hash]} @Chg{Version=[3],New=[@ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Fixed],Child=[Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Bounded],Child=[Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Unbounded],Child=[Wide_@!Equal_Case_Insensitive]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Fixed],Child=[Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Bounded],Child=[Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_@!Unbounded],Child=[Wide_@!Hash_Case_Insensitive]}],Old=[]} @ChildUnit{Parent=[Ada.Strings.Wide_@!Maps],Child=[Wide_@!Constants]} @end{Intro} @begin{StaticSem} The package Strings.Wide_Maps has the following declaration. @begin{example} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_@!Maps]}@key[package] Ada.Strings.Wide_Maps @key[is] @key[pragma] Preelaborate(Wide_Maps); @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@Examcom{ Representation for a set of Wide_Character values:} @key[type] @AdaTypeDefn{Wide_Character_Set} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Wide_Character_Set);],Old=[]} @AdaObjDefn{Null_Set} : @key[constant] Wide_Character_Set; @key[type] @AdaTypeDefn{Wide_Character_Range} @key[is] @key[record] Low : Wide_Character; High : Wide_Character; @key[end] @key[record]; -- @Examcom{Represents Wide_Character range Low..High} @key[type] @AdaTypeDefn{Wide_Character_Ranges} @key[is] @key[array] (Positive @key[range] <>) @key[of] Wide_Character_Range; @key[function] @AdaSubDefn{To_Set} (Ranges : @key[in] Wide_Character_Ranges) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Set} (Span : @key[in] Wide_Character_Range) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Ranges} (Set : @key[in] Wide_Character_Set) @key[return] Wide_Character_Ranges; @key[function] "=" (Left, Right : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] "@key[not]" (Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[and]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[or]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "@key[xor]" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] "-" (Left, Right : @key[in] Wide_Character_Set) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{Is_In} (Element : @key[in] Wide_Character; Set : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Subset} (Elements : @key[in] Wide_Character_Set; Set : @key[in] Wide_Character_Set) @key[return] Boolean; @key[function] "<=" (Left : @key[in] Wide_Character_Set; Right : @key[in] Wide_Character_Set) @key[return] Boolean @key[renames] Is_Subset; --@Examcom{ Alternative representation for a set of Wide_Character values:} @key[subtype] @AdaSubtypeDefn{Name=[Wide_Character_Sequence],Of=[Wide_String]} @key[is] Wide_String; @key[function] @AdaSubDefn{To_Set} (Sequence : @key[in] Wide_Character_Sequence) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Set} (Singleton : @key[in] Wide_Character) @key[return] Wide_Character_Set; @key[function] @AdaSubDefn{To_Sequence} (Set : @key[in] Wide_Character_Set) @key[return] Wide_Character_Sequence; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00161-01]} --@Examcom{ Representation for a Wide_Character to Wide_Character mapping:} @key[type] @AdaTypeDefn{Wide_Character_Mapping} @key[is] @key[private];@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization(Wide_Character_Mapping);],Old=[]} @key[function] @AdaSubDefn{Value} (Map : @key[in] Wide_Character_Mapping; Element : @key[in] Wide_Character) @key[return] Wide_Character; @AdaObjDefn{Identity} : @key[constant] Wide_Character_Mapping; @key[function] @AdaSubDefn{To_Mapping} (From, To : @key[in] Wide_Character_Sequence) @key[return] Wide_Character_Mapping; @key[function] @AdaSubDefn{To_Domain} (Map : @key[in] Wide_Character_Mapping) @key[return] Wide_Character_Sequence; @key[function] @AdaSubDefn{To_Range} (Map : @key[in] Wide_Character_Mapping) @key[return] Wide_Character_Sequence; @key{type} @AdaTypeDefn{Wide_Character_Mapping_Function} @key{is} @key{access} @key{function} (From : @key{in} Wide_Character) @key{return} Wide_Character; @key[private] ... -- @Examcom{not specified by the language} @key[end] Ada.Strings.Wide_Maps; @end{example} The context clause for each of the packages Strings.Wide_Fixed, Strings.Wide_Bounded, and Strings.Wide_Unbounded identifies Strings.Wide_Maps instead of Strings.Maps. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0223-1]} @ChgAdded{Version=[3],Text=[Types Wide_Character_Set and Wide_Character_Mapping need finalization.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00302-03]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0286-1]} @Leading@;For each of the packages Strings.Fixed, Strings.Bounded, Strings.Unbounded, and Strings.Maps.Constants@Chg{Version=[2],New=[, and for @Chg{Version=[3],New=[library ],Old=[]}functions Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash, @Chg{Version=[3],New=[],Old=[and ]}Strings.@!Unbounded.Hash, @Chg{Version=[3],New=[Strings.@!Hash_@!Case_@!Insensitive, Strings.@!Fixed.Hash_@!Case_@!Insensitive, Strings.@!Bounded.Hash_@!Case_@!Insensitive, Strings.@!Unbounded.Hash_@!Case_@!Insensitive, Strings.@!Equal_@!Case_@!Insensitive, Strings.@!Fixed.Equal_@!Case_@!Insensitive, Strings.@!Bounded.Equal_@!Case_@!Insensitive, and Strings.@!Unbounded.Equal_@!Case_@!Insensitive, ],Old=[]}],Old=[]}the corresponding wide string package @Chg{Version=[3],New=[or function ],Old=[]}has the same contents except that @begin{itemize} Wide_Space replaces Space Wide_Character replaces Character Wide_String replaces String Wide_Character_Set replaces Character_Set Wide_Character_Mapping replaces Character_Mapping Wide_Character_Mapping_Function replaces Character_Mapping_Function Wide_Maps replaces Maps Bounded_Wide_String replaces Bounded_String Null_Bounded_Wide_String replaces Null_Bounded_String To_Bounded_Wide_String replaces To_Bounded_String To_Wide_String replaces To_String @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Bounded_Wide_String replaces Set_Bounded_String]} Unbounded_Wide_String replaces Unbounded_String Null_Unbounded_Wide_String replaces Null_Unbounded_String Wide_String_Access replaces String_Access To_Unbounded_Wide_String replaces To_Unbounded_String @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Unbounded_Wide_String replaces Set_Unbounded_String]} @end{Itemize} @Leading@keepnext@;The following additional declaration is present in Strings.Wide_Maps.Wide_Constants: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @AdaObjDefn{Character_Set} : @key[constant] Wide_Maps.Wide_Character_Set; --@Examcom{Contains each Wide_Character value WC such that}@Chg{Version=[2],New=[ --],Old=[]}@Examcom{Characters.@Chg{Version=[2],New=[Conversions.],Old=[]}Is_Character(WC) is True} @end{example} @end{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Each Wide_Character_Set constant in the package Strings.Wide_Maps.Wide_Constants contains no values outside the Character portion of Wide_Character. Similarly, each Wide_Character_Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Character.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Pure is replaced by @nt{pragma} Preelaborate in Strings.Wide_Maps.Wide_Constants.]} @begin{Notes} @Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Wide_Character_Mapping_Function is passed to any of the Wide_String handling subprograms, Constraint_Error is propagated. @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00395-01]} @ChgDeleted{Version=[2],Text=[Each Wide_Character_Set constant in the package Strings.Wide_Maps.Wide_Constants contains no values outside the Character portion of Wide_Character. Similarly, each Wide_Character_Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Character.]} @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Various new operations are added to Strings.Wide_Fixed, Strings.Wide_Bounded, and Strings.Wide_Unbounded. If one of these packages is referenced in a @nt{use_clause}, and an entity @i<E> with the same @nt{defining_identifier} as a new entity is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Added @nt{pragma} Preelaborable_Initialization to types Wide_Character_Set and Wide_Character_Mapping, so that they can be used to declare default-initialized objects in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Corrected the description of Character_Set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[Added wide versions of Strings.Hash and Strings.Unbounded.Hash.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Added wording so that Strings.Wide_Maps.Wide_Constants does not change to Pure.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[The second Note is now normative text, since there is no way to derive it from the other rules. It's a little weird given the use of Unicode character classifications in Ada 2005; but changing it would be inconsistent with Ada 95 and a one-to-one mapping isn't necessarily correct anyway.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The case insenstive library functions (Strings.Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_@!Fixed.Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_@!Bounded.Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_@!Unbounded.Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_@!Hash_@!Case_@!Insensitive, Strings.Wide_@!Fixed.Wide_@!Hash_@!Case_@!Insensitive, Strings.Wide_@!Bounded.Wide_@!Hash_@!Case_@!Insensitive, and Strings.Wide_@!Unbounded.Wide_@!Hash_@!Case_@!Insensitive) are new.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0223-1]} @ChgAdded{Version=[3],Text=[@b<Correction>: Identified Wide_Character_Set and Wide_Character_Mapping as needing finalization. It is likely that they are implemented with a controlled type, so this change is unlikely to make any difference in practice.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[2],Name=[Wide_Wide_String Handling]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0286-1]} @ChgAdded{Version=[2],Text=[Facilities for handling strings of Wide_Wide_Character elements are found in the packages Strings.@!Wide_Wide_@!Maps, Strings.@!Wide_Wide_@!Fixed, Strings.@!Wide_Wide_@!Bounded, Strings.@!Wide_Wide_@!Unbounded, and Strings.@!Wide_Wide_@!Maps.@!Wide_Wide_@!Constants, and in the @Chg{Version=[3],New=[library ],Old=[]}functions Strings.@!Wide_Wide_@!Hash, Strings.@!Wide_Wide_@!Fixed.@!Wide_Wide_@!Hash, Strings.@!Wide_Wide_@!Bounded.@!Wide_@!Wide_@!Hash,@Chg{Version=[3],New=[],Old=[ and]} Strings.@!Wide_Wide_@!Unbounded.@!Wide_@!Wide_@!Hash@Chg{Version=[3],New=[, Strings.@!Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Fixed.Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Bounded.Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Unbounded.Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Fixed.Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.@!Wide_Wide_@!Bounded.Wide_Wide_@!Equal_@!Case_@!Insensitive, and Strings.@!Wide_Wide_@!Unbounded.Wide_Wide_@!Equal_@!Case_@!Insensitive],Old=[]}. They provide the same string-handling operations as the corresponding packages and functions for strings of Character elements. @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Fixed]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Bounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Unbounded]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Fixed],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Bounded],Child=[Wide_Wide_@!Hash]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Unbounded],Child=[Wide_Wide_@!Hash]} @Chg{Version=[3],New=[@ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Fixed],Child=[Wide_Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Bounded],Child=[Wide_Wide_@!Equal_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Unbounded],Child=[Wide_Wide_@!Equal_Case_Insensitive]} @ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Fixed],Child=[Wide_Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Bounded],Child=[Wide_Wide_@!Hash_Case_Insensitive]} @SubChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Unbounded],Child=[Wide_Wide_@!Hash_Case_Insensitive]}],Old=[]} @ChildUnit{Parent=[Ada.Strings.Wide_Wide_@!Maps],Child=[Wide_Wide_@!Constants]}]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The library package Strings.Wide_Wide_Maps has the following declaration.]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<package> Ada.Strings.Wide_Wide_Maps @key<is>@ChildUnit{Parent=[Ada.Strings],Child=[Wide_Wide_Maps]} @key<pragma> Preelaborate(Wide_Wide_Maps);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @Examcom[Representation for a set of Wide_Wide_Character values:] @key<type> @AdaTypeDefn{Wide_Wide_Character_Set} @key<is private>; @key<pragma> Preelaborable_Initialization(Wide_Wide_Character_Set);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Null_Set} : @key<constant> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Range} @key<is> @key<record> Low : Wide_Wide_Character; High : Wide_Wide_Character; @key<end record>; -- @Examcom[Represents Wide_Wide_Character range Low..High]]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Ranges} @key<is array> (Positive @key<range> <>) @key<of> Wide_Wide_Character_Range;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Ranges : @key<in> Wide_Wide_Character_Ranges) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Span : @key<in> Wide_Wide_Character_Range) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Ranges} (Set : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Ranges;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "=" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "@key<not>" (Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<and>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<or>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "@key<xor>" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set; @key<function> "-" (Left, Right : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_In} (Element : @key<in> Wide_Wide_Character; Set : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Is_Subset} (Elements : @key<in> Wide_Wide_Character_Set; Set : @key<in> Wide_Wide_Character_Set) @key<return> Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> "<=" (Left : @key<in> Wide_Wide_Character_Set; Right : @key<in> Wide_Wide_Character_Set) @key<return> Boolean @key<renames> Is_Subset;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @Examcom[Alternative representation for a set of Wide_Wide_Character values:] @key<subtype> @AdaSubtypeDefn{Name=[Wide_Wide_Character_Sequence],Of=[Wide_Wide_String]} @key<is> Wide_Wide_String;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Sequence : @key<in> Wide_Wide_Character_Sequence) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Set} (Singleton : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character_Set;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Sequence} (Set : @key<in> Wide_Wide_Character_Set) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ -- @Examcom[Representation for a Wide_Wide_Character to Wide_Wide_Character] -- @Examcom[mapping:] @key<type> @AdaTypeDefn{Wide_Wide_Character_Mapping} @key<is private>; @key<pragma> Preelaborable_Initialization(Wide_Wide_Character_Mapping);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{Value} (Map : @key<in> Wide_Wide_Character_Mapping; Element : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Identity} : @key<constant> Wide_Wide_Character_Mapping;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Mapping} (From, To : @key<in> Wide_Wide_Character_Sequence) @key<return> Wide_Wide_Character_Mapping;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Domain} (Map : @key<in> Wide_Wide_Character_Mapping) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<function> @AdaSubDefn{To_Range} (Map : @key<in> Wide_Wide_Character_Mapping) @key<return> Wide_Wide_Character_Sequence;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Wide_Wide_Character_Mapping_Function} @key<is> @key<access function> (From : @key<in> Wide_Wide_Character) @key<return> Wide_Wide_Character;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<private> ... -- @Examcom[not specified by the language] @key<end> Ada.Strings.Wide_Wide_Maps;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@ChildUnit{Parent=[Ada.Strings.Wide_@!Maps],Child=[Wide_@!Constants]} The context clause for each of the packages Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, and Strings.Wide_Wide_Unbounded identifies Strings.Wide_Wide_Maps instead of Strings.Maps.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0223-1]} @ChgAdded{Version=[3],Text=[Types Wide_Wide_Character_Set and Wide_Wide_Character_Mapping need finalization.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0286-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[For each of the packages Strings.@!Fixed, Strings.@!Bounded, Strings.@!Unbounded, and Strings.@!Maps.Constants, and for @Chg{Version=[3],New=[library ],Old=[]}functions Strings.@!Hash, Strings.@!Fixed.Hash, Strings.@!Bounded.Hash, @Chg{Version=[3],New=[],Old=[and ]}Strings.@!Unbounded.Hash, @Chg{Version=[3],New=[Strings.@!Hash_@!Case_@!Insensitive, Strings.@!Fixed.Hash_@!Case_@!Insensitive, Strings.@!Bounded.Hash_@!Case_@!Insensitive, Strings.@!Unbounded.Hash_@!Case_@!Insensitive, Strings.@!Equal_@!Case_@!Insensitive, Strings.@!Fixed.Equal_@!Case_@!Insensitive, Strings.@!Bounded.Equal_@!Case_@!Insensitive, and Strings.@!Unbounded.Equal_@!Case_@!Insensitive, ],Old=[]}the corresponding wide wide string package or function has the same contents except that]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Space replaces Space]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character replaces Character]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_String replaces String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Set replaces Character_Set]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Mapping replaces Character_Mapping]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Character_Mapping_Function replaces Character_Mapping_Function]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_Maps replaces Maps]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Bounded_Wide_Wide_String replaces Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Null_Bounded_Wide_Wide_String replaces Null_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Bounded_Wide_Wide_String replaces To_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Wide_Wide_String replaces To_String]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Bounded_Wide_Wide_String replaces Set_Bounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unbounded_Wide_Wide_String replaces Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Null_Unbounded_Wide_Wide_String replaces Null_Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Wide_Wide_String_Access replaces String_Access]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[To_Unbounded_Wide_Wide_String replaces To_Unbounded_String]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00301-01]} @ChgAdded{Version=[2],Text=[Set_Unbounded_Wide_Wide_String replaces Set_Unbounded_String]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following additional declarations are present in Strings.Wide_Wide_Maps.Wide_Wide_Constants:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@AdaObjDefn{Character_Set} : @key<constant> Wide_Wide_Maps.Wide_Wide_Character_Set; -- @Examcom[Contains each Wide_Wide_Character value WWC such that] -- @Examcom[Characters.Conversions.Is_Character(WWC) is True] @AdaObjDefn{Wide_Character_Set} : @key<constant> Wide_Wide_Maps.Wide_Wide_Character_Set; -- @Examcom[Contains each Wide_Wide_Character value WWC such that] -- @Examcom[Characters.Conversions.Is_Wide_Character(WWC) is True]]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[Each Wide_Wide_Character_Set constant in the package Strings.@!Wide_Wide_@!Maps.@!Wide_Wide_@!Constants contains no values outside the Character portion of Wide_Wide_@!Character. Similarly, each Wide_Wide_@!Character_@!Mapping constant in this package is the identity mapping when applied to any element outside the Character portion of Wide_Wide_Character.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Pure is replaced by @nt{pragma} Preelaborate in Strings.Wide_Wide_Maps.Wide_Wide_Constants.]} @end{StaticSem} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[Constraint_Error],Sec=(raised by failure of run-time check)} If a null Wide_Wide_Character_Mapping_Function is passed to any of the Wide_Wide_String handling subprograms, Constraint_Error is propagated.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00395-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The double-wide string-handling packages (Strings.Wide_Wide_Maps, Strings.Wide_Wide_Fixed, Strings.Wide_Wide_Bounded, Strings.Wide_Wide_Unbounded, and Strings.Wide_Wide_Maps.Wide_Wide_Constants), and functions Strings.Wide_Wide_Hash and Strings.Wide_Wide_Unbounded.Wide_Wide_Hash are new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The case insenstive library functions (Strings.Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_Wide_@!Fixed.Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_Wide_@!Bounded.Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_Wide_@!Unbounded.Wide_Wide_@!Equal_@!Case_@!Insensitive, Strings.Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.Wide_Wide_@!Fixed.Wide_Wide_@!Hash_@!Case_@!Insensitive, Strings.Wide_Wide_@!Bounded.Wide_Wide_@!Hash_@!Case_@!Insensitive, and Strings.Wide_Wide_@!Unbounded.Wide_Wide_@!Hash_@!Case_@!Insensitive) are new.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0223-1]} @ChgAdded{Version=[3],Text=[@b<Correction>: Identified Wide_Wide_Character_Set and Wide_Wide_Character_Mapping as needing finalization. It is likely that they are implemented with a controlled type, so this change is unlikely to make any difference in practice.]} @end{DiffWord2005} @LabeledAddedSubClause{Version=[2],Name=[String Hashing]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<function> Ada.Strings.Hash (Key : String) @key<return> Containers.Hash_Type;@SubChildUnit{Parent=[Ada.Strings],Child=[Hash]} @key<pragma> Pure(@Chg{Version=[3],New=[Ada.Strings.Hash],Old=[Hash]});]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Trailing],Text=[Returns an implementation-defined value which is a function of the value of Key. If @i<A> and @i<B> are strings such that @i<A> equals @i<B>, Hash(@i<A>) equals Hash(@i<B>).]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values returned by Strings.Hash.]}]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Fixed.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers, Ada.Strings.Hash; @key<function> Ada.Strings.Fixed.Hash (Key : String) @key<return> Containers.Hash_Type @key<renames> Ada.Strings.Hash;@Chg{Version=[3],New=[],Old=[ @key<pragma> Pure(Hash);]}]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The generic library function Strings.Bounded.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<generic>@SubChildUnit{Parent=[Ada.Strings.Bounded],Child=[Hash]} @key<with package> Bounded @key<is> @key<new> Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key<function> Ada.Strings.Bounded.Hash (Key : Bounded.Bounded_String) @key<return> Containers.Hash_Type; @key<pragma> Preelaborate(@Chg{Version=[3],New=[Ada.Strings.Bounded.Hash],Old=[Hash]});]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[Equivalent to], Old=[Strings.Bounded.Hash is equivalent to the function call]} Strings.Hash (Bounded.To_String (Key));]} @end{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Unbounded.Hash has the following declaration:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0298-1]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Containers; @key<function> Ada.Strings.Unbounded.Hash (Key : Unbounded_String)@SubChildUnit{Parent=[Ada.Strings.Unbounded],Child=[Hash]} @key<return> Containers.Hash_Type; @key<pragma> Preelaborate(@Chg{Version=[3],New=[Ada.Strings.Unbounded.Hash],Old=[Hash]});]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0001-1]} @ChgAdded{Version=[2],Type=[Trailing],Text=[@Chg{Version=[3],New=[Equivalent to], Old=[Strings.Unbounded.Hash is equivalent to the function call]} Strings.Hash (To_String (Key));]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Hash_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key<with> Ada.Containers; @key<function> Ada.Strings.Hash_Case_Insensitive (Key : String)@SubChildUnit{Parent=[Ada.Strings],Child=[Hash_Case_Insensitive]} @key<return> Containers.Hash_Type; @key<pragma> Pure(Ada.Strings.Hash_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns an implementation-defined value which is a function of the value of Key, converted to lower case. If A and B are strings such that Strings.Equal_Case_Insensitive (A, B) (see @RefSecNum{String Comparison}) is True, then Hash_Case_Insensitive(A) equals Hash_Case_Insensitive(B).]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Fixed.Hash_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key<with> Ada.Containers, Ada.Strings.Hash_Case_Insensitive; @key[function] Ada.Strings.Fixed.Hash_Case_Insensitive (Key : String)@SubChildUnit{Parent=[Ada.Strings.Fixed],Child=[Hash_Case_Insensitive]} @key[return] Containers.Hash_Type @key[renames] Ada.Strings.Hash_Case_Insensitive;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library function Strings.Bounded.Hash_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key<with> Ada.Containers; @key[generic] @key[with package] Bounded @key[is] @key[new] Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key[function] Ada.Strings.Bounded.Hash_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Bounded],Child=[Hash_Case_Insensitive]} (Key : Bounded.Bounded_String) @key[return] Containers.Hash_Type; @key[pragma] Preelaborate(Ada.Strings.Bounded.Hash_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Hash_Case_Insensitive (Bounded.To_String (Key));]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0001-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Unbounded.Hash_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key<with> Ada.Containers; @key[function] Ada.Strings.Unbounded.Hash_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Unbounded],Child=[Hash_Case_Insensitive]} (Key : Unbounded_String) @key[return] Containers.Hash_Type; @key[pragma] Preelaborate(Ada.Strings.Unbounded.Hash_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Hash_Case_Insensitive (To_String (Key));]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[The Hash functions should be good hash functions, returning a wide spread of values for different string values. It should be unlikely for similar strings to return the same value.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Strings.Hash should be good a hash function, returning a wide spread of values for different string values, and similar strings should rarely return the same value.]}]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The other functions are defined in terms of Strings.Hash, so they don't need separate advice in the Annex.]} @end{Ramification} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00302-03]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Strings.Hash, Strings.Fixed.Hash, Strings.Bounded.Hash, and Strings.Unbounded.Hash functions are new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The Strings.Hash_Case_Insensitive, Strings.Fixed.Hash_Case_Insensitive, Strings.Bounded.Hash_Case_Insensitive, and Strings.Unbounded.Hash_Case_Insensitive functions are new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[String Comparison]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0286-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Equal_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] Ada.Strings.Equal_Case_Insensitive (Left, Right : String)@SubChildUnit{Parent=[Ada.Strings],Child=[Equal_Case_Insensitive]} @key[return] Boolean; @key[pragma] Pure(Ada.Strings.Equal_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns True if the strings consist of the same sequence of characters after applying locale-independent simple case folding, as defined by documents referenced in the note in Clause 1 of ISO/IEC 10646:2011. Otherwise, returns False. This function uses the same method as is used to determine whether two identifiers are the same.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[For String, this is equivalent to converting to lower case and comparing. Not so for other string types. For Wide_Strings and Wide_Wide_Strings, note that this result is a more accurate comparison than converting the strings to lower case and comparing the results; it is possible that the lower case conversions are the same but this routine will report the strings as different. Additionally, Unicode says that the result of this function will never change for strings made up solely of defined code points; there is no such guarantee for case conversion to lower case.]} @end{Discussion} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Fixed.Equal_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Ada.Strings.Equal_Case_Insensitive; @key[function] Ada.Strings.Fixed.Equal_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Fixed],Child=[Equal_Case_Insensitive]} (Left, Right : String) @key[return] Boolean @key[renames] Ada.Strings.Equal_Case_Insensitive;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library function Strings.Bounded.Equal_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[with package] Bounded @key[is] @key[new] Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key[function] Ada.Strings.Bounded.Equal_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Bounded],Child=[Equal_Case_Insensitive]} (Left, Right : Bounded.Bounded_String) @key[return] Boolean; @key[pragma] Preelaborate(Ada.Strings.Bounded.Equal_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Equal_Case_Insensitive (Bounded.To_String (Left), Bounded.To_String (Right));]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Unbounded.Equal_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] Ada.Strings.Unbounded.Equal_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Unbounded],Child=[Equal_Case_Insensitive]} (Left, Right : Unbounded_String) @key[return] Boolean; @key[pragma] Preelaborate(Ada.Strings.Unbounded.Equal_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Equal_Case_Insensitive (To_String (Left), To_String (Right));]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Less_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] Ada.Strings.Less_Case_Insensitive (Left, Right : String)@SubChildUnit{Parent=[Ada.Strings],Child=[Less_Case_Insensitive]} @key[return] Boolean; @key[pragma] Pure(Ada.Strings.Less_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Performs a lexicographic comparison of strings Left and Right, converted to lower case.]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Fixed.Less_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Ada.Strings.Less_Case_Insensitive; @key[function] Ada.Strings.Fixed.Less_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Fixed],Child=[Less_Case_Insensitive]} (Left, Right : String) @key[return] Boolean @key[renames] Ada.Strings.Less_Case_Insensitive;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The generic library function Strings.Bounded.Less_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[generic] @key[with package] Bounded @key[is] @key[new] Ada.Strings.Bounded.Generic_Bounded_Length (<>); @key[function] Ada.Strings.Bounded.Less_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Bounded],Child=[Less_Case_Insensitive]} (Left, Right : Bounded.Bounded_String) @key[return] Boolean; @key[pragma] Preelaborate(Ada.Strings.Bounded.Less_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Less_Case_Insensitive (Bounded.To_String (Left), Bounded.To_String (Right));]} @end{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0248-1],ARef=[AI05-0298-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The library function Strings.Unbounded.Less_Case_Insensitive has the following declaration:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[function] Ada.Strings.Unbounded.Less_Case_Insensitive@SubChildUnit{Parent=[Ada.Strings.Unbounded],Child=[Less_Case_Insensitive]} (Left, Right : Unbounded_String) @key[return] Boolean; @key[pragma] Preelaborate(Ada.Strings.Unbounded.Less_Case_Insensitive);]} @end{Example} @begin{DescribeCode} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Equivalent to Strings.Less_Case_Insensitive (To_String (Left), To_String (Right));]} @end{DescribeCode} @end{StaticSem} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0001-1],ARef=[AI05-0286-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The Strings.Equal_Case_Insensitive, Strings.Fixed.Equal_Case_Insensitive, Strings.Bounded.Equal_Case_Insensitive, Strings.Unbounded.Equal_Case_Insensitive, Strings.Less_Case_Insensitive, Strings.Fixed.Less_Case_Insensitive, Strings.Bounded.Less_Case_Insensitive, Strings.Unbounded.Less_Case_Insensitive functions are new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[String Encoding]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[Facilities for encoding, decoding, and converting strings in various character encoding schemes are provided by packages Strings.@!UTF_Encoding, Strings.@!UTF_Encoding.@!Conversions, Strings.@!UTF_Encoding.@!Strings, Strings.@!UTF_Encoding.@!Wide_Strings, and Strings.@!UTF_Encoding.@!Wide_Wide_Strings.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[The encoding library packages have the following declarations:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada.Strings],Child=[UTF_Encoding]}@key[package] Ada.Strings.UTF_Encoding @key[is] @key[pragma] Pure (UTF_Encoding);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom[Declarations common to the string encoding packages] @key[type] @AdaTypeDefn{Encoding_Scheme} @key[is] (UTF_8, UTF_16BE, UTF_16LE);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[subtype] @AdaSubtypeDefn{Name=[UTF_String],Of=[String]} @key[is] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[subtype] @AdaSubtypeDefn{Name=[UTF_8_String],Of=[String]} @key[is] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[subtype] @AdaSubtypeDefn{Name=[UTF_16_Wide_String],Of=[Wide_String]} @key[is] Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaExcDefn{Encoding_Error} : @key[exception];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{BOM_8} : @key[constant] UTF_8_String := Character'Val(16#EF#) & Character'Val(16#BB#) & Character'Val(16#BF#);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{BOM_16BE} : @key[constant] UTF_String := Character'Val(16#FE#) & Character'Val(16#FF#);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{BOM_16LE} : @key[constant] UTF_String := Character'Val(16#FF#) & Character'Val(16#FE#);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{BOM_16} : @key[constant] UTF_16_Wide_String := (1 => Wide_Character'Val(16#FEFF#));]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encoding} (Item : UTF_String; Default : Encoding_Scheme := UTF_8) @key[return] Encoding_Scheme;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Strings.UTF_Encoding;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada.Strings.UTF_Encoding],Child=[Conversions]}@key[package] Ada.Strings.UTF_Encoding.Conversions @key[is] @key[pragma] Pure (Conversions);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Conversions between various encoding schemes} @key[function] @AdaSubDefn{Convert} (Item : UTF_String; Input_Scheme : Encoding_Scheme; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Convert} (Item : UTF_String; Input_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Convert} (Item : UTF_8_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Convert} (Item : UTF_16_Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Convert} (Item : UTF_16_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Strings.UTF_Encoding.Conversions;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada.Strings.UTF_Encoding],Child=[Strings]}@key[package] Ada.Strings.UTF_Encoding.Strings @key[is] @key[pragma] Pure (Strings);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Encoding / decoding between String and various encoding schemes} @key[function] @AdaSubDefn{Encode} (Item : String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_8_String) @key[return] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_16_Wide_String) @key[return] String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Strings.UTF_Encoding.Strings;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada.Strings.UTF_Encoding],Child=[Wide_Strings]}@key[package] Ada.Strings.UTF_Encoding.Wide_Strings @key[is] @key[pragma] Pure (Wide_Strings);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Encoding / decoding between Wide_String and various encoding schemes} @key[function] @AdaSubDefn{Encode} (Item : Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : Wide_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_8_String) @key[return] Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_16_Wide_String) @key[return] Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Strings.UTF_Encoding.Wide_Strings;]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@ChildUnit{Parent=[Ada.Strings.UTF_Encoding],Child=[Wide_Wide_Strings]}@key[package] Ada.Strings.UTF_Encoding.Wide_Wide_Strings @key[is] @key[pragma] Pure (Wide_Wide_Strings);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ -- @Examcom{Encoding / decoding between Wide_Wide_String and various encoding schemes} @key[function] @AdaSubDefn{Encode} (Item : Wide_Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : Wide_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Encode} (Item : Wide_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] Wide_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_8_String) @key[return] Wide_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Decode} (Item : UTF_16_Wide_String) @key[return] Wide_Wide_String;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[end] Ada.Strings.UTF_Encoding.Wide_Wide_Strings;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The type Encoding_Scheme defines encoding schemes. UTF_8 corresponds to the UTF-8 encoding scheme defined by Annex D of ISO/IEC 10646. UTF_16BE corresponds to the UTF-16 encoding scheme defined by Annex C of ISO/IEC 10646 in 8 bit, big-endian order; and UTF_16LE corresponds to the UTF-16 encoding scheme in 8 bit, little-endian order.@Defn{encoding scheme}@Defn{character encoding}@Defn{UTF-8}@Defn{UTF-16}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[The subtype UTF_String is used to represent a String of 8-bit values containing a sequence of values encoded in one of three ways (UTF-8, UTF-16BE, or UTF-16LE). The subtype UTF_8_String is used to represent a String of 8-bit values containing a sequence of values encoded in UTF-8. The subtype UTF_16_Wide_String is used to represent a Wide_String of 16-bit values containing a sequence of values encoded in UTF-16.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[The BOM_8, BOM_16BE, BOM_16LE, and BOM_16 constants correspond to values used at the start of a string to indicate the encoding.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Each of the Encode functions takes a String, Wide_String, or Wide_Wide_String Item parameter that is assumed to be an array of unencoded characters. Each of the Convert functions takes a UTF_String, UTF_8_String, or UTF_16_String Item parameter that is assumed to contain characters whose position values correspond to a valid encoding sequence according to the encoding scheme required by the function or specified by its Input_Scheme parameter.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0262-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[Each of the Convert and Encode functions returns a UTF_String, UTF_8_String, or UTF_16_String value whose characters have position values that correspond to the encoding of the Item parameter according to the encoding scheme required by the function or specified by its Output_Scheme parameter. For UTF_8, no overlong encoding is returned. A BOM is included at the start of the returned string if the Output_BOM parameter is set to True. The lower bound of the returned string is 1.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[Each of the Decode functions takes a UTF_String, UTF_8_String, or UTF_16_String Item parameter which is assumed to contain characters whose position values correspond to a valid encoding sequence according to the encoding scheme required by the function or specified by its Input_Scheme parameter, and returns the corresponding String, Wide_String, or Wide_Wide_String value. The lower bound of the returned string is 1.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[For each of the Convert and Decode functions, an initial BOM in the input that matches the expected encoding scheme is ignored, and a different initial BOM causes Encoding_Error to be propagated.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Type=[Leading],Text=[The exception Encoding_Error is also propagated in the following situations:]} @begin{Itemize} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[By a Decode function when a UTF encoded string contains an invalid encoding sequence.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[By a Decode function when the expected encoding is UTF-16BE or UTF-16LE and the input string has an odd length.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[By a Decode function yielding a String when the decoding of a sequence results in a code point whose value exceeds 16#FF#.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[By a Decode function yielding a Wide_String when the decoding of a sequence results in a code point whose value exceeds 16#FFFF#.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[By an Encode function taking a Wide_String as input when an invalid character appears in the input. In particular, the characters whose position is in the range 16#D800# .. 16#DFFF# are invalid because they conflict with UTF-16 surrogate encodings, and the characters whose position is 16#FFFE# or 16#FFFF# are also invalid because they conflict with BOM codes.]} @end{Itemize} @begin{DescribeCode} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encoding (Item : UTF_String; Default : Encoding_Scheme := UTF_8) @key[return] Encoding_Scheme;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Inspects a UTF_String value to determine whether it starts with a BOM for UTF-8, UTF-16BE, or UTF_16LE. If so, returns the scheme corresponding to the BOM; otherwise, returns the value of Default.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Convert (Item : UTF_String; Input_Scheme : Encoding_Scheme; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item (originally encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Input_Scheme) encoded in one of these three schemes as specified by Output_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Convert (Item : UTF_String; Input_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item (originally encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Input_Scheme) encoded in UTF-16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Convert (Item : UTF_8_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item (originally encoded in UTF-8) encoded in UTF-16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Convert (Item : UTF_16_Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item (originally encoded in UTF-16) encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Output_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Convert (Item : UTF_16_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item (originally encoded in UTF-16) encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Output_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF_16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Input_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_8_String) @key[return] String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_16_Wide_String) @key[return] String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Output_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF_16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Input_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_8_String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_16_Wide_String) @key[return] Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_Wide_String; Output_Scheme : Encoding_Scheme; Output_BOM : Boolean := False) @key[return] UTF_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Output_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_8_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Encode (Item : Wide_Wide_String; Output_BOM : Boolean := False) @key[return] UTF_16_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the value of Item encoded in UTF_16.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_String; Input_Scheme : Encoding_Scheme) @key[return] Wide_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by Input_Scheme.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_8_String) @key[return] Wide_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-8.]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Keepnext=[T],Text=[@key[function] Decode (Item : UTF_16_Wide_String) @key[return] Wide_Wide_String;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Type=[Trailing],Text=[Returns the result of decoding Item, which is encoded in UTF-16.]} @end{DescribeCode} @end{StaticSem} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[If an implementation supports other encoding schemes, another similar child of Ada.Strings should be defined.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[If an implementation supports other string encoding schemes, a child of Ada.Strings similar to UTF_Encoding should be defined.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[A BOM (Byte-Order Mark, code position 16#FEFF#) can be included in a file or other entity to indicate the encoding; it is skipped when decoding. Typically, only the first line of a file or other entity contains a BOM. When decoding, the Encoding function can be called on the first line to determine the encoding; this encoding will then be used in subsequent calls to Decode to convert all of the lines to an internal format.]} @end{Notes} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0137-2]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The packages Strings.UTF_Encoding, Strings.UTF_Encoding.Conversions, Strings.UTF_Encoding.Strings, Strings.UTF_Encoding.Wide_Strings, and Strings.UTF_Encoding.Wide_Wide_Strings are new.]} @end{Extend2005} ��������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/real_attribs.mss�����������������������������������������������������0000755�0001752�0001001�00000077077�11776511201�020637� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(realattribs, Root="ada.mss") @Comment{$Date: 2011/09/29 06:37:25 $} @comment{$Source: e:\\cvsroot/ARM/Source/real_attribs.mss,v $} @comment{$Revision: 1.27 $} @LabeledSubClause{Attributes of Floating Point Types} @begin{StaticSem} @Leading@Defn2{Term=[representation-oriented attributes], Sec=[of a floating point subtype]} The following @i{representation-oriented attributes} are defined for @PrefixType{every subtype S of a floating point type @i{T}}. @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Radix>, Text=[Yields the radix of the hardware representation of the type @i{T}. The value of this attribute is of the type @i{universal_integer}.]} @end{Description} @Defn{canonical form} The values of other representation-oriented attributes of a floating point subtype, and of the @lquotes@;primitive function@rquotes@; attributes of a floating point subtype described later, are defined in terms of a particular representation of nonzero values called the @i{canonical form}. The canonical form (for the type @i{T}) is the form@* @ @ @ @ @PorM @RI{mantissa} @Times @RI{T}@R['Machine_Radix]@+{@RI{exponent}}@* where @begin{Itemize} @i{mantissa} is a fraction in the number base @i{T}'Machine_Radix, the first digit of which is nonzero, and @i{exponent} is an integer. @end{Itemize} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Mantissa>, Text=[Yields the largest value of @RI{p} such that every value expressible in the canonical form (for the type @i{T}), having a @RI{p}-digit @i{mantissa} and an @i{exponent} between @i{T}'Machine_Emin and @i{T}'Machine_Emax, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} Values of a type held in an extended register are, in general, not machine numbers of the type, since they cannot be expressed in the canonical form with a sufficiently short @i{mantissa}. @end{Ramification} @Attribute{Prefix=<S>, AttrName=<Machine_Emin>, Text=[Yields the smallest (most negative) value of @i{exponent} such that every value expressible in the canonical form (for the type @i{T}), having a @i{mantissa} of @i{T}'Machine_Mantissa digits, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Machine_Emax>, Text=[Yields the largest (most positive) value of @i{exponent} such that every value expressible in the canonical form (for the type @i{T}), having a @i{mantissa} of @i{T}'Machine_Mantissa digits, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}. This attribute yields a value of the type @i{universal_integer}.]} @begin{Ramification} Note that the above definitions do not determine unique values for the representation-oriented attributes of floating point types. The implementation may choose any set of values that collectively satisfies the definitions. @end{Ramification} @Attribute{Prefix=<S>, AttrName=<Denorm>, Text=[Yields the value True if every value expressible in the form@* @ @ @ @ @PorM @RI{mantissa} @Times @RI{T}@R{'Machine_Radix}@+{@RI{T}@R{'Machine_Emin}}@* where @i{mantissa} is a nonzero @i{T}'Machine_Mantissa-digit fraction in the number base @i{T}'Machine_Radix, the first digit of which is zero, is a machine number (see @RefSecNum{Floating Point Types}) of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @Defn{denormalized number} The values described by the formula in the definition of S'Denorm are called @i{denormalized numbers}. @Defn{normalized number} A nonzero machine number that is not a denormalized number is a @i{normalized number}. @Defn{represented in canonical form} @Defn{canonical-form representation} A normalized number @RI{x} of a given type @i{T} is said to be @i{represented in canonical form} when it is expressed in the canonical form (for the type @i{T}) with a @i{mantissa} having @i{T}'Machine_Mantissa digits; the resulting form is the @i{canonical-form representation} of @RI{x}. @begin{Discussion} The intent is that S'Denorm be True when such denormalized numbers exist and are generated in the circumstances defined by IEC 559:1989, though the latter requirement is not formalized here. @end{Discussion} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Rounds>, Text=[Yields the value True if rounding is performed on inexact results of every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @begin{Discussion} @Leading@;It is difficult to be more precise about what it means to round the result of a predefined operation. If the implementation does not use extended registers, so that every arithmetic result is necessarily a machine number, then rounding seems to imply two things: @begin{Itemize} S'Model_Mantissa = S'Machine_Mantissa, so that operand preperturbation never occurs; when the exact mathematical result is not a machine number, the result of a predefined operation must be the nearer of the two adjacent machine numbers. @end{Itemize} Technically, this attribute should yield False when extended registers are used, since a few computed results will cross over the half-way point as a result of double rounding, if and when a value held in an extended register has to be reduced in precision to that of the machine numbers. It does not seem desirable to preclude the use of extended registers when S'Machine_Rounds could otherwise be True. @end{Discussion} @Attribute{Prefix=<S>, AttrName=<Machine_Overflows>, Text=[Yields the value True if overflow and divide-by-zero are detected and reported by raising Constraint_Error for every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @Attribute{Prefix=<S>, AttrName=<Signed_Zeros>, Text=[Yields the value True if the hardware representation for the type @i{T} has the capability of representing both positively and negatively signed zeros, these being generated and used by the predefined operations of the type @i{T} as specified in IEC 559:1989; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @Leading@Defn{normalized exponent} For every value @RI{x} of a floating point type @i{T}, the @i{normalized exponent} of @RI{x} is defined as follows: @begin{Itemize} the normalized exponent of zero is (by convention) zero; for nonzero @RI{x}, the normalized exponent of @RI{x} is the unique integer @RI{k} such that @RI{T}@R['Machine_Radix]@+{@RI{k}@en@;1} @leq @Abs{@RI{x}} @Lt @RI{T}@R['Machine_Radix]@+{@RI{k}}. @end{Itemize} @begin{Ramification} The normalized exponent of a normalized number @RI{x} is the value of @i{exponent} in the canonical-form representation of @RI{x}. The normalized exponent of a denormalized number is less than the value of @i{T}'Machine_Emin. @end{Ramification} @begin{WideAbove} @Leading@Defn{primitive function} The following @i{primitive function attributes} are defined for any subtype S of a floating point type @i{T}. @end{WideAbove} @begin(Description) @AttributeLeading{Prefix=<S>, AttrName=<Exponent>, Text=[S'Exponent denotes a function with the following specification: @begin(DescExample) @key(function) S'Exponent (@RI(X) : @RI(T)) @key(return) @RI(universal_integer) @end(DescExample) @NoPrefix@;The function yields the normalized exponent of @i{X}.]} @AttributeLeading{Prefix=<S>, AttrName=<Fraction>, Text=[S'Fraction denotes a function with the following specification: @begin(DescExample) @key(function) S'Fraction (@RI(X) : @RI(T)) @key(return) @RI(T) @end(DescExample) @NoPrefix@;The function yields the value @RI(X) @Times @RI(T)@R('Machine_Radix)@+(@en@RI(k)), where @RI(k) is the normalized exponent of @i(X). A zero result@Redundant(, which can only occur when @i(X) is zero,) has the sign of @i(X).]} @begin{Discussion} Informally, when @i{X} is a normalized number, the result is the value obtained by replacing the @i{exponent} by zero in the canonical-form representation of @i{X}. @end{Discussion} @begin{Ramification} Except when @i{X} is zero, the magnitude of the result is greater than or equal to the reciprocal of @i{T}'Machine_Radix and less than one; consequently, the result is always a normalized number, even when @i{X} is a denormalized number. @end{Ramification} @begin{ImplNote} When @i{X} is a denormalized number, the result is the value obtained by replacing the @i{exponent} by zero in the canonical-form representation of the result of scaling @i{X} up sufficiently to normalize it. @end{ImplNote} @AttributeLeading{Prefix=<S>, AttrName=<Compose>, Text=[S'Compose denotes a function with the following specification: @begin{DescExample} @key(function) S'Compose (@RI{Fraction} : @RI{T}; @RI{Exponent} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} Let @RI{v} be the value @RI{Fraction} @Times @RI{T}@R('Machine_Radix)@+{@RI{Exponent}@en@RI{k}}, where @RI{k} is the normalized exponent of @i{Fraction}. If @RI{v} is a machine number of the type @i{T}, or if @Abs{@RI{v}} @geq @RI{T}@R('Model_Small), the function yields @RI{v}; otherwise, it yields either one of the machine numbers of the type @i{T} adjacent to @RI{v}. @IndexCheck{Range_Check}Constraint_Error is optionally raised if @RI{v} is outside the base range of S. A zero result has the sign of @i{Fraction} when S'Signed_Zeros is True.]} @begin{Discussion} Informally, when @i{Fraction} and @RI{v} are both normalized numbers, the result is the value obtained by replacing the @i{exponent} by @i{Exponent} in the canonical-form representation of @i{Fraction}. @end{Discussion} @begin{Ramification} If @i{Exponent} is less than @i{T}'Machine_Emin and @i{Fraction} is nonzero, the result is either zero, @i{T}'Model_Small, or (if @i{T}'Denorm is True) a denormalized number. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Scaling>, Text=[S'Scaling denotes a function with the following specification: @begin{DescExample} @key(function) S'Scaling (@RI{X} : @RI{T}; @RI{Adjustment} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} Let @RI{v} be the value @RI{X} @Times @RI{T}@R('Machine_Radix)@+{@RI{Adjustment}}. If @RI{v} is a machine number of the type @i{T}, or if @Abs{@RI{v}} @geq @RI{T}@R('Model_Small), the function yields @RI{v}; otherwise, it yields either one of the machine numbers of the type @i{T} adjacent to @RI{v}. @IndexCheck{Range_Check}Constraint_Error is optionally raised if @RI{v} is outside the base range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Discussion} Informally, when @i{X} and @RI{v} are both normalized numbers, the result is the value obtained by increasing the @i{exponent} by @i{Adjustment} in the canonical-form representation of @i{X}. @end{Discussion} @begin{Ramification} If @i{Adjustment} is sufficiently small (i.e., sufficiently negative), the result is either zero, @i{T}'Model_Small, or (if @i{T}'Denorm is True) a denormalized number. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Floor>, Text=[S'Floor denotes a function with the following specification: @begin{DescExample} @key(function) S'Floor (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Floor{@RI{X}}, i.e., the largest (most positive) integral value less than or equal to @i{X}. When @i{X} is zero, the result has the sign of @i{X}; a zero result otherwise has a positive sign.]} @AttributeLeading{Prefix=<S>, AttrName=<Ceiling>, Text=[S'Ceiling denotes a function with the following specification: @begin{DescExample} @key(function) S'Ceiling (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Ceiling{@RI{X}}, i.e., the smallest (most negative) integral value greater than or equal to @i{X}. When @i{X} is zero, the result has the sign of @i{X}; a zero result otherwise has a negative sign when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Rounding>, Text=[S'Rounding denotes a function with the following specification: @begin{DescExample} @key(function) S'Rounding (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the integral value nearest to @i{X}, rounding away from zero if @i{X} lies exactly halfway between two integers. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Unbiased_Rounding>, Text=[S'Unbiased_Rounding denotes a function with the following specification: @begin{DescExample} @key(function) S'Unbiased_Rounding (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the integral value nearest to @i{X}, rounding toward the even integer if @i{X} lies exactly halfway between two integers. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @ChgAttribute{Version=[2],Kind=[Added],ChginAnnex=[T], Leading=<T>, Prefix=<S>, AttrName=<Machine_Rounding>, ARef=[AI95-00267-01], Text=[@Chg{Version=[2],New=[S'Machine_Rounding denotes a function with the following specification:],Old=[]} @begin(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[@key(function) S'Machine_Rounding (@RI{X} : @RI{T}) @key(return) @RI{T}]} @end(Descexample) @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],NoPrefix=[T],Text=[The function yields the integral value nearest to @i{X}. If @i{X} lies exactly halfway between two integers, one of those integers is returned, but which of them is returned is unspecified. A zero result has the sign of @i{X} when S'Signed_Zeros is True. This function provides access to the rounding behavior which is most efficient on the target processor.@PDefn{unspecified}]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[We leave the rounding unspecified, so that users cannot depend on a particular rounding. This attribute is intended for use in cases where the particular rounding chosen is irrelevant. If there is a need to know which way values halfway between two integers are rounded, one of the other rounding attributes should be used.]} @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Truncation>, Text=[S'Truncation denotes a function with the following specification: @begin{DescExample} @key(function) S'Truncation (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;The function yields the value @Ceiling{@RI{X}} when @i{X} is negative, and @Floor{@RI{X}} otherwise. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @AttributeLeading{Prefix=<S>, AttrName=<Remainder>, Text=[S'Remainder denotes a function with the following specification: @begin{DescExample} @key(function) S'Remainder (@RI{X}, @RI{Y} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} For nonzero @i{Y}, let @RI{v} be the value @RI{X} @en @RI{n} @Times @RI{Y}, where @RI{n} is the integer nearest to the exact value of @RI{X}/@RI{Y}; if @Abs{@RI{n} @en @RI{X}/@RI{Y}} = 1/2, then @RI(n) is chosen to be even. If @RI{v} is a machine number of the type @i{T}, the function yields @RI{v}; otherwise, it yields zero. @IndexCheck{Division_Check}Constraint_Error is raised if @i{Y} is zero. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Ramification} The magnitude of the result is less than or equal to one-half the magnitude of @i{Y}. @end{Ramification} @begin{Discussion} Given machine numbers @i{X} and @i{Y} of the type @i{T}, @RI{v} is necessarily a machine number of the type @i{T}, except when @i{Y} is in the neighborhood of zero, @i{X} is sufficiently close to a multiple of @i{Y}, and @i{T}'Denorm is False. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Adjacent>, Text=[S'Adjacent denotes a function with the following specification: @begin{DescExample} @key(function) S'Adjacent (@RI{X}, @RI{Towards} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If @RI{Towards} = @RI{X}, the function yields @i{X}; otherwise, it yields the machine number of the type @i{T} adjacent to @i{X} in the direction of @i{Towards}, if that machine number exists. @IndexCheck{Range_Check}If the result would be outside the base range of S, Constraint_Error is raised. When @i{T}'Signed_Zeros is True, a zero result has the sign of @i{X}. When @i{Towards} is zero, its sign has no bearing on the result.]} @begin{Ramification} The value of S'Adjacent(0.0, 1.0) is the smallest normalized positive number of the type @i{T} when @i{T}'Denorm is False and the smallest denormalized positive number of the type @i{T} when @i{T}'Denorm is True. @end{Ramification} @AttributeLeading{Prefix=<S>, AttrName=<Copy_Sign>, Text=[S'Copy_Sign denotes a function with the following specification: @begin{DescExample} @key(function) S'Copy_Sign (@RI{Value}, @RI{Sign} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If the value of @i{Value} is nonzero, the function yields a result whose magnitude is that of @i{Value} and whose sign is that of @i{Sign}; otherwise, it yields the value zero. @IndexCheck{Range_Check}Constraint_Error is optionally raised if the result is outside the base range of S. A zero result has the sign of @i{Sign} when S'Signed_Zeros is True.]} @begin{Discussion} S'Copy_Sign is provided for convenience in restoring the sign to a quantity from which it has been temporarily removed, or to a related quantity. When S'Signed_Zeros is True, it is also instrumental in determining the sign of a zero quantity, when required. (Because negative and positive zeros compare equal in systems conforming to IEC 559:1989, a negative zero does @i{not} appear to be negative when compared to zero.) The sign determination is accomplished by transferring the sign of the zero quantity to a nonzero quantity and then testing for a negative result. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Leading_Part>, Text=[S'Leading_Part denotes a function with the following specification: @begin{DescExample} @key(function) S'Leading_Part (@RI{X} : @RI{T}; @RI{Radix_Digits} : @RI{universal_integer}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;Let @RI{v} be the value @RI{T}@R('Machine_Radix)@+{@RI{k}@en@RI{Radix_Digits}}, where @RI{k} is the normalized exponent of @i{X}. The function yields the value @begin{Itemize} @Floor{@RI{X}/@RI{v}} @Times @RI{v}, when @i{X} is nonnegative and @i{Radix_Digits} is positive; @Ceiling{@RI{X}/@RI{v}} @Times @RI{v}, when @i{X} is negative and @i{Radix_Digits} is positive. @end{Itemize} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} @IndexCheck{Range_Check}Constraint_Error is raised when @i{Radix_Digits} is zero or negative. A zero result@Redundant{, which can only occur when @i{X} is zero,} has the sign of @i{X}.]} @begin{Discussion} Informally, if @i{X} is nonzero, the result is the value obtained by retaining only the specified number of (leading) significant digits of @i{X} (in the machine radix), setting all other digits to zero. @end{Discussion} @begin{ImplNote} The result can be obtained by first scaling @i{X} up, if necessary to normalize it, then masking the mantissa so as to retain only the specified number of leading digits, then scaling the result back down if @i{X} was scaled up. @end{ImplNote} @AttributeLeading{Prefix=<S>, AttrName=<Machine>, Text=[S'Machine denotes a function with the following specification: @begin{DescExample} @key(function) S'Machine (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@Defn2{Term=(Constraint_Error),Sec=(raised by failure of run-time check)} If @i{X} is a machine number of the type @i{T}, the function yields @i{X}; otherwise, it yields the value obtained by rounding or truncating @i{X} to either one of the adjacent machine numbers of the type @i(T). @IndexCheck{Range_Check}Constraint_Error is raised if rounding or truncating @i{X} to the precision of the machine numbers results in a value outside the base range of S. A zero result has the sign of @i{X} when S'Signed_Zeros is True.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} All of the primitive function attributes except Rounding and Machine correspond to subprograms in the Generic_Primitive_Functions generic package @Chg{Version=[3],New=[that was ],Old=[]}proposed as a separate ISO standard (ISO/IEC DIS 11729) for Ada 83. The Scaling, Unbiased_Rounding, and Truncation attributes correspond to the Scale, Round, and Truncate functions, respectively, in Generic_Primitive_Functions. The Rounding attribute rounds away from zero; this functionality was not provided in Generic_Primitive_Functions. The name Round was not available for either of the primitive function attributes that perform rounding, since an attribute of that name is used for a different purpose for decimal fixed point types. Likewise, the name Scale was not available, since an attribute of that name is also used for a different purpose for decimal fixed point types. The functionality of the Machine attribute was also not provided in Generic_Primitive_Functions. The functionality of the Decompose procedure of Generic_Primitive_Functions is only provided in the form of the separate attributes Exponent and Fraction. The functionality of the Successor and Predecessor functions of Generic_Primitive_Functions is provided by the extension of the existing Succ and Pred attributes. @end{Discussion} @begin{ImplNote} The primitive function attributes may be implemented either with appropriate floating point arithmetic operations or with integer and logical operations that act on parts of the representation directly. The latter is strongly encouraged when it is more efficient than the former; it is mandatory when the former cannot deliver the required accuracy due to limitations of the implementation's arithmetic operations. @end{ImplNote} @end(Description) @begin{WideAbove} @Leading@Defn2{Term=[model-oriented attributes], Sec=[of a floating point subtype]} The following @i{model-oriented attributes} are defined for any subtype S of a floating point type @i{T}. @end{WideAbove} @begin{Description} @Attribute{Prefix=<S>, AttrName=<Model_Mantissa>, Text=[If the Numerics Annex is not supported, this attribute yields an implementation defined value that is greater than or equal to @Ceiling{@RI{d} @Times @Log(10) / @Log(@RI{T}'@R{Machine_Radix})} + 1, where @RI{d} is the requested decimal precision of @i{T}, and less than or equal to the value of @i{T}'Machine_Mantissa. See @RefSecNum{Model-Oriented Attributes of Floating Point Types} for further requirements that apply to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Model_Emin>, Text=[If the Numerics Annex is not supported, this attribute yields an implementation defined value that is greater than or equal to the value of @i{T}'Machine_Emin. See @RefSecNum{Model-Oriented Attributes of Floating Point Types} for further requirements that apply to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Model_Epsilon>, Text=[Yields the value @RI{T}@R('Machine_Radix)@+{1 @en @RI{T}@R('Model_Mantissa)}. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} In most implementations, this attribute yields the absolute value of the difference between one and the smallest machine number of the type @i{T} above one which, when added to one, yields a machine number different from one. Further discussion can be found in @RefSecNum{Model-Oriented Attributes of Floating Point Types}. @end{Discussion} @Attribute{Prefix=<S>, AttrName=<Model_Small>, Text=[Yields the value @RI{T}@R('Machine_Radix)@+{@RI{T}@R('Model_Emin) @en 1}. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} In most implementations, this attribute yields the smallest positive normalized number of the type @i{T}, i.e. the number corresponding to the positive underflow threshold. In some implementations employing a radix-complement representation for the type @i{T}, the positive underflow threshold is closer to zero than is the negative underflow threshold, with the consequence that the smallest positive normalized number does not coincide with the positive underflow threshold (i.e., it exceeds the latter). Further discussion can be found in @RefSecNum{Model-Oriented Attributes of Floating Point Types}. @end{Discussion} @AttributeLeading{Prefix=<S>, AttrName=<Model>, Text=[S'Model denotes a function with the following specification: @begin{DescExample} @key(function) S'Model (@RI{X} : @RI{T}) @key(return) @RI{T} @end{DescExample} @NoPrefix@;If the Numerics Annex is not supported, the meaning of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex.]} @Attribute{Prefix=<S>, AttrName=<Safe_First>, Text=[Yields the lower bound of the safe range (see @RefSecNum{Floating Point Types}) of the type @i{T}. If the Numerics Annex is not supported, the value of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_real}.]} @Attribute{Prefix=<S>, AttrName=<Safe_Last>, Text=[Yields the upper bound of the safe range (see @RefSecNum{Floating Point Types}) of the type @i{T}. If the Numerics Annex is not supported, the value of this attribute is implementation defined; see @RefSecNum{Model-Oriented Attributes of Floating Point Types} for the definition that applies to implementations supporting the Numerics Annex. The value of this attribute is of the type @i{universal_real}.]} @begin{Discussion} A predefined floating point arithmetic operation that yields a value in the safe range of its result type is guaranteed not to overflow. @end{Discussion} @begin{Honest} An exception is made for exponentiation by a negative exponent in @RefSecNum{Highest Precedence Operators}. @end{Honest} @ImplDef{The values of the Model_Mantissa, Model_Emin, Model_Epsilon, Model, Safe_First, and Safe_Last attributes, if the Numerics Annex is not supported.} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The Epsilon and Mantissa attributes of floating point types are removed from the language and replaced by Model_Epsilon and Model_Mantissa, which may have different values (as a result of changes in the definition of model numbers); the replacement of one set of attributes by another is intended to convert what would be an inconsistent change into an incompatible change. The Emax, Small, Large, Safe_Emax, Safe_Small, and Safe_Large attributes of floating point types are removed from the language. Small and Safe_Small are collectively replaced by Model_Small, which is functionally equivalent to Safe_Small, though it may have a slightly different value. The others are collectively replaced by Safe_First and Safe_Last. Safe_Last is functionally equivalent to Safe_Large, though it may have a different value; Safe_First is comparable to the negation of Safe_Large but may differ slightly from it as well as from the negation of Safe_Last. Emax and Safe_Emax had relatively few uses in Ada 83; T'Safe_Emax can be computed in the revised language as Integer'Min(T'Exponent(T'Safe_First), T'Exponent(T'Safe_Last)). Implementations are encouraged to eliminate the incompatibilities discussed here by retaining the old attributes, during a transition period, in the form of implementation-defined attributes with their former values. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The Model_Emin attribute is new. It is conceptually similar to the negation of Safe_Emax attribute of Ada 83, adjusted for the fact that the model numbers now have the hardware radix. It is a fundamental determinant, along with Model_Mantissa, of the set of model numbers of a type (see @RefSecNum{Model of Floating Point Arithmetic}). The Denorm and Signed_Zeros attributes are new, as are all of the primitive function attributes. @end{Extend83} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00388-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Machine_Rounding attribute is new.]} @end{Extend95} @LabeledSubClause{Attributes of Fixed Point Types} @begin{StaticSem} @Leading@Defn2{Term=[representation-oriented attributes], Sec=[of a fixed point subtype]} The following @i{representation-oriented} attributes are defined for @PrefixType{every subtype S of a fixed point type @i{T}}. @begin{Description} @Attribute{Prefix=<S>, AttrName=<Machine_Radix>, Text=[Yields the radix of the hardware representation of the type @i{T}. The value of this attribute is of the type @i{universal_integer}.]} @Attribute{Prefix=<S>, AttrName=<Machine_Rounds>, Text=[Yields the value True if rounding is performed on inexact results of every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @Attribute{Prefix=<S>, AttrName=<Machine_Overflows>, Text=[Yields the value True if overflow and divide-by-zero are detected and reported by raising Constraint_Error for every predefined operation that yields a result of the type @i{T}; yields the value False otherwise. The value of this attribute is of the predefined type Boolean.]} @end{Description} @EndPrefixType{} @end{StaticSem} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} The Mantissa, Large, Safe_Small, and Safe_Large attributes of fixed point types are removed from the language. Implementations are encouraged to eliminate the resulting incompatibility by retaining these attributes, during a transition period, in the form of implementation-defined attributes with their former values. @end{Incompatible83} @begin{Extend83} @Defn{extensions to Ada 83} The Machine_Radix attribute is now allowed for fixed point types. It is also specifiable in an attribute definition clause (see @RefSecNum{Machine_Radix Attribute Definition Clause}). @end{Extend83} �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/rm.msm���������������������������������������������������������������0000755�0001752�0001001�00000014636�12273462240�016565� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{Master file for the RM (public versions)} @Comment{Global properties} @HideIndexEntries @HideAnnotations @HideISO @NumberParagraphs @LinkNonTerminals @Title{Version=[0],Text=[Ada Reference Manual]}@Comment{Same title for all versions} @FilePrefix{RM} @ExampleFont{Fixed} @BodyFont{Roman} @NoteFormat{Ada95} @ContentsFormat{Ada95} @ListFormat{Ada95} @SubdivisionNames{Clause}@Comment{For Ada 95 and 2005, use "section" instead} @Comment{RTF properties} @SingleRTFOutputFile @Comment{One large file allows Word to make a TOC} @RTFHeaderPrefix{Version=[0],Text=[ISO/IEC 8652:1995(E)]} @RTFHeaderPrefix{Version=[1],Text=[ISO/IEC 8652:1995(E) with COR.1:2001]} @Comment{PDFs: }@RTFHeaderPrefix{Version=[2],Text=[ISO/IEC 8652:2007(E) Ed. 3]} @Comment{Springer: @RTFHeaderPrefix{Version=[2],Text=[Consolidated Ada Reference Manual - 2005 Edition]}} @Comment{PDFs: }@RTFHeaderPrefix{Version=[3],Text=[ISO/IEC 8652:2012(E)]} @Comment{Springer: @RTFHeaderPrefix{Version=[2],Text=[Ada Reference Manual - 2012 Edition]}} @RTFFooter{UseDate=[T],UseClauseName=[T],UseISOFormat=[F]}@Comment{RM style footers} @RTFPageSize{Ada95} @RTFFonts{Serif=[Times],SansSerif=[Arial]} @RTFVersionName{Version=[0],Text=[Original Text]} @RTFVersionName{Version=[1],Text=[Technical Corrigendum 1]} @RTFVersionName{Version=[2],Text=[Amendment 1]} @RTFVersionName{Version=[3],Text=[Ada 2012]} @Comment{HTML properties} @Comment{Many small files are used, thus no @SingleHTMLOutputFile command} @HTMLKind{Version=[4],Unicode=[T]}@Comment{Was "4Comp" for the Consolidated AARM} @HTMLNavBar{RefName=[RM-STDS.html],SrchName=[RM-SRCH.html],IndexName=[], UseButtons=[T],OnTop=[T],OnBottom=[T]} @Comment{We let the program link to the index} @HTMLTabs{EmulateFixedOnly} @HTMLHeader{<DIV><SPAN Style="font-size:200%; color: rgb(0,0,153)"><B>Ada Reference Manual</B></SPAN> — <A HREF="RM-TTL.html"><B>Legal Information</B></A></DIV>} @HTMLFooter{<DIV Style="margin-top:0.0em"><IMG SRC="AE_logo.gif" height=100 width=113 align=right ALT="Ada-Europe"> <SPAN Style="vertical-align: middle; font-size:120%">Ada 2005 and 2012 Editions sponsored in part by <SPAN Style="font-size: 125%"><A HREF="http://www.ada-europe.org/"><B>Ada-Europe</B></A></SPAN></SPAN></DIV>} @HTMLColor{Text=[#000000],Background=[#FFFFF0],Link=[#000080],VLink=[#330033],ALink=[#0000FF]} @Comment{Source files and related items, in collating order} @Source{Name=<Title.MSS>,SectionName=<Ttl>,SectionNumber=[0],NewSection=[T]} @TOC @Comment{The table of contents goes here in the collating order} @Source{Name=<Front_Matter.MSS>,SectionName=<00>,SectionNumber=[0],NewSection=[T]} @Source{Name=<01.MSS>,SectionName=<01>,SectionNumber=[1],NewSection=[T]} @Source{Name=<02.MSS>,SectionName=<02>,SectionNumber=[2],NewSection=[T]} @Source{Name=<03A.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[T]} @Source{Name=<03B.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<03C.MSS>,SectionName=<03>,SectionNumber=[3],NewSection=[F]} @Source{Name=<04A.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[T]} @Source{Name=<04B.MSS>,SectionName=<04>,SectionNumber=[4],NewSection=[F]} @Source{Name=<05.MSS>,SectionName=<05>,SectionNumber=[5],NewSection=[T]} @Source{Name=<06.MSS>,SectionName=<06>,SectionNumber=[6],NewSection=[T]} @Source{Name=<07.MSS>,SectionName=<07>,SectionNumber=[7],NewSection=[T]} @Source{Name=<08.MSS>,SectionName=<08>,SectionNumber=[8],NewSection=[T]} @Source{Name=<09.MSS>,SectionName=<09>,SectionNumber=[9],NewSection=[T]} @Source{Name=<10.MSS>,SectionName=<10>,SectionNumber=[10],NewSection=[T]} @Source{Name=<11.MSS>,SectionName=<11>,SectionNumber=[11],NewSection=[T]} @Source{Name=<12.MSS>,SectionName=<12>,SectionNumber=[12],NewSection=[T]} @Source{Name=<13A.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[T]} @Source{Name=<13B.MSS>,SectionName=<13>,SectionNumber=[13],NewSection=[F]} @Comment{Now, the "Standard Libraries" separator page} @Source{Name=<LIBRARY.MSS>,SectionName=<Lib>,SectionNumber=[0],NewSection=[T]} @Comment{Annex A; all of the files starting with "Pre_" are part of Annex A.} @Source{Name=<PRE.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[T]} @Source{Name=<PRE_Standard.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Ada.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Chars.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Strings.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Math.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<Real_Attribs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_IO.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Cmdln.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Dirs.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Environ.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Containers.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Con2.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Source{Name=<PRE_Locales.MSS>,SectionName=<A>,SectionNumber=[A],NewSection=[F]} @Comment{Other normative annexes:} @Source{Name=<Interface.MSS>,SectionName=<B>,SectionNumber=[B],NewSection=[T]} @Source{Name=<SP.MSS>,SectionName=<C>,SectionNumber=[C],NewSection=[T]} @Source{Name=<RT.MSS>,SectionName=<D>,SectionNumber=[D],NewSection=[T]} @Source{Name=<DS.MSS>,SectionName=<E>,SectionNumber=[E],NewSection=[T]} @Source{Name=<InfoSys.MSS>,SectionName=<F>,SectionNumber=[F],NewSection=[T]} @Source{Name=<Numerics.MSS>,SectionName=<G>,SectionNumber=[G],NewSection=[T]} @Source{Name=<Safety.MSS>,SectionName=<H>,SectionNumber=[H],NewSection=[T]} @Comment{We don't use Annex I, as ISO used to require skipping I and O} @Source{Name=<Obsolescent.MSS>,SectionName=<J>,SectionNumber=[J],NewSection=[T]} @Comment{Informative annexes:} @Source{Name=<Attribs.MSS>,SectionName=<K>,SectionNumber=[K],NewSection=[T]} @Source{Name=<Pragmas.MSS>,SectionName=<L>,SectionNumber=[L],NewSection=[T]} @Source{Name=<Impldef.MSS>,SectionName=<M>,SectionNumber=[M],NewSection=[T]} @Source{Name=<Glossary.MSS>,SectionName=<N>,SectionNumber=[N],NewSection=[T]} @Comment{We don't use Annex O, as ISO used to require skipping I and O} @Source{Name=<Syntax.MSS>,SectionName=<P>,SectionNumber=[P],NewSection=[T]} @Source{Name=<Langdef.MSS>,SectionName=<Q>,SectionNumber=[Q],NewSection=[T]} @Source{Name=<Index.MSS>,SectionName=<IDX>,SectionNumber=[0],NewSection=[T]} ��������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/rt.mss���������������������������������������������������������������0000755�0001752�0001001�00001066730�12066652506�016613� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{ $Source: e:\\cvsroot/ARM/Source/rt.mss,v $ } @comment{ $Revision: 1.114 $ $Date: 2012/11/28 23:53:05 $ $Author: randy $ } @Part(realtime, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:05 $} @LabeledNormativeAnnex{Real-Time Systems} @begin{Intro} @Defn{real-time systems} @Defn{embedded systems} This Annex specifies additional characteristics of Ada implementations intended for real-time systems software. To conform to this Annex, an implementation shall also conform to the Systems Programming Annex. @end{Intro} @begin{Metrics} The metrics are documentation requirements; an implementation shall document the values of the language-defined metrics for at least one configuration @Redundant[of hardware or an underlying system] supported by the implementation, and shall document the details of that configuration. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Values of all @MetricsTitle.]}]}@ChgNote{We're going to document the individual metrics sections.} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The details of the configuration used to generate the values of all metrics.]}]} @begin{Reason} The actual values of the metrics are likely to depend on hardware configuration details that are variable and generally outside the control of a compiler vendor. @end{Reason} The metrics do not necessarily yield a simple number. @Redundant[For some, a range is more suitable, for others a formula dependent on some parameter is appropriate, and for others, it may be more suitable to break the metric into several cases.] Unless specified otherwise, the metrics in this annex are expressed in processor clock cycles. For metrics that require documentation of an upper bound, if there is no upper bound, the implementation shall report that the metric is unbounded. @begin{Discussion} There are several good reasons to specify metrics in seconds; there are however equally good reasons to specify them in processor clock cycles. In defining the metrics, we have tried to strike a balance on a case-by-case basis. It has been suggested that all metrics should be given names, so that @lquotes@;data-sheets@rquotes@; could be formulated and published by vendors. However the paragraph number can serve that purpose. @end{Discussion} @end{Metrics} @begin{Notes} The specification of the metrics makes a distinction between upper bounds and simple execution times. Where something is just specified as @lquotes@;the execution time of@rquotes@; a piece of code, this leaves one the freedom to choose a nonpathological case. This kind of metric is of the form @lquotes@;there exists a program such that the value of the metric is V@rquotes@;. Conversely, the meaning of upper bounds is @lquotes@;there is no program such that the value of the metric is greater than V@rquotes@;. This kind of metric can only be partially tested, by finding the value of V for one or more test programs. The metrics do not cover the whole language; they are limited to features that are specified in @RefSec{Systems Programming} and in this Annex. The metrics are intended to provide guidance to potential users as to whether a particular implementation of such a feature is going to be adequate for a particular real-time application. As such, the metrics are aimed at known implementation choices that can result in significant performance differences. The purpose of the metrics is not necessarily to provide fine-grained quantitative results or to serve as a comparison between different implementations on the same or different platforms. Instead, their goal is rather qualitative; to define a standard set of approximate values that can be measured and used to estimate the general suitability of an implementation, or to evaluate the comparative utility of certain features of an implementation for a particular real-time application. @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Task Priorities} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies the priority model for real-time systems. In addition, the methods for specifying priorities are defined.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 6 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Priority is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Priority)(@Syn2{expression});]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Interrupt_Priority is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Interrupt_Priority)[(@Syn2{expression})];]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[expected type], Sec=(Priority pragma argument)} @PDefn2{Term=[expected type], Sec=(Interrupt_Priority pragma argument)} The expected type for the @nt{expression} in a Priority or Interrupt_Priority pragma is Integer.]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a task type (including the anonymous type of a @nt{single_task_declaration}), protected type (including the anonymous type of a @nt{single_protected_declaration}), or subprogram, the following language-defined representation aspects may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Priority@\The aspect Priority is an @nt{expression}, which shall be of type Integer.@AspectDefn{Priority}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Priority], Text=[@ChgAdded{Version=[3],Text=[Priority of a task object or type, or priority of a protected object or type; the priority is not in the interrupt range.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Interrupt_Priority@\The aspect Interrupt_Priority is an @nt{expression}, which shall be of type Integer.@AspectDefn{Interrupt_Priority}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Interrupt_Priority], Text=[@ChgAdded{Version=[3],Text=[Priority of a task object or type, or priority of a protected object or type; the priority is in the interrupt range.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[A Priority pragma is allowed only immediately within a @nt{task_definition}, a @nt{protected_definition}, or the @nt{declarative_part} of a @nt{subprogram_body}. An Interrupt_Priority pragma is allowed only immediately within a @nt{task_definition} or a @nt{protected_definition}. At most one such pragma shall appear within a given construct.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[If the],Old=[For a]} Priority @Chg{Version=[3],New=[aspect is specified for a subprogram],Old=[pragma that appears in the @nt{declarative_part} of a @nt{subprogram_body}]}, the @nt{expression} shall be static, and its value shall be in the range of System.Priority. @begin{Reason} This value is needed before it gets elaborated, when the environment task starts executing. @end{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[At most one of the Priority and Interrupt_Priority aspects may be specified for a given entity.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[This includes specifying via pragmas (see @RefSecNum{Pragmas Priority and Interrupt_Priority}). Note that @RefSecNum{Operational and Representation Aspects} prevents multiple specifications of a single representation aspect by any means.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Neither of the Priority or Interrupt_Priority aspects shall be specified for a synchronized interface type.]} @end{Legality} @begin{StaticSem} @leading@keepnext@;The following declarations exist in package System: @begin{example} @key{subtype} Any_Priority @key{is} Integer @key{range} @RI{implementation-defined}; @key{subtype} Priority @key{is} Any_Priority @key{range} Any_Priority'First .. @RI{implementation-defined}; @key{subtype} Interrupt_Priority @key{is} Any_Priority @key{range} Priority'Last+1 .. Any_Priority'Last; Default_Priority : @key{constant} Priority := (Priority'First + Priority'Last)/2; @end{example} @ImplDef{The declarations of Any_Priority and Priority.} The full range of priority values supported by an implementation is specified by the subtype Any_Priority. The subrange of priority values that are high enough to require the blocking of one or more interrupts is specified by the subtype Interrupt_@!Priority. @Redundant[The subrange of priority values below System.@!Interrupt_@!Priority'First is specified by the subtype System.@!Priority.] @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The priority specified by a Priority or Interrupt_Priority pragma is the value of the @nt{expression} in the pragma, if any. If there is no @nt{expression} in an Interrupt_Priority pragma, the priority value is Interrupt_Priority'Last.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[The],Old=[A]} Priority @Chg{Version=[3],New=[aspect],Old=[pragma]} has no effect if it @Chg{Version=[3],New=[is specified for],Old=[it occurs in the @nt{declarative_part} of the @nt{subprogram_body} of]} a subprogram other than the main subprogram@Chg{Version=[3],New=[; the Priority value is not associated with any task],Old=[]}. @Defn{task priority} @Defn{priority} @Defn{priority inheritance} @Defn{base priority} @Defn{active priority} A @i{task priority} is an integer value that indicates a degree of urgency and is the basis for resolving competing demands of tasks for resources. Unless otherwise specified, whenever tasks compete for processors or other implementation-defined resources, the resources are allocated to the task with the highest priority value. The @i{base priority} of a task is the priority with which it was created, or to which it was later set by Dynamic_Priorities.Set_Priority (see @RefSecNum{Dynamic Priorities}). At all times, a task also has an @i{active priority}, which generally reflects its base priority as well as any priority it inherits from other sources. @i{Priority inheritance} is the process by which the priority of a task or other entity (e.g. a protected object; see @RefSecNum{Priority Ceiling Locking}) is used in the evaluation of another task's active priority. @ImplDef{Implementation-defined execution resources.} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The effect of specifying @Chg{Version=[3],New=[a Priority or Interrupt_Priority aspect for a protected type or @nt{single_protected_declaration}],Old=[such a pragma in a @nt{protected_definition}]} is discussed in @RefSecNum{Priority Ceiling Locking}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[creation], Sec=(of a task object)} The @nt{expression} @Chg{Version=[3],New=[specified for the],Old=[in a]} Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect of a task], Old=[pragma that appears in a @nt{task_definition}]} is evaluated for each task object (see @RefSecNum{Task Units and Task Objects}). For @Chg{Version=[3],New=[the],Old=[a]} Priority @Chg{Version=[3],New=[aspect],Old=[pragma]}, the value of the @nt{expression} is converted to the subtype Priority; for @Chg{Version=[3],New=[the],Old=[an]} Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]}, this value is converted to the subtype Any_Priority. The priority value is then associated with the task object whose @Chg{Version=[3],New=[task declaration specifies the aspect],Old=[@nt{task_definition} contains the pragma]}. @Chg{Version=[3],New=[@PDefn2{Term=[implicit subtype conversion],Sec=(Priority aspect)} @PDefn2{Term=[implicit subtype conversion],Sec=(Interrupt_Priority aspect)}], Old=[@PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Likewise, the priority value is associated with the environment task if the @Chg{Version=[3],New=[aspect is specified for],Old=[pragma appears in the @nt{declarative_part} of]} the main subprogram. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The initial value of a task's base priority is specified by default or by means of a Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]}. @Redundant[After a task is created, its base priority can be changed only by a call to Dynamic_Priorities.Set_Priority (see @RefSecNum{Dynamic Priorities}).] The initial base priority of a task in the absence of @Chg{Version=[3],New=[an aspect],Old=[a pragma]} is the base priority of the task that creates it at the time of creation (see @RefSecNum{Task Units and Task Objects}). If @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Priority @Chg{Version=[3],New=[is not specified for],Old=[does not apply to]} the main subprogram, the initial base priority of the environment task is System.Default_Priority. @Redundant[The task's active priority is used when the task competes for processors. Similarly, the task's active priority is used to determine the task's position in any queue when Priority_Queuing is specified (see @RefSecNum{Entry Queuing Policies}).] @Leading@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} At any time, the active priority of a task is the maximum of all the priorities the task is inheriting at that instant. For a task that is not held (see @RefSecNum{Asynchronous Task Control}), its base priority is @Chg{Version=[2],New=[],Old=[always ]}a source of priority inheritance @Chg{Version=[2],New=[unless otherwise specified for a particular task dispatching policy],Old=[]}. Other sources of priority inheritance are specified under the following conditions: @begin{Discussion} Other parts of the annex, e.g. @RefSecNum{Asynchronous Task Control}, define other sources of priority inheritance. @end{Discussion} @begin{itemize} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0072],ARef=[AI95-00092-01]} During activation, a task being activated inherits the active priority @Chg{New=[that],Old=[of the]} its activator (see @RefSecNum{Task Execution - Task Activation})@Chg{New=[ had at the time the activation was initiated],Old=[]}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0072],ARef=[AI95-00092-01]} During rendezvous, the task accepting the entry call inherits the @Chg{New=[],Old=[active ]}priority of the @Chg{New=[entry call],Old=[caller]} (see @RefSecNum{Entry Calls}@Chg{New=[ and @RefSecNum{Entry Queuing Policies}],Old=[]}). During a protected action on a protected object, a task inherits the ceiling priority of the protected object (see @RefSecNum{Intertask Communication} and @RefSecNum{Priority Ceiling Locking}). @end{itemize} In all of these cases, the priority ceases to be inherited as soon as the condition calling for the inheritance no longer exists. @end{RunTime} @begin{ImplReq} The range of System.Interrupt_Priority shall include at least one value. The range of System.Priority shall include at least 30 values. @end{ImplReq} @begin{Notes} The priority expression can include references to discriminants of the enclosing type. It is a consequence of the active priority rules that at the point when a task stops inheriting a priority from another source, its active priority is re-evaluated. This is in addition to other instances described in this Annex for such re-evaluation. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0248-1]} An implementation may provide a @Chg{Version=[3],New=[nonstandard],Old=[non-standard]} mode in which tasks inherit priorities under conditions other than those specified above. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The use of a Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]} does not require the package System to be named in a @nt{with_clause} for the enclosing @nt{compilation_unit}. @end{Ramification} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} The priority of a task is per-object and not per-type. Priorities need not be static anymore (except for the main subprogram). @end{Extend83} @begin{DiffWord83} The description of the Priority pragma has been moved to this annex. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0072],ARef=[AI95-00092-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that dynamic priority changes are not transitive - that is, they don't apply to tasks that are being activated by or in rendezvous with the task that had its priority changed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[Generalized the definition of priority inheritance to take into account the differences between the existing and new dispatching policies.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspects Priority and Interrupt_Priority are new; @nt{pragma}s Priority and Interrupt_Priority are now obsolescent.]} @end{Extend2005} @LabeledClause{Priority Scheduling} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes the rules that determine which task is selected for execution when more than one task is ready (see @Chg{Version=[2],New=[@RefSecNum{Tasks and Synchronization}], Old=[@RefSecNum{Task Execution - Task Activation}]}).@Chg{Version=[2], New=[],Old=[ The rules have two parts: the task dispatching model (see @RefSecNum{The Task Dispatching Model}), and a specific task dispatching policy (see @RefSecNum{Task Dispatching Pragmas}).]}] @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This introduction is simplified in order to reflect the rearrangement and expansion of this @Chg{Version=[3],New=[subclause],Old=[clause]}.]} @end{DiffWord95} @LabeledSubClause{The Task Dispatching Model} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Redundant[The task dispatching model specifies @Chg{Version=[2], New=[task],Old=[preemptive]} scheduling, based on conceptual priority-ordered ready queues.] @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0166-1]} @ChgAdded{Version=[2],Text=[@key<package> Ada.Dispatching @key<is>@ChildUnit{Parent=[Ada],Child=[Dispatching]} @key<pragma> @Chg{Version=[3],New=[Preelaborate],Old=[Pure]}(Dispatching);@Chg{Version=[3],New=[],Old=[ @AdaExcDefn{Dispatching_Policy_Error} : @key<exception>; @key<end> Ada.Dispatching;]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],Text=[ @key<procedure> @AdaSubDefn{Yield};]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],Text=[ @AdaExcDefn{Dispatching_Policy_Error} : @key<exception>; @key<end> Ada.Dispatching;]} @end{Example} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Dispatching serves as the parent of other language-defined library units concerned with task dispatching.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} A task @Chg{Version=[2],New=[can become],Old=[runs (that is, it becomes]} a @i{running task}@Chg{Version=[2],New=[],Old=[)]} only @Chg{Version=[2], New=[if],Old=[when]} it is ready (see @Chg{Version=[2],New=[@RefSecNum{Tasks and Synchronization}], Old=[@RefSecNum{Task Execution - Task Activation}]}) and the execution resources required by that task are available. Processors are allocated to tasks based on each task's active priority. It is implementation defined whether, on a multiprocessor, a task that is waiting for access to a protected object keeps its processor busy. @ImplDef{Whether, on a multiprocessor, a task that is waiting for access to a protected object keeps its processor busy.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{task dispatching} @Defn{dispatching, task} @RootDefn{task dispatching point} @RootDefn{dispatching point} @i{Task dispatching} is the process by which one ready task is selected for execution on a processor. This selection is done at certain points during the execution of a task called @i{task dispatching points}. A task reaches a task dispatching point whenever it becomes blocked, and @Chg{Version=[2],New=[when it terminates],Old=[whenever it becomes ready. In addition, the completion of an @nt{accept_statement} (see @RefSecNum{Entries and Accept Statements}), and task termination are task dispatching points for the executing task]}. @Redundant[Other task dispatching points are defined throughout this Annex@Chg{Version=[2],New=[ for specific policies],Old=[]}.] @begin{Ramification} On multiprocessor systems, more than one task can be chosen, at the same time, for execution on more than one processor, as explained below. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{ready queue} @Defn{head (of a queue)} @Defn{tail (of a queue)} @Defn{ready task} @PDefn{task dispatching policy} @PDefn{dispatching policy for tasks} @i{Task dispatching policies} are specified in terms of conceptual @i{ready queues}@Chg{Version=[2],New=[ and],Old=[,]} task states@Chg{Version=[2], New=[],Old=[, and task preemption]}. A ready queue is an ordered list of ready tasks. The first position in a queue is called the @i{head of the queue}, and the last position is called the @i{tail of the queue}. A task is @i{ready} if it is in a ready queue, or if it is running. Each processor has one ready queue for each priority value. At any instant, each ready queue of a processor contains exactly the set of tasks of that priority that are ready for execution on that processor, but are not running on any processor; that is, those tasks that are ready, are not running on any processor, and can be executed using that processor and other available resources. A task can be on the ready queues of more than one processor. @begin{Discussion} The core language defines a ready task as one that is not blocked. Here we refine this definition and talk about ready queues. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} @Defn{running task} Each processor also has one @i{running task}, which is the task currently being executed by that processor. Whenever a task running on a processor reaches a task dispatching point@Chg{Version=[2],New=[ it goes back to one or more ready queues; a], Old=[, one]} task @Chg{Version=[2],New=[(possibly the same task) ],Old=[]}is @Chg{Version=[2],New=[then ],Old=[]}selected to run on that processor. The task selected is the one at the head of the highest priority nonempty ready queue; this task is then removed from all ready queues to which it belongs. @begin{Discussion} There is always at least one task to run, if we count the idle task. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0166-1]} @ChgDeleted{Version=[2],Text=[@Defn{preemptible resource} A preemptible resource is a resource that while allocated to one task can be allocated (temporarily) to another instead. Processors are preemptible resources. Access to a protected object (see @RefSecNum{Protected Subprograms and Protected Actions}) is a nonpreemptible resource. @Defn{preempted task} When a higher-priority task is dispatched to the processor, and the previously running task is placed on the appropriate ready queue, the latter task is said to be @i{preempted}.]} @ChgAdded{Version=[3],Text=[A call of Yield is a task dispatching point. Yield is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[A processor that is executing a task is available to execute tasks of higher priority, within the set of tasks that that processor is able to execute. Write access to a protected object, on the other hand, cannot be granted to a new task before the old task has released it.]} @end{Reason} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} A new running task is also selected whenever there is a nonempty ready queue with a higher priority than the priority of the running task, or when the task dispatching policy requires a running task to go back to a ready queue. @Redundant[These are also task dispatching points.]]} @begin{Ramification} @ChgRef{Version=[2],Kind=[Deleted]} @ChgDeleted{Version=[2],Text=[Thus, when a task becomes ready, this is a task dispatching point for all running tasks of lower priority.]} @end{Ramification} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} An implementation is allowed to define additional resources as execution resources, and to define the corresponding allocation policies for them. Such resources may have an implementation@Chg{Version=[2],New=[-],Old=[ ]}defined effect on task dispatching@Chg{Version=[2],New=[], Old=[ (see @RefSecNum{Task Dispatching Pragmas})]}. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The @Chg{Version=[2],New=[effect],Old=[affect]} of implementation@Chg{Version=[2],New=[-],Old=[ ]}defined execution resources on task dispatching.]} An implementation may place implementation-defined restrictions on tasks whose active priority is in the Interrupt_Priority range. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For example, on some operating systems, it might be necessary to disallow them altogether. This permission applies to tasks whose priority is set to interrupt level for any reason: via @Chg{Version=[3],New=[an aspect],Old=[a pragma]}, via a call to Dynamic_Priorities.Set_Priority, or via priority inheritance. @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00321-01]} @ChgNote{This was moved up from the previous section.} @ChgAdded{Version=[2],Text=[@Redundant[For optimization purposes,] an implementation may alter the points at which task dispatching occurs, in an implementation-defined manner. However, a @nt{delay_statement} always corresponds to at least one task dispatching point.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Chg{Version=[3],New=[Clause],Old=[Section]} @RefSecNum{Tasks and Synchronization} specifies under which circumstances a task becomes ready. The ready state is affected by the rules for task activation and termination, delay statements, and entry calls. @PDefn{blocked} When a task is not ready, it is said to be blocked. An example of a possible implementation-defined execution resource is a page of physical memory, which needs to be loaded with a particular page of virtual memory before a task can continue execution. The ready queues are purely conceptual; there is no requirement that such lists physically exist in an implementation. While a task is running, it is not on any ready queue. Any time the task that is running on a processor is added to a ready queue, a new running task is selected for that processor. In a multiprocessor system, a task can be on the ready queues of more than one processor. At the extreme, if several processors share the same set of ready tasks, the contents of their ready queues is identical, and so they can be viewed as sharing one ready queue, and can be implemented that way. @Redundant[Thus, the dispatching model covers multiprocessors where dispatching is implemented using a single ready queue, as well as those with separate dispatching domains.] The priority of a task is determined by rules specified in this subclause, and under @RefSec{Task Priorities}, @RefSec{Priority Ceiling Locking}, and @RefSec{Dynamic Priorities}. @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgNote{This note is moved up from the next subclause.} @ChgAdded{Version=[2],Text=[The setting of a task's base priority as a result of a call to Set_Priority does not always take effect immediately when Set_Priority is called. The effect of setting the task's base priority is deferred while the affected task performs a protected action.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[This description is simplified to describe only the parts of the dispatching model common to all policies. In particular, rules about preemption are moved elsewhere. This makes it easier to add other policies (which @Chg{Version=[3],New=[might],Old=[may]} not involve preemption).]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Procedure Yield is added to Dispatching. If Dispatching is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Yield is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @LabeledRevisedSubClause{Version=[2], New=[Task Dispatching Pragmas], Old=[The Standard Task Dispatching Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} allows a single task dispatching policy to be defined for all priorities, or the range of priorities to be split into subranges that are assigned individual dispatching policies.]]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Task_Dispatching_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Task_Dispatching_Policy)(@SynI{policy_}@Syn2{identifier});' @begin{SyntaxText} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Priority_Specific_Dispatching is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[Added]} @AddedPragmaSyn<Version=[2],@ChgAdded{Version=[2],Text=`@key{pragma} @prag<Priority_Specific_Dispatching> (@* @ @ @ @ @ @SynI{policy_}@Syn2{identifier}, @SynI{first_priority_}@Syn2{expression}, @SynI{last_priority_}@Syn2{expression});'}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The expected type for @SynI{first_priority_}@nt{expression} and @SynI{last_priority_}@nt{expression} is Integer.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01],ARef=[AI95-00355-01]} The @SynI{policy_}@nt{identifier} @Chg{Version=[2],New=[used in a @nt{pragma} Task_Dispatching_Policy shall be the name of a task dispatching policy], Old=[shall either be FIFO_Within_Priorities or an implementation-defined @Syn2{identifier}]}. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined @SynI{policy_}@Syn2{identifier}s allowed in a @nt{pragma} Task_Dispatching_Policy.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} used in a @nt{pragma} Priority_Specific_Dispatching shall be the name of a task dispatching policy.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Both @Syni{first_priority_}@!@nt{expression} and @Syni{last_priority_}@!@nt{expression} shall be static expressions in the range of System.Any_Priority; @SynI{last_priority_}@!@nt{expression} shall have a value greater than or equal to @SynI{first_priority_}@!@nt{expression}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Task_Dispatching_Policy specifies the single task dispatching policy.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@nt{Pragma} Priority_Specific_Dispatching specifies the task dispatching policy for the specified range of priorities. Tasks with base priorities within the range of priorities specified in a Priority_Specific_Dispatching pragma have their active priorities determined according to the specified dispatching policy. Tasks with active priorities within the range of priorities specified in a Priority_Specific_Dispatching pragma are dispatched according to the specified dispatching policy.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Each ready queue is managed by exactly one policy. Anything else would be chaos. The ready queue is determined by the active priority. However, how the active priority is calculated is determined by the policy; in order to break out of this circle, we have to say that the active priority is calculated by the method determined by the policy of the base priority.]} @end{Reason} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas@Chg{Version=[3],New=[,],Old=[]} the dispatching policy for priorities not covered by any Priority_Specific_Dispatching pragmas is FIFO_Within_Priorities.]} @end{StaticSem} @begin{LinkTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @PDefn2{Term=[configuration pragma], Sec=(Task_Dispatching_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Task_Dispatching_Policy)} A Task_Dispatching_Policy pragma is a configuration pragma.@Chg{Version=[2], New=[ A Priority_Specific_Dispatching pragma is a configuration pragma. @PDefn2{Term=[configuration pragma], Sec=(Priority_Specific_Dispatching)} @PDefn2{Term=[pragma, configuration], Sec=(Priority_Specific_Dispatching)}],Old=[]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The priority ranges specified in more than one Priority_Specific_Dispatching pragma within the same partition shall not be overlapping.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas it shall not contain a Task_Dispatching_Policy pragma.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00333-01]} @ChgDeleted{Version=[2],Text=[If the FIFO_Within_Priorities policy is specified for a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @Defn{task dispatching policy} @Redundant[A @i{task dispatching policy} specifies the details of task dispatching that are not covered by the basic task dispatching model. These rules govern when tasks are inserted into and deleted from the ready queues@Chg{Version=[2],New=[],Old=[, and whether a task is inserted at the head or the tail of the queue for its active priority]}.] @Chg{Version=[2],New=[A single],Old=[The]} task dispatching policy is specified by a Task_Dispatching_Policy @Chg{Version=[2],New=[],Old=[configuration ]}pragma. @Chg{Version=[2],New=[Pragma Priority_Specific_Dispatching assigns distinct dispatching policies to subranges of System.Any_Priority.], Old=[@PDefn{unspecified}If no such pragma appears in any of the program units comprising a partition, the task dispatching policy for that partition is unspecified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@PDefn{unspecified}If neither @nt{pragma} applies to any of the program units comprising a partition, the task dispatching policy for that partition is unspecified.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0262-1]} @ChgAdded{Version=[2],Text=[If a partition contains one or more Priority_Specific_Dispatching pragmas@Chg{Version=[3],New=[,],Old=[]} a task dispatching point occurs for the currently running task of a processor whenever there is a nonempty ready queue for that processor with a higher priority than the priority of the running task.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[If we have priority specific dispatching then we want preemption across the entire range of priorities. That prevents higher priority tasks from being blocked by lower priority tasks that have a different policy. On the other hand, if we have a single policy for the entire partition, we want the characteristics of that policy to apply for preemption; specifically, we @Chg{Version=[3],New=[might],Old=[may]} not require any preemption. Note that policy Non_Preemptive_FIFO_Within_Priorities is not allowed in a priority specific dispatching pragma.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A task that has its base priority changed may move from one dispatching policy to another. It is immediately subject to the new dispatching policy.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Once subject to the new dispatching policy, it may be immediately preempted or dispatched, according the rules of the new policy.]} @end{Ramification} @ChgNote{The following stuff is moved to the next subclause} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 7 through 13 were moved to D.2.3.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[The language defines only one task dispatching policy, FIFO_Within_Priorities; when this policy is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority, except in the case where the active priority is lowered due to the loss of inherited priority, in which case the task is added at the head of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} Each of the events specified above is a task dispatching point (see @RefSecNum{The Task Dispatching Model}).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[In addition, when a task is preempted, it is added at the head of the ready queue for its active priority.]} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00333-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking and also one or more Priority_Specific_Dispatching pragmas to be given.]} @end{ImplReq} @begin{DocReq} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 14 through 16 were moved to D.2.3.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Type=[Leading],Text=[@Defn{priority inversion} @i{Priority inversion} is the duration for which a task remains at the head of the highest priority ready queue while the processor executes a lower priority task. The implementation shall document:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[The maximum priority inversion a user task can experience due to activity of the implementation (on behalf of lower priority tasks), and]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[whether execution of a task can be preempted by the implementation processing of delay expirations for lower priority tasks, and if so, for how long.]} @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of priority inversion.]}]} @end{Itemize} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other task dispatching policies, but need not support more than one @Chg{Version=[2],New=[task dispatching], Old=[such]} policy per partition. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} @Chg{Version=[2],New=[An implementation need not support @nt{pragma} Priority_Specific_Dispatching if it is infeasible to support it in the target environment.], Old=[@Redundant[For optimization purposes,] an implementation may alter the points at which task dispatching occurs, in an implementation defined manner. However, a @nt{delay_statement} always corresponds to at least one task dispatching point.]} @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[Implementation defined task dispatching@Chg{Version=[2],New=[ policies],Old=[]}.]} @end{ImplPerm} @begin{Notes} @begin{NotIso} @ChgAdded{Version=[2],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 19 through 21 were deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[If the active priority of a running task is lowered due to loss of inherited priority (as it is on completion of a protected operation) and there is a ready task of the same active priority that is not running, the running task continues to run (provided that there is no higher priority task).]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[The setting of a task's base priority as a result of a call to Set_Priority does not always take effect immediately when Set_Priority is called. The effect of setting the task's base priority is deferred while the affected task performs a protected action.]} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00321-01]} @ChgDeleted{Version=[2],Text=[Setting the base priority of a ready task causes the task to move to the end of the queue for its active priority, regardless of whether the active priority of the task actually changes.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @B[Amendment Correction:] It is no longer required to specify Ceiling_Locking with the language-defined task dispatching policies; we only require that implementations @i<allow> them to be used together.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@key{Pragma} Priority_Specific_Dispatching is new; it allows @Chg{Version=[3],New=[the specification of],Old=[specifying]} different policies for different priorities.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one task dispatching policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[This description is simplified to describe only the rules for the Task_Dispatching_Policy pragma that are common to all policies. In particular, rules about preemption are moved elsewhere. This makes it easier to add other policies (which @Chg{Version=[3],New=[might],Old=[may]} not involve preemption).]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Preemptive Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines a preemptive task dispatching policy.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} FIFO_Within_Priorities is a task dispatching policy.@Chg{Version=[3],New=[@Defn2{Term=[task dispatching policy], Sec=(FIFO_Within_Priorities)}@Defn{FIFO_Within_Priorities task dispatching policy}], Old=[]}]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[When FIFO_Within_Priorities is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority, except in the case where the active priority is lowered due to the loss of inherited priority, in which case the task is added at the head of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[@PDefn{task dispatching point} @PDefn{dispatching point} Each of the events specified above is a task dispatching point (see @RefSecNum{The Task Dispatching Model}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[A task dispatching point occurs for the currently running task of a processor whenever there is a nonempty ready queue for that processor with a higher priority than the priority of the running task. The currently running task is said to be @i<preempted> and it is added at the head of the ready queue for its active priority.@Defn2{Term=[preempt],Sec=[a running task]}]} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as FIFO_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the FIFO_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Defn{priority inversion} @i{Priority inversion} is the duration for which a task remains at the head of the highest priority nonempty ready queue while the processor executes a lower priority task. The implementation shall document:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The maximum priority inversion a user task can experience due to activity of the implementation (on behalf of lower priority tasks), and]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The maximum priority inversion a user task can experience from the implementation.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[whether execution of a task can be preempted by the implementation processing of delay expirations for lower priority tasks, and if so, for how long.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The amount of time that a task can be preempted for processing on behalf of lower-priority tasks.]}]} @end{Itemize} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[If the active priority of a running task is lowered due to loss of inherited priority (as it is on completion of a protected operation) and there is a ready task of the same active priority that is not running, the running task continues to run (provided that there is no higher priority task).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[Setting the base priority of a ready task causes the task to move to the tail of the queue for its active priority, regardless of whether the active priority of the task actually changes.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[This subclause is new; it mainly consists of text that was found in @RefSecNum{The Task Dispatching Model} and @RefSecNum{Task Dispatching Pragmas} in Ada 95. This was separated out so the definition of additional policies was easier.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[We require that implementations allow this policy and Ceiling_Locking together.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[We explicitly defined FIFO_Within_Priorities to be a task dispatching policy.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Non-Preemptive Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines a non-preemptive task dispatching policy.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} Non_Preemptive_FIFO_Within_Priorities is a task dispatching policy.@Chg{Version=[3],New=[@Defn2{Term=[task dispatching policy], Sec=(Non_Preemptive_@!FIFO_@!Within_@!Priorities)}@Defn{Non_Preemptive_FIFO_@!Within_@!Priorities task disp. policy}], Old=[]}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[@key<package> Ada.Dispatching.Non_Preemptive @key<is>@ChildUnit{Parent=[Ada.Dispatching],Child=[Non_Preemptive]} @key<pragma> Preelaborate(Non_Preemptive); @key<procedure> @AdaSubDefn{Yield_To_Higher}; @key<procedure> @AdaSubDefn{Yield_To_Same_Or_Higher} @key<renames> Yield; @key<end> Ada.Dispatching.Non_Preemptive;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0166-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[A call of Yield_To_Higher is a task dispatching point for this policy. If the task at the head of the highest priority ready queue has a higher active priority than the calling task, then the calling task is preempted.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[For language-defined policies other than Non_Preemptive_FIFO_Within_Priorities, a higher priority task should never be on a ready queue while a lower priority task is executed. Thus, for such policies, Yield_To_Higher does nothing.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Yield_To_Higher is @i<not> a potentially blocking operation; it can be used during a protected operation. That is allowed, as under the predefined Ceiling_Locking policy any task with a higher priority than the protected operation cannot call the operation (that would violate the locking policy). An implementation-defined locking policy may need to define the semantics of Yield_To_Higher differently.]} @end{Ramification} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Non_Preemptive_FIFO_Within_Priorities shall not be specified as the @SynI{policy_}@nt{identifier} of @nt{pragma} Priority_Specific_Dispatching (see @RefSecNum{Task Dispatching Pragmas}).]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The non-preemptive nature of this policy could cause the policies of higher priority tasks to malfunction, missing deadlines and having unlimited priority inversion. That would render the use of such policies impotent and misleading. As such, this policy only makes sense for a complete system.]} @end{Reason} @end{Legality} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[When Non_Preemptive_FIFO_Within_Priorities is in effect, modifications to the ready queues occur only as follows:]} @begin{itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgAdded{Version=[2],Text=[When a blocked task becomes ready, it is added at the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the active priority of a ready task that is not running changes, or the setting of its base priority takes effect, the task is removed from the ready queue for its old active priority and is added at the tail of the ready queue for its new active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a running task takes effect, the task is added to the tail of the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task executes a @nt{delay_statement} that does not result in blocking, it is added to the tail of the ready queue for its active priority.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[If the delay does result in blocking, the task moves to the @lquotes@;delay queue@rquotes@;, not to the ready queue.]} @end{Ramification} @end{itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0166-1]} @ChgAdded{Version=[2],Text=[For this policy, @Chg{Version=[3],New=[blocking or termination of a task, ],Old=[]}a@Chg{Version=[3],New=[],Old=[ non-blocking]} @nt{delay_statement}@Chg{Version=[3],New=[, a call to Yield_To_Higher, and a call to Yield_To_Same_Or_Higher or Yield are],Old=[ is]} the only@Chg{Version=[3],New=[],Old=[ non-blocking event that is a]} task dispatching @Chg{Version=[3],New=[points],Old=[point]} (see @RefSecNum{The Task Dispatching Model}).@PDefn{task dispatching point} @PDefn{dispatching point}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],Text=[A @nt{delay_statement} is always a task dispatching point even if it is not blocking. Similarly, a call to Yield_To_Higher is never blocking, but it is a task dispatching point In each of these cases, they can cause the current task to stop running (it is still ready). Otherwise, the running task continues to run until it is blocked.]} @end{Ramification} @end{RunTime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as Non_Preemptive_FIFO_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the Non_Preemptive_FIFO_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[2],Text=[Since implementations are allowed to round all ceiling priorities in subrange System.Priority to System.Priority'Last (see @RefSecNum{Priority Ceiling Locking}), an implementation may allow a task@Chg{Version=[3],New=[ of a partition using the Non_Premptive_FIFO_Within_Priorities policy],Old=[]} to execute within a protected object without raising its active priority provided the associated protected unit does not contain @Chg{Version=[3],New=[any subprograms with aspects Interrupt_Handler or Attach_Handler specified, nor does the unit have aspect],Old=[pragma]} Interrupt_Priority @Chg{Version=[3],New=[ specified. When the locking policy (see @RefSecNum{Priority Ceiling Locking}) is Ceiling_Locking, an implementation taking advantage of this permission shall ensure that a call to Yield_to_Higher that occurs within a protected action uses the ceiling priority of the protected object (rather than the active priority of the task) when determining whether to preempt the task],Old=[, Interrupt_Handler, or Attach_Handler]}.]} @begin{Reason} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[We explicitly require that the ceiling priority be used in calls to Yield_to_Higher in order to prevent a risk of priority inversion and consequent loss of mutual exclusion when Yield_to_Higher is used in a protected object. This requirement might lessen the value of the permission (as the current Ceiling_Priority will have to be maintained in the TCB), but loss of mutual exclusion cannot be tolerated. The primary benefit of the permission (eliminating the need for preemption at the end of a protected action) is still available. As noted above, an implementation-defined locking policy will need to specify the semantics of Yield_to_Higher, including this case.]} @end{Reason} @end{ImplPerm} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00298-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy Non_Preemptive_FIFO_Within_Priorities is new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0166-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Package Dispatching.Non_Preemptive is new.]} @end{Extend2005} @RMNewPageVer{Version=[3]}@Comment{For printed RM Ada 2012} @LabeledAddedSubClause{Version=[2],Name=[Round Robin Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines the task dispatching policy Round_Robin_Within_Priorities and the package Round_Robin.]]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy}_@nt{identifier} Round_Robin_Within_Priorities is a task dispatching policy.@Chg{Version=[3],New=[@Defn2{Term=[task dispatching policy], Sec=(Round_Robin_Within_Priorities)}@Defn{Round_Robin_Within_Priorities task dispatching policy}], Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} System; @key{with} Ada.Real_Time; @key{package} Ada.Dispatching.Round_Robin @key{is}@ChildUnit{Parent=[Ada.Dispatching],Child=[Round_Robin]} @AdaObjDefn{Default_Quantum} : @key{constant} Ada.Real_Time.Time_Span := @RI[implementation-defined]; @key{procedure} @AdaSubDefn{Set_Quantum} (Pri : @key{in} System.Priority; Quantum : @key{in} Ada.Real_Time.Time_Span); @key{procedure} @AdaSubDefn{Set_Quantum} (Low, High : @key{in} System.Priority; Quantum : @key{in} Ada.Real_Time.Time_Span); @key{function} @AdaSubDefn{Actual_Quantum} (Pri : System.Priority) @key{return} Ada.Real_Time.Time_Span; @key{function} @AdaSubDefn{Is_Round_Robin} (Pri : System.Priority) @key{return} Boolean; @key{end} Ada.Dispatching.Round_Robin;]} @end{Example} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The value of Default_Quantum in Dispatching.Round_Robin.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[When task dispatching policy Round_Robin_Within_Priorities is the single policy in effect for a partition, each task with priority in the range of System.Interrupt_Priority is dispatched according to policy FIFO_Within_Priorities.]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The procedures Set_Quantum set the required Quantum value for a single priority level Pri or a range of priority levels Low .. High. If no quantum is set for a Round Robin priority level, Default_Quantum is used.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The function Actual_Quantum returns the actual quantum used by the implementation for the priority level Pri.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Is_Round_Robin returns True if priority Pri is covered by task dispatching policy Round_Robin_Within_Priorities; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A call of Actual_Quantum or Set_Quantum raises exception Dispatching.Dispatching_Policy_Error if a predefined policy other than Round_Robin_Within_Priorities applies to the specified priority or any of the priorities in the specified range.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For Round_Robin_Within_Priorities, the dispatching rules for FIFO_Within_Priorities apply with the following additional rules:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task is added or moved to the tail of the ready queue for its base priority, it has an execution time budget equal to the quantum for that priority level. This will also occur when a blocked task becomes executable again.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task is preempted (by a higher priority task) and is added to the head of the ready queue for its priority level, it retains its remaining budget.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[While a task is executing, its budget is decreased by the amount of execution time it uses. The accuracy of this accounting is the same as that for execution time clocks (see @RefSecNum{Execution Time}).]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Note that this happens even when the task is executing at a higher, inherited priority, and even if that higher priority is dispatched by a different policy than round robin.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[When a task has exhausted its budget and is without an inherited priority (and is not executing within a protected operation), it is moved to the tail of the ready queue for its priority level. This is a task dispatching point.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In this case, it will be given a budget as described in the first bullet.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The rules for FIFO_Within_Priority (to which these bullets are added) say that a task that has its base priority set to a Round Robin priority is moved to the tail of the ready queue for its new priority level, and then will be given a budget as described in the first bullet. That happens whether or not the task's original base priority was a Round Robin priority.]} @end{Ramification} @end{Itemize} @end{Runtime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00333-01],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall allow, for a single partition, both the task dispatching policy to be specified as Round_Robin_Within_Priorities and also the locking policy (see @RefSecNum{Priority Ceiling Locking}) to be specified as Ceiling_Locking.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the preferred combination of the Round_Robin_Within_Priorities policy with a locking policy, and we want that combination to be portable.]} @end{Reason} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall document the quantum values supported.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The quantum values supported for round robin dispatching.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[An implementation shall document the accuracy with which it detects the exhaustion of the budget of a task.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The accuracy of the detection of the exhaustion of the budget of a task for round robin dispatching.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Due to implementation constraints, the quantum value returned by Actual_Quantum might not be identical to that set with Set_Quantum.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[A task that executes continuously with an inherited priority will not be subject to round robin dispatching.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy Round_Robin_Within_Priorities and package Dispatching.Round_Robin are new.]} @end{Extend95} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledAddedSubClause{Version=[2],Name=[Earliest Deadline First Dispatching]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The deadline of a task is an indication of the urgency of the task; it represents a point on an ideal physical time line. The deadline might affect how resources are allocated to the task.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines a package for representing the deadline of a task and a dispatching policy that defines Earliest Deadline First (EDF) dispatching. @Chg{Version=[3],New=[An aspect],Old=[A pragma]} is defined to assign an initial deadline to a task.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[aspect],Old=[pragma]} is the only way of assigning an initial deadline to a task so that its activation can be controlled by EDF scheduling. This is similar to the way @Chg{Version=[3],New=[aspect],Old=[pragma]} Priority is used to give an initial priority to a task.]} @end{Discussion} @end{Intro} @begin{MetaRules} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[To predict the behavior of a multi-tasking program it is necessary to control access to the processor which is preemptive, and shared objects which are usually non-preemptive and embodied in protected objects. Two common dispatching policies for the processor are fixed priority and EDF. The most effective control over shared objects is via preemption levels. With a pure priority scheme a single notion of priority is used for processor dispatching and preemption levels. With EDF and similar schemes priority is used for preemption levels (only), with another measure used for dispatching. T.P. Baker showed (@i<Real-Time Systems>, March 1991, vol. 3, num. 1, @i<Stack-Based Scheduling of Realtime Processes>) that for EDF a newly released task should only preempt the currently running task if it has an earlier deadline and a higher preemption level than any currently @lquotes@;locked@rquotes protected object. The rules of this @Chg{Version=[3],New=[subclause],Old=[clause]} implement this scheme including the case where the newly released task should execute before some existing tasks but not preempt the currently executing task.]} @end{MetaRules} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 3 through 6 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Keepnext=[T],Text=[@Chg{Version=[2],New=[The form of a @nt{pragma} Relative_Deadline is as follows:],Old=[]}]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[2],@ChgDeleted{Version=[3], Text=`@Chg{Version=[2],New=[@key{pragma} @prag<Relative_Deadline> (@SynI{relative_deadline_}@Syn2{expression});],Old=[]}'}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[The expected type for @SynI{relative_deadline_}@nt{expression} is Real_Time.Time_Span.],Old=[]}]} @end{Resolution} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@Chg{Version=[2],New=[A Relative_Deadline pragma is allowed only immediately within a @nt{task_definition} or the @nt{declarative_part} of a @nt{subprogram_body}. At most one such pragma shall appear within a given construct.],Old=[]}]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The @SynI{policy_}@nt{identifier} EDF_Across_Priorities is a task dispatching policy.@Chg{Version=[3],New=[@Defn2{Term=[task dispatching policy], Sec=(EDF_Across_Priorities)}@Defn{EDF_Across_Priorities task dispatching policy}], Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Real_Time; @key{with} Ada.Task_Identification; @key{package} Ada.Dispatching.EDF @key{is}@ChildUnit{Parent=[Ada.Dispatching],Child=[EDF]} @key{subtype} @AdaSubtypeDefn{Name=[Deadline],Of=[Time]} @key{is} Ada.Real_Time.Time; @AdaObjDefn{Default_Deadline} : @key{constant} Deadline := Ada.Real_Time.Time_Last; @key{procedure} @AdaSubDefn{Set_Deadline} (D : @key{in} Deadline; T : @key{in} Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task); @key{procedure} @AdaSubDefn{Delay_Until_And_Set_Deadline} ( Delay_Until_Time : @key{in} Ada.Real_Time.Time; Deadline_Offset : @key{in} Ada.Real_Time.Time_Span); @key{function} @AdaSubDefn{Get_Deadline} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key{return} Deadline; @key{end} Ada.Dispatching.EDF;]} @end{Example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a task type (including the anonymous type of a @nt{single_task_declaration}) or subprogram, the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Relative_Deadline@\The aspect Relative_Deadline is an @nt{expression}, which shall be of type Real_Time.Time_Span.@AspectDefn{Relative_Deadline}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Relative_Deadline], Text=[@ChgAdded{Version=[3],Text=[Task parameter used in Earliest Deadline First Dispatching.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The Relative_Deadline aspect shall not be specified on a task interface type.]} @end{Legality} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[If the EDF_Across_Priorities policy is specified for a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[If the EDF_Across_Priorities policy appears in a Priority_Specific_Dispatching pragma (see @RefSecNum{Task Dispatching Pragmas}) in a partition, then the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) shall also be specified for the partition.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Unlike the other language-defined dispatching policies, the semantic description of EDF_Across_Priorities assumes Ceiling_Locking (and a ceiling priority) in order to make the mapping between deadlines and priorities work. Thus, we require both policies to be specified if EDF is used in the partition.]} @end{Reason} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[The],Old=[A]} Relative_Deadline @Chg{Version=[3],New=[aspect],Old=[pragma]} has no effect if it @Chg{Version=[3],New=[is specified for], Old=[occurs in the @nt{declarative_part} of the @nt{subprogram_body} of]} a subprogram other than the main subprogram.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[The initial absolute deadline of a task @Chg{Version=[3],New=[for which aspect],Old=[containing pragma]} Relative_Deadline@Chg{Version=[3],New=[ is specified],Old=[]} is the value of Real_Time.Clock + @Chg{Version=[3],New=[the @nt{expression} that is the value of the aspect],Old=[@SynI{relative_deadline_}@nt{expression}]}, where @Chg{Version=[3],New=[this entire expression, including ],Old=[]}the call of Real_Time.Clock@Chg{Version=[3],New=[, is evaluated],Old=[ is made]} between task creation and the start of its activation. If @Chg{Version=[3],New=[the aspect],Old=[there is no]} Relative_Deadline @Chg{Version=[3],New=[is not specified,],Old=[pragma]} then the initial absolute deadline of a task is the value of Default_Deadline. The environment task is also given an initial deadline by this rule@Chg{Version=[3],New=[, using the value of the Relative_Deadline aspect of the main subprogram (if any)],Old=[]}.]} @begin{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task is a normal task by @RefSecNum{Program Execution}, so of course this rule applies to it.]} @end{TheProof} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The procedure Set_Deadline changes the absolute deadline of the task to D. The function Get_Deadline returns the absolute deadline of the task.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The procedure Delay_Until_And_Set_Deadline delays the calling task until time Delay_Until_Time. When the task becomes runnable again it will have deadline Delay_Until_Time + Deadline_Offset.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[On a system with a single processor, the setting of the deadline of a task to the new value occurs immediately at the first point that is outside the execution of a protected action. If the task is currently on a ready queue it is removed and re-entered on to the ready queue determined by the rules defined below.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When EDF_Across_Priorities is specified for priority range @i<Low>..@i<High> all ready queues in this range are ordered by deadline. The task at the head of a queue is the one with the earliest deadline.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[A task dispatching point occurs for the currently running task @i<T> to which policy EDF_Across_Priorities applies:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[when a change to the deadline of @i<T> occurs;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[there is a task on the ready queue for the active priority of @i<T> with a deadline earlier than the deadline of @i<T>; or]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[there is a nonempty ready queue for that processor with a higher priority than the active priority of the running task.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[In these cases, the currently running task is said to be preempted and is returned to the ready queue for its active priority.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[For a task @i<T> to which policy EDF_Across_Priorities applies, the base priority is not a source of priority inheritance; the active priority when first activated or while it is blocked is defined as the maximum of the following:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the lowest priority in the range specified as EDF_Across_Priorities that includes the base priority of @i<T>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[the priorities, if any, currently inherited by @i<T>;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised], ARef=[AI05-0055-1]} @ChgAdded{Version=[2],Text=[the highest priority @i<P>, if any, less than the base priority of @i<T> such that one or more tasks are executing within a protected object with ceiling priority @i<P> and task @i<T> has an earlier deadline than all such tasks@Chg{Version=[3],New=[; and furthermore @i<T> has an earlier deadline than all other tasks on ready queues with priorities in the given EDF_Across_Priorities range that are strictly less than @i<P>],Old=[]}.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The active priority of @i<T> might be lower than its base priority.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When a task @i<T> is first activated or becomes unblocked, it is added to the ready queue corresponding to this active priority. Until it becomes blocked again, the active priority of @i<T> remains no less than this value; it will exceed this value only while it is inheriting a higher priority.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[These rules ensure that a task executing in a protected object is preempted only by a task with a shorter deadline and a higher base priority. This matches the traditional preemption level description without the need to define a new kind of protected object locking.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[When the setting of the base priority of a ready task takes effect and the new priority is in a range specified as EDF_Across_Priorities, the task is added to the ready queue corresponding to its new active priority, as determined above.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[For all the operations defined in Dispatching.EDF, Tasking_Error is raised if the task identified by T has terminated. Program_Error is raised if the value of T is Null_Task_Id.]} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If EDF_Across_Priorities is specified for priority range @i<Low>..@i<High>, it is a bounded error to declare a protected object with ceiling priority @i<Low> or to assign the value @i<Low> to attribute 'Priority. In either case either Program_Error is raised or the ceiling of the protected object is assigned the value @i<Low>+1.]} @end{Bounded} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the subprograms of this package and the corresponding task object no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[On a multiprocessor, the implementation shall document any conditions that cause the completion of the setting of the deadline of a task to be delayed later than what is specified for a single processor.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any conditions that cause the completion of the setting of the deadline of a task to be delayed for a multiprocessor.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If two adjacent priority ranges, @i<A>..@i<B> and @i<B>+1..@i<C> are specified to have policy EDF_Across_Priorities@Chg{Version=[3],New=[,],Old=[]} then this is not equivalent to this policy being specified for the single range, @i<A>..@i<C>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The above rules implement the preemption-level protocol (also called Stack Resource Policy protocol) for resource sharing under EDF dispatching. The preemption-level for a task is denoted by its base priority. The definition of a ceiling preemption-level for a protected object follows the existing rules for ceiling locking.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[An implementation may support additional dispatching policies by replacing absolute deadline with an alternative measure of urgency.]} @end{ImplNote} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Policy EDF_Across_Priorities and package Dispatching.EDF are new.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspect Relative_Deadline is new; @nt{pragma} Relative_Deadline is now obsolescent.]} @end{Extend2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0055-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Corrected definition of active priority to avoid deadline inversion in an unusual case.]} @end{Diffword2005} @LabeledClause{Priority Ceiling Locking} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies the interactions between priority task scheduling and protected object ceilings. This interaction is based on the concept of the @i{ceiling priority} of a protected object.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Locking_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Locking_Policy)(@SynI{policy_}@Syn2{identifier});' @end{Syntax} @begin{Legality} The @SynI{policy_}@Syn2{identifier} shall either be Ceiling_Locking or an implementation-defined @Syn2{identifier}. @ImplDef{Implementation-defined @SynI{policy_}@Syn2{identifier}s allowed in a @nt{pragma} Locking_Policy.} @end{Legality} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Locking_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Locking_Policy)} A Locking_Policy pragma is a configuration pragma. @end{LinkTime} @begin{RunTime} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0073],ARef=[AI95-00091-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @Defn{locking policy} @Redundant[A locking policy specifies the details of protected object locking. @Chg{Version=[2],New=[All protected objects have a priority. The locking policy specifies the meaning of the priority of a],Old=[These rules specify whether or not]} protected @Chg{Version=[2], New=[object],Old=[objects have priorities]}, and the relationships between these priorities and task priorities. In addition, the policy specifies the state of a task when it executes a protected action, and how its active priority is affected by the locking.] The @i{locking policy} is specified by a Locking_Policy pragma. For implementation-defined locking policies, the @Chg{Version=[2],New=[meaning of the priority of],Old=[effect of a Priority or Interrupt_Priority pragma on]} a protected object is implementation defined. If no Locking_Policy pragma @Chg{New=[applies to],Old=[appears in]} any of the program units comprising a partition, the locking policy for that partition, as well as the @Chg{Version=[2],New=[meaning of the priority of],Old=[effect of specifying either a Priority or Interrupt_Priority pragma for]} a protected object, are implementation defined. @Chg{Version=[2],New=[@Defn2{Term=[Priority],Sec=[of a protected object]}],Old=[]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The locking policy if no Locking_Policy pragma applies to any unit of a partition.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[The @nt{expression} @Chg{Version=[3],New=[specified for the],Old=[of a]} Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]} (see @RefSecNum{Task Priorities}) is evaluated as part of the creation of the corresponding protected object and converted to the subtype System.Any_Priority or System.Interrupt_Priority, respectively. The value of the expression is the initial priority of the corresponding protected object. If no Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect is specified for],Old=[pragma applies to]} a protected object, the initial priority is specified by the locking policy. @Chg{Version=[3],New=[@PDefn2{Term=[implicit subtype conversion],Sec=(Priority aspect)} @PDefn2{Term=[implicit subtype conversion],Sec=(Interrupt_Priority aspect)}], Old=[@PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)}]}]} @Leading@;There is one predefined locking policy, Ceiling_Locking; this policy is defined as follows:@Chg{Version=[3],New=[@Defn2{Term=[locking policy], Sec=(Ceiling_Locking)}@Defn{Ceiling_Locking locking policy}], Old=[]} @begin{itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[ceiling priority], Sec=(of a protected object)} Every protected object has a @i{ceiling priority}, which is determined by either a Priority or Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]} as defined in @RefSecNum{Task Priorities}@Chg{Version=[2],New=[, or by assignment to the Priority attribute as described in @RefSecNum{Dynamic Priorities for Protected Objects}],Old=[]}. The ceiling priority of a protected object (or ceiling, for short) is an upper bound on the active priority a task can have when it calls protected operations of that protected object. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} The @Chg{Version=[2],New=[initial ceiling priority of a],Old=[@nt{expression} of a Priority or Interrupt_Priority pragma is evaluated as part of the creation of the corresponding]} protected object @Chg{Version=[2],New=[is equal to the initial priority for that object.],Old=[and converted to the subtype System.Any_Priority or System.Interrupt_Priority, respectively. The value of the @nt{expression} is the ceiling priority of the corresponding protected object. @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Priority)} @PDefn2{Term=[implicit subtype conversion],Sec=(pragma Interrupt_Priority)}]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If an Interrupt_Handler or Attach_Handler @Chg{Version=[3],New=[aspect], Old=[pragma]} (see @RefSecNum{Protected Procedure Handlers}) @Chg{Version=[3],New=[is specified for a protected subprogram of a protected type that does not have the ],Old=[appears in a @nt{protected_definition} without an]} Interrupt_Priority @Chg{Version=[3],New=[aspect specified],Old=[pragma]}, the @Chg{Version=[2],New=[initial],Old=[ceiling]} priority of protected objects of that type is implementation defined, but in the range of the subtype System.Interrupt_Priority. @ImplDef{Default ceiling priorities.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If @Chg{Version=[3],New=[neither aspect],Old=[no @nt{pragma}]} Priority@Chg{Version=[3],New=[ nor],Old=[,]} Interrupt_Priority@Chg{Version=[3],New=[],Old=[, Interrupt_Handler, or Attach_Handler]} is specified @Chg{Version=[3],New=[for a protected type, and no protected subprogram of the type has aspect Interrupt_Handler or Attach_Handler specified],Old=[in the @nt{protected_definition}]}, then the @Chg{Version=[2],New=[initial],Old=[ceiling]} priority of the corresponding protected object is System.Priority'Last. While a task executes a protected action, it inherits the ceiling priority of the corresponding protected object. @IndexCheck{Ceiling_Check} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} When a task calls a protected operation, a check is made that its active priority is not higher than the ceiling of the corresponding protected object; Program_Error is raised if this check fails. @end{Itemize} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[Following any change of priority, it is a bounded error for the active priority of any task with a call queued on an entry of a protected object to be higher than the ceiling priority of the protected object. @PDefn2{Term=(bounded error),Sec=(cause)} In this case one of the following applies:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[at any time prior to executing the entry body Program_Error is raised in the calling task; @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object;]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object and then Program_Error is raised in the calling task; or @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[when the entry is open the entry body is executed at the ceiling priority of the protected object that was in effect when the entry call was queued.]} @end{Itemize} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]}@Comment{This note was moved along with the above rules} @ChgAdded{Version=[2],Text=[Note that the error is @lquotes@;blamed@rquotes@; on the task that did the entry call, not the task that changed the priority of the task or protected object. This seems to make sense for the case of changing the priority of a task blocked on a call, since if the Set_Priority had happened a little bit sooner, before the task queued a call, the entry-calling task would get the error. Similarly, there is no reason not to raise the priority of a task that is executing in an @nt{abortable_part}, so long as its priority is lowered before it gets to the end and needs to cancel the call. The priority might need to be lowered to allow it to remove the call from the entry queue, in order to avoid violating the ceiling. This seems relatively harmless, since there is an error, and the task is about to start raising an exception anyway.]} @end{Ramification} @end{Bounded} @begin{ImplPerm} The implementation is allowed to round all ceilings in a certain subrange of System.Priority or System.Interrupt_Priority up to the top of that subrange, uniformly. @begin{Discussion} For example, an implementation might use Priority'Last for all ceilings in Priority, and Interrupt_Priority'Last for all ceilings in Interrupt_Priority. This would be equivalent to having two ceiling priorities for protected objects, @lquotes@;nonpreemptible@rquotes@; and @lquotes@;noninterruptible@rquotes@;, and is an allowed behavior. Note that the implementation cannot choose a subrange that crosses the boundary between normal and interrupt priorities. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other locking policies, but need not support more than one @Chg{Version=[2],New=[locking],Old=[such]} policy per partition. @Redundant[Since implementations are allowed to place restrictions on code that runs at an interrupt-level active priority (see @RefSecNum{Protected Procedure Handlers} and @RefSecNum{The Task Dispatching Model}), the implementation may implement a language feature in terms of a protected object with an implementation-defined ceiling, but the ceiling shall be no less than Priority'Last.] @ImplDef{The ceiling of any protected object used internally by the implementation.} @begin{TheProof} This permission follows from the fact that the implementation can place restrictions on interrupt handlers and on any other code that runs at an interrupt-level active priority. The implementation might protect a storage pool with a protected object whose ceiling is Priority'Last, which would cause @nt{allocator}s to fail when evaluated at interrupt priority. Note that the ceiling of such an object has to be at least Priority'Last, since there is no permission for @nt{allocator}s to fail when evaluated at a noninterrupt priority. @end{TheProof} @end{ImplPerm} @begin{ImplAdvice} The implementation should use names that end with @lquotes@;_Locking@rquotes@; for implementation-defined locking policies. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Names that end with @lquotes@;_Locking@rquotes@; should be used for implementation-defined locking policies.]}]} @end{ImplAdvice} @begin{Notes} While a task executes in a protected action, it can be preempted only by tasks whose active priorities are higher than the ceiling priority of the protected object. If a protected object has a ceiling priority in the range of Interrupt_Priority, certain interrupts are blocked while protected actions of that object execute. In the extreme, if the ceiling is Interrupt_Priority'Last, all blockable interrupts are blocked during that time. The ceiling priority of a protected object has to be in the Interrupt_Priority range if one of its procedures is to be used as an interrupt handler (see @RefSecNum{Interrupt Support}). When specifying the ceiling of a protected object, one should choose a value that is at least as high as the highest active priority at which tasks can be executing when they call protected operations of that object. In determining this value the following factors, which can affect active priority, should be considered: the effect of Set_Priority, nested protected operations, entry calls, task activation, and other implementation-defined factors. Attaching a protected procedure whose ceiling is below the interrupt hardware priority to an interrupt causes the execution of the program to be erroneous (see @RefSecNum{Protected Procedure Handlers}). On a single processor implementation, the ceiling priority rules guarantee that there is no possibility of deadlock involving only protected subprograms (excluding the case where a protected operation calls another protected operation on the same protected object). @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} All protected objects now have a priority, which is the value of the Priority attribute of @RefSecNum{Dynamic Priorities for Protected Objects}. How this value is interpreted depends on the locking policy; for instance, the ceiling priority is derived from this value when the locking policy is Ceiling_Locking.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0073],ARef=[AI95-00091-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the wording to reflect that pragma Locking_Policy cannot be inside of a program unit.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one locking policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The bounded error for the priority of a task being higher than the ceiling of an object it is currently in was moved here from @RefSecNum{Dynamic Priorities}, so that it applies no matter how the situation arises.]} @end{DiffWord95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Revised to use aspects Priority and Interrupt_Priority as @nt{pragma}s Priority and Interrupt_Priority are now obsolescent.]} @end{DiffWord2005} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledClause{Entry Queuing Policies} @begin{Intro} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0074],ARef=[AI95-00068-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[@Defn{queuing policy} This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies a mechanism for a user to choose an entry @i{queuing policy}. It also defines @Chg{New=[two],Old=[one]} such polic@Chg{New=[ies],Old=[y]}. Other policies are implementation defined.] @ImplDef{Implementation-defined queuing policies.} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Queuing_Policy is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Queuing_Policy)(@SynI{policy_}@Syn2{identifier});' @end{Syntax} @begin{Legality} The @SynI{policy_}@Syn2{identifier} shall be either FIFO_Queuing, Priority_Queuing or an implementation-defined @Syn2{identifier}. @end{Legality} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Queuing_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Queuing_Policy)} A Queuing_Policy pragma is a configuration pragma. @end{LinkTime} @begin{RunTime} @Defn{queuing policy} @Redundant[A @i{queuing policy} governs the order in which tasks are queued for entry service, and the order in which different entry queues are considered for service.] The queuing policy is specified by a Queuing_Policy pragma. @begin{Ramification} The queuing policy includes entry queuing order, the choice among open alternatives of a @nt{selective_accept}, and the choice among queued entry calls of a protected object when more than one @nt{entry_barrier} @nt{condition} is True. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00355-01]} Two queuing policies, FIFO_Queuing and Priority_Queuing, are language defined. If no Queuing_Policy pragma @Chg{Version=[2],New=[applies to],Old=[appears in]} any of the program units comprising the partition, the queuing policy for that partition is FIFO_Queuing.@Chg{Version=[3],New=[@Defn2{Term=[queuing policy], Sec=(FIFO_Queuing)}@Defn{FIFO_Queuing queuing policy}], Old=[]} The rules for this policy are specified in @RefSecNum{Entry Calls} and @RefSecNum{Selective Accept}. @Leading@Keepnext@;The Priority_Queuing policy is defined as follows:@Chg{Version=[3],New=[@Defn2{Term=[queuing policy], Sec=(Priority_Queuing)}@Defn{Priority_Queuing queuing policy}], Old=[]}@begin{itemize} @Defn{priority of an entry call} The calls to an entry @Redundant[(including a member of an entry family)] are queued in an order consistent with the priorities of the calls. The @i{priority of an entry call} is initialized from the active priority of the calling task at the time the call is made, but can change later. Within the same priority, the order is consistent with the calling (or requeuing, or priority setting) time (that is, a FIFO order). @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0075],ARef=[AI95-00205-01]} After a call is first queued, changes to the active priority of a task do not affect the priority of the call, unless the base priority of the task is set@Chg{New=[ while the task is blocked on an entry call],Old=[]}. When the base priority of a task is set (see @RefSecNum{Dynamic Priorities}), if the task is blocked on an entry call, and the call is queued, the priority of the call is updated to the new active priority of the calling task. This causes the call to be removed from and then reinserted in the queue at the new active priority. @begin{Reason} A task is blocked on an entry call if the entry call is simple, conditional, or timed. If the call came from the @nt{triggering_statement} of an @nt{asynchronous_select}, or a requeue thereof, then the task is not blocked on that call; such calls do not have their priority updated. Thus, there can exist many queued calls from a given task (caused by many nested ATC's), but a task can be blocked on only one call at a time. A previous version of Ada 9X required queue reordering in the @nt{asynchronous_select} case as well. If the call corresponds to a @lquotes@;synchronous@rquotes@; entry call, then the task is blocked while queued, and it makes good sense to move it up in the queue if its priority is raised. However, if the entry call is @lquotes@;asynchronous,@rquotes@; that is, it is due to an @nt{asynchronous_select} whose @nt{triggering_statement} is an entry call, then the task is not waiting for this entry call, so the placement of the entry call on the queue is irrelevant to the rate at which the task proceeds. Furthermore, when an entry is used for @nt{asynchronous_select}s, it is almost certain to be a @lquotes@;broadcast@rquotes@; entry or have only one caller at a time. For example, if the entry is used to notify tasks of a mode switch, then all tasks on the entry queue would be signaled when the mode changes. Similarly, if it is indicating some interrupting event such as a control-C, all tasks sensitive to the interrupt will want to be informed that the event occurred. Hence, the order on such a queue is essentially irrelevant. Given the above, it seems an unnecessary semantic and implementation complexity to specify that asynchronous queued calls are moved in response to dynamic priority changes. Furthermore, it is somewhat inconsistent, since the call was originally queued based on the active priority of the task, but dynamic priority changes are changing the base priority of the task, and only indirectly the active priority. We say explicitly that asynchronous queued calls are not affected by normal changes in active priority during the execution of an @nt{abortable_part}. Saying that, if a change in the base priority affects the active priority, then we do want the calls reordered, would be inconsistent. It would also require the implementation to maintain a readily accessible list of all queued calls which would not otherwise be necessary. Several rules were removed or simplified when we changed the rules so that calls due to @nt{asynchronous_select}s are never moved due to intervening changes in active priority, be they due to protected actions, some other priority inheritance, or changes in the base priority. @end{Reason} When more than one @nt{condition} of an @nt{entry_barrier} of a protected object becomes True, and more than one of the respective queues is nonempty, the call with the highest priority is selected. If more than one such call has the same priority, the call that is queued on the entry whose declaration is first in textual order in the @nt{protected_definition} is selected. For members of the same entry family, the one with the lower family index is selected. If the expiration time of two or more open @nt{delay_alternative}s is the same and no other @nt{accept_alternative}s are open, the @nt{sequence_of_statements} of the @nt{delay_alternative} that is first in textual order in the @nt{selective_accept} is executed. When more than one alternative of a @nt{selective_accept} is open and has queued calls, an alternative whose queue has the highest-priority call at its head is selected. If two or more open alternatives have equal-priority queued calls, then a call on the entry in the @nt{accept_alternative} that is first in textual order in the @nt{selective_accept} is selected. @end{itemize} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00256-01]} Implementations are allowed to define other queuing policies, but need not support more than one @Chg{Version=[2],New=[queuing],Old=[such]} policy per partition. @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0116],ARef=[AI95-00069-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00256-01]} @ChgAdded{Version=[1],Text=[This rule is really redundant, as @RefSecNum(Pragmas and Program Units) allows an implementation to limit the use of configuration pragmas to an empty environment. In that case, there would be no way to have multiple policies in a partition.@Chg{Version=[2],New=[], Old=[ In any case, the wording here really ought to be "...more than one queuing policy per partition.", since this part of the rule applies to all queuing policies, not just implementation-defined ones.]}]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[Implementations are allowed to defer the reordering of entry queues following a change of base priority of a task blocked on the entry call if it is not practical to reorder the queue immediately.]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Priority change is immediate, but the effect of the change on entry queues can be deferred. That is necessary in order to implement priority changes on top of a non-Ada kernel.]} @end{Reason} @begin{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[The reordering should occur as soon as the blocked task can itself perform the reinsertion into the entry queue.]} @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} The implementation should use names that end with @lquotes@;_Queuing@rquotes@; for implementation-defined queuing policies. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Names that end with @lquotes@;_Queuing@rquotes@; should be used for implementation-defined queuing policies.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0074],ARef=[AI95-00068-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the number of queuing policies defined.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0075],ARef=[AI95-00205-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected so that a call of Set_Priority in an abortable part does not change the priority of the triggering entry call.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[Added a permission to defer queue reordering when the base priority of a task is changed. This is a counterpart to stronger requirements on the implementation of priority change.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00256-01]} @ChgAdded{Version=[2],Text=[Clarified that an implementation need support only one queuing policy (of any kind, language-defined or otherwise) per partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[Fixed wording to make clear that @nt{pragma} never appears inside of a unit; rather it @lquotes@;applies to@rquotes the unit.]} @end{DiffWord95} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Dynamic Priorities} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes how the priority of an entity can be modified or queried at run time.]]} @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} is turned into two subclauses. This @Chg{Version=[3],New=[subclause],Old=[clause]} introduction is new.]} @end{DiffWord95} @LabeledAddedSubClause{Version=[2],Name=[Dynamic Priorities for Tasks]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes how the base priority of a task can be modified or queried at run time.] @end{Intro} @begin{StaticSem} @Leading@Keepnext@;The following language-defined library package exists: @begin{Example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[with] System; @key[with] Ada.Task_Identification; @RI{-- See @RefSecNum[The Package Task_Identification]} @key[package] Ada.Dynamic_Priorities @key[is]@ChildUnit{Parent=[Ada],Child=[Dynamic_Priorities]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Dynamic_Priorities);],Old=[]} @key[procedure] @AdaSubDefn{Set_Priority}(Priority : @key[in] System.Any_Priority; T : @key[in] Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task); @key[function] @AdaSubDefn{Get_Priority} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key[return] System.Any_Priority; @key[end] Ada.Dynamic_Priorities; @end{example} @end{StaticSem} @begin{RunTime} The procedure Set_Priority sets the base priority of the specified task to the specified Priority value. Set_Priority has no effect if the task is terminated. The function Get_Priority returns T's current base priority. @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Tasking_Error is raised if the task is terminated. @begin{Reason} There is no harm in setting the priority of a terminated task. A previous version of Ada 9X made this a run-time error. However, there is little difference between setting the priority of a terminated task, and setting the priority of a task that is about to terminate very soon; neither case should be an error. Furthermore, the run-time check is not necessarily feasible to implement on all systems, since priority changes might be deferred due to inter-processor communication overhead, so the error might not be detected until after Set_Priority has returned. However, we wish to allow implementations to avoid storing @lquotes@;extra@rquotes@; information about terminated tasks. Therefore, we make Get_Priority of a terminated task raise an exception; the implementation need not continue to store the priority of a task that has terminated. @end{Reason} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised by Set_Priority and Get_Priority if T is equal to Null_Task_Id. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00188-02]} @Chg{Version=[2],New=[On a system with a single processor, the setting of], Old=[Setting]} the @Chg{Version=[2],New=[],Old=[task's ]}base priority@Chg{Version=[2],New=[ of a task @i{T}],Old=[]} to the new value @Chg{Version=[2], New=[occurs immediately at the first point when @i{T} is outside the execution of],Old=[takes place as soon as is practical but not while the task is performing]} a protected action@Chg{Version=[2],New=[],Old=[. This setting occurs no later then the next abort completion point of the task T (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements})]}. @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00188-02]} @Chg{Version=[2],New=[The priority change is immediate if the target task is on a delay queue or a ready queue outside of a protected action. However, consider when],Old=[When]} Set_Priority is called by a task T1 to set the priority of T2, if T2 is blocked, waiting on an entry call queued on a protected object, the entry queue needs to be reordered. Since T1 might have a priority that is higher than the ceiling of the protected object, T1 cannot, in general, do the reordering. One way to implement this is to wake T2 up and have T2 do the work. This is similar to the disentangling of queues that needs to happen when a high-priority task aborts a lower-priority task, which might have a call queued on a protected object with a low ceiling.@Chg{Version=[2],New=[ We have an @ImplPermName in @RefSecNum{Entry Queuing Policies} to allow this implementation. We could have required an immediate priority change if on a ready queue during a protected action, but that would have required extra checks for ceiling violations to meet @BoundedName requirements of @RefSecNum{Priority Ceiling Locking} and potentially could cause a protected action to be abandoned in the middle (by raising Program_Error). That seems bad.],Old=[]} @end{ImplNote} @begin{Reason} @Leading@;A previous version of Ada 9X made it a run-time error for a high-priority task to set the priority of a lower-priority task that has a queued call on a protected object with a low ceiling. This was changed because: @begin{Itemize} The check was not feasible to implement on all systems, since priority changes might be deferred due to inter-processor communication overhead. The calling task would continue to execute without finding out whether the operation succeeded or not. The run-time check would tend to cause intermittent system failures @em how is the caller supposed to know whether the other task happens to have a queued call at any given time? Consider for example an interrupt that needs to trigger a priority change in some task. The interrupt handler could not safely call Set_Priority without knowing exactly what the other task is doing, or without severely restricting the ceilings used in the system. If the interrupt handler wants to hand the job off to a third task whose job is to call Set_Priority, this won't help, because one would normally want the third task to have high priority. @end{Itemize} @end{Reason} @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00327-01]} @ChgDeleted{Version=[2],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If a task is blocked on a protected entry call, and the call is queued, it is a bounded error to raise its base priority above the ceiling priority of the corresponding protected object. When an entry call is cancelled, it is a bounded error if the priority of the calling task is higher than the ceiling priority of the corresponding protected object. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} In either of these cases, either Program_Error is raised in the task that called the entry, or its priority is temporarily lowered, or both, or neither.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Note that the error is @lquotes@;blamed@rquotes@; on the task that did the entry call, not the task that called Set_Priority. This seems to make sense for the case of a task blocked on a call, since if the Set_Priority had happened a little bit sooner, before the task queued a call, the entry-calling task would get the error. In the other case, there is no reason not to raise the priority of a task that is executing in an @nt{abortable_part}, so long as its priority is lowered before it gets to the end and needs to cancel the call. The priority might need to be lowered to allow it to remove the call from the entry queue, in order to avoid violating the ceiling. This seems relatively harmless, since there is an error, and the task is about to start raising an exception anyway.]} @end{Ramification} @end{Bounded} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 11 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If any subprogram in this package is called with a parameter T that specifies a task object that no longer exists, the execution of the program is erroneous. @begin{Ramification} Note that this rule overrides the above rule saying that Program_Error is raised on Get_Priority of a terminated task. If the task object still exists, and the task is terminated, Get_Priority raises Program_Error. However, if the task object no longer exists, calling Get_Priority causes erroneous execution. @end{Ramification} @end{Erron} @begin{DocReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[On a multiprocessor, the implementation shall document any conditions that cause the completion of the setting of the priority of a task to be delayed later than what is specified for a single processor.]} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any conditions that cause the completion of the setting of the priority of a task to be delayed for a multiprocessor.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metric: @begin{Itemize} The execution time of a call to Set_Priority, for the nonpreempting case, in processor clock cycles. This is measured for a call that modifies the priority of a ready task that is not running (which cannot be the calling one), where the new base priority of the affected task is lower than the active priority of the calling task, and the affected task is not on any entry queue and is not executing a protected operation. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for Set_Priority.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00321-01]} Setting a task's base priority affects task dispatching. First, it can change the task's active priority. Second, under the @Chg{Version=[2], New=[FIFO_Within_Priorities],Old=[standard task dispatching]} policy it always causes the task to move to the tail of the ready queue corresponding to its active priority, even if the new base priority is unchanged. Under the priority queuing policy, setting a task's base priority has an effect on a queued entry call if the task is blocked waiting for the call. That is, setting the base priority of a task causes the priority of a queued entry call from that task to be updated and the call to be removed and then reinserted in the entry queue at the new priority (see @RefSecNum{Entry Queuing Policies}), unless the call originated from the @nt{triggering_statement} of an @nt{asynchronous_select}. The effect of two or more Set_Priority calls executed in parallel on the same task is defined as executing these calls in some serial order. @begin{TheProof} This follows from the general reentrancy requirements stated near the beginning of @RefSec{Predefined Language Environment}. @end{TheProof} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1]} The rule for when Tasking_Error is raised for Set_Priority or Get_Priority is different from the rule for when Tasking_Error is raised on an entry call (see @RefSecNum{Entry Calls}). In particular, @Chg{Version=[3],New=[],Old=[setting or ]}querying the priority of a completed or an abnormal task is allowed, so long as the task is not yet terminated@Chg{Version=[3],New=[, and setting the priority of a task is allowed for any task state (including for terminated tasks)],Old=[]}. Changing the priorities of a set of tasks can be performed by a series of calls to Set_Priority for each task separately. For this to work reliably, it should be done within a protected operation that has high enough ceiling priority to guarantee that the operation completes without being preempted by any of the affected tasks. @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00188-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @b[Amendment Correction:] Priority changes are now required to be done immediately so long as the target task is not on an entry queue.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Dynamic_Priorities is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This Ada 95 @Chg{Version=[3],New=[subclause], Old=[clause]} was @Chg{Version=[3],New=[moved down a level],Old=[turned into a subclause]}. The paragraph numbers are the same as those for @RefSecNum{Dynamic Priorities} in Ada 95.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00321-01]} @ChgAdded{Version=[2],Text=[There is no @lquotes@;standard@rquotes policy anymore, so that phrase was replaced by the name of a specific policy in the notes.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The bounded error for the priority of a task being higher than the ceiling of an object it is currently in was moved to @RefSecNum{Priority Ceiling Locking}, so that it applies no matter how the situation arises.]} @end{DiffWord95} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledAddedSubClause{Version=[2],Name=[Dynamic Priorities for Protected Objects]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies how the priority of a protected object can be modified or queried at run time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The following attribute is defined for @PrefixType{a @nt{prefix} P that denotes a protected object}:]} @begin(Description) @ChgAttribute{Version=[2],Kind=[AddedNormal],ChginAnnex=[T], Leading=<F>, Prefix=<P>, AttrName=<Priority>, ARef=[AI95-00327-01], Text=[@Chg{Version=[2],New=[Denotes a non-aliased component of the protected object P. This component is of type System.Any_Priority and its value is the priority of P. P'Priority denotes a variable if and only if P denotes a variable. A reference to this attribute shall appear only within the body of P.],Old=[]}]} @EndPrefixType{} @end{Description} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[The initial value of this attribute is the initial value of the priority of the protected object@Redundant[, and can be changed by an assignment].]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the locking policy Ceiling_Locking (see @RefSecNum{Priority Ceiling Locking}) is in effect@Chg{Version=[3],New=[,],Old=[]} then the ceiling priority of a protected object @i<P> is set to the value of @i<P>'Priority at the end of each protected action of @i<P>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00445-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[2],Text=[If the locking policy Ceiling_Locking is in effect, then for a protected object @i<P> with either an Attach_Handler or Interrupt_Handler @Chg{Version=[3],New=[aspect specified for],Old=[pragma applying to]} one of its procedures, a check is made that the value to be assigned to @i<P>'Priority is in the range System.Interrupt_Priority. If the check fails, Program_Error is raised.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @end{Runtime} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The implementation shall document the following metric:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[The difference in execution time of calls to the following procedures in protected object P:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<protected> P @key<is> @key<procedure> Do_Not_Set_Ceiling (Pr : System.Any_Priority); @key<procedure> Set_Ceiling (Pr : System.Any_Priority); @key<end> P;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<protected body> P @key<is> @key<procedure> Do_Not_Set_Ceiling (Pr : System.Any_Priority) @key<is> @key<begin> @key<null>; @key<end>; @key<procedure> Set_Ceiling (Pr : System.Any_Priority) @key<is> @key<begin> P'Priority := Pr; @key<end>; @key<end> P;]} @end{Example} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for setting the priority of a protected object.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[Since P'Priority is a normal variable, the value following an assignment to the attribute immediately reflects the new value even though its impact on the ceiling priority of P is postponed until completion of the protected action in which it is executed.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01],ARef=[AI95-00445-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The ability to dynamically change and query the priority of a protected object is new.]} @end{Extend95} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledClause{Preemptive Abort} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies requirements on the immediacy with which an aborted construct is completed.] @end{Intro} @begin{RunTime} On a system with a single processor, an aborted construct is completed immediately at the first point that is outside the execution of an abort-deferred operation. @end{RunTime} @begin{DocReq} On a multiprocessor, the implementation shall document any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[On a multiprocessor, any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[On a multiprocessor, any conditions that cause the completion of an aborted construct to be delayed later than what is specified for a single processor.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metrics: @begin{Itemize} The execution time, in processor clock cycles, that it takes for an @nt{abort_statement} to cause the completion of the aborted task. This is measured in a situation where a task T2 preempts task T1 and aborts T1. T1 does not have any finalization code. T2 shall verify that T1 has terminated, by means of the Terminated attribute. On a multiprocessor, an upper bound in seconds, on the time that the completion of an aborted task can be delayed beyond the point that it is required for a single processor. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An upper bound on the execution time of an @nt{asynchronous_select}, in processor clock cycles. This is measured between a point immediately before a task T1 executes a protected operation Pr.Set that makes the @nt{condition} of an @nt{entry_barrier} Pr.Wait @Chg{Version=[2], New=[True],Old=[true]}, and the point where task T2 resumes execution immediately after an entry call to Pr.Wait in an @nt{asynchronous_select}. T1 preempts T2 while T2 is executing the abortable part, and then blocks itself so that T2 can execute. The execution time of T1 is measured separately, and subtracted. An upper bound on the execution time of an @nt{asynchronous_select}, in the case that no asynchronous transfer of control takes place. This is measured between a point immediately before a task executes the @nt{asynchronous_select} with a nonnull abortable part, and the point where the task continues execution immediately after it. The execution time of the abortable part is subtracted. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for aborts.]}]} @end{Metrics} @begin{ImplAdvice} Even though the @nt{abort_statement} is included in the list of potentially blocking operations (see @RefSecNum{Protected Subprograms and Protected Actions}), it is recommended that this statement be implemented in a way that never requires the task executing the @nt{abort_statement} to block. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The @nt{abort_statement} should not require the task executing the statement to block.]}]} On a multi-processor, the delay associated with aborting a task on another processor should be bounded; the implementation should use periodic polling, if necessary, to achieve this. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[On a multi-processor, the delay associated with aborting a task on another processor should be bounded.]}]} @end{ImplAdvice} @begin{Notes} Abortion does not change the active or base priority of the aborted task. Abortion cannot be more immediate than is allowed by the rules for deferral of abortion during finalization and in protected actions. @end{Notes} @LabeledClause{Tasking Restrictions} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines restrictions that can be used with a pragma Restrictions (see @RefSecNum{Pragma Restrictions and Pragma Profile}) to facilitate the construction of highly efficient tasking run-time systems.] @end{Intro} @begin{StaticSem} @Leading@;The following @SynI{restriction_}@nt{identifier}s are language defined: @begin{Description} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0013-1],ARef=[AI05-0216-1]} @Defn2{Term=[restrictions],Sec=(No_Task_Hierarchy)}@Chg{Version=[3],New=[@Defn{No_Task_Hierarchy restriction}], Old=[]}No_Task_Hierarchy @\@Chg{Version=[3], New=[No task depends on a master other than the library-level master],Old=[All (nonenvironment) tasks depend directly on the environment task of the partition]}. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0216-1]} @ChgAdded{Version=[3],Text=[This is equivalent to saying @ldquote@;no task depends on a master other than the master that is the execution of the body of the environment task of the partition@rdquote, but it is much easier to understand. This is a post-compilation check, which can be checked at compile-time.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[This disallows any function returning an object with a task part or coextension, even if called at the library level, as such a task would temporarily depend on a nested master (the master of the return statement), which is disallowed by this restriction.]} @end{Ramification} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00360-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0013-1]} @Defn2{Term=[restrictions],Sec=(No_Nested_Finalization)}@Chg{Version=[3],New=[@Defn{No_Nested_Finalization restriction}], Old=[]}No_Nested_Finalization @\Objects @Chg{Version=[2],New=[of a type that needs finalization (see @RefSecNum{Assignment and Finalization})],Old=[with controlled@Chg{New=[, protected, or task],Old=[]} parts]} @Chg{Version=[3],New=[are],Old=[and access types that designate @Chg{Version=[2],New=[a type that needs finalization],Old=[such objects@Chg{New=[,],Old=[]}]} shall be]} declared only at library level.@Chg{Version=[3],New=[ If an access type does not have library-level accessibility, then there are no @nt{allocator}s of the type where the type determined by the @nt{subtype_mark} of the @nt{subtype_indication} or @nt{qualified_expression} needs finalization.],Old=[]} @begin{Ramification} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgNote{This is no longer true.} @ChgDeleted{Version=[1],Text=[Note that protected types with entries and interrupt-handling protected types have nontrivial finalization actions. However, this restriction does not restrict those things.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[The second sentence prevents the declaration of objects of access types which would require nested finalization. It also prevents the declarations of coextensions that need finalization in a nested scope. The latter cannot be done by preventing the declaration of the objects, as it is not necessarily known if the coextension type needs finalization (it could be a limited view).]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0211-1]} @Defn2{Term=[restrictions],Sec=(No_Abort_Statements)}@Chg{Version=[3],New=[@Defn{No_Abort_Statements restriction}], Old=[]}No_Abort_Statements @\There are no @nt{abort_statement}s, and there @Chg{Version=[3],New=[is no use of a @nt{name} denoting],Old=[are no calls on]} Task_Identification.Abort_Task. @Defn2{Term=[restrictions],Sec=(No_Terminate_Alternatives)}@Chg{Version=[3],New=[@Defn{No_Terminate_Alternatives restriction}], Old=[]}No_Terminate_Alternatives @\There are no @nt{selective_accept}s with @nt{terminate_alternative}s. @Defn2{Term=[restrictions],Sec=(No_Task_Allocators)}@Chg{Version=[3],New=[@Defn{No_Task_Allocators restriction}], Old=[]}No_Task_Allocators @\There are no @nt{allocator}s for task types or types containing task subcomponents. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0224-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[In the case of an initialized @nt{allocator} of an access type whose designated type is class-wide and limited, a check is made that the specific type of the allocated object has no task subcomponents. Program_Error is raised if this check fails.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @Comment{We don't index this "check" as it doesn't have a name.} @Defn2{Term=[restrictions],Sec=(No_Implicit_Heap_Allocations)}@Chg{Version=[3],New=[@Defn{No_Implicit_Heap_Allocations restriction}], Old=[]}No_Implicit_Heap_Allocations @\There are no operations that implicitly require heap storage allocation to be performed by the implementation. The operations that implicitly require heap storage allocation are implementation defined. @ImplDef{Any operations that implicitly require heap storage allocation.} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00327-01]} No_Dynamic_Priorities @\There are no semantic dependences on the package Dynamic_Priorities@Chg{Version=[2],New=[, and no occurrences of the attribute Priority],Old=[]}. @Defn2{Term=[restrictions],Sec=(No_Dynamic_Priorities)}@Chg{Version=[3],New=[@Defn{No_Dynamic_Priorities restriction}], Old=[]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0013-1],ARef=[AI05-0211-1]} @Chg{Version=[2],New=[@Defn2{Term=[restrictions], Sec=(No_Dynamic_Attachment)}@Chg{Version=[3],New=[@Defn{No_Dynamic_Attachment restriction}], Old=[]}No_Dynamic_Attachment], Old=[@Defn2{Term=[restrictions],Sec=(No_Asynchronous_Control)}No_Asynchronous_Control]} @\There @Chg{Version=[2],New=[is no @Chg{Version=[3],New=[use of a @nt{name} denoting],Old=[call to]} any of the operations defined in package Interrupts (Is_Reserved, Is_Attached, Current_Handler, Attach_Handler, Exchange_Handler, Detach_Handler, and Reference).], Old=[are no semantic dependences on the package Asynchronous_Task_Control.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[This includes 'Access and 'Address of any of these operations, as well as inherited versions of these operations.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0013-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Local_Protected_Objects)}@Chg{Version=[3],New=[@Defn{No_Local_Protected_Objects restriction}], Old=[]}No_Local_Protected_Objects @\Protected objects @Chg{Version=[2],New=[are],Old=[shall be]} declared only at library level.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0013-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Local_Timing_Events)}@Chg{Version=[3],New=[@Defn{No_Local_Timing_Events restriction}], Old=[]}No_Local_Timing_Events @\Timing_Events @Chg{Version=[2],New=[are],Old=[shall be]} declared only at library level.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Protected_Type_Allocators)}@Chg{Version=[3],New=[@Defn{No_Protected_Type_Allocators restriction}], Old=[]}No_Protected_Type_Allocators @\There are no @nt{allocator}s for protected types or types containing protected type subcomponents.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0224-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[In the case of an initialized @nt{allocator} of an access type whose designated type is class-wide and limited, a check is made that the specific type of the allocated object has no protected subcomponents. Program_Error is raised if this check fails.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @Comment{We don't index this "check" as it doesn't have a name.} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0211-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Relative_Delay)}@Chg{Version=[3],New=[@Defn{No_Relative_Delay restriction}], Old=[]}No_Relative_Delay @\There are no @nt{delay_relative_statement}s@Chg{Version=[3],New=[, and there is no use of a @nt{name} that denotes the Timing_Events.Set_Handler subprogram that has a Time_Span parameter],Old=[]}.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@Comment{Number changed due to insertion above} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Requeue_Statements)}@Chg{Version=[3],New=[@Defn{No_Requeue_Statements restriction}], Old=[]}No_Requeue_Statements @\There are no @nt{requeue_statement}s.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgRef{Version=[3],Kind=[RevisedAdded]}@Comment{Number changed due to insertion above} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Select_Statements)}@Chg{Version=[3],New=[@Defn{No_Select_Statements restriction}], Old=[]}No_Select_Statements @\There are no @nt{select_statement}s.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0211-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Specific_Termination_Handlers)}@Chg{Version=[3],New=[@Defn{No_Specific_Termination_Handlers restriction}], Old=[]}No_Specific_Termination_Handlers @\There @Chg{Version=[3],New=[is no use of a @nt{name} denoting],Old=[are no calls to]} the Set_Specific_Handler and Specific_Handler subprograms in Task_Termination.]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0013-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(Simple_Barriers)}@Chg{Version=[3],New=[@Defn{Simple_Barriers restriction}], Old=[]}Simple_Barriers @\The Boolean expression in @Chg{Version=[3],New=[each],Old=[an]} entry barrier @Chg{Version=[3],New=[is],Old=[shall be]} either a static @Chg{Version=[3],New=[],Old=[Boolean ]}expression or a @Chg{Version=[3],New=[name that statically denotes a],Old=[Boolean]} component of the enclosing protected object.]} @end{Description} @Leading@;The following @SynI{restriction_parameter_}@nt{identifier}s are language defined: @begin{Description} @Defn2{Term=[restrictions],Sec=(Max_Select_Alternatives)}@Chg{Version=[3],New=[@Defn{Max_Select_Alternatives restriction}], Old=[]}Max_Select_Alternatives @\Specifies the maximum number of alternatives in a @nt{selective_accept}. @Defn2{Term=[restrictions],Sec=(Max_Task_Entries)}@Chg{Version=[3],New=[@Defn{Max_Task_Entries restriction}], Old=[]}Max_Task_Entries @\Specifies the maximum number of entries per task. The bounds of every entry family of a task unit shall be static, or shall be defined by a discriminant of a subtype whose corresponding bound is static. @Redundant[A value of zero indicates that no rendezvous are possible.] Max_Protected_Entries @\Specifies the maximum number of entries per protected type. The bounds of every entry family of a protected unit shall be static, or shall be defined by a discriminant of a subtype whose corresponding bound is static. @Defn2{Term=[restrictions],Sec=(Max_Protected_Entries)}@Chg{Version=[3],New=[@Defn{Max_Protected_Entries restriction}], Old=[]} @end{Description} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0076],ARef=[AI95-00067-01]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The following @SynI{restriction_}@nt{identifier} is language defined:]}@Comment{Use ChgAdded so we get conditional Leading.}@Chg{Version=[1],New=[],Old=[If the following restrictions are violated, the behavior is implementation defined. @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} If an implementation chooses to detect such a violation, Storage_Error should be raised.]} @begin{Description} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions],Sec=(No_Task_Termination)}@Chg{Version=[3],New=[@Defn{No_Task_Termination restriction}], Old=[]}No_Task_Termination @\All tasks are nonterminating. It is implementation-defined what happens if a task attempts to terminate. If there is a fall-back handler (see C.7.3) set for the partition it should be called when the first task attempts to terminate.]} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[When restriction No_Task_Termination applies to a partition, what happens when a task terminates.]}]} @end{Description} @Leading@;The following @SynI{restriction_parameter_}@nt{identifier}s are language defined: @begin{Description} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[restrictions],Sec=(Max_Storage_At_Blocking)}@Chg{Version=[3],New=[@Defn{Max_Storage_At_Blocking restriction}], Old=[]}Max_Storage_At_Blocking @\Specifies the maximum portion @redundant[(in storage elements)] of a task's Storage_Size that can be retained by a blocked task@Chg{New=[. If an implementation chooses to detect a violation of this restriction, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Storage_At_Blocking is violated.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[restrictions],Sec=(Max_Asynchronous_Select_Nesting)}@Chg{Version=[3],New=[@Defn{Max_Asynchronous_Select_Nesting restriction}], Old=[]}Max_Asynchronous_Select_Nesting @\Specifies the maximum dynamic nesting level of @nt{asynchronous_select}s. A value of zero prevents the use of any @nt{asynchronous_@!select}@Chg{New=[ and, if a program contains an @nt{asynchronous_@!select}, it is illegal. @ChgNote{Part of the previous rule is redundant, but it is a different part [all of it for Old; from "prevents" to "and," for New] for each. So we omit it.} If an implementation chooses to detect a violation of this restriction for values other than zero, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Asynchronous_Select_Nesting is violated.]}]} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0076],ARef=[AI95-00067-01]} @Defn2{Term=[restrictions],Sec=(Max_Tasks)}@Chg{Version=[3],New=[@Defn{Max_Tasks restriction}], Old=[]}Max_Tasks @\Specifies the maximum number of task creations that may be executed over the lifetime of a partition, not counting the creation of the environment task@Chg{New=[. A value of zero prevents any task creation and, if a program contains a task creation, it is illegal. If an implementation chooses to detect a violation of this restriction, Storage_Error should be raised; @IndexCheck{Storage_Check} @Defn2{Term=[Storage_Error],Sec=(raised by failure of run-time check)} otherwise, the behavior is implementation defined],Old=[]}. @begin{Ramification} Note that this is not a limit on the number of tasks active at a given time; it is a limit on the total number of task creations that occur. @end{Ramification} @begin{ImplNote} We envision an implementation approach that places TCBs or pointers to them in a fixed-size table, and never reuses table elements. @end{ImplNote} @ChgImplDef{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The behavior when restriction Max_Tasks is violated.]}]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(Max_Entry_Queue_Length)}@Chg{Version=[3],New=[@Defn{Max_Entry_Queue_Length restriction}], Old=[]}Max_Entry_Queue_Length @\Max_Entry_Queue_Length defines the maximum number of calls that are queued on an entry. Violation of this restriction results in the raising of Program_Error at the point of the call or requeue.@Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)}]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Standard_Allocators_After_Elaboration)}@Defn{No_Standard_Allocators_After_Elaboration restriction} No_Standard_Allocators_After_Elaboration @\Specifies that an @nt{allocator} using a standard storage pool (see @RefSecNum{Storage Management}) shall not occur within a parameterless library subprogram, nor within the @nt{handled_sequence_of_statements} of a task body. For the purposes of this rule, an @nt{allocator} of a type derived from a formal access type does not use a standard storage pool.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0189-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],NoPrefix=[T],Text=[At run time, Storage_Error is raised if an @nt{allocator} using a standard storage pool is evaluated after the elaboration of the @nt{library_item}s of the partition has completed.@Defn2{Term=[Storage_Error], Sec=(raised by failure of run-time check)}]} @end{Description} It is implementation defined whether the use of pragma Restrictions results in a reduction in executable program size, storage requirements, or execution time. If possible, the implementation should provide quantitative descriptions of such effects for each restriction. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[@Chg{Version=[2], New=[Whether the use of],Old=[Implementation-defined aspects of]} pragma Restrictions@Chg{Version=[2],New=[ results in a reduction in program code or data size or execution time],Old=[]}.]} @end{RunTime} @begin{ImplAdvice} When feasible, the implementation should take advantage of the specified restrictions to produce a more efficient implementation. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When feasible, specified restrictions should be used to produce a more efficient implementation.]}]} @end{ImplAdvice} @begin{Notes} The above Storage_Checks can be suppressed with pragma Suppress. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00360-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] The No_Nested_Finalization is now defined in terms of types that need finalization. These types include a variety of language-defined types that @i<might> be implemented with a controlled type. If the restriction No_Nested_Finalization (see @RefSecNum{Tasking Restrictions}) applies to the partition, and one of these language-defined types does not have a controlled part, it will not be allowed in local objects in Ada 2005 whereas it would be allowed in original Ada 95. Such code is not portable, as other Ada compilers may have had a controlled part, and thus would be illegal under the restriction.]} @end{Incompatible95} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01],ARef=[AI95-00305-01],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Restrictions No_Dynamic_Attachment, No_Local_Protected_Objects, No_Protected_Type_Allocators, No_Local_Timing_Events, No_Relative_Delay, No_Requeue_Statement, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Termination, Max_Entry_Queue_Length, and Simple_Barriers are newly added to Ada.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that No_Nested_Finalization covered task and protected parts as well.]} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0076],ARef=[AI95-00067-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Changed the description of Max_Tasks and Max_Asynchronous_Select_Nested to eliminate conflicts with the High Integrity Annex (see @RefSecNum{High Integrity Restrictions}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00327-01]} @ChgAdded{Version=[2],Text=[Added using of the new Priority attribute to the restriction No_Dynamic_Priorities.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Restriction No_Asynchronous_Control is now obsolescent.]} @end{DiffWord95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Changed so that coextensions of types that require nested finalization are also prohibited; this is done by prohibiting @nt{allocator}s rather than objects of specific access types. It seems unlikely that any program depending on this restriction would violate it in this blatant manner, so it is expected that very few programs will be affected by this change.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0211-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> The restriction No_Relative_Delay was changed to include the Timing_Events routine that uses a relative delay. This means that a program that uses that routine and this restriction will now be rejected. However, such a program violates the spirit and intent of the restriction and as such the program should never have been allowed. Moreover, it is unlikely that any program depending on this restriction would violate it in such an obvious manner, so it is expected that very few programs will be affected by this change.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0211-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> A number of restrictions were changed from "no calls" on some subprogram to "no use of a @nt{name} that denotes" that subprogram. This closes a hole where renames, uses as the prefix of 'Access, and the like, would not be rejected by the restriction, possibly allowing backdoor access to the prohibited subprogram. A program that uses one of these restrictions and using such backdoor access will now be rejected; however, it is extremely unlikely that any program that relies on these restrictions would also use an end-run around the restriction, so it is expected that very few programs will be affected by this change.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Restriction No_Standard_Allocators_After_Elaboration is newly added to Ada.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0013-1],ARef=[AI05-0216-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Improved the wording of various restrictions to make it clearer that they prohibit things that would otherwise be legal, and to word them as definitions, not @LegalityTitle;.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0192-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Added wording to explain how No_Task_Allocators and No_Protected_Type_Allocators are checked for class-wide types. This might be an extension if the compiler assumed the worst in the past (it is now a runtime check).]} @end{DiffWord2005} @LabeledClause{Monotonic Time} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies a high-resolution, monotonic clock package.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{example} @key[package] Ada.Real_Time @key[is]@ChildUnit{Parent=[Ada],Child=[Real_Time]} @key[type] @AdaTypeDefn{Time} @key[is] @key[private]; @AdaObjDefn{Time_First} : @key[constant] Time; @AdaObjDefn{Time_Last} : @key[constant] Time; @AdaObjDefn{Time_Unit} : @key[constant] := @RI{implementation-defined-real-number}; @key[type] @AdaTypeDefn{Time_Span} @key[is] @key[private]; @AdaObjDefn{Time_Span_First} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Last} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Zero} : @key[constant] Time_Span; @AdaObjDefn{Time_Span_Unit} : @key[constant] Time_Span; @AdaObjDefn{Tick} : @key[constant] Time_Span; @key[function] @AdaSubDefn{Clock} @key[return] Time; @key[function] "+" (Left : Time; Right : Time_Span) @key[return] Time; @key[function] "+" (Left : Time_Span; Right : Time) @key[return] Time; @key[function] "-" (Left : Time; Right : Time_Span) @key[return] Time; @key[function] "-" (Left : Time; Right : Time) @key[return] Time_Span; @key[function] "<" (Left, Right : Time) @key[return] Boolean; @key[function] "<="(Left, Right : Time) @key[return] Boolean; @key[function] ">" (Left, Right : Time) @key[return] Boolean; @key[function] ">="(Left, Right : Time) @key[return] Boolean; @key[function] "+" (Left, Right : Time_Span) @key[return] Time_Span; @key[function] "-" (Left, Right : Time_Span) @key[return] Time_Span; @key[function] "-" (Right : Time_Span) @key[return] Time_Span; @key[function] "*" (Left : Time_Span; Right : Integer) @key{return} Time_Span; @key[function] "*" (Left : Integer; Right : Time_Span) @key{return} Time_Span; @key[function] "/" (Left, Right : Time_Span) @key[return] Integer; @key[function] "/" (Left : Time_Span; Right : Integer) @key[return] Time_Span; @key[function] "@key[abs]"(Right : Time_Span) @key[return] Time_Span; @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[function] "<" (Left, Right : Time_Span) @key[return] Boolean; @key[function] "<="(Left, Right : Time_Span) @key[return] Boolean; @key[function] ">" (Left, Right : Time_Span) @key[return] Boolean; @key[function] ">="(Left, Right : Time_Span) @key[return] Boolean; @key[function] @AdaSubDefn{To_Duration} (TS : Time_Span) @key[return] Duration; @key[function] @AdaSubDefn{To_Time_Span} (D : Duration) @key[return] Time_Span; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00386-01]} @key[function] @AdaSubDefn{Nanoseconds} (NS : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Microseconds} (US : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Milliseconds} (MS : Integer) @key{return} Time_Span;@Chg{Version=[2],New=[ @key[function] @AdaSubDefn{Seconds} (S : Integer) @key{return} Time_Span; @key[function] @AdaSubDefn{Minutes} (M : Integer) @key{return} Time_Span;],Old=[]} @key[type] @AdaTypeDefn{Seconds_Count} @key[is] @key[range] @RI{implementation-defined}; @key{procedure} @AdaSubDefn{Split}(T : @key{in} Time; SC : @key{out} Seconds_Count; TS : @key{out} Time_Span); @key{function} @AdaSubDefn{Time_Of}(SC : Seconds_Count; TS : Time_Span) @key{return} Time; @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Real_Time; @end{example} @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of package Real_Time.]}]} @Defn{real time} In this Annex, @i{real time} is defined to be the physical time as observed in the external environment. The type Time is a @i{time type} as defined by @RefSecNum{Delay Statements, Duration, and Time}; @Redundant[values of this type may be used in a @nt{delay_until_statement}.] Values of this type represent segments of an ideal time line. The set of values of the type Time corresponds one-to-one with an implementation-defined range of mathematical integers. @begin{Discussion} Informally, real time is defined to be the International Atomic Time (TAI) which is monotonic and nondecreasing. We use it here for the purpose of discussing rate of change and monotonic behavior only. It does not imply anything about the absolute value of Real_Time.Clock, or about Real_Time.Time being synchronized with TAI. It is also used for real time in the metrics, for comparison purposes. @end{Discussion} @begin{ImplNote} The specification of TAI as @lquotes@;real time@rquotes@; does not preclude the use of a simulated TAI clock for simulated execution environments. @end{ImplNote} @Defn{epoch} @PDefn{unspecified} The Time value I represents the half-open real time interval that starts with E+I*Time_Unit and is limited by E+(I+1)*Time_Unit, where Time_Unit is an implementation-defined real number and E is an unspecified origin point, the @i{epoch}, that is the same for all values of the type Time. It is not specified by the language whether the time values are synchronized with any standard time reference. @Redundant[For example, E can correspond to the time of system initialization or it can correspond to the epoch of some time standard.] @begin{Discussion} E itself does not have to be a proper time value. This half-open interval I consists of all real numbers R such that E+I*Time_Unit <= R < E+(I+1)*Time_Unit. @end{Discussion} Values of the type Time_Span represent length of real time duration. The set of values of this type corresponds one-to-one with an implementation-defined range of mathematical integers. The Time_Span value corresponding to the integer I represents the real-time duration I*Time_Unit. @begin{Reason} The purpose of this type is similar to Standard.Duration; the idea is to have a type with a higher resolution. @end{Reason} @begin{Discussion} We looked at many possible names for this type: Real_Time.Duration, Fine_Duration, Interval, Time_Interval_Length, Time_Measure, and more. Each of these names had some problems, and we've finally settled for Time_Span. @end{Discussion} Time_First and Time_Last are the smallest and largest values of the Time type, respectively. Similarly, Time_Span_First and Time_Span_Last are the smallest and largest values of the Time_Span type, respectively. A value of type Seconds_Count represents an elapsed time, measured in seconds, since the epoch. @end{StaticSem} @begin{RunTime} Time_Unit is the smallest amount of real time representable by the Time type; it is expressed in seconds. Time_Span_Unit is the difference between two successive values of the Time type. It is also the smallest positive value of type Time_Span. Time_Unit and Time_Span_Unit represent the same real time duration. @Defn{clock tick} A @i{clock tick} is a real time interval during which the clock value (as observed by calling the Clock function) remains constant. Tick is the average length of such intervals. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00432-01]} The function To_Duration converts the value TS to a value of type Duration. Similarly, the function To_Time_Span converts the value D to a value of type Time_Span. For @Chg{Version=[2],New=[To_Duration], Old=[both operations]}, the result is rounded to the nearest @Chg{Version=[2],New=[value of type Duration], Old=[exactly representable value]} (away from zero if exactly halfway between two @Chg{Version=[2],New=[], Old=[exactly representable ]}values).@Chg{Version=[2],New=[ If the result is outside the range of Duration, Constraint_Error is raised. For To_Time_Span, the value of D is first rounded to the nearest integral multiple of Time_Unit, away from zero if exactly halfway between two multiples. If the rounded value is outside the range of Time_Span, Constraint_Error is raised. Otherwise, the value is converted to the type Time_Span.],Old=[]} To_Duration(Time_Span_Zero) returns 0.0, and To_Time_Span(0.0) returns Time_Span_Zero. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00386-01],ARef=[AI95-00432-01]} The functions Nanoseconds, Microseconds, @Chg{Version=[2],New=[], Old=[and ]}Milliseconds@Chg{Version=[2],New=[, Seconds, and Minutes],Old=[]} convert the input parameter to a value of the type Time_Span. NS, US,@Chg{Version=[2],New=[],Old=[ and]} MS@Chg{Version=[2],New=[, S, and M],Old=[]} are interpreted as a number of nanoseconds, microseconds,@Chg{Version=[2],New=[],Old=[ and]} milliseconds@Chg{Version=[2],New=[, seconds, and minutes],Old=[]} respectively.@Chg{Version=[2],New=[ The input parameter is first converted to seconds and rounded to the nearest integral multiple of Time_Unit, ], Old=[The result is rounded to the nearest exactly representable value (]}away from zero if exactly halfway between two @Chg{Version=[2],New=[multiples. If the rounded value is outside the range of Time_Span, Constraint_Error is raised. Otherwise, the rounded value is converted to the type Time_Span], Old=[exactly representable values)]}. @begin{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00432-01]} @ChgDeleted{Version=[2],Text=[The above does not imply that the Time_Span type will have to accommodate Integer'Last of milliseconds; Constraint_Error is allowed to be raised.]} @end{Discussion} The effects of the operators on Time and Time_Span are as for the operators defined for integer types. @begin{ImplNote} Though time values are modeled by integers, the types Time and Time_Span need not be implemented as integers. @end{ImplNote} The function Clock returns the amount of time since the epoch. The effects of the Split and Time_Of operations are defined as follows, treating values of type Time, Time_Span, and Seconds_Count as mathematical integers. The effect of Split(T,SC,TS) is to set SC and TS to values such that T*Time_Unit = SC*1.0 + TS*Time_Unit, and 0.0 <= TS*Time_Unit < 1.0. The value returned by Time_Of(SC,TS) is the value T such that T*Time_Unit = SC*1.0 + TS*Time_Unit. @end{RunTime} @begin{ImplReq} The range of Time values shall be sufficient to uniquely represent the range of real times from program start-up to 50 years later. Tick shall be no greater than 1 millisecond. Time_Unit shall be less than or equal to 20 microseconds. @begin{ImplNote} The required range and accuracy of Time are such that 32-bits worth of seconds and 32-bits worth of ticks in a second could be used as the representation. @end{ImplNote} Time_Span_First shall be no greater than @en@;3600 seconds, and Time_Span_Last shall be no less than 3600 seconds. @begin{Reason} This is equivalent to @PorM one hour and there is still room for a two-microsecond resolution. @end{Reason} @Defn{clock jump} A @i{clock jump} is the difference between two successive distinct values of the clock (as observed by calling the Clock function). There shall be no backward clock jumps. @end{ImplReq} @begin{DocReq} The implementation shall document the values of Time_First, Time_Last, Time_Span_@!First, Time_Span_@!Last, Time_Span_@!Unit, and Tick. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values of Time_First, Time_Last, Time_Span_@!First, Time_Span_@!Last, Time_Span_@!Unit, and Tick for package Real_Time.]}]} The implementation shall document the properties of the underlying time base used for the clock and for type Time, such as the range of values supported and any relevant aspects of the underlying hardware or operating system facilities used. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The properties of the underlying time base used in package Real_Time.]}]} @begin{Discussion} If there is an underlying operating system, this might include information about which system call is used to implement the clock. Otherwise, it might include information about which hardware clock is used. @end{Discussion} The implementation shall document whether or not there is any synchronization with external time references, and if such synchronization exists, the sources of synchronization information, the frequency of synchronization, and the synchronization method applied. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any synchronization of package Real_Time with external time references.]}]} @ChgRef{Version=[1],Kind=[Revised]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The implementation shall document any aspects of the @Chg{New=[], Old=[the]} @chgnote{Correct typo as noted at Potsdam ARG meeting} external environment that could interfere with the clock behavior as defined in this @Chg{Version=[3],New=[subclause],Old=[clause]}. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Any aspects of the external environment that could interfere with package Real_Time.]}]} @begin{Discussion} For example, the implementation is allowed to rely on the time services of an underlying operating system, and this operating system clock can implement time zones or allow the clock to be reset by an operator. This dependence has to be documented. @end{Discussion} @end{DocReq} @begin{Metrics} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} For the purpose of the metrics defined in this @Chg{Version=[3],New=[subclause],Old=[clause]}, real time is defined to be the International Atomic Time (TAI). @Leading@;The implementation shall document the following metrics: @begin{Itemize} An upper bound on the real-time duration of a clock tick. This is a value D such that if t1 and t2 are any real times such that t1 < t2 and Clock@-{t1} = Clock@-{t2} then t2 @en@; t1 <= D. An upper bound on the size of a clock jump. @Defn{drift rate} An upper bound on the @i{drift rate} of Clock with respect to real time. This is a real number D such that @begin{display} E*(1@en@;D) <= (Clock@-{t+E} @en@; Clock@-{t}) <= E*(1+D) provided that: Clock@-{t} + E*(1+D) <= Time_Last. @end{display} where Clock@-{t} is the value of Clock at time t, and E is a real time duration not less than 24 hours. The value of E used for this metric shall be reported. @begin{Reason} This metric is intended to provide a measurement of the long term (cumulative) deviation; therefore, 24 hours is the lower bound on the measurement period. On some implementations, this is also the maximum period, since the language does not require that the range of the type Duration be more than 24 hours. On those implementations that support longer-range Duration, longer measurements should be performed. @end{Reason} An upper bound on the execution time of a call to the Clock function, in processor clock cycles. Upper bounds on the execution times of the operators of the types Time and Time_Span, in processor clock cycles. @begin{ImplNote} A fast implementation of the Clock function involves repeated reading until you get the same value twice. It is highly improbable that more than three reads will be necessary. Arithmetic on time values should not be significantly slower than 64-bit arithmetic in the underlying machine instruction set. @end{ImplNote} @end{Itemize} @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The metrics for package Real_Time.]}]} @end{Metrics} @begin{ImplPerm} Implementations targeted to machines with word size smaller than 32 bits need not support the full range and granularity of the Time and Time_Span types. @begin{Discussion} These requirements are based on machines with a word size of 32 bits. Since the range and granularity are implementation defined, the supported values need to be documented. @end{Discussion} @end{ImplPerm} @begin{ImplAdvice} When appropriate, implementations should provide configuration mechanisms to change the value of Tick. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[When appropriate, mechanisms to change the value of Tick should be provided.]}]} @begin{Reason} This is often needed when the compilation system was originally targeted to a particular processor with a particular interval timer, but the customer uses the same processor with a different interval timer. @end{Reason} @begin{Discussion} Tick is a deferred constant and not a named number specifically for this purpose. @end{Discussion} @begin{ImplNote} This can be achieved either by pre-run-time configuration tools, or by having Tick be initialized (in the package private part) by a function call residing in a board specific module. @end{ImplNote} It is recommended that Calendar.Clock and Real_Time.Clock be implemented as transformations of the same time base. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Calendar.Clock and Real_Time.Clock should be transformations of the same time base.]}]} It is recommended that the @lquotes@;best@rquotes@; time base which exists in the underlying system be available to the application through Clock. @lquotes@;Best@rquotes@; may mean highest accuracy or largest range. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The @lquotes@;best@rquotes@; time base which exists in the underlying system should be available to the application through Real_Time.Clock.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} The rules in this @Chg{Version=[3],New=[subclause],Old=[clause]} do not imply that the implementation can protect the user from operator or installation errors which could result in the clock being set incorrectly. Time_Unit is the granularity of the Time type. In contrast, Tick represents the granularity of Real_Time.Clock. There is no requirement that these be the same. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00386-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} Functions Seconds and Minutes are @Chg{Version=[3],New=[],Old=[newly ]}added to Real_Time. If Real_Time is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Seconds or Minutes is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00432-01]} @ChgAdded{Version=[2],Text=[Added wording explaining how and when many of these functions can raise Constraint_Error. While there always was an intent to raise Constraint_Error if the values did not fit, there never was any wording to that effect, and since Time_Span was a private type, the normal numeric type rules do not apply to it.]} @end{DiffWord95} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Delay Accuracy} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies performance requirements for the @nt{delay_statement}. The rules apply both to @nt{delay_@!relative_@!statement} and to @nt{delay_@!until_@!statement}. Similarly, they apply equally to a simple @nt{delay_@!statement} and to one which appears in a @nt{delay_@!alternative}.] @end{Intro} @begin{RunTime} @Leading@;The effect of the @nt{delay_statement} for Real_Time.Time is defined in terms of Real_Time.Clock: @begin{itemize} If C@-{1} is a value of Clock read before a task executes a @nt{delay_relative_statement} with duration D, and C@-{2} is a value of Clock read after the task resumes execution following that @nt{delay_statement}, then C@-{2} @en@; C@-{1} >= D. If C is a value of Clock read after a task resumes execution following a @nt{delay_until_statement} with Real_Time.Time value T, then C >= T. @end{itemize} @PDefn2{Term=[potentially blocking operation],Sec=(delay_statement)} @PDefn2{Term=[blocking, potentially],Sec=(delay_statement)} A simple @nt{delay_statement} with a negative or zero value for the expiration time does not cause the calling task to be blocked; it is nevertheless a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} When a @nt{delay_statement} appears in a @nt{delay_alternative} of a @nt{timed_entry_call} the selection of the entry call is attempted, regardless of the specified expiration time. When a @nt{delay_statement} appears in a @Chg{Version=[3],New=[@nt{select_alternative}],Old=[@ntf{selective_accept_alternative}]}, and a call is queued on one of the open entries, the selection of that entry call proceeds, regardless of the value of the delay expression. @begin{Ramification} The effect of these requirements is that one has to always attempt a rendezvous, regardless of the value of the delay expression. This can be tested by issuing a @nt{timed_entry_call} with an expiration time of zero, to an open entry. @end{Ramification} @end{RunTime} @begin{DocReq} The implementation shall document the minimum value of the delay expression of a @nt{delay_relative_statement} that causes the task to actually be blocked. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The minimum value of the delay expression of a @nt{delay_relative_statement} that causes a task to actually be blocked.]}]} The implementation shall document the minimum difference between the value of the delay expression of a @nt{delay_until_statement} and the value of Real_Time.Clock, that causes the task to actually be blocked. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of @nt{delay_statement}s.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The minimum difference between the value of the delay expression of a @nt{delay_until_statement} and the value of Real_Time.Clock, that causes the task to actually be blocked.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metrics: @begin{Itemize} An upper bound on the execution time, in processor clock cycles, of a @nt{delay_relative_statement} whose requested value of the delay expression is less than or equal to zero. An upper bound on the execution time, in processor clock cycles, of a @nt{delay_until_statement} whose requested value of the delay expression is less than or equal to the value of Real_Time.Clock at the time of executing the statement. Similarly, for Calendar.Clock. @Defn{lateness} @Defn{actual duration} An upper bound on the @i{lateness} of a @nt{delay_relative_statement}, for a positive value of the delay expression, in a situation where the task has sufficient priority to preempt the processor as soon as it becomes ready, and does not need to wait for any other execution resources. The upper bound is expressed as a function of the value of the delay expression. The lateness is obtained by subtracting the value of the delay expression from the @i{actual duration}. The actual duration is measured from a point immediately before a task executes the @nt{delay_statement} to a point immediately after the task resumes execution following this statement. An upper bound on the lateness of a @nt{delay_until_statement}, in a situation where the value of the requested expiration time is after the time the task begins executing the statement, the task has sufficient priority to preempt the processor as soon as it becomes ready, and it does not need to wait for any other execution resources. The upper bound is expressed as a function of the difference between the requested expiration time and the clock value at the time the statement begins execution. The lateness of a @nt{delay_until_statement} is obtained by subtracting the requested expiration time from the real time that the task resumes execution following this statement. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for delay statements.]}]} @end{Metrics} @begin{Notes} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00355-01]} @ChgDeleted{Version=[2],Text=[The execution time of a @nt{delay_statement} that does not cause the task to be blocked (e.g. @lquotes@;@key[delay] 0.0;@rquotes@; ) is of interest in situations where delays are used to achieve voluntary round-robin task dispatching among equal-priority tasks.]} @end{Notes} @begin{DiffWord83} The rules regarding a @nt{timed_entry_call} with a very small positive Duration value, have been tightened to always require the check whether the rendezvous is immediately possible. @end{DiffWord83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00355-01]} @ChgAdded{Version=[2],Text=[The note about @lquotes@;voluntary round-robin@rquote, while still true, has been deleted as potentially confusing as it is describing a different kind of round-robin than is defined by the round-robin dispatching policy.]} @end{DiffWord95} @LabeledClause{Synchronous Task Control} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined private semaphore (suspension object), which can be used for @i{two-stage suspend} operations and as a simple building block for implementing higher-level queues.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key{package} Ada.Synchronous_Task_Control @key{is}@ChildUnit{Parent=[Ada],Child=[Synchronous_Task_Control]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Synchronous_Task_Control);],Old=[]} @key{type} @AdaTypeDefn{Suspension_Object} @key{is} @key{limited} @key{private}; @key{procedure} @AdaSubDefn{Set_True}(S : @key{in} @key{out} Suspension_Object); @key{procedure} @AdaSubDefn{Set_False}(S : @key{in} @key{out} Suspension_Object); @key{function} @AdaSubDefn{Current_State}(S : Suspension_Object) @key{return} Boolean; @key{procedure} @AdaSubDefn{Suspend_Until_True}(S : @key{in} @key{out} Suspension_Object); @key{private} ... -- @RI{not specified by the language} @key{end} Ada.Synchronous_Task_Control; @end{example} The type Suspension_Object is a by-reference type.@begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00318-02]}@ChgNote{This is a real term now, let's get it right} The implementation can ensure this by, for example, making the full view @Chg{Version=[2],New=[an explicitly],Old=[a]} limited record type.@end{implnote} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0168-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[The following language-defined package exists:]} @begin{example} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0168-1]} @ChgAdded{Version=[3],Text=[@key{package} Ada.Synchronous_Task_Control.EDF @key{is}@ChildUnit{Parent=[Ada.Synchronous_Task_Control],Child=[EDF]} @key{procedure} @AdaSubDefn{Suspend_Until_True_And_Set_Deadline} (S : @key{in out} Suspension_Object; TS : @key{in} Ada.Real_Time.Time_Span); @key{end} Ada.Synchronous_Task_Control.EDF;]} @end{example} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} An object of the type Suspension_Object has two visible states: @Chg{Version=[2],New=[True],Old=[true]} and @Chg{Version=[2],New=[False],Old=[false]}. Upon initialization, its value is set to @Chg{Version=[2],New=[False],Old=[false]}. @begin{Discussion} This object is assumed to be private to the declaring task, i.e. only that task will call Suspend_Until_True on this object, and the count of callers is at most one. Other tasks can, of course, change and query the state of this object. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The operations Set_True and Set_False are atomic with respect to each other and with respect to Suspend_Until_True; they set the state to @Chg{Version=[2],New=[True],Old=[true]} and @Chg{Version=[2],New=[False],Old=[false]} respectively. Current_State returns the current state of the object. @begin{Discussion} This state can change immediately after the operation returns. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The procedure Suspend_Until_True blocks the calling task until the state of the object S is @Chg{Version=[2],New=[True],Old=[true]}; at that point the task becomes ready and the state of the object becomes @Chg{Version=[2],New=[False],Old=[false]}. @PDefn2{Term=[potentially blocking operation],Sec=(Suspend_Until_True)} @PDefn2{Term=[blocking, potentially],Sec=(Suspend_Until_True)} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised upon calling Suspend_Until_True if another task is already waiting on that suspension object. Suspend_Until_True is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0168-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[3],Text=[The procedure Suspend_Until_True_And_Set_Deadline blocks the calling task until the state of the object S is True; at that point the task becomes ready with a deadline of Ada.Real_Time.Clock + TS, and the state of the object becomes False. Program_Error is raised upon calling Suspend_Until_True_And_Set_Deadline if another task is already waiting on that suspension object. Suspend_Until_True_And_Set_Deadline is a potentially blocking operation.]} @end{RunTime} @begin{ImplReq} The implementation is required to allow the calling of Set_False and Set_True during any protected action, even one that has its ceiling priority in the Interrupt_Priority range. @end{ImplReq} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0168-1]} @ChgAdded{Version=[3],Text=[More complex schemes, such as setting the deadline relative to when Set_True is called, can be programmed using a protected object.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Synchronous_Task_Control is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0168-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005}Child package Ada.Synchronous_Task_Control.EDF is new.]} @end{Extend2005} @LabeledAddedSubClause{Version=[3],Name=[Synchronous Barriers]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This subclause introduces a language-defined package to synchronously release a group of tasks after the number of blocked tasks reaches a specified count value.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] Ada.Synchronous_Barriers @key{is}@ChildUnit{Parent=[Ada],Child=[Synchronous_Barriers]} @key[pragma] Preelaborate(Synchronous_Barriers);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[subtype] @AdaSubtypeDefn{Name=[Barrier_Limit],Of=[Positive]} @key[is] Positive @key[range] 1 .. @RI<implementation-defined>;]} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The value of Barrier_Limit'Last in Synchronous_Barriers.]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Synchronous_Barrier} (Release_Threshold : Barrier_Limit) @key[is limited private];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Wait_For_Release} (The_Barrier : @key[in out] Synchronous_Barrier; Notified : @key[out] Boolean);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[private] -- @RI{not specified by the language} @key[end] Ada.Synchronous_Barriers;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[Type Synchronous_Barrier needs finalization (see @RefSecNum{Assignment and Finalization}).]} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[Each call to Wait_For_Release blocks the calling task until the number of blocked tasks associated with the Synchronous_Barrier object is equal to Release_Threshold, at which time all blocked tasks are released. Notified is set to True for one of the released tasks, and set to False for all other released tasks.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[The mechanism for determining which task sets Notified to True is implementation defined.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[Once all tasks have been released, a Synchronous_Barrier object may be reused to block another Release_Threshold number of tasks.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[As the first step of the finalization of a Synchronous_Barrier, each blocked task is unblocked and Program_Error is raised at the place of the call to Wait_For_Release.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[It is implementation defined whether an abnormal task which is waiting on a Synchronous_Barrier object is aborted immediately or aborted when the tasks waiting on the object are released.]} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[When an aborted task that is waiting on a Synchronous_Barrier is aborted.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[Wait_For_Release is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}).]} @end{Runtime} @begin{Bounded} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[It is a bounded error to call Wait_For_Release on a Synchronous_Barrier object after that object is finalized. If the error is detected, Program_Error is raised. Otherwise, the call proceeds normally, which may leave a task blocked forever.]} @end{Bounded} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0174-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package Ada.Synchronous_Barriers is new.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledClause{Asynchronous Task Control} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} introduces a language-defined package to do asynchronous suspend/resume on tasks. It uses a conceptual @i{held priority} value to represent the task's @i{held} state.] @end{Intro} @begin{StaticSem} @Leading@;The following language-defined library package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key{with} Ada.Task_Identification; @key{package} Ada.Asynchronous_Task_Control @key{is}@ChildUnit{parent=[Ada],Child=[Asynchronous_Task_Control]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Asynchronous_Task_Control);],Old=[]} @key{procedure} @AdaSubDefn{Hold}(T : @key[in] Ada.Task_Identification.Task_Id); @key{procedure} @AdaSubDefn{Continue}(T : @key[in] Ada.Task_Identification.Task_Id); @key{function} @AdaSubDefn{Is_Held}(T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{end} Ada.Asynchronous_Task_Control; @end{example} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} @PDefn2{Term=[task state], Sec=(held)} @Defn{held priority} @Defn{idle task} After the Hold operation has been applied to a task, the task becomes @i{held}. For each processor there is a conceptual @i{idle task}, which is always ready. The base priority of the idle task is below System.@!Any_@!Priority'First. The @i{held priority} is a constant of the type @Chg{Version=[2],New=[Integer],Old=[integer]} whose value is below the base priority of the idle task. @begin{Discussion} The held state should not be confused with the blocked state as defined in @RefSecNum{Task Execution - Task Activation}; the task is still ready. @end{Discussion} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[For any priority below System.Any_Priority'First, the task dispatching policy is FIFO_Within_Priorities.]} @begin{Honest} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This applies even if a Task_Dispatching_Policy specifies the policy for all of the priorities of the partition.]} @end{Honest} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[A task at the held priority never runs, so it is not necessary to implement FIFO_Within_Priorities for systems that have only one policy (such as EDF_Across_Priorities).]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} The Hold operation sets the state of T to held. For a held task@Chg{Version=[2],New=[, the active priority is reevaluated as if the base priority of the task were the held priority],Old=[: the task's own base priority does not constitute an inheritance source (see @RefSecNum{Task Priorities}), and the value of the held priority is defined to be such a source instead]}. @begin{Ramification} For example, if T is currently inheriting priorities from other sources (e.g. it is executing in a protected action), its active priority does not change, and it continues to execute until it leaves the protected action. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00357-01]} The Continue operation resets the state of T to not-held; @Chg{Version=[2],New=[its],Old=[T's]} active priority is then reevaluated as @Chg{Version=[2],New=[determined by the task dispatching policy associated with its base priority.],Old=[described in @RefSecNum{Task Priorities}. @Redundant[This time, T's base priority is taken into account.]]} The Is_Held function returns True if and only if T is in the held state. @begin{Discussion} Note that the state of T can be changed immediately after Is_Held returns. @end{Discussion} As part of these operations, a check is made that the task identified by T is not terminated. @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} Tasking_Error is raised if the check fails. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the value of T is Null_Task_Id. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If any operation in this package is called with a parameter T that specifies a task object that no longer exists, the execution of the program is erroneous. @end{Erron} @begin{ImplPerm} An implementation need not support Asynchronous_Task_Control if it is infeasible to support it in the target environment. @begin{Reason} A direct implementation of the Asynchronous_Task_Control semantics using priorities is not necessarily efficient enough. Thus, we envision implementations that use some other mechanism to set the @lquotes@;held@rquotes@; state. If there is no other such mechanism, support for Asynchronous_Task_Control might be infeasible, because an implementation in terms of priority would require one idle task per processor. On some systems, programs are not supposed to know how many processors are available, so creating enough idle tasks would be problematic. @end{Reason} @end{ImplPerm} @begin{Notes} It is a consequence of the priority rules that held tasks cannot be dispatched on any processor in a partition (unless they are inheriting priorities) since their priorities are defined to be below the priority of any idle task. The effect of calling Get_Priority and Set_Priority on a Held task is the same as on any other task. Calling Hold on a held task or Continue on a non-held task has no effect. @Leading@;The rules affecting queuing are derived from the above rules, in addition to the normal priority rules: @begin{itemize} When a held task is on the ready queue, its priority is so low as to never reach the top of the queue as long as there are other tasks on that queue. If a task is executing in a protected action, inside a rendezvous, or is inheriting priorities from other sources (e.g. when activated), it continues to execute until it is no longer executing the corresponding construct. If a task becomes held while waiting (as a caller) for a rendezvous to complete, the active priority of the accepting task is not affected. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0077],ARef=[AI95-00111-01]} If a task becomes held while waiting in a @nt{selective_accept}, and a@Chg{New=[n],Old=[]} entry call is issued to one of the open entries, the corresponding @Chg{New=[@nt{accept_@!alternative}],Old=[accept body]} executes. When the rendezvous completes, the active priority of the accepting task is lowered to the held priority (unless it is still inheriting from other sources), and the task does not execute until another Continue. The same holds if the held task is the only task on a protected entry queue whose barrier becomes open. The corresponding entry body executes. @end{itemize} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Asynchronous_Task_Control is now Preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0077],ARef=[AI95-00111-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected to eliminate the use of the undefined term @lquotes@;accept body@rquotes@;.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00357-01]} @ChgAdded{Version=[2],Text=[The description of held tasks was changed to reflect that the calculation of active priorities depends on the dispatching policy of the base priority. Thus, the policy of the held priority was specified in order to avoid surprises (especially when using the EDF policy).]} @end{DiffWord95} @LabeledClause{Other Optimizations and Determinism Rules} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes various requirements for improving the response and determinism in a real-time system.] @end{Intro} @begin{ImplReq} If the implementation blocks interrupts (see @RefSecNum{Interrupt Support}) not as a result of direct user action (e.g. an execution of a protected action) there shall be an upper bound on the duration of this blocking. @begin{Ramification} The implementation shall not allow itself to be interrupted when it is in a state where it is unable to support all the language-defined operations permitted in the execution of interrupt handlers. (see @RefSecNum{Protected Subprograms and Protected Actions}). @end{Ramification} The implementation shall recognize entry-less protected types. The overhead of acquiring the execution resource of an object of such a type (see @RefSecNum{Protected Subprograms and Protected Actions}) shall be minimized. In particular, there should not be any overhead due to evaluating @nt{entry_barrier} @nt{condition}s. @begin{ImplNote} Ideally the overhead should just be a spin-lock. @end{ImplNote} Unchecked_Deallocation shall be supported for terminated tasks that are designated by access types, and shall have the effect of releasing all the storage associated with the task. This includes any run-time system or heap storage that has been implicitly allocated for the task by the implementation. @end{ImplReq} @begin{DocReq} The implementation shall document the upper bound on the duration of interrupt blocking caused by the implementation. If this is different for different interrupts or interrupt priority levels, it should be documented for each case. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[The upper bound on the duration of interrupt blocking caused by the implementation.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The upper bound on the duration of interrupt blocking caused by the implementation.]}]} @end{DocReq} @begin{Metrics} @Leading@;The implementation shall document the following metric: @begin{Itemize} The overhead associated with obtaining a mutual-exclusive access to an entry-less protected object. This shall be measured in the following way: @NoPrefix@Leading@keepnext@;For a protected object of the form: @begin{example} @key{protected} Lock @key{is} @key{procedure} Set; @Key{function} Read @Key{return} Boolean; @key{private} Flag : Boolean := False; @key{end} Lock; @key{protected body} Lock @key{is} @key{procedure} Set @key{is} @key{begin} Flag := True; @key{end} Set; @Key{function} Read @Key{return} Boolean @key{Begin} @key{return} Flag; @key{end} Read; @key{end} Lock; @end{example} @NoPrefix@;The execution time, in processor clock cycles, of a call to Set. This shall be measured between the point just before issuing the call, and the point just after the call completes. The function Read shall be called later to verify that Set was indeed called (and not optimized away). The calling task shall have sufficiently high priority as to not be preempted during the measurement period. The protected object shall have sufficiently high ceiling priority to allow the task to call Set. @NoPrefix@;For a multiprocessor, if supported, the metric shall be reported for the case where no contention (on the execution resource) exists @Redundant[from tasks executing on other processors]. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for entry-less protected objects.]}]} @end{Metrics} @LabeledRevisedClause{Version=[3],InitialVersion=[2],New=[The Ravenscar Profile],Old=[Run-time Profiles]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0246-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} @Chg{Version=[3],New=[defines the Ravenscar profile.@Defn{Ravenscar}], Old=[specifies a mechanism for defining run-time profiles.]}]]} @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 and 3 were moved to @RefSec{Pragma Restrictions and Pragma Profile}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0246-1]} @ChgDeleted{Version=[3],Type=[Leading],Keepnext=[T],Text=[@Chg{Version=[2],New=[The form of a @nt{pragma} Profile is as follows:],Old=[]}]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[2],@ChgDeleted{Version=[3], Text=`@Chg[Version=[2],New=[@key{pragma} @prag<Profile> (@SynI{profile_}@Syn2{identifier} {, @SynI{profile_}@Syn2{pragma_argument_association}});],Old=[]]'}> @end{Syntax} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0246-1]} @ChgAdded{Version=[2],Text=[The @SynI{profile_}@nt{identifier} @Chg{Version=[3],New=[Ravenscar is a usage profile (see @RefSecNum{Pragma Restrictions and Pragma Profile}). For usage profile Ravenscar, there shall be no],Old=[shall be the name of a run-time profile. The semantics of any]} @SynI{profile_}@nt{pragma_@!argument_@!association}s@Chg{Version=[3],New=[],Old=[ are defined by the run-time profile specified by the @SynI{profile_}@nt{identifier}]}.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0246-1]} @ChgAdded{Version=[2],Type=[Leading],Text=[@Chg{Version=[3],New=[The usage profile Ravenscar is equivalent to the following set of pragmas:],Old=[A profile is equivalent to the set of configuration pragmas that is defined for each run-time profile.]}]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI95-00297-01],ARef=[AI95-00394-01],ARef=[AI05-0171-1],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[ @key{pragma} Task_Dispatching_Policy (FIFO_Within_Priorities); @key{pragma} Locking_Policy (Ceiling_Locking); @key{pragma} Detect_Blocking; @key{pragma} Restrictions ( No_Abort_Statements, No_Dynamic_Attachment, No_Dynamic_Priorities, No_Implicit_Heap_Allocations, No_Local_Protected_Objects, No_Local_Timing_Events, No_Protected_Type_Allocators, No_Relative_Delay, No_Requeue_Statements, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Allocators, No_Task_Hierarchy, No_Task_Termination, Simple_Barriers, Max_Entry_Queue_Length => 1, Max_Protected_Entries => 1, Max_Task_Entries => 0, No_Dependence => Ada.Asynchronous_Task_Control, No_Dependence => Ada.Calendar, No_Dependence => Ada.Execution_Time.Group_Budgets, No_Dependence => Ada.Execution_Time.Timers, No_Dependence => Ada.Task_Attributes@Chg{Version=[3],New=[, No_Dependence => System.Multiprocessors.Dispatching_Domains],Old=[]});]} @end{Example} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The Ravenscar profile is named for the location of the meeting that defined its initial version. The name is now in widespread use, so we stick with existing practice, rather than using a more descriptive name.@Comment{ This is another example of Ada's lousy marketing sense; casual readers, especially those outside of Ada, have no conception of what @lquotes@;Ravenscar@rquotes@; is, and thus are much less likely to investigate it to find out how it can help them.}]} @end{Discussion} @end{StaticSem} @begin{Linktime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0246-1]} @ChgAdded{Version=[2],Text=[@Chg{Version=[3],New=[],Old=[@PDefn2{Term=[configuration pragma], Sec=(Profile)} @PDefn2{Term=[pragma, configuration], Sec=(Profile)} A @nt{pragma} Profile is a configuration pragma. There may be more than one @nt{pragma} Profile for a partition.]}]} @end{Linktime} @begin{NotIso} @ChgAdded{Version=[3],Noparanum=[T],Text=[@Shrink{@i<Paragraph 7 was deleted.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[A task shall only be on the ready queues of one processor, and the processor to which a task belongs shall be defined statically. Whenever a task running on a processor reaches a task dispatching point, it goes back to the ready queues of the same processor. A task with a CPU value of Not_A_Specific_CPU will execute on an implementation defined processor. @Redundant[A task without a CPU aspect will activate and execute on the same processor as its activating task.]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The processor of a task without a CPU aspect is defined in @RefSecNum{Multiprocessor Implementation}.]} @end{TheProof} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The processor on which a task with a CPU value of a Not_A_Specific_CPU will execute when the Ravenscar profile is in effect.]}]} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[On a multiprocessor system, an implementation should support a fully partitioned approach. Each processor should have separate and disjoint ready queues.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[On a multiprocessor system, each processor should have a separate and disjoint ready queue.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI05-0246-1]} @ChgAdded{Version=[3],Text=[The effect of the Max_Entry_Queue_Length => 1 restriction applies only to protected entry queues due to the accompanying restriction of Max_Task_Entries => 0.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0246-1]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @Chg{Version=[3],New=[The Ravenscar profile is new; it was moved here by Ada 2012],Old=[@nt{Pragma} Profile is new]}.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[How Ravenscar behaves on a multiprocessor system is now defined.]} @end{DiffWord2005} @Comment{Moved the following to the previous subclause... @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledAddedSubClause{Version=[2],Name=[The Ravenscar Profile]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[@Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines the Ravenscar profile.]@Defn{Ravenscar}]} @end{Intro} @begin{Legality} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[The @SynI{profile_}@nt{identifier} Ravenscar is a run-time profile. For run-time profile Ravenscar, there shall be no @Syni{profile_}@nt{pragma_argument_association}s.]} @end{Legality} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The run-time profile Ravenscar is equivalent to the following set of pragmas:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01],ARef=[AI95-00297-01],ARef=[AI95-00394-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0171-1]} @ChgAdded{Version=[2],Text=[ @key{pragma} Task_Dispatching_Policy (FIFO_Within_Priorities); @key{pragma} Locking_Policy (Ceiling_Locking); @key{pragma} Detect_Blocking; @key{pragma} Restrictions ( No_Abort_Statements, No_Dynamic_Attachment, No_Dynamic_Priorities, No_Implicit_Heap_Allocations, No_Local_Protected_Objects, No_Local_Timing_Events, No_Protected_Type_Allocators, No_Relative_Delay, No_Requeue_Statements, No_Select_Statements, No_Specific_Termination_Handlers, No_Task_Allocators, No_Task_Hierarchy, No_Task_Termination, Simple_Barriers, Max_Entry_Queue_Length => 1, Max_Protected_Entries => 1, Max_Task_Entries => 0, No_Dependence => Ada.Asynchronous_Task_Control, No_Dependence => Ada.Calendar, No_Dependence => Ada.Execution_Time.Group_Budgets, No_Dependence => Ada.Execution_Time.Timers, No_Dependence => Ada.Task_Attributes@Chg{Version=[3],New=[, No_Dependence => System.Multiprocessors.Dispatching_Domains],Old=[]});]} @end{Example} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The Ravenscar profile is named for the location of the meeting that defined its initial version. The name is now in widespread use, so we stick with existing practice, rather than using a more descriptive name.@Comment{ This is another example of Ada's lousy marketing sense; casual readers, especially those outside of Ada, have no conception of what @lquotes@;Ravenscar@rquotes@; is, and thus are much less likely to investigate it to find out how it can help them.}]} @end{Discussion} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[A task shall only be on the ready queues of one processor, and the processor to which a task belongs shall be defined statically. Whenever a task running on a processor reaches a task dispatching point, it goes back to the ready queues of the same processor. A task with a CPU value of Not_A_Specific_CPU will execute on an implementation defined processor. @Redundant[A task without a CPU aspect will activate and execute on the same processor as its activating task.]]} @begin{TheProof} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The processor of a task without an aspect CPU is defined in @RefSecNum{Multiprocessor Implementation}.]} @end{TheProof} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The processor on which a task with a CPU value of a Not_A_Specific_CPU will execute when the Ravenscar profile is in effect.]}]} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[On a multiprocessor system, an implementation should support a fully partitioned approach. Each processor should have separate and disjoint ready queues.]} @ChgImplAdvice{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[On a multiprocessor system, each processor should have a separate and disjoint ready queue.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[ The effect of the Max_Entry_Queue_Length => 1 restriction applies only to protected entry queues due to the accompanying restriction of Max_Task_Entries => 0.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00249-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The Ravenscar profile is new.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[How Ravenscar behaves on a multiprocessor system is now defined.]} @end{DiffWord2005} end commented out text...}@Comment{End of original Ravenscar} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @LabeledAddedClause{Version=[2],Name=[Execution Time]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined package to measure execution time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} Ada.Task_Identification; @key{with} Ada.Real_Time; @key{use} Ada.Real_Time; @key{package} Ada.Execution_Time @key{is}@ChildUnit{Parent=[Ada],Child=[Execution_Time]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{CPU_Time} @key{is private}; @AdaObjDefn{CPU_Time_First} : @key{constant} CPU_Time; @AdaObjDefn{CPU_Time_Last} : @key{constant} CPU_Time; @AdaObjDefn{CPU_Time_Unit} : @key{constant} := @RI{implementation-defined-real-number}; @AdaObjDefn{CPU_Tick} : @key{constant} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Clock} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key{return} CPU_Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "+" (Left : CPU_Time; Right : Time_Span) @key{return} CPU_Time; @key{function} "+" (Left : Time_Span; Right : CPU_Time) @key{return} CPU_Time; @key{function} "-" (Left : CPU_Time; Right : Time_Span) @key{return} CPU_Time; @key{function} "-" (Left : CPU_Time; Right : CPU_Time) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} "<" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} "<=" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} ">" (Left, Right : CPU_Time) @key{return} Boolean; @key{function} ">=" (Left, Right : CPU_Time) @key{return} Boolean;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Split} (T : @key{in} CPU_Time; SC : @key{out} Seconds_Count; TS : @key{out} Time_Span);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Of} (SC : Seconds_Count; TS : Time_Span := Time_Span_Zero) @key{return} CPU_Time;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{Interrupt_Clocks_Supported} : @key[constant] Boolean := @RI<implementation-defined>;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{Separate_Interrupt_Clocks_Supported} : @key[constant] Boolean := @RI<implementation-defined>;]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Clock_For_Interrupts} @key[return] CPU_Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- @RI[not specified by the language] @key{end} Ada.Execution_Time;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0170-1],ARef=[AI05-0269-1]} @ChgAdded{Version=[2],Text=[@Defn2{Term=[execution time],Sec=[of a task]} @Defn2{Term=[CPU time],Sec=[of a task]} The @i<execution time> or CPU time of a given task is defined as the time spent by the system executing that task, including the time spent executing run-time or system services on its behalf. The mechanism used to measure execution time is implementation defined. @Chg{Version=[3],New=[The Boolean constant Interrupt_Clocks_Supported is set to True if the implementation separately accounts for the execution time of interrupt handlers. If it is set to False it],Old=[It]} is implementation defined which task, if any, is charged the execution time that is consumed by interrupt handlers@Chg{Version=[3],New=[. The Boolean constant Separate_Interrupt_Clocks_Supported is set to True if the implementation separately accounts for the execution time of individual interrupt handlers (see @RefSecNum{Execution Time of Interrupt Handlers})],Old=[ and run-time services on behalf of the system]}.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The implementation-defined properties above and of the values declared in the package are repeated in @DocReqTitle, so we don't mark them as implementation-defined.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type CPU_Time represents the execution time of a task. The set of values of this type corresponds one-to-one with an implementation-defined range of mathematical integers.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The CPU_Time value I represents the half-open execution-time interval that starts with I*CPU_Time_Unit and is limited by (I+1)*CPU_Time_Unit, where CPU_Time_Unit is an implementation-defined real number. For each task, the execution time value is set to zero at the creation of the task.]} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since it is implementation-defined which task is charged execution time for system services, the execution time value may become nonzero even before the start of the activation of the task.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[CPU_Time_First and CPU_Time_Last are the smallest and largest values of the CPU_Time type, respectively.]} @end{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[The execution time value for the function Clock_For_Interrupts is initialized to zero.]} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{CPU clock tick} CPU_Time_Unit is the smallest amount of execution time representable by the CPU_Time type; it is expressed in seconds. A @i<CPU clock tick> is an execution time interval during which the clock value (as observed by calling the Clock function) remains constant. CPU_Tick is the average length of such intervals.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The effects of the operators on CPU_Time and Time_Span are as for the operators defined for integer types.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The function Clock returns the current execution time of the task identified by T; Tasking_Error is raised if that task has terminated; Program_Error is raised if the value of T is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The effects of the Split and Time_Of operations are defined as follows, treating values of type CPU_Time, Time_Span, and Seconds_Count as mathematical integers. The effect of Split (T, SC, TS) is to set SC and TS to values such that T*CPU_Time_Unit = SC*1.0 + TS*CPU_Time_Unit, and 0.0 <= TS*CPU_Time_Unit < 1.0. The value returned by Time_Of(SC,TS) is the execution-time value T such that T*CPU_Time_Unit=SC*1.0 + TS*CPU_Time_Unit.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[The function Clock_For_Interrupts returns the total cumulative time spent executing within all interrupt handlers. This time is not allocated to any task execution time clock. If Interrupt_Clocks_Supported is set to False the function raises Program_Error.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of Clock, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The range of CPU_Time values shall be sufficient to uniquely represent the range of execution times from the task start-up to 50 years of execution time later. CPU_Tick shall be no greater than 1 millisecond.]} @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The implementation shall document the values of CPU_Time_First, CPU_Time_Last, CPU_Time_Unit, and CPU_Tick.]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The values of CPU_Time_First, CPU_Time_Last, CPU_Time_Unit, and CPU_Tick of package Execution_Time.]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The implementation shall document the properties of the underlying mechanism used to measure execution times, such as the range of values supported and any relevant aspects of the underlying hardware or operating system facilities used.]} @ChgDocReq{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[The properties of the mechanism used to implement package Execution_Time@Chg{Version=[3],New=[, including the values of the constants defined in the package],Old=[]}.]}]} @end{DocReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The implementation shall document the following metrics:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text={An upper bound on the execution-time duration of a clock tick. This is a value D such that if t1 and t2 are any execution times of a given task such that t1 < t2 and Clock@-{t1} = Clock@-{t2} then t2 @en@; t1 <= D.}} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An upper bound on the size of a clock jump. A clock jump is the difference between two successive distinct values of an execution-time clock (as observed by calling the Clock function with the same Task_Id).]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[An upper bound on the execution time of a call to the Clock function, in processor clock cycles.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Upper bounds on the execution times of the operators of the type CPU_Time, in processor clock cycles.]} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for execution time.]}]} @end{Metrics} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[Implementations targeted to machines with word size smaller than 32 bits need not support the full range and granularity of the CPU_Time type.]} @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When appropriate, implementations should provide configuration mechanisms to change the value of CPU_Tick.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[When appropriate, implementations should provide configuration mechanisms to change the value of Execution_Time.CPU_Tick.]}]} @end{ImplAdvice} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time is new.]} @end{Extend95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Function Clock_For_Interrupts, and constants Interrupt_Clocks_Supported and Separate_Interrupt_Clocks_Supported are added to Execution_Time. If Execution_Time is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of one of the added entities is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[If Interrupt_Clocks_Supported is True, it is now possible to determine the execution time of interrupt handlers. This is not an inconsistency, as not charging any task for such time was a legitimate implementation for Ada 2005.]} @end{Diffword2005} @LabeledAddedSubclause{Version=[2],Name=[Execution Time Timers]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined package that provides a facility for calling a handler when a task has used a defined amount of CPU time.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{with} System; @key{package} Ada.Execution_Time.Timers @key{is}@ChildUnit{Parent=[Ada.Execution_Time],Child=[Timers]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timer} (T : @key{not null access constant} Ada.Task_Identification.Task_Id) @key{is} @key{tagged limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timer_Handler} @key{is} @key{access protected procedure} (TM : @key{in out} Timer);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Min_Handler_Ceiling} : @key{constant} System.Any_Priority := @RI[implementation-defined];]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (TM : @key{in out} Timer; In_Time : @key{in} Time_Span; Handler : @key{in} Timer_Handler); @key{procedure} @AdaSubDefn{Set_Handler} (TM : @key{in out} Timer; At_Time : @key{in} CPU_Time; Handler : @key{in} Timer_Handler); @key{function} @AdaSubDefn{Current_Handler} (TM : Timer) @key{return} Timer_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (TM : @key{in out} Timer; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Remaining} (TM : Timer) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Timer_Resource_Error} : @key{exception};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- @RI{not specified by the language} @key{end} Ada.Execution_Time.Timers;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type Timer represents an execution-time event for a single task and is capable of detecting execution-time overruns. The access discriminant T identifies the task concerned. The type Timer needs finalization (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[An object of type Timer is said to be @i<set> if it is associated with a nonnull value of type Timer_Handler and @i<cleared> otherwise. All Timer objects are initially cleared. @PDefn2{Term=[set],Sec=[execution timer object]} @PDefn2{Term=[clear],Sec=[execution timer object]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The type Timer_Handler identifies a protected procedure to be executed by the implementation when the timer expires. Such a protected procedure is called a @i<handler>. @PDefn2{Term=[handler],Sec=[execution timer]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Type Timer is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific timer object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Timer can be declared; a double type conversion can be used to access the extension data. An example of how this can be done can be found for the similar type Timing_Event, see @RefSecNum{Timing Events}.]} @end{Discussion} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When a Timer object is created, or upon the first call of a Set_Handler procedure with the timer as parameter, the resources required to operate an execution-time timer based on the associated execution-time clock are allocated and initialized. If this operation would exceed the available resources, Timer_Resource_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedures Set_Handler associate the handler Handler with the timer TM@Chg{Version=[3],New=[:],Old=[;]} if Handler is @key[null], the timer is cleared@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is set. The first procedure Set_Handler loads the timer TM with an interval specified by the Time_Span parameter. In this mode, the timer TM @i<expires> when the execution time of the task identified by TM.T.@key[all] has increased by In_Time; if In_Time is less than or equal to zero, the timer expires immediately. The second procedure Set_Handler loads the timer TM with the absolute value specified by At_Time. In this mode, the timer TM expires when the execution time of the task identified by TM.T.@key[all] reaches At_Time; if the value of At_Time has already been reached when Set_Handler is called, the timer expires immediately.@Defn2{Term=[expires], Sec=[execution timer]}]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since an access-to-constant can designate a variable, the Task_Id value designated by the discriminant of a Timer object can be changed after the object is created. Thus, an implementation cannot use the value of the Task_Id other than where this Standard specifies. For instance, the Task_Id should be read when the timer is set, but it should not be used when the timer expires (as it may designate a different task at that point).]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[A call of a procedure Set_Handler for a timer that is already set replaces the handler and the (absolute or relative) execution time; if Handler is not @b<null>, the timer remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When a timer expires, the associated handler is executed, passing the timer as parameter. The initial action of the execution of the handler is to clear the event.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the timer TM if that timer is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns @b<null>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the timer if it is set. Cancelled is assigned True if the timer was set prior to it being cleared; otherwise@Chg{Version=[3],New=[,],Old=[]} it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Time_Remaining returns the execution time interval that remains until the timer TM would expire, if that timer is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns Time_Span_Zero.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[The constant Min_Handler_Ceiling is the minimum ceiling priority required for a protected object with a handler to ensure that no ceiling violation will occur when that handler is invoked.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Timer, the timer is cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[For all the subprograms defined in this package, Tasking_Error is raised if the task identified by TM.T.@key[all] has terminated, and Program_Error is raised if the value of TM.T.@key[all] is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked as part of the expiration of a timer has no effect.]} @end{Runtime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of any of the subprograms defined in this package, if the task identified by TM.T.@key[all] no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[For a given Timer object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Timer object. The replacement of a handler by a call of Set_Handler shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if an event occurs when Set_Handler is changing the handler then either the new or old handler is executed in response to the appropriate event. It is never possible for a new handler to be executed in response to an old event]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[When an object of type Timer is finalized, the system resources used by the timer shall be deallocated.]} @end{ImplReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[Implementations may limit the number of timers that can be defined for each task. If this limit is exceeded@Chg{Version=[3],New=[,],Old=[]} then Timer_Resource_Error is raised.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[A Timer_Handler can be associated with several Timer objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00307-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time.Timers is new.]} @end{Extend95} @RMNewPageVer{Version=[2]}@Comment{For printed RM Ada 2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledAddedSubclause{Version=[2],Name=[Group Execution Time Budgets]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined package to assign execution time budgets to groups of tasks.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0169-1]} @ChgAdded{Version=[2],Text=[@key{with} System;@Chg{Version=[3],New=[ @key{with} System.Multiprocessors;],Old=[]} @key{package} Ada.Execution_Time.Group_Budgets @key{is}@ChildUnit{Parent=[Ada.Execution_Time],Child=[Group_Budgets]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1],ARef=[AI05-0169-1]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Group_Budget}@Chg{Version=[3],New=[(CPU : System.Multiprocessors.CPU := System.Multiprocessors.CPU'First) ],Old=[]} @key{is tagged limited private};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Group_Budget_Handler} @key{is access} @key{protected procedure} (GB : @key{in out} Group_Budget);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Task_Array} @key{is array} (Positive @key{range} <>) @key{of} Ada.Task_Identification.Task_Id;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaObjDefn{Min_Handler_Ceiling} : @key{constant} System.Any_Priority := @RI[implementation-defined];]} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The value of Min_Handler_Ceiling in Execution_Time.Group_Budgets.]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Add_Task} (GB : @key{in out} Group_Budget; T : @key{in} Ada.Task_Identification.Task_Id); @key{procedure} @AdaSubDefn{Remove_Task} (GB: @key{in out} Group_Budget; T : @key{in} Ada.Task_Identification.Task_Id); @key{function} @AdaSubDefn{Is_Member} (GB : Group_Budget; T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{function} @AdaSubDefn{Is_A_Group_Member} (T : Ada.Task_Identification.Task_Id) @key{return} Boolean; @key{function} @AdaSubDefn{Members} (GB : Group_Budget) @key{return} Task_Array;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Replenish} (GB : @key{in out} Group_Budget; To : @key{in} Time_Span); @key{procedure} @AdaSubDefn{Add} (GB : @key{in out} Group_Budget; Interval : @key{in} Time_Span); @key{function} @AdaSubDefn{Budget_Has_Expired} (GB : Group_Budget) @key{return} Boolean; @key{function} @AdaSubDefn{Budget_Remaining} (GB : Group_Budget) @key{return} Time_Span;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (GB : @key{in out} Group_Budget; Handler : @key{in} Group_Budget_Handler); @key{function} @AdaSubDefn{Current_Handler} (GB : Group_Budget) @key{return} Group_Budget_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (GB : @key{in out} Group_Budget; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @AdaExcDefn{Group_Budget_Error} : @key{exception};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} -- @RI{not specified by the language} @key{end} Ada.Execution_Time.Group_Budgets;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The type Group_Budget represents an execution time budget to be used by a group of tasks. The type Group_Budget needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}). A task can belong to at most one group. Tasks of any priority can be added to a group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An object of type Group_Budget has an associated nonnegative value of type Time_Span known as its @i<budget>, which is initially Time_Span_Zero. The type Group_Budget_Handler identifies a protected procedure to be executed by the implementation when the budget is @i<exhausted>, that is, reaches zero. Such a protected procedure is called a @i<handler>.@Defn{budget}@Defn2{Term=[exhaust],Sec=[a budget]} @PDefn2{Term=[handler],Sec=[group budget]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An object of type Group_Budget also includes a handler, which is a value of type Group_Budget_Handler. The handler of the object is said to be @i<set> if it is not null and @i<cleared> otherwise. The handler of all Group_Budget objects is initially cleared. @PDefn2{Term=[set],Sec=[group budget object]} @PDefn2{Term=[clear],Sec=[group budget object]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Type Group_Budget is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific group budget object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Group_Budget can be declared; a double type conversion can be used to access the extension data. An example of how this can be done can be found for the similar type Timing_Event, see @RefSecNum{Timing Events}.]} @end{Discussion} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Add_Task adds the task identified by T to the group GB; if that task is already a member of some other group, Group_Budget_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Remove_Task removes the task identified by T from the group GB; if that task is not a member of the group GB, Group_Budget_Error is raised. After successful execution of this procedure, the task is no longer a member of any group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Is_Member returns True if the task identified by T is a member of the group GB; otherwise@Chg{Version=[3],New=[,],Old=[]} it @Chg{Version=[3],New=[returns],Old=[return]} False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Is_A_Group_Member returns True if the task identified by T is a member of some group; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Members returns an array of values of type Task_Identification.Task_Id identifying the members of the group GB. The order of the components of the array is unspecified.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0092-1],ARef=[AI05-0169-1]} @ChgAdded{Version=[2],Text=[The procedure Replenish loads the group budget GB with To as the Time_Span value. The exception Group_Budget_Error is raised if the Time_Span value To is nonpositive. Any execution @Chg{Version=[3],New=[on CPU ],Old=[]}of any member of the group of tasks results in the budget counting down, unless exhausted. When the budget becomes exhausted (reaches Time_Span_Zero), the associated handler is executed if the handler of group budget GB is set. Nevertheless, the tasks continue to execute.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The procedure Add modifies the budget of the group GB. A positive value for Interval increases the budget. A negative value for Interval reduces the budget, but never below Time_Span_Zero. A zero value for Interval has no effect. A call of procedure Add that results in the value of the budget going to Time_Span_Zero causes the associated handler to be executed if the handler of the group budget GB is set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Budget_Has_Expired returns True if the budget of group GB is exhausted (equal to Time_Span_Zero); otherwise@Chg{Version=[3],New=[,],Old=[]} it returns False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The function Budget_Remaining returns the remaining budget for the group GB. If the budget is exhausted it returns Time_Span_Zero. This is the minimum value for a budget.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Set_Handler associates the handler Handler with the Group_Budget GB@Chg{Version=[3],New=[:],Old=[;]} if Handler is @b<null>, the handler of Group_Budget is cleared@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[A call of Set_Handler for a Group_Budget that already has a handler set replaces the handler; if Handler is not @b<null>, the handler for Group_Budget remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the group budget GB if the handler for that group budget is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns @b<null>.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the handler for the group budget if it is set. Cancelled is assigned True if the handler for the group budget was set prior to it being cleared; otherwise@Chg{Version=[3],New=[,],Old=[]} it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The constant Min_Handler_Ceiling is the minimum ceiling priority required for a protected object with a handler to ensure that no ceiling violation will occur when that handler is invoked.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[The precision of the accounting of task execution time to a Group_Budget is the same as that defined for execution-time clocks from the parent package.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Group_Budget all member tasks are removed from the group identified by that object.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If a task is a member of a Group_Budget when it terminates@Chg{Version=[3],New=[,],Old=[]} then as part of the finalization of the task it is removed from the group.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[For all the operations defined in this package, Tasking_Error is raised if the task identified by T has terminated, and Program_Error is raised if the value of T is Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked when the budget of a group of tasks becomes exhausted has no effect.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} For a call of any of the subprograms defined in this package, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[For a given Group_Budget object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Group_Budget object. The replacement of a handler, by a call of Set_Handler, shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if the budget is exhausted when Set_Handler is changing the handler then either the new or old handler is executed and the exhausting event is not lost.]} @end{Reason} @end{ImplReq} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[Clearing or setting of the handler of a group budget does not change the current value of the budget. Exhaustion or loading of a budget does not change whether the handler of the group budget is set or cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[A Group_Budget_Handler can be associated with several Group_Budget objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00354-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Execution_Time.Group_Budgets is new.]} @end{Extend95} @begin{Inconsistent2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0169-1]} @ChgAdded{Version=[3],Text=[@Defn{inconsistencies with Ada 2005} A Group_Budget is now defined to work on a single processor. If an implementation managed to make this package work for programs running on a multiprocessor system, and a program depends on that fact, it could fail when ported to Ada 2012. We believe it is unlikely that such an implementation exists because of the difficulty of signalling other processors when the time reaches zero; in any case, depending on such an implementation is not portable.]} @end{Inconsistent2005} @LabeledAddedSubClause{Version=[3],Name=[Execution Time of Interrupt Handlers]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined package to measure the execution time of interrupt handlers.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key{with} Ada.Interrupts; @key{package} Ada.Execution_Time.Interrupts @key{is}@ChildUnit{Parent=[Ada.Execution_Time],Child=[Interrupts]} @key{function} @AdaSubDefn{Clock} (Interrupt : Ada.Interrupts.Interrupt_Id) @key{return} CPU_Time; @key{function} @AdaSubDefn{Supported} (Interrupt : Ada.Interrupts.Interrupt_Id) @key{return} Boolean; @key{end} Ada.Execution_Time.Interrupts;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[The execution time or CPU time of a given interrupt Interrupt is defined as the time spent by the system executing interrupt handlers identified by Interrupt, including the time spent executing run-time or system services on its behalf. The mechanism used to measure execution time is implementation defined. Time spent executing interrupt handlers is distinct from time spent executing any task.]} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[The implementation-defined mechanism here is the same as that covered by the @DocReqTitle of @RefSecNum{Execution Time}, so we don't repeat that requirement here.]} @end{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[For each interrupt, the execution time value is initially set to zero.]} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[The function Clock returns the current cumulative execution time of the interrupt identified by Interrupt. If Separate_Interrupt_Clocks_Supported is set to False the function raises Program_Error.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[The function Supported returns True if the implementation is monitoring the execution time of the interrupt identified by Interrupt; otherwise, it returns False. For any Interrupt_Id Interrupt for which Supported(Interrupt) returns False, the function Clock(Interrupt) will return a value equal to Ada.Execution_Time.Time_Of(0).]} @end{RunTime} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0170-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package Execution_Time.Interrupts is new.]} @end{Extend2005} @LabeledAddedClause{Version=[2],Name=[Timing Events]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes a language-defined package to allow user-defined protected procedures to be executed at a specified time without the need for a task or a delay statement.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{package} Ada.Real_Time.Timing_Events @key{is}@ChildUnit{Parent=[Ada.Real_Time],Child=[Timing_Events]}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{type} @AdaTypeDefn{Timing_Event} @key{is tagged limited private}; @key{type} @AdaTypeDefn{Timing_Event_Handler} @key{is access protected procedure} (Event : @key{in out} Timing_Event);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} @AdaSubDefn{Set_Handler} (Event : @key{in out} Timing_Event; At_Time : @key{in} Time; Handler : @key{in} Timing_Event_Handler); @key{procedure} @AdaSubDefn{Set_Handler} (Event : @key{in out} Timing_Event; In_Time : @key{in} Time_Span; Handler : @key{in} Timing_Event_Handler); @key{function} @AdaSubDefn{Current_Handler} (Event : Timing_Event) @key{return} Timing_Event_Handler; @key{procedure} @AdaSubDefn{Cancel_Handler} (Event : @key{in out} Timing_Event; Cancelled : @key{out} Boolean);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{function} @AdaSubDefn{Time_Of_Event} (Event : Timing_Event) @key{return} Time;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{private} ... -- @RI[not specified by the language] @key{end} Ada.Real_Time.Timing_Events;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The type Timing_Event represents a time in the future when an event is to occur. The type Timing_Event needs finalization@PDefn2{Term=<needs finalization>,Sec=<language-defined type>} (see @RefSecNum{Assignment and Finalization}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[An object of type Timing_Event is said to be @i<set> if it is associated with a nonnull value of type Timing_Event_Handler and @i<cleared> otherwise. All Timing_Event objects are initially cleared. @PDefn2{Term=[set],Sec=[timing event object]} @PDefn2{Term=[clear],Sec=[timing event object]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The type Timing_Event_Handler identifies a protected procedure to be executed by the implementation when the timing event occurs. Such a protected procedure is called a @i{handler}. @PDefn2{Term=[handler],Sec=[timing event]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Type=[Leading],Text=[Type Timing_Event is tagged. This makes it possible to share a handler between several events. In simple cases, 'Access can be used to compare the parameter with a specific timing event object (this works because a tagged type is a by-reference type). In more complex cases, a type extension of type Timing_Event can be declared; a double type conversion can be used to access the extension data. For example:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{type} Toaster_Timing_Event @key{is new} Timing_Event @key{with record} Slot : Natural; @key{end record};]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[...]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key{protected body} Toaster @key{is}]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key{procedure} Timer (Event : @key{in out} Timing_Event) @key{is} @key{begin} Pop_Up_Toast (Toaster_Timing_Event(Timing_Event'Class(Event)).Slot); @key{end} Timer;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ ... @key{end} Toaster;]} @end{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The extra conversion to the class-wide type is necessary to make the conversions legal. While this usage is clearly ugly, we think that the need for this sort of usage will be rare, so we can live with it. It's certainly better than having no way to associate data with an event.]} @end{Discussion} @end{StaticSem} @begin{Runtime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedures Set_Handler associate the handler Handler with the event Event@Chg{Version=[3],New=[:],Old=[;]} if Handler is @key{null}, the event is cleared@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is set. The first procedure Set_Handler sets the execution time for the event to be At_Time. The second procedure Set_Handler sets the execution time for the event to be Real_Time.Clock + In_Time.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[A call of a procedure Set_Handler for an event that is already set replaces the handler and the time of execution; if Handler is not @key{null}, the event remains set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[As soon as possible after the time set for the event, the handler is executed, passing the event as parameter. The handler is only executed if the timing event is in the set state at the time of execution. The initial action of the execution of the handler is to clear the event.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The second sentence of this paragraph is because of a potential race condition. The time might expire and yet before the handler is executed, some task could call Cancel_Handler (or equivalently call Set_Handler with a @key{null} parameter) and thus clear the handler.]} @end{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect when a procedure Set_Handler is called, a check is made that the ceiling priority of Handler.@key{all} is Interrupt_Priority'Last. If the check fails, Program_Error is raised.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0094-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If a procedure Set_Handler is called with zero or negative In_Time or with At_Time indicating a time in the past@Chg{Version=[3],New=[,],Old=[]} then the handler is executed @Chg{Version=[3],New=[as soon as possible after the completion of], Old=[immediately by the task executing]} the call of Set_Handler.@Chg{Version=[3], New=[],Old=[ The timing event Event is cleared.]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0094-1]} @ChgAdded{Version=[3],Text=[The handler will still be executed. Under no circumstances is a scheduled call of a handler lost.]} @end{Ramification} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0094-1]} @ChgAdded{Version=[3],Text=[We say @ldquote@;as soon as possible@rdquote so that we do not deadlock if we are executing the handler when Set_Handler is called. In that case, the current invocation of the handler must complete before the new handler can start executing.]} @end{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Current_Handler returns the handler associated with the event Event if that event is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Cancel_Handler clears the event if it is set. Cancelled is assigned True if the event was set prior to it being cleared; otherwise@Chg{Version=[3],New=[,],Old=[]} it is assigned False.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Time_Of_Event returns the time of the event if the event is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns Real_Time.Time_First.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[As part of the finalization of an object of type Timing_Event, the Timing_Event is cleared.]} @begin{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is the only finalization defined by the language that has a visible effect; but an implementation may have other finalization that it needs to perform. Implementations need to ensure that the event is cleared before anything else is finalized that would prevent a set event from being triggered.]} @end{ImplNote} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[If several timing events are set for the same time, they are executed in FIFO order of being set.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler invoked by a timing event has no effect.]} @end{Runtime} @begin{ImplReq} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[For a given Timing_Event object, the implementation shall perform the operations declared in this package atomically with respect to any of these operations on the same Timing_Event object. The replacement of a handler by a call of Set_Handler shall be performed atomically with respect to the execution of the handler.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This prevents various race conditions. In particular it ensures that if an event occurs when Set_Handler is changing the handler then either the new or old handler is executed in response to the appropriate event. It is never possible for a new handler to be executed in response to an old event.]} @end{Reason} @end{ImplReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[The implementation shall document the following metric:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0210-1]} @ChgAdded{Version=[2],Text=[An upper bound on the lateness of the execution of a handler. That is, the maximum time between @Chg{Version=[3],New=[the time specified for the event and ],Old=[]}when a handler is actually @Chg{Version=[3],New=[invoked assuming no other handler or task is executing during this interval],Old=[executed and the time specified when the event was set]}.]} @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for timing events.]}]} @end{Metrics} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[The protected handler procedure should be executed directly by the real-time clock interrupt mechanism.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For a timing event, the handler should be executed directly by the real-time clock interrupt mechanism.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[Since a call of Set_Handler is not a potentially blocking operation, it can be called from within a handler.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[A Timing_Event_Handler can be associated with several Timing_Event objects.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00297-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} The package Real_Time.Timing_Events is new.]} @end{Extend95} @begin{Diffword2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0094-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Reworded to eliminate a deadlock condition if the event time is in the past and a handler is currently executing. This is technically an inconsistency, but only if a program is depending on deadlocking; since it is impossible to imagine how that could be useful, we have not documented this as an inconsistency.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0210-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Clarified the metric for lateness of a timing event to exclude interference from other handlers and tasks. This change might change the documentation of an implementation, but not the implementation itself, so there is no inconsistency.]} @end{Diffword2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedClause{Version=[3],Name=[Multiprocessor Implementation]} @begin{Intro} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} allows implementations on multiprocessor platforms to be configured.]} @end{Intro} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[package] System.Multiprocessors @key{is}@ChildUnit{Parent=[System],Child=[Multiprocessors]} @key[pragma] Preelaborate(Multiprocessors);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{CPU_Range} @key[is range] 0 .. @RI<implementation-defined>; @AdaObjDefn{Not_A_Specific_CPU} : @key[constant] CPU_Range := 0; @key[subtype] @AdaSubtypeDefn{Name=[CPU],Of=[CPU_Range]} @key[is] CPU_Range @key[range] 1 .. CPU_Range'Last;]} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The value of CPU_Range'Last in System.Multiprocessors.]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Number_Of_CPUs} @key[return] CPU; @key[end] System.Multiprocessors;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1]} @ChgAdded{Version=[3],Text=[A call of Number_Of_CPUs returns the number of processors available to the program. Within a given partition, each call on Number_Of_CPUs will return the same value.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a task type (including the anonymous type of a @nt{single_task_declaration}) or subprogram, the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[CPU@\The aspect CPU is an @nt{expression}, which shall be of type System.Multiprocessors.CPU_Range.@AspectDefn{CPU}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[CPU], Text=[@ChgAdded{Version=[3],Text=[Processor on which a given task should run.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If the CPU aspect is specified for a subprogram, the @nt{expression} shall be static.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The CPU aspect shall not be specified on a task interface type.]} @end{Legality} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The @nt{expression} specified for the CPU aspect of a task is evaluated for each task object (see @RefSecNum{Task Units and Task Objects}). The CPU value is then associated with the task object whose task declaration specifies the aspect.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The CPU aspect has no effect if it is specified for a subprogram other than the main subprogram; the CPU value is not associated with any task.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[The CPU value is associated with the environment task if the CPU aspect is specified for the main subprogram. If the CPU aspect is not specified for the main subprogram it is implementation defined on which processor the environment task executes.]} @ChgImplDef{Version=[3],Kind=[Added],Text=[@ChgAdded{Version=[3], Text=[The processor on which the environment task executes in the absence of a value for the aspect CPU.]}]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0264-1]} @ChgAdded{Version=[3],Text=[The CPU value determines the processor on which the task will activate and execute; the task is said to be assigned to that processor. If the CPU value is Not_A_Specific_CPU, then the task is not assigned to a processor. A task without a CPU aspect specified will activate and execute on the same processor as its activating task if the activating task is assigned a processor. If the CPU value is not in the range of System.Multiprocessors.CPU_Range or is greater than Number_Of_CPUs the task is defined to have failed, and it becomes a completed task (see @RefSecNum{Task Execution - Task Activation}).]} @end{Runtime} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0171-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package System.Multiprocessors and the CPU aspect are new.]} @end{Extend2005} @NotISORMNewPageVer{Version=[3]}@Comment{For printed version of Ada 2012 RM} @LabeledAddedSubClause{Version=[3],Name=[Multiprocessor Dispatching Domains]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1],ARef=[AI05-0299-1]} @ChgAdded{Version=[3],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} allows implementations on multiprocessor platforms to be partitioned into distinct dispatching domains during program startup.]} @begin{StaticSem} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[with] Ada.Real_Time; @key[with] Ada.Task_Identification; @key[package] System.Multiprocessors.Dispatching_Domains @key{is}@ChildUnit{Parent=[System.Multiprocessors],Child=[Dispatching_Domains]}]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaExcDefn{Dispatching_Domain_Error} : @key[exception];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[type] @AdaTypeDefn{Dispatching_Domain} (<>) @key[is limited private];]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @AdaObjDefn{System_Dispatching_Domain} : @key[constant] Dispatching_Domain;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Create} (First, Last : CPU) @key[return] Dispatching_Domain;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Get_First_CPU} (Domain : Dispatching_Domain) @key[return] CPU;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Get_Last_CPU} (Domain : Dispatching_Domain) @key[return] CPU;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Get_Dispatching_Domain} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key[return] Dispatching_Domain;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Assign_Task} (Domain : @key[in out] Dispatching_Domain; CPU : @key[in] CPU_Range := Not_A_Specific_CPU; T : @key[in] Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Set_CPU} (CPU : @key[in] CPU_Range; T : @key[in] Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Get_CPU} (T : Ada.Task_Identification.Task_Id := Ada.Task_Identification.Current_Task) @key[return] CPU_Range;]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[ @key[procedure] @AdaSubDefn{Delay_Until_And_Set_CPU} (Delay_Until_Time : @key[in] Ada.Real_Time.Time; CPU : @key[in] CPU_Range);]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[@key[private] ... -- @RI[not specified by the language] @key[end] System.Multiprocessors.Dispatching_Domains;]} @end{Example} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The type Dispatching_Domain represents a series of processors on which a task may execute. Each processor is contained within exactly one Dispatching_Domain. System_Dispatching_Domain contains the processor or processors on which the environment task executes. At program start-up all processors are contained within System_Dispatching_Domain.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a task type (including the anonymous type of a @nt{single_task_declaration}), the following language-defined representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Dispatching_Domain@\The value of aspect Dispatching_Domain is an @nt{expression}, which shall be of type Dispatching_Domains.Dispatching_Domain. This aspect is the domain to which the task (or all objects of the task type) are assigned.@AspectDefn{Dispatching_Domain}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Dispatching_Domain], Text=[@ChgAdded{Version=[3],Text=[Domain (group of processors) on which a given task should run.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The Dispatching_Domain aspect shall not be specified for a task interface.]} @end{Legality} @begin{Runtime} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The expression specified for the Dispatching_Domain aspect of a task is evaluated for each task object (see @RefSecNum{Task Units and Task Objects}). The Dispatching_Domain value is then associated with the task object whose task declaration specifies the aspect.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[If a task is not explicitly assigned to any domain, it is assigned to that of the activating task. A task always executes on some CPU in its domain.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[If both Dispatching_Domain and CPU are specified for a task, and the CPU value is not contained within the range of processors for the domain (and is not Not_A_Specific_CPU), the activation of the task is defined to have failed, and it becomes a completed task (see @RefSecNum{Task Execution - Task Activation}).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The function Create creates and returns a Dispatching_Domain containing all the processors in the range First .. Last. These processors are removed from System_Dispatching_Domain. A call of Create will raise Dispatching_Domain_Error if any designated processor is not currently in System_Dispatching_Domain, or if the system cannot support a distinct domain over the processors identified, or if a processor has a task assigned to it, or if the allocation would leave System_Dispatching_Domain empty. A call of Create will raise Dispatching_Domain_Error if the calling task is not the environment task, or if Create is called after the call to the main subprogram.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The function Get_First_CPU returns the first CPU in Domain; Get_Last_CPU returns the last one.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The function Get_Dispatching_Domain returns the Dispatching_Domain on which the task is assigned.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1],ARef=[AI05-0278-1]} @ChgAdded{Version=[3],Text=[A call of the procedure Assign_Task assigns task T to the CPU within Dispatching_Domain Domain. Task T can now execute only on CPU unless CPU designates Not_A_Specific_CPU, in which case it can execute on any processor within Domain. The exception Dispatching_Domain_Error is propagated if T is already assigned to a Dispatching_Domain other than System_Dispatching_Domain, or if CPU is not one of the processors of Domain (and is not Not_A_Specific_CPU). A call of Assign_Task is a task dispatching point for task T unless T is inside of a protected action, in which case the effect on task T is delayed until its next task dispatching point. If T is the Current_Task the effect is immediate if T is not inside a protected action, otherwise the effect is as soon as practical. Assigning a task to System_Dispatching_Domain that is already assigned to that domain has no effect.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1],ARef=[AI05-0278-1]} @ChgAdded{Version=[3],Text=[A call of procedure Set_CPU assigns task T to the CPU. Task T can now execute only on CPU, unless CPU designates Not_A_Specific_CPU, in which case it can execute on any processor within its Dispatching_Domain. The exception Dispatching_Domain_Error is propagated if CPU is not one of the processors of the Dispatching_Domain on which T is assigned (and is not Not_A_Specific_CPU). A call of Set_CPU is a task dispatching point for task T unless T is inside of a protected action, in which case the effect on task T is delayed until its next task dispatching point. If T is the Current_Task the effect is immediate if T is not inside a protected action, otherwise the effect is as soon as practical.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The function Get_CPU returns the processor assigned to task T, or Not_A_Specific_CPU if the task is not assigned to a processor.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[A call of Delay_Until_And_Set_CPU delays the calling task for the designated time and then assigns the task to the specified processor when the delay expires. The exception Dispatching_Domain_Error is propagated if P is not one of the processors of the calling task's Dispatching_Domain (and is not Not_A_Specific_CPU).]} @end{Runtime} @begin{ImplReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The implementation shall perform the operations Assign_Task, Set_CPU, Get_CPU and Delay_Until_And_Set_CPU atomically with respect to any of these operations on the same dispatching_domain, processor or task.]} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[Each dispatching domain should have separate and disjoint ready queues.]} @ChgImplAdvice{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[Each dispatching domain should have separate and disjoint ready queues.]}]} @end{ImplAdvice} @begin{DocReq} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[The implementation shall document the processor(s) on which the clock interrupt is handled and hence where delay queue and ready queue manipulations occur. For any Interrupt_Id whose handler can execute on more than one processor the implementation shall also document this set of processors.]} @ChgDocReq{Version=[3],Kind=[AddedNormal],Text=[@ChgAdded{Version=[3], Text=[The processor(s) on which the clock interrupt is handled; the processors on which each Interrupt_Id can be handled.]}]} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[An implementation may limit the number of dispatching domains that can be created and raise Dispatching_Domain_Error if an attempt is made to exceed this number.]} @end{ImplPerm} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1],ARef=[AI05-0278-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} The package System.Multiprocessors.Dispatching_Domains and the aspect Dispatching_Domains are new.]} @end{Extend2005} ����������������������������������������org.adaic.arm_form/source_2012/safety.mss�����������������������������������������������������������0000755�0001752�0001001�00000161052�12066652506�017451� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Comment{ $Source: e:\\cvsroot/ARM/Source/safety.mss,v $ } @Comment{ $Revision: 1.59 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(safety, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledRevisedNormativeAnnex{Version=[2], New=[High Integrity Systems], Old=[Safety and Security]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00347-01]} @Leading@Defn{safety-critical systems} @Defn{secure systems} This Annex addresses requirements for @Chg{Version=[2], New=[high integrity ],Old=[]}systems @Chg{Version=[2],New=[(including], Old=[that are]} safety@Chg{Version=[2],New=[-],Old=[ ]}critical @Chg{Version=[2],New=[systems and],Old=[or have]} security@Chg{Version=[2],New=[-critical systems)],Old=[ constraints]}. It provides facilities and specifies documentation requirements that relate to several needs: @begin{Itemize} Understanding program execution; Reviewing object code; Restricting language constructs whose usage might complicate the demonstration of program correctness @end{Itemize} @ChgNote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}Execution understandability is supported by pragma Normalize_Scalars, and also by requirements for the implementation to document the effect of a program in the presence of a bounded error or where the language rules leave the effect unspecified. @PDefn{unspecified} The @nt[pragma]s Reviewable and Restrictions relate to the other requirements addressed by this Annex. @end{Intro} @begin{Notes} The @attr[Valid] attribute (see @RefSecNum(The Valid Attribute)) is also useful in addressing these needs, to avoid problems that could otherwise arise from scalars that have values outside their declared range constraints. @begin{Discussion} The Annex tries to provide high assurance rather than language features. However, it is not possible, in general, to test for high assurance. For any specific language feature, it is possible to demonstrate its presence by a functional test, as in the ACVC. One can also check for the presence of some documentation requirements, but it is not easy to determine objectively that the documentation is @lquotes@;adequate@rquotes@;. @end{Discussion} @end{Notes} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[The title of this annex was changed to better reflect its purpose and scope. High integrity systems has become the standard way of identifying systems that have high reliability requirements; it subsumes terms such as safety and security. Moreover, the annex does not include any security specific features and as such the previous title is somewhat misleading.]} @end{DiffWord95} @LabeledClause{Pragma Normalize_Scalars} @begin{Intro} This pragma ensures that an otherwise uninitialized scalar object is set to a predictable value, but out of range if possible. @begin[discussion] The goal of the pragma is to reduce the impact of a bounded error that results from a reference to an uninitialized scalar object, by having such a reference violate a range check and thus raise Constraint_Error. @end[discussion] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Normalize_Scalars is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Normalize_Scalars);' @end{Syntax} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Normalize_Scalars)} @PDefn2{Term=[pragma, configuration], Sec=(Normalize_Scalars)} Pragma Normalize_Scalars is a configuration pragma. It applies to all @nt[compilation_unit]s included in a partition. @end{LinkTime} @begin{DocReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If a @nt{pragma} Normalize_Scalars applies, the implementation shall document the implicit initial @Chg{Version=[2], New=[values],Old=[value]} for scalar subtypes, and shall identify each case in which such a value is used and is not an invalid representation. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[If a @nt{pragma} Normalize_Scalars applies, the implicit initial values of scalar subtypes shall be documented. Such a value should be an invalid representation when possible; any cases when is it not shall be documented.]}]} @begin{Honest} It's slightly inaccurate to say that the value is a representation, but the point should be clear anyway. @end{Honest} @begin{Discussion} By providing a type with a size specification so that spare bits are present, it is possible to force an implementation of Normalize_Scalars to use an out of range value. This can be tested for by ensuring that Constraint_Error is raised. Similarly, for an unconstrained integer type, in which no spare bit is surely present, one can check that the initialization takes place to the value specified in the documentation of the implementation. For a floating point type, spare bits might not be available, but a range constraint can provide the ability to use an out of range value. If it is difficult to document the general rule for the implicit initial value, the implementation might choose instead to record the value on the object code listing or similar output produced during compilation. @end{Discussion} @end{DocReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Whenever possible, the implicit initial @Chg{Version=[2], New=[values],Old=[value]} for a scalar subtype should be an invalid representation (see @RefSecNum{Data Validity}). @begin{Discussion} When an out of range value is used for the initialization, it is likely that constraint checks will detect it. In addition, it can be detected by the Valid attribute. @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This rule is included in the documentation requirements, and thus does not need a separate summary item.]} @end{Discussion} @end{ImplAdvice} @begin{Notes} The initialization requirement applies to uninitialized scalar objects that are subcomponents of composite objects, to allocated objects, and to stand-alone objects. It also applies to scalar @key{out} parameters. Scalar subcomponents of composite @key{out} parameters are initialized to the corresponding part of the actual, by virtue of @RefSecNum(Parameter Associations). The initialization requirement does not apply to a scalar for which pragma Import has been specified, since initialization of an imported object is performed solely by the foreign language environment (see @RefSecNum[Interfacing Aspects]). The use of pragma Normalize_Scalars in conjunction with Pragma Restrictions(No_Exceptions) may result in erroneous execution (see @RefSecNum[High Integrity Restrictions]). @begin{Discussion} Since the effect of an access to an out of range value will often be to raise Constraint_Error, it is clear that suppressing the exception mechanism could result in erroneous execution. In particular, the assignment to an array, with the array index out of range, will result in a write to an arbitrary store location, having unpredictable effects. @end{Discussion} @end{Notes} @LabeledClause{Documentation of Implementation Decisions} @begin{DocReq} @PDefn{unspecified} The implementation shall document the range of effects for each situation that the language rules identify as either a bounded error or as having an unspecified effect. If the implementation can constrain the effects of erroneous execution for a given construct, then it shall document such constraints. @Redundant[The documentation might be provided either independently of any compilation unit or partition, or as part of an annotated listing for a given unit or partition. See also @RefSecNum(Conformity of an Implementation with the Standard), and @RefSecNum(Structure).] @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Information regarding bounded errors and erroneous execution.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ The range of effects for each bounded error and each unspecified effect. If the effects of a given erroneous construct are constrained, the constraints shall be documented.]}]} @end{DocReq} @begin{Notes} Among the situations to be documented are the conventions chosen for parameter passing, the methods used for the management of run-time storage, and the method used to evaluate numeric expressions if this involves extended range or extra precision. @begin{Discussion} Look up @lquotes@;unspecified@rquotes@; and @lquotes@;erroneous execution@rquotes@; in the index for a list of the cases. The management of run-time storage is particularly important. For safety applications, it is often necessary to show that a program cannot raise Storage_Error, and for security applications that information cannot leak via the run-time system. Users are likely to prefer a simple storage model that can be easily validated. The documentation could helpfully take into account that users may well adopt a subset to avoid some forms of erroneous execution, for instance, not using the abort statement, so that the effects of a partly completed @nt{assignment_statement} do not have to be considered in the validation of a program (see @RefSecNum{Abort of a Task - Abort of a Sequence of Statements}). For this reason documentation linked to an actual compilation may be most useful. Similarly, an implementation may be able to take into account use of the Restrictions pragma. @end{Discussion} @end{Notes} @LabeledClause{Reviewable Object Code} @begin{Intro} Object code review and validation are supported by pragmas Reviewable and Inspection_Point. @end{Intro} @LabeledSubClause{Pragma Reviewable} @begin{Intro} This pragma directs the implementation to provide information to facilitate analysis and review of a program's object code, in particular to allow determination of execution time and storage usage and to identify the correspondence between the source and object programs. @begin{Discussion} Since the purpose of this pragma is to provide information to the user, it is hard to objectively test for conformity. In practice, users want the information in an easily understood and convenient form, but neither of these properties can be easily measured. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Reviewable is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Reviewable);' @end{Syntax} @begin{LinkTime} @PDefn2{Term=[configuration pragma], Sec=(Reviewable)} @PDefn2{Term=[pragma, configuration], Sec=(Reviewable)} Pragma Reviewable is a configuration pragma. It applies to all @nt[compilation_unit]s included in a partition. @end{LinkTime} @begin{ImplReq} @Leading@;The implementation shall provide the following information for any compilation unit to which such a pragma applies: @begin{Discussion} The list of requirements can be checked for, even if issues like intelligibility are not addressed. @end{Discussion} @begin{itemize} Where compiler-generated run-time checks remain; @begin{Discussion} A constraint check which is implemented via a check on the upper and lower bound should clearly be indicated. If a check is implicit in the form of machine instructions used (such an overflow checking), this should also be covered by the documentation. It is particularly important to cover those checks which are not obvious from the source code, such as that for stack overflow. @end{Discussion} An identification of any construct with a language-defined check that is recognized prior to run time as certain to fail if executed (even if the generation of run-time checks has been suppressed); @begin{Discussion} In this case, if the compiler determines that a check must fail, the user should be informed of this. However, since it is not in general possible to know what the compiler will detect, it is not easy to test for this. In practice, it is thought that compilers claiming conformity to this Annex will perform significant optimizations and therefore @i{will} detect such situations. Of course, such events could well indicate a programmer error. @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00209-01]} For each @Chg{Version=[2],New=[read of],Old=[reference to]} a scalar object, an identification of the @Chg{Version=[2],New=[read],Old=[reference]} as either @lquotes@;known to be initialized,@rquotes@; or @lquotes@;possibly uninitialized,@rquotes@; independent of whether pragma Normalize_Scalars applies; @begin{Discussion} This issue again raises the question as to what the compiler has determined. A lazy implementation could clearly mark all scalars as @lquotes@;possibly uninitialized@rquotes@;, but this would be very unhelpful to the user. It should be possible to analyze a range of scalar uses and note the percentage in each class. Note that an access marked @lquotes@;known to be initialized@rquotes@; does not imply that the value is in range, since the initialization could be from an (erroneous) call of unchecked conversion, or by means external to the Ada program. @end{Discussion} Where run-time support routines are implicitly invoked; @begin{Discussion} Validators will need to know the calls invoked in order to check for the correct functionality. For instance, for some safety applications, it may be necessary to ensure that certain sections of code can execute in a particular time. @end{Discussion} @Leading@Keepnext@;An object code listing, including: @begin{inneritemize} Machine instructions, with relative offsets; @begin{Discussion} The machine instructions should be in a format that is easily understood, such as the symbolic format of the assembler. The relative offsets are needed in numeric format, to check any alignment restrictions that the architecture might impose. @end{Discussion} Where each data object is stored during its lifetime; @begin{Discussion} This requirement implies that if the optimizer assigns a variable to a register, this needs to be evident. @end{Discussion} Correspondence with the source program, including an identification of the code produced per declaration and per statement. @begin{Discussion} This correspondence will be quite complex when extensive optimization is performed. In particular, address calculation to access some data structures could be moved from the actual access. However, when all the machine code arising from a statement or declaration is in one basic block, this must be indicated by the implementation. @end{Discussion} @end{inneritemize} An identification of each construct for which the implementation detects the possibility of erroneous execution; @begin{Discussion} This requirement is quite vague. In general, it is hard for compilers to detect erroneous execution and therefore the requirement will be rarely invoked. However, if the pragma Suppress is used and the compiler can show that a predefined exception will be raised, then such an identification would be useful. @end{Discussion} @Trailing@;For each subprogram, block, task, or other construct implemented by reserving and subsequently freeing an area on a run-time stack, an identification of the length of the fixed-size portion of the area and an indication of whether the non-fixed size portion is reserved on the stack or in a dynamically-managed storage region. @begin{Discussion} This requirement is vital for those requiring to show that the storage available to a program is sufficient. This is crucial in those cases in which the internal checks for stack overflow are suppressed (perhaps by @key[pragma] Restrictions(No_Exceptions)). @end{Discussion} @end{itemize} @Leading@;The implementation shall provide the following information for any partition to which the pragma applies: @begin{Itemize} An object code listing of the entire partition, including initialization and finalization code as well as run-time system components, and with an identification of those instructions and data that will be relocated at load time; @begin{Discussion} The object code listing should enable a validator to estimate upper bounds for the time taken by critical parts of a program. Similarly, by an analysis of the entire partition, it should be possible to ensure that the storage requirements are suitably bounded, assuming that the partition was written in an appropriate manner.@end{discussion} A description of the run-time model relevant to the partition. @begin{Discussion} For example, a description of the storage model is vital, since the Ada language does not explicitly define such a model. @end{Discussion} @end{itemize} @end{ImplReq} @Chgnote{The following paragraph is missing a number in the original version. To give it a number in the new version, it is marked as an insertion.} @ChgRef{Version=[0],Kind=[Added]} @Chg{New=[],Old=[@Noparanum@;]}The implementation shall provide control- and data-flow information, both within each compilation unit and across the compilation units of the partition. @begin{Discussion} This requirement is quite vague, since it is unclear what control and data flow information the compiler has produced. It is really a plea not to throw away information that could be useful to the validator. Note that the data flow information is relevant to the detection of @lquotes@;possibly uninitialized@rquotes@; objects referred to above. @end{Discussion} @begin{ImplAdvice} The implementation should provide the above information in both a human-readable and machine-readable form, and should document the latter so as to ease further processing by automated tools. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The information produced by @nt{pragma} Reviewable should be provided in both a human-readable and machine-readable form, and the latter form should be documented.]}]} Object code listings should be provided both in a symbolic format and also in an appropriate numeric format (such as hexadecimal or octal). @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Object code listings should be provided both in a symbolic format and in a numeric format.]}]} @begin{Reason} This is to enable other tools to perform any analysis that the user needed to aid validation. The format should be in some agreed form. @end{Reason} @end{ImplAdvice} @begin{Notes} The order of elaboration of library units will be documented even in the absence of @nt[pragma] Reviewable (see @RefSecNum{Program Execution}). @end{Notes} @begin[discussion] There might be some interactions between pragma Reviewable and compiler optimizations. For example, an implementation may disable some optimizations when pragma Reviewable is in force if it would be overly complicated to provide the detailed information to allow review of the optimized object code. See also @nt<pragma> Optimize (@RefSecNum{Pragmas}). @end[discussion] @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00209-01]} @ChgAdded{Version=[2],Text=[The wording was clarified that pragma Reviewable applies to each read of an object, as it makes no sense to talk about the state of an object that will immediately be overwritten.]} @end{DiffWord95} @LabeledSubClause{Pragma Inspection_Point} @begin{Intro} An occurrence of a pragma Inspection_Point identifies a set of objects each of whose values is to be available at the point(s) during program execution corresponding to the position of the pragma in the compilation unit. The purpose of such a pragma is to facilitate code validation. @begin{Discussion} Inspection points are a high level equivalent of break points used by debuggers. @end{Discussion} @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Inspection_Point is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Inspection_Point)[(@SynI{object_}@Syn2{name} {, @SynI{object_}@Syn2{name}})];' @end{Syntax} @begin{Legality} A pragma Inspection_Point is allowed wherever a @nt[declarative_item] or @nt[statement] is allowed. Each @SynI{object_}name shall statically denote the declaration of an object. @begin{Discussion} The static denotation is required, since no dynamic evaluation of a name is involved in this pragma. @end{Discussion} @end{Legality} @begin{StaticSem} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Defn{inspection point} An @i{inspection point} is a point in the object code corresponding to the occurrence of a pragma Inspection_@!Point in the compilation unit. @Defn{inspectable object} An object is @i{inspectable} at an inspection point if the corresponding pragma Inspection_Point either has an argument denoting that object, or has no arguments@Chg{New=[ and the @Chg{Version=[2],New=[declaration of the ],Old=[]}object is visible at the inspection point],Old=[]}. @begin{ramification} If a pragma Inspection_Point is in an in-lined subprogram, there might be numerous inspection points in the object code corresponding to the single occurrence of the pragma in the source; similar considerations apply if such a pragma is in a generic, or in a loop that has been @lquotes@;unrolled@rquotes@; by an optimizer. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgAdded{Version=[1],Text=[The short form of the pragma is a convenient shorthand for listing all objects which could be explicitly made inspectable by the long form of the pragma; thus only visible objects are made inspectable by it. Objects that are not visible at the point of the pragma are not made inspectable by the short form pragma. This is necessary so that implementations need not keep information about (or prevent optimizations on) a unit simply because some other unit @i<might> contain a short form Inspection_Point pragma.]} @end{ramification} @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0093],ARef=[AI95-00207-01]} If the short form of the pragma is used, then all@Chg{New=[ visible],Old=[]} objects are inspectable. This implies that @Chg{New=[global objects from other compilation units], Old=[objects out of scope at the point of the pragma]} are inspectable. A good interactive debugging system could provide information similar to a post-mortem dump at such inspection points. The annex does not require that any inspection facility is provided, merely that the information is available to understand the state of the machine at those points. @end{Discussion} @end{StaticSem} @begin{RunTime} Execution of a pragma Inspection_Point has no effect. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} Although an inspection point has no (semantic) effect, the removal or adding @Chg{Version=[2],New=[of ],Old=[]}a new point could change the machine code generated by the compiler. @end{Discussion} @end{RunTime} @begin{ImplReq} Reaching an inspection point is an external interaction with respect to the values of the inspectable objects at that point (see @RefSecNum{Conformity of an Implementation with the Standard}). @begin{Ramification} The compiler is inhibited from moving an assignment to an inspectable variable past an inspection point for that variable. On the other hand, the evaluation of an expression that might raise an exception may be moved past an inspection point (see @RefSecNum[Exceptions and Optimization]).@end{ramification} @end{ImplReq} @begin{DocReq} For each inspection point, the implementation shall identify a mapping between each inspectable object and the machine resources (such as memory locations or registers) from which the object's value can be obtained. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of pragma Inspection_Point.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For each inspection point, a mapping between each inspectable object and the machine resources where the object's value can be obtained shall be provided.]}]} @end{DocReq} @begin{Notes} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00209-01]} The implementation is not allowed to perform @lquotes@;dead store elimination@rquotes@; on the last assignment to a variable prior to a point where the variable is inspectable. Thus an inspection point has the effect of an implicit @Chg{Version=[2],New=[read of],Old=[reference to]} each of its inspectable objects. Inspection points are useful in maintaining a correspondence between the state of the program in source code terms, and the machine state during the program's execution. Assertions about the values of program objects can be tested in machine terms at inspection points. Object code between inspection points can be processed by automated tools to verify programs mechanically. @begin{Discussion} Although it is not a requirement of the annex, it would be useful if the state of the stack and heap could be interrogated. This would allow users to check that a program did not have a `storage leak'. @end{Discussion} The identification of the mapping from source program objects to machine resources is allowed to be in the form of an annotated object listing, in human-readable or tool-processable form. @begin{Discussion} In principle, it is easy to check an implementation for this pragma, since one merely needs to check the content of objects against those values known from the source listing. In practice, one needs a tool similar to an interactive debugger to perform the check. @end{Discussion} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0093],ARef=[AI95-00207-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the definition of the Inspection_Point pragma to apply to only variables visible at the point of the pragma. Otherwise, the compiler would have to assume that some other code somewhere could have a pragma Inspection_Point, preventing many optimizations (such as unused object elimination).]} @end{DiffWord95} @LabeledRevisedClause{Version=[2],New=[High Integrity Restrictions],Old=[Safety and Security Restrictions]} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} defines restrictions that can be used with pragma Restrictions (see @RefSecNum(Pragma Restrictions and Pragma Profile)); these facilitate the demonstration of program correctness by allowing tailored versions of the run-time system. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} Note that the restrictions are absolute. If a partition has 100 library units and just one needs Unchecked_Conversion, then the pragma cannot be used to ensure the other 99 units do not use Unchecked_Conversion. Note also that these are restrictions on all Ada code within a partition, and therefore it @Chg{Version=[3],New=[might],Old=[may]} not be evident from the specification of a package whether a restriction can be imposed. @end{Discussion} @end{Intro} @begin{StaticSem} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00347-01],ARef=[AI95-00394-01]} @ChgDeleted{Version=[2],Text=[The following restrictions, the same as in @RefSecNum{Tasking Restrictions}, apply in this Annex: No_Task_@!Hierarchy, No_Abort_@!Statement, No_Implicit_@!Heap_@!Allocation, Max_@!Task_@!Entries is 0, Max_@!Asynchronous_@!Select_@!Nesting is 0, and Max_@!Tasks is 0. @redundant[The last three restrictions are checked prior to program execution.]]} @Trailing@ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00394-01]} The following @Chg{Version=[2],New=[@SynI{restriction_}@nt{identifier}s are language defined:],Old=[additional restrictions apply in this Annex.]} @leading@keepnext@b{Tasking-related restriction:} @begin{Description} @Trailing@;@Defn2{Term=[restrictions],Sec=(No_Protected_Types)}@Chg{Version=[3],New=[@Defn{No_Protected_Types restriction}], Old=[]}No_Protected_Types @\There are no declarations of protected types or protected objects. @end{Description} @leading@keepnext@b{Memory-management related restrictions:} @begin{Description} @Defn2{Term=[restrictions],Sec=(No_Allocators)}@Chg{Version=[3],New=[@Defn{No_Allocators restriction}], Old=[]}No_Allocators @\There are no occurrences of an @nt{allocator}. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0042],ARef=[AI95-00130]} @Defn2{Term=[restrictions],Sec=(No_Local_Allocators)}@Chg{Version=[3],New=[@Defn{No_Local_Allocators restriction}], Old=[]}No_Local_Allocators @\@nt{Allocator}s are prohibited in subprograms, generic subprograms, tasks, and entry bodies@Chg{New=[],Old=[; instantiations of generic packages are also prohibited in these contexts]}. @begin[Ramification] Thus @nt{allocator}s are permitted only in expressions whose evaluation can only be performed before the main subprogram is invoked. @end[Ramification] @begin[Reason] @ChgRef{Version=[1],Kind=[Deleted],Ref=[8652/0042],ARef=[AI95-00130]} @ChgNote{The associated rule has been deleted.} @ChgDeleted{Version=[1],Text=[The reason for the prohibition against instantiations of generic packages is to avoid contract model violations. An alternative would be to prohibit @nt{allocator}s from generic packages, but it seems preferable to allow generality on the defining side and then place the restrictions on the usage (instantiation), rather than inhibiting what can be in the generic while liberalizing where they can be instantiated.]} @end[Reason] @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0152-1],ARef=[AI05-0262-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions],Sec=(No_Anonymous_Allocators)}@Defn{No_Anonymous_Allocators restriction} No_Anonymous_Allocators @\There are no @nt{allocator}s of anonymous access types.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions],Sec=(No_Coextensions)}@Defn{No_Coextensions restriction} No_Coextensions @\There are no coextensions. See @RefSecNum{Operations of Access Types}.]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Defn2{Term=[restrictions], Sec=(No_Access_Parameter_Allocators)}@Defn{No_Access_Parameter_Allocators restriction} No_Access_Parameter_Allocators @\@nt{Allocator}s are not permitted as the actual parameter to an access parameter. See @RefSecNum{Subprogram Declarations}.]} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00394-01]} @Comment{We can't reuse this paragraph for the above, because there is no way to have the hanging marker in both the added and deleted text (and since it isn't in Ada 2005 at all).} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(No_Unchecked_Deallocation)}No_Unchecked_Deallocation @\Semantic dependence on Unchecked_Deallocation is not allowed.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[This restriction would be useful in those contexts in which heap storage is needed on program start-up, but need not be increased subsequently. The danger of a dangling pointer can therefore be avoided.]} @end{Discussion} @Trailing@;Immediate_Reclamation @\Except for storage occupied by objects created by @nt{allocator}s and not deallocated via unchecked deallocation, any storage reserved at run time for an object is immediately reclaimed when the object no longer exists. @Defn2{Term=[restrictions],Sec=(Immediate_Reclamation)}@Chg{Version=[3],New=[@Defn{Immediate_Reclamation restriction}], Old=[]} @begin{Discussion} Immediate reclamation would apply to storage created by the compiler, such as for a return value from a function whose size is not known at the call site. @end{Discussion} @end{Description} @leading@keepnext@b{Exception-related restriction:} @begin{Description} @Trailing@Defn2{Term=[restrictions],Sec=(No_Exceptions)}@Chg{Version=[3],New=[@Defn{No_Exceptions restriction}], Old=[]}No_Exceptions @\@nt{Raise_statement}s and @nt{exception_handler}s are not allowed. No language-defined run-time checks are generated; however, a run-time check performed automatically by the hardware is permitted. @begin{Discussion} This restriction mirrors a method of working that is quite common in the safety area. The programmer is required to show that exceptions cannot be raised. Then a simplified run-time system is used without exception handling. However, some hardware checks may still be enforced. If the software check would have failed, or if the hardware check actually fails, then the execution of the program is unpredictable. There are obvious dangers in this approach, but it is similar to programming at the assembler level. @end{Discussion} @end{Description} @leading@keepnext@b{Other restrictions:} @begin{Description} @Defn2{Term=[restrictions],Sec=(No_Floating_Point)}@Chg{Version=[3],New=[@Defn{No_Floating_Point restriction}], Old=[]}No_Floating_Point @\Uses of predefined floating point types and operations, and declarations of new floating point types, are not allowed. @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The intention is to avoid the use of floating point hardware at run time, but this is expressed in language terms. It is conceivable that floating point is used implicitly in some contexts, say fixed point type conversions of high accuracy. However, the @ImplReqTitle below make it clear that the restriction would apply to the @lquotes@;run-time system@rquotes@; and hence not be allowed. This @Chg{Version=[2],New=[restriction],Old=[parameter]} could be used to inform a compiler that a variant of the architecture is being used which does not have floating point instructions. @end{Discussion} @Defn2{Term=[restrictions],Sec=(No_Fixed_Point)}@Chg{Version=[3],New=[@Defn{No_Fixed_Point restriction}], Old=[]}No_Fixed_Point @\Uses of predefined fixed point types and operations, and declarations of new fixed point types, are not allowed. @begin{Discussion} This restriction would have the side effect of prohibiting the @nt{delay_relative_statement}. As with the No_Floating_Point restriction, this might be used to avoid any question of rounding errors. Unless an Ada run-time is written in Ada, it seems hard to rule out implicit use of fixed point, since at the machine level, fixed point is virtually the same as integer arithmetic. @end{Discussion} @ChgRef{Version=[2],Kind=[Deleted],ARef=[AI95-00394-01]} @ChgDeleted{Version=[2],Text=[@Defn2{Term=[restrictions], Sec=(No_Unchecked_Conversion)}No_Unchecked_Conversion @\Semantic dependence on the predefined generic Unchecked_Conversion is not allowed.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[DeletedNoDelMsg]} @ChgDeleted{Version=[2],Text=[Most critical applications would require some restrictions or additional validation checks on uses of unchecked conversion. If the application does not require the functionality, then this restriction provides a means of ensuring the design requirement has been satisfied. The same applies to several of the following restrictions.]} @end{Discussion} No_Access_Subprograms @\The declaration of access-to-subprogram types is not allowed. @Defn2{Term=[restrictions],Sec=(No_Access_Subprograms)}@Chg{Version=[3],New=[@Defn{No_Access_Subprograms restriction}], Old=[]} @begin{Discussion}@ChgNote{Moved from above} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Most critical applications would require some restrictions or additional validation checks on uses of access-to-subprogram types. If the application does not require the functionality, then this restriction provides a means of ensuring the design requirement has been satisfied. The same applies to several of the following restrictions, and to restriction No_Dependence => Ada.Unchecked_Conversion.]} @end{Discussion} @Defn2{Term=[restrictions],Sec=(No_Unchecked_Access)}@Chg{Version=[3],New=[@Defn{No_Unchecked_Access restriction}], Old=[]}No_Unchecked_Access @\The @attr[Unchecked_Access] attribute is not allowed. @Defn2{Term=[restrictions],Sec=(No_Dispatch)}@Chg{Version=[3],New=[@Defn{No_Dispatch restriction}], Old=[]}No_Dispatch @\Occurrences of T'Class are not allowed, for any (tagged) subtype T. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} @Defn2{Term=[restrictions],Sec=(No_IO)}@Chg{Version=[3],New=[@Defn{No_IO restriction}], Old=[]}No_IO @\Semantic dependence on any of the library units Sequential_IO, Direct_IO, Text_IO, Wide_Text_IO, @Chg{Version=[2], New=[Wide_Wide_Text_IO, ],Old=[]}or Stream_IO is not allowed. @begin{Discussion} Excluding the input-output facilities of an implementation may be needed in those environments which cannot support the supplied functionality. A program in such an environment is likely to require some low level facilities or a call on a non-Ada feature. @end{Discussion} @Defn2{Term=[restrictions],Sec=(No_Delay)}@Chg{Version=[3],New=[@Defn{No_Delay restriction}], Old=[]}No_Delay @\@nt[Delay_Statement]s and semantic dependence on package Calendar are not allowed. @begin[Ramification] This implies that @nt[delay_alternative]s in a @nt[select_statement] are prohibited. The purpose of this restriction is to avoid the need for timing facilities within the run-time system. @end[ramification] @Defn2{Term=[restrictions],Sec=(No_Recursion)}@Chg{Version=[3],New=[@Defn{No_Recursion restriction}], Old=[]}No_Recursion @\As part of the execution of a subprogram, the same subprogram is not invoked. @Defn2{Term=[restrictions],Sec=(No_Reentrancy)}@Chg{Version=[3],New=[@Defn{No_Reentrancy restriction}], Old=[]}No_Reentrancy @\During the execution of a subprogram by a task, no other task invokes the same subprogram. @end{description} @end{StaticSem} @begin{ImplReq} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[An implementation of this Annex shall support:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[the restrictions defined in this subclause; and]} @ChgRef{Version=[2],Kind=[Added]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0189-1]} @ChgAdded{Version=[2],Text=[the following restrictions defined in @RefSecNum{Tasking Restrictions}: No_Task_Hierarchy, No_Abort_Statement, No_Implicit_Heap_Allocation@Chg{Version=[3],New=[, No_Standard_Allocators_After_Elaboration], Old=[]}; and]} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[the @key{pragma} Profile(Ravenscar); and]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgAdded{Version=[2],Text=[The reference to pragma Profile(Ravenscar) is intended to show that properly restricted tasking is appropriate for use in high integrity systems. The Ada 95 Annex seemed to suggest that tasking was inappropriate for such systems.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Type=[Leading],Text=[the following uses of @SynI{restriction_parameter_}@nt{identifier}s defined in @RefSecNum{Tasking Restrictions}@Redundant[, which are checked prior to program execution]:]} @begin{InnerItemize} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Task_Entries => 0,]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Asynchronous_Select_Nesting => 0, and]} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[Max_Tasks => 0.]} @end{InnerItemize} @end{Itemize} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0263-1],ARef=[AI05-0272-1]} If an implementation supports @nt[pragma] Restrictions for a particular argument, then except for the restrictions No_Unchecked_Deallocation, No_Unchecked_Conversion, No_Access_Subprograms, @Chg{Version=[3],New=[],Old=[and ]}No_Unchecked_Access, @Chg{Version=[3],New=[No_Specification_of_Aspect, No_Use_of_Attribute, No_Use_of_Pragma, and the equivalent use of No_Dependence, ],Old=[]}the associated restriction applies to the run-time system. @begin[reason] Permission is granted for the run-time system to use the specified otherwise-restricted features, since the use of these features may simplify the run-time system by allowing more of it to be written in Ada. @end[reason] @begin{Discussion} The restrictions that are applied to the partition are also applied to the run-time system. For example, if No_Floating_Point is specified, then an implementation that uses floating point for implementing the delay statement (say) would require that No_Floating_Point is only used in conjunction with No_Delay. It is clearly important that restrictions are effective so that Max_Tasks=0 does imply that tasking is not used, even implicitly (for input-output, say). An implementation of tasking could be produced based upon a run-time system written in Ada in which the rendezvous was controlled by protected types. In this case, No_Protected_Types could only be used in conjunction with Max_Task_Entries=0. Other implementation dependencies could be envisaged. If the run-time system is not written in Ada, then the wording needs to be applied in an appropriate fashion. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0263-1]} @ChgAdded{Version=[3],Text=["the equivalent use of No_Dependence" refers to @exam{No_Dependence => Ada.Unchecked_Conversion} and the like, not all uses of No_Dependence.]} @end{Discussion} @end{ImplReq} @begin{DocReq} If a pragma Restrictions(No_Exceptions) is specified, the implementation shall document the effects of all constructs where language-defined checks are still performed automatically (for example, an overflow check performed by the processor). @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of pragma Restrictions.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2],Text=[ If a pragma Restrictions(No_Exceptions) is specified, the effects of all constructs where language-defined checks are still performed.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The documentation requirements here are quite difficult to satisfy. One method is to review the object code generated and determine the checks that are still present, either explicitly, or implicitly within the architecture. As another example from that of overflow, consider the question of @Chg{Version=[2],New=[dereferencing],Old=[deferencing]} a null pointer. This could be undertaken by a memory access trap when checks are performed. When checks are suppressed via the argument No_Exceptions, it would not be necessary to have the memory access trap mechanism enabled. @end{Discussion} @end{DocReq} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if pragma Restrictions(No_Exceptions) has been specified and the conditions arise under which a generated language-defined run-time check would fail. @begin{Discussion} The situation here is very similar to the application of pragma Suppress. Since users are removing some of the protection the language provides, they had better be careful! @end{Discussion} @PDefn2{Term=(erroneous execution),Sec=(cause)} Program execution is erroneous if pragma Restrictions(No_Recursion) has been specified and a subprogram is invoked as part of its own execution, or if pragma Restrictions(No_Reentrancy) has been specified and during the execution of a subprogram by a task, another task invokes the same subprogram. @begin{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0005-1]} In practice, many implementations @Chg{Version=[3],New=[might],Old=[may]} not exploit the absence of recursion or need for reentrancy, in which case the program execution would be unaffected by the use of recursion or reentrancy, even though the program is still formally erroneous. @end{Discussion} @end{Erron} @ChgNote{I can't find any reason in the normative wording for this item; therefore I've removed it. The notes below (commented out anyway) refer only to a nonstandard mode, which is irrelevant in the Standard.} @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Any restrictions on pragma Restrictions.]}]} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Uses of @Syni{restriction_parameter_}@nt{identifier} No_Dependence defined in @RefSecNum{Language-Defined Restrictions and Profiles}: No_Dependence => Ada.@!Unchecked_@!Deallocation and No_Dependence => Ada.@!Unchecked_@!Conversion may be appropriate for high-integrity systems. Other uses of No_Dependence can also be appropriate for high-integrity systems.]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The specific mention of these two uses is meant to replace the identifiers now banished to @RefSec{Dependence Restriction Identifiers}.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence => Ada.Unchecked_Deallocation would be useful in those contexts in which heap storage is needed on program start-up, but need not be increased subsequently. The danger of a dangling pointer can therefore be avoided.]}@ChgNote{Moved down from above.} @end{Discussion} @end{Notes} @begin{comment} @begin{Notes} The standard mode for pragma Restrictions is that a compilation unit (or a partition if at link time) is illegal if it makes use of a feature identified in the pragma. However, an implementation is allowed to have a mode of operation where it issues a warning message versus rejecting the unit or partition, and where the run-time system supplied for the partition includes support for the identified feature. An implementation need not independently support the restrictions identified above, but may instead require that if a particular restriction is identified in a @nt(pragma) Restrictions, then other restrictions (the exact set of which is implementation defined) need also to be identified. In such a case, if the additional restrictions are not specified in a @nt(pragma) Restrictions, and a unit or partition uses such a feature, the implementation should @begin{itemize} issue a warning that the pragma is being ignored (that is, the full RTS is being used), identify to the user the additional restrictions that need to be specified in the pragma in order to obtain the reduced RTS, and identify any constructs that would use any of the features so proscribed @end{itemize} @end{Notes} @end{comment} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0042],ARef=[AI95-00130-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} No_Local_Allocators no longer prohibits generic instantiations.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01]} @ChgAdded{Version=[2],Text=[Wide_Wide_Text_IO (which is new) is added to the No_IO restriction.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00347-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The title of this @Chg{Version=[3],New=[subclause],Old=[clause]} was changed to match the change to the Annex title. Pragma Profile(Ravenscar) is part of this annex.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[Restriction No_Dependence is used instead of special @i<restriction_>@nt<identifier>s. The old names are banished to Obsolescent Features (see @RefSecNum{Dependence Restriction Identifiers}).]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00394-01]} @ChgAdded{Version=[2],Text=[The bizarre wording @lquotes@;apply in this Annex@rquotes (which no one quite can explain the meaning of) is banished.]} @end{DiffWord95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0152-1],ARef=[AI05-0190-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 95}Restrictions No_Anonymous_Allocators, No_Coextensions, and No_Access_Parameter_Allocators are new.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[New restriction No_Standard_Allocators_After_Elaboration is added to the list of restrictions that are required by this annex.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0263-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Ada 2005 restriction No_Dependence is added where needed (this was missed in Ada 2005).]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0272-1]} @ChgAdded{Version=[3],Text=[Restrictions against individual aspects, pragmas, and attributes do not apply to the run-time system, in order that an implementation can use whatever aspects, pragmas, and attributes are needed to do the job. For instance, attempting to write a run-time system for Linux that does not use the Import aspect would be very difficult and probably is not what the user is trying to prevent anyway.]} @end{DiffWord2005} @LabeledAddedClause{Version=[2],Name=[Pragma Detect_Blocking]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[The following @nt{pragma} forces an implementation to detect potentially blocking operations within a protected operation.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Detect_Blocking is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[2],@ChgAdded{Version=[2], Text=[@key{pragma} @prag<Detect_Blocking>;]}> @end{Syntax} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Detect_Blocking)} @PDefn2{Term=[pragma, configuration], Sec=(Detect_Blocking)} A @nt{pragma} Detect_Blocking is a configuration pragma.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An implementation is required to detect a potentially blocking operation within a protected operation, and to raise Program_Error (see @RefSecNum{Protected Subprograms and Protected Actions}).]} @end{RunTime} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An implementation is allowed to reject a @nt{compilation_unit} if a potentially blocking operation is present directly within an @nt{entry_body} or the body of a protected subprogram.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[An operation that causes a task to be blocked within a foreign language domain is not defined to be potentially blocking, and need not be detected.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00305-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Pragma Detect_Blocking is new.]} @end{Extend95} @RMNewPageVer{Version=[2]}@Comment{For printed version of Ada 2005 RM} @LabeledAddedClause{Version=[2],Name=[Pragma Partition_Elaboration_Policy]} @begin{Intro} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[This @Chg{Version=[3],New=[subclause],Old=[clause]} defines a @nt{pragma} for user control over elaboration policy.]} @end{Intro} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Type=[Leading],Keepnext=[T],Text=[The form of a @nt{pragma} Partition_Elaboration_Policy is as follows:]} @end{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @AddedPragmaSyn<Version=[2],@ChgAdded{Version=[2], Text=[@key{pragma} @prag<Partition_Elaboration_Policy> (@SynI<policy_>@Syn2<identifier>);]}> @begin{SyntaxText} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The @SynI<policy_>@nt{identifier} shall be either Sequential, Concurrent or an implementation-defined identifier.]} @ChgImplDef{Version=[2],Kind=[AddedNormal],Text=[@Chg{Version=[2],New=[Implementation-defined @SynI<policy_>@nt<identifier>s allowed in a @nt{pragma} Partition_Elaboration_Policy.],Old=[]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Note that the Ravenscar profile (see @RefSecNum{The Ravenscar Profile}) has nothing to say about which Partition_Elaboration_Policy is used. This was intentionally omitted from the profile, as there was no agreement as to whether the Sequential policy should be required for Ravenscar programs. As such it was defined separately.]} @end{Ramification} @end{SyntaxText} @end{Syntax} @begin{LinkTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[@PDefn2{Term=[configuration pragma], Sec=(Partition_Elaboration_Policy)} @PDefn2{Term=[pragma, configuration], Sec=(Partition_Elaboration_Policy)} A @nt{pragma} Partition_Elaboration_Policy is a configuration pragma. It specifies the elaboration policy for a partition. At most one elaboration policy shall be specified for a partition.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the Sequential policy is specified for a partition@Chg{Version=[3],New=[,],Old=[]} then pragma Restrictions (No_Task_Hierarchy) shall also be specified for the partition.]} @end{LinkTime} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgAdded{Version=[2],Text=[Notwithstanding@Defn{notwithstanding} what this International Standard says elsewhere, this @nt{pragma} allows partition elaboration rules concerning task activation and interrupt attachment to be changed. If the @SynI{policy_}@nt{identifier} is Concurrent, or if there is no pragma Partition_Elaboration_Policy defined for the partition, then the rules defined elsewhere in this Standard apply.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Type=[Leading],Text=[If the partition elaboration policy is Sequential, then task activation and interrupt attachment are performed in the following sequence of steps:]} @begin{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The activation of all library-level tasks and the attachment of interrupt handlers are deferred until all library units are elaborated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The interrupt handlers are attached by the environment task.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task is suspended while the library-level tasks are activated.]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The environment task executes the main subprogram (if any) concurrently with these executing tasks.]} @end{Itemize} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If several dynamic interrupt handler attachments for the same interrupt are deferred, then the most recent call of Attach_Handler or Exchange_Handler determines which handler is attached.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If any deferred task activation fails, Tasking_Error is raised at the beginning of the sequence of statements of the body of the environment task prior to calling the main subprogram.]} @end{RunTime} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the partition elaboration policy is Sequential and the Environment task becomes permanently blocked during elaboration@Chg{Version=[3],New=[,],Old=[]} then the partition is deadlocked and it is recommended that the partition be immediately terminated.]} @ChgImplAdvice{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[If the partition elaboration policy is Sequential and the Environment task becomes permanently blocked during elaboration@Chg{Version=[3],New=[,],Old=[]} then the partition should be immediately terminated.]}]} @end{ImplAdvice} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[If the partition elaboration policy is Sequential and any task activation fails@Chg{Version=[3],New=[,],Old=[]} then an implementation may immediately terminate the active partition to mitigate the hazard posed by continuing to execute with a subset of the tasks being active.]} @end{ImplPerm} @begin{Notes} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[If any deferred task activation fails, the environment task is unable to handle the Tasking_Error exception and completes immediately. By contrast, if the partition elaboration policy is Concurrent, then this exception could be handled within a library unit.]} @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00265-01],ARef=[AI95-00421-01]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} @nt{Pragma} Partition_Elaboration_Policy is new.]} @end{Extend95} ��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/sp.mss���������������������������������������������������������������0000755�0001752�0001001�00000344546�12066652506�016613� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@comment{ $Source: e:\\cvsroot/ARM/Source/sp.mss,v $ } @comment{ $Revision: 1.75 $ $Date: 2012/11/28 23:53:06 $ $Author: randy $ } @Part(sysprog, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledNormativeAnnex{Systems Programming} @begin{Intro} @Redundant[@Defn{systems programming} @Defn{low-level programming} @Defn{real-time systems} @Defn{embedded systems} @Defn{distributed systems} @Defn{information systems} The Systems Programming Annex specifies additional capabilities provided for low-level programming. These capabilities are also required in many real-time, embedded, distributed, and information systems.] @end{Intro} @begin{Extend83} @Defn{extensions to Ada 83} This Annex is new to Ada 95. @end{Extend83} @LabeledClause{Access to Machine Operations} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies rules regarding access to machine instructions from within an Ada program.] @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[@Chg{Version=[2], New=[Implementation-defined intrinsic subprograms], Old=[Support for access to machine instructions]}.]} @end{Intro} @begin{ImplReq} @Defn{machine code insertion} The implementation shall support machine code insertions (see @RefSecNum{Machine Code Insertions}) or intrinsic subprograms (see @RefSecNum{Conformance Rules}) (or both). Implementation-defined attributes shall be provided to allow the use of Ada entities as operands. @end{ImplReq} @begin{ImplAdvice} The machine code or intrinsics support should allow access to all operations normally available to assembly language programmers for the target environment, including privileged instructions, if any. @ChgImplAdvice{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[The machine code or intrinsics support should allow access to all operations normally available to assembly language programmers for the target environment.]}]} @begin{Ramification} Of course, on a machine with protection, an attempt to execute a privileged instruction in user mode will probably trap. Nonetheless, we want implementations to provide access to them so that Ada can be used to write systems programs that run in privileged mode. @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{interface to assembly language} @Defn2{Term=[language], Sec=(interface to assembly)} @Defn{mixed-language programs} @Defn{assembly language} The @Chg{Version=[3],New=[support for ],Old=[]}interfacing @Chg{Version=[3],New=[aspects],Old=[pragmas]} (see @RefSecNum{Interface to Other Languages}) should @Chg{Version=[3],New=[include],Old=[support]} interface to assembler; the default assembler should be associated with the convention identifier Assembler. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Interface to assembler should be supported; the default assembler should be associated with the convention identifier Assembler.]}]} If an entity is exported to assembly language, then the implementation should allocate it at an addressable location, and should ensure that it is retained by the linking process, even if not otherwise referenced from the Ada code. The implementation should assume that any call to a machine code or assembler subprogram is allowed to read or update every object that is specified as exported. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If an entity is exported to assembly language, then the implementation should allocate it at an addressable location even if not otherwise referenced from the Ada code. A call to a machine code or assembler subprogram should be treated as if it could read or update every object that is specified as exported.]}]} @end{ImplAdvice} @begin{DocReq} The implementation shall document the overhead associated with calling machine-code or intrinsic subprograms, as compared to a fully-inlined call, and to a regular out-of-line call. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The overhead of calling machine-code or intrinsic subprograms.]}]} The implementation shall document the types of the package System.Machine_Code usable for machine code insertions, and the attributes to be used in machine code insertions for references to Ada entities. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The types and attributes used in machine code insertions.]}]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The implementation shall document the subprogram calling conventions associated with the convention identifiers available for use with the @Chg{Version=[3],New=[Convention aspect],Old=[interfacing pragmas]} (Ada and Assembler, at a minimum), including register saving, exception propagation, parameter passing, and function value returning. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The subprogram calling conventions for all supported convention identifiers.]}]} For exported and imported subprograms, the implementation shall document the mapping between the Link_Name string, if specified, or the Ada designator, if not, and the external link name used for such a subprogram. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of access to machine operations.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The mapping between the Link_Name or Ada designator and the external link name.]}]} @end{DocReq} @begin{ImplAdvice} The implementation should ensure that little or no overhead is associated with calling intrinsic and machine-code subprograms. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Little or no overhead should be associated with calling intrinsic and machine-code subprograms.]}]} @Leading@;It is recommended that intrinsic subprograms be provided for convenient access to any machine operations that provide special capabilities or efficiency and that are not otherwise available through the language constructs. Examples of such instructions include: @begin{itemize} Atomic read-modify-write operations @em e.g., test and set, compare and swap, decrement and test, enqueue/dequeue. Standard numeric functions @em e.g., @i{sin}, @i{log}. String manipulation operations @em e.g., translate and test. Vector operations @em e.g., compare vector against thresholds. Direct operations on I/O ports. @end{itemize} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Intrinsic subprograms should be provided to access any machine operations that provide special capabilities or efficiency not normally available.]}]} @end{ImplAdvice} @LabeledClause{Required Representation Support} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies minimal requirements on the @Chg{Version=[2],New=[],Old=[implementation's ]}support for representation items and related features. @end{Intro} @begin{ImplReq} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @PDefn2{Term=[recommended level of support], Sec=(required in Systems Programming Annex)} The implementation shall support at least the functionality defined by the recommended levels of support in @Chg{Version=[3],New=[Clause], Old=[Section]} @RefSecNum{Representation Issues}. @end{ImplReq} @LabeledClause{Interrupt Support} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies the language-defined model for hardware interrupts in addition to mechanisms for handling interrupts.] @IndexSee{Term=[signal],See=(interrupt)} @end{Intro} @begin{RunTime} @Defn{interrupt} @Redundant[An @i{interrupt} represents a class of events that are detected by the hardware or the system software.] @Defn2{Term=[occurrence], Sec=(of an interrupt)} Interrupts are said to occur. An @i{occurrence} of an interrupt is separable into generation and delivery. @Defn2{Term=[generation], Sec=(of an interrupt)} @i{Generation} of an interrupt is the event in the underlying hardware or system that makes the interrupt available to the program. @Defn2{Term=[delivery], Sec=(of an interrupt)} @i{Delivery} is the action that invokes part of the program as response to the interrupt occurrence. @Defn{pending interrupt occurrence} Between generation and delivery, the interrupt occurrence @Redundant[(or interrupt)] is @i{pending}. @Defn{blocked interrupt} Some or all interrupts may be @i{blocked}. When an interrupt is blocked, all occurrences of that interrupt are prevented from being delivered. @Defn2{Term=[attaching], Sec=(to an interrupt)} @Defn{reserved interrupt} Certain interrupts are @i{reserved}. The set of reserved interrupts is implementation defined. A reserved interrupt is either an interrupt for which user-defined handlers are not supported, or one which already has an attached handler by some other implementation-defined means. @Defn{interrupt handler}@PDefn2{Term=[handler],Sec=[interrupt]} Program units can be connected to nonreserved interrupts. While connected, the program unit is said to be @i{attached} to that interrupt. The execution of that program unit, the @i{interrupt handler}, is invoked upon delivery of the interrupt occurrence. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of interrupts.]}]} @begin{Honest} As an obsolescent feature, interrupts may be attached to task entries by an address clause. See @RefSecNum{Interrupt Entries}. @end{Honest} While a handler is attached to an interrupt, it is called once for each delivered occurrence of that interrupt. While the handler executes, the corresponding interrupt is blocked. While an interrupt is blocked, all occurrences of that interrupt are prevented from being delivered. Whether such occurrences remain pending or are lost is implementation defined. @Defn{default treatment} Each interrupt has a @i{default treatment} which determines the system's response to an occurrence of that interrupt when no user-defined handler is attached. The set of possible default treatments is implementation defined, as is the method (if one exists) for configuring the default treatments for interrupts. An interrupt is delivered to the handler (or default treatment) that is in effect for that interrupt at the time of delivery. An exception propagated from a handler that is invoked by an interrupt has no effect. @Redundant[If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect, the interrupt handler executes with the active priority that is the ceiling priority of the corresponding protected object.] @end{RunTime} @begin{ImplReq} The implementation shall provide a mechanism to determine the minimum stack space that is needed for each interrupt handler and to reserve that space for the execution of the handler. @Redundant{This space should accommodate nested invocations of the handler where the system permits this.} If the hardware or the underlying system holds pending interrupt occurrences, the implementation shall provide for later delivery of these occurrences to the program. If the Ceiling_Locking policy is not in effect, the implementation shall provide means for the application to specify whether interrupts are to be blocked during protected actions. @end{ImplReq} @begin{DocReq} @Leading@;The implementation shall document the following items: @begin{Discussion} This information may be different for different forms of interrupt handlers. @end{Discussion} @begin{Enumerate} For each interrupt, which interrupts are blocked from delivery when a handler attached to that interrupt executes (either as a result of an interrupt delivery or of an ordinary call on a procedure of the corresponding protected object). Any interrupts that cannot be blocked, and the effect of attaching handlers to such interrupts, if this is permitted. Which run-time stack an interrupt handler uses when it executes as a result of an interrupt delivery; if this is configurable, what is the mechanism to do so; how to specify how much space to reserve on that stack. Any implementation- or hardware-specific activity that happens before a user-defined interrupt handler gets control (e.g., reading device registers, acknowledging devices). Any timing or other limitations imposed on the execution of interrupt handlers. The state (blocked/unblocked) of the nonreserved interrupts when the program starts; if some interrupts are unblocked, what is the mechanism a program can use to protect itself before it can attach the corresponding handlers. Whether the interrupted task is allowed to resume execution before the interrupt handler returns. The treatment of interrupt occurrences that are generated while the interrupt is blocked; i.e., whether one or more occurrences are held for later delivery, or all are lost. Whether predefined or implementation-defined exceptions are raised as a result of the occurrence of any interrupt, and the mapping between the machine interrupts (or traps) and the predefined exceptions. On a multi-processor, the rules governing the delivery of an interrupt to a particular processor. @end{Enumerate} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The treatment of interrupts.]}]} @ChgNote{A Bob Duff explanation, but this is just too much junk.} @end{DocReq} @begin{ImplPerm} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If the underlying system or hardware does not allow interrupts to be blocked, then no blocking is required @Redundant[as part of the execution of subprograms of a protected object @Chg{Version=[2],New=[for which],Old=[whose]} one of its subprograms is an interrupt handler]. In a multi-processor with more than one interrupt subsystem, it is implementation defined whether (and how) interrupt sources from separate subsystems share the same Interrupt_Id type (see @RefSecNum{The Package Interrupts}). In particular, the meaning of a blocked or pending interrupt may then be applicable to one processor only. @begin{discussion} This issue is tightly related to the issue of scheduling on a multi-processor. In a sense, if a particular interrupt source is not available to all processors, the system is not truly homogeneous. One way to approach this problem is to assign sub-ranges within Interrupt_Id to each interrupt subsystem, such that @lquotes@;similar@rquotes@; interrupt sources (e.g. a timer) in different subsystems get a distinct id. @end{Discussion} Implementations are allowed to impose timing or other limitations on the execution of interrupt handlers. @begin{Reason} These limitations are often necessary to ensure proper behavior of the implementation. @end{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} Other forms of handlers are allowed to be supported, in which case@Chg{Version=[2],New=[],Old=[,]} the rules of this @Chg{Version=[3],New=[subclause],Old=[@Chg{Version=[2],New=[clause],Old=[subclause]}]} should be adhered to. The active priority of the execution of an interrupt handler is allowed to vary from one occurrence of the same interrupt to another. @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} If the Ceiling_Locking policy is not in effect, the implementation should provide means for the application to specify which interrupts are to be blocked during protected actions, if the underlying system allows for @Chg{Version=[2],New=[finer-grained],Old=[a finer-grain]} control of interrupt blocking. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the Ceiling_Locking policy is not in effect and the target system allows for finer-grained control of interrupt blocking, a means for the application to specify which interrupts are to be blocked during protected actions should be provided.]}]} @end{ImplAdvice} @begin{Notes} The default treatment for an interrupt can be to keep the interrupt pending or to deliver it to an implementation-defined handler. Examples of actions that an implementation-defined handler is allowed to perform include aborting the partition, ignoring (i.e., discarding occurrences of) the interrupt, or queuing one or more occurrences of the interrupt for possible later delivery when a user-defined handler is attached to that interrupt. It is a bounded error to call Task_Identification.Current_Task (see @RefSecNum{The Package Task_Identification}) from an interrupt handler. The rule that an exception propagated from an interrupt handler has no effect is modeled after the rule about exceptions propagated out of task bodies. @end{Notes} @LabeledSubClause{Protected Procedure Handlers} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 1 through 6 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Interrupt_Handler is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Interrupt_Handler)(@SynI{handler_}@Syn2{name});]}> @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],KeepNext=[T],Text=[The form of a @nt{pragma} Attach_Handler is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Attach_Handler)(@SynI{handler_}@Syn2{name}, @Syn2{expression});]}> @end{Syntax} @begin{Resolution} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[For the Interrupt_Handler and Attach_Handler pragmas, the @SynI{handler_}@nt{name} shall resolve to denote a protected procedure with a parameterless profile.]} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[For the Attach_Handler pragma, the expected type for the @nt{expression} is Interrupts.Interrupt_Id (see @RefSecNum{The Package Interrupts}).]} @end{Resolution} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a parameterless protected procedure, the following language-defined representation aspects may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Interrupt_Handler@\ The type of aspect Interrupt_Handler is Boolean. If directly specified, the aspect_definition shall be a static expression. @Redundant[This aspect is never inherited;] if not directly specified, the aspect is False.@AspectDefn{Interrupt_Handler}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Interrupt_Handler], Text=[@ChgAdded{Version=[3],Text=[Protected procedure may be attached to interrupts.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Attach_Handler@\ The aspect Attach_Handler is an @nt{expression}, which shall be of type Interrupts.Interrupt_Id. @Redundant[This aspect is never inherited.]@AspectDefn{Attach_Handler}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Attach_Handler], Text=[@ChgAdded{Version=[3],Text=[Protected procedure is attached to an interrupt.]}]} @end{Description} @end{StaticSem} @begin{Legality} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0033-1],ARef=[AI05-0229-1]} @Chg{Version=[3],New=[If either the],Old=[The]} Attach_Handler @Chg{Version=[3],New=[or Interrupt_Handler aspect are specified for a protected procedure, the],Old=[pragma is only allowed immediately within the @nt{protected_definition} where the corresponding subprogram is declared. The]} corresponding @nt{protected_@!type_@!declaration} or @nt{single_@!protected_@!declaration} shall be a library@Chg{Version=[2],New=[-],Old=[]}level declaration@Chg{Version=[3],New=[ and shall not be declared within a generic body. @PDefn{generic contract issue}In addition to the places where @LegalityTitle normally apply (see @RefSecNum{Generic Instantiation}), this rule also applies in the private part of an instance of a generic unit],Old=[]}. @begin{Discussion} In the case of a @nt{protected_type_declaration}, an @nt{object_declaration} of an object of that type need not be at library level. @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[We cannot allow these aspects in protected declarations in a generic body, because legality rules are not checked for instance bodies, and these should not be allowed if the instance is not at the library level. The protected types can be declared in the private part if this is desired. Note that while the 'Access to use the handler would provide the check in the case of Interrupt_Handler, there is no other check for Attach_Handler. Since these aspects are so similar, we want the rules to be the same.]} @end{Discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00253-01],ARef=[AI95-00303-01]} @ChgRef{Version=[3],Kind=[Deleted],ARef=[AI05-0033-1]} @ChgDeleted{Version=[3],Text=[The Interrupt_Handler pragma is only allowed immediately within @Chg{Version=[2],New=[the],Old=[a]} @nt{protected_definition}@Chg{Version=[2],New=[ where the corresponding subprogram is declared],Old=[]}. The cor@!responding @nt{protected_@!type_declaration} @Chg{Version=[2],New=[or @nt{single_@!protected_@!declaration} ],Old=[]}shall be a library@Chg{Version=[2],New=[-],Old=[]}level declaration.@Chg{Version=[2],New=[],Old=[ In addition, any @nt{object_@!declaration} of such a type shall be a library level declaration.]}]} @end{Legality} @begin{RunTime} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If the @Chg{Version=[3],New=[],Old=[pragma ]}Interrupt_Handler @Chg{Version=[3],New=[aspect of a protected procedure is True],Old=[appears in a @nt{protected_definition}]}, then the @Chg{Version=[3],New=[],Old=[corresponding ]}procedure @Chg{Version=[3],New=[may],Old=[can]} be attached dynamically, as a handler, to interrupts (see @RefSecNum{The Package Interrupts}). @Redundant[Such procedures are allowed to be attached to multiple interrupts.] @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[creation], Sec=(of a protected object)} @Defn2{Term=[initialization], Sec=(of a protected object)} The @nt{expression} @Chg{Version=[3],New=[specified for],Old=[in]} the Attach_Handler @Chg{Version=[3],New=[aspect of a protected procedure @i<P> is evaluated as part of the creation of the protected object that contains @i<P>. The value of the @nt{expression} identifies],Old=[pragma @Redundant[as evaluated at object creation time] specifies]} an interrupt. As part of the initialization of that object, @Chg{Version=[3],New=[@i<P> (],Old=[if the Attach_Handler pragma is specified, ]}the @SynI{handler} procedure@Chg{Version=[3],New=[)],Old=[]} is attached to the @Chg{Version=[3],New=[identified],Old=[specified]} interrupt. @IndexCheck{Reserved_Check} A check is made that the corresponding interrupt is not reserved. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the check fails, and the existing treatment for the interrupt is not affected. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[initialization], Sec=(of a protected object)} @IndexCheck{Ceiling_Check} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect@Chg{Version=[2],New=[,],Old=[]} then upon the initialization of a protected object @Chg{Version=[3],New=[that contains a protected procedure ],Old=[]}@Chg{Version=[2],New=[for which],Old=[that]} either @Chg{Version=[3],New=[the],Old=[an]} Attach_Handler@Chg{Version=[3],New=[ aspect is specified],Old=[]} or @Chg{Version=[3],New=[the ],Old=[]} Interrupt_Handler @Chg{Version=[3],New=[aspect is True],Old=[pragma applies to one of its procedures]}, a check is made that the @Chg{Version=[3],New=[initial ],Old=[]}ceiling priority @Chg{Version=[3],New=[of the object],Old=[defined in the @nt{protected_definition}]} is in the range of System.@!Interrupt_Priority. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If the check fails, Program_Error is raised. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn2{Term=[finalization], Sec=(of a protected object)} When a protected object is finalized, for any of its procedures that are attached to interrupts, the handler is detached. If the handler was attached by a procedure in the Interrupts package or if no user handler was previously attached to the interrupt, the default treatment is restored. @Chg{New=[If @Chg{Version=[3],New=[the],Old=[an]} Attach_@!Handler @Chg{Version=[3],New=[aspect],Old=[pragma]} was @Chg{Version=[3],New=[specified],Old=[used]} and the most recently attached handler for the same interrupt is the same as the one that was attached at the time the protected object was initialized], Old=[Otherwise, @Redundant[that is, if an Attach_@!Handler pragma was specified]]}, the previous handler is restored. @begin{Discussion} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00303-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Chg{New=[If all protected objects for interrupt handlers are declared at the library@Chg{Version=[2],New=[ ],Old=[-]}level],Old=[Since only library-level protected procedures can be attached as handlers using the Interrupts package]}, the finalization discussed above occurs only as part of the finalization of all library-level packages in a partition. @Chg{New=[However, objects of a protected type containing @Chg{Version=[3],New=[procedures with ],Old=[]}an Attach_@!Handler @Chg{Version=[3],New=[aspect specified],Old=[pragma]} need not be at the library level. Thus, an implementation needs to be able to restore handlers during the execution of the program.@Chg{Version=[2], New=[ (An object with an Interrupt_@!Handler @Chg{Version=[3],New=[aspect],Old=[pragma]} also need not be at the library level, but such a handler cannot be attached to an interrupt using the Interrupts package.)], Old=[]}],Old=[]} @end{Discussion} When a handler is attached to an interrupt, the interrupt is blocked @Redundant[(subject to the @ImplPermName in @RefSecNum{Interrupt Support})] during the execution of every protected action on the protected object containing the handler. @end{RunTime} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect and an interrupt is delivered to a handler, and the interrupt hardware priority is higher than the ceiling priority of the corresponding protected object, the execution of the program is erroneous. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgRef{Version=[3],Kind=[RevisedAdded],ARef=[AI05-0229-1]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} If the handlers for a given interrupt attached via @Chg{Version=[3],New=[aspect],Old=[pragma]} Attach_Handler are not attached and detached in a stack-like (LIFO) order, program execution is erroneous. In particular, when a protected object is finalized, the execution is erroneous if any of the procedures of the protected object are attached to interrupts via @Chg{Version=[3],New=[aspect],Old=[pragma]} Attach_@!Handler and the most recently attached handler for the same interrupt is not the same as the one that was attached at the time the protected object was initialized.]} @begin{Discussion} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @ChgAdded{Version=[1],Text=[This simplifies implementation of the Attach_@!Handler @Chg{Version=[3],New=[aspect],Old=[pragma]} by not requiring a check that the current handler is the same as the one attached by the initialization of a protected object.]} @end{Discussion} @end{Erron} @begin{Metrics} @Leading@Keepnext@;The following metric shall be documented by the implementation: @ChgNote{This was @begin{enumerate}, which is wrong} @begin{Itemize} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The worst@Chg{Version=[2],New=[-],Old=[ ]}case overhead for an interrupt handler that is a parameterless protected procedure, in clock cycles. This is the execution time not directly attributable to the handler procedure or the interrupted execution. It is estimated as C @en@; (A+B), where A is how long it takes to complete a given sequence of instructions without any interrupt, B is how long it takes to complete a normal call to a given protected procedure, and C is how long it takes to complete the same sequence of instructions when it is interrupted by one execution of the same procedure called via an interrupt. @begin{ImplNote} The instruction sequence and interrupt handler used to measure interrupt handling overhead should be chosen so as to maximize the execution time cost due to cache misses. For example, if the processor has cache memory and the activity of an interrupt handler could invalidate the contents of cache memory, the handler should be written such that it invalidates all of the cache memory. @end{ImplNote} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for interrupt handlers.]}]} @ChgNote{This was @end{enumerate}, which is wrong} @end{Itemize} @end{Metrics} @begin{ImplPerm} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} When the @Chg{Version=[3],New=[aspects],Old=[pragmas]} Attach_Handler or Interrupt_Handler @Chg{Version=[3],New=[are specified for],Old=[apply to]} a protected procedure, the implementation is allowed to impose implementation-defined restrictions on the corresponding @nt{protected_@!type_@!declaration} and @nt{protected_@!body}. @begin{Ramification} The restrictions may be on the constructs that are allowed within them, and on ordinary calls (i.e. not via interrupts) on protected operations in these protected objects. @end{Ramification} @ChgImplDef{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@Chg{Version=[2], New=[Any restrictions on a protected procedure or its containing type when @Chg{Version=[3],New=[an aspect],Old=[a @nt{pragma}]} Attach_handler or Interrupt_Handler @Chg{Version=[3],New=[is specified],Old=[applies]}.],Old=[]}]} An implementation may use a different mechanism for invoking a protected procedure in response to a hardware interrupt than is used for a call to that protected procedure from a task. @begin{Discussion} This is despite the fact that the priority of an interrupt handler (see @RefSecNum{Task Priorities}) is modeled after a hardware task calling the handler. @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{notwithstanding} Notwithstanding what this subclause says elsewhere, the Attach_Handler and Interrupt_Handler @Chg{Version=[3],New=[aspects],Old=[pragmas]} are allowed to be used for other, implementation defined, forms of interrupt handlers. @begin{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} For example, if an implementation wishes to allow interrupt handlers to have parameters, it is allowed to do so via these @Chg{Version=[3],New=[aspects],Old=[pragmas]}; it need not invent implementation-defined @Chg{Version=[3],New=[aspects],Old=[pragmas]} for the purpose. @end{Ramification} @ChgImplDef{Version=[3],Kind=[Revised],InitialVersion=[2], Text=[@Chg{Version=[2], New=[Any other forms of interrupt handler supported by the Attach_Handler and Interrupt_Handler @Chg{Version=[3],New=[aspects],Old=[pragmas]}.],Old=[]}]} @end{ImplPerm} @begin{ImplAdvice} Whenever possible, the implementation should allow interrupt handlers to be called directly by the hardware. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Interrupt handlers should be called directly by the hardware.]}]} Whenever practical, the implementation should detect violations of any implementation-defined restrictions before run time. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Violations of any implementation-defined restrictions on interrupt handlers should be detected before run time.]}]} @end{ImplAdvice} @begin{Notes} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The Attach_Handler @Chg{Version=[3],New=[aspect may],Old=[pragma can]} provide static attachment of handlers to interrupts if the implementation supports preelaboration of protected objects. (See @RefSecNum{Preelaboration Requirements}.) @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @Chg{Version=[2],New=[A],Old=[The ceiling priority of a]} protected object that @Chg{Version=[2],New=[has a (protected) procedure], Old=[one of its procedures is]} attached to an interrupt should @Chg{Version=[2],New=[have a ceiling priority], Old=[be]} at least as high as the highest processor priority at which that interrupt will ever be delivered. Protected procedures can also be attached dynamically to interrupts via operations declared in the predefined package Interrupts. An example of a possible implementation-defined restriction is disallowing the use of the standard storage pools within the body of a protected procedure that is an interrupt handler. @end{Notes} @begin{Incompatible95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00253-01]} @ChgAdded{Version=[2],Text=[@Defn{incompatibilities with Ada 95} @b[Amendment Correction:] Corrected the wording so that the rules for the use of Attach_Handler and Interrupt_Handler are identical. This means that uses of pragma Interrupt_Handler outside of the target protected type or single protected object are now illegal.]} @end{Incompatible95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0068],ARef=[AI95-00121-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified the meaning of @lquotes@;the previous handler@rquotes when finalizing protected objects containing interrupt handlers.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00303-01]} @ChgAdded{Version=[2],Text=[Dropped the requirement that an object of a type containing an Interrupt_Handler pragma must be declared at the library level. This was a generic contract model violation. This change is not an extension, as an attempt to attach such a handler with a routine in package Interrupts will fail an accessibility check anyway. Moreover, implementations can retain the rule as an implementation-defined restriction on the use of the type, as permitted by the @ImplPermTitle above.]} @end{Diffword95} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspects Interrupt_Handler and Attach_Handler are new; @nt{pragma}s Interrupt_Handler and Attach_Handler are now obsolescent.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0033-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Added missing generic contract wording for the aspects Attach_Handler and Interrupt_Handler.]} @end{DiffWord2005} @LabeledSubClause{The Package Interrupts} @begin{StaticSem} @Leading@Keepnext@;The following language-defined packages exist: @begin{example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0167-1]} @key{with} System;@ChildUnit{Parent=[Ada],Child=[Interrupts]}@Chg{Version=[3],New=[ @key{with} System.Multiprocessors;],Old=[]} @key[package] Ada.Interrupts @key[is] @key[type] @AdaTypeDefn{Interrupt_Id} @key[is] @RI{implementation-defined}; @key[type] @AdaTypeDefn{Parameterless_Handler} @key[is] @key[access] @key[protected] @key[procedure]; @ChgRef{Version=[1], Kind=[Deleted]} @Chg[New=<>,Old=<@ @;@comment{Empty paragraph to hang junk paragraph number from original RM}>] @key[function] @AdaSubDefn{Is_Reserved} (Interrupt : Interrupt_Id) @key[return] Boolean; @key[function] @AdaSubDefn{Is_Attached} (Interrupt : Interrupt_Id) @key[return] Boolean; @key[function] @AdaSubDefn{Current_Handler} (Interrupt : Interrupt_Id) @key[return] Parameterless_Handler; @key[procedure] @AdaSubDefn{Attach_Handler} (New_Handler : @key[in] Parameterless_Handler; Interrupt : @key[in] Interrupt_Id); @key[procedure] @AdaSubDefn{Exchange_Handler} (Old_Handler : @key[out] Parameterless_Handler; New_Handler : @key[in] Parameterless_Handler; Interrupt : @key[in] Interrupt_Id); @key[procedure] @AdaSubDefn{Detach_Handler} (Interrupt : @key[in] Interrupt_Id); @key[function] @AdaSubDefn{Reference} (Interrupt : Interrupt_Id) @key{return} System.Address; @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[ @key[function] @AdaSubDefn{Get_CPU} (Interrupt : Interrupt_Id) @key{return} System.Multiprocessors.CPU_Range;]} @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Interrupts; @key[package] Ada.Interrupts.Names @key[is]@ChildUnit{Parent=[Ada.Interrupts],Child=[Names]} @RI{implementation-defined} : @key[constant] Interrupt_Id := @RI{implementation-defined}; . . . @RI{implementation-defined} : @key[constant] Interrupt_Id := @RI{implementation-defined}; @key[end] Ada.Interrupts.Names; @end{example} @end{StaticSem} @begin{RunTime} The Interrupt_Id type is an implementation-defined discrete type used to identify interrupts. The Is_Reserved function returns True if and only if the specified interrupt is reserved. The Is_Attached function returns True if and only if a user-specified interrupt handler is attached to the interrupt. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0069],ARef=[AI95-00166-01]} The Current_Handler function returns a value that represents the attached handler of the interrupt. If no user-defined handler is attached to the interrupt, Current_Handler returns @Chg{New=[@key{null}], Old=[a value that designates the default treatment; calling Attach_Handler or Exchange_Handler with this value restores the default treatment]}. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} The Attach_Handler procedure attaches the specified handler to the interrupt, overriding any existing treatment (including a user handler) in effect for that interrupt. If New_Handler is @key[null], the default treatment is restored. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} If New_Handler designates a protected procedure @Chg{Version=[3],New=[for], Old=[to]} which the @Chg{Version=[3],New=[aspect], Old=[pragma]} Interrupt_@!Handler @Chg{Version=[3],New=[is False],Old=[does not apply]}, Program_Error is raised. In this case, the operation does not modify the existing interrupt treatment. @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0069],ARef=[AI95-00166-01]} The Exchange_Handler procedure operates in the same manner as Attach_Handler with the addition that the value returned in Old_Handler designates the previous treatment for the specified interrupt.@Chg{New=[ If the previous treatment is not a user-defined handler, @key[null] is returned.],Old=[]} @begin{Ramification} Calling Attach_Handler or Exchange_Handler with this value for New_Handler restores the previous handler. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0069],ARef=[AI95-00166-01]} @ChgAdded{Version=[1],Text=[If the application uses only parameterless procedures as handlers (other types of handlers may be provided by the implementation, but are not required by the standard), then if Old_Handler is not @key(null), it may be called to execute the previous handler. This provides a way to cascade application interrupt handlers. However, the default handler cannot be cascaded this way (Old_Handler must be @key(null) for the default handler).]} @end{Ramification} The Detach_Handler procedure restores the default treatment for the specified interrupt. For all operations defined in this package that take a parameter of type Interrupt_Id, with the exception of Is_Reserved and Reference, a check is made that the specified interrupt is not reserved. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if this check fails. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If, by using the Attach_Handler, Detach_Handler, or Exchange_Handler procedures, an attempt is made to detach a handler that was attached statically (using the @Chg{Version=[3],New=[aspect],Old=[pragma]} Attach_Handler), the handler is not detached and Program_Error is raised. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The Reference function returns a value of type System.Address that can be used to attach a task entry@Chg{Version=[2],New=[],Old=[,]} via an address clause (see @RefSecNum{Interrupt Entries}) to the interrupt specified by Interrupt. This function raises Program_Error if attaching task entries to interrupts (or to this particular interrupt) is not supported. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0153-3]} @ChgAdded{Version=[3],Text=[The function Get_CPU returns the processor on which the handler for Interrupt is executed. If the handler can execute on more than one processor the value System.Multiprocessors.Not_A_Specific_CPU is returned.]} @end{RunTime} @begin{ImplReq} At no time during attachment or exchange of handlers shall the current handler of the corresponding interrupt be undefined. @end{ImplReq} @begin{DocReq} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If the Ceiling_Locking policy (see @RefSecNum{Priority Ceiling Locking}) is in effect@Chg{Version=[2],New=[,],Old=[]} the implementation shall document the default ceiling priority assigned to a protected object that contains @Chg{Version=[3],New=[a protected procedure that specifies ],Old=[]}either the Attach_Handler or Interrupt_Handler @Chg{Version=[3],New=[aspects],Old=[pragmas]}, but @Chg{Version=[3],New=[does not specify],Old=[not]} the Interrupt_Priority @Chg{Version=[3],New=[aspect],Old=[pragma]}. @Redundant[This default need not be the same for all interrupts.] @ChgDocReq{Version=[3],Kind=[RevisedAdded],InitialVersion=[2], Text=[@ChgAdded{Version=[2], Text=[If the Ceiling_Locking policy is in effect, the default ceiling priority for a protected object that @Chg{Version=[3],New=[specifies],Old=[contains]} an interrupt handler @Chg{Version=[3],New=[aspect],Old=[pragma]}.]}]} @end{DocReq} @begin{ImplAdvice} If implementation-defined forms of interrupt handler procedures are supported, such as protected procedures with parameters, then for each such form of a handler, a type analogous to Parameterless_@!Handler should be specified in a child package of Interrupts, with the same operations as in the predefined package Interrupts. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If implementation-defined forms of interrupt handler procedures are supported, then for each such form of a handler, a type analogous to Parameterless_@!Handler should be specified in a child package of Interrupts, with the same operations as in the predefined package Interrupts.]}]} @end{ImplAdvice} @begin{Notes} The package Interrupts.Names contains implementation-defined names (and constant values) for the interrupts that are supported by the implementation. @end{Notes} @begin{Examples} @Leading@Keepnext@i{Example of interrupt handlers:} @begin{example} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} Device_Priority : @key[constant] @key[array] (1..5) of System.Interrupt_Priority := ( ... );@Softpage @key[protected] @key[type] Device_Interface (Int_Id : Ada.Interrupts.Interrupt_Id) @Chg{Version=[3],New=[ @key[with] Interrupt_Priority => Device_Priority(Int_Id) ],Old=[]}@key[is] @key[procedure] Handler@Chg{Version=[3],New=[ @key[with] Attach_Handler => Int_Id],Old=[; @key[pragma] Attach_Handler(Handler, Int_Id)]}; ... @Chg{Version=[3],New=[],Old=[@key[pragma] Interrupt_Priority(Device_Priority(Int_Id)); ]}@key[end] Device_Interface;@Softpage ... Device_1_Driver : Device_Interface(1); ... Device_5_Driver : Device_Interface(5); ... @end{example} @end{Examples} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0069],ARef=[AI95-00166-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that the value returned by Current_Handler and Exchange_Handler for the default treatment is null.]} @end{Diffword95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0167-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Functions Get_CPU is added to Interrupts. If Interrupts is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Get_CPU is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @ISOOnlyRMNewPageVer{Version=[3]}@Comment{For ISO version of Ada 2012 Standard} @LabeledClause{Preelaboration Requirements} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} specifies additional implementation and documentation requirements for the Preelaborate pragma (see @RefSecNum{Elaboration Control}).] @end{Intro} @begin{ImplReq} The implementation shall not incur any run-time overhead for the elaboration checks of subprograms and @ntf{protected_bodies} declared in preelaborated library units. The implementation shall not execute any memory write operations after load time for the elaboration of constant objects declared immediately within the declarative region of a preelaborated library package, so long as the subtype and initial expression (or default initial expressions if initialized by default) of the @nt<object_declaration> satisfy the following restrictions. @Defn{load time} The meaning of @i{load time} is implementation defined. @begin{Discussion} On systems where the image of the partition is initially copied from disk to RAM, or from ROM to RAM, prior to starting execution of the partition, the intention is that @lquotes@;load time@rquotes@; consist of this initial copying step. On other systems, load time and run time might actually be interspersed. @end{Discussion} @begin{itemize} Any @nt<subtype_mark> denotes a statically constrained subtype, with statically constrained subcomponents, if any; @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[no @nt{subtype_mark} denotes a controlled type, a private type, a private extension, a generic formal private type, a generic formal derived type, or a descendant of such a type;]} @begin{Reason} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[For an implementation that uses the registration method of finalization, a controlled object will require some code executed to register the object at the appropriate point. The other types are those that @i{might} have a controlled component. None of these types were allowed in preelaborated units in Ada 95. These types are covered by the @ImplAdviceTitle, of course, so they should still execute as little code as possible.]} @end{Reason} any @nt<constraint> is a static constraint; any @nt<allocator> is for an access-to-constant type; any uses of predefined operators appear only within static expressions; any @ntf<primaries> that are @nt<name>s, other than @nt<attribute_reference>s for the Access or Address attributes, appear only within static expressions; @begin{ramification} This cuts out @nt<attribute_reference>s that are not static, except for Access and Address. @end{Ramification} any @nt<name> that is not part of a static expression is an expanded name or @nt<direct_name> that statically denotes some entity; @begin{Ramification} This cuts out @nt<function_call>s and @nt<type_conversion>s that are not static, including calls on attribute functions like 'Image and 'Value. @end{Ramification} any @nt<discrete_choice> of an @nt<array_aggregate> is static; no language-defined check associated with the elaboration of the @nt<object_declaration> can fail. @begin{Reason} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} The intent is that aggregates all of whose scalar subcomponents are static@Chg{Version=[2],New=[],Old=[,]} and all of whose access subcomponents are @key(null), allocators for access-to-constant types, or X'Access, will be supported with no run-time code generated. @end{Reason} @end{itemize} @end{ImplReq} @begin{DocReq} The implementation shall document any circumstances under which the elaboration of a preelaborated package causes code to be executed at run time. @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Any circumstances when the elaboration of a preelaborated package causes code to be executed.]}]} The implementation shall document whether the method used for initialization of preelaborated variables allows a partition to be restarted without reloading. @ChgDocReq{Version=[2],Kind=[Added],Text=[@ChgAdded{Version=[2], Text=[Whether a partition can be restarted without reloading.]}]} @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[Implementation-defined aspects of preelaboration.]}]} @begin{discussion} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This covers the issue of the @Chg{Version=[2],New=[run-time system],Old=[RTS]} itself being restartable, so that need not be a separate @DocReqName. @end{discussion} @end{DocReq} @begin{ImplAdvice} It is recommended that preelaborated packages be implemented in such a way that there should be little or no code executed at run time for the elaboration of entities not already covered by the @ImplReqName@;s. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Preelaborated packages should be implemented such that little or no code is executed at run time for the elaboration of entities.]}]} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00161-01]} @ChgAdded{Version=[2],Text=[Added wording to exclude the additional kinds of types allowed in preelaborated units from the @ImplReqTitle.]} @end{DiffWord95} @LabeledClause{Pragma Discard_Names} @begin{Intro} @Redundant[A @nt{pragma} Discard_Names may be used to request a reduction in storage used for the names of certain entities.] @end{Intro} @begin{Syntax} @begin{SyntaxText} @Leading@Keepnext@;The form of a @nt{pragma} Discard_Names is as follows: @end{SyntaxText} @PragmaSyn`@key{pragma} @prag(Discard_Names)[([On => ] @Syn2[local_name])];' @begin{SyntaxText} A @nt{pragma} Discard_Names is allowed only immediately within a @nt{declarative_part}, immediately within a @nt{package_specification}, or as a configuration pragma. @PDefn2{Term=[configuration pragma], Sec=(Discard_Names)} @PDefn2{Term=[pragma, configuration], Sec=(Discard_Names)} @end{SyntaxText} @end{Syntax} @begin{Legality} The @nt{local_name} (if present) shall denote a nonderived enumeration @Redundant[first] subtype, a tagged @Redundant[first] subtype, or an exception. The pragma applies to the type or exception. Without a @nt{local_name}, the pragma applies to all such entities declared after the pragma, within the same declarative region. Alternatively, the pragma can be used as a configuration pragma. If the pragma applies to a type, then it applies also to all descendants of the type. @end{Legality} @begin{StaticSem} @PDefn2{Term=[representation pragma], Sec=(Discard_Names)} @PDefn2{Term=[pragma, representation], Sec=(Discard_Names)} If a @nt{local_name} is given, then a @nt{pragma} Discard_Names is a representation pragma. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Representation pragmas automatically specify aspects of the same name, so Discard_Names can be used as an @nt{aspect_mark} in an @nt{aspect_specification} instead of using the pragma on individual entities.]} @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01],ARef=[AI95-00400-01]} If the pragma applies to an enumeration type, then the semantics of the @Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and @Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} attributes are implementation defined for that type@Redundant[; the semantics of Image@Chg{Version=[2],New=[, Wide_Image,],Old=[ and]} Value@Chg{Version=[2],New=[, and Wide_Value],Old=[]} are still defined in terms of @Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and @Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]}]. In addition, the semantics of Text_IO.Enumeration_IO are implementation defined. If the pragma applies to a tagged type, then the semantics of the Tags.@!@Chg{Version=[2],New=[Wide_Wide_@!Expanded_@!Name], Old=[Expanded_@!Name]} function are implementation defined for that type@Chg{Version=[2],New=[@Redundant[; the semantics of Tags.@!Expanded_@!Name and Tags.@!Wide_@!Expanded_@!Name are still defined in terms of Tags.@!Wide_Wide_@!Expanded_@!Name]], Old=[]}. If the pragma applies to an exception, then the semantics of the Exceptions.@!@Chg{Version=[2],New=[Wide_Wide_@!Exception_@!Name], Old=[Exception_@!Name]} function are implementation defined for that exception@Chg{Version=[2],New=[@Redundant[; the semantics of Exceptions.@!Exception_@!Name and Exceptions.@!Wide_@!Exception_@!Name are still defined in terms of Exceptions.@!Wide_Wide_@!Exception_@!Name]], Old=[]}. @ImplDef{The semantics of pragma Discard_Names.} @begin{Ramification} The Width attribute is still defined in terms of Image. @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00285-01]} The semantics of S'@Chg{Version=[2],New=[Wide_Wide_Image],Old=[Wide_Image]} and S'@Chg{Version=[2],New=[Wide_Wide_Value],Old=[Wide_Value]} are implementation defined for any subtype of an enumeration type to which the pragma applies. (The pragma actually names the first subtype, of course.) @end{Ramification} @end{StaticSem} @begin{ImplAdvice} If the pragma applies to an entity, then the implementation should reduce the amount of storage used for storing names associated with that entity. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If @nt{pragma} Discard_Names applies to an entity, then the amount of storage used for storing names associated with that entity should be reduced.]}]} @begin{Reason} A typical implementation of the Image attribute for enumeration types is to store a table containing the names of all the enumeration literals. Pragma Discard_Names allows the implementation to avoid storing such a table without having to prove that the Image attribute is never used (which can be difficult in the presence of separate compilation). We did not specify the semantics of the Image attribute in the presence of this pragma because different semantics might be desirable in different situations. In some cases, it might make sense to use the Image attribute to print out a useful value that can be used to identify the entity given information in compiler-generated listings. In other cases, it might make sense to get an error at compile time or at run time. In cases where memory is plentiful, the simplest implementation makes sense: ignore the pragma. Implementations that are capable of avoiding the extra storage in cases where the Image attribute is never used might also wish to ignore the pragma. The same applies to the Tags.Expanded_Name and Exceptions.Exception_Name functions. @end{Reason} @end{ImplAdvice} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00285-01],ARef=[AI95-00400-01]} @ChgAdded{Version=[2],Text=[Updated the wording to reflect that the double wide image and value functions are now the master versions that the others are defined from.]} @end{DiffWord95} @LabeledClause{Shared Variable Control} @begin{Intro} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause defines],Old=[clause specifies]} representation @Chg{Version=[3],New=[aspects],Old=[pragmas]} that control the use of shared variables.] @end{Intro} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraphs 2 through 6 were moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.} @end{NotIso} @begin{Syntax} @begin{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Type=[Leading],Text=[The form for pragmas Atomic, Volatile, Atomic_Components, and Volatile_Components is as follows:]} @end{SyntaxText} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Atomic)(@Syn2{local_name});]}> @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Volatile)(@Syn2{local_name});]}> @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Atomic_Components)(@SynI{array_}@Syn2{local_name});]}> @ChgRef{Version=[3],Kind=[DeletedNoDelMsg]} @DeletedPragmaSyn<Version=[3],InitialVersion=[0],@ChgDeleted{Version=[3], Text=[@key{pragma} @prag(Volatile_Components)(@SynI{array_}@Syn2{local_name});]}> @end{Syntax} @Comment{Original: @begin{Intro}, Replaced with below for Ada 2012} @begin{StaticSem} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For an @nt{object_declaration}, a @nt{component_declaration}, or a @nt{full_type_declaration}, the following representation aspects may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Atomic@\The type of aspect Atomic is Boolean.@AspectDefn{Atomic}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Atomic], Text=[@ChgAdded{Version=[3],Text=[Declare that a type, object, or component is atomic.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Independent@\The type of aspect Independent is Boolean.@AspectDefn{Independent}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Independent], Text=[@ChgAdded{Version=[3],Text=[Declare that a type, object, or component is independently addressable.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Volatile@\The type of aspect Volatile is Boolean.@AspectDefn{Volatile}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Volatile], Text=[@ChgAdded{Version=[3],Text=[Declare that a type, object, or component is volatile.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a @nt{full_type_declaration} of an array type (including the anonymous type of an @nt{object_declaration} of an anonymous array object), the following representation aspects may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Atomic_Components@\The type of aspect Atomic_Components is Boolean.@AspectDefn{Atomic_Components}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Atomic_Components], Text=[@ChgAdded{Version=[3],Text=[Declare that the components of an array type or object are atomic.]}]} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Volatile_Components@\The type of aspect Volatile_Components is Boolean.@AspectDefn{Volatile_Components}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Volatile_Components], Text=[@ChgAdded{Version=[3],Text=[Declare that the components of an array type or object are volatile.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Type=[Leading],Text=[For a @nt{full_type_declaration} (including the anonymous type of an @nt{object_declaration} of an anonymous array object), the following representation aspect may be specified:]} @begin{Description} @ChgRef{Version=[3],Kind=[Added]} @ChgAdded{Version=[3],Text=[Independent_Components@\The type of aspect Independent_Components is Boolean.@AspectDefn{Independent_Components}]} @ChgAspectDesc{Version=[3],Kind=[AddedNormal],Aspect=[Independent_Components], Text=[@ChgAdded{Version=[3],Text=[Declare that the components of an array or record type, or an array object, are independently addressable.]}]} @end{Description} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If any of these aspects are directly specified, the @nt{aspect_definition} shall be a static expression. If not specified (including by inheritance), each of these aspects is False.]} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00272-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{atomic} An @i{atomic} type is one @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Atomic @Chg{Version=[3],New=[is True],Old=[applies]}. An @i{atomic} object (including a component) is one @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Atomic @Chg{Version=[3],New=[is True],Old=[applies]}, or a component of an array @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Atomic_Components @Chg{Version=[3],New=[is True for the associated type],Old=[applies]}, or any object of an atomic type@Chg{Version=[2], New=[, other than objects obtained by evaluating a slice],Old=[]}. @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00272-01]} @ChgAdded{Version=[2],Text=[A slice of an atomic array object is not itself atomic. That's necessary as executing a read or write of a dynamic number of components in a single instruction is not possible on many targets.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{volatile} A @i{volatile} type is one @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Volatile @Chg{Version=[3],New=[is True],Old=[applies]}. A @i{volatile} object (including a component) is one @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Volatile @Chg{Version=[3],New=[is True],Old=[applies]}, or a component of an array @Chg{Version=[3],New=[for],Old=[to]} which @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Volatile_@!Components @Chg{Version=[3],New=[is True for the associated type],Old=[applies]}, or any object of a volatile type. In addition, every atomic type or object is also defined to be volatile. Finally, if an object is volatile, then so are all of its subcomponents @Redundant[(the same does not apply to atomic)]. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[When True, the aspects Independent and Independent_Components @i<specify as independently addressable> the named object or component(s), or in the case of a type, all objects or components of that type. All atomic objects are considered to be specified as independently addressable.@Defn{specified as independently addressable}@Defn2{Term=[independently addressable],Sec=[specified]}]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[If the compiler cannot guarantee that an object (including a component) for which aspect Independent or aspect Independent_Components is True is independently addressable from any other nonoverlapping object, then the aspect specification must be rejected.]} @ChgRef{Version=[3],Kind=[AddedNormal]} @ChgAdded{Version=[3],Text=[Similarly, an atomic object (including atomic components) is always independently addressable from any other nonoverlapping object. Any representation item which would prevent this from being true should be rejected, notwithstanding what this Standard says elsewhere (specifically, in the Recommended Level of Support).]} @end{Ramification} @Comment{Original: @end{Intro}, Replaced with below for Ada 2012} @end{StaticSem} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraph 9 was moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.}@ChgNote{We use this message rather than the "automatic one" to get rid of the resolution subheader} @end{NotIso} @begin{Resolution} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[The @nt{local_name} in an Atomic or Volatile pragma shall resolve to denote either an @nt{object_declaration}, a noninherited @nt{component_@!declaration}, or a @nt{full_type_@!declaration}. The @SynI{array_}@nt{local_name} in an Atomic_@!Components or Volatile_@!Components pragma shall resolve to denote the declaration of an array type or an array object of an anonymous type.]} @end{Resolution} @begin{Legality} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[If aspect Independent_Components is specified for a @nt{full_type_declaration}, the declaration shall be that of an array or record type.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} @Defn{indivisible} It is illegal to @Chg{Version=[3],New=[specify],Old=[apply]} either @Chg{Version=[3],New=[of the aspects],Old=[an]} Atomic or Atomic_Components @Chg{Version=[3],New=[],Old=[pragma ]}to @Chg{Version=[3],New=[have the value True for ],Old=[]}an object or type if the implementation cannot support the indivisible reads and updates required by the @Chg{Version=[3],New=[aspect],Old=[pragma]} (see below). It is illegal to specify the Size attribute of an atomic object, the Component_Size attribute for an array type with atomic components, or the layout attributes of an atomic component, in a way that prevents the implementation from performing the required indivisible reads and updates. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0142-4],ARef=[AI05-0218-1]} If an atomic object is passed as a parameter, then @Chg{Version=[3],New=[],Old=[the type of ]}the formal parameter shall either @Chg{Version=[3],New=[have an],Old=[be]} atomic @Chg{Version=[3],New=[type ],Old=[]}or allow pass by copy@Chg{Version=[3],New=[],Old=[ @Redundant[(that is, not be a nonatomic by-reference type)]]}. If an atomic object is used as an actual for a generic formal object of mode @key{in out}, then the type of the generic formal object shall be atomic. If the @nt<prefix> of an @nt<attribute_reference> for an Access attribute denotes an atomic object @Redundant[(including a component)], then the designated type of the resulting access type shall be atomic. If an atomic type is used as an actual for a generic formal derived type, then the ancestor of the formal type shall be atomic@Chg{Version=[3],New=[],Old=[ or allow pass by copy]}. Corresponding rules apply to volatile objects and types. @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[A formal parameter allows pass by copy if it is not @key[aliased] and it is of a type that allows pass by copy (that is, is not a by-reference type).]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0218-1]} @ChgAdded{Version=[3],Text=[If a volatile type is used as an actual for a generic formal array type, then the element type of the formal type shall be volatile.]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If @Chg{Version=[3],New=[an aspect],Old=[a pragma]} Volatile, Volatile_Components, Atomic, or Atomic_Components @Chg{Version=[3],New=[is directly specified to have the value True for],Old=[applies to]} a stand-alone constant object, then @Chg{Version=[3],New=[the aspect],Old=[a pragma]} Import shall also @Chg{Version=[3],New=[be specified as True for],Old=[apply to]} it. @begin{Ramification} Hence, no initialization expression is allowed for such a constant. Note that a constant that is atomic or volatile because of its type is allowed. @end{Ramification} @begin{Reason} Stand-alone constants that are explicitly specified as Atomic or Volatile only make sense if they are being manipulated outside the Ada program. From the Ada perspective the object is read-only. Nevertheless, if imported and atomic or volatile, the implementation should presume it might be altered externally. For an imported stand-alone constant that is not atomic or volatile, the implementation can assume that it will not be altered. @end{Reason} @begin{Honest} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0218-1]} @ChgAdded{Version=[3],Text=[Volatile_Components and Atomic_Components actually are aspects of the anonymous array type; this rule only applies when the aspect is specified directly on the constant object and not when the (named) array type has the aspect.]} @end{Honest} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[It is illegal to specify the aspect Independent or Independent_Components as True for a component, object or type if the implementation cannot provide the independent addressability required by the aspect (see @RefSecNum{Shared Variables}).]} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[It is illegal to specify a representation aspect for a component, object or type for which the aspect Independent or Independent_Components is True, in a way that prevents the implementation from providing the independent addressability required by the aspect.]} @end{Legality} @begin{NotIso} @ChgAdded{Version=[3],Noprefix=[T],Noparanum=[T],Text=[@Shrink{@i<Paragraph 14 was moved to @RefSec{Obsolescent Features}.>}]}@Comment{This message should be deleted if the paragraphs are ever renumbered.}@ChgNote{We use this message rather than the "automatic one" to get rid of the resolution subheader} @end{NotIso} @begin{StaticSem} @ChgRef{Version=[3],Kind=[DeletedNoDelMsg],ARef=[AI05-0229-1]} @ChgDeleted{Version=[3],Text=[@PDefn2{Term=[representation pragma], Sec=(Atomic)} @PDefn2{Term=[pragma, representation], Sec=(Atomic)} @PDefn2{Term=[representation pragma], Sec=(Volatile)} @PDefn2{Term=[pragma, representation], Sec=(Volatile)} @PDefn2{Term=[representation pragma], Sec=(Atomic_Components)} @PDefn2{Term=[pragma, representation], Sec=(Atomic_Components)} @PDefn2{Term=[representation pragma], Sec=(Volatile_Components)} @PDefn2{Term=[pragma, representation], Sec=(Volatile_Components)} These @nt{pragma}s are representation pragmas (see @RefSecNum{Operational and Representation Aspects}).]} @end{StaticSem} @begin{RunTime} For an atomic object (including an atomic component) all reads and updates of the object as a whole are indivisible. @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0117-1],ARef=[AI05-0275-1]} @Chg{Version=[3],New=[All tasks of the program (on all processors) that read or update volatile variables see the same order of updates to the variables. A use of an atomic variable or other mechanism may be necessary to avoid erroneous execution and to ensure that access to nonatomic volatile variables is sequential (see @RefSecNum{Shared Variables}).], Old=[For a volatile object all reads and updates of the object as a whole are performed directly to memory.]} @begin{ImplNote} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0117-1],ARef=[AI05-0275-1]} @Chg{Version=[3],New=[To ensure this, on a multiprocessor, any read or update of an atomic object may require the use of an appropriate memory barrier.],Old=[This precludes any use of register temporaries, caches, and other similar optimizations for that object.]} @end{ImplNote} @begin{Discussion} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0275-1]} @ChgAdded{Version=[3],Text=[From @RefSecNum{Shared Variables} it follows that (in non-erroneous programs) accesses to variables, including those shared by multiple tasks, are always sequential. This guarantees that no task will ever see partial updates of any variable. For volatile variables (including atomic variables), the above rule additionally specifies that all tasks see the same order of updates.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0275-1]} @ChgAdded{Version=[3],Text=[If for a shared variable @i<X>, a read of @i<X> occurs sequentially after an update of @i<X>, then the read will return the updated value if @i<X> is volatile or atomic, but may or or may not return the updated value if @i<X> is nonvolatile. For nonvolatile accesses, a signaling action is needed in order to share the updated value.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0275-1]} @ChgAdded{Version=[3],Text=[Because accesses to the same atomic variable by different tasks establish a sequential order between the actions of those tasks, implementations may be required to emit memory barriers around such updates or use atomic instructions that imply such barriers.]} @end{Discussion} @Defn2{Term=[sequential], Sec=(actions)} Two actions are sequential (see @RefSecNum{Shared Variables}) if each is the read or update of the same atomic object. @PDefn2{Term=[by-reference type], Sec=(atomic or volatile)} If a type is atomic or volatile and it is not a by-copy type, then the type is defined to be a by-reference type. If any subcomponent of a type is atomic or volatile, then the type is defined to be a by-reference type. If an actual parameter is atomic or volatile, and the corresponding formal parameter is not, then the parameter is passed by copy. @begin{ImplNote} Note that in the case where such a parameter is normally passed by reference, a copy of the actual will have to be produced at the call-site, and a pointer to the copy passed to the formal parameter. If the actual is atomic, any copying has to use indivisible read on the way in, and indivisible write on the way out. @end{ImplNote} @begin{Reason} It has to be known at compile time whether an atomic or a volatile parameter is to be passed by copy or by reference. For some types, it is unspecified whether parameters are passed by copy or by reference. The above rules further specify the parameter passing rules involving atomic and volatile types and objects. @end{Reason} @end{RunTime} @begin{ImplReq} @PDefn2{Term=[external effect], Sec=(volatile/atomic objects)} The external effect of a program (see @RefSecNum(Conformity of an Implementation with the Standard)) is defined to include each read and update of a volatile or atomic object. The implementation shall not generate any memory reads or updates of atomic or volatile objects other than those specified by the program. @begin{Discussion} The presumption is that volatile or atomic objects might reside in an @lquotes@;active@rquotes@; part of the address space where each read has a potential side effect, and at the very least might deliver a different value. @Leading@;The rule above and the definition of external effect are intended to prevent (at least) the following incorrect optimizations, where V is a volatile variable: @begin{itemize} X:= V; Y:=V; cannot be allowed to be translated as Y:=V; X:=V; Deleting redundant loads: X:= V; X:= V; shall read the value of V from memory twice. Deleting redundant stores: V:= X; V:= X; shall write into V twice. Extra stores: V:= X+Y; should not translate to something like V:= X; V:= V+Y; Extra loads: X:= V; Y:= X+Z; X:=X+B; should not translate to something like Y:= V+Z; X:= V+B; Reordering of loads from volatile variables: X:= V1; Y:= V2; (whether or not V1 = V2) should not translate to Y:= V2; X:= V1; Reordering of stores to volatile variables: V1:= X; V2:= X; should not translate to V2:=X; V1:= X; @end{itemize} @end{Discussion} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0229-1]} If @Chg{Version=[3],New=[the],Old=[a pragma]} Pack @Chg{Version=[3],New=[aspect is True for],Old=[applies to]} a type any of whose subcomponents are atomic, the implementation shall not pack the atomic subcomponents more tightly than that for which it can support indivisible reads and updates. @begin{ImplNote} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0009-1]} @Chg{Version=[3],New=[Usually, specifying aspect Pack for such a type will be illegal as the Recommended Level of Support cannot be achieved; otherwise, a],Old=[A]} warning might be appropriate if no packing whatsoever can be achieved. @end{ImplNote} @end{ImplReq} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[A load or store of a volatile object whose size is a multiple of System.Storage_Unit and whose alignment is nonzero, should be implemented by accessing exactly the bits of the object and no others.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A load or store of a volatile object whose size is a multiple of System.Storage_Unit and whose alignment is nonzero, should be implemented by accessing exactly the bits of the object and no others.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[Since any object can be a volatile object, including packed array components and bit-mapped record components, we require the above only when it is reasonable to assume that the machine can avoid accessing bits outside of the object.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This implies that the load or store of a volatile object that meets the above requirement should not be combined with that of any other object, nor should it access any bits not belonging to any other object. This means that the suitability of the implementation for memory-mapped I/O can be determined from its documentation, as any cases where the implementation does not follow @ImplAdviceTitle must be documented.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[A load or store of an atomic object should, where possible, be implemented by a single load or store instruction.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[A load or store of an atomic object should be implemented by a single load or store instruction.]}]} @end{ImplAdvice} @begin{Notes} An imported volatile or atomic constant behaves as a constant (i.e. read-only) with respect to other parts of the Ada program, but can still be modified by an @lquotes@;external source.@rquotes@; @end{Notes} @begin{Incompatible83} @Defn{incompatibilities with Ada 83} Pragma Atomic replaces Ada 83's pragma Shared. The name @lquotes@;Shared@rquotes@; was confusing, because the pragma was not used to mark variables as shared. @end{Incompatible83} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00259-01]} @ChgAdded{Version=[2],Text=[Added @ImplAdviceTitle to clarify the meaning of Atomic and Volatile in machine terms. The documentation that this advice applies will make the use of Ada implementations more predictable for low-level (such as device register) programming.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00272-01]} @ChgAdded{Version=[2],Text=[Added wording to clarify that a slice of an object of an atomic type is not atomic, just like a component of an atomic type is not (necessarily) atomic.]} @end{Diffword95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0218-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005}@b<Correction:> Plugged a hole involving volatile components of formal types when the formal type's component has a nonvolatile type. This was done by making certain actual types illegal for formal derived and formal array types; these types were allowed for Ada 95 and Ada 2005.]} @end{Incompatible2005} @begin{Extend2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0009-1],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[@Defn{extensions to Ada 2005} Aspects Independent and Independent_Components are new; they eliminate ambiguity about independent addressability.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0229-1]} @ChgAdded{Version=[3],Text=[Aspects Atomic, Atomic_Components, Volatile, and Volatile_Components are new; @nt{pragma}s Atomic, Atomic_Components, Volatile, and Volatile_Components are now obsolescent.]} @end{Extend2005} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0117-1],ARef=[AI05-0275-1]} @ChgAdded{Version=[3],Text=[Revised the definition of volatile to eliminate overspecification and simply focus on the root requirement (that all tasks see the same view of volatile objects). This is not an inconsistency; "memory" arguably includes on-chip caches so long as those are kept consistent. Moreover, it is difficult to imagine a program that could tell the difference.]} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0142-4]} @ChgAdded{Version=[3],Text=[Added wording to take explicitly aliased parameters (see @RefSecNum{Subprogram Declarations}) into account when determining the legality of parameter passing of volatile and atomic objects.]} @end{DiffWord2005} @LabeledRevisedClause{Version=[2],New=[Task Information], Old=[Task Identification and Attributes]} @begin{Intro} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @Redundant[This @Chg{Version=[3],New=[subclause],Old=[clause]} describes operations and attributes that can be used to obtain the identity of a task. In addition, a package that associates user-defined information with a task is defined.@Chg{Version=[2],New=[ Finally, a package that associates termination procedures with a task or set of tasks is defined.],Old=[]}] @end{Intro} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[The title and text here were updated to reflect the addition of task termination procedures to this @Chg{Version=[3],New=[subclause],Old=[clause]}.]} @end{DiffWord95} @LabeledSubClause{The Package Task_Identification} @begin{StaticSem} @Leading@Keepnext@;The following language-defined library package exists: @begin{example} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00362-01]} @key[package] Ada.Task_Identification @key[is]@ChildUnit{Parent=[Ada],Child=[Task_Identification]}@Chg{Version=[2],New=[ @key[pragma] Preelaborate(Task_Identification);],Old=[]} @key[type] @AdaTypeDefn{Task_Id} @key[is] @key{private};@Chg{Version=[2],New=[ @key[pragma] Preelaborable_Initialization (Task_Id);],Old=[]} @AdaSubDefn{Null_Task_Id} : @key{constant} Task_Id; @key{function} "=" (Left, Right : Task_Id) @key{return} Boolean; @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0070],ARef=[AI95-00101-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0189-1]} @key{function} @AdaSubDefn{Image} (T : Task_Id) @key{return} String; @key[function] @AdaSubDefn{Current_Task} @key[return] Task_Id;@Chg{Version=[3],New=[ @key[function] @AdaSubDefn{Environment_Task} @key[return] Task_Id;],Old=[]} @Key[procedure] @AdaSubDefn{Abort_Task} (T : @key[in] @Chg{New=[],Old=[@key[out] ]}Task_Id); @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0189-1]} @key[function] @AdaSubDefn{Is_Terminated} (T : Task_Id) @key{return} Boolean; @key[function] @AdaSubDefn{Is_Callable} (T : Task_Id) @key{return} Boolean;@Chg{Version=[3],New=[ @key[function] @AdaSubDefn{Activation_Is_Complete} (T : Task_Id) @key{return} Boolean;],Old=[]} @key[private] ... -- @RI{not specified by the language} @key[end] Ada.Task_Identification; @end{example} @end{StaticSem} @begin{RunTime} A value of the type Task_Id identifies an existent task. The constant Null_Task_Id does not identify any task. Each object of the type Task_Id is default initialized to the value of Null_Task_Id. The function "=" returns True if and only if Left and Right identify the same task or both have the value Null_Task_Id. The function Image returns an implementation-defined string that identifies T. If T equals Null_Task_Id, Image returns an empty string. @ImplDef{The result of the Task_Identification.Image attribute.} The function Current_Task returns a value that identifies the calling task. @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[The function Environment_Task returns a value that identifies the environment task.]} The effect of Abort_Task is the same as the @nt{abort_statement} for the task identified by T. @Redundant[In addition, if T identifies the environment task, the entire partition is aborted, See @RefSecNum{Partitions}.] The functions Is_Terminated and Is_Callable return the value of the corresponding attribute of the task identified by T. @begin{Ramification} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0115],ARef=[AI95-00206-01]} @ChgAdded{Version=[1],Text=[These routines can be called with an argument identifying the environment task. Is_Terminated will always be False for such a call, but Is_Callable (usually True) could be False if the environment task is waiting for the termination of dependent tasks. Thus, a dependent task can use Is_Callable to determine if the main subprogram has completed.]} @end{Ramification} @ChgRef{Version=[3],Kind=[Added],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[The function Activation_Is_Complete returns True if the task identified by T has completed its activation (whether successfully or not). It returns False otherwise. If T identifies the environment task, Activation_Is_Complete returns True after the elaboration of the @nt{library_item}s of the partition has completed.]} @Leading@;For @PrefixType{a @nt<prefix> T that is of a task type @Redundant[(after any implicit dereference)]}, the following attribute is defined: @begin{Description} @Attribute{Prefix=<T>, AttrName=<Identity>, Text=[Yields a value of the type Task_Id that identifies the task denoted by T.]} @end{Description} @EndPrefixType{} @Leading@;For @PrefixType{a @nt<prefix> E that denotes an @nt<entry_declaration>}, the following attribute is defined: @begin{Description} @ChgAttribute{Version=[3],Kind=[Revised],ChginAnnex=[T], Leading=<F>, Prefix=<E>, AttrName=<Caller>, ARef=[AI05-0262-1], Text=[Yields a value of the type Task_Id that identifies the task whose call is now being serviced. Use of this attribute is allowed only inside an @Chg{Version=[3],New=[],Old=[@nt{entry_body} or ]}@nt{accept_statement}@Chg{Version=[3],New=[, or @nt{entry_body} after the @nt{entry_barrier}, ],Old=[]}corresponding to the @nt{entry_declaration} denoted by E.]} @end{Description} @EndPrefixType{} @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if a value of Null_Task_Id is passed as a parameter to Abort_Task, Is_Terminated, and Is_Callable. @PDefn2{Term=[potentially blocking operation],Sec=(Abort_Task)} @PDefn2{Term=[blocking, potentially],Sec=(Abort_Task)} Abort_Task is a potentially blocking operation (see @RefSecNum{Protected Subprograms and Protected Actions}). @end{RunTime} @begin{Bounded} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0004-1]} @PDefn2{Term=(bounded error),Sec=(cause)} It is a bounded error to call the Current_Task function from an @Chg{Version=[3],New=[@nt{entry_body}],Old=[entry body]}@Chg{Version=[2],New=[,],Old=[ or an]} interrupt handler@Chg{Version=[2],New=[, or finalization of a task attribute],Old=[]}. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised, or an implementation-defined value of the type Task_Id is returned. @ChgImplDef{Version=[2],Kind=[Revised],InitialVersion=[0], Text=[The value of Current_Task when in a protected entry@Chg{Version=[2],New=[,],Old=[ or]} interrupt handler@Chg{Version=[2], New=[, or finalization of a task attribute],Old=[]}.]} @begin{ImplNote} This value could be Null_Task_Id, or the ID of some user task, or that of an internal task created by the implementation. @end{ImplNote} @begin{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]}@Comment{This really should reference AI05-0004, but we don't have that yet. And that hasn't been approved, either} @ChgAdded{Version=[2],Text=[An entry barrier is syntactically part of an @nt{entry_body}, so a call to Current_Task from an entry barrier is also covered by this rule.]} @end{Ramification} @end{Bounded} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the operations declared in this package (or any language-defined child of this package), and the corresponding task object no longer exists, the execution of the program is erroneous. @end{Erron} @begin{DocReq} The implementation shall document the effect of calling Current_Task from an entry body or interrupt handler. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[The effect of calling Current_Task from an entry body or interrupt handler.]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The effect of calling Current_Task from an entry body or interrupt handler.]}]} @end{DocReq} @begin{Notes} This package is intended for use in writing user-defined task scheduling packages and constructing server tasks. Current_Task can be used in conjunction with other operations requiring a task as an argument such as Set_Priority (see @RefSecNum{Dynamic Priorities}). The function Current_Task and the attribute Caller can return a Task_Id value that identifies the environment task. @end{Notes} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00362-01]} @ChgAdded{Version=[2],Text=[Task_Identification is now preelaborated, so it can be used in preelaborated units.]} @end{Extend95} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0070],ARef=[AI95-00101-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Corrected the mode of the parameter to Abort_Task to @key{in}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Corrected the wording to include finalization of a task attribute in the bounded error case; we don't want to specify which task does these operations.]} @end{Diffword95} @begin{Incompatible2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0189-1]} @ChgAdded{Version=[3],Text=[@Defn{incompatibilities with Ada 2005} Functions Environment_Task and Activation_Is_Complete are added to Task_Identification. If Task_Identification is referenced in a @nt{use_clause}, and an entity @i<E> with a @nt{defining_identifier} of Environment_Task or Activation_Is_Complete is defined in a package that is also referenced in a @nt{use_clause}, the entity @i<E> may no longer be use-visible, resulting in errors. This should be rare and is easily fixed if it does occur.]} @end{Incompatible2005} @LabeledSubClause{The Package Task_Attributes} @begin{StaticSem} @Leading@Keepnext@;The following language-defined generic library package exists: @begin{example} @key{with} Ada.Task_Identification; @key{use} Ada.Task_Identification; @key{generic} @key{type} Attribute @key{is} @key{private}; Initial_Value : @key[in] Attribute; @key{package} Ada.Task_Attributes @key{is}@ChildUnit{Parent=[Ada],Child=[Task_Attributes]} @key{type} @AdaTypeDefn{Attribute_Handle} @key{is} @key{access} @key{all} Attribute; @key{function} @AdaSubDefn{Value}(T : Task_Id := Current_Task) @key{return} Attribute; @key{function} @AdaSubDefn{Reference}(T : Task_Id := Current_Task) @key{return} Attribute_Handle; @key{procedure} @AdaSubDefn{Set_Value}(Val : @key[in] Attribute; T : @key[in] Task_Id := Current_Task); @key{procedure} @AdaSubDefn{Reinitialize}(T : @key[in] Task_Id := Current_Task); @key{end} Ada.Task_Attributes; @end{example} @end{StaticSem} @begin{RunTime} When an instance of Task_Attributes is elaborated in a given active partition, an object of the actual type corresponding to the formal type Attribute is implicitly created for each task (of that partition) that exists and is not yet terminated. This object acts as a user-defined attribute of the task. A task created previously in the partition and not yet terminated has this attribute from that point on. Each task subsequently created in the partition will have this attribute when created. In all these cases, the initial value of the given attribute is Initial_Value. The Value operation returns the value of the corresponding attribute of T. The Reference operation returns an access value that designates the corresponding attribute of T. The Set_Value operation performs any finalization on the old value of the attribute of T and assigns Val to that attribute (see @RefSecNum{Assignment Statements} and @RefSecNum{Assignment and Finalization}). The effect of the Reinitialize operation is the same as Set_Value where the Val parameter is replaced with Initial_Value. @begin{ImplNote} In most cases, the attribute memory can be reclaimed at this point. @end{ImplNote} @Defn2{Term=[Tasking_Error],Sec=(raised by failure of run-time check)} For all the operations declared in this package, Tasking_Error is raised if the task identified by T is terminated. @Defn2{Term=[Program_Error],Sec=(raised by failure of run-time check)} Program_Error is raised if the value of T is Null_Task_Id. @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[After a task has terminated, all of its attributes are finalized, unless they have been finalized earlier. When the master of an instantiation of Ada.Task_Attributes is finalized, the corresponding attribute of each task is finalized, unless it has been finalized earlier.]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[This is necessary so that a task attribute does not outlive its type. For instance, that's possible if the instantiation is nested, and the attribute is on a library-level task.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[The task owning an attribute cannot, in general, finalize that attribute. That's because the attributes are finalized @i<after> the task is terminated; moreover, a task may have attributes as soon as it is created; the task may never even have been activated.]} @end{Ramification} @end{RunTime} @begin{Bounded} @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(bounded error),Sec=(cause)} If the package Ada.Task_Attributes is instantiated with a controlled type and the controlled type has user-defined Adjust or Finalize operations that in turn access task attributes by any of the above operations, then a call of Set_Value of the instantiated package constitutes a bounded error. The call may perform as expected or may result in forever blocking the calling task and subsequently some or all tasks of the partition.]} @end{Bounded} @begin{Erron} @PDefn2{Term=(erroneous execution),Sec=(cause)} It is erroneous to dereference the access value returned by a given call on Reference after a subsequent call on Reinitialize for the same task attribute, or after the associated task terminates. @begin{Reason} This allows the storage to be reclaimed for the object associated with an attribute upon Reinitialize or task termination. @end{Reason} @PDefn2{Term=(erroneous execution),Sec=(cause)} If a value of Task_Id is passed as a parameter to any of the operations declared in this package and the corresponding task object no longer exists, the execution of the program is erroneous. @ChgRef{Version=[1],Kind=[Added],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgRef{Version=[2],Kind=[RevisedAdded],ARef=[AI95-00237-01]} @ChgAdded{Version=[1],Text=[@PDefn2{Term=(erroneous execution),Sec=(cause)} @Chg{Version=[2],New=[An access],Old=[Accesses]} to @Chg{Version=[2],New=[a ],Old=[]}task @Chg{Version=[2],New=[attribute],Old=[attributes]} via a value of type Attribute_Handle @Chg{Version=[2],New=[is],Old=[are]} erroneous if executed concurrently with @Chg{Version=[2],New=[another such access], Old=[each other]} or @Chg{Version=[2],New=[a call],Old=[with calls]} of any of the operations declared in package Task_Attributes.@Chg{Version=[2],New=[ An access to a task attribute is erroneous if executed concurrently with or after the finalization of the task attribute.],Old=[]}]} @begin{Reason} @ChgRef{Version=[1],Kind=[Added]} @ChgAdded{Version=[1],Text=[There is no requirement of atomicity on accesses via a value of type Attribute_Handle.]} @end{Reason} @begin{Ramification} @ChgRef{Version=[2],Kind=[Added]} @ChgAdded{Version=[2],Text=[A task attribute can only be accessed after finalization through a value of type Attribute_Handle. Operations in package Task_Attributes cannot be used to access a task attribute after finalization, because either the master of the instance has been or is in the process of being left (in which case the instance is out of scope and thus cannot be called), or the associated task is already terminated (in which case Tasking_Error is raised for any attempt to call a task attribute operation).]} @end{Ramification} @end{Erron} @begin{ImplReq} @ChgRef{Version=[1],Kind=[Revised],Ref=[8652/0071],ARef=[AI95-00165-01]} @Chg{New=[For a given attribute of a given task, the],Old=[The]} implementation shall perform @Chg{New=[the operations declared in this package], Old=[each of the above operations for a given attribute of a given task]} atomically with respect to any @Chg{New=[of these operations of], Old=[other of the above operations for]} the same attribute of the same task. @Chg{New=[The granularity of any locking mechanism necessary to achieve such atomicity is implementation defined.],Old=[]} @ChgImplDef{Version=[1],Kind=[Added],Text=[@Chg{New=[Granularity of locking for Task_Attributes.],Old=[]}]} @begin{Ramification} Hence, other than by dereferencing an access value returned by Reference, an attribute of a given task can be safely read and updated concurrently by multiple tasks. @end{Ramification} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00237-01]} @Chg{Version=[2],New=[After],Old=[When a]} task @Chg{Version=[2],New=[attributes are finalized],Old=[terminates]}, the implementation shall @Chg{Version=[2],New=[],Old=[finalize all attributes of the task, and ]}reclaim any @Chg{Version=[2],New=[],Old=[other ]}storage associated with the attributes. @end{ImplReq} @begin{DocReq} The implementation shall document the limit on the number of attributes per task, if any, and the limit on the total storage for attribute values per task, if such a limit exists. In addition, if these limits can be configured, the implementation shall document how to configure them. @ChgImplDef{Version=[2],Kind=[Deleted],InitialVersion=[0], Text=[@ChgDeleted{Version=[2], Text=[@Chg{New=[Limits on the number and size of task attributes, and how to configure them.], Old=[Implementation-defined aspects of Task_Attributes.]}]}]} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[For package Task_Attributes, limits on the number and size of task attributes, and how to configure any limits.]}]} @end{DocReq} @begin{Metrics} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} The implementation shall document the following metrics: A task calling the following subprograms shall execute @Chg{Version=[2],New=[at],Old=[in]} a sufficiently high priority as to not be preempted during the measurement period. This period shall start just before issuing the call and end just after the call completes. If the attributes of task T are accessed by the measurement tests, no other task shall access attributes of that task during the measurement period. For all measurements described here, the Attribute type shall be a scalar @Chg{Version=[2],New=[type ],Old=[]}whose size is equal to the size of the predefined @Chg{Version=[2],New=[type Integer],Old=[integer size]}. For each measurement, two cases shall be documented: one where the accessed attributes are of the calling task @Redundant[(that is, the default value for the T parameter is used)], and the other, where T identifies another, nonterminated, task. @Leading@;The following calls (to subprograms in the Task_Attributes package) shall be measured: @begin{Itemize} a call to Value, where the return value is Initial_Value; a call to Value, where the return value is not equal to Initial_Value; a call to Reference, where the return value designates a value equal to Initial_Value; a call to Reference, where the return value designates a value not equal to Initial_Value; @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} a call to Set_Value where the Val parameter is not equal to Initial_Value and the old attribute value is equal to Initial_Value@Chg{Version=[2],New=[;],Old=[.]} a call to Set_Value where the Val parameter is not equal to Initial_Value and the old attribute value is not equal to Initial_Value. @end{Itemize} @ChgDocReq{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[The metrics for the Task_Attributes package.]}]} @end{Metrics} @begin{ImplPerm} An implementation need not actually create the object corresponding to a task attribute until its value is set to something other than that of Initial_Value, or until Reference is called for the task attribute. Similarly, when the value of the attribute is to be reinitialized to that of Initial_Value, the object may instead be finalized and its storage reclaimed, to be recreated when needed later. While the object does not exist, the function Value may simply return Initial_Value, rather than implicitly creating the object. @begin{Discussion} The effect of this permission can only be observed if the assignment operation for the corresponding type has side effects. @end{Discussion} @begin{ImplNote} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00114-01]} This permission means that even though every task has every attribute, storage need only be allocated for those attributes @Chg{Version=[2],New=[for which function Reference has been invoked],Old=[that have been Reference'd]} or set to a value other than that of Initial_Value. @end{ImplNote} An implementation is allowed to place restrictions on the maximum number of attributes a task may have, the maximum size of each attribute, and the total storage size allocated for all the attributes of a task. @end{ImplPerm} @begin{ImplAdvice} @ChgRef{Version=[2],Kind=[Revised],ARef=[AI95-00434-01]} Some implementations are targeted to domains in which memory use at run time must be completely deterministic. For such implementations, it is recommended that the storage for task attributes will be pre-allocated statically and not from the heap. This can be accomplished by either placing restrictions on the number and the size of the @Chg{Version=[2], New=[],Old=[task's ]}attributes@Chg{Version=[2],New=[ of a task],Old=[]}, or by using the pre-allocated storage for the first N attribute objects, and the heap for the others. In the latter case, N should be documented. @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[If the target domain requires deterministic memory use at run time, storage for task attributes should be pre-allocated statically and the number of attributes pre-allocated should be documented.]}]} @begin{Discussion} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[We don't mention @lquotes@;restrictions on the size and number@rquotes (that is, limits) in the text for the Annex, because it is covered by the @DocReqName above, and we try not to repeat requirements in the Annex (they're enough work to meet without having to do things twice).]} @end{Discussion} @end{ImplAdvice} @ChgRef{Version=[2],Kind=[Added],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Finalization of task attributes and reclamation of associated storage should be performed as soon as possible after task termination.]} @ChgImplAdvice{Version=[2],Kind=[AddedNormal],Text=[@ChgAdded{Version=[2], Text=[Finalization of task attributes and reclamation of associated storage should be performed as soon as possible after task termination.]}]} @begin{Reason} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[This is necessary because the normative wording only says that attributes are finalized @lquotes@;after@rquotes@; task termination. Without this advice, waiting until the instance is finalized would meet the requirements (it is after termination, but may be a very long time after termination). We can't say anything more specific than this, as we do not want to require the overhead of an interaction with the tasking system to be done at a specific point.]} @end{Reason} @begin{Notes} An attribute always exists (after instantiation), and has the initial value. It need not occupy memory until the first operation that potentially changes the attribute value. The same holds true after Reinitialize. The result of the Reference function should be used with care; it is always safe to use that result in the task body whose attribute is being accessed. However, when the result is being used by another task, the programmer must make sure that the task whose attribute is being accessed is not yet terminated. Failing to do so could make the program execution erroneous. @ChgRef{Version=[2],Kind=[DeletedNoDelMsg],ARef=[AI95-00434-01]} @ChgDeleted{Version=[2],Text=[As specified in @RefSecNum{The Package Task_Identification}, if the parameter T (in a call on a subprogram of an instance of this package) identifies a nonexistent task, the execution of the program is erroneous.]} @end{Notes} @begin{DiffWord95} @ChgRef{Version=[2],Kind=[AddedNormal],Ref=[8652/0071],ARef=[AI95-00165-01]} @ChgAdded{Version=[2],Text=[@b<Corrigendum:> Clarified that use of task attribute operations from within a task attribute operation (by an Adjust or Finalize call) is a bounded error, and that concurrent use of attribute handles is erroneous.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00237-01]} @ChgAdded{Version=[2],Text=[Clarified the wording so that the finalization takes place after the termination of the task or when the instance is finalized (whichever is sooner).]} @end{Diffword95} @LabeledAddedSubClause{Version=[2],Name=[The Package Task_Termination]} @begin{StaticSem} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],KeepNext=[T],Type=[Leading],Text=[The following language-defined library package exists:]} @begin{Example} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<with> Ada.Task_Identification; @key<with> Ada.Exceptions; @key<package> Ada.Task_Termination @key<is>@ChildUnit{Parent=[Ada],Child=[Task_Termination]} @key<pragma> Preelaborate(Task_Termination);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Cause_Of_Termination} @key<is> (Normal, Abnormal, Unhandled_Exception);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<type> @AdaTypeDefn{Termination_Handler} @key<is access protected procedure> (Cause : @key<in> Cause_Of_Termination; T : @key<in> Ada.Task_Identification.Task_Id; X : @key<in> Ada.Exceptions.Exception_Occurrence);]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Set_Dependents_Fallback_Handler} (Handler: @key<in> Termination_Handler); @key<function> @AdaSubDefn{Current_Task_Fallback_Handler} @key<return> Termination_Handler;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[ @key<procedure> @AdaSubDefn{Set_Specific_Handler} (T : @key<in> Ada.Task_Identification.Task_Id; Handler : @key<in> Termination_Handler); @key<function> @AdaSubDefn{Specific_Handler} (T : Ada.Task_Identification.Task_Id) @key<return> Termination_Handler;]} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgAdded{Version=[2],Text=[@key<end> Ada.Task_Termination;]} @end{Example} @end{StaticSem} @begin{RunTime} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0202-1]} @ChgAdded{Version=[2],Text=[@Defn{termination handler}@Defn2{Term=[handler],Sec=[termination]} The type Termination_Handler identifies a protected procedure to be executed by the implementation when a task terminates. Such a protected procedure is called a @i<handler>. In all cases T identifies the task that is terminating. If the task terminates due to completing the last statement of its body, or as a result of waiting on a terminate alternative, @Chg{Version=[3],New=[and the finalization of the task completes normally, ],Old=[]}then Cause is set to Normal and X is set to Null_Occurrence. If the task terminates because it is being aborted, then Cause is set to Abnormal@Chg{Version=[3],New=[;],Old=[ and]} X is set to Null_Occurrence@Chg{Version=[3],New=[ if the finalization of the task completes normally],Old=[]}. If the task terminates because of an exception raised by the execution of its @nt{task_body}, then Cause is set to Unhandled_Exception@Chg{Version=[3],New=[;],Old=[ and]} X is set to the associated exception occurrence@Chg{Version=[3],New=[ if the finalization of the task completes normally],Old=[]}.@Chg{Version=[3],New=[ Independent of how the task completes, if finalization of the task propagates an exception, then Cause is either Unhandled_Exception or Abnormal, and X is an exception occurrence that identifies the Program_Error exception.],Old=[]}]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[@Defn{fall-back handler}@Defn2{Term=[termination handler],Sec=[fall-back]} @Defn{specific handler}@Defn2{Term=[termination handler],Sec=[specific]} @Defn2{Term=[set],Sec=[termination handler]} @Defn2{Term=[cleared],Sec=[termination handler]} Each task has two termination handlers, a @i<fall-back handler> and a @i<specific handler>. The specific handler applies only to the task itself, while the fall-back handler applies only to the dependent tasks of the task. A handler is said to be @i<set> if it is associated with a nonnull value of type Termination_Handler, and @i<cleared> otherwise. When a task is created, its specific handler and fall-back handler are cleared.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Set_Dependents_Fallback_Handler changes the fall-back handler for the calling task@Chg{Version=[3],New=[:],Old=[;]} if Handler is @key{null}, that fall-back handler is cleared@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is set to be Handler.@key{all}. If a fall-back handler had previously been set it is replaced.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Current_Task_Fallback_Handler returns the fall-back handler that is currently set for the calling task, if one is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The procedure Set_Specific_Handler changes the specific handler for the task identified by T@Chg{Version=[3],New=[:],Old=[;]} if Handler is @key{null}, that specific handler is cleared@Chg{Version=[3],New=[;],Old=[,]} otherwise@Chg{Version=[3],New=[,],Old=[]} it is set to be Handler.@key{all}. If a specific handler had previously been set it is replaced.]} @begin{Ramification} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0005-1]} @ChgAdded{Version=[3],Text=[This package cannot portably be used to set a handler on the program as a whole. It is possible to call Set_Specific_Handler with the environment task's ID. But any call to the handler would necessarily be a @BoundedName, as the handler is called after the task's finalization has completed. In the case of the environment task, that includes any possible protected objects, and calling a protected object after it is finalized is a @BoundedName (see @RefSecNum{Protected Units and Protected Objects}). This might work in a particular implementation, but it cannot be depended upon.]} @end{Ramification} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0264-1]} @ChgAdded{Version=[2],Text=[The function Specific_Handler returns the specific handler that is currently set for the task identified by T, if one is set; otherwise@Chg{Version=[3],New=[,],Old=[]} it returns @key{null}.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[As part of the finalization of a @nt{task_body}, after performing the actions specified in @RefSecNum{Assignment and Finalization} for finalization of a master, the specific handler for the task, if one is set, is executed. If the specific handler is cleared, a search for a fall-back handler proceeds by recursively following the master relationship for the task. If a task is found whose fall-back handler is set, that handler is executed; otherwise, no handler is executed.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[For Set_Specific_Handler or Specific_Handler, Tasking_Error is raised if the task identified by T has already terminated. Program_Error is raised if the value of T is Ada.Task_Identification.Null_Task_Id.]} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[An exception propagated from a handler that is invoked as part of the termination of a task has no effect.]} @end{RunTime} @begin{Erron} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[For a call of Set_Specific_Handler or Specific_Handler, if the task identified by T no longer exists, the execution of the program is erroneous.]} @end{Erron} @begin{Extend95} @ChgRef{Version=[2],Kind=[AddedNormal],ARef=[AI95-00266-02]} @ChgAdded{Version=[2],Text=[@Defn{extensions to Ada 95} Package Task_Termination is new.]} @end{Extend95} @begin{DiffWord2005} @ChgRef{Version=[3],Kind=[AddedNormal],ARef=[AI05-0202-1]} @ChgAdded{Version=[3],Text=[@b<Correction:> Specified what is passed to the handler if the finalization of the task fails after it is completed. This was not specified at all in Ada 2005, so there is a possibility that some program depended on some other behavior of an implementation. But as this case is very unlikely (and only occurs when there is already a significant bug in the program - so should not occur in fielded systems), we're not listing this as an inconsistency.]} @end{DiffWord2005} ����������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/syntax.mss�����������������������������������������������������������0000755�0001752�0001001�00000003103�12066652506�017474� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(syntax, Root="ada.mss") @Comment{$Date: 2012/11/28 23:53:06 $} @LabeledInformativeAnnex{Syntax Summary} @comment{$Source: e:\\cvsroot/ARM/Source/syntax.mss,v $} @comment{$Revision: 1.20 $} @NoParaNum@Defn2{Term=[syntax], Sec=(complete listing)} @Defn2{Term=[grammar], Sec=(complete listing)} @Defn2{Term=[context free grammar], Sec=(complete listing)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(complete listing)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(complete listing)} This Annex summarizes the complete syntax of the language. See @RefSecNum{Method of Description and Syntax Notation} for a description of the notation used. @SyntaxSummary @NewPage @NoParaNum@Heading{Syntax Cross Reference} @NoParaNum@Defn2{Term=[syntax], Sec=(cross reference)} @Defn2{Term=[grammar], Sec=(cross reference)} @Defn2{Term=[context free grammar], Sec=(cross reference)} @Defn2{Term=[BNF (Backus-Naur Form)], Sec=(cross reference)} @Defn2{Term=[Backus-Naur Form (BNF)], Sec=(cross reference)} @ChgRef{Version=[2],Kind=[AddedNormal]} @ChgRef{Version=[3],Kind=[Revised],ARef=[AI05-0299-1]} @ChgAdded{Version=[2],Text=[In the following syntax cross reference, each syntactic category is followed by the @Chg{Version=[3],New=[subclause],Old=[clause]} number where it is defined. In addition, each syntactic category @i{S} is followed by a list of the categories that use @i{S} in their definitions. For example, the first listing below shows that @nt{abort_statement} appears in the definition of @nt{simple_statement}.]} @Comment{This explanation is a simplified version of the Ada 83 one.} @SyntaxXRef �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������org.adaic.arm_form/source_2012/title.mss������������������������������������������������������������0000755�0001752�0001001�00000026236�12066652506�017303� 0����������������������������������������������������������������������������������������������������ustar �stephe��������������������������None�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������@Part(title, Root="ada.mss") @comment{$Source: e:\\cvsroot/ARM/Source/title.mss,v $} @comment{$Revision: 1.60 $ $Date: 2012/12/14 04:10:49 $} @begin{ISOOnly} @Noparanum@Right{@Swiss{@Grow{@Chg{Version=[3],New=[@b{ISO/IEC JTC 1/SC 22 N}],Old=[@B{INTERNATIONAL STANDARD} ISO/IEC 8652:@Chg{Version=[2],New=[2007(E) Ed. 3],Old=[1995(E)@Chg{Version=[1], New=[ with COR.1:2001], Old=[]}]}]}}}} @Comment{CD draft text} @Noparanum@Right{@Swiss{@Chg{Version=[3],New=[Date: 2012-11-27],Old=[]}}} @Noparanum@Right{@Swiss{@Grow{@Chg{Version=[3],New=[@B{ISO/IEC 8652:2012(E)}],Old=[]}}}} @Noparanum@Right{@Swiss{@Chg{Version=[3],New=[ISO/IEC JTC 1/SC 22/WG 9],Old=[]}}} @end{ISOOnly} @begin{NotISO} @Noparanum@Right{@Swiss{@Grow{@B{Ada Reference Manual}, ISO/IEC 8652:@Chg{Version=[3],New=[2012(E)],Old=[@Chg{Version=[2],New=[2007(E) Ed. 3],Old=[1995(E)@Chg{Version=[1], New=[ with COR.1:2001], Old=[]}]}]}}}} @end{NotISO} @Noparanum@ @* @ @* @ @* @Comment{Final header... @begin{ISOOnly} @Noparanum@swiss{@shrink{@shrink{@shrink{INTERNATIONAL ORGANIZATION FOR STANDARDIZATION}}}} @Noparanum@swiss{@shrink{@shrink{@shrink{INTERNATIONAL ELECTROTECHNICAL COMMISSION}}}} @end{ISOOnly} End comment} @Noparanum@ @* @ @* @begin{ISOOnly} @Noparanum@Swiss{@b{@grow{@grow{@grow{@grow{Information technology @Em Programming languages @Em Ada}}}}}} @ @* @Noparanum@Swiss{@i{Technologies de l'information @Em Langages de programmation @Em Ada}} @end{ISOOnly} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @begin{NotISO} @Noparanum@ @*@;@comment{A dummy paragraph containing three blank lines} @ @* @ @* @ @* @end{NotISO} @begin{ISOOnly} @Comment{Jim Moore wanted this deleted in the consolidated editions, as it is confusing.} @Noparanum@Chg{Version=[3],New=[@Swiss{Revision of second edition (ISO/IEC 8652:1995)}],Old=[@Chg{New=[@ @*@Comment{Dummy paragraph}], Old=[@Swiss{[Revision of first edition (ISO 8652:1987)]}]}]} @end{ISOOnly} @Noparanum@ @* @begin{NotISO} @begin{RMOnly} @Noparanum@Heading{Ada Reference Manual} @end{RMOnly} @begin{AARMOnly} @Noparanum@Heading{Annotated Ada Reference Manual} @end{AARMOnly} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@Center{@Swiss{@Grow{ISO/IEC 8652:@Chg{Version=[3],New=[2012],Old=[1995]}(E)@Chg{Version=[3],New=<>,Old=[]}}}} @Noparanum@Center{@Swiss{@Chg{Version=[3],New=[],Old=[@Chg{Version=[1], New=[@Grow{with Technical Corrigendum 1}], Old=[]}]}}} @Noparanum@Center{@Swiss{@Chg{Version=[3],New=[],Old=[@Chg{Version=[2], New=[@Grow{and Amendment 1}], Old=[]}]}}} @end{NotISO} @Noparanum@ @;@comment{A dummy paragraph containing just a blank} @begin{NotISO} @Noparanum@Center{@Swiss{@Grow{Language and Standard Libraries}}} @Noparanum@Comment{The following puts the copyright near the bottom of the page} @ @*@*@*@*@*@*@* @Noparanum@;Copyright @Latin1(169) 1992, 1993, 1994, 1995 Intermetrics, Inc. @Noparanum@;@Chg{Version=[1], New=[Copyright @Latin1(169) 2000 The MITRE Corporation, Inc.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006 AXE Consultants], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006 Ada-Europe], Old=[]} @Noparanum@;@Chg{Version=[3], New=[Copyright @Latin1(169) 2008, 2009, 2010, 2011, 2012 AXE Consultants], Old=[]} @end{NotISO} @begin{ISOOnly} @Comment{The following is not needed in the final Standard: @ThinLine @Noparanum@Center{@Swiss{@Grow{@b{Warning}}}} @Noparanum@;This document is not an ISO International Standard. It is distributed for review and comment. It is subject to change without notice and may not be referred to as an International Standard. @Noparanum@;Recipients of this draft are invited to submit, with their comment, notification of any relevant patent rights of which they are aware and to provide supporting documentation. @ThinLine *End comment*} @end{ISOOnly} @NewPage @begin{NotISO} @Comment{The following puts the copyright near the bottom of the page} @Noparanum@ @*@*@*@*@* @Noparanum@;@b{Ada Reference Manual - Language and Standard Libraries} @Noparanum@;Copyright @Latin1(169) 1992, 1993, 1994, 1995, Intermetrics, Inc. @Noparanum@;This copyright is assigned to the U.S. Government. All rights reserved. @Noparanum@;This document may be copied, in whole or in part, in any form or by any means, as is or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Compiled copies of standard library units and examples need not contain this copyright notice so long as the notice is included in all copies of source code and documentation. @ThinLine @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[1], New=[@b{Technical Corrigendum 1}], Old=[]} @Noparanum@;@Chg{Version=[1], New=[Copyright @Latin1(169) 2000, The MITRE Corporation. All Rights Reserved.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of MITRE.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[You use this document on the condition that you indemnify and hold harmless MITRE, its Board of Trustees, officers, agents, and employees, from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[1], New=[MITRE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL MITRE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF MITRE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[2], New=[@b{Amendment 1}], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006@Chg{Version=[3], New=[, 2007],Old=[]}, AXE Consultants. All Rights Reserved.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of AXE.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[You use this document on the condition that you indemnify and hold harmless AXE, its board, officers, agents, and employees, from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[AXE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL AXE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF AXE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @Noparanum@;@Chg{Version=[3], New=[@b{Third Edition}], Old=[]} @Noparanum@;@Chg{Version=[3], New=[Copyright @Latin1(169) 2008, 2009, 2010, 2011, 2012 AXE Consultants. All Rights Reserved.], Old=[]} @Noparanum@;@Chg{Version=[3], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of AXE.], Old=[]} @Noparanum@;@Chg{Version=[3], New=[You use this document on the condition that you indemnify and hold harmless AXE, its board, officers, agents, and employees, from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[3], New=[AXE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL AXE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF AXE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @Noparanum@;@ @;@comment{A dummy paragraph containing just a blank} @Noparanum@;@Chg{Version=[2], New=[@b{Ada 2005 Consolidated Standard}], Old=[]} @Noparanum@;@Chg{Version=[2], New=[Copyright @Latin1(169) 2004, 2005, 2006, Ada-Europe.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[This document may be copied, in whole or in part, in any form or by any means, as is, or with alterations, provided that (1) alterations are clearly marked as alterations and (2) this copyright notice is included unmodified in any copy. Any other use or distribution of this document is prohibited without the prior express permission of Ada-Europe.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[You use this document on the condition that you indemnify and hold harmless Ada-Europe and its Board from any and all liability or damages to yourself or your hardware or software, or third parties, including attorneys' fees, court costs, and other related costs and expenses, arising out of your use of this document irrespective of the cause of said liability.], Old=[]} @Noparanum@;@Chg{Version=[2], New=[ADA-EUROPE MAKES THIS DOCUMENT AVAILABLE ON AN "AS IS" BASIS AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE ACCURACY, CAPABILITY, EFFICIENCY MERCHANTABILITY, OR FUNCTIONING OF THIS DOCUMENT. IN NO EVENT WILL ADA-EUROPE BE LIABLE FOR ANY GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL, EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF ADA-EUROPE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.], Old=[]} @end{NotISO} @begin{ISOOnly} @ThinLine @Noparanum@Center{@Swiss{@Grow{@Grow{@b{Copyright Notice}}}}} @Noparanum@;This ISO document is a working draft or committee draft and is copyright-protected by ISO. While the reproduction of working drafts or committee drafts in any form for use by participants in the ISO standards development process is permitted without prior permission from ISO, neither this document nor any extract from it may be reproduced, stored, or transmitted in any form for any other purpose without prior written permission from ISO. @Noparanum@;Reproduction for sales purposes may be subject to royalty payments or a licensing agreement. @Noparanum@;Violators may be prosecuted. @ThinLine @end{ISOOnly} ����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������